Skip to content

Commit 87547ae

Browse files
rbucktonDanielRosenwasser
authored andcommitted
Reverse order of decorator-injected initializers (#54269)
1 parent fdd5cf2 commit 87547ae

11 files changed

+58
-28
lines changed

src/compiler/factory/emitHelpers.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -761,10 +761,10 @@ export const esDecorateHelper: UnscopedEmitHelper = {
761761
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
762762
if (_ = accept(result.get)) descriptor.get = _;
763763
if (_ = accept(result.set)) descriptor.set = _;
764-
if (_ = accept(result.init)) initializers.push(_);
764+
if (_ = accept(result.init)) initializers.unshift(_);
765765
}
766766
else if (_ = accept(result)) {
767-
if (kind === "field") initializers.push(_);
767+
if (kind === "field") initializers.unshift(_);
768768
else descriptor[key] = _;
769769
}
770770
}

src/testRunner/unittests/evaluation/esDecorators.ts

+40-10
Original file line numberDiff line numberDiff line change
@@ -1729,12 +1729,11 @@ describe("unittests:: evaluation:: esDecorators", () => {
17291729
`;
17301730
assert.strictEqual(C.x, 2);
17311731
});
1732-
it("multiple initializer pipe-throughs applied in reverse order", () => {
1732+
it("multiple initializer pipe-throughs applied in order", () => {
17331733
const { C } = exec`
1734-
function initializer(x) { return x + 1; }
17351734
export class C {
1736-
@((t, c) => x => [...x, 3])
17371735
@((t, c) => x => [...x, 2])
1736+
@((t, c) => x => [...x, 3])
17381737
static x: number[] = [1];
17391738
}
17401739
`;
@@ -1797,12 +1796,11 @@ describe("unittests:: evaluation:: esDecorators", () => {
17971796
`;
17981797
assert.strictEqual(C.x, 2);
17991798
});
1800-
it("multiple initializer pipe-throughs applied in reverse order", () => {
1799+
it("multiple init pipe-throughs applied in order", () => {
18011800
const { C } = exec`
1802-
function initializer(x) { return x + 1; }
18031801
export class C {
1804-
@((t, c) => ({ init: x => [...x, 3] }))
18051802
@((t, c) => ({ init: x => [...x, 2] }))
1803+
@((t, c) => ({ init: x => [...x, 3] }))
18061804
static accessor x: number[] = [1];
18071805
}
18081806
`;
@@ -1861,6 +1859,38 @@ describe("unittests:: evaluation:: esDecorators", () => {
18611859
assert.throws(() => main("abc"));
18621860
});
18631861
});
1862+
it("accessor 'init' evaluation order (#54267)", () => {
1863+
const { main } = exec`
1864+
function minusTwo({ set }: any, ctx: any) {
1865+
return {
1866+
set(v) { set.call(this, v - 2); },
1867+
init(v) { return v - 2; },
1868+
};
1869+
}
1870+
1871+
function timesFour({ set }: any, ctx: any) {
1872+
return {
1873+
set(v) { set.call(this, v * 4); },
1874+
init(v) { return v * 4; }
1875+
};
1876+
}
1877+
1878+
class C {
1879+
@minusTwo @timesFour accessor x = 5;
1880+
}
1881+
1882+
export const main = () => {
1883+
const obj = new C();
1884+
const afterInit = obj.x;
1885+
obj.x = 5;
1886+
const afterSet = obj.x;
1887+
return { afterInit, afterSet };
1888+
};
1889+
`;
1890+
const { afterInit, afterSet } = main();
1891+
assert.strictEqual(afterInit, 12);
1892+
assert.strictEqual(afterSet, 12);
1893+
});
18641894
});
18651895

18661896
const nodeVersion = new ts.Version(process.versions.node);
@@ -2162,11 +2192,11 @@ describe("unittests:: evaluation:: esDecorators", () => {
21622192
// order and applied to the replacement class:
21632193
"static block evaluation",
21642194
"static field initializer evaluation",
2165-
"static field injected initializer evaluation 2",
21662195
"static field injected initializer evaluation 1",
2196+
"static field injected initializer evaluation 2",
21672197
"static auto-accessor initializer evaluation",
2168-
"static auto-accessor injected initializer evaluation 2",
21692198
"static auto-accessor injected initializer evaluation 1",
2199+
"static auto-accessor injected initializer evaluation 2",
21702200
// NOTE: at this point, static private fields will be installed (TODO: on the replacement class)
21712201

21722202
// finally, class extra initializers are applied in the order they were added (i.e., methods before fields,
@@ -2208,11 +2238,11 @@ describe("unittests:: evaluation:: esDecorators", () => {
22082238
// next, instance initializers (i.e., fields, auto-accessors, and static blocks) are evaluated in document
22092239
// order:
22102240
"instance field initializer evaluation",
2211-
"instance field injected initializer evaluation 2",
22122241
"instance field injected initializer evaluation 1",
2242+
"instance field injected initializer evaluation 2",
22132243
"instance auto-accessor initializer evaluation",
2214-
"instance auto-accessor injected initializer evaluation 2",
22152244
"instance auto-accessor injected initializer evaluation 1",
2245+
"instance auto-accessor injected initializer evaluation 2",
22162246
// NOTE: at this point, instance private fields will be installed.
22172247

22182248
// finally, statements in the constructor after the call to `super()` are evaluated:

tests/baselines/reference/esDecorators-classDeclaration-commonjs-classNamespaceMerge.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn,
3131
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
3232
if (_ = accept(result.get)) descriptor.get = _;
3333
if (_ = accept(result.set)) descriptor.set = _;
34-
if (_ = accept(result.init)) initializers.push(_);
34+
if (_ = accept(result.init)) initializers.unshift(_);
3535
}
3636
else if (_ = accept(result)) {
37-
if (kind === "field") initializers.push(_);
37+
if (kind === "field") initializers.unshift(_);
3838
else descriptor[key] = _;
3939
}
4040
}

tests/baselines/reference/esDecorators-classDeclaration-commonjs.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn,
2727
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
2828
if (_ = accept(result.get)) descriptor.get = _;
2929
if (_ = accept(result.set)) descriptor.set = _;
30-
if (_ = accept(result.init)) initializers.push(_);
30+
if (_ = accept(result.init)) initializers.unshift(_);
3131
}
3232
else if (_ = accept(result)) {
33-
if (kind === "field") initializers.push(_);
33+
if (kind === "field") initializers.unshift(_);
3434
else descriptor[key] = _;
3535
}
3636
}

tests/baselines/reference/esDecorators-classDeclaration-sourceMap(target=es2015).js

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/baselines/reference/esDecorators-classDeclaration-sourceMap(target=es2015).js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/baselines/reference/esDecorators-classDeclaration-sourceMap(target=es2015).sourcemap.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@ sourceFile:esDecorators-classDeclaration-sourceMap.ts
2525
>>> if (result === null || typeof result !== "object") throw new TypeError("Object expected");
2626
>>> if (_ = accept(result.get)) descriptor.get = _;
2727
>>> if (_ = accept(result.set)) descriptor.set = _;
28-
>>> if (_ = accept(result.init)) initializers.push(_);
28+
>>> if (_ = accept(result.init)) initializers.unshift(_);
2929
>>> }
3030
>>> else if (_ = accept(result)) {
31-
>>> if (kind === "field") initializers.push(_);
31+
>>> if (kind === "field") initializers.unshift(_);
3232
>>> else descriptor[key] = _;
3333
>>> }
3434
>>> }

tests/baselines/reference/esDecorators-classDeclaration-sourceMap(target=es2022).js

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/baselines/reference/esDecorators-classDeclaration-sourceMap(target=es2022).js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/baselines/reference/esDecorators-classDeclaration-sourceMap(target=es2022).sourcemap.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@ sourceFile:esDecorators-classDeclaration-sourceMap.ts
2525
>>> if (result === null || typeof result !== "object") throw new TypeError("Object expected");
2626
>>> if (_ = accept(result.get)) descriptor.get = _;
2727
>>> if (_ = accept(result.set)) descriptor.set = _;
28-
>>> if (_ = accept(result.init)) initializers.push(_);
28+
>>> if (_ = accept(result.init)) initializers.unshift(_);
2929
>>> }
3030
>>> else if (_ = accept(result)) {
31-
>>> if (kind === "field") initializers.push(_);
31+
>>> if (kind === "field") initializers.unshift(_);
3232
>>> else descriptor[key] = _;
3333
>>> }
3434
>>> }

tests/baselines/reference/tscWatch/programUpdates/updates-diagnostics-and-emit-for-decorators.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,10 @@ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn,
9696
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
9797
if (_ = accept(result.get)) descriptor.get = _;
9898
if (_ = accept(result.set)) descriptor.set = _;
99-
if (_ = accept(result.init)) initializers.push(_);
99+
if (_ = accept(result.init)) initializers.unshift(_);
100100
}
101101
else if (_ = accept(result)) {
102-
if (kind === "field") initializers.push(_);
102+
if (kind === "field") initializers.unshift(_);
103103
else descriptor[key] = _;
104104
}
105105
}

0 commit comments

Comments
 (0)