Skip to content

Commit

Permalink
build: produce metadata bundles for @angular modules (angular#14509)
Browse files Browse the repository at this point in the history
  • Loading branch information
chuckjaz authored and IgorMinar committed Feb 16, 2017
1 parent 3b89670 commit 724ca37
Show file tree
Hide file tree
Showing 35 changed files with 349 additions and 166 deletions.
1 change: 1 addition & 0 deletions integration/hello_world__closure/bundle.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ CLOSURE_ARGS=(
node_modules/zone.js/dist/zone.js
$(find -L vendor/rxjs -name *.js)
node_modules/@angular/{core,common,compiler,platform-browser}/index.js
node_modules/@angular/{core,common}/public_api.js
$(find node_modules/@angular/{core,common,compiler,platform-browser}/src -name *.js)
"built/src/*.js"
"--entry_point=./built/src/main"
Expand Down
12 changes: 6 additions & 6 deletions modules/@angular/animation/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
* found in the LICENSE file at https://angular.io/license
*/

/**
* @module
* @description
* Entry point for all public APIs of the animation package.
*/
export * from './src/animation';
// This file is not used to build this module. It is only used during editing
// by the TypeScript language serivce and during build for verifcation. `ngc`
// replaces this file with production index.ts when it rewrites private symbol
// names.

export * from './public_api';
14 changes: 14 additions & 0 deletions modules/@angular/animation/public_api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**
* @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
*/

/**
* @module
* @description
* Entry point for all public APIs of the animation package.
*/
export * from './src/animation';
6 changes: 4 additions & 2 deletions modules/@angular/animation/tsconfig-build.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,14 @@
"types": []
},
"files": [
"index.ts",
"public_api.ts",
"../../../node_modules/zone.js/dist/zone.js.d.ts",
"../../system.d.ts"
],
"angularCompilerOptions": {
"annotateForClosureCompiler": true,
"strictMetadataEmit": true
"strictMetadataEmit": true,
"bundleIndex": "index",
"importAs": "@angular/animation"
}
}
12 changes: 5 additions & 7 deletions modules/@angular/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,9 @@
* found in the LICENSE file at https://angular.io/license
*/

/**
* @module
* @description
* Entry point for all public APIs of the common package.
*/
export * from './src/common';
// This file is not used to build this module. It is only used during editing
// by the TypeScript language serivce and during build for verifcation. `ngc`
// replaces this file with production index.ts when it rewrites private symbol
// names.

// This file only reexports content of the `src` folder. Keep it that way.
export * from './public_api';
16 changes: 16 additions & 0 deletions modules/@angular/common/public_api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* @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
*/

/**
* @module
* @description
* Entry point for all public APIs of the common package.
*/
export * from './src/common';

// This file only reexports content of the `src` folder. Keep it that way.
2 changes: 1 addition & 1 deletion modules/@angular/common/src/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
*/
export * from './location/index';
export {NgLocaleLocalization, NgLocalization} from './localization';
export {CommonModule} from './common_module';
export {CommonModule, DeprecatedCommonModule} from './common_module';
export {NgClass, NgFor, NgForOf, NgIf, NgPlural, NgPluralCase, NgStyle, NgSwitch, NgSwitchCase, NgSwitchDefault, NgTemplateOutlet, NgComponentOutlet} from './directives/index';
export {AsyncPipe, DatePipe, I18nPluralPipe, I18nSelectPipe, JsonPipe, LowerCasePipe, CurrencyPipe, DecimalPipe, PercentPipe, SlicePipe, UpperCasePipe, TitleCasePipe} from './pipes/index';
export {VERSION} from './version';
4 changes: 3 additions & 1 deletion modules/@angular/common/src/common_module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ export class CommonModule {

/**
* A module to contain deprecated directives.
*
* @deprecated
*/
@NgModule({declarations: [COMMON_DEPRECATED_DIRECTIVES], exports: [COMMON_DEPRECATED_DIRECTIVES]})
export class CommonDeprecatedModule {
export class DeprecatedCommonModule {
}
6 changes: 4 additions & 2 deletions modules/@angular/common/tsconfig-build.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@
"types": []
},
"files": [
"index.ts",
"public_api.ts",
"../../../node_modules/zone.js/dist/zone.js.d.ts"
],
"angularCompilerOptions": {
"annotateForClosureCompiler": true,
"strictMetadataEmit": true
"strictMetadataEmit": true,
"bundleIndex": "index",
"importAs": "@angular/common"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@ function main() {

class AssertingHostContext extends NodeCompilerHostContext {
readFile(fileName: string): string {
if (/.*\/node_modules\/.*/.test(fileName) && !/.*ngsummary\.json$/.test(fileName)) {
// Only allow to read summaries from node_modules
if (/.*\/node_modules\/.*/.test(fileName) && !/.*ngsummary\.json$/.test(fileName) &&
!/package\.json$/.test(fileName)) {
// Only allow to read summaries and package.json files from node_modules
return null;
}
readFiles.push(path.relative(basePath, fileName));
Expand Down
2 changes: 1 addition & 1 deletion modules/@angular/compiler-cli/src/ngtools_impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {NgModule} from '@angular/core';

// We cannot depend directly to @angular/router.
type Route = any;
const ROUTER_MODULE_PATH = '@angular/router/src/router_config_loader';
const ROUTER_MODULE_PATH = '@angular/router';
const ROUTER_ROUTES_SYMBOL_NAME = 'ROUTES';


Expand Down
81 changes: 35 additions & 46 deletions modules/@angular/compiler/src/aot/static_reflector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,7 @@ import {syntaxError} from '../util';
import {StaticSymbol} from './static_symbol';
import {StaticSymbolResolver} from './static_symbol_resolver';

const ANGULAR_IMPORT_LOCATIONS = {
coreDecorators: '@angular/core/src/metadata',
diDecorators: '@angular/core/src/di/metadata',
diMetadata: '@angular/core/src/di/metadata',
diInjectionToken: '@angular/core/src/di/injection_token',
diOpaqueToken: '@angular/core/src/di/injection_token',
animationMetadata: '@angular/core/src/animation/metadata',
provider: '@angular/core/src/di/provider'
};
const ANGULAR_CORE = '@angular/core';

const HIDDEN_KEY = /^\$.*\$$/;

Expand Down Expand Up @@ -241,56 +233,53 @@ export class StaticReflector implements ReflectorReader {
}

private initializeConversionMap(): void {
const {coreDecorators, diDecorators, diMetadata, diInjectionToken,
diOpaqueToken, animationMetadata, provider} = ANGULAR_IMPORT_LOCATIONS;
this.injectionToken = this.findDeclaration(diInjectionToken, 'InjectionToken');
this.opaqueToken = this.findDeclaration(diInjectionToken, 'OpaqueToken');
this.injectionToken = this.findDeclaration(ANGULAR_CORE, 'InjectionToken');
this.opaqueToken = this.findDeclaration(ANGULAR_CORE, 'OpaqueToken');

this._registerDecoratorOrConstructor(this.findDeclaration(diDecorators, 'Host'), Host);
this._registerDecoratorOrConstructor(this.findDeclaration(ANGULAR_CORE, 'Host'), Host);
this._registerDecoratorOrConstructor(
this.findDeclaration(diDecorators, 'Injectable'), Injectable);
this._registerDecoratorOrConstructor(this.findDeclaration(diDecorators, 'Self'), Self);
this._registerDecoratorOrConstructor(this.findDeclaration(diDecorators, 'SkipSelf'), SkipSelf);
this._registerDecoratorOrConstructor(this.findDeclaration(diDecorators, 'Inject'), Inject);
this._registerDecoratorOrConstructor(this.findDeclaration(diDecorators, 'Optional'), Optional);
this.findDeclaration(ANGULAR_CORE, 'Injectable'), Injectable);
this._registerDecoratorOrConstructor(this.findDeclaration(ANGULAR_CORE, 'Self'), Self);
this._registerDecoratorOrConstructor(this.findDeclaration(ANGULAR_CORE, 'SkipSelf'), SkipSelf);
this._registerDecoratorOrConstructor(this.findDeclaration(ANGULAR_CORE, 'Inject'), Inject);
this._registerDecoratorOrConstructor(this.findDeclaration(ANGULAR_CORE, 'Optional'), Optional);
this._registerDecoratorOrConstructor(
this.findDeclaration(coreDecorators, 'Attribute'), Attribute);
this.findDeclaration(ANGULAR_CORE, 'Attribute'), Attribute);
this._registerDecoratorOrConstructor(
this.findDeclaration(coreDecorators, 'ContentChild'), ContentChild);
this.findDeclaration(ANGULAR_CORE, 'ContentChild'), ContentChild);
this._registerDecoratorOrConstructor(
this.findDeclaration(coreDecorators, 'ContentChildren'), ContentChildren);
this.findDeclaration(ANGULAR_CORE, 'ContentChildren'), ContentChildren);
this._registerDecoratorOrConstructor(
this.findDeclaration(coreDecorators, 'ViewChild'), ViewChild);
this.findDeclaration(ANGULAR_CORE, 'ViewChild'), ViewChild);
this._registerDecoratorOrConstructor(
this.findDeclaration(coreDecorators, 'ViewChildren'), ViewChildren);
this._registerDecoratorOrConstructor(this.findDeclaration(coreDecorators, 'Input'), Input);
this._registerDecoratorOrConstructor(this.findDeclaration(coreDecorators, 'Output'), Output);
this._registerDecoratorOrConstructor(this.findDeclaration(coreDecorators, 'Pipe'), Pipe);
this.findDeclaration(ANGULAR_CORE, 'ViewChildren'), ViewChildren);
this._registerDecoratorOrConstructor(this.findDeclaration(ANGULAR_CORE, 'Input'), Input);
this._registerDecoratorOrConstructor(this.findDeclaration(ANGULAR_CORE, 'Output'), Output);
this._registerDecoratorOrConstructor(this.findDeclaration(ANGULAR_CORE, 'Pipe'), Pipe);
this._registerDecoratorOrConstructor(
this.findDeclaration(coreDecorators, 'HostBinding'), HostBinding);
this.findDeclaration(ANGULAR_CORE, 'HostBinding'), HostBinding);
this._registerDecoratorOrConstructor(
this.findDeclaration(coreDecorators, 'HostListener'), HostListener);
this.findDeclaration(ANGULAR_CORE, 'HostListener'), HostListener);
this._registerDecoratorOrConstructor(
this.findDeclaration(coreDecorators, 'Directive'), Directive);
this.findDeclaration(ANGULAR_CORE, 'Directive'), Directive);
this._registerDecoratorOrConstructor(
this.findDeclaration(coreDecorators, 'Component'), Component);
this._registerDecoratorOrConstructor(
this.findDeclaration(coreDecorators, 'NgModule'), NgModule);
this.findDeclaration(ANGULAR_CORE, 'Component'), Component);
this._registerDecoratorOrConstructor(this.findDeclaration(ANGULAR_CORE, 'NgModule'), NgModule);

// Note: Some metadata classes can be used directly with Provider.deps.
this._registerDecoratorOrConstructor(this.findDeclaration(diMetadata, 'Host'), Host);
this._registerDecoratorOrConstructor(this.findDeclaration(diMetadata, 'Self'), Self);
this._registerDecoratorOrConstructor(this.findDeclaration(diMetadata, 'SkipSelf'), SkipSelf);
this._registerDecoratorOrConstructor(this.findDeclaration(diMetadata, 'Optional'), Optional);

this._registerFunction(this.findDeclaration(animationMetadata, 'trigger'), trigger);
this._registerFunction(this.findDeclaration(animationMetadata, 'state'), state);
this._registerFunction(this.findDeclaration(animationMetadata, 'transition'), transition);
this._registerFunction(this.findDeclaration(animationMetadata, 'style'), style);
this._registerFunction(this.findDeclaration(animationMetadata, 'animate'), animate);
this._registerFunction(this.findDeclaration(animationMetadata, 'keyframes'), keyframes);
this._registerFunction(this.findDeclaration(animationMetadata, 'sequence'), sequence);
this._registerFunction(this.findDeclaration(animationMetadata, 'group'), group);
this._registerDecoratorOrConstructor(this.findDeclaration(ANGULAR_CORE, 'Host'), Host);
this._registerDecoratorOrConstructor(this.findDeclaration(ANGULAR_CORE, 'Self'), Self);
this._registerDecoratorOrConstructor(this.findDeclaration(ANGULAR_CORE, 'SkipSelf'), SkipSelf);
this._registerDecoratorOrConstructor(this.findDeclaration(ANGULAR_CORE, 'Optional'), Optional);

this._registerFunction(this.findDeclaration(ANGULAR_CORE, 'trigger'), trigger);
this._registerFunction(this.findDeclaration(ANGULAR_CORE, 'state'), state);
this._registerFunction(this.findDeclaration(ANGULAR_CORE, 'transition'), transition);
this._registerFunction(this.findDeclaration(ANGULAR_CORE, 'style'), style);
this._registerFunction(this.findDeclaration(ANGULAR_CORE, 'animate'), animate);
this._registerFunction(this.findDeclaration(ANGULAR_CORE, 'keyframes'), keyframes);
this._registerFunction(this.findDeclaration(ANGULAR_CORE, 'sequence'), sequence);
this._registerFunction(this.findDeclaration(ANGULAR_CORE, 'group'), group);
}

/**
Expand Down
15 changes: 11 additions & 4 deletions modules/@angular/compiler/src/aot/static_symbol_resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,9 +202,16 @@ export class StaticSymbolResolver {
new Set<string>(Object.keys(metadata['metadata']).map(unescapeIdentifier));
Object.keys(metadata['metadata']).forEach((metadataKey) => {
const symbolMeta = metadata['metadata'][metadataKey];
resolvedSymbols.push(this.createResolvedSymbol(
this.getStaticSymbol(filePath, unescapeIdentifier(metadataKey)), topLevelSymbolNames,
symbolMeta));
const name = unescapeIdentifier(metadataKey);
const canonicalSymbol = this.getStaticSymbol(filePath, name);
if (metadata['importAs']) {
// Index bundle indexes should use the importAs module name instead of a reference
// to the .d.ts file directly.
const importSymbol = this.getStaticSymbol(metadata['importAs'], name);
this.recordImportAs(canonicalSymbol, importSymbol);
}
resolvedSymbols.push(
this.createResolvedSymbol(canonicalSymbol, topLevelSymbolNames, symbolMeta));
});
}

Expand Down Expand Up @@ -372,7 +379,7 @@ export class StaticSymbolResolver {
return this.host.moduleNameToFileName(module, containingFile);
} catch (e) {
console.error(`Could not resolve module '${module}' relative to file ${containingFile}`);
this.reportError(new e, null, containingFile);
this.reportError(e, null, containingFile);
}
}
}
Expand Down
62 changes: 56 additions & 6 deletions modules/@angular/compiler/test/aot/compiler_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,18 @@
import {AotCompiler, AotCompilerHost, createAotCompiler} from '@angular/compiler';
import {RenderComponentType} from '@angular/core';
import {async} from '@angular/core/testing';
import {MetadataBundler, MetadataCollector, ModuleMetadata, privateEntriesToIndex} from '@angular/tsc-wrapped';
import * as path from 'path';
import * as ts from 'typescript';

import {ReflectionCapabilities, reflector} from './private_import_core';
import {EmittingCompilerHost, MockAotCompilerHost, MockCompilerHost, MockData, settings} from './test_util';
import {EmittingCompilerHost, MockAotCompilerHost, MockCompilerHost, MockData, MockMetadataBundlerHost, settings} from './test_util';

const DTS = /\.d\.ts$/;

const minCoreIndex = `
export * from './src/application_module';
export * from './src/change_detection';
export * from './src/metadata';
export * from './src/di/metadata';
export * from './src/di/injector';
Expand All @@ -28,7 +31,7 @@ const minCoreIndex = `
export * from './src/codegen_private_exports';
`;

describe('compiler', () => {
describe('compiler (unbundled Angular)', () => {
let angularFiles: Map<string, string>;

beforeAll(() => {
Expand All @@ -55,17 +58,64 @@ describe('compiler', () => {
it('should compile',
async(() => compile(host, aotHost, expectNoDiagnostics).then(generatedFiles => {
expect(generatedFiles.find(f => /app\.component\.ngfactory\.ts/.test(f.genFileUrl)))
.not.toBeUndefined();
.toBeDefined();
expect(generatedFiles.find(f => /app\.module\.ngfactory\.ts/.test(f.genFileUrl)))
.not.toBeUndefined();
.toBeDefined();
})));

it('should compile using summaries',
async(() => summaryCompile(host, aotHost).then(generatedFiles => {
expect(generatedFiles.find(f => /app\.component\.ngfactory\.ts/.test(f.genFileUrl)))
.not.toBeUndefined();
.toBeDefined();
expect(generatedFiles.find(f => /app\.module\.ngfactory\.ts/.test(f.genFileUrl)))
.not.toBeUndefined();
.toBeDefined();
})));
});
});

describe('compiler (bundled Angular)', () => {
let angularFiles: Map<string, string>;

beforeAll(() => {
const emittingHost = new EmittingCompilerHost(['@angular/core/index'], {emitMetadata: false});

// Create the metadata bundled
const indexModule = emittingHost.effectiveName('@angular/core/index');
const bundler = new MetadataBundler(
indexModule, '@angular/core', new MockMetadataBundlerHost(emittingHost));
const bundle = bundler.getMetadataBundle();
const metadata = JSON.stringify(bundle.metadata, null, ' ');
const bundleIndexSource = privateEntriesToIndex('./index', bundle.privates);
emittingHost.override('@angular/core/bundle_index.ts', bundleIndexSource);
emittingHost.addWrittenFile(
'@angular/core/package.json', JSON.stringify({typings: 'bundle_index.d.ts'}));
emittingHost.addWrittenFile('@angular/core/bundle_index.metadata.json', metadata);

// Emit the sources
const bundleIndexName = emittingHost.effectiveName('@angular/core/bundle_index.ts');
const emittingProgram = ts.createProgram([bundleIndexName], settings, emittingHost);
emittingProgram.emit();
angularFiles = emittingHost.written;
});

describe('Quickstart', () => {
let host: MockCompilerHost;
let aotHost: MockAotCompilerHost;

beforeEach(() => {
host = new MockCompilerHost(QUICKSTART, FILES, angularFiles);
aotHost = new MockAotCompilerHost(host);
});

// Restore reflector since AoT compiler will update it with a new static reflector
afterEach(() => { reflector.updateCapabilities(new ReflectionCapabilities()); });

it('should compile',
async(() => compile(host, aotHost, expectNoDiagnostics).then(generatedFiles => {
expect(generatedFiles.find(f => /app\.component\.ngfactory\.ts/.test(f.genFileUrl)))
.toBeDefined();
expect(generatedFiles.find(f => /app\.module\.ngfactory\.ts/.test(f.genFileUrl)))
.toBeDefined();
})));
});
});
Expand Down
Loading

0 comments on commit 724ca37

Please sign in to comment.