refactor(compiler): allow disabling external symbol factory reexports (#28594)
Currently external static symbols which are referenced by AOT compiler generated code, will be re-exported in the corresponding `.ngfactory` files. This way of handling the symbol resolution has been introduced in favor of avoding dynamically generated module dependencies. This behavior therefore avoids any strict dependency failures. Read more about a particular scenario here: https://github.com/angular/angular/issues/25644#issuecomment-458354439 Now with `ngtsc`, this behavior has changed since `ngtsc` just introduces these module dependencies in order to properly reference the external symbol from its original location (also eliminating the need for factories). Similarly we should provide a way to use the same behavior with `ngc` because the downside of using the re-exported symbol resolution is that user-code transformations (e.g. the `ngInjectableDef` metadata which is added to the user source code), can resolve external symbols to previous factory symbol re-exports. This is a critical issue because it means that the actual JIT code references factory files in order to access external symbols. This means that the generated output cannot shipped to NPM without shipping the referenced factory files. A specific example has been reported here: https://github.com/angular/angular/issues/25644#issue-353554070 PR Close #28594
This commit is contained in:

committed by
Miško Hevery

parent
2f73c554c9
commit
aa163bea93
@ -466,5 +466,58 @@ import {MockAotSummaryResolverHost, createMockOutputContext} from './summary_res
|
||||
expect(serialized.json).not.toContain('error');
|
||||
});
|
||||
});
|
||||
|
||||
describe('createExternalSymbolReexports disabled', () => {
|
||||
it('should use existing reexports for "importAs" for symbols of libraries', () => {
|
||||
init();
|
||||
const externalSerialized = serializeSummaries(
|
||||
'someFile.ts', createMockOutputContext(), summaryResolver, symbolResolver,
|
||||
[
|
||||
{symbol: symbolCache.get('/tmp/external.ts', 'value'), metadata: 'aValue'},
|
||||
{
|
||||
symbol: symbolCache.get('/tmp/external.ts', 'reexportValue'),
|
||||
metadata: symbolCache.get('/tmp/external.ts', 'value')
|
||||
},
|
||||
],
|
||||
[], false);
|
||||
expect(externalSerialized.exportAs).toEqual([]);
|
||||
init({
|
||||
'/tmp/external.ngsummary.json': externalSerialized.json,
|
||||
});
|
||||
const serialized = serializeSummaries(
|
||||
'someFile.ts', createMockOutputContext(), summaryResolver, symbolResolver, [{
|
||||
symbol: symbolCache.get('/tmp/test.ts', 'mainValue'),
|
||||
metadata: symbolCache.get('/tmp/external.d.ts', 'reexportValue'),
|
||||
}],
|
||||
[]);
|
||||
expect(serialized.exportAs).toEqual([]);
|
||||
const importAs =
|
||||
deserializeSummaries(symbolCache, summaryResolver, 'someFile.d.ts', serialized.json)
|
||||
.importAs;
|
||||
expect(importAs).toEqual([{
|
||||
symbol: symbolCache.get('/tmp/external.d.ts', 'value'),
|
||||
importAs: symbolCache.get('/tmp/test.d.ts', 'mainValue'),
|
||||
}]);
|
||||
});
|
||||
|
||||
it('should not create reexports in the ngfactory for external symbols', () => {
|
||||
init();
|
||||
const serialized = serializeSummaries(
|
||||
'someFile.ts', createMockOutputContext(), summaryResolver, symbolResolver, [{
|
||||
symbol: symbolCache.get('/tmp/test.ts', 'main'),
|
||||
metadata: [
|
||||
symbolCache.get('/tmp/external.d.ts', 'lib'),
|
||||
symbolCache.get('/tmp/external.d.ts', 'lib', ['someMember']),
|
||||
]
|
||||
}],
|
||||
[], false);
|
||||
expect(serialized.exportAs.length)
|
||||
.toBe(0, 'Expected no external symbols to be re-exported.');
|
||||
const deserialized =
|
||||
deserializeSummaries(symbolCache, summaryResolver, 'someFile.d.ts', serialized.json);
|
||||
expect(deserialized.importAs.length)
|
||||
.toBe(0, 'Expected no symbols that can be imported from a re-exported location');
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
Reference in New Issue
Block a user