refactor(compiler): add @nocollapse
annotation using a synthetic comment (#35932)
In Ivy, Angular decorators are compiled into static fields that are inserted into a class declaration in a TypeScript transform. When targeting Closure compiler such fields need to be annotated with `@nocollapse` to prevent them from being lifted from a static field into a variable, as that would prevent the Ivy runtime from being able to find the compiled definitions. Previously, there was a bug in TypeScript where synthetic comments added in a transform would not be emitted at all, so as a workaround a global regex-replace was done in the emit's `writeFile` callback that would add the `@nocollapse` annotation to all static Ivy definition fields. This approach is no longer possible when ngtsc is running as TypeScript plugin, as a plugin cannot control emit behavior. The workaround is no longer necessary, as synthetic comments are now properly emitted, likely as of https://github.com/microsoft/TypeScript/pull/22141 which has been released with TypeScript 2.8. This change is required for running ngtsc as TypeScript plugin in Bazel's `ts_library` rule, to move away from the custom `ngc_wrapped` approach. Resolves FW-1952 PR Close #35932
This commit is contained in:
@ -1,26 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {nocollapseHack} from '../../src/transformers/nocollapse_hack';
|
||||
|
||||
describe('@nocollapse hack', () => {
|
||||
it('should add @nocollapse to a basic class', () => {
|
||||
const decl = `Foo.ɵinj = define(...);`;
|
||||
expect(nocollapseHack(decl)).toEqual('/** @nocollapse */ ' + decl);
|
||||
});
|
||||
|
||||
it('should add nocollapse to an if (false) declaration of the kind generated by tsickle', () => {
|
||||
const decl = `
|
||||
if (false) {
|
||||
/** @type {?} */
|
||||
Foo.ɵinj;
|
||||
}
|
||||
`;
|
||||
expect(nocollapseHack(decl)).toContain('/** @nocollapse @type {?} */');
|
||||
});
|
||||
});
|
@ -33,7 +33,7 @@ describe('TypeScriptNodeEmitter', () => {
|
||||
beforeEach(() => {
|
||||
context = new MockAotContext('/', FILES);
|
||||
host = new MockCompilerHost(context);
|
||||
emitter = new TypeScriptNodeEmitter();
|
||||
emitter = new TypeScriptNodeEmitter(false);
|
||||
someVar = o.variable('someVar', null, null);
|
||||
});
|
||||
|
||||
|
@ -40,14 +40,16 @@ describe('r3_transform_spec', () => {
|
||||
});
|
||||
|
||||
it('should be able to modify multiple classes in the same module', () => {
|
||||
const result = emit(getAngularClassTransformerFactory([{
|
||||
fileName: someGenFileName,
|
||||
statements: [
|
||||
classMethod(new o.ReturnStatement(o.variable('v')), ['v'], 'someMethod', 'SomeClass'),
|
||||
classMethod(
|
||||
new o.ReturnStatement(o.variable('v')), ['v'], 'someOtherMethod', 'SomeOtherClass')
|
||||
]
|
||||
}]));
|
||||
const result = emit(getAngularClassTransformerFactory(
|
||||
[{
|
||||
fileName: someGenFileName,
|
||||
statements: [
|
||||
classMethod(new o.ReturnStatement(o.variable('v')), ['v'], 'someMethod', 'SomeClass'),
|
||||
classMethod(
|
||||
new o.ReturnStatement(o.variable('v')), ['v'], 'someOtherMethod', 'SomeOtherClass')
|
||||
]
|
||||
}],
|
||||
false));
|
||||
expect(result).toContain('static someMethod(v) { return v; }');
|
||||
expect(result).toContain('static someOtherMethod(v) { return v; }');
|
||||
});
|
||||
@ -94,7 +96,7 @@ describe('r3_transform_spec', () => {
|
||||
fileName: someGenFileName,
|
||||
statements: [classMethod(stmt, parameters, methodName, className)]
|
||||
};
|
||||
return emit(getAngularClassTransformerFactory([module]));
|
||||
return emit(getAngularClassTransformerFactory([module], false));
|
||||
}
|
||||
|
||||
function emitStaticField(
|
||||
@ -104,7 +106,7 @@ describe('r3_transform_spec', () => {
|
||||
fileName: someGenFileName,
|
||||
statements: [classField(initializer, fieldName, className)]
|
||||
};
|
||||
return emit(getAngularClassTransformerFactory([module]));
|
||||
return emit(getAngularClassTransformerFactory([module], false));
|
||||
}
|
||||
});
|
||||
|
||||
|
Reference in New Issue
Block a user