Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce helper size for decorator 2023-11 #16263

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/babel-helpers/src/helpers-generated.ts
Original file line number Diff line number Diff line change
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: 2833, gzip size: 1416
// size: 2777, gzip size: 1412
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 c,a=Symbol.metadata||Symbol.for("Symbol.metadata"),u=Object.defineProperty,s=n.length;function l(e,t,n){return function(r,o){return n&&n(r),e[t].call(r,o)}}function f(e,t){for(var n=0;n<e.length;n++)e[n].call(t);return t}function p(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,a,u,s,d,m,h){function v(e){if(!h(e))throw new TypeError("Attempted to access private element on non-instance")}var y,g=[].concat(t[0]),b=t[3],w=!a;if(!w){var j={},P=[],S=3===o?"get":4===o||m?"set":"value";s?(d||m?j={get:setFunctionName((function(){return b(this)}),r,"get"),set:function(e){t[4](this,e)}}:j[S]=b,d||setFunctionName(j[S],r,2===o?"":S)):d||(j=Object.getOwnPropertyDescriptor(e,r))}for(var D=e,I=g.length-1;I>=0;I-=n?2:1){var O=g[I],k=n?g[I-1]:void 0,E={},F={kind:["field","accessor","method","getter","setter","class"][o],name:r,metadata:c,addInitializer:function(e,t){if(e.v)throw new Error("attempted to call addInitializer after decoration was finished");p(t,"An initializer","be",!0),i.push(t)}.bind(null,E)};if(w)(y=p(O.call(k,D,F),"class decorators","return"))&&(D=y);else{var N,z;F.static=u,F.private=s,s?2===o?N=function(e){return v(e),j.value}:(o<4&&(N=l(j,"get",v)),3!==o&&(z=l(j,"set",v))):(N=function(e){return e[r]},(o<2||4===o)&&(z=function(e,t){e[r]=t}));var H=F.access={has:s?h.bind():function(e){return r in e}};if(N&&(H.get=N),z&&(H.set=z),D=O.call(k,m?{get:j.get,set:j.set}:j[S],F),m){if("object"==typeof D&&D)(y=p(D.get,"accessor.get"))&&(j.get=y),(y=p(D.set,"accessor.set"))&&(j.set=y),(y=p(D.init,"accessor.init"))&&P.push(y);else if(void 0!==D)throw new TypeError("accessor decorators must return an object with get, set, or init properties or undefined")}else p(D,(d?"field":"method")+" decorators","return")&&(d?P.push(D):j[S]=D)}E.v=!0}return(d||m)&&a.push((function(e,t){for(var n=P.length-1;n>=0;n--)t=P[n].call(e,t);return t}),f.bind(null,i)),d||w||(s?m?a.splice(-1,0,l(j,"get"),l(j,"set")):a.push(2===o?j[S]:l.call.bind(j[S])):Object.defineProperty(e,r,j)),D}function d(e){return u(e,a,{configurable:!0,enumerable:!0,value:c})}void 0!==i&&(c=i[a]),c=Object.create(null==c?null:c);var m=function(){var n,r,i=[],c=function(t){return checkInRHS(t)===e};function a(e){e&&i.push(f.bind(null,e))}for(var u=0;u<t.length;u++){var s=t[u],l=s[1],p=s[2],d=!!s[3],m=16&l,h=!!(8&l),v=0==(l&=7),y=1===l;applyDec(h?e:e.prototype,s,m,d?"#"+p:toPropertyKey(p),l,v||y?[]:h?r=r||[]:n=n||[],i,h,d,v,y,h&&d?c:o)}return a(n),a(r),i}();return s||d(e),{e:m,get c(){var t=[];return s&&[d(applyDec(e,[n],r,e.name,5,t)),f.bind(null,t,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=n.length;function f(e,t,n,r){for(var o=0;o<e.length;o++)r=e[o].apply(n,t?[r]:[]);return t?r:n}function p(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,d,m,h,v){function y(e){if(!v(e))throw new TypeError("Attempted to access private element on non-instance")}var g=[].concat(t[0]),b=t[3],w=!u;function S(e,t){return function(n,r){return t&&t(n),j[e].call(n,r)}}if(!w){var j={},D=[],I=3===o?"get":4===o||h?"set":"value";d?(m||h?j={get:setFunctionName((function(){return b(this)}),r,"get"),set:function(e){t[4](this,e)}}:j[I]=b,m||setFunctionName(j[I],r,2===o?"":I)):m||(j=Object.getOwnPropertyDescriptor(e,r))}for(var P=e,k=g.length-1;k>=0;k-=n?2:1){var E=g[k],F=n?g[k-1]:void 0,N={},O={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");p(t,"An initializer","be",!0),i.push(t)}.bind(null,N)};if(w)c=E.call(F,P,O),N.v=1,p(c,"class decorators","return")&&(P=c);else{var z,H;O.static=l,O.private=d,d?2===o?z=function(e){return y(e),j.value}:(o<4&&(z=S("get",y)),3!==o&&(H=S("set",y))):(z=function(e){return e[r]},(o<2||4===o)&&(H=function(e,t){e[r]=t}));var K=O.access={has:d?v.bind():function(e){return r in e}};if(z&&(K.get=z),H&&(K.set=H),P=E.call(F,h?{get:j.get,set:j.set}:j[I],O),N.v=1,h){if("object"==typeof P&&P)(c=p(P.get,"accessor.get"))&&(j.get=c),(c=p(P.set,"accessor.set"))&&(j.set=c),(c=p(P.init,"accessor.init"))&&D.unshift(c);else if(void 0!==P)throw new TypeError("accessor decorators must return an object with get, set, or init properties or undefined")}else p(P,(m?"field":"method")+" decorators","return")&&(m?D.unshift(P):j[I]=P)}}return(m||h)&&u.push(f.bind(null,D,1),f.bind(null,i,0)),m||w||(d?h?u.splice(-1,0,S("get"),S("set")):u.push(2===o?j[I]:f.call.bind(j[I])):s(e,r,j)),P}function d(e){return s(e,u,{configurable:!0,enumerable:!0,value:a})}return void 0!==i&&(a=i[u]),a=Object.create(null==a?null:a),c=function(){var n,r,i=[];function a(e){e&&i.push(f.bind(null,e,0))}for(var c=0;c<t.length;c++){var u=t[c],s=u[1],l=u[2],p=!!u[3],d=16&s,m=!!(8&s),h=0==(s&=7),v=1===s;applyDec(m?e:e.prototype,u,d,p?"#"+l:toPropertyKey(l),s,h||v?[]:m?r=r||[]:n=n||[],i,m,p,h,v,m&&p?function(t){return checkInRHS(t)===e}:o)}return a(n),a(r),i}(),l||d(e),{e:c,get c(){var t=[];return l&&[d(applyDec(e,[n],r,e.name,5,t)),f.bind(null,t,0,e)]}}}',
),
// size: 544, gzip size: 300
asyncGeneratorDelegate: helper(
Expand Down
93 changes: 43 additions & 50 deletions packages/babel-helpers/src/helpers/applyDecs2311.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const enum PROP_KIND {
DECORATORS_HAVE_THIS = 16,
}

type DecoratorFinishedRef = { v?: boolean };
type DecoratorFinishedRef = { v?: number };
type DecoratorContextAccess = {
get?: (target: object) => any;
set?: (target: object, value: any) => void;
Expand Down Expand Up @@ -201,21 +201,18 @@ export default /* @no-mangle */ function applyDecs2311(
var defineProperty = Object.defineProperty;
var metadata: any;
var hasClassDecs = classDecs.length;
var _: any;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you leave a comment here that _ is an accumulator, which will be frequently reassigned and serve only as a temporary variable.


function _bindPropCall(obj: any, name: string, before?: Function) {
return function (_this: any, value?: any) {
if (before) {
before(_this);
}
return obj[name].call(_this, value);
};
}

function runInitializers(initializers: Function[], value: any) {
function runInitializers(
initializers: Function[],
hasValue: 0 | 1,
thisArg: any,
value?: any,
) {
for (var i = 0; i < initializers.length; i++) {
initializers[i].call(value);
value = initializers[i].apply(thisArg, hasValue ? [value] : []);
}
return value;
return hasValue ? value : thisArg;
}

function assertCallable(
Expand Down Expand Up @@ -263,9 +260,18 @@ export default /* @no-mangle */ function applyDecs2311(

var decs = [].concat(decInfo[0]),
decVal = decInfo[3],
_: any,
isClass = !ret;

function _bindPropCall(name: keyof PropertyDescriptor, before?: Function) {
return function (_this: any, value?: any) {
if (before) {
before(_this);
}
// eslint-disable-next-line @typescript-eslint/no-use-before-define
return desc[name].call(_this, value);
};
}

if (!isClass) {
var desc: PropertyDescriptor = {},
init: Function[] = [],
Expand Down Expand Up @@ -335,13 +341,10 @@ export default /* @no-mangle */ function applyDecs2311(
};

if (isClass) {
if (
(_ = assertCallable(
dec.call(decThis, newValue, ctx),
"class decorators",
"return",
))
) {
_ = dec.call(decThis, newValue, ctx);
decoratorFinishedRef.v = 1;

if (assertCallable(_, "class decorators", "return")) {
newValue = _;
}
} else {
Expand All @@ -365,10 +368,10 @@ export default /* @no-mangle */ function applyDecs2311(
};
} else {
if (kind < PROP_KIND.SETTER) {
get = _bindPropCall(desc, "get", assertInstanceIfPrivate);
get = _bindPropCall("get", assertInstanceIfPrivate);
}
if (kind !== PROP_KIND.GETTER) {
set = _bindPropCall(desc, "set", assertInstanceIfPrivate);
set = _bindPropCall("set", assertInstanceIfPrivate);
}
}

Expand All @@ -393,6 +396,7 @@ export default /* @no-mangle */ function applyDecs2311(
: desc[key],
ctx,
);
decoratorFinishedRef.v = 1;

if (isAccessor) {
if (typeof newValue === "object" && newValue) {
Expand All @@ -403,7 +407,7 @@ export default /* @no-mangle */ function applyDecs2311(
desc.set = _;
}
if ((_ = assertCallable(newValue.init, "accessor.init"))) {
init.push(_);
init.unshift(_);
}
} else if (newValue !== void 0) {
throw new TypeError(
Expand All @@ -418,49 +422,37 @@ export default /* @no-mangle */ function applyDecs2311(
)
) {
if (isField) {
init.push(newValue);
init.unshift(newValue);
} else {
desc[key] = newValue;
}
}
}

decoratorFinishedRef.v = true;
}

if (isField || isAccessor) {
ret.push(
// init
function (instance: any, value: any) {
for (var i = init.length - 1; i >= 0; i--) {
value = init[i].call(instance, value);
}
return value;
},
runInitializers.bind(null, init, 1),
// init_extra
runInitializers.bind(null, initializers),
runInitializers.bind(null, initializers, 0),
);
}

if (!isField && !isClass) {
if (isPrivate) {
if (isAccessor) {
// get and set should be returned before init_extra
ret.splice(
-1,
0,
_bindPropCall(desc, "get"),
_bindPropCall(desc, "set"),
);
ret.splice(-1, 0, _bindPropCall("get"), _bindPropCall("set"));
} else {
ret.push(
kind === PROP_KIND.METHOD
? desc[key]
: _bindPropCall.call.bind(desc[key]),
: runInitializers.call.bind(desc[key]),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
: runInitializers.call.bind(desc[key]),
: Function.call.bind(desc[key]),

Here it doesn't actually matter that we are using runInitializers, because we are replacing .call's function with desc[key] anyway. Let's just use Function.call.bind to avoid potential confusion.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will add some extra size, can we add some comments instead? :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure!

);
}
} else {
Object.defineProperty(Class, name, desc);
defineProperty(Class, name, desc);
}
}
return newValue;
Expand All @@ -471,13 +463,10 @@ export default /* @no-mangle */ function applyDecs2311(
var ret: Function[] = [];
var protoInitializers: Function[];
var staticInitializers: Function[];
var staticBrand = function (_: any) {
return checkInRHS(_) === targetClass;
};

function pushInitializers(initializers: Function[]) {
if (initializers) {
ret.push(runInitializers.bind(null, initializers));
ret.push(runInitializers.bind(null, initializers, 0));
}
}

Expand Down Expand Up @@ -512,7 +501,11 @@ export default /* @no-mangle */ function applyDecs2311(
isPrivate,
isField,
isAccessor,
isStatic && isPrivate ? staticBrand : instanceBrand,
isStatic && isPrivate
? function (_: any) {
return checkInRHS(_) === targetClass;
}
: instanceBrand,
);
}

Expand All @@ -533,10 +526,10 @@ export default /* @no-mangle */ function applyDecs2311(
metadata = parentClass[symbolMetadata];
}
metadata = Object.create(metadata == null ? null : metadata);
var e = applyMemberDecs();
_ = applyMemberDecs();
if (!hasClassDecs) defineMetadata(targetClass);
return {
e: e,
e: _,
// Lazily apply class decorations so that member init locals can be properly bound.
get c() {
// The transformer will not emit assignment when there are no class decorators,
Expand All @@ -554,7 +547,7 @@ export default /* @no-mangle */ function applyDecs2311(
initializers,
),
),
runInitializers.bind(null, initializers, targetClass),
runInitializers.bind(null, initializers, 0, targetClass),
]
);
},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
let addInitializer;

function decMethod(_, context) {
({ addInitializer } = context);
return null;
}

try {
class C {
@decMethod
m() {}
}
} catch(_) {}

expect(() => {
addInitializer(() => null);
}).toThrow('attempted to call addInitializer after decoration was finished');
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@ let addInitializer;

function decMethod(_, context) {
({ addInitializer } = context);
addInitializer(() => null);
throw new Error();
}

try {
class C {
@decMethod
m() {}
}
} finally {}
} catch(_) {}

expect(() => {
addInitializer(() => null);
}).toThrow('attempted to call addInitializer after decoration was finished')
}).not.toThrow();