Created
May 12, 2016 17:32
-
-
Save shuhei/7f80280733191d49c85a902b385af1ba to your computer and use it in GitHub Desktop.
Angular 2 Offline Compile
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// https://github.com/angular/angular/blob/master/modules/%40angular/compiler/test/offline_compiler_util.ts | |
// https://github.com/angular/angular/blob/master/modules/%40angular/compiler/test/offline_compiler_codegen_untyped.ts | |
/* eslint-env node */ | |
import {OutputEmitter} from '@angular/compiler/src/output/abstract_emitter'; | |
import {createOfflineCompileUrlResolver} from '@angular/compiler/src/url_resolver'; | |
// import {JavaScriptEmitter} from '@angular/compiler/src/output/js_emitter'; | |
import {JavaScriptEmitter} from './js_emitter'; | |
import { | |
CompileDirectiveMetadata, | |
CompileTypeMetadata, | |
CompileTemplateMetadata | |
} from '@angular/compiler/src/compile_metadata'; | |
import {ImportGenerator} from '@angular/compiler/src/output/path_util'; | |
import {Parser} from '@angular/compiler/src/expression_parser/parser'; | |
import {Lexer} from '@angular/compiler/src/expression_parser/lexer'; | |
import {HtmlParser} from '@angular/compiler/src/html_parser'; | |
import {TemplateParser} from '@angular/compiler/src/template_parser'; | |
import {MockXHR} from '@angular/compiler/testing/xhr_mock'; | |
import { | |
OfflineCompiler, | |
NormalizedComponentWithViewDirectives, | |
SourceModule | |
} from '@angular/compiler/src/offline_compiler'; | |
import {StyleCompiler} from '@angular/compiler/src/style_compiler'; | |
import {ViewCompiler} from '@angular/compiler/src/view_compiler/view_compiler'; | |
import {DirectiveNormalizer} from '@angular/compiler/src/directive_normalizer'; | |
import {MockSchemaRegistry} from '@angular/compiler/testing/schema_registry_mock'; | |
import {Console} from '@angular/compiler/core_private'; | |
import {CompilerConfig} from '@angular/compiler/src/config'; | |
class SimpleJsImportGenerator { | |
getImportPath(moduleUrlStr, importedUrlStr) { | |
// var moduleAssetUrl = ImportGenerator.parseAssetUrl(moduleUrlStr); | |
var importedAssetUrl = ImportGenerator.parseAssetUrl(importedUrlStr); | |
if (!!importedAssetUrl) { | |
return `${importedAssetUrl.packageName}/${importedAssetUrl.modulePath}`; | |
} else { | |
return importedUrlStr; | |
} | |
} | |
} | |
function _createOfflineCompiler(xhr, emitter) { | |
const urlResolver = createOfflineCompileUrlResolver(); | |
const htmlParser = new HtmlParser(); | |
const normalizer = new DirectiveNormalizer(xhr, urlResolver, htmlParser); | |
const tmplParser = new TemplateParser(new Parser(new Lexer()), new MockSchemaRegistry({}, {}), | |
htmlParser, new Console(), []); | |
const styleCompiler = new StyleCompiler(urlResolver); | |
const viewCompiler = new ViewCompiler(new CompilerConfig(true, true, true)); | |
return new OfflineCompiler(normalizer, tmplParser, styleCompiler, viewCompiler, emitter, xhr); | |
} | |
function compileComp(emitter, comp) { | |
const xhr = new MockXHR(); | |
const compiler = _createOfflineCompiler(xhr, emitter); | |
const result = compiler.normalizeDirectiveMetadata(comp) | |
.then(normComp => { | |
return compiler.compileTemplates([new NormalizedComponentWithViewDirectives(normComp, [], [])]) | |
.source; | |
}); | |
// xhr.flush(); | |
return result; | |
} | |
class CompA { | |
user: string; | |
} | |
const compAMetadata = CompileDirectiveMetadata.create({ | |
isComponent: true, | |
selector: 'comp-a', | |
type: new CompileTypeMetadata( | |
{name: 'CompA', moduleUrl: 'asset:foo/bar', runtime: CompA, diDeps: []}), | |
template: new CompileTemplateMetadata({ | |
template: 'Hello World {{user}}', | |
styles: ['.redStyle { color: red; }'] | |
}) | |
}); | |
function emit() { | |
// const emitter = new JavaScriptEmitter(new SimpleJsImportGenerator()); | |
const emitter = new JavaScriptEmitter(new SimpleJsImportGenerator()); | |
return compileComp(emitter, compAMetadata); | |
} | |
emit() | |
.then(source => console.log(source)); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var import0 = require('@angular/core/src/linker/debug_context'); | |
var import1 = require('@angular/core/src/linker/view'); | |
var import2 = require('@angular/core/src/linker/view_type'); | |
var import3 = require('@angular/core/src/change_detection/change_detection'); | |
var import4 = require('@angular/core/src/linker/view_utils'); | |
var import5 = require('@angular/core/src/metadata/view'); | |
var import6 = require('asset:foo/bar'); | |
var import7 = require('@angular/core/src/linker/element'); | |
var import8 = require('@angular/core/src/linker/component_factory'); | |
var styles_CompA = ['.redStyle[_ngcontent-%COMP%] { color: red; }']; | |
var nodeDebugInfos_CompA0 = [new import0.StaticNodeDebugInfo([],null,{})]; | |
var renderType_CompA = null; | |
function _View_CompA0(viewUtils,parentInjector,declarationEl) { | |
var self = this; | |
import1.DebugAppView.call(this, _View_CompA0,renderType_CompA,import2.ViewType.COMPONENT,viewUtils,parentInjector,declarationEl,import3.ChangeDetectionStrategy.CheckAlways,nodeDebugInfos_CompA0); | |
} | |
_View_CompA0.prototype = Object.create(import1.DebugAppView.prototype); | |
_View_CompA0.prototype.createInternal = function(rootSelector) { | |
var self = this; | |
var parentRenderNode = self.renderer.createViewRoot(self.declarationAppElement.nativeElement); | |
self._text_0 = self.renderer.createText(parentRenderNode,'',self.debug(0,0,0)); | |
self._expr_0 = import3.uninitialized; | |
self.init([],[self._text_0],[],[]); | |
return null; | |
}; | |
_View_CompA0.prototype.detectChangesInternal = function(throwOnChange) { | |
var self = this; | |
self.detectContentChildrenChanges(throwOnChange); | |
self.debug(0,0,0); | |
var currVal_0 = import4.interpolate(1,'Hello World ',self.context.user,''); | |
if (import4.checkBinding(throwOnChange,self._expr_0,currVal_0)) { | |
self.renderer.setText(self._text_0,currVal_0); | |
self._expr_0 = currVal_0; | |
} | |
self.detectViewChildrenChanges(throwOnChange); | |
}; | |
function viewFactory_CompA0(viewUtils,parentInjector,declarationEl) { | |
if ((renderType_CompA === null)) { (renderType_CompA = viewUtils.createRenderComponentType('asset:foo/bar class CompA - inline template',0,import5.ViewEncapsulation.Emulated,styles_CompA)); } | |
return new _View_CompA0(viewUtils,parentInjector,declarationEl); | |
} | |
Object.defineProperty(exports, 'viewFactory_CompA0', { get: function() { return viewFactory_CompA0; }}); | |
var styles_CompA_Host = []; | |
var nodeDebugInfos_CompA_Host0 = [new import0.StaticNodeDebugInfo([import6.CompA],import6.CompA,{})]; | |
var renderType_CompA_Host = null; | |
function _View_CompA_Host0(viewUtils,parentInjector,declarationEl) { | |
var self = this; | |
import1.DebugAppView.call(this, _View_CompA_Host0,renderType_CompA_Host,import2.ViewType.HOST,viewUtils,parentInjector,declarationEl,import3.ChangeDetectionStrategy.CheckAlways,nodeDebugInfos_CompA_Host0); | |
} | |
_View_CompA_Host0.prototype = Object.create(import1.DebugAppView.prototype); | |
_View_CompA_Host0.prototype.createInternal = function(rootSelector) { | |
var self = this; | |
self._el_0 = self.selectOrCreateHostElement('comp-a',rootSelector,self.debug(0,0,0)); | |
self._appEl_0 = new import7.AppElement(0,null,self,self._el_0); | |
var compView_0 = viewFactory_CompA0(self.viewUtils,self.injector(0),self._appEl_0); | |
self._CompA_0_4 = new import6.CompA(); | |
self._appEl_0.initComponent(self._CompA_0_4,[],compView_0); | |
compView_0.create(self._CompA_0_4,self.projectableNodes,null); | |
self.init([].concat([self._el_0]),[self._el_0],[],[]); | |
return self._appEl_0; | |
}; | |
_View_CompA_Host0.prototype.injectorGetInternal = function(token,requestNodeIndex,notFoundResult) { | |
var self = this; | |
if (((token === import6.CompA) && (0 === requestNodeIndex))) { return self._CompA_0_4; } | |
return notFoundResult; | |
}; | |
function viewFactory_CompA_Host0(viewUtils,parentInjector,declarationEl) { | |
if ((renderType_CompA_Host === null)) { (renderType_CompA_Host = viewUtils.createRenderComponentType('',0,import5.ViewEncapsulation.Emulated,styles_CompA_Host)); } | |
return new _View_CompA_Host0(viewUtils,parentInjector,declarationEl); | |
} | |
var CompANgFactory = new import8.ComponentFactory('comp-a',viewFactory_CompA_Host0,import6.CompA); | |
Object.defineProperty(exports, 'CompANgFactory', { get: function() { return CompANgFactory; }}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as o from '@angular/compiler/src/output/output_ast'; | |
import { | |
isPresent, | |
isBlank, | |
isString, | |
evalExpression, | |
RegExpWrapper, | |
StringWrapper | |
} from '@angular/compiler/src/facade/lang'; | |
import {BaseException} from '@angular/core'; | |
import {OutputEmitter, EmitterVisitorContext} from '@angular/compiler/src/output/abstract_emitter'; | |
import {AbstractJsEmitterVisitor} from '@angular/compiler/src/output/abstract_js_emitter'; | |
import {ImportGenerator} from '@angular/compiler/src/output/path_util'; | |
export class JavaScriptEmitter implements OutputEmitter { | |
constructor(_importGenerator) { | |
this._importGenerator = _importGenerator; | |
} | |
emitStatements(moduleUrl: string, stmts: o.Statement[], exportedVars: string[]): string { | |
var converter = new JsEmitterVisitor(moduleUrl); | |
var ctx = EmitterVisitorContext.createRoot(exportedVars); | |
converter.visitAllStatements(stmts, ctx); | |
var srcParts = []; | |
converter.importsWithPrefixes.forEach((prefix, importedModuleUrl) => { | |
// Note: can't write the real word for import as it screws up system.js auto detection... | |
srcParts.push( | |
`var ${prefix} = req` + | |
`uire('${this._importGenerator.getImportPath(moduleUrl, importedModuleUrl)}');`); | |
}); | |
srcParts.push(ctx.toSource()); | |
return srcParts.join('\n'); | |
} | |
} | |
class JsEmitterVisitor extends AbstractJsEmitterVisitor { | |
importsWithPrefixes = new Map(); | |
constructor(_moduleUrl: string) { | |
super(); | |
this._moduleUrl = _moduleUrl; | |
} | |
visitExternalExpr(ast: o.ExternalExpr, ctx: EmitterVisitorContext): any { | |
if (isBlank(ast.value.name)) { | |
throw new BaseException(`Internal error: unknown identifier ${ast.value}`); | |
} | |
if (isPresent(ast.value.moduleUrl) && ast.value.moduleUrl != this._moduleUrl) { | |
var prefix = this.importsWithPrefixes.get(ast.value.moduleUrl); | |
if (isBlank(prefix)) { | |
prefix = `import${this.importsWithPrefixes.size}`; | |
this.importsWithPrefixes.set(ast.value.moduleUrl, prefix); | |
} | |
ctx.print(`${prefix}.`); | |
} | |
ctx.print(ast.value.name); | |
return null; | |
} | |
visitDeclareVarStmt(stmt: o.DeclareVarStmt, ctx: EmitterVisitorContext): any { | |
super.visitDeclareVarStmt(stmt, ctx); | |
if (ctx.isExportedVar(stmt.name)) { | |
ctx.println(exportVar(stmt.name)); | |
} | |
return null; | |
} | |
visitDeclareFunctionStmt(stmt: o.DeclareFunctionStmt, ctx: EmitterVisitorContext): any { | |
super.visitDeclareFunctionStmt(stmt, ctx); | |
if (ctx.isExportedVar(stmt.name)) { | |
ctx.println(exportVar(stmt.name)); | |
} | |
return null; | |
} | |
visitDeclareClassStmt(stmt: o.ClassStmt, ctx: EmitterVisitorContext): any { | |
super.visitDeclareClassStmt(stmt, ctx); | |
if (ctx.isExportedVar(stmt.name)) { | |
ctx.println(exportVar(stmt.name)); | |
} | |
return null; | |
} | |
} | |
function exportVar(varName: string): string { | |
return `Object.defineProperty(exports, '${varName}', { get: function() { return ${varName}; }});`; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment