Skip to content

Commit 7316f93

Browse files
Update decorators to match latest spec (#14353)
Co-authored-by: Nicolò Ribaudo <nicolo.ribaudo@gmail.com>
1 parent 338d7f1 commit 7316f93

File tree

28 files changed

+423
-203
lines changed

28 files changed

+423
-203
lines changed

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

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

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

Lines changed: 129 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,16 @@
1818
CLASS = 10; // only used in assertValidReturnValue
1919
*/
2020

21-
function createMetadataMethodsForProperty(metadataMap, kind, property) {
21+
function createMetadataMethodsForProperty(
22+
metadataMap,
23+
kind,
24+
property,
25+
decoratorFinishedRef
26+
) {
2227
return {
2328
getMetadata: function (key) {
24-
if (typeof key !== "symbol") {
25-
throw new TypeError("Metadata keys must be symbols, received: " + key);
26-
}
29+
assertNotFinished(decoratorFinishedRef, "getMetadata");
30+
assertMetadataKey(key);
2731

2832
var metadataForKey = metadataMap[key];
2933

@@ -44,9 +48,8 @@ function createMetadataMethodsForProperty(metadataMap, kind, property) {
4448
}
4549
},
4650
setMetadata: function (key, value) {
47-
if (typeof key !== "symbol") {
48-
throw new TypeError("Metadata keys must be symbols, received: " + key);
49-
}
51+
assertNotFinished(decoratorFinishedRef, "setMetadata");
52+
assertMetadataKey(key);
5053

5154
var metadataForKey = metadataMap[key];
5255

@@ -120,21 +123,24 @@ function convertMetadataMapToFinal(obj, metadataMap) {
120123
obj[Symbol.metadata || Symbol.for("Symbol.metadata")] = metadataMap;
121124
}
122125

123-
function createAddInitializerMethod(initializers) {
126+
function createAddInitializerMethod(initializers, decoratorFinishedRef) {
124127
return function addInitializer(initializer) {
128+
assertNotFinished(decoratorFinishedRef, "addInitializer");
125129
assertCallable(initializer, "An initializer");
126130
initializers.push(initializer);
127131
};
128132
}
129133

130-
function memberDecCtx(
134+
function memberDec(
135+
dec,
131136
name,
132137
desc,
133138
metadataMap,
134139
initializers,
135140
kind,
136141
isStatic,
137-
isPrivate
142+
isPrivate,
143+
value
138144
) {
139145
var kindStr;
140146

@@ -162,8 +168,13 @@ function memberDecCtx(
162168
isPrivate: isPrivate,
163169
};
164170

171+
var decoratorFinishedRef = { v: false };
172+
165173
if (kind !== 0 /* FIELD */) {
166-
ctx.addInitializer = createAddInitializerMethod(initializers);
174+
ctx.addInitializer = createAddInitializerMethod(
175+
initializers,
176+
decoratorFinishedRef
177+
);
167178
}
168179

169180
var metadataKind, metadataName;
@@ -202,10 +213,36 @@ function memberDecCtx(
202213
metadataName = name;
203214
}
204215

205-
return Object.assign(
206-
ctx,
207-
createMetadataMethodsForProperty(metadataMap, metadataKind, metadataName)
208-
);
216+
try {
217+
return dec(
218+
value,
219+
Object.assign(
220+
ctx,
221+
createMetadataMethodsForProperty(
222+
metadataMap,
223+
metadataKind,
224+
metadataName,
225+
decoratorFinishedRef
226+
)
227+
)
228+
);
229+
} finally {
230+
decoratorFinishedRef.v = true;
231+
}
232+
}
233+
234+
function assertNotFinished(decoratorFinishedRef, fnName) {
235+
if (decoratorFinishedRef.v) {
236+
throw new Error(
237+
"attempted to call " + fnName + " after decoration was finished"
238+
);
239+
}
240+
}
241+
242+
function assertMetadataKey(key) {
243+
if (typeof key !== "symbol") {
244+
throw new TypeError("Metadata keys must be symbols, received: " + key);
245+
}
209246
}
210247

211248
function assertCallable(fn, hint) {
@@ -220,7 +257,7 @@ function assertValidReturnValue(kind, value) {
220257
if (kind === 1 /* ACCESSOR */) {
221258
if (type !== "object" || value === null) {
222259
throw new TypeError(
223-
"accessor decorators must return an object with get, set, or initializer properties or void 0"
260+
"accessor decorators must return an object with get, set, or init properties or void 0"
224261
);
225262
}
226263
if (value.get !== undefined) {
@@ -229,8 +266,11 @@ function assertValidReturnValue(kind, value) {
229266
if (value.set !== undefined) {
230267
assertCallable(value.set, "accessor.set");
231268
}
232-
if (value.initialize !== undefined) {
233-
assertCallable(value.initialize, "accessor.initialize");
269+
if (value.init !== undefined) {
270+
assertCallable(value.init, "accessor.init");
271+
}
272+
if (value.initializer !== undefined) {
273+
assertCallable(value.initializer, "accessor.initializer");
234274
}
235275
} else if (type !== "function") {
236276
var hint;
@@ -245,6 +285,18 @@ function assertValidReturnValue(kind, value) {
245285
}
246286
}
247287

288+
function getInit(desc) {
289+
var initializer;
290+
if (
291+
(initializer = desc.init) == null &&
292+
(initializer = desc.initializer) &&
293+
typeof console !== "undefined"
294+
) {
295+
console.warn(".initializer has been renamed to .init as of March 2022");
296+
}
297+
return initializer;
298+
}
299+
248300
function applyMemberDec(
249301
ret,
250302
base,
@@ -296,29 +348,28 @@ function applyMemberDec(
296348
value = desc.set;
297349
}
298350

299-
var ctx = memberDecCtx(
300-
name,
301-
desc,
302-
metadataMap,
303-
initializers,
304-
kind,
305-
isStatic,
306-
isPrivate
307-
);
308-
309351
var newValue, get, set;
310352

311353
if (typeof decs === "function") {
312-
newValue = decs(value, ctx);
354+
newValue = memberDec(
355+
decs,
356+
name,
357+
desc,
358+
metadataMap,
359+
initializers,
360+
kind,
361+
isStatic,
362+
isPrivate,
363+
value
364+
);
313365

314366
if (newValue !== void 0) {
315367
assertValidReturnValue(kind, newValue);
316368

317369
if (kind === 0 /* FIELD */) {
318370
initializer = newValue;
319371
} else if (kind === 1 /* ACCESSOR */) {
320-
initializer = newValue.initialize;
321-
372+
initializer = getInit(newValue);
322373
get = newValue.get || value.get;
323374
set = newValue.set || value.set;
324375

@@ -331,7 +382,17 @@ function applyMemberDec(
331382
for (var i = decs.length - 1; i >= 0; i--) {
332383
var dec = decs[i];
333384

334-
newValue = dec(value, ctx);
385+
newValue = memberDec(
386+
dec,
387+
name,
388+
desc,
389+
metadataMap,
390+
initializers,
391+
kind,
392+
isStatic,
393+
isPrivate,
394+
value
395+
);
335396

336397
if (newValue !== void 0) {
337398
assertValidReturnValue(kind, newValue);
@@ -340,8 +401,7 @@ function applyMemberDec(
340401
if (kind === 0 /* FIELD */) {
341402
newInit = newValue;
342403
} else if (kind === 1 /* ACCESSOR */) {
343-
newInit = newValue.initialize;
344-
404+
newInit = getInit(newValue);
345405
get = newValue.get || value.get;
346406
set = newValue.set || value.set;
347407

@@ -514,59 +574,57 @@ function applyMemberDecs(
514574

515575
function pushInitializers(ret, initializers) {
516576
if (initializers) {
517-
if (initializers.length > 0) {
518-
// Slice the array, which means that `addInitializer` can no longer add
519-
// additional initializers to the array
520-
initializers = initializers.slice();
521-
522-
ret.push(function (instance) {
523-
for (var i = 0; i < initializers.length; i++) {
524-
initializers[i].call(instance);
525-
}
526-
return instance;
527-
});
528-
} else {
529-
ret.push(function (instance) {
530-
return instance;
531-
});
532-
}
577+
ret.push(function (instance) {
578+
for (var i = 0; i < initializers.length; i++) {
579+
initializers[i].call(instance);
580+
}
581+
return instance;
582+
});
533583
}
534584
}
535585

536586
function applyClassDecs(ret, targetClass, metadataMap, classDecs) {
537587
if (classDecs.length > 0) {
538588
var initializers = [];
539589
var newClass = targetClass;
540-
541590
var name = targetClass.name;
542-
var ctx = Object.assign(
543-
{
544-
kind: "class",
545-
name: name,
546-
addInitializer: createAddInitializerMethod(initializers),
547-
},
548-
createMetadataMethodsForProperty(metadataMap, 0 /* CONSTRUCTOR */, name)
549-
);
550591

551592
for (var i = classDecs.length - 1; i >= 0; i--) {
552-
var nextNewClass = classDecs[i](newClass, ctx);
593+
var decoratorFinishedRef = { v: false };
594+
595+
try {
596+
var ctx = Object.assign(
597+
{
598+
kind: "class",
599+
name: name,
600+
addInitializer: createAddInitializerMethod(
601+
initializers,
602+
decoratorFinishedRef
603+
),
604+
},
605+
createMetadataMethodsForProperty(
606+
metadataMap,
607+
0 /* CONSTRUCTOR */,
608+
name,
609+
decoratorFinishedRef
610+
)
611+
);
612+
var nextNewClass = classDecs[i](newClass, ctx);
613+
} finally {
614+
decoratorFinishedRef.v = true;
615+
}
616+
553617
if (nextNewClass !== undefined) {
554618
assertValidReturnValue(10 /* CLASS */, nextNewClass);
555619
newClass = nextNewClass;
556620
}
557621
}
558622

559-
ret.push(newClass);
560-
561-
if (initializers.length > 0) {
562-
ret.push(function () {
563-
for (var i = 0; i < initializers.length; i++) {
564-
initializers[i].call(newClass);
565-
}
566-
});
567-
} else {
568-
ret.push(function () {});
569-
}
623+
ret.push(newClass, function () {
624+
for (var i = 0; i < initializers.length; i++) {
625+
initializers[i].call(newClass);
626+
}
627+
});
570628
}
571629
}
572630

packages/babel-plugin-proposal-decorators/src/transformer-2021-12.ts

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -311,11 +311,28 @@ function isDecoratorInfo(
311311
return "decorators" in info;
312312
}
313313

314+
function filteredOrderedDecoratorInfo(
315+
info: (DecoratorInfo | ComputedPropInfo)[],
316+
): DecoratorInfo[] {
317+
const filtered = info.filter(isDecoratorInfo);
318+
319+
return [
320+
...filtered.filter(
321+
el => el.isStatic && el.kind >= ACCESSOR && el.kind <= SETTER,
322+
),
323+
...filtered.filter(
324+
el => !el.isStatic && el.kind >= ACCESSOR && el.kind <= SETTER,
325+
),
326+
...filtered.filter(el => el.isStatic && el.kind === FIELD),
327+
...filtered.filter(el => !el.isStatic && el.kind === FIELD),
328+
];
329+
}
330+
314331
function generateDecorationExprs(
315332
info: (DecoratorInfo | ComputedPropInfo)[],
316333
): t.ArrayExpression {
317334
return t.arrayExpression(
318-
info.filter(isDecoratorInfo).map(el => {
335+
filteredOrderedDecoratorInfo(info).map(el => {
319336
const decs =
320337
el.decorators.length > 1
321338
? t.arrayExpression(el.decorators)
@@ -341,19 +358,19 @@ function generateDecorationExprs(
341358
function extractElementLocalAssignments(
342359
decorationInfo: (DecoratorInfo | ComputedPropInfo)[],
343360
) {
344-
const locals: t.Identifier[] = [];
361+
const localIds: t.Identifier[] = [];
345362

346-
for (const el of decorationInfo) {
347-
if ("locals" in el && el.locals) {
348-
if (Array.isArray(el.locals)) {
349-
locals.push(...el.locals);
350-
} else {
351-
locals.push(el.locals);
352-
}
363+
for (const el of filteredOrderedDecoratorInfo(decorationInfo)) {
364+
const { locals } = el;
365+
366+
if (Array.isArray(locals)) {
367+
localIds.push(...locals);
368+
} else if (locals !== undefined) {
369+
localIds.push(locals);
353370
}
354371
}
355372

356-
return locals;
373+
return localIds;
357374
}
358375

359376
function addCallAccessorsFor(

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ function dec({ get, set }, context) {
1212
set.call(this, v + 1);
1313
},
1414

15-
initialize(v) {
15+
init(v) {
1616
return v ? v : 1;
1717
}
1818
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy