Skip to content

Commit

Permalink
Add .has method to context.access
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolo-ribaudo committed Feb 3, 2023
1 parent fa1ffc6 commit d3bed4d
Show file tree
Hide file tree
Showing 56 changed files with 259 additions and 98 deletions.
4 changes: 2 additions & 2 deletions packages/babel-helpers/src/helpers-generated.ts

Large diffs are not rendered by default.

51 changes: 34 additions & 17 deletions packages/babel-helpers/src/helpers/applyDecs2301.js
Expand Up @@ -34,7 +34,8 @@ function memberDec(
kind,
isStatic,
isPrivate,
value
value,
privateHas
) {
var kindStr;

Expand Down Expand Up @@ -71,7 +72,13 @@ function memberDec(
);
}

var get, set;
var get, set, has;
if (isPrivate) has = privateHas;
else {
has = function (receiver) {
return name in receiver;
};
}
if (!isPrivate && (kind === 0 /* FIELD */ || kind === 2) /* METHOD */) {
get = function (receiver) {
return receiver[name];
Expand Down Expand Up @@ -102,7 +109,11 @@ function memberDec(
}
}
ctx.access =
get && set ? { get: get, set: set } : get ? { get: get } : { set: set };
get && set
? { get: get, set: set, has: has }
: get
? { get: get, has: has }
: { set: set, has: has };

try {
return dec(value, ctx);
Expand Down Expand Up @@ -168,26 +179,30 @@ function applyMemberDec(
) {
var decs = decInfo[0];

var desc, init, value;
var desc, init, value, has;

if (isPrivate) {
if (kind === 0 /* FIELD */ || kind === 1 /* ACCESSOR */) {
desc = {
get: decInfo[3],
set: decInfo[4],
};
} else if (kind === 3 /* GETTER */) {
desc = {
get: decInfo[3],
};
} else if (kind === 4 /* SETTER */) {
desc = {
set: decInfo[3],
};
has = decInfo[5];
} else {
desc = {
value: decInfo[3],
};
if (kind === 3 /* GETTER */) {
desc = {
get: decInfo[3],
};
} else if (kind === 4 /* SETTER */) {
desc = {
set: decInfo[3],
};
} else {
desc = {
value: decInfo[3],
};
}
has = decInfo[4];
}
} else if (kind !== 0 /* FIELD */) {
desc = Object.getOwnPropertyDescriptor(base, name);
Expand Down Expand Up @@ -217,7 +232,8 @@ function applyMemberDec(
kind,
isStatic,
isPrivate,
value
value,
has
);

if (newValue !== void 0) {
Expand Down Expand Up @@ -247,7 +263,8 @@ function applyMemberDec(
kind,
isStatic,
isPrivate,
value
value,
has
);

if (newValue !== void 0) {
Expand Down
Expand Up @@ -231,31 +231,24 @@ function addProxyAccessorsFor(

function extractProxyAccessorsFor(
targetKey: t.PrivateName,
): t.FunctionExpression[] {
injectHas: boolean,
): (t.FunctionExpression | t.ArrowFunctionExpression)[] {
return [
t.functionExpression(
undefined,
[],
t.blockStatement([
t.returnStatement(
t.memberExpression(t.thisExpression(), t.cloneNode(targetKey)),
),
]),
),
t.functionExpression(
undefined,
[t.identifier("value")],
t.blockStatement([
t.expressionStatement(
t.assignmentExpression(
"=",
t.memberExpression(t.thisExpression(), t.cloneNode(targetKey)),
t.identifier("value"),
),
),
]),
),
];
template.expression.ast`
function () {
return this.${t.cloneNode(targetKey)};
}
` as t.FunctionExpression,
template.expression.ast`
function (value) {
this.${t.cloneNode(targetKey)} = value;
}
` as t.FunctionExpression,
injectHas &&
(template.expression.ast`
_ => ${t.cloneNode(targetKey)} in _
` as t.ArrowFunctionExpression),
].filter(Boolean);
}

const FIELD = 0;
Expand Down Expand Up @@ -299,7 +292,9 @@ interface DecoratorInfo {
// The name of the decorator
name: t.StringLiteral | t.Expression;

privateMethods: t.FunctionExpression | t.FunctionExpression[] | undefined;
privateMethods:
| (t.FunctionExpression | t.ArrowFunctionExpression)[]
| undefined;

// The names of local variables that will be used/returned from the decoration
locals: t.Identifier | t.Identifier[] | undefined;
Expand Down Expand Up @@ -496,6 +491,8 @@ function transformClass(
const classDecorators = path.node.decorators;
let hasElementDecorators = false;

const injectHasChecks = version === "2023-01";

const generateClassPrivateUid = createLazyPrivateUidGeneratorForClass(path);

// Iterate over the class to see if we need to decorate it, and also to
Expand Down Expand Up @@ -623,7 +620,9 @@ function transformClass(

if (hasDecorators) {
let locals: t.Identifier | t.Identifier[];
let privateMethods: t.FunctionExpression | t.FunctionExpression[];
let privateMethods: Array<
t.FunctionExpression | t.ArrowFunctionExpression
>;

if (kind === ACCESSOR) {
const { value } = element.node as t.ClassAccessorProperty;
Expand All @@ -646,7 +645,7 @@ function transformClass(
const [newPath] = element.replaceWith(newField);

if (isPrivate) {
privateMethods = extractProxyAccessorsFor(newId);
privateMethods = extractProxyAccessorsFor(newId, injectHasChecks);

const getId = newPath.scope.parent.generateDeclaredUidIdentifier(
`get_${name}`,
Expand Down Expand Up @@ -680,7 +679,7 @@ function transformClass(
locals = initId;

if (isPrivate) {
privateMethods = extractProxyAccessorsFor(key);
privateMethods = extractProxyAccessorsFor(key, injectHasChecks);
}
} else if (isPrivate) {
locals = element.scope.parent.generateDeclaredUidIdentifier(
Expand All @@ -704,12 +703,18 @@ function transformClass(
async: isAsync,
} = element.node as t.ClassPrivateMethod;

privateMethods = t.functionExpression(
undefined,
params.filter(isNotTsParameter),
body,
isAsync,
);
privateMethods = [
t.functionExpression(
undefined,
params.filter(isNotTsParameter),
body,
isAsync,
),
injectHasChecks &&
(template.expression.ast`
_ => ${t.cloneNode(key)} in _
` as t.ArrowFunctionExpression),
].filter(Boolean);

if (kind === GETTER || kind === SETTER) {
movePrivateAccessor(
Expand Down
Expand Up @@ -31,6 +31,10 @@ let foo = new Foo();
const aContext = foo['#aContext'];
const bContext = foo['#bContext'];

expect(aContext.access.has(foo)).toBe(true);
expect(aContext.access.has({})).toBe(false);
expect(aContext.access.has(Object.create(foo))).toBe(false);

expect(aContext.access.get(foo)).toBe(2);
aContext.access.set(foo, 123);
expect(aContext.access.get(foo)).toBe(125);
Expand Down
Expand Up @@ -40,8 +40,8 @@ function _get_b2() {
return babelHelpers.classPrivateFieldGet(this, _A);
}, function (value) {
babelHelpers.classPrivateFieldSet(this, _A, value);
}], [dec, 1, "b", function () {
}, _ => _A.has(babelHelpers.checkInRHS(_))], [dec, 1, "b", function () {
return babelHelpers.classPrivateFieldGet(this, _B);
}, function (value) {
babelHelpers.classPrivateFieldSet(this, _B, value);
}]], []).e;
}, _ => _B.has(babelHelpers.checkInRHS(_))]], []).e;
Expand Up @@ -35,6 +35,12 @@ const aContext = foo['aContext'];
const bContext = foo['bContext'];
const cContext = foo['cContext'];

expect(aContext.access.has(foo)).toBe(true);
expect(aContext.access.has({})).toBe(false);
expect(aContext.access.has(Object.create(foo))).toBe(true);
expect(aContext.access.has({ a: 1 })).toBe(true);
expect(aContext.access.has(Object.create({ a: 1 }))).toBe(true);

expect(foo.a).toBe(2);
expect(aContext.access.get(foo)).toBe(2);
foo.a = 123;
Expand Down
Expand Up @@ -29,6 +29,10 @@ class Foo {
const aContext = Foo['#aContext'];
const bContext = Foo['#bContext'];

expect(aContext.access.has(Foo)).toBe(true);
expect(aContext.access.has({})).toBe(false);
expect(aContext.access.has(Object.create(Foo))).toBe(false);

expect(aContext.access.get(Foo)).toBe(2);
aContext.access.set(Foo, 123);
expect(aContext.access.get(Foo)).toBe(125);
Expand Down
Expand Up @@ -31,11 +31,11 @@ function _get_b2() {
return babelHelpers.classStaticPrivateFieldSpecGet(this, Foo, _A);
}, function (value) {
babelHelpers.classStaticPrivateFieldSpecSet(this, Foo, _A, value);
}], [dec, 6, "b", function () {
}, _ => babelHelpers.checkInRHS(_) === Foo], [dec, 6, "b", function () {
return babelHelpers.classStaticPrivateFieldSpecGet(this, Foo, _B);
}, function (value) {
babelHelpers.classStaticPrivateFieldSpecSet(this, Foo, _B, value);
}]], []).e;
}, _ => babelHelpers.checkInRHS(_) === Foo]], []).e;
_initStatic(Foo);
})();
var _A = {
Expand Down
Expand Up @@ -33,6 +33,12 @@ const aContext = Foo['aContext'];
const bContext = Foo['bContext'];
const cContext = Foo['cContext'];

expect(aContext.access.has(Foo)).toBe(true);
expect(aContext.access.has({})).toBe(false);
expect(aContext.access.has(Object.create(Foo))).toBe(true);
expect(aContext.access.has({ a: 1 })).toBe(true);
expect(aContext.access.has(Object.create({ a: 1 }))).toBe(true);

expect(Foo.a).toBe(2);
expect(aContext.access.get(Foo)).toBe(2);
Foo.a = 123;
Expand Down
Expand Up @@ -6,11 +6,11 @@ class Foo {
return this.#A;
}, function (value) {
this.#A = value;
}], [dec, 1, "b", function () {
}, _ => #A in _], [dec, 1, "b", function () {
return this.#B;
}, function (value) {
this.#B = value;
}]], []).e;
}, _ => #B in _]], []).e;
}
#A = (_initProto(this), _init_a(this));
set #a(v) {
Expand Down
Expand Up @@ -6,11 +6,11 @@ class Foo {
return this.#A;
}, function (value) {
this.#A = value;
}], [dec, 6, "b", function () {
}, _ => #A in _], [dec, 6, "b", function () {
return this.#B;
}, function (value) {
this.#B = value;
}]], []).e;
}, _ => #B in _]], []).e;
_initStatic(this);
}
static #A = _init_a(this);
Expand Down
Expand Up @@ -4,7 +4,7 @@ class Foo extends Bar {
static {
[_call_x, _initProto] = babelHelpers.applyDecs2301(this, [[dec, 3, "x", function () {
return Bar.prototype.foo.call(this);
}]], []).e;
}, _ => #x in _]], []).e;
}
constructor(...args) {
super(...args);
Expand Down
Expand Up @@ -4,7 +4,7 @@ class Foo extends Bar {
static {
[_call_x, _initProto] = babelHelpers.applyDecs2301(this, [[dec, 2, "x", function () {
return Bar.prototype.foo.call(this);
}]], []).e;
}, _ => #x in _]], []).e;
}
constructor(...args) {
super(...args);
Expand Down
Expand Up @@ -18,6 +18,10 @@ let foo = new Foo();
const aContext = foo['#aContext'];
const bContext = foo['#bContext'];

expect(aContext.access.has(foo)).toBe(true);
expect(aContext.access.has({})).toBe(false);
expect(aContext.access.has(Object.create(foo))).toBe(false);

expect(aContext.access.get(foo)).toBe(2);
aContext.access.set(foo, 123);
expect(aContext.access.get(foo)).toBe(123);
Expand Down
Expand Up @@ -18,8 +18,8 @@ class Foo {
return babelHelpers.classPrivateFieldGet(this, _a);
}, function (value) {
babelHelpers.classPrivateFieldSet(this, _a, value);
}], [dec, 0, "b", function () {
}, _ => _a.has(babelHelpers.checkInRHS(_))], [dec, 0, "b", function () {
return babelHelpers.classPrivateFieldGet(this, _b);
}, function (value) {
babelHelpers.classPrivateFieldSet(this, _b, value);
}]], []).e;
}, _ => _b.has(babelHelpers.checkInRHS(_))]], []).e;
Expand Up @@ -22,6 +22,12 @@ const aContext = foo['aContext'];
const bContext = foo['bContext'];
const cContext = foo['cContext'];

expect(aContext.access.has(foo)).toBe(true);
expect(aContext.access.has({})).toBe(false);
expect(aContext.access.has(Object.create(foo))).toBe(true);
expect(aContext.access.has({ a: 1 })).toBe(true);
expect(aContext.access.has(Object.create({ a: 1 }))).toBe(true);

expect(foo.a).toBe(2);
expect(aContext.access.get(foo)).toBe(2);
foo.a = 123;
Expand Down
Expand Up @@ -16,6 +16,10 @@ class Foo {
const aContext = Foo['#aContext'];
const bContext = Foo['#bContext'];

expect(aContext.access.has(Foo)).toBe(true);
expect(aContext.access.has({})).toBe(false);
expect(aContext.access.has(Object.create(Foo))).toBe(false);

expect(aContext.access.get(Foo)).toBe(2);
aContext.access.set(Foo, 123);
expect(aContext.access.get(Foo)).toBe(123);
Expand Down

0 comments on commit d3bed4d

Please sign in to comment.