Skip to content

Commit 8b7fd2b

Browse files
Add .has method to context.access
1 parent 3cf9ebd commit 8b7fd2b

File tree

56 files changed

+258
-97
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+258
-97
lines changed

packages/babel-helpers/src/helpers-generated.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export default Object.freeze({
3535
),
3636
applyDecs2301: helper(
3737
"7.20.0",
38-
'function createAddInitializerMethod(initializers,decoratorFinishedRef){return function(initializer){assertNotFinished(decoratorFinishedRef,"addInitializer"),assertCallable(initializer,"An initializer"),initializers.push(initializer)}}function memberDec(dec,name,desc,initializers,kind,isStatic,isPrivate,value){var kindStr;switch(kind){case 1:kindStr="accessor";break;case 2:kindStr="method";break;case 3:kindStr="getter";break;case 4:kindStr="setter";break;default:kindStr="field"}var get,set,ctx={kind:kindStr,name:isPrivate?"#"+name:name,static:isStatic,private:isPrivate},decoratorFinishedRef={v:!1};if(0!==kind&&(ctx.addInitializer=createAddInitializerMethod(initializers,decoratorFinishedRef)),isPrivate||0!==kind&&2!==kind)if(2===kind)get=function(){return desc.value};else{var t=0===kind||1===kind;(t||3===kind)&&(get=function(target){return desc.get.call(target)}),(t||4===kind)&&(set=function(target,value){desc.set.call(target,value)})}else get=function(receiver){return receiver[name]},0===kind&&(set=function(receiver,v){receiver[name]=v});ctx.access=get&&set?{get:get,set:set}:get?{get:get}:{set:set};try{return dec(value,ctx)}finally{decoratorFinishedRef.v=!0}}function assertNotFinished(decoratorFinishedRef,fnName){if(decoratorFinishedRef.v)throw new Error("attempted to call "+fnName+" after decoration was finished")}function assertCallable(fn,hint){if("function"!=typeof fn)throw new TypeError(hint+" must be a function")}function assertValidReturnValue(kind,value){var type=typeof value;if(1===kind){if("object"!==type||null===value)throw new TypeError("accessor decorators must return an object with get, set, or init properties or void 0");void 0!==value.get&&assertCallable(value.get,"accessor.get"),void 0!==value.set&&assertCallable(value.set,"accessor.set"),void 0!==value.init&&assertCallable(value.init,"accessor.init")}else if("function"!==type){var hint;throw hint=0===kind?"field":10===kind?"class":"method",new TypeError(hint+" decorators must return a function or void 0")}}function applyMemberDec(ret,base,decInfo,name,kind,isStatic,isPrivate,initializers){var desc,init,value,newValue,get,set,decs=decInfo[0];if(isPrivate?desc=0===kind||1===kind?{get:decInfo[3],set:decInfo[4]}:3===kind?{get:decInfo[3]}:4===kind?{set:decInfo[3]}:{value:decInfo[3]}:0!==kind&&(desc=Object.getOwnPropertyDescriptor(base,name)),1===kind?value={get:desc.get,set:desc.set}:2===kind?value=desc.value:3===kind?value=desc.get:4===kind&&(value=desc.set),"function"==typeof decs)void 0!==(newValue=memberDec(decs,name,desc,initializers,kind,isStatic,isPrivate,value))&&(assertValidReturnValue(kind,newValue),0===kind?init=newValue:1===kind?(init=newValue.init,get=newValue.get||value.get,set=newValue.set||value.set,value={get:get,set:set}):value=newValue);else for(var i=decs.length-1;i>=0;i--){var newInit;if(void 0!==(newValue=memberDec(decs[i],name,desc,initializers,kind,isStatic,isPrivate,value)))assertValidReturnValue(kind,newValue),0===kind?newInit=newValue:1===kind?(newInit=newValue.init,get=newValue.get||value.get,set=newValue.set||value.set,value={get:get,set:set}):value=newValue,void 0!==newInit&&(void 0===init?init=newInit:"function"==typeof init?init=[init,newInit]:init.push(newInit))}if(0===kind||1===kind){if(void 0===init)init=function(instance,init){return init};else if("function"!=typeof init){var ownInitializers=init;init=function(instance,init){for(var value=init,i=0;i<ownInitializers.length;i++)value=ownInitializers[i].call(instance,value);return value}}else{var originalInitializer=init;init=function(instance,init){return originalInitializer.call(instance,init)}}ret.push(init)}0!==kind&&(1===kind?(desc.get=value.get,desc.set=value.set):2===kind?desc.value=value:3===kind?desc.get=value:4===kind&&(desc.set=value),isPrivate?1===kind?(ret.push((function(instance,args){return value.get.call(instance,args)})),ret.push((function(instance,args){return value.set.call(instance,args)}))):2===kind?ret.push(value):ret.push((function(instance,args){return value.call(instance,args)})):Object.defineProperty(base,name,desc))}function applyMemberDecs(Class,decInfos){for(var protoInitializers,staticInitializers,ret=[],existingProtoNonFields=new Map,existingStaticNonFields=new Map,i=0;i<decInfos.length;i++){var decInfo=decInfos[i];if(Array.isArray(decInfo)){var base,initializers,kind=decInfo[1],name=decInfo[2],isPrivate=decInfo.length>3,isStatic=kind>=5;if(isStatic?(base=Class,0!==(kind-=5)&&(initializers=staticInitializers=staticInitializers||[])):(base=Class.prototype,0!==kind&&(initializers=protoInitializers=protoInitializers||[])),0!==kind&&!isPrivate){var existingNonFields=isStatic?existingStaticNonFields:existingProtoNonFields,existingKind=existingNonFields.get(name)||0;if(!0===existingKind||3===existingKind&&4!==kind||4===existingKind&&3!==kind)throw new Error("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: "+name);!existingKind&&kind>2?existingNonFields.set(name,kind):existingNonFields.set(name,!0)}applyMemberDec(ret,base,decInfo,name,kind,isStatic,isPrivate,initializers)}}return pushInitializers(ret,protoInitializers),pushInitializers(ret,staticInitializers),ret}function pushInitializers(ret,initializers){initializers&&ret.push((function(instance){for(var i=0;i<initializers.length;i++)initializers[i].call(instance);return instance}))}function applyClassDecs(targetClass,classDecs){if(classDecs.length>0){for(var initializers=[],newClass=targetClass,name=targetClass.name,i=classDecs.length-1;i>=0;i--){var decoratorFinishedRef={v:!1};try{var nextNewClass=classDecs[i](newClass,{kind:"class",name:name,addInitializer:createAddInitializerMethod(initializers,decoratorFinishedRef)})}finally{decoratorFinishedRef.v=!0}void 0!==nextNewClass&&(assertValidReturnValue(10,nextNewClass),newClass=nextNewClass)}return[newClass,function(){for(var i=0;i<initializers.length;i++)initializers[i].call(newClass)}]}}export default function applyDecs2301(targetClass,memberDecs,classDecs){return{e:applyMemberDecs(targetClass,memberDecs),get c(){return applyClassDecs(targetClass,classDecs)}}}',
38+
'function createAddInitializerMethod(initializers,decoratorFinishedRef){return function(initializer){assertNotFinished(decoratorFinishedRef,"addInitializer"),assertCallable(initializer,"An initializer"),initializers.push(initializer)}}function memberDec(dec,name,desc,initializers,kind,isStatic,isPrivate,value,privateHas){var kindStr;switch(kind){case 1:kindStr="accessor";break;case 2:kindStr="method";break;case 3:kindStr="getter";break;case 4:kindStr="setter";break;default:kindStr="field"}var get,set,has,ctx={kind:kindStr,name:isPrivate?"#"+name:name,static:isStatic,private:isPrivate},decoratorFinishedRef={v:!1};if(0!==kind&&(ctx.addInitializer=createAddInitializerMethod(initializers,decoratorFinishedRef)),has=isPrivate?privateHas:function(receiver){return name in receiver},isPrivate||0!==kind&&2!==kind)if(2===kind)get=function(){return desc.value};else{var t=0===kind||1===kind;(t||3===kind)&&(get=function(target){return desc.get.call(target)}),(t||4===kind)&&(set=function(target,value){desc.set.call(target,value)})}else get=function(receiver){return receiver[name]},0===kind&&(set=function(receiver,v){receiver[name]=v});ctx.access=get&&set?{get:get,set:set,has:has}:get?{get:get,has:has}:{set:set,has:has};try{return dec(value,ctx)}finally{decoratorFinishedRef.v=!0}}function assertNotFinished(decoratorFinishedRef,fnName){if(decoratorFinishedRef.v)throw new Error("attempted to call "+fnName+" after decoration was finished")}function assertCallable(fn,hint){if("function"!=typeof fn)throw new TypeError(hint+" must be a function")}function assertValidReturnValue(kind,value){var type=typeof value;if(1===kind){if("object"!==type||null===value)throw new TypeError("accessor decorators must return an object with get, set, or init properties or void 0");void 0!==value.get&&assertCallable(value.get,"accessor.get"),void 0!==value.set&&assertCallable(value.set,"accessor.set"),void 0!==value.init&&assertCallable(value.init,"accessor.init")}else if("function"!==type){var hint;throw hint=0===kind?"field":10===kind?"class":"method",new TypeError(hint+" decorators must return a function or void 0")}}function applyMemberDec(ret,base,decInfo,name,kind,isStatic,isPrivate,initializers){var desc,init,value,has,newValue,get,set,decs=decInfo[0];if(isPrivate?0===kind||1===kind?(desc={get:decInfo[3],set:decInfo[4]},has=decInfo[5]):(desc=3===kind?{get:decInfo[3]}:4===kind?{set:decInfo[3]}:{value:decInfo[3]},has=decInfo[4]):0!==kind&&(desc=Object.getOwnPropertyDescriptor(base,name)),1===kind?value={get:desc.get,set:desc.set}:2===kind?value=desc.value:3===kind?value=desc.get:4===kind&&(value=desc.set),"function"==typeof decs)void 0!==(newValue=memberDec(decs,name,desc,initializers,kind,isStatic,isPrivate,value,has))&&(assertValidReturnValue(kind,newValue),0===kind?init=newValue:1===kind?(init=newValue.init,get=newValue.get||value.get,set=newValue.set||value.set,value={get:get,set:set}):value=newValue);else for(var i=decs.length-1;i>=0;i--){var newInit;if(void 0!==(newValue=memberDec(decs[i],name,desc,initializers,kind,isStatic,isPrivate,value,has)))assertValidReturnValue(kind,newValue),0===kind?newInit=newValue:1===kind?(newInit=newValue.init,get=newValue.get||value.get,set=newValue.set||value.set,value={get:get,set:set}):value=newValue,void 0!==newInit&&(void 0===init?init=newInit:"function"==typeof init?init=[init,newInit]:init.push(newInit))}if(0===kind||1===kind){if(void 0===init)init=function(instance,init){return init};else if("function"!=typeof init){var ownInitializers=init;init=function(instance,init){for(var value=init,i=0;i<ownInitializers.length;i++)value=ownInitializers[i].call(instance,value);return value}}else{var originalInitializer=init;init=function(instance,init){return originalInitializer.call(instance,init)}}ret.push(init)}0!==kind&&(1===kind?(desc.get=value.get,desc.set=value.set):2===kind?desc.value=value:3===kind?desc.get=value:4===kind&&(desc.set=value),isPrivate?1===kind?(ret.push((function(instance,args){return value.get.call(instance,args)})),ret.push((function(instance,args){return value.set.call(instance,args)}))):2===kind?ret.push(value):ret.push((function(instance,args){return value.call(instance,args)})):Object.defineProperty(base,name,desc))}function applyMemberDecs(Class,decInfos){for(var protoInitializers,staticInitializers,ret=[],existingProtoNonFields=new Map,existingStaticNonFields=new Map,i=0;i<decInfos.length;i++){var decInfo=decInfos[i];if(Array.isArray(decInfo)){var base,initializers,kind=decInfo[1],name=decInfo[2],isPrivate=decInfo.length>3,isStatic=kind>=5;if(isStatic?(base=Class,0!==(kind-=5)&&(initializers=staticInitializers=staticInitializers||[])):(base=Class.prototype,0!==kind&&(initializers=protoInitializers=protoInitializers||[])),0!==kind&&!isPrivate){var existingNonFields=isStatic?existingStaticNonFields:existingProtoNonFields,existingKind=existingNonFields.get(name)||0;if(!0===existingKind||3===existingKind&&4!==kind||4===existingKind&&3!==kind)throw new Error("Attempted to decorate a public method/accessor that has the same name as a previously decorated public method/accessor. This is not currently supported by the decorators plugin. Property name was: "+name);!existingKind&&kind>2?existingNonFields.set(name,kind):existingNonFields.set(name,!0)}applyMemberDec(ret,base,decInfo,name,kind,isStatic,isPrivate,initializers)}}return pushInitializers(ret,protoInitializers),pushInitializers(ret,staticInitializers),ret}function pushInitializers(ret,initializers){initializers&&ret.push((function(instance){for(var i=0;i<initializers.length;i++)initializers[i].call(instance);return instance}))}function applyClassDecs(targetClass,classDecs){if(classDecs.length>0){for(var initializers=[],newClass=targetClass,name=targetClass.name,i=classDecs.length-1;i>=0;i--){var decoratorFinishedRef={v:!1};try{var nextNewClass=classDecs[i](newClass,{kind:"class",name:name,addInitializer:createAddInitializerMethod(initializers,decoratorFinishedRef)})}finally{decoratorFinishedRef.v=!0}void 0!==nextNewClass&&(assertValidReturnValue(10,nextNewClass),newClass=nextNewClass)}return[newClass,function(){for(var i=0;i<initializers.length;i++)initializers[i].call(newClass)}]}}export default function applyDecs2301(targetClass,memberDecs,classDecs){return{e:applyMemberDecs(targetClass,memberDecs),get c(){return applyClassDecs(targetClass,classDecs)}}}',
3939
),
4040
asyncGeneratorDelegate: helper(
4141
"7.0.0-beta.0",

packages/babel-helpers/src/helpers/applyDecs2301.js

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ function memberDec(
3434
kind,
3535
isStatic,
3636
isPrivate,
37-
value
37+
value,
38+
privateHas
3839
) {
3940
var kindStr;
4041

@@ -71,7 +72,13 @@ function memberDec(
7172
);
7273
}
7374

74-
var get, set;
75+
var get, set, has;
76+
if (isPrivate) has = privateHas;
77+
else {
78+
has = function (receiver) {
79+
return name in receiver;
80+
};
81+
}
7582
if (!isPrivate && (kind === 0 /* FIELD */ || kind === 2) /* METHOD */) {
7683
get = function (receiver) {
7784
return receiver[name];
@@ -102,7 +109,11 @@ function memberDec(
102109
}
103110
}
104111
ctx.access =
105-
get && set ? { get: get, set: set } : get ? { get: get } : { set: set };
112+
get && set
113+
? { get: get, set: set, has: has }
114+
: get
115+
? { get: get, has: has }
116+
: { set: set, has: has };
106117

107118
try {
108119
return dec(value, ctx);
@@ -168,26 +179,30 @@ function applyMemberDec(
168179
) {
169180
var decs = decInfo[0];
170181

171-
var desc, init, value;
182+
var desc, init, value, has;
172183

173184
if (isPrivate) {
174185
if (kind === 0 /* FIELD */ || kind === 1 /* ACCESSOR */) {
175186
desc = {
176187
get: decInfo[3],
177188
set: decInfo[4],
178189
};
179-
} else if (kind === 3 /* GETTER */) {
180-
desc = {
181-
get: decInfo[3],
182-
};
183-
} else if (kind === 4 /* SETTER */) {
184-
desc = {
185-
set: decInfo[3],
186-
};
190+
has = decInfo[5];
187191
} else {
188-
desc = {
189-
value: decInfo[3],
190-
};
192+
if (kind === 3 /* GETTER */) {
193+
desc = {
194+
get: decInfo[3],
195+
};
196+
} else if (kind === 4 /* SETTER */) {
197+
desc = {
198+
set: decInfo[3],
199+
};
200+
} else {
201+
desc = {
202+
value: decInfo[3],
203+
};
204+
}
205+
has = decInfo[4];
191206
}
192207
} else if (kind !== 0 /* FIELD */) {
193208
desc = Object.getOwnPropertyDescriptor(base, name);
@@ -217,7 +232,8 @@ function applyMemberDec(
217232
kind,
218233
isStatic,
219234
isPrivate,
220-
value
235+
value,
236+
has
221237
);
222238

223239
if (newValue !== void 0) {
@@ -247,7 +263,8 @@ function applyMemberDec(
247263
kind,
248264
isStatic,
249265
isPrivate,
250-
value
266+
value,
267+
has
251268
);
252269

253270
if (newValue !== void 0) {

packages/babel-plugin-proposal-decorators/src/transformer-2023-01.ts

Lines changed: 39 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -231,31 +231,24 @@ function addProxyAccessorsFor(
231231

232232
function extractProxyAccessorsFor(
233233
targetKey: t.PrivateName,
234-
): t.FunctionExpression[] {
234+
injectHas: boolean,
235+
): (t.FunctionExpression | t.ArrowFunctionExpression)[] {
235236
return [
236-
t.functionExpression(
237-
undefined,
238-
[],
239-
t.blockStatement([
240-
t.returnStatement(
241-
t.memberExpression(t.thisExpression(), t.cloneNode(targetKey)),
242-
),
243-
]),
244-
),
245-
t.functionExpression(
246-
undefined,
247-
[t.identifier("value")],
248-
t.blockStatement([
249-
t.expressionStatement(
250-
t.assignmentExpression(
251-
"=",
252-
t.memberExpression(t.thisExpression(), t.cloneNode(targetKey)),
253-
t.identifier("value"),
254-
),
255-
),
256-
]),
257-
),
258-
];
237+
template.expression.ast`
238+
function () {
239+
return this.${t.cloneNode(targetKey)};
240+
}
241+
` as t.FunctionExpression,
242+
template.expression.ast`
243+
function (value) {
244+
this.${t.cloneNode(targetKey)} = value;
245+
}
246+
` as t.FunctionExpression,
247+
injectHas &&
248+
(template.expression.ast`
249+
_ => ${t.cloneNode(targetKey)} in _
250+
` as t.ArrowFunctionExpression),
251+
].filter(Boolean);
259252
}
260253

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

302-
privateMethods: t.FunctionExpression | t.FunctionExpression[] | undefined;
295+
privateMethods:
296+
| (t.FunctionExpression | t.ArrowFunctionExpression)[]
297+
| undefined;
303298

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

494+
const injectHasChecks = version === "2023-01";
495+
499496
const generateClassPrivateUid = createLazyPrivateUidGeneratorForClass(path);
500497

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

624621
if (hasDecorators) {
625622
let locals: t.Identifier | t.Identifier[];
626-
let privateMethods: t.FunctionExpression | t.FunctionExpression[];
623+
let privateMethods: Array<
624+
t.FunctionExpression | t.ArrowFunctionExpression
625+
>;
627626

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

648647
if (isPrivate) {
649-
privateMethods = extractProxyAccessorsFor(newId);
648+
privateMethods = extractProxyAccessorsFor(newId, injectHasChecks);
650649

651650
const getId = newPath.scope.parent.generateDeclaredUidIdentifier(
652651
`get_${name}`,
@@ -680,7 +679,7 @@ function transformClass(
680679
locals = initId;
681680

682681
if (isPrivate) {
683-
privateMethods = extractProxyAccessorsFor(key);
682+
privateMethods = extractProxyAccessorsFor(key, injectHasChecks);
684683
}
685684
} else if (isPrivate) {
686685
locals = element.scope.parent.generateDeclaredUidIdentifier(
@@ -704,12 +703,18 @@ function transformClass(
704703
async: isAsync,
705704
} = element.node as t.ClassPrivateMethod;
706705

707-
privateMethods = t.functionExpression(
708-
undefined,
709-
params.filter(isNotTsParameter),
710-
body,
711-
isAsync,
712-
);
706+
privateMethods = [
707+
t.functionExpression(
708+
undefined,
709+
params.filter(isNotTsParameter),
710+
body,
711+
isAsync,
712+
),
713+
injectHasChecks &&
714+
(template.expression.ast`
715+
_ => ${t.cloneNode(key)} in _
716+
` as t.ArrowFunctionExpression),
717+
].filter(Boolean);
713718

714719
if (kind === GETTER || kind === SETTER) {
715720
movePrivateAccessor(

packages/babel-plugin-proposal-decorators/test/fixtures/2023-01-accessors--to-es2015/private/exec.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ let foo = new Foo();
3131
const aContext = foo['#aContext'];
3232
const bContext = foo['#bContext'];
3333

34+
expect(aContext.access.has(foo)).toBe(true);
35+
expect(aContext.access.has({})).toBe(false);
36+
expect(aContext.access.has(Object.create(foo))).toBe(false);
37+
3438
expect(aContext.access.get(foo)).toBe(2);
3539
aContext.access.set(foo, 123);
3640
expect(aContext.access.get(foo)).toBe(125);

packages/babel-plugin-proposal-decorators/test/fixtures/2023-01-accessors--to-es2015/private/output.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ function _get_b2() {
4040
return babelHelpers.classPrivateFieldGet(this, _A);
4141
}, function (value) {
4242
babelHelpers.classPrivateFieldSet(this, _A, value);
43-
}], [dec, 1, "b", function () {
43+
}, _ => _A.has(babelHelpers.checkInRHS(_))], [dec, 1, "b", function () {
4444
return babelHelpers.classPrivateFieldGet(this, _B);
4545
}, function (value) {
4646
babelHelpers.classPrivateFieldSet(this, _B, value);
47-
}]], []).e;
47+
}, _ => _B.has(babelHelpers.checkInRHS(_))]], []).e;

packages/babel-plugin-proposal-decorators/test/fixtures/2023-01-accessors--to-es2015/public/exec.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ const aContext = foo['aContext'];
3535
const bContext = foo['bContext'];
3636
const cContext = foo['cContext'];
3737

38+
expect(aContext.access.has(foo)).toBe(true);
39+
expect(aContext.access.has({})).toBe(false);
40+
expect(aContext.access.has(Object.create(foo))).toBe(true);
41+
expect(aContext.access.has({ a: 1 })).toBe(true);
42+
expect(aContext.access.has(Object.create({ a: 1 }))).toBe(true);
43+
3844
expect(foo.a).toBe(2);
3945
expect(aContext.access.get(foo)).toBe(2);
4046
foo.a = 123;

0 commit comments

Comments
 (0)