Save full descriptor instead of only value for private fields. (#8318)

* Save full descriptor instead of only value for private fields.

Decorators can make private fields non-writable, so we need to store this
information somewhere.
The descriptor can also be used to implement private accessors.
This commit is contained in:
Nicolò Ribaudo 2018-07-27 22:24:57 +02:00 committed by Henry Zhu
parent 5fdcd29ef9
commit ec69b4bb12
21 changed files with 155 additions and 45 deletions

View File

@ -1016,7 +1016,7 @@ helpers.classPrivateFieldGet = () => template.program.ast`
if (!privateMap.has(receiver)) {
throw new TypeError("attempted to get private field on non-instance");
}
return privateMap.get(receiver);
return privateMap.get(receiver).value;
}
`;
@ -1025,7 +1025,14 @@ helpers.classPrivateFieldSet = () => template.program.ast`
if (!privateMap.has(receiver)) {
throw new TypeError("attempted to set private field on non-instance");
}
privateMap.set(receiver, value);
var descriptor = privateMap.get(receiver);
if (!descriptor.writable) {
// This should only throw in strict mode, but class bodies are
// always strict and private fields can only be used inside
// class bodies.
throw new TypeError("attempted to set read only private field");
}
descriptor.value = value;
return value;
}
`;

View File

@ -201,7 +201,14 @@ export default declare((api, options) => {
// Must be late evaluated in case it references another private field.
return () =>
template.statement`MAP.set(REF, VALUE);`({
template.statement`
MAP.set(REF, {
// configurable is always false for private elements
// enumerable is always false for private elements
writable: true,
value: VALUE
});
`({
MAP: map,
REF: ref,
VALUE: path.node.value || scope.buildUndefinedNode(),

View File

@ -6,7 +6,10 @@ function () {
function Foo() {
babelHelpers.classCallCheck(this, Foo);
_foo.set(this, 0);
_foo.set(this, {
writable: true,
value: 0
});
}
babelHelpers.createClass(Foo, [{

View File

@ -6,8 +6,11 @@ function () {
function Foo() {
babelHelpers.classCallCheck(this, Foo);
_foo.set(this, function () {
return this;
_foo.set(this, {
writable: true,
value: function () {
return this;
}
});
}

View File

@ -6,9 +6,15 @@ function () {
function Point(_x2 = 0, _y2 = 0) {
babelHelpers.classCallCheck(this, Point);
_x.set(this, void 0);
_x.set(this, {
writable: true,
value: void 0
});
_y.set(this, void 0);
_y.set(this, {
writable: true,
value: void 0
});
babelHelpers.classPrivateFieldSet(this, _x, +_x2);
babelHelpers.classPrivateFieldSet(this, _y, +_y2);

View File

@ -5,7 +5,10 @@ var Foo = function Foo() {
babelHelpers.classCallCheck(this, Foo);
_bar.set(this, foo);
_bar.set(this, {
writable: true,
value: foo
});
var _foo = "foo";
};

View File

@ -4,7 +4,10 @@ var C = function C() {
babelHelpers.classCallCheck(this, C);
babelHelpers.defineProperty(this, "y", babelHelpers.classPrivateFieldGet(this, _x));
_x.set(this, void 0);
_x.set(this, {
writable: true,
value: void 0
});
};
var _x = new WeakMap();

View File

@ -13,11 +13,17 @@ function (_Bar) {
if (condition) {
_this = babelHelpers.possibleConstructorReturn(this, babelHelpers.getPrototypeOf(Foo).call(this));
_bar.set(babelHelpers.assertThisInitialized(babelHelpers.assertThisInitialized(babelHelpers.assertThisInitialized(_this))), "foo");
_bar.set(babelHelpers.assertThisInitialized(babelHelpers.assertThisInitialized(babelHelpers.assertThisInitialized(_this))), {
writable: true,
value: "foo"
});
} else {
_this = babelHelpers.possibleConstructorReturn(this, babelHelpers.getPrototypeOf(Foo).call(this));
_bar.set(babelHelpers.assertThisInitialized(babelHelpers.assertThisInitialized(babelHelpers.assertThisInitialized(_this))), "foo");
_bar.set(babelHelpers.assertThisInitialized(babelHelpers.assertThisInitialized(babelHelpers.assertThisInitialized(_this))), {
writable: true,
value: "foo"
});
}
return babelHelpers.possibleConstructorReturn(_this);

View File

@ -3,7 +3,10 @@ var Foo = function Foo() {
babelHelpers.classCallCheck(this, Foo);
_prop.set(this, "foo");
_prop.set(this, {
writable: true,
value: "foo"
});
};
var _prop = new WeakMap();
@ -21,7 +24,10 @@ function (_Foo) {
babelHelpers.classCallCheck(this, Bar);
_this = babelHelpers.possibleConstructorReturn(this, babelHelpers.getPrototypeOf(Bar).call(this, ...args));
_prop2.set(babelHelpers.assertThisInitialized(babelHelpers.assertThisInitialized(_this)), "bar");
_prop2.set(babelHelpers.assertThisInitialized(babelHelpers.assertThisInitialized(_this)), {
writable: true,
value: "bar"
});
return _this;
}

View File

@ -5,9 +5,15 @@ var Foo = function Foo(_foo) {
babelHelpers.classCallCheck(this, Foo);
_bar.set(this, this);
_bar.set(this, {
writable: true,
value: this
});
_baz.set(this, foo);
_baz.set(this, {
writable: true,
value: foo
});
};
var _bar = new WeakMap();

View File

@ -11,8 +11,11 @@ function (_Parent) {
babelHelpers.classCallCheck(this, Child);
_this = babelHelpers.possibleConstructorReturn(this, babelHelpers.getPrototypeOf(Child).call(this));
_scopedFunctionWithThis.set(babelHelpers.assertThisInitialized(babelHelpers.assertThisInitialized(_this)), () => {
_this.name = {};
_scopedFunctionWithThis.set(babelHelpers.assertThisInitialized(babelHelpers.assertThisInitialized(_this)), {
writable: true,
value: () => {
_this.name = {};
}
});
return _this;

View File

@ -3,7 +3,10 @@ var Foo = function Foo() {
babelHelpers.classCallCheck(this, Foo);
_bar.set(this, void 0);
_bar.set(this, {
writable: true,
value: void 0
});
};
var _bar = new WeakMap();

View File

@ -3,7 +3,10 @@ var Foo = function Foo() {
babelHelpers.classCallCheck(this, Foo);
_bar.set(this, "foo");
_bar.set(this, {
writable: true,
value: "foo"
});
};
var _bar = new WeakMap();

View File

@ -3,9 +3,15 @@ var Foo = function Foo() {
babelHelpers.classCallCheck(this, Foo);
_x.set(this, 0);
_x.set(this, {
writable: true,
value: 0
});
_y.set(this, babelHelpers.classPrivateFieldGet(this, _x));
_y.set(this, {
writable: true,
value: babelHelpers.classPrivateFieldGet(this, _x)
});
};
var _x = new WeakMap();

View File

@ -3,7 +3,10 @@ var Outer = function Outer() {
babelHelpers.classCallCheck(this, Outer);
_outer.set(this, void 0);
_outer.set(this, {
writable: true,
value: void 0
});
var Test =
/*#__PURE__*/

View File

@ -4,13 +4,22 @@ var Foo = function Foo() {
babelHelpers.classCallCheck(this, Foo);
babelHelpers.defineProperty(this, "one", babelHelpers.classPrivateFieldGet(this, _private));
_two.set(this, babelHelpers.classPrivateFieldGet(this, _private));
_two.set(this, {
writable: true,
value: babelHelpers.classPrivateFieldGet(this, _private)
});
_private.set(this, 0);
_private.set(this, {
writable: true,
value: 0
});
babelHelpers.defineProperty(this, "three", babelHelpers.classPrivateFieldGet(this, _private));
_four.set(this, babelHelpers.classPrivateFieldGet(this, _private));
_four.set(this, {
writable: true,
value: babelHelpers.classPrivateFieldGet(this, _private)
});
};
var _two = new WeakMap();

View File

@ -4,11 +4,18 @@ class MyClass {
constructor() {
var _this = this;
_myAsyncMethod.set(this,
/*#__PURE__*/
babelHelpers.asyncToGenerator(function* () {
console.log(_this);
}));
_myAsyncMethod.set(this, {
writable: true,
value: function () {
var _ref = babelHelpers.asyncToGenerator(function* () {
console.log(_this);
});
return function value() {
return _ref.apply(this, arguments);
};
}()
});
}
}
@ -19,11 +26,18 @@ _class = class MyClass2 {
constructor() {
var _this2 = this;
_myAsyncMethod2.set(this,
/*#__PURE__*/
babelHelpers.asyncToGenerator(function* () {
console.log(_this2);
}));
_myAsyncMethod2.set(this, {
writable: true,
value: function () {
var _ref2 = babelHelpers.asyncToGenerator(function* () {
console.log(_this2);
});
return function value() {
return _ref2.apply(this, arguments);
};
}()
});
}
};
@ -34,11 +48,18 @@ export default class MyClass3 {
constructor() {
var _this3 = this;
_myAsyncMethod3.set(this,
/*#__PURE__*/
babelHelpers.asyncToGenerator(function* () {
console.log(_this3);
}));
_myAsyncMethod3.set(this, {
writable: true,
value: function () {
var _ref3 = babelHelpers.asyncToGenerator(function* () {
console.log(_this3);
});
return function value() {
return _ref3.apply(this, arguments);
};
}()
});
}
}

View File

@ -29,7 +29,10 @@ function (_A) {
babelHelpers.classCallCheck(this, B);
_this = babelHelpers.possibleConstructorReturn(this, babelHelpers.getPrototypeOf(B).call(this, ...args));
_foo.set(babelHelpers.assertThisInitialized(babelHelpers.assertThisInitialized(_this)), babelHelpers.get(babelHelpers.getPrototypeOf(B.prototype), "foo", babelHelpers.assertThisInitialized(_this)).call(babelHelpers.assertThisInitialized(_this)));
_foo.set(babelHelpers.assertThisInitialized(babelHelpers.assertThisInitialized(_this)), {
writable: true,
value: babelHelpers.get(babelHelpers.getPrototypeOf(B.prototype), "foo", babelHelpers.assertThisInitialized(_this)).call(babelHelpers.assertThisInitialized(_this))
});
return _this;
}

View File

@ -9,7 +9,10 @@ function (_Bar) {
var _temp, _this;
babelHelpers.classCallCheck(this, Foo);
foo((_temp = _this = babelHelpers.possibleConstructorReturn(this, babelHelpers.getPrototypeOf(Foo).call(this)), _bar.set(babelHelpers.assertThisInitialized(babelHelpers.assertThisInitialized(_this)), "foo"), _temp));
foo((_temp = _this = babelHelpers.possibleConstructorReturn(this, babelHelpers.getPrototypeOf(Foo).call(this)), _bar.set(babelHelpers.assertThisInitialized(babelHelpers.assertThisInitialized(_this)), {
writable: true,
value: "foo"
}), _temp));
return _this;
}

View File

@ -11,7 +11,10 @@ function (_Bar) {
babelHelpers.classCallCheck(this, Foo);
_this = babelHelpers.possibleConstructorReturn(this, babelHelpers.getPrototypeOf(Foo).call(this));
_bar.set(babelHelpers.assertThisInitialized(babelHelpers.assertThisInitialized(_this)), "foo");
_bar.set(babelHelpers.assertThisInitialized(babelHelpers.assertThisInitialized(_this)), {
writable: true,
value: "foo"
});
return _this;
}

View File

@ -6,7 +6,10 @@ function () {
function Foo() {
babelHelpers.classCallCheck(this, Foo);
_foo.set(this, 0);
_foo.set(this, {
writable: true,
value: 0
});
}
babelHelpers.createClass(Foo, [{