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)) { if (!privateMap.has(receiver)) {
throw new TypeError("attempted to get private field on non-instance"); 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)) { if (!privateMap.has(receiver)) {
throw new TypeError("attempted to set private field on non-instance"); 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; return value;
} }
`; `;

View File

@ -201,7 +201,14 @@ export default declare((api, options) => {
// Must be late evaluated in case it references another private field. // Must be late evaluated in case it references another private field.
return () => 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, MAP: map,
REF: ref, REF: ref,
VALUE: path.node.value || scope.buildUndefinedNode(), VALUE: path.node.value || scope.buildUndefinedNode(),

View File

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

View File

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

View File

@ -6,9 +6,15 @@ function () {
function Point(_x2 = 0, _y2 = 0) { function Point(_x2 = 0, _y2 = 0) {
babelHelpers.classCallCheck(this, Point); 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, _x, +_x2);
babelHelpers.classPrivateFieldSet(this, _y, +_y2); babelHelpers.classPrivateFieldSet(this, _y, +_y2);

View File

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

View File

@ -4,7 +4,10 @@ var C = function C() {
babelHelpers.classCallCheck(this, C); babelHelpers.classCallCheck(this, C);
babelHelpers.defineProperty(this, "y", babelHelpers.classPrivateFieldGet(this, _x)); 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(); var _x = new WeakMap();

View File

@ -13,11 +13,17 @@ function (_Bar) {
if (condition) { if (condition) {
_this = babelHelpers.possibleConstructorReturn(this, babelHelpers.getPrototypeOf(Foo).call(this)); _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 { } else {
_this = babelHelpers.possibleConstructorReturn(this, babelHelpers.getPrototypeOf(Foo).call(this)); _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); return babelHelpers.possibleConstructorReturn(_this);

View File

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

View File

@ -5,9 +5,15 @@ var Foo = function Foo(_foo) {
babelHelpers.classCallCheck(this, 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(); var _bar = new WeakMap();

View File

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

View File

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

View File

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

View File

@ -3,9 +3,15 @@ var Foo = function Foo() {
babelHelpers.classCallCheck(this, 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(); var _x = new WeakMap();

View File

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

View File

@ -4,13 +4,22 @@ var Foo = function Foo() {
babelHelpers.classCallCheck(this, Foo); babelHelpers.classCallCheck(this, Foo);
babelHelpers.defineProperty(this, "one", babelHelpers.classPrivateFieldGet(this, _private)); 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)); 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(); var _two = new WeakMap();

View File

@ -4,11 +4,18 @@ class MyClass {
constructor() { constructor() {
var _this = this; var _this = this;
_myAsyncMethod.set(this, _myAsyncMethod.set(this, {
/*#__PURE__*/ writable: true,
babelHelpers.asyncToGenerator(function* () { value: function () {
console.log(_this); var _ref = babelHelpers.asyncToGenerator(function* () {
})); console.log(_this);
});
return function value() {
return _ref.apply(this, arguments);
};
}()
});
} }
} }
@ -19,11 +26,18 @@ _class = class MyClass2 {
constructor() { constructor() {
var _this2 = this; var _this2 = this;
_myAsyncMethod2.set(this, _myAsyncMethod2.set(this, {
/*#__PURE__*/ writable: true,
babelHelpers.asyncToGenerator(function* () { value: function () {
console.log(_this2); 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() { constructor() {
var _this3 = this; var _this3 = this;
_myAsyncMethod3.set(this, _myAsyncMethod3.set(this, {
/*#__PURE__*/ writable: true,
babelHelpers.asyncToGenerator(function* () { value: function () {
console.log(_this3); 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); babelHelpers.classCallCheck(this, B);
_this = babelHelpers.possibleConstructorReturn(this, babelHelpers.getPrototypeOf(B).call(this, ...args)); _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; return _this;
} }

View File

@ -9,7 +9,10 @@ function (_Bar) {
var _temp, _this; var _temp, _this;
babelHelpers.classCallCheck(this, Foo); 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; return _this;
} }

View File

@ -11,7 +11,10 @@ function (_Bar) {
babelHelpers.classCallCheck(this, Foo); babelHelpers.classCallCheck(this, Foo);
_this = babelHelpers.possibleConstructorReturn(this, babelHelpers.getPrototypeOf(Foo).call(this)); _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; return _this;
} }

View File

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