refactor(compiler): wrap the jit evaluation in an injectable class (#28055)
When testing JIT code, it is useful to be able to access the generated JIT source. Previously this is done by spying on the global `Function` object, to capture the code when it is being evaluated. This is problematic because you can only capture the body of the function, and not the arguments, which messes up line and column positions for source mapping for instance. Now the code that generates and then evaluates JIT code is wrapped in a `JitEvaluator` class, making it possible to provide a mock implementation that can capture the generated source of the function passed to `executeFunction(fn: Function, args: any[])`. PR Close #28055
This commit is contained in:
parent
8c3f1717a8
commit
54ca24b47d
|
@ -77,6 +77,7 @@ export * from './ml_parser/tags';
|
||||||
export {NgModuleCompiler} from './ng_module_compiler';
|
export {NgModuleCompiler} from './ng_module_compiler';
|
||||||
export {ArrayType, AssertNotNull, BinaryOperator, BinaryOperatorExpr, BuiltinMethod, BuiltinType, BuiltinTypeName, BuiltinVar, CastExpr, ClassField, ClassMethod, ClassStmt, CommaExpr, CommentStmt, ConditionalExpr, DeclareFunctionStmt, DeclareVarStmt, Expression, ExpressionStatement, ExpressionType, ExpressionVisitor, ExternalExpr, ExternalReference, FunctionExpr, IfStmt, InstantiateExpr, InvokeFunctionExpr, InvokeMethodExpr, JSDocCommentStmt, LiteralArrayExpr, LiteralExpr, LiteralMapExpr, MapType, NotExpr, ReadKeyExpr, ReadPropExpr, ReadVarExpr, ReturnStatement, StatementVisitor, ThrowStmt, TryCatchStmt, Type, TypeVisitor, WrappedNodeExpr, WriteKeyExpr, WritePropExpr, WriteVarExpr, StmtModifier, Statement, TypeofExpr, collectExternalReferences} from './output/output_ast';
|
export {ArrayType, AssertNotNull, BinaryOperator, BinaryOperatorExpr, BuiltinMethod, BuiltinType, BuiltinTypeName, BuiltinVar, CastExpr, ClassField, ClassMethod, ClassStmt, CommaExpr, CommentStmt, ConditionalExpr, DeclareFunctionStmt, DeclareVarStmt, Expression, ExpressionStatement, ExpressionType, ExpressionVisitor, ExternalExpr, ExternalReference, FunctionExpr, IfStmt, InstantiateExpr, InvokeFunctionExpr, InvokeMethodExpr, JSDocCommentStmt, LiteralArrayExpr, LiteralExpr, LiteralMapExpr, MapType, NotExpr, ReadKeyExpr, ReadPropExpr, ReadVarExpr, ReturnStatement, StatementVisitor, ThrowStmt, TryCatchStmt, Type, TypeVisitor, WrappedNodeExpr, WriteKeyExpr, WritePropExpr, WriteVarExpr, StmtModifier, Statement, TypeofExpr, collectExternalReferences} from './output/output_ast';
|
||||||
export {EmitterVisitorContext} from './output/abstract_emitter';
|
export {EmitterVisitorContext} from './output/abstract_emitter';
|
||||||
|
export {JitEvaluator} from './output/output_jit';
|
||||||
export * from './output/ts_emitter';
|
export * from './output/ts_emitter';
|
||||||
export * from './parse_util';
|
export * from './parse_util';
|
||||||
export * from './schema/dom_element_schema_registry';
|
export * from './schema/dom_element_schema_registry';
|
||||||
|
@ -92,7 +93,6 @@ export {BoundAttribute as TmplAstBoundAttribute, BoundEvent as TmplAstBoundEvent
|
||||||
export * from './render3/view/t2_api';
|
export * from './render3/view/t2_api';
|
||||||
export * from './render3/view/t2_binder';
|
export * from './render3/view/t2_binder';
|
||||||
export {Identifiers as R3Identifiers} from './render3/r3_identifiers';
|
export {Identifiers as R3Identifiers} from './render3/r3_identifiers';
|
||||||
export {jitExpression} from './render3/r3_jit';
|
|
||||||
export {R3DependencyMetadata, R3FactoryMetadata, R3ResolvedDependencyType} from './render3/r3_factory';
|
export {R3DependencyMetadata, R3FactoryMetadata, R3ResolvedDependencyType} from './render3/r3_factory';
|
||||||
export {compileInjector, compileNgModule, R3InjectorMetadata, R3NgModuleMetadata} from './render3/r3_module_compiler';
|
export {compileInjector, compileNgModule, R3InjectorMetadata, R3NgModuleMetadata} from './render3/r3_module_compiler';
|
||||||
export {compilePipeFromMetadata, R3PipeMetadata} from './render3/r3_pipe_compiler';
|
export {compilePipeFromMetadata, R3PipeMetadata} from './render3/r3_pipe_compiler';
|
||||||
|
|
|
@ -15,7 +15,7 @@ import {CompileMetadataResolver} from '../metadata_resolver';
|
||||||
import {NgModuleCompiler} from '../ng_module_compiler';
|
import {NgModuleCompiler} from '../ng_module_compiler';
|
||||||
import * as ir from '../output/output_ast';
|
import * as ir from '../output/output_ast';
|
||||||
import {interpretStatements} from '../output/output_interpreter';
|
import {interpretStatements} from '../output/output_interpreter';
|
||||||
import {jitStatements} from '../output/output_jit';
|
import {JitEvaluator} from '../output/output_jit';
|
||||||
import {CompiledStylesheet, StyleCompiler} from '../style_compiler';
|
import {CompiledStylesheet, StyleCompiler} from '../style_compiler';
|
||||||
import {SummaryResolver} from '../summary_resolver';
|
import {SummaryResolver} from '../summary_resolver';
|
||||||
import {TemplateAst} from '../template_parser/template_ast';
|
import {TemplateAst} from '../template_parser/template_ast';
|
||||||
|
@ -49,8 +49,8 @@ export class JitCompiler {
|
||||||
private _metadataResolver: CompileMetadataResolver, private _templateParser: TemplateParser,
|
private _metadataResolver: CompileMetadataResolver, private _templateParser: TemplateParser,
|
||||||
private _styleCompiler: StyleCompiler, private _viewCompiler: ViewCompiler,
|
private _styleCompiler: StyleCompiler, private _viewCompiler: ViewCompiler,
|
||||||
private _ngModuleCompiler: NgModuleCompiler, private _summaryResolver: SummaryResolver<Type>,
|
private _ngModuleCompiler: NgModuleCompiler, private _summaryResolver: SummaryResolver<Type>,
|
||||||
private _reflector: CompileReflector, private _compilerConfig: CompilerConfig,
|
private _reflector: CompileReflector, private _jitEvaluator: JitEvaluator,
|
||||||
private _console: Console,
|
private _compilerConfig: CompilerConfig, private _console: Console,
|
||||||
private getExtraNgModuleProviders: (ngModule: any) => CompileProviderMetadata[]) {}
|
private getExtraNgModuleProviders: (ngModule: any) => CompileProviderMetadata[]) {}
|
||||||
|
|
||||||
compileModuleSync(moduleType: Type): object {
|
compileModuleSync(moduleType: Type): object {
|
||||||
|
@ -322,7 +322,8 @@ export class JitCompiler {
|
||||||
if (!this._compilerConfig.useJit) {
|
if (!this._compilerConfig.useJit) {
|
||||||
return interpretStatements(statements, this._reflector);
|
return interpretStatements(statements, this._reflector);
|
||||||
} else {
|
} else {
|
||||||
return jitStatements(sourceUrl, statements, this._reflector, this._compilerConfig.jitDevMode);
|
return this._jitEvaluator.evaluateStatements(
|
||||||
|
sourceUrl, statements, this._reflector, this._compilerConfig.jitDevMode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,10 +12,11 @@ import {ConstantPool} from './constant_pool';
|
||||||
import {HostBinding, HostListener, Input, Output, Type} from './core';
|
import {HostBinding, HostListener, Input, Output, Type} from './core';
|
||||||
import {compileInjectable} from './injectable_compiler_2';
|
import {compileInjectable} from './injectable_compiler_2';
|
||||||
import {DEFAULT_INTERPOLATION_CONFIG, InterpolationConfig} from './ml_parser/interpolation_config';
|
import {DEFAULT_INTERPOLATION_CONFIG, InterpolationConfig} from './ml_parser/interpolation_config';
|
||||||
import {Expression, LiteralExpr, WrappedNodeExpr} from './output/output_ast';
|
import {DeclareVarStmt, Expression, LiteralExpr, Statement, StmtModifier, WrappedNodeExpr} from './output/output_ast';
|
||||||
|
import {JitEvaluator} from './output/output_jit';
|
||||||
import {ParseError, ParseSourceSpan, r3JitTypeSourceSpan} from './parse_util';
|
import {ParseError, ParseSourceSpan, r3JitTypeSourceSpan} from './parse_util';
|
||||||
import {R3DependencyMetadata, R3ResolvedDependencyType} from './render3/r3_factory';
|
import {R3DependencyMetadata, R3ResolvedDependencyType} from './render3/r3_factory';
|
||||||
import {jitExpression} from './render3/r3_jit';
|
import {R3JitReflector} from './render3/r3_jit';
|
||||||
import {R3InjectorMetadata, R3NgModuleMetadata, compileInjector, compileNgModule} from './render3/r3_module_compiler';
|
import {R3InjectorMetadata, R3NgModuleMetadata, compileInjector, compileNgModule} from './render3/r3_module_compiler';
|
||||||
import {compilePipeFromMetadata} from './render3/r3_pipe_compiler';
|
import {compilePipeFromMetadata} from './render3/r3_pipe_compiler';
|
||||||
import {R3Reference} from './render3/util';
|
import {R3Reference} from './render3/util';
|
||||||
|
@ -27,6 +28,7 @@ import {DomElementSchemaRegistry} from './schema/dom_element_schema_registry';
|
||||||
export class CompilerFacadeImpl implements CompilerFacade {
|
export class CompilerFacadeImpl implements CompilerFacade {
|
||||||
R3ResolvedDependencyType = R3ResolvedDependencyType as any;
|
R3ResolvedDependencyType = R3ResolvedDependencyType as any;
|
||||||
private elementSchemaRegistry = new DomElementSchemaRegistry();
|
private elementSchemaRegistry = new DomElementSchemaRegistry();
|
||||||
|
private jitEvaluator = new JitEvaluator();
|
||||||
|
|
||||||
compilePipe(angularCoreEnv: CoreEnvironment, sourceMapUrl: string, facade: R3PipeMetadataFacade):
|
compilePipe(angularCoreEnv: CoreEnvironment, sourceMapUrl: string, facade: R3PipeMetadataFacade):
|
||||||
any {
|
any {
|
||||||
|
@ -37,7 +39,7 @@ export class CompilerFacadeImpl implements CompilerFacade {
|
||||||
pipeName: facade.pipeName,
|
pipeName: facade.pipeName,
|
||||||
pure: facade.pure,
|
pure: facade.pure,
|
||||||
});
|
});
|
||||||
return jitExpression(res.expression, angularCoreEnv, sourceMapUrl, res.statements);
|
return this.jitExpression(res.expression, angularCoreEnv, sourceMapUrl, res.statements);
|
||||||
}
|
}
|
||||||
|
|
||||||
compileInjectable(
|
compileInjectable(
|
||||||
|
@ -56,7 +58,7 @@ export class CompilerFacadeImpl implements CompilerFacade {
|
||||||
userDeps: convertR3DependencyMetadataArray(facade.userDeps) || undefined,
|
userDeps: convertR3DependencyMetadataArray(facade.userDeps) || undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
return jitExpression(expression, angularCoreEnv, sourceMapUrl, statements);
|
return this.jitExpression(expression, angularCoreEnv, sourceMapUrl, statements);
|
||||||
}
|
}
|
||||||
|
|
||||||
compileInjector(
|
compileInjector(
|
||||||
|
@ -70,7 +72,7 @@ export class CompilerFacadeImpl implements CompilerFacade {
|
||||||
imports: new WrappedNodeExpr(facade.imports),
|
imports: new WrappedNodeExpr(facade.imports),
|
||||||
};
|
};
|
||||||
const res = compileInjector(meta);
|
const res = compileInjector(meta);
|
||||||
return jitExpression(res.expression, angularCoreEnv, sourceMapUrl, res.statements);
|
return this.jitExpression(res.expression, angularCoreEnv, sourceMapUrl, res.statements);
|
||||||
}
|
}
|
||||||
|
|
||||||
compileNgModule(
|
compileNgModule(
|
||||||
|
@ -85,7 +87,7 @@ export class CompilerFacadeImpl implements CompilerFacade {
|
||||||
emitInline: true,
|
emitInline: true,
|
||||||
};
|
};
|
||||||
const res = compileNgModule(meta);
|
const res = compileNgModule(meta);
|
||||||
return jitExpression(res.expression, angularCoreEnv, sourceMapUrl, []);
|
return this.jitExpression(res.expression, angularCoreEnv, sourceMapUrl, []);
|
||||||
}
|
}
|
||||||
|
|
||||||
compileDirective(
|
compileDirective(
|
||||||
|
@ -97,7 +99,7 @@ export class CompilerFacadeImpl implements CompilerFacade {
|
||||||
const meta: R3DirectiveMetadata = convertDirectiveFacadeToMetadata(facade);
|
const meta: R3DirectiveMetadata = convertDirectiveFacadeToMetadata(facade);
|
||||||
const res = compileDirectiveFromMetadata(meta, constantPool, bindingParser);
|
const res = compileDirectiveFromMetadata(meta, constantPool, bindingParser);
|
||||||
const preStatements = [...constantPool.statements, ...res.statements];
|
const preStatements = [...constantPool.statements, ...res.statements];
|
||||||
return jitExpression(res.expression, angularCoreEnv, sourceMapUrl, preStatements);
|
return this.jitExpression(res.expression, angularCoreEnv, sourceMapUrl, preStatements);
|
||||||
}
|
}
|
||||||
|
|
||||||
compileComponent(
|
compileComponent(
|
||||||
|
@ -140,13 +142,38 @@ export class CompilerFacadeImpl implements CompilerFacade {
|
||||||
},
|
},
|
||||||
constantPool, makeBindingParser(interpolationConfig));
|
constantPool, makeBindingParser(interpolationConfig));
|
||||||
const preStatements = [...constantPool.statements, ...res.statements];
|
const preStatements = [...constantPool.statements, ...res.statements];
|
||||||
|
return this.jitExpression(
|
||||||
return jitExpression(res.expression, angularCoreEnv, sourceMapUrl, preStatements);
|
res.expression, angularCoreEnv, sourceMapUrl, preStatements);
|
||||||
}
|
}
|
||||||
|
|
||||||
createParseSourceSpan(kind: string, typeName: string, sourceUrl: string): ParseSourceSpan {
|
createParseSourceSpan(kind: string, typeName: string, sourceUrl: string): ParseSourceSpan {
|
||||||
return r3JitTypeSourceSpan(kind, typeName, sourceUrl);
|
return r3JitTypeSourceSpan(kind, typeName, sourceUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JIT compiles an expression and returns the result of executing that expression.
|
||||||
|
*
|
||||||
|
* @param def the definition which will be compiled and executed to get the value to patch
|
||||||
|
* @param context an object map of @angular/core symbol names to symbols which will be available
|
||||||
|
* in the context of the compiled expression
|
||||||
|
* @param sourceUrl a URL to use for the source map of the compiled expression
|
||||||
|
* @param preStatements a collection of statements that should be evaluated before the expression.
|
||||||
|
*/
|
||||||
|
private jitExpression(
|
||||||
|
def: Expression, context: {[key: string]: any}, sourceUrl: string,
|
||||||
|
preStatements: Statement[]): any {
|
||||||
|
// The ConstantPool may contain Statements which declare variables used in the final expression.
|
||||||
|
// Therefore, its statements need to precede the actual JIT operation. The final statement is a
|
||||||
|
// declaration of $def which is set to the expression being compiled.
|
||||||
|
const statements: Statement[] = [
|
||||||
|
...preStatements,
|
||||||
|
new DeclareVarStmt('$def', def, undefined, [StmtModifier.Exported]),
|
||||||
|
];
|
||||||
|
|
||||||
|
const res = this.jitEvaluator.evaluateStatements(
|
||||||
|
sourceUrl, statements, new R3JitReflector(context), /* enableSourceMaps */ true);
|
||||||
|
return res['$def'];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This seems to be needed to placate TS v3.0 only
|
// This seems to be needed to placate TS v3.0 only
|
||||||
|
|
|
@ -13,39 +13,79 @@ import {EmitterVisitorContext} from './abstract_emitter';
|
||||||
import {AbstractJsEmitterVisitor} from './abstract_js_emitter';
|
import {AbstractJsEmitterVisitor} from './abstract_js_emitter';
|
||||||
import * as o from './output_ast';
|
import * as o from './output_ast';
|
||||||
|
|
||||||
function evalExpression(
|
/**
|
||||||
sourceUrl: string, ctx: EmitterVisitorContext, vars: {[key: string]: any},
|
* A helper class to manage the evaluation of JIT generated code.
|
||||||
createSourceMap: boolean): any {
|
*/
|
||||||
let fnBody = `${ctx.toSource()}\n//# sourceURL=${sourceUrl}`;
|
export class JitEvaluator {
|
||||||
const fnArgNames: string[] = [];
|
/**
|
||||||
const fnArgValues: any[] = [];
|
*
|
||||||
for (const argName in vars) {
|
* @param sourceUrl The URL of the generated code.
|
||||||
fnArgNames.push(argName);
|
* @param statements An array of Angular statement AST nodes to be evaluated.
|
||||||
fnArgValues.push(vars[argName]);
|
* @param reflector A helper used when converting the statements to executable code.
|
||||||
|
* @param createSourceMaps If true then create a source-map for the generated code and include it
|
||||||
|
* inline as a source-map comment.
|
||||||
|
* @returns A map of all the variables in the generated code.
|
||||||
|
*/
|
||||||
|
evaluateStatements(
|
||||||
|
sourceUrl: string, statements: o.Statement[], reflector: CompileReflector,
|
||||||
|
createSourceMaps: boolean): {[key: string]: any} {
|
||||||
|
const converter = new JitEmitterVisitor(reflector);
|
||||||
|
const ctx = EmitterVisitorContext.createRoot();
|
||||||
|
converter.visitAllStatements(statements, ctx);
|
||||||
|
converter.createReturnStmt(ctx);
|
||||||
|
return this.evaluateCode(sourceUrl, ctx, converter.getArgs(), createSourceMaps);
|
||||||
}
|
}
|
||||||
if (createSourceMap) {
|
|
||||||
// using `new Function(...)` generates a header, 1 line of no arguments, 2 lines otherwise
|
/**
|
||||||
// E.g. ```
|
* Evaluate a piece of JIT generated code.
|
||||||
// function anonymous(a,b,c
|
* @param sourceUrl The URL of this generated code.
|
||||||
// /**/) { ... }```
|
* @param ctx A context object that contains an AST of the code to be evaluated.
|
||||||
// We don't want to hard code this fact, so we auto detect it via an empty function first.
|
* @param vars A map containing the names and values of variables that the evaluated code might
|
||||||
const emptyFn = new Function(...fnArgNames.concat('return null;')).toString();
|
* reference.
|
||||||
const headerLines = emptyFn.slice(0, emptyFn.indexOf('return null;')).split('\n').length - 1;
|
* @param createSourceMap If true then create a source-map for the generated code and include it
|
||||||
fnBody += `\n${ctx.toSourceMapGenerator(sourceUrl, headerLines).toJsComment()}`;
|
* inline as a source-map comment.
|
||||||
|
* @returns The result of evaluating the code.
|
||||||
|
*/
|
||||||
|
evaluateCode(
|
||||||
|
sourceUrl: string, ctx: EmitterVisitorContext, vars: {[key: string]: any},
|
||||||
|
createSourceMap: boolean): any {
|
||||||
|
let fnBody = `${ctx.toSource()}\n//# sourceURL=${sourceUrl}`;
|
||||||
|
const fnArgNames: string[] = [];
|
||||||
|
const fnArgValues: any[] = [];
|
||||||
|
for (const argName in vars) {
|
||||||
|
fnArgValues.push(vars[argName]);
|
||||||
|
fnArgNames.push(argName);
|
||||||
|
}
|
||||||
|
if (createSourceMap) {
|
||||||
|
// using `new Function(...)` generates a header, 1 line of no arguments, 2 lines otherwise
|
||||||
|
// E.g. ```
|
||||||
|
// function anonymous(a,b,c
|
||||||
|
// /**/) { ... }```
|
||||||
|
// We don't want to hard code this fact, so we auto detect it via an empty function first.
|
||||||
|
const emptyFn = new Function(...fnArgNames.concat('return null;')).toString();
|
||||||
|
const headerLines = emptyFn.slice(0, emptyFn.indexOf('return null;')).split('\n').length - 1;
|
||||||
|
fnBody += `\n${ctx.toSourceMapGenerator(sourceUrl, headerLines).toJsComment()}`;
|
||||||
|
}
|
||||||
|
const fn = new Function(...fnArgNames.concat(fnBody));
|
||||||
|
return this.executeFunction(fn, fnArgValues);
|
||||||
}
|
}
|
||||||
return new Function(...fnArgNames.concat(fnBody))(...fnArgValues);
|
|
||||||
}
|
/**
|
||||||
|
* Execute a JIT generated function by calling it.
|
||||||
export function jitStatements(
|
*
|
||||||
sourceUrl: string, statements: o.Statement[], reflector: CompileReflector,
|
* This method can be overridden in tests to capture the functions that are generated
|
||||||
createSourceMaps: boolean): {[key: string]: any} {
|
* by this `JitEvaluator` class.
|
||||||
const converter = new JitEmitterVisitor(reflector);
|
*
|
||||||
const ctx = EmitterVisitorContext.createRoot();
|
* @param fn A function to execute.
|
||||||
converter.visitAllStatements(statements, ctx);
|
* @param args The arguments to pass to the function being executed.
|
||||||
converter.createReturnStmt(ctx);
|
* @returns The return value of the executed function.
|
||||||
return evalExpression(sourceUrl, ctx, converter.getArgs(), createSourceMaps);
|
*/
|
||||||
|
executeFunction(fn: Function, args: any[]) { return fn(...args); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An Angular AST visitor that converts AST nodes into executable JavaScript code.
|
||||||
|
*/
|
||||||
export class JitEmitterVisitor extends AbstractJsEmitterVisitor {
|
export class JitEmitterVisitor extends AbstractJsEmitterVisitor {
|
||||||
private _evalArgNames: string[] = [];
|
private _evalArgNames: string[] = [];
|
||||||
private _evalArgValues: any[] = [];
|
private _evalArgValues: any[] = [];
|
||||||
|
|
|
@ -7,9 +7,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {CompileReflector} from '../compile_reflector';
|
import {CompileReflector} from '../compile_reflector';
|
||||||
import {ConstantPool} from '../constant_pool';
|
|
||||||
import * as o from '../output/output_ast';
|
import * as o from '../output/output_ast';
|
||||||
import {jitStatements} from '../output/output_jit';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of `CompileReflector` which resolves references to @angular/core
|
* Implementation of `CompileReflector` which resolves references to @angular/core
|
||||||
|
@ -17,7 +15,7 @@ import {jitStatements} from '../output/output_jit';
|
||||||
*
|
*
|
||||||
* Only supports `resolveExternalReference`, all other methods throw.
|
* Only supports `resolveExternalReference`, all other methods throw.
|
||||||
*/
|
*/
|
||||||
class R3JitReflector implements CompileReflector {
|
export class R3JitReflector implements CompileReflector {
|
||||||
constructor(private context: {[key: string]: any}) {}
|
constructor(private context: {[key: string]: any}) {}
|
||||||
|
|
||||||
resolveExternalReference(ref: o.ExternalReference): any {
|
resolveExternalReference(ref: o.ExternalReference): any {
|
||||||
|
@ -48,27 +46,3 @@ class R3JitReflector implements CompileReflector {
|
||||||
|
|
||||||
componentModuleUrl(type: any, cmpMetadata: any): string { throw new Error('Not implemented.'); }
|
componentModuleUrl(type: any, cmpMetadata: any): string { throw new Error('Not implemented.'); }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* JIT compiles an expression and returns the result of executing that expression.
|
|
||||||
*
|
|
||||||
* @param def the definition which will be compiled and executed to get the value to patch
|
|
||||||
* @param context an object map of @angular/core symbol names to symbols which will be available in
|
|
||||||
* the context of the compiled expression
|
|
||||||
* @param sourceUrl a URL to use for the source map of the compiled expression
|
|
||||||
* @param constantPool an optional `ConstantPool` which contains constants used in the expression
|
|
||||||
*/
|
|
||||||
export function jitExpression(
|
|
||||||
def: o.Expression, context: {[key: string]: any}, sourceUrl: string,
|
|
||||||
preStatements: o.Statement[]): any {
|
|
||||||
// The ConstantPool may contain Statements which declare variables used in the final expression.
|
|
||||||
// Therefore, its statements need to precede the actual JIT operation. The final statement is a
|
|
||||||
// declaration of $def which is set to the expression being compiled.
|
|
||||||
const statements: o.Statement[] = [
|
|
||||||
...preStatements,
|
|
||||||
new o.DeclareVarStmt('$def', def, undefined, [o.StmtModifier.Exported]),
|
|
||||||
];
|
|
||||||
|
|
||||||
const res = jitStatements(sourceUrl, statements, new R3JitReflector(context), false);
|
|
||||||
return res['$def'];
|
|
||||||
}
|
|
||||||
|
|
|
@ -6,9 +6,9 @@
|
||||||
* found in the LICENSE file at https://angular.io/license
|
* found in the LICENSE file at https://angular.io/license
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {Compiler, CompilerFactory, ComponentFactory, CompilerOptions, ModuleWithComponentFactories, Inject, InjectionToken, Optional, PACKAGE_ROOT_URL, PlatformRef, StaticProvider, TRANSLATIONS, Type, isDevMode, platformCore, ɵConsole as Console, ViewEncapsulation, Injector, NgModuleFactory, TRANSLATIONS_FORMAT, MissingTranslationStrategy,} from '@angular/core';
|
import {Compiler, CompilerFactory, ComponentFactory, CompilerOptions, ModuleWithComponentFactories, Inject, InjectionToken, Optional, PACKAGE_ROOT_URL, StaticProvider, TRANSLATIONS, Type, isDevMode, ɵConsole as Console, ViewEncapsulation, Injector, NgModuleFactory, TRANSLATIONS_FORMAT, MissingTranslationStrategy,} from '@angular/core';
|
||||||
|
|
||||||
import {StaticSymbolCache, JitCompiler, ProviderMeta, ExternalReference, I18NHtmlParser, Identifiers, ViewCompiler, CompileMetadataResolver, UrlResolver, TemplateParser, NgModuleCompiler, JitSummaryResolver, SummaryResolver, StyleCompiler, PipeResolver, ElementSchemaRegistry, DomElementSchemaRegistry, ResourceLoader, NgModuleResolver, HtmlParser, CompileReflector, CompilerConfig, DirectiveNormalizer, DirectiveResolver, Lexer, Parser} from '@angular/compiler';
|
import {StaticSymbolCache, JitCompiler, ProviderMeta, I18NHtmlParser, ViewCompiler, CompileMetadataResolver, UrlResolver, TemplateParser, NgModuleCompiler, JitEvaluator, JitSummaryResolver, SummaryResolver, StyleCompiler, PipeResolver, ElementSchemaRegistry, DomElementSchemaRegistry, ResourceLoader, NgModuleResolver, HtmlParser, CompileReflector, CompilerConfig, DirectiveNormalizer, DirectiveResolver, Lexer, Parser} from '@angular/compiler';
|
||||||
|
|
||||||
import {JitReflector} from './compiler_reflector';
|
import {JitReflector} from './compiler_reflector';
|
||||||
|
|
||||||
|
@ -37,10 +37,11 @@ export class CompilerImpl implements Compiler {
|
||||||
injector: Injector, private _metadataResolver: CompileMetadataResolver,
|
injector: Injector, private _metadataResolver: CompileMetadataResolver,
|
||||||
templateParser: TemplateParser, styleCompiler: StyleCompiler, viewCompiler: ViewCompiler,
|
templateParser: TemplateParser, styleCompiler: StyleCompiler, viewCompiler: ViewCompiler,
|
||||||
ngModuleCompiler: NgModuleCompiler, summaryResolver: SummaryResolver<Type<any>>,
|
ngModuleCompiler: NgModuleCompiler, summaryResolver: SummaryResolver<Type<any>>,
|
||||||
compileReflector: CompileReflector, compilerConfig: CompilerConfig, console: Console) {
|
compileReflector: CompileReflector, jitEvaluator: JitEvaluator,
|
||||||
|
compilerConfig: CompilerConfig, console: Console) {
|
||||||
this._delegate = new JitCompiler(
|
this._delegate = new JitCompiler(
|
||||||
_metadataResolver, templateParser, styleCompiler, viewCompiler, ngModuleCompiler,
|
_metadataResolver, templateParser, styleCompiler, viewCompiler, ngModuleCompiler,
|
||||||
summaryResolver, compileReflector, compilerConfig, console,
|
summaryResolver, compileReflector, jitEvaluator, compilerConfig, console,
|
||||||
this.getExtraNgModuleProviders.bind(this));
|
this.getExtraNgModuleProviders.bind(this));
|
||||||
this.injector = injector;
|
this.injector = injector;
|
||||||
}
|
}
|
||||||
|
@ -127,6 +128,7 @@ export const COMPILER_PROVIDERS = <StaticProvider[]>[
|
||||||
Parser, ElementSchemaRegistry,
|
Parser, ElementSchemaRegistry,
|
||||||
I18NHtmlParser, Console]
|
I18NHtmlParser, Console]
|
||||||
},
|
},
|
||||||
|
{ provide: JitEvaluator, useClass: JitEvaluator, deps: [] },
|
||||||
{ provide: DirectiveNormalizer, deps: [ResourceLoader, UrlResolver, HtmlParser, CompilerConfig]},
|
{ provide: DirectiveNormalizer, deps: [ResourceLoader, UrlResolver, HtmlParser, CompilerConfig]},
|
||||||
{ provide: CompileMetadataResolver, deps: [CompilerConfig, HtmlParser, NgModuleResolver,
|
{ provide: CompileMetadataResolver, deps: [CompilerConfig, HtmlParser, NgModuleResolver,
|
||||||
DirectiveResolver, PipeResolver,
|
DirectiveResolver, PipeResolver,
|
||||||
|
@ -144,7 +146,7 @@ export const COMPILER_PROVIDERS = <StaticProvider[]>[
|
||||||
{ provide: Compiler, useClass: CompilerImpl, deps: [Injector, CompileMetadataResolver,
|
{ provide: Compiler, useClass: CompilerImpl, deps: [Injector, CompileMetadataResolver,
|
||||||
TemplateParser, StyleCompiler,
|
TemplateParser, StyleCompiler,
|
||||||
ViewCompiler, NgModuleCompiler,
|
ViewCompiler, NgModuleCompiler,
|
||||||
SummaryResolver, CompileReflector, CompilerConfig,
|
SummaryResolver, CompileReflector, JitEvaluator, CompilerConfig,
|
||||||
Console]},
|
Console]},
|
||||||
{ provide: DomElementSchemaRegistry, deps: []},
|
{ provide: DomElementSchemaRegistry, deps: []},
|
||||||
{ provide: ElementSchemaRegistry, useExisting: DomElementSchemaRegistry},
|
{ provide: ElementSchemaRegistry, useExisting: DomElementSchemaRegistry},
|
||||||
|
|
Loading…
Reference in New Issue