@angular/compiler
Version:
Angular - the compiler library
858 lines • 160 kB
JavaScript
/**
* @license
* Copyright Google LLC 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
*/
(function (factory) {
if (typeof module === "object" && typeof module.exports === "object") {
var v = factory(require, exports);
if (v !== undefined) module.exports = v;
}
else if (typeof define === "function" && define.amd) {
define("@angular/compiler/src/aot/static_reflector", ["require", "exports", "tslib", "@angular/compiler/src/compile_metadata", "@angular/compiler/src/core", "@angular/compiler/src/util", "@angular/compiler/src/aot/formatted_error", "@angular/compiler/src/aot/static_symbol"], factory);
}
})(function (require, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.StaticReflector = void 0;
var tslib_1 = require("tslib");
var compile_metadata_1 = require("@angular/compiler/src/compile_metadata");
var core_1 = require("@angular/compiler/src/core");
var util_1 = require("@angular/compiler/src/util");
var formatted_error_1 = require("@angular/compiler/src/aot/formatted_error");
var static_symbol_1 = require("@angular/compiler/src/aot/static_symbol");
var ANGULAR_CORE = '@angular/core';
var ANGULAR_ROUTER = '@angular/router';
var HIDDEN_KEY = /^\$.*\$$/;
var IGNORE = {
__symbolic: 'ignore'
};
var USE_VALUE = 'useValue';
var PROVIDE = 'provide';
var REFERENCE_SET = new Set([USE_VALUE, 'useFactory', 'data', 'id', 'loadChildren']);
var TYPEGUARD_POSTFIX = 'TypeGuard';
var USE_IF = 'UseIf';
function shouldIgnore(value) {
return value && value.__symbolic == 'ignore';
}
/**
* A static reflector implements enough of the Reflector API that is necessary to compile
* templates statically.
*/
var StaticReflector = /** @class */ (function () {
function StaticReflector(summaryResolver, symbolResolver, knownMetadataClasses, knownMetadataFunctions, errorRecorder) {
var _this = this;
if (knownMetadataClasses === void 0) { knownMetadataClasses = []; }
if (knownMetadataFunctions === void 0) { knownMetadataFunctions = []; }
this.summaryResolver = summaryResolver;
this.symbolResolver = symbolResolver;
this.errorRecorder = errorRecorder;
this.annotationCache = new Map();
this.shallowAnnotationCache = new Map();
this.propertyCache = new Map();
this.parameterCache = new Map();
this.methodCache = new Map();
this.staticCache = new Map();
this.conversionMap = new Map();
this.resolvedExternalReferences = new Map();
this.annotationForParentClassWithSummaryKind = new Map();
this.initializeConversionMap();
knownMetadataClasses.forEach(function (kc) { return _this._registerDecoratorOrConstructor(_this.getStaticSymbol(kc.filePath, kc.name), kc.ctor); });
knownMetadataFunctions.forEach(function (kf) { return _this._registerFunction(_this.getStaticSymbol(kf.filePath, kf.name), kf.fn); });
this.annotationForParentClassWithSummaryKind.set(compile_metadata_1.CompileSummaryKind.Directive, [core_1.createDirective, core_1.createComponent]);
this.annotationForParentClassWithSummaryKind.set(compile_metadata_1.CompileSummaryKind.Pipe, [core_1.createPipe]);
this.annotationForParentClassWithSummaryKind.set(compile_metadata_1.CompileSummaryKind.NgModule, [core_1.createNgModule]);
this.annotationForParentClassWithSummaryKind.set(compile_metadata_1.CompileSummaryKind.Injectable, [core_1.createInjectable, core_1.createPipe, core_1.createDirective, core_1.createComponent, core_1.createNgModule]);
}
StaticReflector.prototype.componentModuleUrl = function (typeOrFunc) {
var staticSymbol = this.findSymbolDeclaration(typeOrFunc);
return this.symbolResolver.getResourcePath(staticSymbol);
};
/**
* Invalidate the specified `symbols` on program change.
* @param symbols
*/
StaticReflector.prototype.invalidateSymbols = function (symbols) {
var e_1, _a;
try {
for (var symbols_1 = tslib_1.__values(symbols), symbols_1_1 = symbols_1.next(); !symbols_1_1.done; symbols_1_1 = symbols_1.next()) {
var symbol = symbols_1_1.value;
this.annotationCache.delete(symbol);
this.shallowAnnotationCache.delete(symbol);
this.propertyCache.delete(symbol);
this.parameterCache.delete(symbol);
this.methodCache.delete(symbol);
this.staticCache.delete(symbol);
this.conversionMap.delete(symbol);
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (symbols_1_1 && !symbols_1_1.done && (_a = symbols_1.return)) _a.call(symbols_1);
}
finally { if (e_1) throw e_1.error; }
}
};
StaticReflector.prototype.resolveExternalReference = function (ref, containingFile) {
var key = undefined;
if (!containingFile) {
key = ref.moduleName + ":" + ref.name;
var declarationSymbol_1 = this.resolvedExternalReferences.get(key);
if (declarationSymbol_1)
return declarationSymbol_1;
}
var refSymbol = this.symbolResolver.getSymbolByModule(ref.moduleName, ref.name, containingFile);
var declarationSymbol = this.findSymbolDeclaration(refSymbol);
if (!containingFile) {
this.symbolResolver.recordModuleNameForFileName(refSymbol.filePath, ref.moduleName);
this.symbolResolver.recordImportAs(declarationSymbol, refSymbol);
}
if (key) {
this.resolvedExternalReferences.set(key, declarationSymbol);
}
return declarationSymbol;
};
StaticReflector.prototype.findDeclaration = function (moduleUrl, name, containingFile) {
return this.findSymbolDeclaration(this.symbolResolver.getSymbolByModule(moduleUrl, name, containingFile));
};
StaticReflector.prototype.tryFindDeclaration = function (moduleUrl, name, containingFile) {
var _this = this;
return this.symbolResolver.ignoreErrorsFor(function () { return _this.findDeclaration(moduleUrl, name, containingFile); });
};
StaticReflector.prototype.findSymbolDeclaration = function (symbol) {
var resolvedSymbol = this.symbolResolver.resolveSymbol(symbol);
if (resolvedSymbol) {
var resolvedMetadata = resolvedSymbol.metadata;
if (resolvedMetadata && resolvedMetadata.__symbolic === 'resolved') {
resolvedMetadata = resolvedMetadata.symbol;
}
if (resolvedMetadata instanceof static_symbol_1.StaticSymbol) {
return this.findSymbolDeclaration(resolvedSymbol.metadata);
}
}
return symbol;
};
StaticReflector.prototype.tryAnnotations = function (type) {
var originalRecorder = this.errorRecorder;
this.errorRecorder = function (error, fileName) { };
try {
return this.annotations(type);
}
finally {
this.errorRecorder = originalRecorder;
}
};
StaticReflector.prototype.annotations = function (type) {
var _this = this;
return this._annotations(type, function (type, decorators) { return _this.simplify(type, decorators); }, this.annotationCache);
};
StaticReflector.prototype.shallowAnnotations = function (type) {
var _this = this;
return this._annotations(type, function (type, decorators) { return _this.simplify(type, decorators, true); }, this.shallowAnnotationCache);
};
StaticReflector.prototype._annotations = function (type, simplify, annotationCache) {
var annotations = annotationCache.get(type);
if (!annotations) {
annotations = [];
var classMetadata = this.getTypeMetadata(type);
var parentType = this.findParentType(type, classMetadata);
if (parentType) {
var parentAnnotations = this.annotations(parentType);
annotations.push.apply(annotations, tslib_1.__spread(parentAnnotations));
}
var ownAnnotations_1 = [];
if (classMetadata['decorators']) {
ownAnnotations_1 = simplify(type, classMetadata['decorators']);
if (ownAnnotations_1) {
annotations.push.apply(annotations, tslib_1.__spread(ownAnnotations_1));
}
}
if (parentType && !this.summaryResolver.isLibraryFile(type.filePath) &&
this.summaryResolver.isLibraryFile(parentType.filePath)) {
var summary = this.summaryResolver.resolveSummary(parentType);
if (summary && summary.type) {
var requiredAnnotationTypes = this.annotationForParentClassWithSummaryKind.get(summary.type.summaryKind);
var typeHasRequiredAnnotation = requiredAnnotationTypes.some(function (requiredType) { return ownAnnotations_1.some(function (ann) { return requiredType.isTypeOf(ann); }); });
if (!typeHasRequiredAnnotation) {
this.reportError(formatMetadataError(metadataError("Class " + type.name + " in " + type.filePath + " extends from a " + compile_metadata_1.CompileSummaryKind[summary.type.summaryKind] + " in another compilation unit without duplicating the decorator",
/* summary */ undefined, "Please add a " + requiredAnnotationTypes.map(function (type) { return type.ngMetadataName; })
.join(' or ') + " decorator to the class"), type), type);
}
}
}
annotationCache.set(type, annotations.filter(function (ann) { return !!ann; }));
}
return annotations;
};
StaticReflector.prototype.propMetadata = function (type) {
var _this = this;
var propMetadata = this.propertyCache.get(type);
if (!propMetadata) {
var classMetadata = this.getTypeMetadata(type);
propMetadata = {};
var parentType = this.findParentType(type, classMetadata);
if (parentType) {
var parentPropMetadata_1 = this.propMetadata(parentType);
Object.keys(parentPropMetadata_1).forEach(function (parentProp) {
propMetadata[parentProp] = parentPropMetadata_1[parentProp];
});
}
var members_1 = classMetadata['members'] || {};
Object.keys(members_1).forEach(function (propName) {
var propData = members_1[propName];
var prop = propData
.find(function (a) { return a['__symbolic'] == 'property' || a['__symbolic'] == 'method'; });
var decorators = [];
// hasOwnProperty() is used here to make sure we do not look up methods
// on `Object.prototype`.
if (propMetadata === null || propMetadata === void 0 ? void 0 : propMetadata.hasOwnProperty(propName)) {
decorators.push.apply(decorators, tslib_1.__spread(propMetadata[propName]));
}
propMetadata[propName] = decorators;
if (prop && prop['decorators']) {
decorators.push.apply(decorators, tslib_1.__spread(_this.simplify(type, prop['decorators'])));
}
});
this.propertyCache.set(type, propMetadata);
}
return propMetadata;
};
StaticReflector.prototype.parameters = function (type) {
var _this = this;
if (!(type instanceof static_symbol_1.StaticSymbol)) {
this.reportError(new Error("parameters received " + JSON.stringify(type) + " which is not a StaticSymbol"), type);
return [];
}
try {
var parameters_1 = this.parameterCache.get(type);
if (!parameters_1) {
var classMetadata = this.getTypeMetadata(type);
var parentType = this.findParentType(type, classMetadata);
var members = classMetadata ? classMetadata['members'] : null;
var ctorData = members ? members['__ctor__'] : null;
if (ctorData) {
var ctor = ctorData.find(function (a) { return a['__symbolic'] == 'constructor'; });
var rawParameterTypes = ctor['parameters'] || [];
var parameterDecorators_1 = this.simplify(type, ctor['parameterDecorators'] || []);
parameters_1 = [];
rawParameterTypes.forEach(function (rawParamType, index) {
var nestedResult = [];
var paramType = _this.trySimplify(type, rawParamType);
if (paramType)
nestedResult.push(paramType);
var decorators = parameterDecorators_1 ? parameterDecorators_1[index] : null;
if (decorators) {
nestedResult.push.apply(nestedResult, tslib_1.__spread(decorators));
}
parameters_1.push(nestedResult);
});
}
else if (parentType) {
parameters_1 = this.parameters(parentType);
}
if (!parameters_1) {
parameters_1 = [];
}
this.parameterCache.set(type, parameters_1);
}
return parameters_1;
}
catch (e) {
console.error("Failed on type " + JSON.stringify(type) + " with error " + e);
throw e;
}
};
StaticReflector.prototype._methodNames = function (type) {
var methodNames = this.methodCache.get(type);
if (!methodNames) {
var classMetadata = this.getTypeMetadata(type);
methodNames = {};
var parentType = this.findParentType(type, classMetadata);
if (parentType) {
var parentMethodNames_1 = this._methodNames(parentType);
Object.keys(parentMethodNames_1).forEach(function (parentProp) {
methodNames[parentProp] = parentMethodNames_1[parentProp];
});
}
var members_2 = classMetadata['members'] || {};
Object.keys(members_2).forEach(function (propName) {
var propData = members_2[propName];
var isMethod = propData.some(function (a) { return a['__symbolic'] == 'method'; });
methodNames[propName] = methodNames[propName] || isMethod;
});
this.methodCache.set(type, methodNames);
}
return methodNames;
};
StaticReflector.prototype._staticMembers = function (type) {
var staticMembers = this.staticCache.get(type);
if (!staticMembers) {
var classMetadata = this.getTypeMetadata(type);
var staticMemberData = classMetadata['statics'] || {};
staticMembers = Object.keys(staticMemberData);
this.staticCache.set(type, staticMembers);
}
return staticMembers;
};
StaticReflector.prototype.findParentType = function (type, classMetadata) {
var parentType = this.trySimplify(type, classMetadata['extends']);
if (parentType instanceof static_symbol_1.StaticSymbol) {
return parentType;
}
};
StaticReflector.prototype.hasLifecycleHook = function (type, lcProperty) {
if (!(type instanceof static_symbol_1.StaticSymbol)) {
this.reportError(new Error("hasLifecycleHook received " + JSON.stringify(type) + " which is not a StaticSymbol"), type);
}
try {
return !!this._methodNames(type)[lcProperty];
}
catch (e) {
console.error("Failed on type " + JSON.stringify(type) + " with error " + e);
throw e;
}
};
StaticReflector.prototype.guards = function (type) {
var e_2, _a;
if (!(type instanceof static_symbol_1.StaticSymbol)) {
this.reportError(new Error("guards received " + JSON.stringify(type) + " which is not a StaticSymbol"), type);
return {};
}
var staticMembers = this._staticMembers(type);
var result = {};
try {
for (var staticMembers_1 = tslib_1.__values(staticMembers), staticMembers_1_1 = staticMembers_1.next(); !staticMembers_1_1.done; staticMembers_1_1 = staticMembers_1.next()) {
var name_1 = staticMembers_1_1.value;
if (name_1.endsWith(TYPEGUARD_POSTFIX)) {
var property = name_1.substr(0, name_1.length - TYPEGUARD_POSTFIX.length);
var value = void 0;
if (property.endsWith(USE_IF)) {
property = name_1.substr(0, property.length - USE_IF.length);
value = USE_IF;
}
else {
value = this.getStaticSymbol(type.filePath, type.name, [name_1]);
}
result[property] = value;
}
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (staticMembers_1_1 && !staticMembers_1_1.done && (_a = staticMembers_1.return)) _a.call(staticMembers_1);
}
finally { if (e_2) throw e_2.error; }
}
return result;
};
StaticReflector.prototype._registerDecoratorOrConstructor = function (type, ctor) {
this.conversionMap.set(type, function (context, args) { return new (ctor.bind.apply(ctor, tslib_1.__spread([void 0], args)))(); });
};
StaticReflector.prototype._registerFunction = function (type, fn) {
this.conversionMap.set(type, function (context, args) { return fn.apply(undefined, args); });
};
StaticReflector.prototype.initializeConversionMap = function () {
this._registerDecoratorOrConstructor(this.findDeclaration(ANGULAR_CORE, 'Injectable'), core_1.createInjectable);
this.injectionToken = this.findDeclaration(ANGULAR_CORE, 'InjectionToken');
this.opaqueToken = this.findDeclaration(ANGULAR_CORE, 'OpaqueToken');
this.ROUTES = this.tryFindDeclaration(ANGULAR_ROUTER, 'ROUTES');
this.ANALYZE_FOR_ENTRY_COMPONENTS =
this.findDeclaration(ANGULAR_CORE, 'ANALYZE_FOR_ENTRY_COMPONENTS');
this._registerDecoratorOrConstructor(this.findDeclaration(ANGULAR_CORE, 'Host'), core_1.createHost);
this._registerDecoratorOrConstructor(this.findDeclaration(ANGULAR_CORE, 'Self'), core_1.createSelf);
this._registerDecoratorOrConstructor(this.findDeclaration(ANGULAR_CORE, 'SkipSelf'), core_1.createSkipSelf);
this._registerDecoratorOrConstructor(this.findDeclaration(ANGULAR_CORE, 'Inject'), core_1.createInject);
this._registerDecoratorOrConstructor(this.findDeclaration(ANGULAR_CORE, 'Optional'), core_1.createOptional);
this._registerDecoratorOrConstructor(this.findDeclaration(ANGULAR_CORE, 'Attribute'), core_1.createAttribute);
this._registerDecoratorOrConstructor(this.findDeclaration(ANGULAR_CORE, 'ContentChild'), core_1.createContentChild);
this._registerDecoratorOrConstructor(this.findDeclaration(ANGULAR_CORE, 'ContentChildren'), core_1.createContentChildren);
this._registerDecoratorOrConstructor(this.findDeclaration(ANGULAR_CORE, 'ViewChild'), core_1.createViewChild);
this._registerDecoratorOrConstructor(this.findDeclaration(ANGULAR_CORE, 'ViewChildren'), core_1.createViewChildren);
this._registerDecoratorOrConstructor(this.findDeclaration(ANGULAR_CORE, 'Input'), core_1.createInput);
this._registerDecoratorOrConstructor(this.findDeclaration(ANGULAR_CORE, 'Output'), core_1.createOutput);
this._registerDecoratorOrConstructor(this.findDeclaration(ANGULAR_CORE, 'Pipe'), core_1.createPipe);
this._registerDecoratorOrConstructor(this.findDeclaration(ANGULAR_CORE, 'HostBinding'), core_1.createHostBinding);
this._registerDecoratorOrConstructor(this.findDeclaration(ANGULAR_CORE, 'HostListener'), core_1.createHostListener);
this._registerDecoratorOrConstructor(this.findDeclaration(ANGULAR_CORE, 'Directive'), core_1.createDirective);
this._registerDecoratorOrConstructor(this.findDeclaration(ANGULAR_CORE, 'Component'), core_1.createComponent);
this._registerDecoratorOrConstructor(this.findDeclaration(ANGULAR_CORE, 'NgModule'), core_1.createNgModule);
// Note: Some metadata classes can be used directly with Provider.deps.
this._registerDecoratorOrConstructor(this.findDeclaration(ANGULAR_CORE, 'Host'), core_1.createHost);
this._registerDecoratorOrConstructor(this.findDeclaration(ANGULAR_CORE, 'Self'), core_1.createSelf);
this._registerDecoratorOrConstructor(this.findDeclaration(ANGULAR_CORE, 'SkipSelf'), core_1.createSkipSelf);
this._registerDecoratorOrConstructor(this.findDeclaration(ANGULAR_CORE, 'Optional'), core_1.createOptional);
};
/**
* getStaticSymbol produces a Type whose metadata is known but whose implementation is not loaded.
* All types passed to the StaticResolver should be pseudo-types returned by this method.
*
* @param declarationFile the absolute path of the file where the symbol is declared
* @param name the name of the type.
*/
StaticReflector.prototype.getStaticSymbol = function (declarationFile, name, members) {
return this.symbolResolver.getStaticSymbol(declarationFile, name, members);
};
/**
* Simplify but discard any errors
*/
StaticReflector.prototype.trySimplify = function (context, value) {
var originalRecorder = this.errorRecorder;
this.errorRecorder = function (error, fileName) { };
var result = this.simplify(context, value);
this.errorRecorder = originalRecorder;
return result;
};
/** @internal */
StaticReflector.prototype.simplify = function (context, value, lazy) {
if (lazy === void 0) { lazy = false; }
var self = this;
var scope = BindingScope.empty;
var calling = new Map();
var rootContext = context;
function simplifyInContext(context, value, depth, references) {
function resolveReferenceValue(staticSymbol) {
var resolvedSymbol = self.symbolResolver.resolveSymbol(staticSymbol);
return resolvedSymbol ? resolvedSymbol.metadata : null;
}
function simplifyEagerly(value) {
return simplifyInContext(context, value, depth, 0);
}
function simplifyLazily(value) {
return simplifyInContext(context, value, depth, references + 1);
}
function simplifyNested(nestedContext, value) {
if (nestedContext === context) {
// If the context hasn't changed let the exception propagate unmodified.
return simplifyInContext(nestedContext, value, depth + 1, references);
}
try {
return simplifyInContext(nestedContext, value, depth + 1, references);
}
catch (e) {
if (isMetadataError(e)) {
// Propagate the message text up but add a message to the chain that explains how we got
// here.
// e.chain implies e.symbol
var summaryMsg = e.chain ? 'references \'' + e.symbol.name + '\'' : errorSummary(e);
var summary = "'" + nestedContext.name + "' " + summaryMsg;
var chain = { message: summary, position: e.position, next: e.chain };
// TODO(chuckj): retrieve the position information indirectly from the collectors node
// map if the metadata is from a .ts file.
self.error({
message: e.message,
advise: e.advise,
context: e.context,
chain: chain,
symbol: nestedContext
}, context);
}
else {
// It is probably an internal error.
throw e;
}
}
}
function simplifyCall(functionSymbol, targetFunction, args, targetExpression) {
if (targetFunction && targetFunction['__symbolic'] == 'function') {
if (calling.get(functionSymbol)) {
self.error({
message: 'Recursion is not supported',
summary: "called '" + functionSymbol.name + "' recursively",
value: targetFunction
}, functionSymbol);
}
try {
var value_1 = targetFunction['value'];
if (value_1 && (depth != 0 || value_1.__symbolic != 'error')) {
var parameters = targetFunction['parameters'];
var defaults = targetFunction.defaults;
args = args.map(function (arg) { return simplifyNested(context, arg); })
.map(function (arg) { return shouldIgnore(arg) ? undefined : arg; });
if (defaults && defaults.length > args.length) {
args.push.apply(args, tslib_1.__spread(defaults.slice(args.length).map(function (value) { return simplify(value); })));
}
calling.set(functionSymbol, true);
var functionScope = BindingScope.build();
for (var i = 0; i < parameters.length; i++) {
functionScope.define(parameters[i], args[i]);
}
var oldScope = scope;
var result_1;
try {
scope = functionScope.done();
result_1 = simplifyNested(functionSymbol, value_1);
}
finally {
scope = oldScope;
}
return result_1;
}
}
finally {
calling.delete(functionSymbol);
}
}
if (depth === 0) {
// If depth is 0 we are evaluating the top level expression that is describing element
// decorator. In this case, it is a decorator we don't understand, such as a custom
// non-angular decorator, and we should just ignore it.
return IGNORE;
}
var position = undefined;
if (targetExpression && targetExpression.__symbolic == 'resolved') {
var line = targetExpression.line;
var character = targetExpression.character;
var fileName = targetExpression.fileName;
if (fileName != null && line != null && character != null) {
position = { fileName: fileName, line: line, column: character };
}
}
self.error({
message: FUNCTION_CALL_NOT_SUPPORTED,
context: functionSymbol,
value: targetFunction,
position: position
}, context);
}
function simplify(expression) {
var e_3, _a, e_4, _b;
if (isPrimitive(expression)) {
return expression;
}
if (Array.isArray(expression)) {
var result_2 = [];
try {
for (var _c = tslib_1.__values(expression), _d = _c.next(); !_d.done; _d = _c.next()) {
var item = _d.value;
// Check for a spread expression
if (item && item.__symbolic === 'spread') {
// We call with references as 0 because we require the actual value and cannot
// tolerate a reference here.
var spreadArray = simplifyEagerly(item.expression);
if (Array.isArray(spreadArray)) {
try {
for (var spreadArray_1 = (e_4 = void 0, tslib_1.__values(spreadArray)), spreadArray_1_1 = spreadArray_1.next(); !spreadArray_1_1.done; spreadArray_1_1 = spreadArray_1.next()) {
var spreadItem = spreadArray_1_1.value;
result_2.push(spreadItem);
}
}
catch (e_4_1) { e_4 = { error: e_4_1 }; }
finally {
try {
if (spreadArray_1_1 && !spreadArray_1_1.done && (_b = spreadArray_1.return)) _b.call(spreadArray_1);
}
finally { if (e_4) throw e_4.error; }
}
continue;
}
}
var value_2 = simplify(item);
if (shouldIgnore(value_2)) {
continue;
}
result_2.push(value_2);
}
}
catch (e_3_1) { e_3 = { error: e_3_1 }; }
finally {
try {
if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
}
finally { if (e_3) throw e_3.error; }
}
return result_2;
}
if (expression instanceof static_symbol_1.StaticSymbol) {
// Stop simplification at builtin symbols or if we are in a reference context and
// the symbol doesn't have members.
if (expression === self.injectionToken || self.conversionMap.has(expression) ||
(references > 0 && !expression.members.length)) {
return expression;
}
else {
var staticSymbol = expression;
var declarationValue = resolveReferenceValue(staticSymbol);
if (declarationValue != null) {
return simplifyNested(staticSymbol, declarationValue);
}
else {
return staticSymbol;
}
}
}
if (expression) {
if (expression['__symbolic']) {
var staticSymbol = void 0;
switch (expression['__symbolic']) {
case 'binop':
var left = simplify(expression['left']);
if (shouldIgnore(left))
return left;
var right = simplify(expression['right']);
if (shouldIgnore(right))
return right;
switch (expression['operator']) {
case '&&':
return left && right;
case '||':
return left || right;
case '|':
return left | right;
case '^':
return left ^ right;
case '&':
return left & right;
case '==':
return left == right;
case '!=':
return left != right;
case '===':
return left === right;
case '!==':
return left !== right;
case '<':
return left < right;
case '>':
return left > right;
case '<=':
return left <= right;
case '>=':
return left >= right;
case '<<':
return left << right;
case '>>':
return left >> right;
case '+':
return left + right;
case '-':
return left - right;
case '*':
return left * right;
case '/':
return left / right;
case '%':
return left % right;
}
return null;
case 'if':
var condition = simplify(expression['condition']);
return condition ? simplify(expression['thenExpression']) :
simplify(expression['elseExpression']);
case 'pre':
var operand = simplify(expression['operand']);
if (shouldIgnore(operand))
return operand;
switch (expression['operator']) {
case '+':
return operand;
case '-':
return -operand;
case '!':
return !operand;
case '~':
return ~operand;
}
return null;
case 'index':
var indexTarget = simplifyEagerly(expression['expression']);
var index = simplifyEagerly(expression['index']);
if (indexTarget && isPrimitive(index))
return indexTarget[index];
return null;
case 'select':
var member = expression['member'];
var selectContext = context;
var selectTarget = simplify(expression['expression']);
if (selectTarget instanceof static_symbol_1.StaticSymbol) {
var members = selectTarget.members.concat(member);
selectContext =
self.getStaticSymbol(selectTarget.filePath, selectTarget.name, members);
var declarationValue = resolveReferenceValue(selectContext);
if (declarationValue != null) {
return simplifyNested(selectContext, declarationValue);
}
else {
return selectContext;
}
}
if (selectTarget && isPrimitive(member))
return simplifyNested(selectContext, selectTarget[member]);
return null;
case 'reference':
// Note: This only has to deal with variable references, as symbol references have
// been converted into 'resolved'
// in the StaticSymbolResolver.
var name_2 = expression['name'];
var localValue = scope.resolve(name_2);
if (localValue != BindingScope.missing) {
return localValue;
}
break;
case 'resolved':
try {
return simplify(expression.symbol);
}
catch (e) {
// If an error is reported evaluating the symbol record the position of the
// reference in the error so it can
// be reported in the error message generated from the exception.
if (isMetadataError(e) && expression.fileName != null &&
expression.line != null && expression.character != null) {
e.position = {
fileName: expression.fileName,
line: expression.line,
column: expression.character
};
}
throw e;
}
case 'class':
return context;
case 'function':
return context;
case 'new':
case 'call':
// Determine if the function is a built-in conversion
staticSymbol = simplifyInContext(context, expression['expression'], depth + 1, /* references */ 0);
if (staticSymbol instanceof static_symbol_1.StaticSymbol) {
if (staticSymbol === self.injectionToken || staticSymbol === self.opaqueToken) {
// if somebody calls new InjectionToken, don't create an InjectionToken,
// but rather return the symbol to which the InjectionToken is assigned to.
// OpaqueToken is supported too as it is required by the language service to
// support v4 and prior versions of Angular.
return context;
}
var argExpressions = expression['arguments'] || [];
var converter = self.conversionMap.get(staticSymbol);
if (converter) {
var args = argExpressions.map(function (arg) { return simplifyNested(context, arg); })
.map(function (arg) { return shouldIgnore(arg) ? undefined : arg; });
return converter(context, args);
}
else {
// Determine if the function is one we can simplify.
var targetFunction = resolveReferenceValue(staticSymbol);
return simplifyCall(staticSymbol, targetFunction, argExpressions, expression['expression']);
}
}
return IGNORE;
case 'error':
var message = expression.message;
if (expression['line'] != null) {
self.error({
message: message,
context: expression.context,
value: expression,
position: {
fileName: expression['fileName'],
line: expression['line'],
column: expression['character']
}
}, context);
}
else {
self.error({ message: message, context: expression.context }, context);
}
return IGNORE;
case 'ignore':
return expression;
}
return null;
}
return mapStringMap(expression, function (value, name) {
if (REFERENCE_SET.has(name)) {
if (name === USE_VALUE && PROVIDE in expression) {
// If this is a provider expression, check for special tokens that need the value
// during analysis.
var provide = simplify(expression.provide);
if (provide === self.ROUTES || provide == self.ANALYZE_FOR_ENTRY_COMPONENTS) {
return simplify(value);
}
}
return simplifyLazily(value);
}
return simplify(value);
});
}
return IGNORE;
}
return simplify(value);
}
var result;
try {
result = simplifyInContext(context, value, 0, lazy ? 1 : 0);
}
catch (e) {
if (this.errorRecorder) {
this.reportError(e, context);
}
else {
throw formatMetadataError(e, context);
}
}
if (shouldIgnore(result)) {
return undefined;
}
return result;
};
StaticReflector.prototype.getTypeMetadata = function (type) {
var resolvedSymbol = this.symbolResolver.resolveSymbol(type);
return resolvedSymbol && resolvedSymbol.metadata ? resolvedSymbol.metadata :
{ __symbolic: 'class' };
};
StaticReflector.prototype.reportError = function (error, context, path) {
if (this.errorRecorder) {
this.errorRecorder(formatMetadataError(error, context), (context && context.filePath) || path);
}
else {
throw error;
}
};
StaticReflector.prototype.error = function (_a, reportingContext) {
var message = _a.message, summary = _a.summary, advise = _a.advise, position = _a.position, context = _a.context, value = _a.value, symbol = _a.symbol, chain = _a.chain;
this.reportError(metadataError(message, summary, advise, position, symbol, context, chain), reportingContext);
};
return StaticReflector;
}());
exports.StaticReflector = StaticReflector;
var METADATA_ERROR = 'ngMetadataError';
function metadataError(message, summary, advise, position, symbol, context, chain) {
var error = util_1.syntaxError(message);
error[METADATA_ERROR] = true;
if (advise)
error.advise = advise;
if (position)
error.position = position;
if (summary)
error.summary = summary;
if (context)
error.context = context;
if (chain)
error.chain = chain;
if (symbol)
error.symbol = symbol;
return error;
}
function isMetadataError(error) {
return !!error[METADATA_ERROR];
}
var REFERENCE_TO_NONEXPORTED_CLASS = 'Reference to non-exported class';
var VARIABLE_NOT_INITIALIZED = 'Variable not initialized';
var DESTRUCTURE_NOT_SUPPORTED = 'Destructuring not supported';
var COULD_NOT_RESOLVE_TYPE = 'Could not resolve type';
var FUNCTION_CALL_NOT_SUPPORTED = 'Function call not supported';
var REFERENCE_TO_LOCAL_SYMBOL = 'Reference to a local symbol';
var LAMBDA_NOT_SUPPORTED = 'Lambda not supported';
function expandedMessage(message, context) {
switch (message) {
case REFERENCE_TO_NONEXPORTED_CLASS:
if (context && context.className) {
return "References to a non-exported class are not supported in decorators but " + context.className + " was referenced.";
}
break;
case VARIABLE_NOT_INITIALIZED:
return 'Only initialized variab