Skip to content

Commit b636306

Browse files
authored
Decorators misc fixes (#14339)
* fix: ensure initializer is invoked without parameters * fix: assert class decorators return a callable or undefined * fix: accessor decorator returns { initialize?: (initialValue: unknown) => unknown }; * fix: assert accessor decorator returns callable get/set/initialize * add getter/setter test cases * add accessor-initializers ordering test * address review comments * remove unused param base * add leaked context addInitializer test
1 parent e597854 commit b636306

33 files changed

Lines changed: 243 additions & 61 deletions

File tree

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: 31 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
SETTER = 4;
1515
1616
STATIC = 5;
17+
18+
CLASS = 10; // only used in assertValidReturnValue
1719
*/
1820

1921
function createMetadataMethodsForProperty(metadataMap, kind, property) {
@@ -120,13 +122,12 @@ function convertMetadataMapToFinal(obj, metadataMap) {
120122

121123
function createAddInitializerMethod(initializers) {
122124
return function addInitializer(initializer) {
123-
assertValidInitializer(initializer);
125+
assertCallable(initializer, "An initializer");
124126
initializers.push(initializer);
125127
};
126128
}
127129

128130
function memberDecCtx(
129-
base,
130131
name,
131132
desc,
132133
metadataMap,
@@ -207,9 +208,9 @@ function memberDecCtx(
207208
);
208209
}
209210

210-
function assertValidInitializer(initializer) {
211-
if (typeof initializer !== "function") {
212-
throw new Error("initializers must be functions");
211+
function assertCallable(fn, hint) {
212+
if (typeof fn !== "function") {
213+
throw new TypeError(hint + " must be a function");
213214
}
214215
}
215216

@@ -218,18 +219,29 @@ function assertValidReturnValue(kind, value) {
218219

219220
if (kind === 1 /* ACCESSOR */) {
220221
if (type !== "object" || value === null) {
221-
throw new Error(
222+
throw new TypeError(
222223
"accessor decorators must return an object with get, set, or initializer properties or void 0"
223224
);
224225
}
226+
if (value.get !== undefined) {
227+
assertCallable(value.get, "accessor.get");
228+
}
229+
if (value.set !== undefined) {
230+
assertCallable(value.set, "accessor.set");
231+
}
232+
if (value.initialize !== undefined) {
233+
assertCallable(value.initialize, "accessor.initialize");
234+
}
225235
} else if (type !== "function") {
236+
var hint;
226237
if (kind === 0 /* FIELD */) {
227-
throw new Error(
228-
"field decorators must return a initializer function or void 0"
229-
);
238+
hint = "field";
239+
} else if (kind === 10 /* CLASS */) {
240+
hint = "class";
230241
} else {
231-
throw new Error("method decorators must return a function or void 0");
242+
hint = "method";
232243
}
244+
throw new TypeError(hint + " decorators must return a function or void 0");
233245
}
234246
}
235247

@@ -285,7 +297,6 @@ function applyMemberDec(
285297
}
286298

287299
var ctx = memberDecCtx(
288-
base,
289300
name,
290301
desc,
291302
metadataMap,
@@ -306,7 +317,7 @@ function applyMemberDec(
306317
if (kind === 0 /* FIELD */) {
307318
initializer = newValue;
308319
} else if (kind === 1 /* ACCESSOR */) {
309-
initializer = newValue.initializer;
320+
initializer = newValue.initialize;
310321

311322
get = newValue.get || value.get;
312323
set = newValue.set || value.set;
@@ -329,7 +340,7 @@ function applyMemberDec(
329340
if (kind === 0 /* FIELD */) {
330341
newInit = newValue;
331342
} else if (kind === 1 /* ACCESSOR */) {
332-
newInit = newValue.initializer;
343+
newInit = newValue.initialize;
333344

334345
get = newValue.get || value.get;
335346
set = newValue.set || value.set;
@@ -510,7 +521,7 @@ function pushInitializers(ret, initializers) {
510521

511522
ret.push(function (instance) {
512523
for (var i = 0; i < initializers.length; i++) {
513-
initializers[i].call(instance, instance);
524+
initializers[i].call(instance);
514525
}
515526
return instance;
516527
});
@@ -538,15 +549,19 @@ function applyClassDecs(ret, targetClass, metadataMap, classDecs) {
538549
);
539550

540551
for (var i = classDecs.length - 1; i >= 0; i--) {
541-
newClass = classDecs[i](newClass, ctx) || newClass;
552+
var nextNewClass = classDecs[i](newClass, ctx);
553+
if (nextNewClass !== undefined) {
554+
assertValidReturnValue(10 /* CLASS */, nextNewClass);
555+
newClass = nextNewClass;
556+
}
542557
}
543558

544559
ret.push(newClass);
545560

546561
if (initializers.length > 0) {
547562
ret.push(function () {
548563
for (var i = 0; i < initializers.length; i++) {
549-
initializers[i].call(newClass, newClass);
564+
initializers[i].call(newClass);
550565
}
551566
});
552567
} else {

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
function dec({ get, set }, context) {
2-
context.addInitializer((instance) => {
3-
instance[context.name + 'Context'] = context;
2+
context.addInitializer(function() {
3+
this[context.name + 'Context'] = context;
44
});
55

66
return {
@@ -12,7 +12,7 @@ function dec({ get, set }, context) {
1212
set.call(this, v + 1);
1313
},
1414

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

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
function dec({ get, set }, context) {
2-
context.addInitializer((instance) => {
3-
instance[context.name + 'Context'] = context;
2+
context.addInitializer(function() {
3+
this[context.name + 'Context'] = context;
44
});
55

66
return {
@@ -12,7 +12,7 @@ function dec({ get, set }, context) {
1212
set.call(this, v + 1);
1313
},
1414

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

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
function dec({ get, set }, context) {
2-
context.addInitializer((instance) => {
3-
instance[context.name + 'Context'] = context;
2+
context.addInitializer(function() {
3+
this[context.name + 'Context'] = context;
44
});
55

66
return {
@@ -12,7 +12,7 @@ function dec({ get, set }, context) {
1212
set.call(this, v + 1);
1313
},
1414

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

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
function dec({ get, set }, context) {
2-
context.addInitializer((instance) => {
3-
instance[context.name + 'Context'] = context;
2+
context.addInitializer(function() {
3+
this[context.name + 'Context'] = context;
44
});
55

66
return {
@@ -12,7 +12,7 @@ function dec({ get, set }, context) {
1212
set.call(this, v + 1);
1313
},
1414

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

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
function dec(get, context) {
2-
context.addInitializer((instance) => {
3-
instance[context.name + 'Context'] = context;
2+
context.addInitializer(function() {
3+
this[context.name + 'Context'] = context;
44
});
55

66
return function () {

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
function dec(get, context) {
2-
context.addInitializer((instance) => {
3-
instance[context.name + 'Context'] = context;
2+
context.addInitializer(function() {
3+
this[context.name + 'Context'] = context;
44
});
55

66
return function () {

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
function dec(get, context) {
2-
context.addInitializer((instance) => {
3-
instance[context.name + 'Context'] = context;
2+
context.addInitializer(function() {
3+
this[context.name + 'Context'] = context;
44
});
55

66
return function () {

packages/babel-plugin-proposal-decorators/test/fixtures/2021-12-getters--to-es2015/static-public/exec.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
function dec(get, context) {
2-
context.addInitializer((instance) => {
3-
instance[context.name + 'Context'] = context;
2+
context.addInitializer(function() {
3+
this[context.name + 'Context'] = context;
44
});
55

66
return function () {

0 commit comments

Comments
 (0)