Skip to content

Commit 94b9cdc

Browse files
committed
"From source" NgFactory compilation / unit tests (some Babel transpilation issues remain)
1 parent 28ed954 commit 94b9cdc

File tree

15 files changed

+100
-62
lines changed

15 files changed

+100
-62
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ source/**/*.ngfactory.ts
99
source/**/*.ngfactory.js
1010
source/**/*.ngsummary.json
1111
source/**/*.ngstyle.ts
12+
source/**/*.shim.ngstyle.ts
1213
source/**/*.shim.ts
13-
source/**/*.shim.jsq
14+
source/**/*.shim.js
1415
source/**/*.metadata.json
1516
source/**/*.js
1617
source/**/*.js.map
Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
11
import {NgModuleFactory} from '@angular/core';
22

33
import {ApplicationBase} from './application';
4-
import {CompilerException} from 'exception';
4+
import {Compiler} from '../compiler';
55
import {Project} from '../project';
66

77
export class ApplicationFromSource<V> extends ApplicationBase<V, any> {
88
constructor(public project: Project) {
99
super();
1010
}
1111

12-
protected getModuleFactory(): Promise<NgModuleFactory<any>> {
13-
throw new CompilerException('Not implemented');
12+
protected async getModuleFactory(): Promise<NgModuleFactory<any>> {
13+
const compiler = new Compiler(this.project);
14+
15+
return await compiler.compile();
1416
}
1517
}

source/application/builder/tests/application.ts renamed to source/application/builder/tests/from-module.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
trimDocument,
1010
} from 'test-fixtures';
1111

12-
describe('Application builder', () => {
12+
describe('ApplicationFromModule', () => {
1313
it('should require a template document in order to render', async (done) => {
1414
const application = new ApplicationFromModule(moduleFromComponent(BasicInlineComponent));
1515
try {
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import {ApplicationFromSource} from '../from-source';
2+
3+
import {templateDocument, getApplicationProject} from 'test-fixtures';
4+
5+
xdescribe('ApplicationFromSource', () => {
6+
it('can compile a project from source and load a NgFactory module', async (done) => {
7+
const application =
8+
new ApplicationFromSource(
9+
getApplicationProject(
10+
'test-fixtures/application-basic-inline',
11+
'BasicInlineApplication'));
12+
13+
application.templateDocument(templateDocument);
14+
15+
const snapshot = await application.render();
16+
17+
snapshot.subscribe(
18+
r => {
19+
expect(r.exceptions).not.toBeNull();
20+
expect(r.exceptions.length).toBe(0);
21+
expect(r.route).not.toBeNull();
22+
expect(r.route.path.length).toBe(0); // route: /
23+
expect(r.variant).toBeUndefined();
24+
expect(r.applicationState).toBeUndefined();
25+
const expr = /<application ng-version="([\d\.]+)"><div>Hello!<\/div><\/application>/;
26+
expect(expr.test(r.renderedDocument)).toBeTruthy();
27+
done();
28+
},
29+
exception => fail(exception));
30+
});
31+
});

source/application/compiler/compiler.ts

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
1-
import {
2-
NgModuleFactory,
3-
NgModule
4-
} from '@angular/core';
1+
import {NgModuleFactory} from '@angular/core';
52

63
import {
74
CompilerHost,
@@ -21,7 +18,6 @@ import {dirname} from 'path';
2118
import {CompileOptions, loadProjectOptions} from './options';
2219
import {CompilerException} from 'exception';
2320
import {Project} from '../project';
24-
import {Reflector} from 'platform';
2521
import {VirtualMachine} from './vm';
2622
import {diagnosticsToException} from './diagnostics';
2723
import {templateCompiler} from './template';
@@ -33,8 +29,11 @@ export class Compiler {
3329
constructor(private project: Project) {
3430
this.options = loadProjectOptions(project);
3531

36-
if (project.ngModule == null ||
37-
project.ngModule.length < 2) {
32+
const {rootModule} = project;
33+
34+
const none = (identifier: string) => identifier == null || identifier.length === 0;
35+
36+
if (rootModule == null || none(rootModule.source) || none(rootModule.symbol)) {
3837
throw new CompilerException('Compiler requires a module ID and an export name in ngModule');
3938
}
4039
}
@@ -44,23 +43,23 @@ export class Compiler {
4443
try {
4544
await this.compileToVm(vm);
4645

47-
const [moduleId, exported] = this.project.ngModule;
46+
const {source, symbol} = this.project.rootModule;
4847

49-
const requiredModule = vm.require(`${moduleId}.ngfactory`); // use the compiled template, not the jit version
48+
const requiredModule = vm.require(`${source}.ngfactory`); // use the compiled template, not the jit version
5049
if (requiredModule == null) {
51-
throw new CompilerException(`Attempted to require ${moduleId}.ngfactory but received a null or undefined object`);
50+
throw new CompilerException(`Attempted to load ${source}.ngfactory but received a null or undefined object`);
5251
}
5352

54-
const rootModule =
55-
!exported
56-
? requiredModule
57-
: requiredModule[exported];
53+
const factorySymbol =
54+
/NgFactory$/.test(symbol) === false
55+
? `${symbol}NgFactory`
56+
: `${symbol}`;
5857

59-
if (Reflector.decorated(rootModule, NgModule) === false) {
60-
throw new CompilerException(`Root module type ${rootModule.name} is not decorated with @NgModule`);
58+
if (requiredModule.hasOwnProperty(factorySymbol) === false) {
59+
throw new CompilerException(`Module ${source} does not export a ${factorySymbol} symbol`);
6160
}
6261

63-
return rootModule;
62+
return requiredModule[factorySymbol];
6463
}
6564
finally {
6665
vm.dispose();

source/application/compiler/tests/compiler.ts

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,15 @@
1-
import {dirname} from 'path';
2-
3-
import {filesystemSearchUpward} from 'test-fixtures';
1+
import {getApplicationProject} from 'test-fixtures';
42

53
import {Compiler} from '../compiler';
64

7-
describe('Compiler', () => {
8-
const createCompiler = () => {
9-
const tsconfig = filesystemSearchUpward(__dirname, 'tsconfig.json');
10-
11-
return new Compiler({
12-
basePath: dirname(tsconfig),
13-
ngModule: ['test-fixtures/application-basic-inline', 'BasicInlineApplication'],
14-
tsconfig,
15-
});
16-
};
5+
xdescribe('Compiler', () => {
6+
it('should be able to build a TypeScript application and produce in-memory artifacts', async () => {
7+
const compiler =
8+
new Compiler(
9+
getApplicationProject(
10+
'test-fixtures/application-basic-inline',
11+
'BasicInlineApplication'));
1712

18-
xit('should be able to build a TypeScript application and produce in-memory artifacts', async () => {
19-
const compiler = createCompiler();
2013
const module = await compiler.compile();
2114
expect(module).not.toBeNull();
2215
expect(typeof module).toBe('function');

source/application/compiler/vm/vm.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,13 +83,15 @@ const normalizeModuleId = (to: string, from?: string): string => {
8383
};
8484

8585
const baseRequire = (moduleId: string) => {
86+
console.log('base require', moduleId);
87+
8688
// For whatever reason, the unbundled JS code in the Angular npm module is compiled into
8789
// ES2015 code which cannot be run on most NodeJS versions. So for Angular, we transpile
8890
// using Babel from ES2015 -> ES5 so that we can get broadly-compatible code (like what
8991
// is in the umd bundles) which we can execute in our VM. Ideally, this hack would not
9092
// be necessary. Other libraries are just require()d normally without the transpilation
9193
// because they do not require it and it would be a performance drain.
92-
if (/^@angular\//.test(moduleId)) {
94+
if (/^\@angular\//.test(moduleId)) {
9395
return transpile(moduleId);
9496
}
9597
return require(moduleId);

source/application/project.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ export interface Project {
55
// path to the tsconfig.json file for this project
66
tsconfig: string;
77

8-
// path to the application root NgModule, and the name of that module
9-
ngModule: [string, string];
8+
// path to the application root NgModule file, and the name of that module
9+
rootModule: {
10+
source: string;
11+
symbol: string;
12+
}
1013
}

source/exception.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ export class Exception extends Error {
2424
export class ApplicationException extends Exception {}
2525
export class CompilerException extends Exception {}
2626
export class ModuleException extends Exception {}
27-
export class PathException extends Exception {}
2827
export class PlatformException extends Exception {}
2928
export class RendererException extends Exception {}
3029
export class ResourceException extends Exception {}

source/route/tests/renderable.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@ import {renderableRoutes} from 'index';
33
import {
44
BasicInlineComponent,
55
moduleFactoryFromComponent,
6-
documentTemplate
6+
templateDocument
77
} from 'test-fixtures';
88

99
describe('renderable routes', () => {
1010
it('should return a single route for an NgModule that does not use Router', async (done) => {
1111
const moduleFactory = await moduleFactoryFromComponent(BasicInlineComponent);
1212

13-
const routes = renderableRoutes(moduleFactory, documentTemplate);
13+
const routes = renderableRoutes(moduleFactory, templateDocument);
1414

1515
routes.then(result => {
1616
expect(result.length).toBe(1);

0 commit comments

Comments
 (0)