Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 26 additions & 3 deletions crates/oxc_transformer/src/decorator/legacy/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -835,10 +835,26 @@ impl<'a> LegacyDecorator<'a, '_> {
}

let mut decorations = ctx.ast.vec_with_capacity(method_decoration_count);

// Split metadata decorators from method decorators.
// Metadata decorators (typically used for emitting design-time type information)
// are identified by having an "unspanned" span. According to TypeScript's legacy
// decorator semantics, metadata decorators must be applied *after* all parameter
// decorators, so we separate them here and will insert them last.
let mut method_decorators = method.decorators.take_in(ctx.ast.allocator);
let metadata_position = method_decorators
.iter()
.position(|decorator| {
// All metadata decorators are unspanned
decorator.span.is_unspanned()
})
.unwrap_or(method_decorators.len());
let metadata_decorators = method_decorators.split_off(metadata_position);

// Method decorators should always be injected before all other decorators
decorations.extend(
method
.decorators
.drain(..)
method_decorators
.into_iter()
.map(|decorator| ArrayExpressionElement::from(decorator.expression)),
);

Expand All @@ -847,6 +863,13 @@ impl<'a> LegacyDecorator<'a, '_> {
self.transform_decorators_of_parameters(&mut decorations, params, ctx);
}

// `decorateMetadata` should always be injected after param decorators
decorations.extend(
metadata_decorators
.into_iter()
.map(|decorator| ArrayExpressionElement::from(decorator.expression)),
);

Some(ctx.ast.expression_array(SPAN, decorations))
}

Expand Down
4 changes: 2 additions & 2 deletions napi/transform/test/transform.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -322,10 +322,10 @@ describe('legacy decorator', () => {
};
_decorate([dce, _decorateMetadata("design:type", Object)], C.prototype, "prop", void 0);
_decorate([
_decorateParam(0, dce),
_decorateMetadata("design:type", Function),
_decorateMetadata("design:paramtypes", [Object]),
_decorateMetadata("design:returntype", void 0),
_decorateParam(0, dce)
_decorateMetadata("design:returntype", void 0)
], C.prototype, "method", null);
C = _decorate([dce], C);
export default C;
Expand Down
16 changes: 8 additions & 8 deletions tasks/coverage/snapshots/semantic_misc.snap
Original file line number Diff line number Diff line change
Expand Up @@ -73,28 +73,28 @@ after transform: SymbolId(1): [ReferenceId(109), ReferenceId(117), ReferenceId(1
rebuilt : SymbolId(1): [ReferenceId(212), ReferenceId(214), ReferenceId(216), ReferenceId(218)]
Symbol reference IDs mismatch for "IEditorService":
after transform: SymbolId(2): [ReferenceId(23), ReferenceId(24), ReferenceId(67), ReferenceId(184), ReferenceId(370), ReferenceId(371)]
rebuilt : SymbolId(2): [ReferenceId(57), ReferenceId(58), ReferenceId(79), ReferenceId(111), ReferenceId(239)]
rebuilt : SymbolId(2): [ReferenceId(38), ReferenceId(73), ReferenceId(74), ReferenceId(111), ReferenceId(239)]
Symbol reference IDs mismatch for "IEditorGroupsService":
after transform: SymbolId(4): [ReferenceId(25), ReferenceId(26), ReferenceId(57), ReferenceId(176), ReferenceId(375), ReferenceId(376)]
rebuilt : SymbolId(3): [ReferenceId(62), ReferenceId(63), ReferenceId(81), ReferenceId(102), ReferenceId(232)]
rebuilt : SymbolId(3): [ReferenceId(40), ReferenceId(78), ReferenceId(79), ReferenceId(102), ReferenceId(232)]
Symbol reference IDs mismatch for "EditorService":
after transform: SymbolId(5): [ReferenceId(61), ReferenceId(64), ReferenceId(178), ReferenceId(181)]
rebuilt : SymbolId(4): [ReferenceId(108), ReferenceId(236)]
Symbol reference IDs mismatch for "IWorkingCopyBackupService":
after transform: SymbolId(7): [ReferenceId(11), ReferenceId(12), ReferenceId(51), ReferenceId(170), ReferenceId(340), ReferenceId(341)]
rebuilt : SymbolId(5): [ReferenceId(27), ReferenceId(28), ReferenceId(67), ReferenceId(96), ReferenceId(226)]
rebuilt : SymbolId(5): [ReferenceId(26), ReferenceId(43), ReferenceId(44), ReferenceId(96), ReferenceId(226)]
Symbol reference IDs mismatch for "IFilesConfigurationService":
after transform: SymbolId(10): [ReferenceId(13), ReferenceId(14), ReferenceId(345), ReferenceId(346)]
rebuilt : SymbolId(8): [ReferenceId(32), ReferenceId(33), ReferenceId(69)]
rebuilt : SymbolId(8): [ReferenceId(28), ReferenceId(48), ReferenceId(49)]
Symbol reference IDs mismatch for "IWorkingCopyService":
after transform: SymbolId(11): [ReferenceId(15), ReferenceId(16), ReferenceId(350), ReferenceId(351)]
rebuilt : SymbolId(9): [ReferenceId(37), ReferenceId(38), ReferenceId(71)]
rebuilt : SymbolId(9): [ReferenceId(30), ReferenceId(53), ReferenceId(54)]
Symbol reference IDs mismatch for "ILogService":
after transform: SymbolId(13): [ReferenceId(19), ReferenceId(20), ReferenceId(360), ReferenceId(361)]
rebuilt : SymbolId(10): [ReferenceId(47), ReferenceId(48), ReferenceId(75)]
rebuilt : SymbolId(10): [ReferenceId(34), ReferenceId(63), ReferenceId(64)]
Symbol reference IDs mismatch for "ILifecycleService":
after transform: SymbolId(14): [ReferenceId(17), ReferenceId(18), ReferenceId(355), ReferenceId(356)]
rebuilt : SymbolId(11): [ReferenceId(42), ReferenceId(43), ReferenceId(73)]
rebuilt : SymbolId(11): [ReferenceId(32), ReferenceId(58), ReferenceId(59)]
Symbol reference IDs mismatch for "UntitledTextEditorInput":
after transform: SymbolId(17): [ReferenceId(38), ReferenceId(87)]
rebuilt : SymbolId(13): [ReferenceId(83)]
Expand All @@ -106,7 +106,7 @@ after transform: SymbolId(21): [ReferenceId(1), ReferenceId(40), ReferenceId(71)
rebuilt : SymbolId(17): [ReferenceId(115), ReferenceId(243)]
Symbol reference IDs mismatch for "IWorkingCopyEditorService":
after transform: SymbolId(32): [ReferenceId(21), ReferenceId(22), ReferenceId(365), ReferenceId(366)]
rebuilt : SymbolId(26): [ReferenceId(52), ReferenceId(53), ReferenceId(77)]
rebuilt : SymbolId(26): [ReferenceId(36), ReferenceId(68), ReferenceId(69)]
Symbol span mismatch for "TestWorkingCopyBackupTracker":
after transform: SymbolId(39): Span { start: 3208, end: 3236 }
rebuilt : SymbolId(46): Span { start: 0, end: 0 }
Expand Down
4 changes: 2 additions & 2 deletions tasks/coverage/snapshots/semantic_typescript.snap
Original file line number Diff line number Diff line change
Expand Up @@ -8599,7 +8599,7 @@ rebuilt : [ReferenceId(13)]
semantic Error: tasks/coverage/typescript/tests/cases/compiler/decoratorMetadataElidedImport.ts
Symbol reference IDs mismatch for "Observable":
after transform: SymbolId(0): [ReferenceId(2), ReferenceId(8), ReferenceId(9)]
rebuilt : SymbolId(0): [ReferenceId(8), ReferenceId(9)]
rebuilt : SymbolId(0): [ReferenceId(12), ReferenceId(13)]

semantic Error: tasks/coverage/typescript/tests/cases/compiler/decoratorMetadataElidedImportOnDeclare.ts
Symbol reference IDs mismatch for "Observable":
Expand Down Expand Up @@ -8791,7 +8791,7 @@ rebuilt : ["Object", "database"]
semantic Error: tasks/coverage/typescript/tests/cases/compiler/decoratorReferenceOnOtherProperty.ts
Symbol reference IDs mismatch for "Yoha":
after transform: SymbolId(0): [ReferenceId(1), ReferenceId(5), ReferenceId(6)]
rebuilt : SymbolId(0): [ReferenceId(6), ReferenceId(7)]
rebuilt : SymbolId(0): [ReferenceId(8), ReferenceId(9)]

semantic Error: tasks/coverage/typescript/tests/cases/compiler/decoratorReferences.ts
Bindings mismatch:
Expand Down
49 changes: 42 additions & 7 deletions tasks/transform_conformance/snapshots/oxc.snap.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
commit: 98d18aa4

Passed: 183/303
Passed: 183/304

# All Passed:
* babel-plugin-transform-class-static-block
Expand Down Expand Up @@ -539,7 +539,7 @@ x Output mismatch
x Output mismatch


# legacy-decorators (6/79)
# legacy-decorators (6/80)
* oxc/metadata/abstract-class/input.ts
Symbol reference IDs mismatch for "Dependency":
after transform: SymbolId(1): [ReferenceId(1), ReferenceId(2), ReferenceId(3)]
Expand All @@ -554,7 +554,7 @@ rebuilt : SymbolId(4): Span { start: 69, end: 82 }
* oxc/metadata/bound-type-reference/input.ts
Symbol reference IDs mismatch for "BoundTypeReference":
after transform: SymbolId(0): [ReferenceId(1), ReferenceId(3), ReferenceId(4), ReferenceId(5), ReferenceId(6)]
rebuilt : SymbolId(0): [ReferenceId(1), ReferenceId(6), ReferenceId(7)]
rebuilt : SymbolId(0): [ReferenceId(1), ReferenceId(8), ReferenceId(9)]
Symbol span mismatch for "Example":
after transform: SymbolId(1): Span { start: 87, end: 94 }
rebuilt : SymbolId(2): Span { start: 0, end: 0 }
Expand All @@ -571,7 +571,7 @@ after transform: ScopeId(0): [ScopeId(1), ScopeId(2)]
rebuilt : ScopeId(0): [ScopeId(1)]
Symbol reference IDs mismatch for "Foo":
after transform: SymbolId(0): [ReferenceId(2), ReferenceId(3), ReferenceId(12), ReferenceId(13)]
rebuilt : SymbolId(0): [ReferenceId(9), ReferenceId(10)]
rebuilt : SymbolId(0): [ReferenceId(11), ReferenceId(12)]
Symbol span mismatch for "Cls":
after transform: SymbolId(7): Span { start: 145, end: 148 }
rebuilt : SymbolId(2): Span { start: 0, end: 0 }
Expand All @@ -585,6 +585,41 @@ Unresolved references mismatch:
after transform: ["Object", "PropertyDescriptor", "babelHelpers", "console"]
rebuilt : ["Object", "babelHelpers", "console", "dec"]

* oxc/metadata/params/input.ts
Bindings mismatch:
after transform: ScopeId(0): ["Foo", "methodDecorator", "paramDecorator"]
rebuilt : ScopeId(0): ["Foo"]
Scope children mismatch:
after transform: ScopeId(0): [ScopeId(1), ScopeId(2), ScopeId(3)]
rebuilt : ScopeId(0): [ScopeId(1)]
Reference symbol mismatch for "methodDecorator":
after transform: SymbolId(0) "methodDecorator"
rebuilt : <None>
Reference symbol mismatch for "methodDecorator":
after transform: SymbolId(0) "methodDecorator"
rebuilt : <None>
Reference symbol mismatch for "paramDecorator":
after transform: SymbolId(2) "paramDecorator"
rebuilt : <None>
Reference symbol mismatch for "methodDecorator":
after transform: SymbolId(0) "methodDecorator"
rebuilt : <None>
Reference symbol mismatch for "methodDecorator":
after transform: SymbolId(0) "methodDecorator"
rebuilt : <None>
Reference symbol mismatch for "paramDecorator":
after transform: SymbolId(2) "paramDecorator"
rebuilt : <None>
Reference symbol mismatch for "paramDecorator":
after transform: SymbolId(2) "paramDecorator"
rebuilt : <None>
Reference symbol mismatch for "paramDecorator":
after transform: SymbolId(2) "paramDecorator"
rebuilt : <None>
Unresolved references mismatch:
after transform: ["Boolean", "Function", "String", "babelHelpers"]
rebuilt : ["Boolean", "Function", "String", "babelHelpers", "methodDecorator", "paramDecorator"]

* oxc/metadata/this/input.ts
Symbol span mismatch for "Example":
after transform: SymbolId(0): Span { start: 6, end: 13 }
Expand Down Expand Up @@ -614,13 +649,13 @@ after transform: SymbolId(3): Span { start: 0, end: 0 }
rebuilt : SymbolId(2): Span { start: 6, end: 13 }
Reference flags mismatch for "UnboundTypeReference":
after transform: ReferenceId(2): ReferenceFlags(Read | Type)
rebuilt : ReferenceId(4): ReferenceFlags(Read)
rebuilt : ReferenceId(6): ReferenceFlags(Read)
Reference flags mismatch for "UnboundTypeReference":
after transform: ReferenceId(3): ReferenceFlags(Read | Type)
rebuilt : ReferenceId(5): ReferenceFlags(Read)
rebuilt : ReferenceId(7): ReferenceFlags(Read)
Unresolved reference IDs mismatch for "UnboundTypeReference":
after transform: [ReferenceId(1), ReferenceId(2), ReferenceId(3)]
rebuilt : [ReferenceId(4), ReferenceId(5)]
rebuilt : [ReferenceId(6), ReferenceId(7)]

* oxc/metadata/without-decorator/input.ts
Symbol span mismatch for "C":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,20 @@ var _ref;
console.log(BoundTypeReference);

let Example = class Example {
constructor(count) { }
prop = 1;
constructor(count) {}
prop = 1;
};

Example = babelHelpers.decorate(
[
babelHelpers.decorateMetadata("design:paramtypes", [
typeof (_ref =
typeof BoundTypeReference !== "undefined" && BoundTypeReference) ===
"function"
? _ref
: Object,
]),
babelHelpers.decorateParam(0, dce),
],
Example,
[
babelHelpers.decorateParam(0, dce),
babelHelpers.decorateMetadata("design:paramtypes", [
typeof (_ref =
typeof BoundTypeReference !== "undefined" && BoundTypeReference) ===
"function"
? _ref
: Object,
]),
],
Example,
);
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ let Cls = class Cls {

Cls = babelHelpers.decorate(
[
babelHelpers.decorateParam(0, dec),
babelHelpers.decorateMetadata("design:paramtypes", [
typeof (_ref = typeof Foo !== "undefined" && Foo) === "function"
? _ref
Expand All @@ -17,7 +18,6 @@ Cls = babelHelpers.decorate(
Object,
Object,
]),
babelHelpers.decorateParam(0, dec),
],
Cls,
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
declare function methodDecorator(target: any);
declare function paramDecorator(target: any);

export class Foo {
@methodDecorator(1)
@methodDecorator(2)
method1(@paramDecorator param: string): boolean {
return !!param
}

@methodDecorator(1)
@methodDecorator(2)
method2(param: string): boolean {
return !!param
}

method3(@paramDecorator param: string): boolean {
return !!param
}

method4(@paramDecorator param: string, @paramDecorator param2: string): boolean {
return !!param
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
export class Foo {
method1(param) {
return !!param;
}
method2(param) {
return !!param;
}
method3(param) {
return !!param;
}
method4(param, param2) {
return !!param;
}
}

babelHelpers.decorate(
[
methodDecorator(1),
methodDecorator(2),
babelHelpers.decorateParam(0, paramDecorator),
babelHelpers.decorateMetadata("design:type", Function),
babelHelpers.decorateMetadata("design:paramtypes", [String]),
babelHelpers.decorateMetadata("design:returntype", Boolean),
],
Foo.prototype,
"method1",
null,
);

babelHelpers.decorate(
[
methodDecorator(1),
methodDecorator(2),
babelHelpers.decorateMetadata("design:type", Function),
babelHelpers.decorateMetadata("design:paramtypes", [String]),
babelHelpers.decorateMetadata("design:returntype", Boolean),
],
Foo.prototype,
"method2",
null,
);

babelHelpers.decorate(
[
babelHelpers.decorateParam(0, paramDecorator),
babelHelpers.decorateMetadata("design:type", Function),
babelHelpers.decorateMetadata("design:paramtypes", [String]),
babelHelpers.decorateMetadata("design:returntype", Boolean),
],
Foo.prototype,
"method3",
null,
);

babelHelpers.decorate(
[
babelHelpers.decorateParam(0, paramDecorator),
babelHelpers.decorateParam(1, paramDecorator),
babelHelpers.decorateMetadata("design:type", Function),
babelHelpers.decorateMetadata("design:paramtypes", [String, String]),
babelHelpers.decorateMetadata("design:returntype", Boolean),
],
Foo.prototype,
"method4",
null,
);
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
let Example = class Example {
constructor(a) {}
constructor(a) {}
};
Example = babelHelpers.decorate([babelHelpers.decorateMetadata("design:paramtypes", [Object]), babelHelpers.decorateParam(0, dce)], Example);
Example = babelHelpers.decorate(
[
babelHelpers.decorateParam(0, dce),
babelHelpers.decorateMetadata("design:paramtypes", [Object]),
],
Example,
);
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ let Example = class Example {

Example = babelHelpers.decorate(
[
babelHelpers.decorateParam(0, dce),
babelHelpers.decorateMetadata("design:paramtypes", [
typeof (_ref =
typeof UnboundTypeReference !== "undefined" && UnboundTypeReference) ===
"function"
? _ref
: Object,
]),
babelHelpers.decorateParam(0, dce),
],
Example,
);
Loading