Skip to content

Commit

Permalink
Handle symbol key class elements decoration (#16270)
Browse files Browse the repository at this point in the history
* fix: handle symbol key class elements decoration

* update generated helpers

* Expand test cases
  • Loading branch information
JLHwung committed Feb 8, 2024
1 parent f89ff9d commit 96d1904
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 17 deletions.
4 changes: 2 additions & 2 deletions packages/babel-helpers/src/helpers-generated.ts
Expand Up @@ -48,10 +48,10 @@ export default Object.freeze({
"7.21.0",
'import checkInRHS from"checkInRHS";import setFunctionName from"setFunctionName";import toPropertyKey from"toPropertyKey";export default function applyDecs2305(e,t,r,n,o,a){function i(e,t,r){return function(n,o){return r&&r(n),e[t].call(n,o)}}function c(e,t){for(var r=0;r<e.length;r++)e[r].call(t);return t}function s(e,t,r,n){if("function"!=typeof e&&(n||void 0!==e))throw new TypeError(t+" must "+(r||"be")+" a function"+(n?"":" or undefined"));return e}function applyDec(e,t,r,n,o,a,c,u,l,f,p,d,h){function m(e){if(!h(e))throw new TypeError("Attempted to access private element on non-instance")}var y,v=t[0],g=t[3],b=!u;if(!b){r||Array.isArray(v)||(v=[v]);var w={},S=[],A=3===o?"get":4===o||d?"set":"value";f?(p||d?w={get:setFunctionName((function(){return g(this)}),n,"get"),set:function(e){t[4](this,e)}}:w[A]=g,p||setFunctionName(w[A],n,2===o?"":A)):p||(w=Object.getOwnPropertyDescriptor(e,n))}for(var P=e,j=v.length-1;j>=0;j-=r?2:1){var D=v[j],E=r?v[j-1]:void 0,I={},O={kind:["field","accessor","method","getter","setter","class"][o],name:n,metadata:a,addInitializer:function(e,t){if(e.v)throw new Error("attempted to call addInitializer after decoration was finished");s(t,"An initializer","be",!0),c.push(t)}.bind(null,I)};try{if(b)(y=s(D.call(E,P,O),"class decorators","return"))&&(P=y);else{var k,F;O.static=l,O.private=f,f?2===o?k=function(e){return m(e),w.value}:(o<4&&(k=i(w,"get",m)),3!==o&&(F=i(w,"set",m))):(k=function(e){return e[n]},(o<2||4===o)&&(F=function(e,t){e[n]=t}));var N=O.access={has:f?h.bind():function(e){return n in e}};if(k&&(N.get=k),F&&(N.set=F),P=D.call(E,d?{get:w.get,set:w.set}:w[A],O),d){if("object"==typeof P&&P)(y=s(P.get,"accessor.get"))&&(w.get=y),(y=s(P.set,"accessor.set"))&&(w.set=y),(y=s(P.init,"accessor.init"))&&S.push(y);else if(void 0!==P)throw new TypeError("accessor decorators must return an object with get, set, or init properties or void 0")}else s(P,(p?"field":"method")+" decorators","return")&&(p?S.push(P):w[A]=P)}}finally{I.v=!0}}return(p||d)&&u.push((function(e,t){for(var r=S.length-1;r>=0;r--)t=S[r].call(e,t);return t})),p||b||(f?d?u.push(i(w,"get"),i(w,"set")):u.push(2===o?w[A]:i.call.bind(w[A])):Object.defineProperty(e,n,w)),P}function u(e,t){return Object.defineProperty(e,Symbol.metadata||Symbol.for("Symbol.metadata"),{configurable:!0,enumerable:!0,value:t})}if(arguments.length>=6)var l=a[Symbol.metadata||Symbol.for("Symbol.metadata")];var f=Object.create(null==l?null:l),p=function(e,t,r,n){var o,a,i=[],s=function(t){return checkInRHS(t)===e},u=new Map;function l(e){e&&i.push(c.bind(null,e))}for(var f=0;f<t.length;f++){var p=t[f];if(Array.isArray(p)){var d=p[1],h=p[2],m=p.length>3,y=16&d,v=!!(8&d),g=0==(d&=7),b=h+"/"+v;if(!g&&!m){var w=u.get(b);if(!0===w||3===w&&4!==d||4===w&&3!==d)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: "+h);u.set(b,!(d>2)||d)}applyDec(v?e:e.prototype,p,y,m?"#"+h:toPropertyKey(h),d,n,v?a=a||[]:o=o||[],i,v,m,g,1===d,v&&m?s:r)}}return l(o),l(a),i}(e,t,o,f);return r.length||u(e,f),{e:p,get c(){var t=[];return r.length&&[u(applyDec(e,[r],n,e.name,5,f,t),f),c.bind(null,t,e)]}}}',
),
// size: 2883, gzip size: 1472
// size: 2899, gzip size: 1475
applyDecs2311: helper(
"7.23.0",
'import checkInRHS from"checkInRHS";import setFunctionName from"setFunctionName";import toPropertyKey from"toPropertyKey";export default function applyDecs2311(e,t,n,r,o,i){var a,c,u=Symbol.metadata||Symbol.for("Symbol.metadata"),s=Object.defineProperty,l=Object.create,f=l(null),p=n.length;function d(e,t,n,r){for(var o=0;o<e.length;o++)r=e[o].apply(n,t?[r]:[]);return t?r:n}function m(e,t,n,r){if("function"!=typeof e&&(r||void 0!==e))throw new TypeError(t+" must "+(n||"be")+" a function"+(r?"":" or undefined"));return e}function applyDec(e,t,n,r,o,i,u,l,p,h,y,v){function g(e){if(!v(e))throw new TypeError("Attempted to access private element on non-instance")}var b=[].concat(t[0]),w=t[3],D=!u,S=r+"/"+l,j=3===o,E=4===o,I=2===o;function P(e,t){return function(n,r){return t&&t(n),k[e].call(n,r)}}if(!D){var k={},F=[],N=j?"get":E||y?"set":"value";if(p?(h||y?k={get:setFunctionName((function(){return w(this)}),r,"get"),set:function(e){t[4](this,e)}}:k[N]=w,h||setFunctionName(k[N],r,I?"":N)):h||(k=Object.getOwnPropertyDescriptor(e,r)),!h&&!p){if((c=f[S])&&7!=(c^o))throw new Error("Decorating two elements with the same name ("+r+") is not supported yet");f[S]=o<3?1:o}}for(var O=e,z=b.length-1;z>=0;z-=n?2:1){var H=b[z],K=n?b[z-1]:void 0,R={},T={kind:["field","accessor","method","getter","setter","class"][o],name:r,metadata:a,addInitializer:function(e,t){if(e.v)throw new Error("attempted to call addInitializer after decoration was finished");m(t,"An initializer","be",!0),i.push(t)}.bind(null,R)};if(D)c=H.call(K,O,T),R.v=1,m(c,"class decorators","return")&&(O=c);else if(T.static=l,T.private=p,c=T.access={has:p?v.bind():function(e){return r in e}},E||(c.get=p?I?function(e){return g(e),k.value}:P("get",g):function(e){return e[r]}),I||j||(c.set=p?P("set",g):function(e,t){e[r]=t}),O=H.call(K,y?{get:k.get,set:k.set}:k[N],T),R.v=1,y){if("object"==typeof O&&O)(c=m(O.get,"accessor.get"))&&(k.get=c),(c=m(O.set,"accessor.set"))&&(k.set=c),(c=m(O.init,"accessor.init"))&&F.unshift(c);else if(void 0!==O)throw new TypeError("accessor decorators must return an object with get, set, or init properties or undefined")}else m(O,(h?"field":"method")+" decorators","return")&&(h?F.unshift(O):k[N]=O)}return o<2&&u.push(d.bind(null,F,1),d.bind(null,i,0)),h||D||(p?y?u.splice(-1,0,P("get"),P("set")):u.push(I?k[N]:d.call.bind(k[N])):s(e,r,k)),O}function h(e){return s(e,u,{configurable:!0,enumerable:!0,value:a})}return void 0!==i&&(a=i[u]),a=l(null==a?null:a),c=function(){var n,r,i=[];function a(e){e&&i.push(d.bind(null,e,0))}for(var c=0;c<t.length;c++){var u=t[c],s=u[1],l=u[2],f=!!u[3],p=16&s,m=!!(8&s),h=0==(s&=7),y=1===s;applyDec(m?e:e.prototype,u,p,f?"#"+l:toPropertyKey(l),s,h||y?[]:m?r=r||[]:n=n||[],i,m,f,h,y,m&&f?function(t){return checkInRHS(t)===e}:o)}return a(n),a(r),i}(),p||h(e),{e:c,get c(){var t=[];return p&&[h(applyDec(e,[n],r,e.name,5,t)),d.bind(null,t,0,e)]}}}',
'import checkInRHS from"checkInRHS";import setFunctionName from"setFunctionName";import toPropertyKey from"toPropertyKey";export default function applyDecs2311(e,t,n,r,o,i){var a,c,u=Symbol.metadata||Symbol.for("Symbol.metadata"),s=Object.defineProperty,l=Object.create,f=[l(null),l(null)],p=n.length;function d(e,t,n,r){for(var o=0;o<e.length;o++)r=e[o].apply(n,t?[r]:[]);return t?r:n}function m(e,t,n,r){if("function"!=typeof e&&(r||void 0!==e))throw new TypeError(t+" must "+(n||"be")+" a function"+(r?"":" or undefined"));return e}function applyDec(e,t,n,r,o,i,u,l,p,h,y,v){function g(e){if(!v(e))throw new TypeError("Attempted to access private element on non-instance")}var b=[].concat(t[0]),w=t[3],D=!u,S=3===o,j=4===o,E=2===o;function I(e,t){return function(n,r){return t&&t(n),P[e].call(n,r)}}if(!D){var P={},k=[],F=S?"get":j||y?"set":"value";if(p?(h||y?P={get:setFunctionName((function(){return w(this)}),r,"get"),set:function(e){t[4](this,e)}}:P[F]=w,h||setFunctionName(P[F],r,E?"":F)):h||(P=Object.getOwnPropertyDescriptor(e,r)),!h&&!p){if((c=f[+l][r])&&7!=(c^o))throw new Error("Decorating two elements with the same name ("+P[F].name+") is not supported yet");f[+l][r]=o<3?1:o}}for(var N=e,O=b.length-1;O>=0;O-=n?2:1){var z=b[O],H=n?b[O-1]:void 0,K={},R={kind:["field","accessor","method","getter","setter","class"][o],name:r,metadata:a,addInitializer:function(e,t){if(e.v)throw new Error("attempted to call addInitializer after decoration was finished");m(t,"An initializer","be",!0),i.push(t)}.bind(null,K)};if(D)c=z.call(H,N,R),K.v=1,m(c,"class decorators","return")&&(N=c);else if(R.static=l,R.private=p,c=R.access={has:p?v.bind():function(e){return r in e}},j||(c.get=p?E?function(e){return g(e),P.value}:I("get",g):function(e){return e[r]}),E||S||(c.set=p?I("set",g):function(e,t){e[r]=t}),N=z.call(H,y?{get:P.get,set:P.set}:P[F],R),K.v=1,y){if("object"==typeof N&&N)(c=m(N.get,"accessor.get"))&&(P.get=c),(c=m(N.set,"accessor.set"))&&(P.set=c),(c=m(N.init,"accessor.init"))&&k.unshift(c);else if(void 0!==N)throw new TypeError("accessor decorators must return an object with get, set, or init properties or undefined")}else m(N,(h?"field":"method")+" decorators","return")&&(h?k.unshift(N):P[F]=N)}return o<2&&u.push(d.bind(null,k,1),d.bind(null,i,0)),h||D||(p?y?u.splice(-1,0,I("get"),I("set")):u.push(E?P[F]:d.call.bind(P[F])):s(e,r,P)),N}function h(e){return s(e,u,{configurable:!0,enumerable:!0,value:a})}return void 0!==i&&(a=i[u]),a=l(null==a?null:a),c=function(){var n,r,i=[];function a(e){e&&i.push(d.bind(null,e,0))}for(var c=0;c<t.length;c++){var u=t[c],s=u[1],l=u[2],f=!!u[3],p=16&s,m=!!(8&s),h=0==(s&=7),y=1===s;applyDec(m?e:e.prototype,u,p,f?"#"+l:toPropertyKey(l),s,h||y?[]:m?r=r||[]:n=n||[],i,m,f,h,y,m&&f?function(t){return checkInRHS(t)===e}:o)}return a(n),a(r),i}(),p||h(e),{e:c,get c(){var t=[];return p&&[h(applyDec(e,[n],r,e.name,5,t)),d.bind(null,t,0,e)]}}}',
),
// size: 187, gzip size: 167
assertClassBrand: helper(
Expand Down
29 changes: 14 additions & 15 deletions packages/babel-helpers/src/helpers/applyDecs2311.ts
Expand Up @@ -26,7 +26,7 @@ type DecoratorContextAccess = {
};
type DecoratorContext = {
kind: "accessor" | "method" | "getter" | "setter" | "field" | "class";
name: string;
name: string | symbol;
static?: boolean;
private?: boolean;
access?: DecoratorContextAccess;
Expand All @@ -42,7 +42,10 @@ type DecoratorInfo =
privateSetter?: Function,
]
| [classDecs: Function[]];

type DecoratorNonFieldCheckStorage = Record<
string | symbol,
PROP_KIND.ACCESSOR | PROP_KIND.GETTER | PROP_KIND.SETTER
>;
/**
Basic usage:
Expand Down Expand Up @@ -202,13 +205,10 @@ export default /* @no-mangle */ function applyDecs2311(
var create = Object.create;
var metadata: any;
// Use both as and satisfies to ensure that we only use non-zero values
var existingNonFields = create(null) as Record<
string,
1 | 3 | 4
> satisfies Record<
string,
PROP_KIND.ACCESSOR | PROP_KIND.GETTER | PROP_KIND.SETTER
>;
var existingNonFields = [create(null), create(null)] as [
DecoratorNonFieldCheckStorage,
DecoratorNonFieldCheckStorage,
];
var hasClassDecs = classDecs.length;
// This is a temporary variable for smaller helper size
var _: any;
Expand Down Expand Up @@ -250,7 +250,7 @@ export default /* @no-mangle */ function applyDecs2311(
Class: any,
decInfo: DecoratorInfo,
decoratorsHaveThis: number,
name: string,
name: string | symbol,
kind: PROP_KIND,
initializers: Function[],
ret?: Function[],
Expand All @@ -270,8 +270,7 @@ export default /* @no-mangle */ function applyDecs2311(

var decs = [].concat(decInfo[0]),
decVal = decInfo[3],
isClass = !ret,
mapKey = name + "/" + isStatic;
isClass = !ret;

var isGetter = kind === PROP_KIND.GETTER;
var isSetter = kind === PROP_KIND.SETTER;
Expand Down Expand Up @@ -322,19 +321,19 @@ export default /* @no-mangle */ function applyDecs2311(
}

if (!isField && !isPrivate) {
_ = existingNonFields[mapKey];
_ = existingNonFields[+isStatic][name];
// flag is 1, 3, or 4; kind is 0, 1, 2, 3, or 4
// flag ^ kind is 7 if and only if one of them is 3 and the other one is 4.
if (_ && (_ ^ kind) !== 7) {
throw new Error(
"Decorating two elements with the same name (" +
name +
desc[key].name +
") is not supported yet",
);
}
// We use PROP_KIND.ACCESSOR to mark a name as "fully used":
// either a get/set pair, or a non-getter/setter.
existingNonFields[mapKey] =
existingNonFields[+isStatic][name] =
kind < PROP_KIND.GETTER
? PROP_KIND.ACCESSOR
: (kind as PROP_KIND.GETTER | PROP_KIND.SETTER);
Expand Down
Expand Up @@ -49,3 +49,30 @@ expect(() => {
}
}
}).toThrow("Decorating two elements with the same name");

expect(() => {
class Foo {
@dec
*[Symbol.iterator]() {
return 1;
}

@dec
get [Symbol.iterator]() {
return function *() {};
}
}
}).toThrow("Decorating two elements with the same name (get [Symbol.iterator]) is not supported yet");

expect(() => {
class Foo {
@dec
*[Symbol.iterator]() {}

@dec
*[Symbol("Symbol.iterator")]() {}

@dec
*"[Symbol.iterator]"() {}
}
}).not.toThrow();

0 comments on commit 96d1904

Please sign in to comment.