style(lint): re-format modules/@angular

This commit is contained in:
Alex Eagle
2016-06-08 16:38:52 -07:00
parent bbed364e7b
commit f39c9c9e75
589 changed files with 21829 additions and 24259 deletions

View File

@ -3,36 +3,8 @@
* @description
* Starting point to import all compiler APIs.
*/
export {COMPILER_PROVIDERS, CompileDiDependencyMetadata, CompileDirectiveMetadata, CompileFactoryMetadata, CompileIdentifierMetadata, CompileMetadataWithIdentifier, CompileMetadataWithType, CompilePipeMetadata, CompileProviderMetadata, CompileQueryMetadata, CompileTemplateMetadata, CompileTokenMetadata, CompileTypeMetadata, CompilerConfig, DEFAULT_PACKAGE_URL_PROVIDER, DirectiveResolver, NormalizedComponentWithViewDirectives, OfflineCompiler, PipeResolver, RenderTypes, RuntimeCompiler, SourceModule, TEMPLATE_TRANSFORMS, UrlResolver, ViewResolver, XHR, createOfflineCompileUrlResolver} from './src/compiler';
export {ElementSchemaRegistry} from './src/schema/element_schema_registry';
export {
COMPILER_PROVIDERS,
TEMPLATE_TRANSFORMS,
CompilerConfig,
RenderTypes,
UrlResolver,
DEFAULT_PACKAGE_URL_PROVIDER,
createOfflineCompileUrlResolver,
XHR,
ViewResolver,
DirectiveResolver,
PipeResolver,
SourceModule,
NormalizedComponentWithViewDirectives,
OfflineCompiler,
RuntimeCompiler,
CompileMetadataWithIdentifier,
CompileMetadataWithType,
CompileIdentifierMetadata,
CompileDiDependencyMetadata,
CompileProviderMetadata,
CompileFactoryMetadata,
CompileTokenMetadata,
CompileTypeMetadata,
CompileQueryMetadata,
CompileTemplateMetadata,
CompileDirectiveMetadata,
CompilePipeMetadata
} from './src/compiler';
export * from './src/template_ast';
export * from './private_export';

View File

@ -81,7 +81,8 @@ export var DEFAULT_STATE = r.DEFAULT_STATE;
export var EMPTY_STATE = r.EMPTY_STATE;
export var FILL_STYLE_FLAG = r.FILL_STYLE_FLAG;
export var balanceAnimationStyles: typeof t.balanceAnimationStyles = r.balanceAnimationStyles;
export var balanceAnimationKeyframes: typeof t.balanceAnimationKeyframes = r.balanceAnimationKeyframes;
export var balanceAnimationKeyframes: typeof t.balanceAnimationKeyframes =
r.balanceAnimationKeyframes;
export var flattenStyles: typeof t.flattenStyles = r.flattenStyles;
export var clearStyles: typeof t.clearStyles = r.clearStyles;
export var collectAndResolveStyles: typeof r.collectAndResolveStyles = r.collectAndResolveStyles;

View File

@ -1,95 +1,95 @@
import * as selector from './src/selector';
import * as path_util from './src/output/path_util';
import * as metadata_resolver from './src/metadata_resolver';
import * as html_parser from './src/html_parser';
import * as i18n_html_parser from './src/i18n/i18n_html_parser';
import * as directive_normalizer from './src/directive_normalizer';
import * as lexer from './src/expression_parser/lexer';
import * as parser from './src/expression_parser/parser';
import * as template_parser from './src/template_parser';
import * as dom_element_schema_registry from './src/schema/dom_element_schema_registry';
import * as style_compiler from './src/style_compiler';
import * as view_compiler from './src/view_compiler/view_compiler';
import * as ts_emitter from './src/output/ts_emitter';
import * as i18n_extractor from './src/i18n/message_extractor';
import * as html_parser from './src/html_parser';
import * as i18n_html_parser from './src/i18n/i18n_html_parser';
import * as i18n_message from './src/i18n/message';
import * as i18n_extractor from './src/i18n/message_extractor';
import * as xmb_serializer from './src/i18n/xmb_serializer';
import * as metadata_resolver from './src/metadata_resolver';
import * as path_util from './src/output/path_util';
import * as ts_emitter from './src/output/ts_emitter';
import * as parse_util from './src/parse_util';
import * as dom_element_schema_registry from './src/schema/dom_element_schema_registry';
import * as selector from './src/selector';
import * as style_compiler from './src/style_compiler';
import * as template_parser from './src/template_parser';
import * as view_compiler from './src/view_compiler/view_compiler';
export namespace __compiler_private__ {
export type SelectorMatcher = selector.SelectorMatcher;
export var SelectorMatcher = selector.SelectorMatcher;
export type SelectorMatcher = selector.SelectorMatcher;
export var SelectorMatcher = selector.SelectorMatcher;
export type CssSelector = selector.CssSelector;
export var CssSelector = selector.CssSelector;
export type CssSelector = selector.CssSelector;
export var CssSelector = selector.CssSelector;
export type AssetUrl = path_util.AssetUrl;
export var AssetUrl = path_util.AssetUrl;
export type AssetUrl = path_util.AssetUrl;
export var AssetUrl = path_util.AssetUrl;
export type ImportGenerator = path_util.ImportGenerator;
export var ImportGenerator = path_util.ImportGenerator;
export type ImportGenerator = path_util.ImportGenerator;
export var ImportGenerator = path_util.ImportGenerator;
export type CompileMetadataResolver = metadata_resolver.CompileMetadataResolver;
export var CompileMetadataResolver = metadata_resolver.CompileMetadataResolver;
export type CompileMetadataResolver = metadata_resolver.CompileMetadataResolver;
export var CompileMetadataResolver = metadata_resolver.CompileMetadataResolver;
export type HtmlParser = html_parser.HtmlParser;
export var HtmlParser = html_parser.HtmlParser;
export type HtmlParser = html_parser.HtmlParser;
export var HtmlParser = html_parser.HtmlParser;
export type I18nHtmlParser = i18n_html_parser.I18nHtmlParser;
export var I18nHtmlParser = i18n_html_parser.I18nHtmlParser;
export type I18nHtmlParser = i18n_html_parser.I18nHtmlParser;
export var I18nHtmlParser = i18n_html_parser.I18nHtmlParser;
export type ExtractionResult = i18n_extractor.ExtractionResult;
export var ExtractionResult = i18n_extractor.ExtractionResult;
export type ExtractionResult = i18n_extractor.ExtractionResult;
export var ExtractionResult = i18n_extractor.ExtractionResult;
export type Message = i18n_message.Message;
export var Message = i18n_message.Message;
export type Message = i18n_message.Message;
export var Message = i18n_message.Message;
export type MessageExtractor = i18n_extractor.MessageExtractor;
export var MessageExtractor = i18n_extractor.MessageExtractor;
export type MessageExtractor = i18n_extractor.MessageExtractor;
export var MessageExtractor = i18n_extractor.MessageExtractor;
export var removeDuplicates = i18n_extractor.removeDuplicates;
export var serializeXmb = xmb_serializer.serializeXmb;
export var deserializeXmb = xmb_serializer.deserializeXmb;
export var removeDuplicates = i18n_extractor.removeDuplicates;
export type DirectiveNormalizer = directive_normalizer.DirectiveNormalizer;
export var DirectiveNormalizer = directive_normalizer.DirectiveNormalizer;
export var serializeXmb = xmb_serializer.serializeXmb;
export var deserializeXmb = xmb_serializer.deserializeXmb;
export type Lexer = lexer.Lexer;
export var Lexer = lexer.Lexer;
export type DirectiveNormalizer = directive_normalizer.DirectiveNormalizer;
export var DirectiveNormalizer = directive_normalizer.DirectiveNormalizer;
export type Parser = parser.Parser;
export var Parser = parser.Parser;
export type Lexer = lexer.Lexer;
export var Lexer = lexer.Lexer;
export type ParseLocation = parse_util.ParseLocation;
export var ParseLocation = parse_util.ParseLocation;
export type Parser = parser.Parser;
export var Parser = parser.Parser;
export type ParseError = parse_util.ParseError;
export var ParseError = parse_util.ParseError;
export type ParseLocation = parse_util.ParseLocation;
export var ParseLocation = parse_util.ParseLocation;
export type ParseErrorLevel = parse_util.ParseErrorLevel;
export var ParseErrorLevel = parse_util.ParseErrorLevel;
export type ParseError = parse_util.ParseError;
export var ParseError = parse_util.ParseError;
export type ParseSourceFile = parse_util.ParseSourceFile;
export var ParseSourceFile = parse_util.ParseSourceFile;
export type ParseErrorLevel = parse_util.ParseErrorLevel;
export var ParseErrorLevel = parse_util.ParseErrorLevel;
export type ParseSourceSpan = parse_util.ParseSourceSpan;
export var ParseSourceSpan = parse_util.ParseSourceSpan;
export type ParseSourceFile = parse_util.ParseSourceFile;
export var ParseSourceFile = parse_util.ParseSourceFile;
export type TemplateParser = template_parser.TemplateParser;
export var TemplateParser = template_parser.TemplateParser;
export type ParseSourceSpan = parse_util.ParseSourceSpan;
export var ParseSourceSpan = parse_util.ParseSourceSpan;
export type TemplateParseResult = template_parser.TemplateParseResult;
export type TemplateParser = template_parser.TemplateParser;
export var TemplateParser = template_parser.TemplateParser;
export type DomElementSchemaRegistry = dom_element_schema_registry.DomElementSchemaRegistry;
export var DomElementSchemaRegistry = dom_element_schema_registry.DomElementSchemaRegistry;
export type TemplateParseResult = template_parser.TemplateParseResult;
export type StyleCompiler = style_compiler.StyleCompiler;
export var StyleCompiler = style_compiler.StyleCompiler;
export type DomElementSchemaRegistry = dom_element_schema_registry.DomElementSchemaRegistry;
export var DomElementSchemaRegistry = dom_element_schema_registry.DomElementSchemaRegistry;
export type ViewCompiler = view_compiler.ViewCompiler;
export var ViewCompiler = view_compiler.ViewCompiler;
export type StyleCompiler = style_compiler.StyleCompiler;
export var StyleCompiler = style_compiler.StyleCompiler;
export type TypeScriptEmitter = ts_emitter.TypeScriptEmitter;
export var TypeScriptEmitter = ts_emitter.TypeScriptEmitter;
export type ViewCompiler = view_compiler.ViewCompiler;
export var ViewCompiler = view_compiler.ViewCompiler;
export type TypeScriptEmitter = ts_emitter.TypeScriptEmitter;
export var TypeScriptEmitter = ts_emitter.TypeScriptEmitter;
}

View File

@ -20,9 +20,9 @@ export interface AnimationAstVisitor {
}
export class AnimationEntryAst extends AnimationAst {
constructor(public name: string,
public stateDeclarations: AnimationStateDeclarationAst[],
public stateTransitions: AnimationStateTransitionAst[]) {
constructor(
public name: string, public stateDeclarations: AnimationStateDeclarationAst[],
public stateTransitions: AnimationStateTransitionAst[]) {
super();
}
visit(visitor: AnimationAstVisitor, context: any): any {
@ -31,9 +31,7 @@ export class AnimationEntryAst extends AnimationAst {
}
export class AnimationStateDeclarationAst extends AnimationStateAst {
constructor(public stateName: string, public styles: AnimationStylesAst) {
super();
}
constructor(public stateName: string, public styles: AnimationStylesAst) { super(); }
visit(visitor: AnimationAstVisitor, context: any): any {
return visitor.visitAnimationStateDeclaration(this, context);
}
@ -44,7 +42,9 @@ export class AnimationStateTransitionExpression {
}
export class AnimationStateTransitionAst extends AnimationStateAst {
constructor(public stateChanges: AnimationStateTransitionExpression[], public animation: AnimationSequenceAst) {
constructor(
public stateChanges: AnimationStateTransitionExpression[],
public animation: AnimationSequenceAst) {
super();
}
visit(visitor: AnimationAstVisitor, context: any): any {
@ -53,11 +53,9 @@ export class AnimationStateTransitionAst extends AnimationStateAst {
}
export class AnimationStepAst extends AnimationAst {
constructor(public startingStyles: AnimationStylesAst,
public keyframes: AnimationKeyframeAst[],
public duration: number,
public delay: number,
public easing: string) {
constructor(
public startingStyles: AnimationStylesAst, public keyframes: AnimationKeyframeAst[],
public duration: number, public delay: number, public easing: string) {
super();
}
visit(visitor: AnimationAstVisitor, context: any): any {

View File

@ -1,41 +1,21 @@
import {BaseException} from '../facade/exceptions';
import {ListWrapper, Map, StringMapWrapper} from '../facade/collection';
import {isPresent, isBlank, isArray} from '../facade/lang';
import {AUTO_STYLE} from '@angular/core';
import {ANY_STATE, DEFAULT_STATE, EMPTY_STATE} from '../../core_private';
import {CompileDirectiveMetadata} from '../compile_metadata';
import {ListWrapper, Map, StringMapWrapper} from '../facade/collection';
import {BaseException} from '../facade/exceptions';
import {isArray, isBlank, isPresent} from '../facade/lang';
import {Identifiers} from '../identifiers';
import * as o from '../output/output_ast';
import {AUTO_STYLE} from '@angular/core';
import {DEFAULT_STATE, ANY_STATE, EMPTY_STATE} from '../../core_private';
import {
AnimationParseError,
ParsedAnimationResult,
parseAnimationEntry
} from './animation_parser';
import {CompileDirectiveMetadata} from "../compile_metadata";
import {
AnimationAst,
AnimationEntryAst,
AnimationStateAst,
AnimationStateDeclarationAst,
AnimationStateTransitionAst,
AnimationKeyframeAst,
AnimationStylesAst,
AnimationSequenceAst,
AnimationGroupAst,
AnimationStepAst,
AnimationAstVisitor
} from './animation_ast';
import {AnimationAst, AnimationAstVisitor, AnimationEntryAst, AnimationGroupAst, AnimationKeyframeAst, AnimationSequenceAst, AnimationStateAst, AnimationStateDeclarationAst, AnimationStateTransitionAst, AnimationStepAst, AnimationStylesAst} from './animation_ast';
import {AnimationParseError, ParsedAnimationResult, parseAnimationEntry} from './animation_parser';
export class CompiledAnimation {
constructor(public name: string,
public statesMapStatement: o.Statement,
public statesVariableName: string,
public fnStatement: o.Statement,
public fnVariable: o.Expression) {}
constructor(
public name: string, public statesMapStatement: o.Statement,
public statesVariableName: string, public fnStatement: o.Statement,
public fnVariable: o.Expression) {}
}
export class AnimationCompiler {
@ -46,11 +26,12 @@ export class AnimationCompiler {
var result = parseAnimationEntry(entry);
if (result.errors.length > 0) {
var errorMessage = '';
result.errors.forEach((error: AnimationParseError) => { errorMessage += "\n- " + error.msg; });
result.errors.forEach(
(error: AnimationParseError) => { errorMessage += '\n- ' + error.msg; });
// todo (matsko): include the component name when throwing
throw new BaseException(
`Unable to parse the animation sequence for "${entry.name}" due to the following errors: ` +
errorMessage);
`Unable to parse the animation sequence for "${entry.name}" due to the following errors: ` +
errorMessage);
}
var factoryName = `${component.type.name}_${entry.name}_${index}`;
@ -86,8 +67,7 @@ class _AnimationBuilder implements AnimationAstVisitor {
this._statesMapVar = o.variable(this._statesMapVarName);
}
visitAnimationStyles(ast: AnimationStylesAst,
context: _AnimationBuilderContext): o.Expression {
visitAnimationStyles(ast: AnimationStylesAst, context: _AnimationBuilderContext): o.Expression {
var stylesArr: any[] /** TODO #9100 */ = [];
if (context.isExpectingFirstStyleStep) {
stylesArr.push(_ANIMATION_START_STATE_STYLES_VAR);
@ -95,22 +75,21 @@ class _AnimationBuilder implements AnimationAstVisitor {
}
ast.styles.forEach(entry => {
stylesArr.push(o.literalMap(StringMapWrapper.keys(entry).map(key => [key, o.literal(entry[key])])));
stylesArr.push(
o.literalMap(StringMapWrapper.keys(entry).map(key => [key, o.literal(entry[key])])));
});
return o.importExpr(Identifiers.AnimationStyles).instantiate([
o.importExpr(Identifiers.collectAndResolveStyles).callFn([
_ANIMATION_COLLECTED_STYLES,
o.literalArr(stylesArr)
_ANIMATION_COLLECTED_STYLES, o.literalArr(stylesArr)
])
]);
}
visitAnimationKeyframe(ast: AnimationKeyframeAst,
context: _AnimationBuilderContext): o.Expression {
visitAnimationKeyframe(ast: AnimationKeyframeAst, context: _AnimationBuilderContext):
o.Expression {
return o.importExpr(Identifiers.AnimationKeyframe).instantiate([
o.literal(ast.offset),
ast.styles.visit(this, context)
o.literal(ast.offset), ast.styles.visit(this, context)
]);
}
@ -120,18 +99,17 @@ class _AnimationBuilder implements AnimationAstVisitor {
}
var startingStylesExpr = ast.startingStyles.visit(this, context);
var keyframeExpressions = ast.keyframes.map(keyframeEntry => keyframeEntry.visit(this, context));
var keyframeExpressions =
ast.keyframes.map(keyframeEntry => keyframeEntry.visit(this, context));
return this._callAnimateMethod(ast, startingStylesExpr, o.literalArr(keyframeExpressions));
}
/** @internal */
_visitEndStateAnimation(ast: AnimationStepAst,
context: _AnimationBuilderContext): o.Expression {
_visitEndStateAnimation(ast: AnimationStepAst, context: _AnimationBuilderContext): o.Expression {
var startingStylesExpr = ast.startingStyles.visit(this, context);
var keyframeExpressions = ast.keyframes.map(keyframe => keyframe.visit(this, context));
var keyframesExpr = o.importExpr(Identifiers.balanceAnimationKeyframes).callFn([
_ANIMATION_COLLECTED_STYLES,
_ANIMATION_END_STATE_STYLES_VAR,
_ANIMATION_COLLECTED_STYLES, _ANIMATION_END_STATE_STYLES_VAR,
o.literalArr(keyframeExpressions)
]);
@ -139,41 +117,41 @@ class _AnimationBuilder implements AnimationAstVisitor {
}
/** @internal */
_callAnimateMethod(ast: AnimationStepAst, startingStylesExpr: any /** TODO #9100 */, keyframesExpr: any /** TODO #9100 */) {
_callAnimateMethod(
ast: AnimationStepAst, startingStylesExpr: any /** TODO #9100 */,
keyframesExpr: any /** TODO #9100 */) {
return _ANIMATION_FACTORY_RENDERER_VAR.callMethod('animate', [
_ANIMATION_FACTORY_ELEMENT_VAR,
startingStylesExpr,
keyframesExpr,
o.literal(ast.duration),
o.literal(ast.delay),
o.literal(ast.easing)
_ANIMATION_FACTORY_ELEMENT_VAR, startingStylesExpr, keyframesExpr, o.literal(ast.duration),
o.literal(ast.delay), o.literal(ast.easing)
]);
}
visitAnimationSequence(ast: AnimationSequenceAst,
context: _AnimationBuilderContext): o.Expression {
visitAnimationSequence(ast: AnimationSequenceAst, context: _AnimationBuilderContext):
o.Expression {
var playerExprs = ast.steps.map(step => step.visit(this, context));
return o.importExpr(Identifiers.AnimationSequencePlayer).instantiate([
o.literalArr(playerExprs)]);
return o.importExpr(Identifiers.AnimationSequencePlayer).instantiate([o.literalArr(
playerExprs)]);
}
visitAnimationGroup(ast: AnimationGroupAst, context: _AnimationBuilderContext): o.Expression {
var playerExprs = ast.steps.map(step => step.visit(this, context));
return o.importExpr(Identifiers.AnimationGroupPlayer).instantiate([
o.literalArr(playerExprs)]);
return o.importExpr(Identifiers.AnimationGroupPlayer).instantiate([o.literalArr(playerExprs)]);
}
visitAnimationStateDeclaration(ast: AnimationStateDeclarationAst, context: _AnimationBuilderContext): void {
var flatStyles: {[key: string]: string|number} = {};
visitAnimationStateDeclaration(
ast: AnimationStateDeclarationAst, context: _AnimationBuilderContext): void {
var flatStyles: {[key: string]: string | number} = {};
_getStylesArray(ast).forEach((entry: any /** TODO #9100 */) => {
StringMapWrapper.forEach(entry, (value: any /** TODO #9100 */, key: any /** TODO #9100 */) => {
flatStyles[key] = value;
});
StringMapWrapper.forEach(
entry, (value: any /** TODO #9100 */, key: any /** TODO #9100 */) => {
flatStyles[key] = value;
});
});
context.stateMap.registerState(ast.stateName, flatStyles);
}
visitAnimationStateTransition(ast: AnimationStateTransitionAst, context: _AnimationBuilderContext): any {
visitAnimationStateTransition(
ast: AnimationStateTransitionAst, context: _AnimationBuilderContext): any {
var steps = ast.animation.steps;
var lastStep = steps[steps.length - 1];
if (_isEndStateAnimateStep(lastStep)) {
@ -186,9 +164,8 @@ class _AnimationBuilder implements AnimationAstVisitor {
ast.stateChanges.forEach(stateChange => {
stateChangePreconditions.push(
_compareToAnimationStateExpr(_ANIMATION_CURRENT_STATE_VAR, stateChange.fromState)
.and(_compareToAnimationStateExpr(_ANIMATION_NEXT_STATE_VAR, stateChange.toState))
);
_compareToAnimationStateExpr(_ANIMATION_CURRENT_STATE_VAR, stateChange.fromState)
.and(_compareToAnimationStateExpr(_ANIMATION_NEXT_STATE_VAR, stateChange.toState)));
if (stateChange.fromState != ANY_STATE) {
context.stateMap.registerState(stateChange.fromState);
@ -201,56 +178,52 @@ class _AnimationBuilder implements AnimationAstVisitor {
var animationPlayerExpr = ast.animation.visit(this, context);
var reducedStateChangesPrecondition = stateChangePreconditions.reduce((a,b) => a.or(b));
var precondition = _ANIMATION_PLAYER_VAR.equals(o.NULL_EXPR).and(reducedStateChangesPrecondition);
var reducedStateChangesPrecondition = stateChangePreconditions.reduce((a, b) => a.or(b));
var precondition =
_ANIMATION_PLAYER_VAR.equals(o.NULL_EXPR).and(reducedStateChangesPrecondition);
return new o.IfStmt(precondition, [
_ANIMATION_PLAYER_VAR.set(animationPlayerExpr).toStmt()
]);
return new o.IfStmt(precondition, [_ANIMATION_PLAYER_VAR.set(animationPlayerExpr).toStmt()]);
}
visitAnimationEntry(ast: AnimationEntryAst, context: _AnimationBuilderContext): any {
//visit each of the declarations first to build the context state map
// visit each of the declarations first to build the context state map
ast.stateDeclarations.forEach(def => def.visit(this, context));
//this should always be defined even if the user overrides it
// this should always be defined even if the user overrides it
context.stateMap.registerState(DEFAULT_STATE, {});
var statements: any[] /** TODO #9100 */ = [];
statements.push(
_ANIMATION_FACTORY_VIEW_VAR.callMethod('cancelActiveAnimation', [
_ANIMATION_FACTORY_ELEMENT_VAR,
o.literal(this.animationName),
_ANIMATION_NEXT_STATE_VAR.equals(o.literal(EMPTY_STATE))
]).toStmt());
statements.push(_ANIMATION_FACTORY_VIEW_VAR
.callMethod(
'cancelActiveAnimation',
[
_ANIMATION_FACTORY_ELEMENT_VAR, o.literal(this.animationName),
_ANIMATION_NEXT_STATE_VAR.equals(o.literal(EMPTY_STATE))
])
.toStmt());
statements.push(_ANIMATION_COLLECTED_STYLES.set(EMPTY_MAP).toDeclStmt());
statements.push(_ANIMATION_PLAYER_VAR.set(o.NULL_EXPR).toDeclStmt());
statements.push(
_ANIMATION_DEFAULT_STATE_VAR.set(
this._statesMapVar.key(o.literal(DEFAULT_STATE))
).toDeclStmt());
_ANIMATION_DEFAULT_STATE_VAR.set(this._statesMapVar.key(o.literal(DEFAULT_STATE)))
.toDeclStmt());
statements.push(
_ANIMATION_START_STATE_STYLES_VAR.set(
this._statesMapVar.key(_ANIMATION_CURRENT_STATE_VAR)
).toDeclStmt());
_ANIMATION_START_STATE_STYLES_VAR.set(this._statesMapVar.key(_ANIMATION_CURRENT_STATE_VAR))
.toDeclStmt());
statements.push(new o.IfStmt(
_ANIMATION_START_STATE_STYLES_VAR.equals(o.NULL_EXPR),
[_ANIMATION_START_STATE_STYLES_VAR.set(_ANIMATION_DEFAULT_STATE_VAR).toStmt()]));
statements.push(
new o.IfStmt(_ANIMATION_START_STATE_STYLES_VAR.equals(o.NULL_EXPR), [
_ANIMATION_START_STATE_STYLES_VAR.set(_ANIMATION_DEFAULT_STATE_VAR).toStmt()
]));
_ANIMATION_END_STATE_STYLES_VAR.set(this._statesMapVar.key(_ANIMATION_NEXT_STATE_VAR))
.toDeclStmt());
statements.push(
_ANIMATION_END_STATE_STYLES_VAR.set(
this._statesMapVar.key(_ANIMATION_NEXT_STATE_VAR)
).toDeclStmt());
statements.push(
new o.IfStmt(_ANIMATION_END_STATE_STYLES_VAR.equals(o.NULL_EXPR), [
_ANIMATION_END_STATE_STYLES_VAR.set(_ANIMATION_DEFAULT_STATE_VAR).toStmt()
]));
statements.push(new o.IfStmt(
_ANIMATION_END_STATE_STYLES_VAR.equals(o.NULL_EXPR),
[_ANIMATION_END_STATE_STYLES_VAR.set(_ANIMATION_DEFAULT_STATE_VAR).toStmt()]));
var RENDER_STYLES_FN = o.importExpr(Identifiers.renderStyles);
@ -259,53 +232,59 @@ class _AnimationBuilder implements AnimationAstVisitor {
// styles from the element's style property (since they were placed
// there at the end of the last animation
statements.push(
RENDER_STYLES_FN.callFn([
_ANIMATION_FACTORY_ELEMENT_VAR,
_ANIMATION_FACTORY_RENDERER_VAR,
o.importExpr(Identifiers.clearStyles).callFn([_ANIMATION_START_STATE_STYLES_VAR])
]).toStmt());
RENDER_STYLES_FN
.callFn([
_ANIMATION_FACTORY_ELEMENT_VAR, _ANIMATION_FACTORY_RENDERER_VAR,
o.importExpr(Identifiers.clearStyles).callFn([_ANIMATION_START_STATE_STYLES_VAR])
])
.toStmt());
ast.stateTransitions.forEach(transAst => statements.push(transAst.visit(this, context)));
// this check ensures that the animation factory always returns a player
// so that the onDone callback can be used for tracking
statements.push(
new o.IfStmt(_ANIMATION_PLAYER_VAR.equals(o.NULL_EXPR), [
_ANIMATION_PLAYER_VAR.set(
o.importExpr(Identifiers.NoOpAnimationPlayer).instantiate([])
).toStmt()
]));
statements.push(new o.IfStmt(
_ANIMATION_PLAYER_VAR.equals(o.NULL_EXPR),
[_ANIMATION_PLAYER_VAR.set(o.importExpr(Identifiers.NoOpAnimationPlayer).instantiate([]))
.toStmt()]));
// once complete we want to apply the styles on the element
// since the destination state's values should persist once
// the animation sequence has completed.
statements.push(
_ANIMATION_PLAYER_VAR.callMethod('onDone', [
o.fn([], [
RENDER_STYLES_FN.callFn([
_ANIMATION_FACTORY_ELEMENT_VAR,
_ANIMATION_FACTORY_RENDERER_VAR,
o.importExpr(Identifiers.balanceAnimationStyles).callFn([
_ANIMATION_START_STATE_STYLES_VAR,
_ANIMATION_END_STATE_STYLES_VAR
])
]).toStmt()
])
]).toStmt());
statements.push(
_ANIMATION_FACTORY_VIEW_VAR.callMethod('registerAndStartAnimation', [
_ANIMATION_FACTORY_ELEMENT_VAR,
o.literal(this.animationName),
_ANIMATION_PLAYER_VAR
]).toStmt());
.callMethod(
'onDone',
[o.fn(
[], [RENDER_STYLES_FN
.callFn([
_ANIMATION_FACTORY_ELEMENT_VAR, _ANIMATION_FACTORY_RENDERER_VAR,
o.importExpr(Identifiers.balanceAnimationStyles).callFn([
_ANIMATION_START_STATE_STYLES_VAR, _ANIMATION_END_STATE_STYLES_VAR
])
])
.toStmt()])])
.toStmt());
return o.fn([
new o.FnParam(_ANIMATION_FACTORY_VIEW_VAR.name, o.importType(Identifiers.AppView, [o.DYNAMIC_TYPE])),
new o.FnParam(_ANIMATION_FACTORY_ELEMENT_VAR.name, o.DYNAMIC_TYPE),
new o.FnParam(_ANIMATION_CURRENT_STATE_VAR.name, o.DYNAMIC_TYPE),
new o.FnParam(_ANIMATION_NEXT_STATE_VAR.name, o.DYNAMIC_TYPE)
], statements);
statements.push(_ANIMATION_FACTORY_VIEW_VAR
.callMethod(
'registerAndStartAnimation',
[
_ANIMATION_FACTORY_ELEMENT_VAR, o.literal(this.animationName),
_ANIMATION_PLAYER_VAR
])
.toStmt());
return o.fn(
[
new o.FnParam(
_ANIMATION_FACTORY_VIEW_VAR.name,
o.importType(Identifiers.AppView, [o.DYNAMIC_TYPE])),
new o.FnParam(_ANIMATION_FACTORY_ELEMENT_VAR.name, o.DYNAMIC_TYPE),
new o.FnParam(_ANIMATION_CURRENT_STATE_VAR.name, o.DYNAMIC_TYPE),
new o.FnParam(_ANIMATION_NEXT_STATE_VAR.name, o.DYNAMIC_TYPE)
],
statements);
}
build(ast: AnimationAst): CompiledAnimation {
@ -314,24 +293,24 @@ class _AnimationBuilder implements AnimationAstVisitor {
var fnVariable = o.variable(this._fnVarName);
var lookupMap: any[] /** TODO #9100 */ = [];
StringMapWrapper.forEach(context.stateMap.states, (value: any /** TODO #9100 */, stateName: any /** TODO #9100 */) => {
var variableValue = EMPTY_MAP;
if (isPresent(value)) {
let styleMap: any[] /** TODO #9100 */ = [];
StringMapWrapper.forEach(value, (value: any /** TODO #9100 */, key: any /** TODO #9100 */) => {
styleMap.push([key, o.literal(value)]);
StringMapWrapper.forEach(
context.stateMap.states,
(value: any /** TODO #9100 */, stateName: any /** TODO #9100 */) => {
var variableValue = EMPTY_MAP;
if (isPresent(value)) {
let styleMap: any[] /** TODO #9100 */ = [];
StringMapWrapper.forEach(
value, (value: any /** TODO #9100 */, key: any /** TODO #9100 */) => {
styleMap.push([key, o.literal(value)]);
});
variableValue = o.literalMap(styleMap);
}
lookupMap.push([stateName, variableValue]);
});
variableValue = o.literalMap(styleMap);
}
lookupMap.push([stateName, variableValue]);
});
var compiledStatesMapExpr = this._statesMapVar.set(o.literalMap(lookupMap)).toDeclStmt();
return new CompiledAnimation(this.animationName,
compiledStatesMapExpr,
this._statesMapVarName,
fnStatement,
fnVariable);
return new CompiledAnimation(
this.animationName, compiledStatesMapExpr, this._statesMapVarName, fnStatement, fnVariable);
}
}
@ -342,9 +321,9 @@ class _AnimationBuilderContext {
}
class _AnimationBuilderStateMap {
private _states: {[key: string]: {[prop: string]: string|number}} = {};
private _states: {[key: string]: {[prop: string]: string | number}} = {};
get states() { return this._states; }
registerState(name: string, value: {[prop: string]: string|number} = null): void {
registerState(name: string, value: {[prop: string]: string | number} = null): void {
var existingEntry = this._states[name];
if (isBlank(existingEntry)) {
this._states[name] = value;
@ -369,9 +348,7 @@ function _compareToAnimationStateExpr(value: o.Expression, animationState: strin
function _isEndStateAnimateStep(step: AnimationAst): boolean {
// the final animation step is characterized by having only TWO
// keyframe values and it must have zero styles for both keyframes
if (step instanceof AnimationStepAst
&& step.duration > 0
&& step.keyframes.length == 2) {
if (step instanceof AnimationStepAst && step.duration > 0 && step.keyframes.length == 2) {
var styles1 = _getStylesArray(step.keyframes[0])[0];
var styles2 = _getStylesArray(step.keyframes[1])[0];
return StringMapWrapper.isEmpty(styles1) && StringMapWrapper.isEmpty(styles2);

View File

@ -1,46 +1,13 @@
import {ListWrapper, StringMapWrapper} from '../facade/collection';
import {Math} from '../facade/math';
import {ANY_STATE, FILL_STYLE_FLAG} from '../../core_private';
import {
RegExpWrapper,
isArray,
isPresent,
isBlank,
isString,
isStringMap,
NumberWrapper
} from '../facade/lang';
import {
CompileAnimationEntryMetadata,
CompileAnimationStateDeclarationMetadata,
CompileAnimationStateTransitionMetadata,
CompileAnimationMetadata,
CompileAnimationWithStepsMetadata,
CompileAnimationStyleMetadata,
CompileAnimationAnimateMetadata,
CompileAnimationGroupMetadata,
CompileAnimationSequenceMetadata,
CompileAnimationKeyframesSequenceMetadata
} from '../compile_metadata';
import {
AnimationAst,
AnimationEntryAst,
AnimationStateTransitionAst,
AnimationStateDeclarationAst,
AnimationKeyframeAst,
AnimationStylesAst,
AnimationWithStepsAst,
AnimationSequenceAst,
AnimationGroupAst,
AnimationStepAst,
AnimationStateTransitionExpression
} from './animation_ast';
import {StylesCollection} from './styles_collection';
import {CompileAnimationAnimateMetadata, CompileAnimationEntryMetadata, CompileAnimationGroupMetadata, CompileAnimationKeyframesSequenceMetadata, CompileAnimationMetadata, CompileAnimationSequenceMetadata, CompileAnimationStateDeclarationMetadata, CompileAnimationStateTransitionMetadata, CompileAnimationStyleMetadata, CompileAnimationWithStepsMetadata} from '../compile_metadata';
import {ListWrapper, StringMapWrapper} from '../facade/collection';
import {NumberWrapper, RegExpWrapper, isArray, isBlank, isPresent, isString, isStringMap} from '../facade/lang';
import {Math} from '../facade/math';
import {ParseError} from '../parse_util';
import {AnimationAst, AnimationEntryAst, AnimationGroupAst, AnimationKeyframeAst, AnimationSequenceAst, AnimationStateDeclarationAst, AnimationStateTransitionAst, AnimationStateTransitionExpression, AnimationStepAst, AnimationStylesAst, AnimationWithStepsAst} from './animation_ast';
import {StylesCollection} from './styles_collection';
const _INITIAL_KEYFRAME = 0;
const _TERMINAL_KEYFRAME = 1;
const _ONE_SECOND = 1000;
@ -71,21 +38,24 @@ export function parseAnimationEntry(entry: CompileAnimationEntryMetadata): Parse
}
});
var stateTransitionAsts = transitions.map(transDef =>
_parseAnimationStateTransition(transDef, stateStyles, errors));
var stateTransitionAsts =
transitions.map(transDef => _parseAnimationStateTransition(transDef, stateStyles, errors));
var ast = new AnimationEntryAst(entry.name, stateDeclarationAsts, stateTransitionAsts);
return new ParsedAnimationResult(ast, errors);
}
function _parseAnimationDeclarationStates(stateMetadata: CompileAnimationStateDeclarationMetadata, errors: AnimationParseError[]): AnimationStateDeclarationAst[] {
var styleValues: {[key: string]: string|number}[] = [];
function _parseAnimationDeclarationStates(
stateMetadata: CompileAnimationStateDeclarationMetadata,
errors: AnimationParseError[]): AnimationStateDeclarationAst[] {
var styleValues: {[key: string]: string | number}[] = [];
stateMetadata.styles.styles.forEach(stylesEntry => {
// TODO (matsko): change this when we get CSS class integration support
if (isStringMap(stylesEntry)) {
styleValues.push(<{[key: string]: string|number}>stylesEntry);
styleValues.push(<{[key: string]: string | number}>stylesEntry);
} else {
errors.push(new AnimationParseError(`State based animations cannot contain references to other states`));
errors.push(new AnimationParseError(
`State based animations cannot contain references to other states`));
}
});
var defStyles = new AnimationStylesAst(styleValues);
@ -94,9 +64,10 @@ function _parseAnimationDeclarationStates(stateMetadata: CompileAnimationStateDe
return states.map(state => new AnimationStateDeclarationAst(state, defStyles));
}
function _parseAnimationStateTransition(transitionStateMetadata: CompileAnimationStateTransitionMetadata,
stateStyles: {[key: string]: AnimationStylesAst},
errors: AnimationParseError[]): AnimationStateTransitionAst {
function _parseAnimationStateTransition(
transitionStateMetadata: CompileAnimationStateTransitionMetadata,
stateStyles: {[key: string]: AnimationStylesAst},
errors: AnimationParseError[]): AnimationStateTransitionAst {
var styles = new StylesCollection();
var transitionExprs: any[] /** TODO #9100 */ = [];
var transitionStates = transitionStateMetadata.stateChangeExpr.split(/\s*,\s*/);
@ -112,14 +83,15 @@ function _parseAnimationStateTransition(transitionStateMetadata: CompileAnimatio
_fillAnimationAstStartingKeyframes(animationAst, styles, errors);
}
var sequenceAst = (animationAst instanceof AnimationSequenceAst)
? <AnimationSequenceAst>animationAst
: new AnimationSequenceAst([animationAst]);
var sequenceAst = (animationAst instanceof AnimationSequenceAst) ?
<AnimationSequenceAst>animationAst :
new AnimationSequenceAst([animationAst]);
return new AnimationStateTransitionAst(transitionExprs, sequenceAst);
}
function _parseAnimationTransitionExpr(eventStr: string, errors: AnimationParseError[]): AnimationStateTransitionExpression[] {
function _parseAnimationTransitionExpr(
eventStr: string, errors: AnimationParseError[]): AnimationStateTransitionExpression[] {
var expressions: any[] /** TODO #9100 */ = [];
var match = eventStr.match(/^(\*|[-\w]+)\s*(<?[=-]>)\s*(\*|[-\w]+)$/);
if (!isPresent(match) || match.length < 4) {
@ -130,19 +102,17 @@ function _parseAnimationTransitionExpr(eventStr: string, errors: AnimationParseE
var fromState = match[1];
var separator = match[2];
var toState = match[3];
expressions.push(
new AnimationStateTransitionExpression(fromState, toState));
expressions.push(new AnimationStateTransitionExpression(fromState, toState));
var isFullAnyStateExpr = fromState == ANY_STATE && toState == ANY_STATE;
if (separator[0] == '<' && !isFullAnyStateExpr) {
expressions.push(
new AnimationStateTransitionExpression(toState, fromState));
expressions.push(new AnimationStateTransitionExpression(toState, fromState));
}
return expressions;
}
function _fetchSylesFromState(stateName: string,
stateStyles: {[key: string]: AnimationStylesAst}): CompileAnimationStyleMetadata {
function _fetchSylesFromState(stateName: string, stateStyles: {[key: string]: AnimationStylesAst}):
CompileAnimationStyleMetadata {
var entry = stateStyles[stateName];
if (isPresent(entry)) {
var styles = <{[key: string]: string | number}[]>entry.styles;
@ -151,20 +121,20 @@ function _fetchSylesFromState(stateName: string,
return null;
}
function _normalizeAnimationEntry(entry: CompileAnimationMetadata | CompileAnimationMetadata[])
:CompileAnimationMetadata {
return isArray(entry)
? new CompileAnimationSequenceMetadata(<CompileAnimationMetadata[]>entry)
: <CompileAnimationMetadata>entry;
function _normalizeAnimationEntry(entry: CompileAnimationMetadata | CompileAnimationMetadata[]):
CompileAnimationMetadata {
return isArray(entry) ? new CompileAnimationSequenceMetadata(<CompileAnimationMetadata[]>entry) :
<CompileAnimationMetadata>entry;
}
function _normalizeStyleMetadata(entry: CompileAnimationStyleMetadata,
stateStyles: {[key: string]: AnimationStylesAst},
errors: AnimationParseError[]): Array<{[key: string]: string|number}> {
function _normalizeStyleMetadata(
entry: CompileAnimationStyleMetadata, stateStyles: {[key: string]: AnimationStylesAst},
errors: AnimationParseError[]): Array<{[key: string]: string | number}> {
var normalizedStyles: any[] /** TODO #9100 */ = [];
entry.styles.forEach(styleEntry => {
if (isString(styleEntry)) {
ListWrapper.addAll(normalizedStyles, _resolveStylesFromState(<string>styleEntry, stateStyles, errors));
ListWrapper.addAll(
normalizedStyles, _resolveStylesFromState(<string>styleEntry, stateStyles, errors));
} else {
normalizedStyles.push(<{[key: string]: string | number}>styleEntry);
}
@ -172,31 +142,30 @@ function _normalizeStyleMetadata(entry: CompileAnimationStyleMetadata,
return normalizedStyles;
}
function _normalizeStyleSteps(entry: CompileAnimationMetadata,
stateStyles: {[key: string]: AnimationStylesAst},
errors: AnimationParseError[]): CompileAnimationMetadata {
function _normalizeStyleSteps(
entry: CompileAnimationMetadata, stateStyles: {[key: string]: AnimationStylesAst},
errors: AnimationParseError[]): CompileAnimationMetadata {
var steps = _normalizeStyleStepEntry(entry, stateStyles, errors);
return new CompileAnimationSequenceMetadata(steps);
}
function _mergeAnimationStyles(stylesList: any[], newItem: {[key: string]: string|number}|string) {
function _mergeAnimationStyles(
stylesList: any[], newItem: {[key: string]: string | number} | string) {
if (isStringMap(newItem) && stylesList.length > 0) {
var lastIndex = stylesList.length - 1;
var lastItem = stylesList[lastIndex];
if (isStringMap(lastItem)) {
stylesList[lastIndex] = StringMapWrapper.merge(
<{[key: string]: string|number}>lastItem,
<{[key: string]: string|number}>newItem
);
<{[key: string]: string | number}>lastItem, <{[key: string]: string | number}>newItem);
return;
}
}
stylesList.push(newItem);
}
function _normalizeStyleStepEntry(entry: CompileAnimationMetadata,
stateStyles: {[key: string]: AnimationStylesAst},
errors: AnimationParseError[]): CompileAnimationMetadata[] {
function _normalizeStyleStepEntry(
entry: CompileAnimationMetadata, stateStyles: {[key: string]: AnimationStylesAst},
errors: AnimationParseError[]): CompileAnimationMetadata[] {
var steps: CompileAnimationMetadata[];
if (entry instanceof CompileAnimationWithStepsMetadata) {
steps = entry.steps;
@ -215,9 +184,8 @@ function _normalizeStyleStepEntry(entry: CompileAnimationMetadata,
if (!isPresent(combinedStyles)) {
combinedStyles = [];
}
_normalizeStyleMetadata(<CompileAnimationStyleMetadata>step, stateStyles, errors).forEach(entry => {
_mergeAnimationStyles(combinedStyles, entry);
});
_normalizeStyleMetadata(<CompileAnimationStyleMetadata>step, stateStyles, errors)
.forEach(entry => { _mergeAnimationStyles(combinedStyles, entry); });
} else {
// it is important that we create a metadata entry of the combined styles
// before we go on an process the animate, sequence or group metadata steps.
@ -233,17 +201,17 @@ function _normalizeStyleStepEntry(entry: CompileAnimationMetadata,
// those style steps are not going to be squashed
var animateStyleValue = (<CompileAnimationAnimateMetadata>step).styles;
if (animateStyleValue instanceof CompileAnimationStyleMetadata) {
animateStyleValue.styles = _normalizeStyleMetadata(animateStyleValue, stateStyles, errors);
animateStyleValue.styles =
_normalizeStyleMetadata(animateStyleValue, stateStyles, errors);
} else if (animateStyleValue instanceof CompileAnimationKeyframesSequenceMetadata) {
animateStyleValue.steps.forEach(step => {
step.styles = _normalizeStyleMetadata(step, stateStyles, errors);
});
animateStyleValue.steps.forEach(
step => { step.styles = _normalizeStyleMetadata(step, stateStyles, errors); });
}
} else if (step instanceof CompileAnimationWithStepsMetadata) {
let innerSteps = _normalizeStyleStepEntry(step, stateStyles, errors);
step = step instanceof CompileAnimationGroupMetadata
? new CompileAnimationGroupMetadata(innerSteps)
: new CompileAnimationSequenceMetadata(innerSteps);
step = step instanceof CompileAnimationGroupMetadata ?
new CompileAnimationGroupMetadata(innerSteps) :
new CompileAnimationSequenceMetadata(innerSteps);
}
newSteps.push(step);
@ -259,15 +227,18 @@ function _normalizeStyleStepEntry(entry: CompileAnimationMetadata,
}
function _resolveStylesFromState(stateName: string, stateStyles: {[key: string]: AnimationStylesAst}, errors: AnimationParseError[]) {
var styles: {[key: string]: string|number}[] = [];
function _resolveStylesFromState(
stateName: string, stateStyles: {[key: string]: AnimationStylesAst},
errors: AnimationParseError[]) {
var styles: {[key: string]: string | number}[] = [];
if (stateName[0] != ':') {
errors.push(new AnimationParseError(`Animation states via styles must be prefixed with a ":"`));
} else {
var normalizedStateName = stateName.substring(1);
var value = stateStyles[normalizedStateName];
if (!isPresent(value)) {
errors.push(new AnimationParseError(`Unable to apply styles due to missing a state: "${normalizedStateName}"`));
errors.push(new AnimationParseError(
`Unable to apply styles due to missing a state: "${normalizedStateName}"`));
} else {
value.styles.forEach(stylesEntry => {
if (isStringMap(stylesEntry)) {
@ -283,17 +254,17 @@ class _AnimationTimings {
constructor(public duration: number, public delay: number, public easing: string) {}
}
function _parseAnimationKeyframes(keyframeSequence: CompileAnimationKeyframesSequenceMetadata,
currentTime: number,
collectedStyles: StylesCollection,
stateStyles: {[key: string]: AnimationStylesAst},
errors: AnimationParseError[]): AnimationKeyframeAst[] {
function _parseAnimationKeyframes(
keyframeSequence: CompileAnimationKeyframesSequenceMetadata, currentTime: number,
collectedStyles: StylesCollection, stateStyles: {[key: string]: AnimationStylesAst},
errors: AnimationParseError[]): AnimationKeyframeAst[] {
var totalEntries = keyframeSequence.steps.length;
var totalOffsets = 0;
keyframeSequence.steps.forEach(step => totalOffsets += (isPresent(step.offset) ? 1 : 0));
if (totalOffsets > 0 && totalOffsets < totalEntries) {
errors.push(new AnimationParseError(`Not all style() entries contain an offset for the provided keyframe()`));
errors.push(new AnimationParseError(
`Not all style() entries contain an offset for the provided keyframe()`));
totalOffsets = totalEntries;
}
@ -305,13 +276,15 @@ function _parseAnimationKeyframes(keyframeSequence: CompileAnimationKeyframesSeq
var lastOffset = 0;
keyframeSequence.steps.forEach(styleMetadata => {
var offset = styleMetadata.offset;
var keyframeStyles: {[key: string]: string|number} = {};
var keyframeStyles: {[key: string]: string | number} = {};
styleMetadata.styles.forEach(entry => {
StringMapWrapper.forEach(<{[key: string]: string|number}>entry, (value: any /** TODO #9100 */, prop: any /** TODO #9100 */) => {
if (prop != 'offset') {
keyframeStyles[prop] = value;
}
});
StringMapWrapper.forEach(
<{[key: string]: string | number}>entry,
(value: any /** TODO #9100 */, prop: any /** TODO #9100 */) => {
if (prop != 'offset') {
keyframeStyles[prop] = value;
}
});
});
if (isPresent(offset)) {
@ -326,7 +299,7 @@ function _parseAnimationKeyframes(keyframeSequence: CompileAnimationKeyframesSeq
});
if (doSortKeyframes) {
ListWrapper.sort(rawKeyframes, (a,b) => a[0] <= b[0] ? -1 : 1);
ListWrapper.sort(rawKeyframes, (a, b) => a[0] <= b[0] ? -1 : 1);
}
var i: any /** TODO #9100 */;
@ -348,32 +321,33 @@ function _parseAnimationKeyframes(keyframeSequence: CompileAnimationKeyframesSeq
let entry = rawKeyframes[i];
let styles = entry[1];
StringMapWrapper.forEach(styles, (value: any /** TODO #9100 */, prop: any /** TODO #9100 */) => {
if (!isPresent(firstKeyframeStyles[prop])) {
firstKeyframeStyles[prop] = FILL_STYLE_FLAG;
}
});
StringMapWrapper.forEach(
styles, (value: any /** TODO #9100 */, prop: any /** TODO #9100 */) => {
if (!isPresent(firstKeyframeStyles[prop])) {
firstKeyframeStyles[prop] = FILL_STYLE_FLAG;
}
});
}
for (i = limit - 1; i >= 0; i--) {
let entry = rawKeyframes[i];
let styles = entry[1];
StringMapWrapper.forEach(styles, (value: any /** TODO #9100 */, prop: any /** TODO #9100 */) => {
if (!isPresent(lastKeyframeStyles[prop])) {
lastKeyframeStyles[prop] = value;
}
});
StringMapWrapper.forEach(
styles, (value: any /** TODO #9100 */, prop: any /** TODO #9100 */) => {
if (!isPresent(lastKeyframeStyles[prop])) {
lastKeyframeStyles[prop] = value;
}
});
}
return rawKeyframes.map(entry => new AnimationKeyframeAst(entry[0], new AnimationStylesAst([entry[1]])));
return rawKeyframes.map(
entry => new AnimationKeyframeAst(entry[0], new AnimationStylesAst([entry[1]])));
}
function _parseTransitionAnimation(entry: CompileAnimationMetadata,
currentTime: number,
collectedStyles: StylesCollection,
stateStyles: {[key: string]: AnimationStylesAst},
errors: AnimationParseError[]): AnimationAst {
function _parseTransitionAnimation(
entry: CompileAnimationMetadata, currentTime: number, collectedStyles: StylesCollection,
stateStyles: {[key: string]: AnimationStylesAst}, errors: AnimationParseError[]): AnimationAst {
var ast: any /** TODO #9100 */;
var playTime = 0;
var startingTime = currentTime;
@ -388,10 +362,11 @@ function _parseTransitionAnimation(entry: CompileAnimationMetadata,
if (entry instanceof CompileAnimationStyleMetadata) {
entry.styles.forEach(stylesEntry => {
// by this point we know that we only have stringmap values
var map = <{[key: string]: string|number}>stylesEntry;
StringMapWrapper.forEach(map, (value: any /** TODO #9100 */, prop: any /** TODO #9100 */) => {
collectedStyles.insertAtTime(prop, time, value);
});
var map = <{[key: string]: string | number}>stylesEntry;
StringMapWrapper.forEach(
map, (value: any /** TODO #9100 */, prop: any /** TODO #9100 */) => {
collectedStyles.insertAtTime(prop, time, value);
});
});
previousStyles = entry.styles;
return;
@ -432,25 +407,26 @@ function _parseTransitionAnimation(entry: CompileAnimationMetadata,
var keyframes: any /** TODO #9100 */;
if (styles instanceof CompileAnimationKeyframesSequenceMetadata) {
keyframes = _parseAnimationKeyframes(styles, currentTime, collectedStyles, stateStyles, errors);
keyframes =
_parseAnimationKeyframes(styles, currentTime, collectedStyles, stateStyles, errors);
} else {
let styleData = <CompileAnimationStyleMetadata>styles;
let offset = _TERMINAL_KEYFRAME;
let styleAst = new AnimationStylesAst(<{[key: string]: string|number}[]>styleData.styles);
let styleAst = new AnimationStylesAst(<{[key: string]: string | number}[]>styleData.styles);
var keyframe = new AnimationKeyframeAst(offset, styleAst);
keyframes = [keyframe];
}
ast = new AnimationStepAst(new AnimationStylesAst([]), keyframes, timings.duration, timings.delay, timings.easing);
ast = new AnimationStepAst(
new AnimationStylesAst([]), keyframes, timings.duration, timings.delay, timings.easing);
playTime = timings.duration + timings.delay;
currentTime += playTime;
keyframes.forEach((keyframe: any /** TODO #9100 */) =>
keyframe.styles.styles.forEach((entry: any /** TODO #9100 */) =>
StringMapWrapper.forEach(entry, (value: any /** TODO #9100 */, prop: any /** TODO #9100 */) =>
collectedStyles.insertAtTime(prop, currentTime, value))
)
);
keyframes.forEach(
(keyframe: any /** TODO #9100 */) => keyframe.styles.styles.forEach(
(entry: any /** TODO #9100 */) => StringMapWrapper.forEach(
entry, (value: any /** TODO #9100 */, prop: any /** TODO #9100 */) =>
collectedStyles.insertAtTime(prop, currentTime, value))));
} else {
// if the code reaches this stage then an error
// has already been populated within the _normalizeStyleSteps()
@ -463,15 +439,15 @@ function _parseTransitionAnimation(entry: CompileAnimationMetadata,
return ast;
}
function _fillAnimationAstStartingKeyframes(ast: AnimationAst, collectedStyles: StylesCollection,
errors: AnimationParseError[]): void {
function _fillAnimationAstStartingKeyframes(
ast: AnimationAst, collectedStyles: StylesCollection, errors: AnimationParseError[]): void {
// steps that only contain style will not be filled
if ((ast instanceof AnimationStepAst) && ast.keyframes.length > 0) {
var keyframes = ast.keyframes;
if (keyframes.length == 1) {
var endKeyframe = keyframes[0];
var startKeyframe = _createStartKeyframeFromEndKeyframe(endKeyframe, ast.startTime,
ast.playTime, collectedStyles, errors);
var startKeyframe = _createStartKeyframeFromEndKeyframe(
endKeyframe, ast.startTime, ast.playTime, collectedStyles, errors);
ast.keyframes = [startKeyframe, endKeyframe];
}
} else if (ast instanceof AnimationWithStepsAst) {
@ -479,8 +455,8 @@ function _fillAnimationAstStartingKeyframes(ast: AnimationAst, collectedStyles:
}
}
function _parseTimeExpression(exp: string | number,
errors: AnimationParseError[]): _AnimationTimings {
function _parseTimeExpression(
exp: string | number, errors: AnimationParseError[]): _AnimationTimings {
var regex = /^([\.\d]+)(m?s)(?:\s+([\.\d]+)(m?s))?(?:\s+([-a-z]+(?:\(.+?\))?))?/gi;
var duration: number;
var delay: number = 0;
@ -520,17 +496,18 @@ function _parseTimeExpression(exp: string | number,
return new _AnimationTimings(duration, delay, easing);
}
function _createStartKeyframeFromEndKeyframe(endKeyframe: AnimationKeyframeAst, startTime: number,
duration: number, collectedStyles: StylesCollection,
errors: AnimationParseError[]): AnimationKeyframeAst {
function _createStartKeyframeFromEndKeyframe(
endKeyframe: AnimationKeyframeAst, startTime: number, duration: number,
collectedStyles: StylesCollection, errors: AnimationParseError[]): AnimationKeyframeAst {
var values: {[key: string]: string | number} = {};
var endTime = startTime + duration;
endKeyframe.styles.styles.forEach((styleData: {[key: string]: string|number}) => {
endKeyframe.styles.styles.forEach((styleData: {[key: string]: string | number}) => {
StringMapWrapper.forEach(styleData, (val: any /** TODO #9100 */, prop: any /** TODO #9100 */) => {
if (prop == 'offset') return;
var resultIndex = collectedStyles.indexOfAtOrBeforeTime(prop, startTime);
var resultEntry: any /** TODO #9100 */, nextEntry: any /** TODO #9100 */, value: any /** TODO #9100 */;
var resultEntry: any /** TODO #9100 */, nextEntry: any /** TODO #9100 */,
value: any /** TODO #9100 */;
if (isPresent(resultIndex)) {
resultEntry = collectedStyles.getByIndex(prop, resultIndex);
value = resultEntry.value;

View File

@ -1,10 +1,10 @@
import {isPresent} from '../facade/lang';
import {ListWrapper} from '../facade/collection';
import {isPresent} from '../facade/lang';
export class StylesCollectionEntry {
constructor(public time: number, public value: string | number) {}
constructor(public time: number, public value: string|number) {}
matches(time: number, value: string | number): boolean {
matches(time: number, value: string|number): boolean {
return time == this.time && value == this.value;
}
}
@ -12,7 +12,7 @@ export class StylesCollectionEntry {
export class StylesCollection {
styles: {[key: string]: StylesCollectionEntry[]} = {};
insertAtTime(property: string, time: number, value: string | number) {
insertAtTime(property: string, time: number, value: string|number) {
var tuple = new StylesCollectionEntry(time, value);
var entries = this.styles[property];
if (!isPresent(entries)) {

View File

@ -1,5 +1,5 @@
import {isArray, isString, isBlank, assertionsEnabled} from '../src/facade/lang';
import {BaseException} from '../src/facade/exceptions';
import {assertionsEnabled, isArray, isBlank, isString} from '../src/facade/lang';
export function assertArrayOfStrings(identifier: string, value: any) {
if (!assertionsEnabled() || isBlank(value)) {

View File

@ -1,32 +1,14 @@
import {ChangeDetectionStrategy, ViewEncapsulation} from '@angular/core';
import {
CHANGE_DETECTION_STRATEGY_VALUES,
VIEW_ENCAPSULATION_VALUES,
LifecycleHooks,
LIFECYCLE_HOOKS_VALUES,
reflector
} from '../core_private';
import {
isPresent,
isBlank,
isNumber,
isBoolean,
normalizeBool,
normalizeBlank,
serializeEnum,
Type,
isString,
RegExpWrapper,
StringWrapper,
NumberWrapper,
isArray
} from '../src/facade/lang';
import {unimplemented, BaseException} from '../src/facade/exceptions';
import {StringMapWrapper, ListWrapper} from '../src/facade/collection';
import {CHANGE_DETECTION_STRATEGY_VALUES, LIFECYCLE_HOOKS_VALUES, LifecycleHooks, VIEW_ENCAPSULATION_VALUES, reflector} from '../core_private';
import {ListWrapper, StringMapWrapper} from '../src/facade/collection';
import {BaseException, unimplemented} from '../src/facade/exceptions';
import {NumberWrapper, RegExpWrapper, StringWrapper, Type, isArray, isBlank, isBoolean, isNumber, isPresent, isString, normalizeBlank, normalizeBool, serializeEnum} from '../src/facade/lang';
import {CssSelector} from './selector';
import {splitAtColon, sanitizeIdentifier} from './util';
import {getUrlScheme} from './url_resolver';
import {sanitizeIdentifier, splitAtColon} from './util';
// group 2: "event" from "(event)"
var HOST_REG_EXP = /^(?:(?:\[([^\]]+)\])|(?:\(([^\)]+)\)))$/g;
@ -56,15 +38,13 @@ export class CompileAnimationEntryMetadata {
return new CompileAnimationEntryMetadata(value['name'], defs);
}
constructor(public name: string = null, public definitions: CompileAnimationStateMetadata[] = null) {}
constructor(
public name: string = null, public definitions: CompileAnimationStateMetadata[] = null) {}
toJson(): {[key: string]: any} {
return {
'class': 'AnimationEntryMetadata',
'value': {
'name' : this.name,
'definitions': _arrayToJson(this.definitions)
}
'value': {'name': this.name, 'definitions': _arrayToJson(this.definitions)}
};
}
}
@ -78,15 +58,14 @@ export class CompileAnimationStateDeclarationMetadata extends CompileAnimationSt
return new CompileAnimationStateDeclarationMetadata(value['stateNameExpr'], styles);
}
constructor(public stateNameExpr: string, public styles: CompileAnimationStyleMetadata) { super(); }
constructor(public stateNameExpr: string, public styles: CompileAnimationStyleMetadata) {
super();
}
toJson(): {[key: string]: any} {
return {
'class': 'AnimationStateDeclarationMetadata',
'value': {
'stateNameExpr': this.stateNameExpr,
'styles': this.styles.toJson()
}
'value': {'stateNameExpr': this.stateNameExpr, 'styles': this.styles.toJson()}
};
}
}
@ -103,17 +82,12 @@ export class CompileAnimationStateTransitionMetadata extends CompileAnimationSta
toJson(): {[key: string]: any} {
return {
'class': 'AnimationStateTransitionMetadata',
'value': {
'stateChangeExpr': this.stateChangeExpr,
'steps': this.steps.toJson()
}
'value': {'stateChangeExpr': this.stateChangeExpr, 'steps': this.steps.toJson()}
};
}
}
export abstract class CompileAnimationMetadata {
abstract toJson(): {[key: string]: any};
}
export abstract class CompileAnimationMetadata { abstract toJson(): {[key: string]: any}; }
export class CompileAnimationKeyframesSequenceMetadata extends CompileAnimationMetadata {
static fromJson(data: {[key: string]: any}): CompileAnimationKeyframesSequenceMetadata {
@ -121,15 +95,10 @@ export class CompileAnimationKeyframesSequenceMetadata extends CompileAnimationM
return new CompileAnimationKeyframesSequenceMetadata(<CompileAnimationStyleMetadata[]>steps);
}
constructor(public steps: CompileAnimationStyleMetadata[] = []) {
super();
}
constructor(public steps: CompileAnimationStyleMetadata[] = []) { super(); }
toJson(): {[key: string]: any} {
return {
'class': 'AnimationKeyframesSequenceMetadata',
'value': _arrayToJson(this.steps)
};
return {'class': 'AnimationKeyframesSequenceMetadata', 'value': _arrayToJson(this.steps)};
}
}
@ -142,15 +111,15 @@ export class CompileAnimationStyleMetadata extends CompileAnimationMetadata {
return new CompileAnimationStyleMetadata(offset, styles);
}
constructor(public offset: number, public styles: Array<string|{[key: string]: string | number}> = null) { super(); }
constructor(
public offset: number, public styles: Array<string|{[key: string]: string | number}> = null) {
super();
}
toJson(): {[key: string]: any} {
return {
'class': 'AnimationStyleMetadata',
'value': {
'offset': this.offset,
'styles': this.styles
}
'value': {'offset': this.offset, 'styles': this.styles}
};
}
}
@ -163,16 +132,16 @@ export class CompileAnimationAnimateMetadata extends CompileAnimationMetadata {
return new CompileAnimationAnimateMetadata(timings, styles);
}
constructor(public timings: string|number = 0,
public styles: CompileAnimationStyleMetadata|CompileAnimationKeyframesSequenceMetadata = null) { super(); }
constructor(
public timings: string|number = 0, public styles: CompileAnimationStyleMetadata|
CompileAnimationKeyframesSequenceMetadata = null) {
super();
}
toJson(): {[key: string]: any} {
return {
'class': 'AnimationAnimateMetadata',
'value': {
'timings': this.timings,
'styles': _objToJson(this.styles)
}
'value': {'timings': this.timings, 'styles': _objToJson(this.styles)}
};
}
}
@ -187,33 +156,23 @@ export class CompileAnimationSequenceMetadata extends CompileAnimationWithStepsM
return new CompileAnimationSequenceMetadata(steps);
}
constructor(steps: CompileAnimationMetadata[] = null) {
super(steps);
}
constructor(steps: CompileAnimationMetadata[] = null) { super(steps); }
toJson(): {[key: string]: any} {
return {
'class': 'AnimationSequenceMetadata',
'value': _arrayToJson(this.steps)
};
return {'class': 'AnimationSequenceMetadata', 'value': _arrayToJson(this.steps)};
}
}
export class CompileAnimationGroupMetadata extends CompileAnimationWithStepsMetadata {
static fromJson(data: {[key: string]: any}): CompileAnimationGroupMetadata {
var steps = _arrayFromJson(data["value"], metadataFromJson);
var steps = _arrayFromJson(data['value'], metadataFromJson);
return new CompileAnimationGroupMetadata(steps);
}
constructor(steps: CompileAnimationMetadata[] = null) {
super(steps);
}
constructor(steps: CompileAnimationMetadata[] = null) { super(steps); }
toJson(): {[key: string]: any} {
return {
'class': 'AnimationGroupMetadata',
'value': _arrayToJson(this.steps)
};
return {'class': 'AnimationGroupMetadata', 'value': _arrayToJson(this.steps)};
}
}
@ -268,19 +227,20 @@ export class CompileDiDependencyMetadata {
token: CompileTokenMetadata;
value: any;
constructor({isAttribute, isSelf, isHost, isSkipSelf, isOptional, isValue, query, viewQuery,
token, value}: {
isAttribute?: boolean,
isSelf?: boolean,
isHost?: boolean,
isSkipSelf?: boolean,
isOptional?: boolean,
isValue?: boolean,
query?: CompileQueryMetadata,
viewQuery?: CompileQueryMetadata,
token?: CompileTokenMetadata,
value?: any
} = {}) {
constructor(
{isAttribute, isSelf, isHost, isSkipSelf, isOptional, isValue, query, viewQuery, token,
value}: {
isAttribute?: boolean,
isSelf?: boolean,
isHost?: boolean,
isSkipSelf?: boolean,
isOptional?: boolean,
isValue?: boolean,
query?: CompileQueryMetadata,
viewQuery?: CompileQueryMetadata,
token?: CompileTokenMetadata,
value?: any
} = {}) {
this.isAttribute = normalizeBool(isAttribute);
this.isSelf = normalizeBool(isSelf);
this.isHost = normalizeBool(isHost);
@ -435,11 +395,9 @@ export class CompileTokenMetadata implements CompileMetadataWithIdentifier {
identifierIsInstance: boolean;
private _assetCacheKey = UNDEFINED;
constructor({value, identifier, identifierIsInstance}: {
value?: any,
identifier?: CompileIdentifierMetadata,
identifierIsInstance?: boolean
}) {
constructor(
{value, identifier, identifierIsInstance}:
{value?: any, identifier?: CompileIdentifierMetadata, identifierIsInstance?: boolean}) {
this.value = value;
this.identifier = identifier;
this.identifierIsInstance = normalizeBool(identifierIsInstance);
@ -473,11 +431,9 @@ export class CompileTokenMetadata implements CompileMetadataWithIdentifier {
if (this._assetCacheKey === UNDEFINED) {
if (isPresent(this.identifier)) {
if (isPresent(this.identifier.moduleUrl) &&
isPresent(getUrlScheme(this.identifier.moduleUrl))) {
var uri = reflector.importUri({
'filePath': this.identifier.moduleUrl,
'name': this.identifier.name
});
isPresent(getUrlScheme(this.identifier.moduleUrl))) {
var uri = reflector.importUri(
{'filePath': this.identifier.moduleUrl, 'name': this.identifier.name});
this._assetCacheKey = `${this.identifier.name}|${uri}|${this.identifierIsInstance}`;
} else {
this._assetCacheKey = null;
@ -493,7 +449,7 @@ export class CompileTokenMetadata implements CompileMetadataWithIdentifier {
var rk = this.runtimeCacheKey;
var ak = this.assetCacheKey;
return (isPresent(rk) && rk == token2.runtimeCacheKey) ||
(isPresent(ak) && ak == token2.assetCacheKey);
(isPresent(ak) && ak == token2.assetCacheKey);
}
get name(): string {
@ -647,15 +603,16 @@ export class CompileTemplateMetadata {
styleUrls: string[];
animations: CompileAnimationEntryMetadata[];
ngContentSelectors: string[];
constructor({encapsulation, template, templateUrl, styles, styleUrls, animations, ngContentSelectors}: {
encapsulation?: ViewEncapsulation,
template?: string,
templateUrl?: string,
styles?: string[],
styleUrls?: string[],
ngContentSelectors?: string[],
animations?: CompileAnimationEntryMetadata[]
} = {}) {
constructor(
{encapsulation, template, templateUrl, styles, styleUrls, animations, ngContentSelectors}: {
encapsulation?: ViewEncapsulation,
template?: string,
templateUrl?: string,
styles?: string[],
styleUrls?: string[],
ngContentSelectors?: string[],
animations?: CompileAnimationEntryMetadata[]
} = {}) {
this.encapsulation = encapsulation;
this.template = template;
this.templateUrl = templateUrl;
@ -666,11 +623,12 @@ export class CompileTemplateMetadata {
}
static fromJson(data: {[key: string]: any}): CompileTemplateMetadata {
var animations = <CompileAnimationEntryMetadata[]>_arrayFromJson(data['animations'], metadataFromJson);
var animations =
<CompileAnimationEntryMetadata[]>_arrayFromJson(data['animations'], metadataFromJson);
return new CompileTemplateMetadata({
encapsulation: isPresent(data['encapsulation']) ?
VIEW_ENCAPSULATION_VALUES[data['encapsulation']] :
data['encapsulation'],
VIEW_ENCAPSULATION_VALUES[data['encapsulation']] :
data['encapsulation'],
template: data['template'],
templateUrl: data['templateUrl'],
styles: data['styles'],
@ -682,8 +640,8 @@ export class CompileTemplateMetadata {
toJson(): {[key: string]: any} {
return {
'encapsulation':
isPresent(this.encapsulation) ? serializeEnum(this.encapsulation) : this.encapsulation,
'encapsulation': isPresent(this.encapsulation) ? serializeEnum(this.encapsulation) :
this.encapsulation,
'template': this.template,
'templateUrl': this.templateUrl,
'styles': this.styles,
@ -698,25 +656,26 @@ export class CompileTemplateMetadata {
* Metadata regarding compilation of a directive.
*/
export class CompileDirectiveMetadata implements CompileMetadataWithType {
static create({type, isComponent, selector, exportAs, changeDetection, inputs, outputs, host,
lifecycleHooks, providers, viewProviders, queries, viewQueries, template}: {
type?: CompileTypeMetadata,
isComponent?: boolean,
selector?: string,
exportAs?: string,
changeDetection?: ChangeDetectionStrategy,
inputs?: string[],
outputs?: string[],
host?: {[key: string]: string},
lifecycleHooks?: LifecycleHooks[],
providers?:
Array<CompileProviderMetadata | CompileTypeMetadata | CompileIdentifierMetadata | any[]>,
viewProviders?:
Array<CompileProviderMetadata | CompileTypeMetadata | CompileIdentifierMetadata | any[]>,
queries?: CompileQueryMetadata[],
viewQueries?: CompileQueryMetadata[],
template?: CompileTemplateMetadata
} = {}): CompileDirectiveMetadata {
static create(
{type, isComponent, selector, exportAs, changeDetection, inputs, outputs, host,
lifecycleHooks, providers, viewProviders, queries, viewQueries, template}: {
type?: CompileTypeMetadata,
isComponent?: boolean,
selector?: string,
exportAs?: string,
changeDetection?: ChangeDetectionStrategy,
inputs?: string[],
outputs?: string[],
host?: {[key: string]: string},
lifecycleHooks?: LifecycleHooks[],
providers?:
Array<CompileProviderMetadata|CompileTypeMetadata|CompileIdentifierMetadata|any[]>,
viewProviders?:
Array<CompileProviderMetadata|CompileTypeMetadata|CompileIdentifierMetadata|any[]>,
queries?: CompileQueryMetadata[],
viewQueries?: CompileQueryMetadata[],
template?: CompileTemplateMetadata
} = {}): CompileDirectiveMetadata {
var hostListeners: {[key: string]: string} = {};
var hostProperties: {[key: string]: string} = {};
var hostAttributes: {[key: string]: string} = {};
@ -787,28 +746,29 @@ export class CompileDirectiveMetadata implements CompileMetadataWithType {
viewQueries: CompileQueryMetadata[];
template: CompileTemplateMetadata;
constructor({type, isComponent, selector, exportAs, changeDetection, inputs, outputs,
hostListeners, hostProperties, hostAttributes, lifecycleHooks, providers,
viewProviders, queries, viewQueries, template}: {
type?: CompileTypeMetadata,
isComponent?: boolean,
selector?: string,
exportAs?: string,
changeDetection?: ChangeDetectionStrategy,
inputs?: {[key: string]: string},
outputs?: {[key: string]: string},
hostListeners?: {[key: string]: string},
hostProperties?: {[key: string]: string},
hostAttributes?: {[key: string]: string},
lifecycleHooks?: LifecycleHooks[],
providers?:
Array<CompileProviderMetadata | CompileTypeMetadata | CompileIdentifierMetadata | any[]>,
viewProviders?:
Array<CompileProviderMetadata | CompileTypeMetadata | CompileIdentifierMetadata | any[]>,
queries?: CompileQueryMetadata[],
viewQueries?: CompileQueryMetadata[],
template?: CompileTemplateMetadata
} = {}) {
constructor(
{type, isComponent, selector, exportAs, changeDetection, inputs, outputs, hostListeners,
hostProperties, hostAttributes, lifecycleHooks, providers, viewProviders, queries,
viewQueries, template}: {
type?: CompileTypeMetadata,
isComponent?: boolean,
selector?: string,
exportAs?: string,
changeDetection?: ChangeDetectionStrategy,
inputs?: {[key: string]: string},
outputs?: {[key: string]: string},
hostListeners?: {[key: string]: string},
hostProperties?: {[key: string]: string},
hostAttributes?: {[key: string]: string},
lifecycleHooks?: LifecycleHooks[],
providers?:
Array<CompileProviderMetadata|CompileTypeMetadata|CompileIdentifierMetadata|any[]>,
viewProviders?:
Array<CompileProviderMetadata|CompileTypeMetadata|CompileIdentifierMetadata|any[]>,
queries?: CompileQueryMetadata[],
viewQueries?: CompileQueryMetadata[],
template?: CompileTemplateMetadata
} = {}) {
this.type = type;
this.isComponent = isComponent;
this.selector = selector;
@ -836,8 +796,8 @@ export class CompileDirectiveMetadata implements CompileMetadataWithType {
exportAs: data['exportAs'],
type: isPresent(data['type']) ? CompileTypeMetadata.fromJson(data['type']) : data['type'],
changeDetection: isPresent(data['changeDetection']) ?
CHANGE_DETECTION_STRATEGY_VALUES[data['changeDetection']] :
data['changeDetection'],
CHANGE_DETECTION_STRATEGY_VALUES[data['changeDetection']] :
data['changeDetection'],
inputs: data['inputs'],
outputs: data['outputs'],
hostListeners: data['hostListeners'],
@ -881,8 +841,8 @@ export class CompileDirectiveMetadata implements CompileMetadataWithType {
/**
* Construct {@link CompileDirectiveMetadata} from {@link ComponentTypeMetadata} and a selector.
*/
export function createHostComponentMeta(componentType: CompileTypeMetadata,
componentSelector: string): CompileDirectiveMetadata {
export function createHostComponentMeta(
componentType: CompileTypeMetadata, componentSelector: string): CompileDirectiveMetadata {
var template = CssSelector.parse(componentSelector)[0].getMatchingElementTemplate();
return CompileDirectiveMetadata.create({
type: new CompileTypeMetadata({
@ -891,8 +851,14 @@ export function createHostComponentMeta(componentType: CompileTypeMetadata,
moduleUrl: componentType.moduleUrl,
isHost: true
}),
template: new CompileTemplateMetadata(
{template: template, templateUrl: '', styles: [], styleUrls: [], ngContentSelectors: [], animations:[]}),
template: new CompileTemplateMetadata({
template: template,
templateUrl: '',
styles: [],
styleUrls: [],
ngContentSelectors: [],
animations: []
}),
changeDetection: ChangeDetectionStrategy.Default,
inputs: [],
outputs: [],
@ -966,7 +932,7 @@ function _arrayFromJson(obj: any[], fn: (a: {[key: string]: any}) => any): any {
return isBlank(obj) ? null : obj.map(o => _objFromJson(o, fn));
}
function _arrayToJson(obj: any[]): string | {[key: string]: any} {
function _arrayToJson(obj: any[]): string|{[key: string]: any} {
return isBlank(obj) ? null : obj.map(_objToJson);
}
@ -976,7 +942,7 @@ function _objFromJson(obj: any, fn: (a: {[key: string]: any}) => any): any {
return fn(obj);
}
function _objToJson(obj: any): string | {[key: string]: any} {
function _objToJson(obj: any): string|{[key: string]: any} {
if (isArray(obj)) return _arrayToJson(obj);
if (isString(obj) || isBlank(obj) || isBoolean(obj) || isNumber(obj)) return obj;
return obj.toJson();

View File

@ -39,24 +39,14 @@ function _createCompilerConfig() {
* A set of providers that provide `RuntimeCompiler` and its dependencies to use for
* template compilation.
*/
export const COMPILER_PROVIDERS: Array<any | Type | {[k: string]: any} | any[]> =
export const COMPILER_PROVIDERS: Array<any|Type|{[k: string]: any}|any[]> =
/*@ts2dart_const*/[
Lexer,
Parser,
HtmlParser,
TemplateParser,
DirectiveNormalizer,
CompileMetadataResolver,
DEFAULT_PACKAGE_URL_PROVIDER,
StyleCompiler,
ViewCompiler,
Lexer, Parser, HtmlParser, TemplateParser, DirectiveNormalizer, CompileMetadataResolver,
DEFAULT_PACKAGE_URL_PROVIDER, StyleCompiler, ViewCompiler,
/*@ts2dart_Provider*/ {provide: CompilerConfig, useFactory: _createCompilerConfig, deps: []},
RuntimeCompiler,
/*@ts2dart_Provider*/ {provide: ComponentResolver, useExisting: RuntimeCompiler},
DomElementSchemaRegistry,
/*@ts2dart_Provider*/ {provide: ElementSchemaRegistry, useExisting: DomElementSchemaRegistry},
UrlResolver,
ViewResolver,
DirectiveResolver,
PipeResolver
UrlResolver, ViewResolver, DirectiveResolver, PipeResolver
];

View File

@ -1,16 +1,18 @@
import {isBlank} from '../src/facade/lang';
import {unimplemented} from '../src/facade/exceptions';
import {Identifiers} from './identifiers';
import {CompileIdentifierMetadata} from './compile_metadata';
import {ViewEncapsulation} from '@angular/core';
import {unimplemented} from '../src/facade/exceptions';
import {isBlank} from '../src/facade/lang';
import {CompileIdentifierMetadata} from './compile_metadata';
import {Identifiers} from './identifiers';
export class CompilerConfig {
public renderTypes: RenderTypes;
public defaultEncapsulation: ViewEncapsulation;
constructor(public genDebugInfo: boolean, public logBindingUpdate: boolean,
public useJit: boolean, renderTypes: RenderTypes = null,
defaultEncapsulation: ViewEncapsulation = null) {
constructor(
public genDebugInfo: boolean, public logBindingUpdate: boolean, public useJit: boolean,
renderTypes: RenderTypes = null, defaultEncapsulation: ViewEncapsulation = null) {
if (isBlank(renderTypes)) {
renderTypes = new DefaultRenderTypes();
}

View File

@ -1,65 +1,9 @@
import {NumberWrapper, StringWrapper, isPresent, resolveEnumToken} from '../facade/lang';
import {$$, $0, $9, $A, $AMPERSAND, $AT, $BACKSLASH, $BANG, $CARET, $COLON, $COMMA, $CR, $DQ, $EOF, $EQ, $FF, $GT, $HASH, $LBRACE, $LBRACKET, $LF, $LPAREN, $MINUS, $PERCENT, $PERIOD, $PIPE, $PLUS, $QUESTION, $RBRACE, $RBRACKET, $RPAREN, $SEMICOLON, $SLASH, $SQ, $STAR, $TILDA, $VTAB, $Z, $_, $a, $z, isWhitespace} from '@angular/compiler/src/chars';
import {BaseException} from '../facade/exceptions';
import {NumberWrapper, StringWrapper, isPresent, resolveEnumToken} from '../facade/lang';
import {
isWhitespace,
$EOF,
$HASH,
$TILDA,
$CARET,
$PERCENT,
$$,
$_,
$COLON,
$SQ,
$DQ,
$EQ,
$SLASH,
$BACKSLASH,
$PERIOD,
$STAR,
$PLUS,
$LPAREN,
$RPAREN,
$LBRACE,
$RBRACE,
$LBRACKET,
$RBRACKET,
$PIPE,
$COMMA,
$SEMICOLON,
$MINUS,
$BANG,
$QUESTION,
$AT,
$AMPERSAND,
$GT,
$a,
$A,
$z,
$Z,
$0,
$9,
$FF,
$CR,
$LF,
$VTAB
} from '@angular/compiler/src/chars';
export {
$EOF,
$AT,
$RBRACE,
$LBRACE,
$LBRACKET,
$RBRACKET,
$LPAREN,
$RPAREN,
$COMMA,
$COLON,
$SEMICOLON,
isWhitespace
} from '@angular/compiler/src/chars';
export {$AT, $COLON, $COMMA, $EOF, $LBRACE, $LBRACKET, $LPAREN, $RBRACE, $RBRACKET, $RPAREN, $SEMICOLON, isWhitespace} from '@angular/compiler/src/chars';
export enum CssTokenType {
EOF,
@ -94,35 +38,37 @@ export class LexedCssResult {
constructor(public error: CssScannerError, public token: CssToken) {}
}
export function generateErrorMessage(input: string, message: string, errorValue: string,
index: number, row: number, column: number): string {
export function generateErrorMessage(
input: string, message: string, errorValue: string, index: number, row: number,
column: number): string {
return `${message} at column ${row}:${column} in expression [` +
findProblemCode(input, errorValue, index, column) + ']';
findProblemCode(input, errorValue, index, column) + ']';
}
export function findProblemCode(input: string, errorValue: string, index: number,
column: number): string {
export function findProblemCode(
input: string, errorValue: string, index: number, column: number): string {
var endOfProblemLine = index;
var current = charCode(input, index);
while (current > 0 && !isNewline(current)) {
current = charCode(input, ++endOfProblemLine);
}
var choppedString = input.substring(0, endOfProblemLine);
var pointerPadding = "";
var pointerPadding = '';
for (var i = 0; i < column; i++) {
pointerPadding += " ";
pointerPadding += ' ';
}
var pointerString = "";
var pointerString = '';
for (var i = 0; i < errorValue.length; i++) {
pointerString += "^";
pointerString += '^';
}
return choppedString + "\n" + pointerPadding + pointerString + "\n";
return choppedString + '\n' + pointerPadding + pointerString + '\n';
}
export class CssToken {
numValue: number;
constructor(public index: number, public column: number, public line: number,
public type: CssTokenType, public strValue: string) {
constructor(
public index: number, public column: number, public line: number, public type: CssTokenType,
public strValue: string) {
this.numValue = charCode(strValue, 0);
}
}
@ -248,7 +194,7 @@ export class CssScanner {
var next = output.token;
if (!isPresent(next)) {
next = new CssToken(0, 0, 0, CssTokenType.EOF, "end of file");
next = new CssToken(0, 0, 0, CssTokenType.EOF, 'end of file');
}
var isMatchingType: any /** TODO #9100 */;
@ -265,16 +211,17 @@ export class CssScanner {
var error: any /** TODO #9100 */ = null;
if (!isMatchingType || (isPresent(value) && value != next.strValue)) {
var errorMessage = resolveEnumToken(CssTokenType, next.type) + " does not match expected " +
resolveEnumToken(CssTokenType, type) + " value";
var errorMessage = resolveEnumToken(CssTokenType, next.type) + ' does not match expected ' +
resolveEnumToken(CssTokenType, type) + ' value';
if (isPresent(value)) {
errorMessage += ' ("' + next.strValue + '" should match "' + value + '")';
}
error = new CssScannerError(
next, generateErrorMessage(this.input, errorMessage, next.strValue, previousIndex,
previousLine, previousColumn));
next, generateErrorMessage(
this.input, errorMessage, next.strValue, previousIndex, previousLine,
previousColumn));
}
return new LexedCssResult(error, next);
@ -354,8 +301,8 @@ export class CssScanner {
}
scanComment(): CssToken {
if (this.assertCondition(isCommentStart(this.peek, this.peekPeek),
"Expected comment start value")) {
if (this.assertCondition(
isCommentStart(this.peek, this.peekPeek), 'Expected comment start value')) {
return null;
}
@ -392,8 +339,8 @@ export class CssScanner {
}
scanString(): CssToken {
if (this.assertCondition(isStringStart(this.peek, this.peekPeek),
"Unexpected non-string starting value")) {
if (this.assertCondition(
isStringStart(this.peek, this.peekPeek), 'Unexpected non-string starting value')) {
return null;
}
@ -412,7 +359,7 @@ export class CssScanner {
this.advance();
}
if (this.assertCondition(this.peek == target, "Unterminated quote")) {
if (this.assertCondition(this.peek == target, 'Unterminated quote')) {
return null;
}
this.advance();
@ -442,8 +389,8 @@ export class CssScanner {
}
scanIdentifier(): CssToken {
if (this.assertCondition(isIdentifierStart(this.peek, this.peekPeek),
'Expected identifier starting value')) {
if (this.assertCondition(
isIdentifierStart(this.peek, this.peekPeek), 'Expected identifier starting value')) {
return null;
}
@ -475,8 +422,9 @@ export class CssScanner {
scanCharacter(): CssToken {
var start = this.index;
var startingColumn = this.column;
if (this.assertCondition(isValidCssCharacter(this.peek, this._currentMode),
charStr(this.peek) + ' is not a valid CSS character')) {
if (this.assertCondition(
isValidCssCharacter(this.peek, this._currentMode),
charStr(this.peek) + ' is not a valid CSS character')) {
return null;
}
@ -563,12 +511,12 @@ function isIdentifierStart(code: number, next: number): boolean {
}
return ($a <= target && target <= $z) || ($A <= target && target <= $Z) || target == $BACKSLASH ||
target == $MINUS || target == $_;
target == $MINUS || target == $_;
}
function isIdentifierPart(target: number): boolean {
return ($a <= target && target <= $z) || ($A <= target && target <= $Z) || target == $BACKSLASH ||
target == $MINUS || target == $_ || isDigit(target);
target == $MINUS || target == $_ || isDigit(target);
}
function isValidPseudoSelectorCharacter(code: number): boolean {

View File

@ -1,38 +1,7 @@
import {
ParseSourceSpan,
ParseSourceFile,
ParseLocation,
ParseError
} from '@angular/compiler/src/parse_util';
import {$AT, $COLON, $COMMA, $EOF, $LBRACE, $LBRACKET, $LPAREN, $RBRACE, $RBRACKET, $RPAREN, $SEMICOLON, CssLexerMode, CssScanner, CssScannerError, CssToken, CssTokenType, generateErrorMessage, isNewline} from '@angular/compiler/src/css/lexer';
import {ParseError, ParseLocation, ParseSourceFile, ParseSourceSpan} from '@angular/compiler/src/parse_util';
import {
bitWiseOr,
bitWiseAnd,
NumberWrapper,
StringWrapper,
isPresent
} from '../facade/lang';
import {
CssLexerMode,
CssToken,
CssTokenType,
CssScanner,
CssScannerError,
generateErrorMessage,
$AT,
$EOF,
$RBRACE,
$LBRACE,
$LBRACKET,
$RBRACKET,
$LPAREN,
$RPAREN,
$COMMA,
$COLON,
$SEMICOLON,
isNewline
} from '@angular/compiler/src/css/lexer';
import {NumberWrapper, StringWrapper, bitWiseAnd, bitWiseOr, isPresent} from '../facade/lang';
export {CssToken} from '@angular/compiler/src/css/lexer';
@ -60,7 +29,7 @@ const SEMICOLON_DELIM = 32;
const NEWLINE_DELIM = 64;
const RPAREN_DELIM = 128;
function mergeTokens(tokens: CssToken[], separator: string = ""): CssToken {
function mergeTokens(tokens: CssToken[], separator: string = ''): CssToken {
var mainToken = tokens[0];
var str = mainToken.strValue;
for (var i = 1; i < tokens.length; i++) {
@ -205,8 +174,9 @@ export class CssParser {
var token = this._scan();
this._assertCondition(token.type == CssTokenType.AtKeyword,
`The CSS Rule ${token.strValue} is not a valid [@] rule.`, token);
this._assertCondition(
token.type == CssTokenType.AtKeyword,
`The CSS Rule ${token.strValue} is not a valid [@] rule.`, token);
var block: any /** TODO #9100 */, type = this._resolveBlockType(token);
switch (type) {
@ -245,11 +215,12 @@ export class CssParser {
default:
var listOfTokens: any[] /** TODO #9100 */ = [];
this._scanner.setMode(CssLexerMode.ALL);
this._error(generateErrorMessage(
this._scanner.input,
`The CSS "at" rule "${token.strValue}" is not allowed to used here`,
token.strValue, token.index, token.line, token.column),
token);
this._error(
generateErrorMessage(
this._scanner.input,
`The CSS "at" rule "${token.strValue}" is not allowed to used here`, token.strValue,
token.index, token.line, token.column),
token);
this._collectUntilDelim(bitWiseOr([delimiters, LBRACE_DELIM, SEMICOLON_DELIM]))
.forEach((token) => { listOfTokens.push(token); });
@ -403,7 +374,7 @@ export class CssParser {
// contains an inner selector that needs to be parsed
// in isolation
if (this._scanner.getMode() == CssLexerMode.PSEUDO_SELECTOR && isPresent(previousToken) &&
previousToken.numValue == $COLON && token.strValue == "not" &&
previousToken.numValue == $COLON && token.strValue == 'not' &&
this._scanner.peek == $LPAREN) {
selectorCssTokens.push(token);
selectorCssTokens.push(this._consume(CssTokenType.Character, '('));
@ -453,7 +424,7 @@ export class CssParser {
this._scanner.setMode(CssLexerMode.STYLE_VALUE);
var strValue = "";
var strValue = '';
var tokens: any[] /** TODO #9100 */ = [];
var previous: CssToken;
while (!characterContainsDelimiter(this._scanner.peek, delimiters)) {
@ -493,9 +464,9 @@ export class CssParser {
this._consume(CssTokenType.Character, ';');
} else if (code != $RBRACE) {
this._error(
generateErrorMessage(this._scanner.input,
`The CSS key/value definition did not end with a semicolon`,
previous.strValue, previous.index, previous.line, previous.column),
generateErrorMessage(
this._scanner.input, `The CSS key/value definition did not end with a semicolon`,
previous.strValue, previous.index, previous.line, previous.column),
previous);
}
@ -592,7 +563,7 @@ export class CssParser {
remainingTokens.forEach((token) => { propStr.push(token.strValue); });
}
prop = new CssToken(prop.index, prop.column, prop.line, prop.type, propStr.join(" "));
prop = new CssToken(prop.index, prop.column, prop.line, prop.type, propStr.join(' '));
}
// this means we've reached the end of the definition and/or block
@ -608,10 +579,11 @@ export class CssParser {
if (parseValue) {
value = this._parseValue(delimiters);
} else {
this._error(generateErrorMessage(this._scanner.input,
`The CSS property was not paired with a style value`,
prop.strValue, prop.index, prop.line, prop.column),
prop);
this._error(
generateErrorMessage(
this._scanner.input, `The CSS property was not paired with a style value`,
prop.strValue, prop.index, prop.line, prop.column),
prop);
}
return new CssDefinitionAST(prop, value);
@ -629,8 +601,8 @@ export class CssParser {
/** @internal */
_error(message: string, problemToken: CssToken) {
var length = problemToken.strValue.length;
var error = CssParseError.create(this._file, 0, problemToken.line, problemToken.column, length,
message);
var error = CssParseError.create(
this._file, 0, problemToken.line, problemToken.column, length, message);
this._errors.push(error);
}
}
@ -657,7 +629,7 @@ export class CssKeyframeRuleAST extends CssBlockRuleAST {
export class CssKeyframeDefinitionAST extends CssBlockRuleAST {
public steps: any /** TODO #9100 */;
constructor(_steps: CssToken[], block: CssBlockAST) {
super(BlockType.Keyframes, block, mergeTokens(_steps, ","));
super(BlockType.Keyframes, block, mergeTokens(_steps, ','));
this.steps = _steps;
}
visit(visitor: CssASTVisitor, context?: any) {
@ -669,10 +641,11 @@ export class CssBlockDefinitionRuleAST extends CssBlockRuleAST {
public strValue: string;
constructor(type: BlockType, public query: CssToken[], block: CssBlockAST) {
super(type, block);
this.strValue = query.map(token => token.strValue).join("");
this.strValue = query.map(token => token.strValue).join('');
var firstCssToken: CssToken = query[0];
this.name = new CssToken(firstCssToken.index, firstCssToken.column, firstCssToken.line,
CssTokenType.Identifier, this.strValue);
this.name = new CssToken(
firstCssToken.index, firstCssToken.column, firstCssToken.line, CssTokenType.Identifier,
this.strValue);
}
visit(visitor: CssASTVisitor, context?: any) { visitor.visitCssBlock(this.block, context); }
}
@ -692,7 +665,7 @@ export class CssSelectorRuleAST extends CssBlockRuleAST {
constructor(public selectors: CssSelectorAST[], block: CssBlockAST) {
super(BlockType.Selector, block);
this.strValue = selectors.map(selector => selector.strValue).join(",");
this.strValue = selectors.map(selector => selector.strValue).join(',');
}
visit(visitor: CssASTVisitor, context?: any) { visitor.visitCssSelectorRule(this, context); }
@ -707,7 +680,7 @@ export class CssSelectorAST extends CssAST {
public strValue: any /** TODO #9100 */;
constructor(public tokens: CssToken[], public isComplex: boolean = false) {
super();
this.strValue = tokens.map(token => token.strValue).join("");
this.strValue = tokens.map(token => token.strValue).join('');
}
visit(visitor: CssASTVisitor, context?: any) { visitor.visitCssSelector(this, context); }
}
@ -723,12 +696,13 @@ export class CssStyleSheetAST extends CssAST {
}
export class CssParseError extends ParseError {
static create(file: ParseSourceFile, offset: number, line: number, col: number, length: number,
errMsg: string): CssParseError {
static create(
file: ParseSourceFile, offset: number, line: number, col: number, length: number,
errMsg: string): CssParseError {
var start = new ParseLocation(file, offset, line, col);
var end = new ParseLocation(file, offset, line, col + length);
var span = new ParseSourceSpan(start, end);
return new CssParseError(span, "CSS Parse Error: " + errMsg);
return new CssParseError(span, 'CSS Parse Error: ' + errMsg);
}
constructor(span: ParseSourceSpan, message: string) { super(span, message); }

View File

@ -1,13 +1,4 @@
import {
OnInit,
OnDestroy,
DoCheck,
OnChanges,
AfterContentInit,
AfterContentChecked,
AfterViewInit,
AfterViewChecked,
} from '@angular/core';
import {OnInit, OnDestroy, DoCheck, OnChanges, AfterContentInit, AfterContentChecked, AfterViewInit, AfterViewChecked,} from '@angular/core';
import {reflector, LifecycleHooks} from '../core_private';
import {Type} from '../src/facade/lang';

View File

@ -1,28 +1,15 @@
import {Injectable, ViewEncapsulation} from '@angular/core';
import {isPresent, isBlank} from '../src/facade/lang';
import {BaseException} from '../src/facade/exceptions';
import {PromiseWrapper} from '../src/facade/async';
import {BaseException} from '../src/facade/exceptions';
import {isBlank, isPresent} from '../src/facade/lang';
import {
CompileTypeMetadata,
CompileDirectiveMetadata,
CompileTemplateMetadata,
} from './compile_metadata';
import {CompileTypeMetadata, CompileDirectiveMetadata, CompileTemplateMetadata,} from './compile_metadata';
import {XHR} from './xhr';
import {UrlResolver} from './url_resolver';
import {extractStyleUrls, isStyleUrlResolvable} from './style_url_resolver';
import {
HtmlAstVisitor,
HtmlElementAst,
HtmlTextAst,
HtmlAttrAst,
HtmlCommentAst,
HtmlExpansionAst,
HtmlExpansionCaseAst,
htmlVisitAll
} from './html_ast';
import {HtmlAstVisitor, HtmlElementAst, HtmlTextAst, HtmlAttrAst, HtmlCommentAst, HtmlExpansionAst, HtmlExpansionCaseAst, htmlVisitAll} from './html_ast';
import {HtmlParser} from './html_parser';
import {CompilerConfig} from './config';
@ -31,8 +18,9 @@ import {preparseElement, PreparsedElementType} from './template_preparser';
@Injectable()
export class DirectiveNormalizer {
constructor(private _xhr: XHR, private _urlResolver: UrlResolver,
private _htmlParser: HtmlParser, private _config: CompilerConfig) {}
constructor(
private _xhr: XHR, private _urlResolver: UrlResolver, private _htmlParser: HtmlParser,
private _config: CompilerConfig) {}
normalizeDirective(directive: CompileDirectiveMetadata): Promise<CompileDirectiveMetadata> {
if (!directive.isComponent) {
@ -60,23 +48,25 @@ export class DirectiveNormalizer {
}));
}
normalizeTemplate(directiveType: CompileTypeMetadata,
template: CompileTemplateMetadata): Promise<CompileTemplateMetadata> {
normalizeTemplate(directiveType: CompileTypeMetadata, template: CompileTemplateMetadata):
Promise<CompileTemplateMetadata> {
if (isPresent(template.template)) {
return PromiseWrapper.resolve(this.normalizeLoadedTemplate(
directiveType, template, template.template, directiveType.moduleUrl));
} else if (isPresent(template.templateUrl)) {
var sourceAbsUrl = this._urlResolver.resolve(directiveType.moduleUrl, template.templateUrl);
return this._xhr.get(sourceAbsUrl)
.then(templateContent => this.normalizeLoadedTemplate(directiveType, template,
templateContent, sourceAbsUrl));
.then(
templateContent => this.normalizeLoadedTemplate(
directiveType, template, templateContent, sourceAbsUrl));
} else {
throw new BaseException(`No template specified for component ${directiveType.name}`);
}
}
normalizeLoadedTemplate(directiveType: CompileTypeMetadata, templateMeta: CompileTemplateMetadata,
template: string, templateAbsUrl: string): CompileTemplateMetadata {
normalizeLoadedTemplate(
directiveType: CompileTypeMetadata, templateMeta: CompileTemplateMetadata, template: string,
templateAbsUrl: string): CompileTemplateMetadata {
var rootNodesAndErrors = this._htmlParser.parse(template, directiveType.name);
if (rootNodesAndErrors.errors.length > 0) {
var errorString = rootNodesAndErrors.errors.join('\n');

View File

@ -1,17 +1,4 @@
import {
resolveForwardRef,
Injectable,
DirectiveMetadata,
ComponentMetadata,
InputMetadata,
OutputMetadata,
HostBindingMetadata,
HostListenerMetadata,
ContentChildrenMetadata,
ViewChildrenMetadata,
ContentChildMetadata,
ViewChildMetadata,
} from '@angular/core';
import {resolveForwardRef, Injectable, DirectiveMetadata, ComponentMetadata, InputMetadata, OutputMetadata, HostBindingMetadata, HostListenerMetadata, ContentChildrenMetadata, ViewChildrenMetadata, ContentChildMetadata, ViewChildMetadata,} from '@angular/core';
import {ReflectorReader, reflector} from '../core_private';
import {Type, isPresent, stringify} from '../src/facade/lang';
@ -58,9 +45,9 @@ export class DirectiveResolver {
throw new BaseException(`No Directive annotation found on ${stringify(type)}`);
}
private _mergeWithPropertyMetadata(dm: DirectiveMetadata,
propertyMetadata: {[key: string]: any[]},
directiveType: Type): DirectiveMetadata {
private _mergeWithPropertyMetadata(
dm: DirectiveMetadata, propertyMetadata: {[key: string]: any[]},
directiveType: Type): DirectiveMetadata {
var inputs: any[] /** TODO #9100 */ = [];
var outputs: any[] /** TODO #9100 */ = [];
var host: {[key: string]: string} = {};
@ -117,9 +104,9 @@ export class DirectiveResolver {
return this._merge(dm, inputs, outputs, host, queries, directiveType);
}
private _merge(dm: DirectiveMetadata, inputs: string[], outputs: string[],
host: {[key: string]: string}, queries: {[key: string]: any},
directiveType: Type): DirectiveMetadata {
private _merge(
dm: DirectiveMetadata, inputs: string[], outputs: string[], host: {[key: string]: string},
queries: {[key: string]: any}, directiveType: Type): DirectiveMetadata {
var mergedInputs = isPresent(dm.inputs) ? ListWrapper.concat(dm.inputs, inputs) : inputs;
var mergedOutputs: any /** TODO #9100 */;

View File

@ -2,7 +2,7 @@ import {ListWrapper} from '../facade/collection';
export class AST {
visit(visitor: AstVisitor, context: any = null): any { return null; }
toString(): string { return "AST"; }
toString(): string { return 'AST'; }
}
/**
@ -23,7 +23,7 @@ export class Quote extends AST {
super();
}
visit(visitor: AstVisitor, context: any = null): any { return visitor.visitQuote(this, context); }
toString(): string { return "Quote"; }
toString(): string { return 'Quote'; }
}
export class EmptyExpr extends AST {
@ -163,8 +163,9 @@ export class ASTWithSource extends AST {
}
export class TemplateBinding {
constructor(public key: string, public keyIsVar: boolean, public name: string,
public expression: ASTWithSource) {}
constructor(
public key: string, public keyIsVar: boolean, public name: string,
public expression: ASTWithSource) {}
}
export interface AstVisitor {
@ -316,8 +317,8 @@ export class AstTransformer implements AstVisitor {
}
visitConditional(ast: Conditional, context: any): AST {
return new Conditional(ast.condition.visit(this), ast.trueExp.visit(this),
ast.falseExp.visit(this));
return new Conditional(
ast.condition.visit(this), ast.trueExp.visit(this), ast.falseExp.visit(this));
}
visitPipe(ast: BindingPipe, context: any): AST {

View File

@ -1,7 +1,8 @@
import {Injectable} from '@angular/core';
import {SetWrapper} from '../facade/collection';
import {NumberWrapper, StringJoiner, StringWrapper, isPresent} from '../facade/lang';
import {BaseException} from '../facade/exceptions';
import {NumberWrapper, StringJoiner, StringWrapper, isPresent} from '../facade/lang';
export enum TokenType {
Character,
@ -27,8 +28,9 @@ export class Lexer {
}
export class Token {
constructor(public index: number, public type: TokenType, public numValue: number,
public strValue: string) {}
constructor(
public index: number, public type: TokenType, public numValue: number,
public strValue: string) {}
isCharacter(code: number): boolean {
return (this.type == TokenType.Character && this.numValue == code);
@ -47,20 +49,20 @@ export class Token {
isKeyword(): boolean { return (this.type == TokenType.Keyword); }
isKeywordDeprecatedVar(): boolean {
return (this.type == TokenType.Keyword && this.strValue == "var");
return (this.type == TokenType.Keyword && this.strValue == 'var');
}
isKeywordLet(): boolean { return (this.type == TokenType.Keyword && this.strValue == "let"); }
isKeywordLet(): boolean { return (this.type == TokenType.Keyword && this.strValue == 'let'); }
isKeywordNull(): boolean { return (this.type == TokenType.Keyword && this.strValue == "null"); }
isKeywordNull(): boolean { return (this.type == TokenType.Keyword && this.strValue == 'null'); }
isKeywordUndefined(): boolean {
return (this.type == TokenType.Keyword && this.strValue == "undefined");
return (this.type == TokenType.Keyword && this.strValue == 'undefined');
}
isKeywordTrue(): boolean { return (this.type == TokenType.Keyword && this.strValue == "true"); }
isKeywordTrue(): boolean { return (this.type == TokenType.Keyword && this.strValue == 'true'); }
isKeywordFalse(): boolean { return (this.type == TokenType.Keyword && this.strValue == "false"); }
isKeywordFalse(): boolean { return (this.type == TokenType.Keyword && this.strValue == 'false'); }
toNumber(): number {
// -1 instead of NULL ok?
@ -104,11 +106,11 @@ function newStringToken(index: number, text: string): Token {
}
function newNumberToken(index: number, n: number): Token {
return new Token(index, TokenType.Number, n, "");
return new Token(index, TokenType.Number, n, '');
}
export var EOF: Token = new Token(-1, TokenType.Character, 0, "");
export var EOF: Token = new Token(-1, TokenType.Character, 0, '');
export const $EOF = /*@ts2dart_const*/ 0;
export const $TAB = /*@ts2dart_const*/ 9;
@ -237,8 +239,8 @@ class _Scanner {
return this.scanComplexOperator(start, StringWrapper.fromCharCode(peek), $EQ, '=');
case $BANG:
case $EQ:
return this.scanComplexOperator(start, StringWrapper.fromCharCode(peek), $EQ, '=', $EQ,
'=');
return this.scanComplexOperator(
start, StringWrapper.fromCharCode(peek), $EQ, '=', $EQ, '=');
case $AMPERSAND:
return this.scanComplexOperator(start, '&', $AMPERSAND, '&');
case $BAR:
@ -274,8 +276,9 @@ class _Scanner {
* @param three third symbol (part of the operator when provided and matches source expression)
* @returns {Token}
*/
scanComplexOperator(start: number, one: string, twoCode: number, two: string, threeCode?: number,
three?: string): Token {
scanComplexOperator(
start: number, one: string, twoCode: number, two: string, threeCode?: number,
three?: string): Token {
this.advance();
var str: string = one;
if (this.peek == twoCode) {
@ -406,7 +409,7 @@ export function isIdentifier(input: string): boolean {
function isIdentifierPart(code: number): boolean {
return ($a <= code && code <= $z) || ($A <= code && code <= $Z) || ($0 <= code && code <= $9) ||
(code == $_) || (code == $$);
(code == $_) || (code == $$);
}
function isDigit(code: number): boolean {
@ -443,29 +446,8 @@ function unescape(code: number): number {
}
var OPERATORS = SetWrapper.createFromList([
'+',
'-',
'*',
'/',
'%',
'^',
'=',
'==',
'!=',
'===',
'!==',
'<',
'>',
'<=',
'>=',
'&&',
'||',
'&',
'|',
'!',
'?',
'#',
'?.'
'+', '-', '*', '/', '%', '^', '=', '==', '!=', '===', '!==', '<',
'>', '<=', '>=', '&&', '||', '&', '|', '!', '?', '#', '?.'
]);

View File

@ -1,51 +1,11 @@
import {Injectable} from '@angular/core';
import {isBlank, isPresent, StringWrapper} from '../facade/lang';
import {BaseException} from '../facade/exceptions';
import {ListWrapper} from '../facade/collection';
import {
Lexer,
EOF,
isIdentifier,
isQuote,
Token,
$PERIOD,
$COLON,
$SEMICOLON,
$LBRACKET,
$RBRACKET,
$COMMA,
$LBRACE,
$RBRACE,
$LPAREN,
$RPAREN,
$SLASH
} from './lexer';
import {
AST,
EmptyExpr,
ImplicitReceiver,
PropertyRead,
PropertyWrite,
SafePropertyRead,
LiteralPrimitive,
Binary,
PrefixNot,
Conditional,
BindingPipe,
Chain,
KeyedRead,
KeyedWrite,
LiteralArray,
LiteralMap,
Interpolation,
MethodCall,
SafeMethodCall,
FunctionCall,
TemplateBinding,
ASTWithSource,
AstVisitor,
Quote
} from './ast';
import {BaseException} from '../facade/exceptions';
import {StringWrapper, isBlank, isPresent} from '../facade/lang';
import {AST, ASTWithSource, AstVisitor, Binary, BindingPipe, Chain, Conditional, EmptyExpr, FunctionCall, ImplicitReceiver, Interpolation, KeyedRead, KeyedWrite, LiteralArray, LiteralMap, LiteralPrimitive, MethodCall, PrefixNot, PropertyRead, PropertyWrite, Quote, SafeMethodCall, SafePropertyRead, TemplateBinding} from './ast';
import {$COLON, $COMMA, $LBRACE, $LBRACKET, $LPAREN, $PERIOD, $RBRACE, $RBRACKET, $RPAREN, $SEMICOLON, $SLASH, EOF, Lexer, Token, isIdentifier, isQuote} from './lexer';
var _implicitReceiver = new ImplicitReceiver();
@ -152,9 +112,9 @@ export class Parser {
} else if (part.trim().length > 0) {
expressions.push(part);
} else {
throw new ParseException('Blank expressions are not allowed in interpolated strings', input,
`at column ${this._findInterpolationErrorColumn(parts, i)} in`,
location);
throw new ParseException(
'Blank expressions are not allowed in interpolated strings', input,
`at column ${this._findInterpolationErrorColumn(parts, i)} in`, location);
}
}
return new SplitInterpolation(strings, expressions);
@ -189,9 +149,9 @@ export class Parser {
private _checkNoInterpolation(input: string, location: any): void {
var parts = StringWrapper.split(input, INTERPOLATION_REGEXP);
if (parts.length > 1) {
throw new ParseException('Got interpolation ({{}}) where expression was expected', input,
`at column ${this._findInterpolationErrorColumn(parts, 1)} in`,
location);
throw new ParseException(
'Got interpolation ({{}}) where expression was expected', input,
`at column ${this._findInterpolationErrorColumn(parts, 1)} in`, location);
}
}
@ -207,8 +167,9 @@ export class Parser {
export class _ParseAST {
index: number = 0;
constructor(public input: string, public location: any, public tokens: any[],
public parseAction: boolean) {}
constructor(
public input: string, public location: any, public tokens: any[],
public parseAction: boolean) {}
peek(offset: number): Token {
var i = this.index + offset;
@ -284,7 +245,7 @@ export class _ParseAST {
if (this.optionalCharacter($SEMICOLON)) {
if (!this.parseAction) {
this.error("Binding expression cannot contain chained expression");
this.error('Binding expression cannot contain chained expression');
}
while (this.optionalCharacter($SEMICOLON)) {
} // read all semicolons
@ -299,9 +260,9 @@ export class _ParseAST {
parsePipe(): AST {
var result = this.parseExpression();
if (this.optionalOperator("|")) {
if (this.optionalOperator('|')) {
if (this.parseAction) {
this.error("Cannot have a pipe in an action expression");
this.error('Cannot have a pipe in an action expression');
}
do {
@ -311,7 +272,7 @@ export class _ParseAST {
args.push(this.parseExpression());
}
result = new BindingPipe(result, name, args);
} while (this.optionalOperator("|"));
} while (this.optionalOperator('|'));
}
return result;
@ -445,7 +406,7 @@ export class _ParseAST {
} else if (this.optionalCharacter($LBRACKET)) {
var key = this.parsePipe();
this.expectCharacter($RBRACKET);
if (this.optionalOperator("=")) {
if (this.optionalOperator('=')) {
var value = this.parseConditional();
result = new KeyedWrite(result, key, value);
} else {
@ -508,7 +469,7 @@ export class _ParseAST {
this.error(`Unexpected token ${this.next}`);
}
// error() throws, so we don't reach here.
throw new BaseException("Fell through all cases in parsePrimary");
throw new BaseException('Fell through all cases in parsePrimary');
}
parseExpressionList(terminator: number): any[] {
@ -547,15 +508,15 @@ export class _ParseAST {
} else {
if (isSafe) {
if (this.optionalOperator("=")) {
this.error("The '?.' operator cannot be used in the assignment");
if (this.optionalOperator('=')) {
this.error('The \'?.\' operator cannot be used in the assignment');
} else {
return new SafePropertyRead(receiver, id);
}
} else {
if (this.optionalOperator("=")) {
if (this.optionalOperator('=')) {
if (!this.parseAction) {
this.error("Bindings cannot contain assignments");
this.error('Bindings cannot contain assignments');
}
let value = this.parseConditional();
@ -580,7 +541,7 @@ export class _ParseAST {
parseBlockContent(): AST {
if (!this.parseAction) {
this.error("Binding expression cannot contain chained expression");
this.error('Binding expression cannot contain chained expression');
}
var exprs: any[] /** TODO #9100 */ = [];
while (this.index < this.tokens.length && !this.next.isCharacter($RBRACE)) {
@ -645,13 +606,14 @@ export class _ParseAST {
var name: any /** TODO #9100 */ = null;
var expression: any /** TODO #9100 */ = null;
if (keyIsVar) {
if (this.optionalOperator("=")) {
if (this.optionalOperator('=')) {
name = this.expectTemplateBindingKey();
} else {
name = '\$implicit';
}
} else if (this.next !== EOF && !this.peekKeywordLet() && !this.peekDeprecatedKeywordVar() &&
!this.peekDeprecatedOperatorHash()) {
} else if (
this.next !== EOF && !this.peekKeywordLet() && !this.peekDeprecatedKeywordVar() &&
!this.peekDeprecatedOperatorHash()) {
var start = this.inputIndex;
var ast = this.parsePipe();
var source = this.input.substring(start, this.inputIndex);

View File

@ -13,17 +13,18 @@ export class HtmlTextAst implements HtmlAst {
}
export class HtmlExpansionAst implements HtmlAst {
constructor(public switchValue: string, public type: string, public cases: HtmlExpansionCaseAst[],
public sourceSpan: ParseSourceSpan, public switchValueSourceSpan: ParseSourceSpan) {}
constructor(
public switchValue: string, public type: string, public cases: HtmlExpansionCaseAst[],
public sourceSpan: ParseSourceSpan, public switchValueSourceSpan: ParseSourceSpan) {}
visit(visitor: HtmlAstVisitor, context: any): any {
return visitor.visitExpansion(this, context);
}
}
export class HtmlExpansionCaseAst implements HtmlAst {
constructor(public value: string, public expression: HtmlAst[],
public sourceSpan: ParseSourceSpan, public valueSourceSpan: ParseSourceSpan,
public expSourceSpan: ParseSourceSpan) {}
constructor(
public value: string, public expression: HtmlAst[], public sourceSpan: ParseSourceSpan,
public valueSourceSpan: ParseSourceSpan, public expSourceSpan: ParseSourceSpan) {}
visit(visitor: HtmlAstVisitor, context: any): any {
return visitor.visitExpansionCase(this, context);
@ -36,9 +37,10 @@ export class HtmlAttrAst implements HtmlAst {
}
export class HtmlElementAst implements HtmlAst {
constructor(public name: string, public attrs: HtmlAttrAst[], public children: HtmlAst[],
public sourceSpan: ParseSourceSpan, public startSourceSpan: ParseSourceSpan,
public endSourceSpan: ParseSourceSpan) {}
constructor(
public name: string, public attrs: HtmlAttrAst[], public children: HtmlAst[],
public sourceSpan: ParseSourceSpan, public startSourceSpan: ParseSourceSpan,
public endSourceSpan: ParseSourceSpan) {}
visit(visitor: HtmlAstVisitor, context: any): any { return visitor.visitElement(this, context); }
}

View File

@ -1,7 +1,7 @@
import {StringWrapper, NumberWrapper, isPresent, isBlank} from './facade/lang';
import {ListWrapper} from './facade/collection';
import {ParseLocation, ParseError, ParseSourceFile, ParseSourceSpan} from './parse_util';
import {getHtmlTagDefinition, HtmlTagContentType, NAMED_ENTITIES} from './html_tags';
import {NumberWrapper, StringWrapper, isBlank, isPresent} from './facade/lang';
import {HtmlTagContentType, NAMED_ENTITIES, getHtmlTagDefinition} from './html_tags';
import {ParseError, ParseLocation, ParseSourceFile, ParseSourceSpan} from './parse_util';
export enum HtmlTokenType {
TAG_OPEN_START,
@ -27,8 +27,8 @@ export enum HtmlTokenType {
}
export class HtmlToken {
constructor(public type: HtmlTokenType, public parts: string[],
public sourceSpan: ParseSourceSpan) {}
constructor(
public type: HtmlTokenType, public parts: string[], public sourceSpan: ParseSourceSpan) {}
}
export class HtmlTokenError extends ParseError {
@ -41,8 +41,9 @@ export class HtmlTokenizeResult {
constructor(public tokens: HtmlToken[], public errors: HtmlTokenError[]) {}
}
export function tokenizeHtml(sourceContent: string, sourceUrl: string,
tokenizeExpansionForms: boolean = false): HtmlTokenizeResult {
export function tokenizeHtml(
sourceContent: string, sourceUrl: string,
tokenizeExpansionForms: boolean = false): HtmlTokenizeResult {
return new _HtmlTokenizer(new ParseSourceFile(sourceContent, sourceUrl), tokenizeExpansionForms)
.tokenize();
}
@ -161,12 +162,12 @@ class _HtmlTokenizer {
} else if (this.peek === $EQ && this.tokenizeExpansionForms) {
this._consumeExpansionCaseStart();
} else if (this.peek === $RBRACE && this.isInExpansionCase() &&
this.tokenizeExpansionForms) {
} else if (
this.peek === $RBRACE && this.isInExpansionCase() && this.tokenizeExpansionForms) {
this._consumeExpansionCaseEnd();
} else if (this.peek === $RBRACE && this.isInExpansionForm() &&
this.tokenizeExpansionForms) {
} else if (
this.peek === $RBRACE && this.isInExpansionForm() && this.tokenizeExpansionForms) {
this._consumeExpansionFormEnd();
} else {
@ -211,8 +212,8 @@ class _HtmlTokenizer {
if (isBlank(end)) {
end = this._getLocation();
}
var token = new HtmlToken(this.currentTokenType, parts,
new ParseSourceSpan(this.currentTokenStart, end));
var token = new HtmlToken(
this.currentTokenType, parts, new ParseSourceSpan(this.currentTokenStart, end));
this.tokens.push(token);
this.currentTokenStart = null;
this.currentTokenType = null;
@ -261,8 +262,8 @@ class _HtmlTokenizer {
private _requireCharCode(charCode: number) {
var location = this._getLocation();
if (!this._attemptCharCode(charCode)) {
throw this._createError(unexpectedCharacterErrorMsg(this.peek),
this._getSpan(location, location));
throw this._createError(
unexpectedCharacterErrorMsg(this.peek), this._getSpan(location, location));
}
}
@ -365,12 +366,12 @@ class _HtmlTokenizer {
}
}
private _consumeRawText(decodeEntities: boolean, firstCharOfEnd: number,
attemptEndRest: Function): HtmlToken {
private _consumeRawText(
decodeEntities: boolean, firstCharOfEnd: number, attemptEndRest: Function): HtmlToken {
var tagCloseStart: any /** TODO #9100 */;
var textStart = this._getLocation();
this._beginToken(decodeEntities ? HtmlTokenType.ESCAPABLE_RAW_TEXT : HtmlTokenType.RAW_TEXT,
textStart);
this._beginToken(
decodeEntities ? HtmlTokenType.ESCAPABLE_RAW_TEXT : HtmlTokenType.RAW_TEXT, textStart);
var parts: any[] /** TODO #9100 */ = [];
while (true) {
tagCloseStart = this._getLocation();
@ -655,14 +656,14 @@ class _HtmlTokenizer {
private isInExpansionCase(): boolean {
return this.expansionCaseStack.length > 0 &&
this.expansionCaseStack[this.expansionCaseStack.length - 1] ===
HtmlTokenType.EXPANSION_CASE_EXP_START;
this.expansionCaseStack[this.expansionCaseStack.length - 1] ===
HtmlTokenType.EXPANSION_CASE_EXP_START;
}
private isInExpansionForm(): boolean {
return this.expansionCaseStack.length > 0 &&
this.expansionCaseStack[this.expansionCaseStack.length - 1] ===
HtmlTokenType.EXPANSION_FORM_START;
this.expansionCaseStack[this.expansionCaseStack.length - 1] ===
HtmlTokenType.EXPANSION_FORM_START;
}
}
@ -676,7 +677,7 @@ function isWhitespace(code: number): boolean {
function isNameEnd(code: number): boolean {
return isWhitespace(code) || code === $GT || code === $SLASH || code === $SQ || code === $DQ ||
code === $EQ;
code === $EQ;
}
function isPrefixEnd(code: number): boolean {

View File

@ -1,21 +1,10 @@
import {Injectable} from '@angular/core';
import {
isPresent,
isBlank,
} from '../src/facade/lang';
import {isPresent, isBlank,} from '../src/facade/lang';
import {ListWrapper} from '../src/facade/collection';
import {
HtmlAst,
HtmlAttrAst,
HtmlTextAst,
HtmlCommentAst,
HtmlElementAst,
HtmlExpansionAst,
HtmlExpansionCaseAst
} from './html_ast';
import {HtmlAst, HtmlAttrAst, HtmlTextAst, HtmlCommentAst, HtmlElementAst, HtmlExpansionAst, HtmlExpansionCaseAst} from './html_ast';
import {HtmlToken, HtmlTokenType, tokenizeHtml} from './html_lexer';
import {ParseError, ParseSourceSpan} from './parse_util';
@ -35,12 +24,13 @@ export class HtmlParseTreeResult {
@Injectable()
export class HtmlParser {
parse(sourceContent: string, sourceUrl: string,
parseExpansionForms: boolean = false): HtmlParseTreeResult {
parse(sourceContent: string, sourceUrl: string, parseExpansionForms: boolean = false):
HtmlParseTreeResult {
var tokensAndErrors = tokenizeHtml(sourceContent, sourceUrl, parseExpansionForms);
var treeAndErrors = new TreeBuilder(tokensAndErrors.tokens).build();
return new HtmlParseTreeResult(treeAndErrors.rootNodes, (<ParseError[]>tokensAndErrors.errors)
.concat(treeAndErrors.errors));
return new HtmlParseTreeResult(
treeAndErrors.rootNodes,
(<ParseError[]>tokensAndErrors.errors).concat(treeAndErrors.errors));
}
}
@ -67,9 +57,9 @@ class TreeBuilder {
} else if (this.peek.type === HtmlTokenType.COMMENT_START) {
this._closeVoidElement();
this._consumeComment(this._advance());
} else if (this.peek.type === HtmlTokenType.TEXT ||
this.peek.type === HtmlTokenType.RAW_TEXT ||
this.peek.type === HtmlTokenType.ESCAPABLE_RAW_TEXT) {
} else if (
this.peek.type === HtmlTokenType.TEXT || this.peek.type === HtmlTokenType.RAW_TEXT ||
this.peek.type === HtmlTokenType.ESCAPABLE_RAW_TEXT) {
this._closeVoidElement();
this._consumeText(this._advance());
} else if (this.peek.type === HtmlTokenType.EXPANSION_FORM_START) {
@ -133,8 +123,8 @@ class TreeBuilder {
this._advance();
let mainSourceSpan = new ParseSourceSpan(token.sourceSpan.start, this.peek.sourceSpan.end);
this._addToParent(new HtmlExpansionAst(switchValue.parts[0], type.parts[0], cases,
mainSourceSpan, switchValue.sourceSpan));
this._addToParent(new HtmlExpansionAst(
switchValue.parts[0], type.parts[0], cases, mainSourceSpan, switchValue.sourceSpan));
}
private _parseExpansionCase(): HtmlExpansionCaseAst {
@ -142,8 +132,8 @@ class TreeBuilder {
// read {
if (this.peek.type !== HtmlTokenType.EXPANSION_CASE_EXP_START) {
this.errors.push(HtmlTreeError.create(null, this.peek.sourceSpan,
`Invalid expansion form. Missing '{'.,`));
this.errors.push(HtmlTreeError.create(
null, this.peek.sourceSpan, `Invalid expansion form. Missing '{'.,`));
return null;
}
@ -165,8 +155,8 @@ class TreeBuilder {
let sourceSpan = new ParseSourceSpan(value.sourceSpan.start, end.sourceSpan.end);
let expSourceSpan = new ParseSourceSpan(start.sourceSpan.start, end.sourceSpan.end);
return new HtmlExpansionCaseAst(value.parts[0], parsedExp.rootNodes, sourceSpan,
value.sourceSpan, expSourceSpan);
return new HtmlExpansionCaseAst(
value.parts[0], parsedExp.rootNodes, sourceSpan, value.sourceSpan, expSourceSpan);
}
private _collectExpansionExpTokens(start: HtmlToken): HtmlToken[] {
@ -280,8 +270,8 @@ class TreeBuilder {
var tagDef = getHtmlTagDefinition(el.name);
var parentEl = this._getParentElement();
if (tagDef.requireExtraParent(isPresent(parentEl) ? parentEl.name : null)) {
var newParent = new HtmlElementAst(tagDef.parentToAdd, [], [el], el.sourceSpan,
el.startSourceSpan, el.endSourceSpan);
var newParent = new HtmlElementAst(
tagDef.parentToAdd, [], [el], el.sourceSpan, el.startSourceSpan, el.endSourceSpan);
this._addToParent(newParent);
this.elementStack.push(newParent);
this.elementStack.push(el);
@ -300,12 +290,12 @@ class TreeBuilder {
}
if (getHtmlTagDefinition(fullName).isVoid) {
this.errors.push(
HtmlTreeError.create(fullName, endTagToken.sourceSpan,
`Void elements do not have end tags "${endTagToken.parts[1]}"`));
this.errors.push(HtmlTreeError.create(
fullName, endTagToken.sourceSpan,
`Void elements do not have end tags "${endTagToken.parts[1]}"`));
} else if (!this._popElement(fullName)) {
this.errors.push(HtmlTreeError.create(fullName, endTagToken.sourceSpan,
`Unexpected closing tag "${endTagToken.parts[1]}"`));
this.errors.push(HtmlTreeError.create(
fullName, endTagToken.sourceSpan, `Unexpected closing tag "${endTagToken.parts[1]}"`));
}
}
@ -350,8 +340,8 @@ class TreeBuilder {
}
}
function getElementFullName(prefix: string, localName: string,
parentElement: HtmlElementAst): string {
function getElementFullName(
prefix: string, localName: string, parentElement: HtmlElementAst): string {
if (isBlank(prefix)) {
prefix = getHtmlTagDefinition(localName).implicitNamespacePrefix;
if (isBlank(prefix) && isPresent(parentElement)) {

View File

@ -1,9 +1,4 @@
import {
isPresent,
isBlank,
normalizeBool,
RegExpWrapper,
} from '../src/facade/lang';
import {isPresent, isBlank, normalizeBool, RegExpWrapper,} from '../src/facade/lang';
// see http://www.w3.org/TR/html51/syntax.html#named-character-references
// see https://html.spec.whatwg.org/multipage/entities.json
@ -280,16 +275,17 @@ export class HtmlTagDefinition {
public isVoid: boolean;
public ignoreFirstLf: boolean;
constructor({closedByChildren, requiredParents, implicitNamespacePrefix, contentType,
closedByParent, isVoid, ignoreFirstLf}: {
closedByChildren?: string[],
closedByParent?: boolean,
requiredParents?: string[],
implicitNamespacePrefix?: string,
contentType?: HtmlTagContentType,
isVoid?: boolean,
ignoreFirstLf?: boolean
} = {}) {
constructor(
{closedByChildren, requiredParents, implicitNamespacePrefix, contentType, closedByParent,
isVoid, ignoreFirstLf}: {
closedByChildren?: string[],
closedByParent?: boolean,
requiredParents?: string[],
implicitNamespacePrefix?: string,
contentType?: HtmlTagContentType,
isVoid?: boolean,
ignoreFirstLf?: boolean
} = {}) {
if (isPresent(closedByChildren) && closedByChildren.length > 0) {
closedByChildren.forEach(tagName => this.closedByChildren[tagName] = true);
}
@ -341,32 +337,9 @@ var TAG_DEFINITIONS: {[key: string]: HtmlTagDefinition} = {
'wbr': new HtmlTagDefinition({isVoid: true}),
'p': new HtmlTagDefinition({
closedByChildren: [
'address',
'article',
'aside',
'blockquote',
'div',
'dl',
'fieldset',
'footer',
'form',
'h1',
'h2',
'h3',
'h4',
'h5',
'h6',
'header',
'hgroup',
'hr',
'main',
'nav',
'ol',
'p',
'pre',
'section',
'table',
'ul'
'address', 'article', 'aside', 'blockquote', 'div', 'dl', 'fieldset', 'footer', 'form',
'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'header', 'hgroup', 'hr',
'main', 'nav', 'ol', 'p', 'pre', 'section', 'table', 'ul'
],
closedByParent: true
}),

View File

@ -1,16 +1,6 @@
import {
HtmlAst,
HtmlAstVisitor,
HtmlElementAst,
HtmlAttrAst,
HtmlTextAst,
HtmlCommentAst,
HtmlExpansionAst,
HtmlExpansionCaseAst,
htmlVisitAll
} from '../html_ast';
import {BaseException} from '../facade/exceptions';
import {HtmlAst, HtmlAstVisitor, HtmlAttrAst, HtmlCommentAst, HtmlElementAst, HtmlExpansionAst, HtmlExpansionCaseAst, HtmlTextAst, htmlVisitAll} from '../html_ast';
/**
@ -51,8 +41,9 @@ class _Expander implements HtmlAstVisitor {
constructor() {}
visitElement(ast: HtmlElementAst, context: any): any {
return new HtmlElementAst(ast.name, ast.attrs, htmlVisitAll(this, ast.children), ast.sourceSpan,
ast.startSourceSpan, ast.endSourceSpan);
return new HtmlElementAst(
ast.name, ast.attrs, htmlVisitAll(this, ast.children), ast.sourceSpan, ast.startSourceSpan,
ast.endSourceSpan);
}
visitAttr(ast: HtmlAttrAst, context: any): any { return ast; }
@ -63,11 +54,11 @@ class _Expander implements HtmlAstVisitor {
visitExpansion(ast: HtmlExpansionAst, context: any): any {
this.expanded = true;
return ast.type == "plural" ? _expandPluralForm(ast) : _expandDefaultForm(ast);
return ast.type == 'plural' ? _expandPluralForm(ast) : _expandDefaultForm(ast);
}
visitExpansionCase(ast: HtmlExpansionCaseAst, context: any): any {
throw new BaseException("Should not be reached");
throw new BaseException('Should not be reached');
}
}
@ -75,42 +66,40 @@ function _expandPluralForm(ast: HtmlExpansionAst): HtmlElementAst {
let children = ast.cases.map(c => {
let expansionResult = expandNodes(c.expression);
let i18nAttrs = expansionResult.expanded ?
[] :
[new HtmlAttrAst("i18n", `${ast.type}_${c.value}`, c.valueSourceSpan)];
[] :
[new HtmlAttrAst('i18n', `${ast.type}_${c.value}`, c.valueSourceSpan)];
return new HtmlElementAst(`template`,
[
new HtmlAttrAst("ngPluralCase", c.value, c.valueSourceSpan),
],
[
new HtmlElementAst(`li`, i18nAttrs, expansionResult.nodes,
c.sourceSpan, c.sourceSpan, c.sourceSpan)
],
c.sourceSpan, c.sourceSpan, c.sourceSpan);
return new HtmlElementAst(
`template`,
[
new HtmlAttrAst('ngPluralCase', c.value, c.valueSourceSpan),
],
[new HtmlElementAst(
`li`, i18nAttrs, expansionResult.nodes, c.sourceSpan, c.sourceSpan, c.sourceSpan)],
c.sourceSpan, c.sourceSpan, c.sourceSpan);
});
let switchAttr = new HtmlAttrAst("[ngPlural]", ast.switchValue, ast.switchValueSourceSpan);
return new HtmlElementAst("ul", [switchAttr], children, ast.sourceSpan, ast.sourceSpan,
ast.sourceSpan);
let switchAttr = new HtmlAttrAst('[ngPlural]', ast.switchValue, ast.switchValueSourceSpan);
return new HtmlElementAst(
'ul', [switchAttr], children, ast.sourceSpan, ast.sourceSpan, ast.sourceSpan);
}
function _expandDefaultForm(ast: HtmlExpansionAst): HtmlElementAst {
let children = ast.cases.map(c => {
let expansionResult = expandNodes(c.expression);
let i18nAttrs = expansionResult.expanded ?
[] :
[new HtmlAttrAst("i18n", `${ast.type}_${c.value}`, c.valueSourceSpan)];
[] :
[new HtmlAttrAst('i18n', `${ast.type}_${c.value}`, c.valueSourceSpan)];
return new HtmlElementAst(`template`,
[
new HtmlAttrAst("ngSwitchWhen", c.value, c.valueSourceSpan),
],
[
new HtmlElementAst(`li`, i18nAttrs, expansionResult.nodes,
c.sourceSpan, c.sourceSpan, c.sourceSpan)
],
c.sourceSpan, c.sourceSpan, c.sourceSpan);
return new HtmlElementAst(
`template`,
[
new HtmlAttrAst('ngSwitchWhen', c.value, c.valueSourceSpan),
],
[new HtmlElementAst(
`li`, i18nAttrs, expansionResult.nodes, c.sourceSpan, c.sourceSpan, c.sourceSpan)],
c.sourceSpan, c.sourceSpan, c.sourceSpan);
});
let switchAttr = new HtmlAttrAst("[ngSwitch]", ast.switchValue, ast.switchValueSourceSpan);
return new HtmlElementAst("ul", [switchAttr], children, ast.sourceSpan, ast.sourceSpan,
ast.sourceSpan);
let switchAttr = new HtmlAttrAst('[ngSwitch]', ast.switchValue, ast.switchValueSourceSpan);
return new HtmlElementAst(
'ul', [switchAttr], children, ast.sourceSpan, ast.sourceSpan, ast.sourceSpan);
}

View File

@ -1,36 +1,17 @@
import {HtmlParser, HtmlParseTreeResult} from "../html_parser";
import {ParseSourceSpan, ParseError} from "../parse_util";
import {
HtmlAst,
HtmlAstVisitor,
HtmlElementAst,
HtmlAttrAst,
HtmlTextAst,
HtmlCommentAst,
HtmlExpansionAst,
HtmlExpansionCaseAst,
htmlVisitAll
} from "../html_ast";
import {ListWrapper, StringMapWrapper} from "../facade/collection";
import {RegExpWrapper, NumberWrapper, isPresent} from "../facade/lang";
import {BaseException} from "../facade/exceptions";
import {Parser} from "../expression_parser/parser";
import {id} from "./message";
import {expandNodes} from "./expander";
import {
messageFromI18nAttribute,
I18nError,
I18N_ATTR_PREFIX,
I18N_ATTR,
partition,
Part,
getPhNameFromBinding,
dedupePhName,
messageFromAttribute
} from "./shared";
import {Parser} from '../expression_parser/parser';
import {ListWrapper, StringMapWrapper} from '../facade/collection';
import {BaseException} from '../facade/exceptions';
import {NumberWrapper, RegExpWrapper, isPresent} from '../facade/lang';
import {HtmlAst, HtmlAstVisitor, HtmlAttrAst, HtmlCommentAst, HtmlElementAst, HtmlExpansionAst, HtmlExpansionCaseAst, HtmlTextAst, htmlVisitAll} from '../html_ast';
import {HtmlParseTreeResult, HtmlParser} from '../html_parser';
import {ParseError, ParseSourceSpan} from '../parse_util';
const _PLACEHOLDER_ELEMENT = "ph";
const _NAME_ATTR = "name";
import {expandNodes} from './expander';
import {id} from './message';
import {I18N_ATTR, I18N_ATTR_PREFIX, I18nError, Part, dedupePhName, getPhNameFromBinding, messageFromAttribute, messageFromI18nAttribute, partition} from './shared';
const _PLACEHOLDER_ELEMENT = 'ph';
const _NAME_ATTR = 'name';
let _PLACEHOLDER_EXPANDED_REGEXP = /<ph(\s)+name=("(\w)+")><\/ph>/gi;
/**
@ -116,12 +97,13 @@ let _PLACEHOLDER_EXPANDED_REGEXP = /<ph(\s)+name=("(\w)+")><\/ph>/gi;
export class I18nHtmlParser implements HtmlParser {
errors: ParseError[];
constructor(private _htmlParser: HtmlParser, private _parser: Parser,
private _messagesContent: string, private _messages: {[key: string]: HtmlAst[]},
private _implicitTags: string[], private _implicitAttrs: {[k: string]: string[]}) {}
constructor(
private _htmlParser: HtmlParser, private _parser: Parser, private _messagesContent: string,
private _messages: {[key: string]: HtmlAst[]}, private _implicitTags: string[],
private _implicitAttrs: {[k: string]: string[]}) {}
parse(sourceContent: string, sourceUrl: string,
parseExpansionForms: boolean = false): HtmlParseTreeResult {
parse(sourceContent: string, sourceUrl: string, parseExpansionForms: boolean = false):
HtmlParseTreeResult {
this.errors = [];
let res = this._htmlParser.parse(sourceContent, sourceUrl, true);
@ -168,10 +150,8 @@ export class I18nHtmlParser implements HtmlParser {
let root = p.rootElement;
let children = this._recurse(p.children);
let attrs = this._i18nAttributes(root);
return [
new HtmlElementAst(root.name, attrs, children, root.sourceSpan, root.startSourceSpan,
root.endSourceSpan)
];
return [new HtmlElementAst(
root.name, attrs, children, root.sourceSpan, root.startSourceSpan, root.endSourceSpan)];
// a text node without i18n or interpolation, nothing to do
} else if (isPresent(p.rootTextNode)) {
@ -200,14 +180,12 @@ export class I18nHtmlParser implements HtmlParser {
if (isPresent(p.rootElement)) {
let root = p.rootElement;
let attrs = this._i18nAttributes(root);
return [
new HtmlElementAst(root.name, attrs, merged, root.sourceSpan, root.startSourceSpan,
root.endSourceSpan)
];
return [new HtmlElementAst(
root.name, attrs, merged, root.sourceSpan, root.startSourceSpan, root.endSourceSpan)];
// this should never happen with a part. Parts that have root text node should not be merged.
} else if (isPresent(p.rootTextNode)) {
throw new BaseException("should not be reached");
throw new BaseException('should not be reached');
} else {
return merged;
@ -223,24 +201,24 @@ export class I18nHtmlParser implements HtmlParser {
return t;
} else {
throw new BaseException("should not be reached");
throw new BaseException('should not be reached');
}
});
}
private _mergeElementOrInterpolation(t: HtmlElementAst, translated: HtmlAst[],
mapping: HtmlAst[]): HtmlAst {
private _mergeElementOrInterpolation(
t: HtmlElementAst, translated: HtmlAst[], mapping: HtmlAst[]): HtmlAst {
let name = this._getName(t);
let type = name[0];
let index = NumberWrapper.parseInt(name.substring(1), 10);
let originalNode = mapping[index];
if (type == "t") {
if (type == 't') {
return this._mergeTextInterpolation(t, <HtmlTextAst>originalNode);
} else if (type == "e") {
} else if (type == 'e') {
return this._mergeElement(t, <HtmlElementAst>originalNode, mapping);
} else {
throw new BaseException("should not be reached");
throw new BaseException('should not be reached');
}
}
@ -270,12 +248,12 @@ export class I18nHtmlParser implements HtmlParser {
return new HtmlTextAst(translated, originalNode.sourceSpan);
}
private _mergeElement(t: HtmlElementAst, originalNode: HtmlElementAst,
mapping: HtmlAst[]): HtmlElementAst {
private _mergeElement(t: HtmlElementAst, originalNode: HtmlElementAst, mapping: HtmlAst[]):
HtmlElementAst {
let children = this._mergeTreesHelper(t.children, mapping);
return new HtmlElementAst(originalNode.name, this._i18nAttributes(originalNode), children,
originalNode.sourceSpan, originalNode.startSourceSpan,
originalNode.endSourceSpan);
return new HtmlElementAst(
originalNode.name, this._i18nAttributes(originalNode), children, originalNode.sourceSpan,
originalNode.startSourceSpan, originalNode.endSourceSpan);
}
private _i18nAttributes(el: HtmlElementAst): HtmlAttrAst[] {
@ -330,14 +308,15 @@ export class I18nHtmlParser implements HtmlParser {
return this._replacePlaceholdersWithExpressions(messageSubstring, exps, attr.sourceSpan);
};
private _replacePlaceholdersWithExpressions(message: string, exps: string[],
sourceSpan: ParseSourceSpan): string {
private _replacePlaceholdersWithExpressions(
message: string, exps: string[], sourceSpan: ParseSourceSpan): string {
let expMap = this._buildExprMap(exps);
return RegExpWrapper.replaceAll(_PLACEHOLDER_EXPANDED_REGEXP, message, (match: any /** TODO #9100 */) => {
let nameWithQuotes = match[2];
let name = nameWithQuotes.substring(1, nameWithQuotes.length - 1);
return this._convertIntoExpression(name, expMap, sourceSpan);
});
return RegExpWrapper.replaceAll(
_PLACEHOLDER_EXPANDED_REGEXP, message, (match: any /** TODO #9100 */) => {
let nameWithQuotes = match[2];
let name = nameWithQuotes.substring(1, nameWithQuotes.length - 1);
return this._convertIntoExpression(name, expMap, sourceSpan);
});
}
private _buildExprMap(exps: string[]): Map<string, string> {
@ -351,8 +330,8 @@ export class I18nHtmlParser implements HtmlParser {
return expMap;
}
private _convertIntoExpression(name: string, expMap: Map<string, string>,
sourceSpan: ParseSourceSpan) {
private _convertIntoExpression(
name: string, expMap: Map<string, string>, sourceSpan: ParseSourceSpan) {
if (expMap.has(name)) {
return `{{${expMap.get(name)}}}`;
} else {
@ -381,5 +360,5 @@ class _CreateNodeMapping implements HtmlAstVisitor {
visitExpansionCase(ast: HtmlExpansionCaseAst, context: any): any { return null; }
visitComment(ast: HtmlCommentAst, context: any): any { return ""; }
visitComment(ast: HtmlCommentAst, context: any): any { return ''; }
}

View File

@ -1,4 +1,5 @@
import {isPresent, escape} from '../facade/lang';
import {escape, isPresent} from '../facade/lang';
/**
* A message extracted from a template.
@ -15,7 +16,7 @@ export class Message {
* Computes the id of a message
*/
export function id(m: Message): string {
let meaning = isPresent(m.meaning) ? m.meaning : "";
let content = isPresent(m.content) ? m.content : "";
let meaning = isPresent(m.meaning) ? m.meaning : '';
let content = isPresent(m.content) ? m.content : '';
return escape(`$ng|${meaning}|${content}`);
}

View File

@ -1,19 +1,14 @@
import {HtmlParser} from "../html_parser";
import {ParseError} from "../parse_util";
import {HtmlAst, HtmlElementAst} from "../html_ast";
import {isPresent} from "../facade/lang";
import {StringMapWrapper} from "../facade/collection";
import {Parser} from "../expression_parser/parser";
import {Message, id} from "./message";
import {expandNodes} from "./expander";
import {
I18nError,
Part,
I18N_ATTR_PREFIX,
partition,
messageFromI18nAttribute,
messageFromAttribute
} from "./shared";
import {Parser} from '../expression_parser/parser';
import {StringMapWrapper} from '../facade/collection';
import {isPresent} from '../facade/lang';
import {HtmlAst, HtmlElementAst} from '../html_ast';
import {HtmlParser} from '../html_parser';
import {ParseError} from '../parse_util';
import {expandNodes} from './expander';
import {Message, id} from './message';
import {I18N_ATTR_PREFIX, I18nError, Part, messageFromAttribute, messageFromI18nAttribute, partition} from './shared';
/**
* All messages extracted from a template.
@ -106,8 +101,9 @@ export class MessageExtractor {
messages: Message[];
errors: ParseError[];
constructor(private _htmlParser: HtmlParser, private _parser: Parser,
private _implicitTags: string[], private _implicitAttrs: {[k: string]: string[]}) {}
constructor(
private _htmlParser: HtmlParser, private _parser: Parser, private _implicitTags: string[],
private _implicitAttrs: {[k: string]: string[]}) {}
extract(template: string, sourceUrl: string): ExtractionResult {
this.messages = [];

View File

@ -1,21 +1,12 @@
import {ParseSourceSpan, ParseError} from '../parse_util';
import {
HtmlAst,
HtmlAstVisitor,
HtmlElementAst,
HtmlAttrAst,
HtmlTextAst,
HtmlCommentAst,
HtmlExpansionAst,
HtmlExpansionCaseAst,
htmlVisitAll
} from '../html_ast';
import {isPresent, isBlank, StringWrapper} from '../facade/lang';
import {Message} from './message';
import {Parser} from '../expression_parser/parser';
import {StringWrapper, isBlank, isPresent} from '../facade/lang';
import {HtmlAst, HtmlAstVisitor, HtmlAttrAst, HtmlCommentAst, HtmlElementAst, HtmlExpansionAst, HtmlExpansionCaseAst, HtmlTextAst, htmlVisitAll} from '../html_ast';
import {ParseError, ParseSourceSpan} from '../parse_util';
export const I18N_ATTR = "i18n";
export const I18N_ATTR_PREFIX = "i18n-";
import {Message} from './message';
export const I18N_ATTR = 'i18n';
export const I18N_ATTR_PREFIX = 'i18n-';
var CUSTOM_PH_EXP = /\/\/[\s\S]*i18n[\s\S]*\([\s\S]*ph[\s\S]*=[\s\S]*"([\s\S]*?)"[\s\S]*\)/g;
/**
@ -39,7 +30,7 @@ export function partition(nodes: HtmlAst[], errors: ParseError[], implicitTags:
while (!_isClosingComment(nodes[i])) {
temp.push(nodes[i++]);
if (i === nodes.length) {
errors.push(new I18nError(n.sourceSpan, "Missing closing 'i18n' comment."));
errors.push(new I18nError(n.sourceSpan, 'Missing closing \'i18n\' comment.'));
break;
}
}
@ -58,8 +49,9 @@ export function partition(nodes: HtmlAst[], errors: ParseError[], implicitTags:
}
export class Part {
constructor(public rootElement: HtmlElementAst, public rootTextNode: HtmlTextAst,
public children: HtmlAst[], public i18n: string, public hasI18n: boolean) {}
constructor(
public rootElement: HtmlElementAst, public rootTextNode: HtmlTextAst,
public children: HtmlAst[], public i18n: string, public hasI18n: boolean) {}
get sourceSpan(): ParseSourceSpan {
if (isPresent(this.rootElement))
@ -71,17 +63,17 @@ export class Part {
}
createMessage(parser: Parser): Message {
return new Message(stringifyNodes(this.children, parser), meaning(this.i18n),
description(this.i18n));
return new Message(
stringifyNodes(this.children, parser), meaning(this.i18n), description(this.i18n));
}
}
function _isOpeningComment(n: HtmlAst): boolean {
return n instanceof HtmlCommentAst && isPresent(n.value) && n.value.startsWith("i18n:");
return n instanceof HtmlCommentAst && isPresent(n.value) && n.value.startsWith('i18n:');
}
function _isClosingComment(n: HtmlAst): boolean {
return n instanceof HtmlCommentAst && isPresent(n.value) && n.value == "/i18n";
return n instanceof HtmlCommentAst && isPresent(n.value) && n.value == '/i18n';
}
function _findI18nAttr(p: HtmlElementAst): HtmlAttrAst {
@ -90,13 +82,13 @@ function _findI18nAttr(p: HtmlElementAst): HtmlAttrAst {
}
export function meaning(i18n: string): string {
if (isBlank(i18n) || i18n == "") return null;
return i18n.split("|")[0];
if (isBlank(i18n) || i18n == '') return null;
return i18n.split('|')[0];
}
export function description(i18n: string): string {
if (isBlank(i18n) || i18n == "") return null;
let parts = i18n.split("|");
if (isBlank(i18n) || i18n == '') return null;
let parts = i18n.split('|');
return parts.length > 1 ? parts[1] : null;
}
@ -105,32 +97,33 @@ export function description(i18n: string): string {
*
* @internal
*/
export function messageFromI18nAttribute(parser: Parser, p: HtmlElementAst,
i18nAttr: HtmlAttrAst): Message {
export function messageFromI18nAttribute(
parser: Parser, p: HtmlElementAst, i18nAttr: HtmlAttrAst): Message {
let expectedName = i18nAttr.name.substring(5);
let matching = p.attrs.filter(a => a.name == expectedName);
if (matching.length > 0) {
return messageFromAttribute(parser, matching[0], meaning(i18nAttr.value),
description(i18nAttr.value));
return messageFromAttribute(
parser, matching[0], meaning(i18nAttr.value), description(i18nAttr.value));
}
throw new I18nError(p.sourceSpan, `Missing attribute '${expectedName}'.`);
}
export function messageFromAttribute(parser: Parser, attr: HtmlAttrAst, meaning: string = null,
description: string = null): Message {
export function messageFromAttribute(
parser: Parser, attr: HtmlAttrAst, meaning: string = null,
description: string = null): Message {
let value = removeInterpolation(attr.value, attr.sourceSpan, parser);
return new Message(value, meaning, description);
}
export function removeInterpolation(value: string, source: ParseSourceSpan,
parser: Parser): string {
export function removeInterpolation(
value: string, source: ParseSourceSpan, parser: Parser): string {
try {
let parsed = parser.splitInterpolation(value, source.toString());
let usedNames = new Map<string, number>();
if (isPresent(parsed)) {
let res = "";
let res = '';
for (let i = 0; i < parsed.strings.length; ++i) {
res += parsed.strings[i];
if (i != parsed.strings.length - 1) {
@ -166,7 +159,7 @@ export function dedupePhName(usedNames: Map<string, number>, name: string): stri
export function stringifyNodes(nodes: HtmlAst[], parser: Parser): string {
let visitor = new _StringifyVisitor(parser);
return htmlVisitAll(visitor, nodes).join("");
return htmlVisitAll(visitor, nodes).join('');
}
class _StringifyVisitor implements HtmlAstVisitor {
@ -175,7 +168,7 @@ class _StringifyVisitor implements HtmlAstVisitor {
visitElement(ast: HtmlElementAst, context: any): any {
let name = this._index++;
let children = this._join(htmlVisitAll(this, ast.children), "");
let children = this._join(htmlVisitAll(this, ast.children), '');
return `<ph name="e${name}">${children}</ph>`;
}
@ -191,7 +184,7 @@ class _StringifyVisitor implements HtmlAstVisitor {
}
}
visitComment(ast: HtmlCommentAst, context: any): any { return ""; }
visitComment(ast: HtmlCommentAst, context: any): any { return ''; }
visitExpansion(ast: HtmlExpansionAst, context: any): any { return null; }

View File

@ -1,22 +1,24 @@
import {isPresent, isBlank, RegExpWrapper} from '../facade/lang';
import {RegExpWrapper, isBlank, isPresent} from '../facade/lang';
import {HtmlAst, HtmlElementAst} from '../html_ast';
import {Message, id} from './message';
import {HtmlParser} from '../html_parser';
import {ParseSourceSpan, ParseError} from '../parse_util';
import {ParseError, ParseSourceSpan} from '../parse_util';
import {Message, id} from './message';
let _PLACEHOLDER_REGEXP = RegExpWrapper.create(`\\<ph(\\s)+name=("(\\w)+")\\/\\>`);
const _ID_ATTR = "id";
const _MSG_ELEMENT = "msg";
const _BUNDLE_ELEMENT = "message-bundle";
const _ID_ATTR = 'id';
const _MSG_ELEMENT = 'msg';
const _BUNDLE_ELEMENT = 'message-bundle';
export function serializeXmb(messages: Message[]): string {
let ms = messages.map((m) => _serializeMessage(m)).join("");
let ms = messages.map((m) => _serializeMessage(m)).join('');
return `<message-bundle>${ms}</message-bundle>`;
}
export class XmbDeserializationResult {
constructor(public content: string, public messages: {[key: string]: HtmlAst[]},
public errors: ParseError[]) {}
constructor(
public content: string, public messages: {[key: string]: HtmlAst[]},
public errors: ParseError[]) {}
}
export class XmbDeserializationError extends ParseError {
@ -44,17 +46,17 @@ export function deserializeXmb(content: string, url: string): XmbDeserialization
_createMessages(bundleEl.children, messages, errors);
return (errors.length == 0) ?
new XmbDeserializationResult(normalizedContent, messages, []) :
new XmbDeserializationResult(null, <{[key: string]: HtmlAst[]}>{}, errors);
new XmbDeserializationResult(normalizedContent, messages, []) :
new XmbDeserializationResult(null, <{[key: string]: HtmlAst[]}>{}, errors);
}
function _checkRootElement(nodes: HtmlAst[]): boolean {
return nodes.length < 1 || !(nodes[0] instanceof HtmlElementAst) ||
(<HtmlElementAst>nodes[0]).name != _BUNDLE_ELEMENT;
(<HtmlElementAst>nodes[0]).name != _BUNDLE_ELEMENT;
}
function _createMessages(nodes: HtmlAst[], messages: {[key: string]: HtmlAst[]},
errors: ParseError[]): void {
function _createMessages(
nodes: HtmlAst[], messages: {[key: string]: HtmlAst[]}, errors: ParseError[]): void {
nodes.forEach((item) => {
if (item instanceof HtmlElementAst) {
let msg = <HtmlElementAst>item;
@ -83,7 +85,7 @@ function _id(el: HtmlElementAst): string {
}
function _serializeMessage(m: Message): string {
let desc = isPresent(m.description) ? ` desc='${m.description}'` : "";
let desc = isPresent(m.description) ? ` desc='${m.description}'` : '';
return `<msg id='${id(m)}'${desc}>${m.content}</msg>`;
}

View File

@ -1,57 +1,6 @@
import {
SimpleChange,
ChangeDetectorRef,
ChangeDetectionStrategy,
ElementRef,
ViewContainerRef,
Renderer,
RenderComponentType,
Injector,
QueryList,
ViewEncapsulation,
TemplateRef
} from '@angular/core';
import {
AppElement,
AppView,
DebugAppView,
ChangeDetectorState,
checkBinding,
DebugContext,
devModeEqual,
flattenNestedViewRenderNodes,
interpolate,
StaticNodeDebugInfo,
TemplateRef_,
uninitialized,
ValueUnwrapper,
ViewType,
ViewUtils,
castByValue,
EMPTY_ARRAY,
EMPTY_MAP,
pureProxy1,
pureProxy2,
pureProxy3,
pureProxy4,
pureProxy5,
pureProxy6,
pureProxy7,
pureProxy8,
pureProxy9,
pureProxy10,
AnimationKeyframe as AnimationKeyframe_,
AnimationStyles as AnimationStyles_,
NoOpAnimationPlayer as NoOpAnimationPlayer_,
AnimationGroupPlayer as AnimationGroupPlayer_,
AnimationSequencePlayer as AnimationSequencePlayer_,
balanceAnimationStyles as impBalanceAnimationStyles,
balanceAnimationKeyframes as impBalanceAnimationKeyframes,
clearStyles as impClearStyles,
collectAndResolveStyles as impCollectAndResolveStyles,
renderStyles as impRenderStyles,
SecurityContext
} from '../core_private';
import {ChangeDetectionStrategy, ChangeDetectorRef, ElementRef, Injector, QueryList, RenderComponentType, Renderer, SimpleChange, TemplateRef, ViewContainerRef, ViewEncapsulation} from '@angular/core';
import {AnimationGroupPlayer as AnimationGroupPlayer_, AnimationKeyframe as AnimationKeyframe_, AnimationSequencePlayer as AnimationSequencePlayer_, AnimationStyles as AnimationStyles_, AppElement, AppView, ChangeDetectorState, DebugAppView, DebugContext, EMPTY_ARRAY, EMPTY_MAP, NoOpAnimationPlayer as NoOpAnimationPlayer_, SecurityContext, StaticNodeDebugInfo, TemplateRef_, ValueUnwrapper, ViewType, ViewUtils, balanceAnimationKeyframes as impBalanceAnimationKeyframes, balanceAnimationStyles as impBalanceAnimationStyles, castByValue, checkBinding, clearStyles as impClearStyles, collectAndResolveStyles as impCollectAndResolveStyles, devModeEqual, flattenNestedViewRenderNodes, interpolate, pureProxy1, pureProxy10, pureProxy2, pureProxy3, pureProxy4, pureProxy5, pureProxy6, pureProxy7, pureProxy8, pureProxy9, renderStyles as impRenderStyles, uninitialized} from '../core_private';
import {CompileIdentifierMetadata, CompileTokenMetadata} from './compile_metadata';
import {assetUrl} from './util';
@ -98,7 +47,7 @@ var impAnimationKeyframe = AnimationKeyframe_;
var impAnimationStyles = AnimationStyles_;
var impNoOpAnimationPlayer = NoOpAnimationPlayer_;
var ANIMATION_STYLE_UTIL_ASSET_URL = assetUrl('core','animation/animation_style_util');
var ANIMATION_STYLE_UTIL_ASSET_URL = assetUrl('core', 'animation/animation_style_util');
export class Identifiers {
static ViewUtils = new CompileIdentifierMetadata(
@ -223,27 +172,27 @@ export class Identifiers {
});
static AnimationKeyframe = new CompileIdentifierMetadata({
name: 'AnimationKeyframe',
moduleUrl: assetUrl('core','animation/animation_keyframe'),
moduleUrl: assetUrl('core', 'animation/animation_keyframe'),
runtime: impAnimationKeyframe
});
static AnimationStyles = new CompileIdentifierMetadata({
name: 'AnimationStyles',
moduleUrl: assetUrl('core','animation/animation_styles'),
moduleUrl: assetUrl('core', 'animation/animation_styles'),
runtime: impAnimationStyles
});
static NoOpAnimationPlayer = new CompileIdentifierMetadata({
name: 'NoOpAnimationPlayer',
moduleUrl: assetUrl('core','animation/animation_player'),
moduleUrl: assetUrl('core', 'animation/animation_player'),
runtime: impNoOpAnimationPlayer
});
static AnimationGroupPlayer = new CompileIdentifierMetadata({
name: 'AnimationGroupPlayer',
moduleUrl: assetUrl('core','animation/animation_group_player'),
moduleUrl: assetUrl('core', 'animation/animation_group_player'),
runtime: impAnimationGroupPlayer
});
static AnimationSequencePlayer = new CompileIdentifierMetadata({
name: 'AnimationSequencePlayer',
moduleUrl: assetUrl('core','animation/animation_sequence_player'),
moduleUrl: assetUrl('core', 'animation/animation_sequence_player'),
runtime: impAnimationSequencePlayer
});
static balanceAnimationStyles = new CompileIdentifierMetadata({
@ -256,16 +205,10 @@ export class Identifiers {
moduleUrl: ANIMATION_STYLE_UTIL_ASSET_URL,
runtime: impBalanceAnimationKeyframes
});
static clearStyles = new CompileIdentifierMetadata({
name: 'clearStyles',
moduleUrl: ANIMATION_STYLE_UTIL_ASSET_URL,
runtime: impClearStyles
});
static renderStyles = new CompileIdentifierMetadata({
name: 'renderStyles',
moduleUrl: ANIMATION_STYLE_UTIL_ASSET_URL,
runtime: impRenderStyles
});
static clearStyles = new CompileIdentifierMetadata(
{name: 'clearStyles', moduleUrl: ANIMATION_STYLE_UTIL_ASSET_URL, runtime: impClearStyles});
static renderStyles = new CompileIdentifierMetadata(
{name: 'renderStyles', moduleUrl: ANIMATION_STYLE_UTIL_ASSET_URL, runtime: impRenderStyles});
static collectAndResolveStyles = new CompileIdentifierMetadata({
name: 'collectAndResolveStyles',
moduleUrl: ANIMATION_STYLE_UTIL_ASSET_URL,

View File

@ -1,53 +1,18 @@
import {
AnimationMetadata,
AnimationEntryMetadata,
AnimationStateMetadata,
AnimationStateDeclarationMetadata,
AnimationStateTransitionMetadata,
AnimationStyleMetadata,
AnimationKeyframesSequenceMetadata,
AnimationAnimateMetadata,
AnimationWithStepsMetadata,
AnimationGroupMetadata,
AttributeMetadata,
OptionalMetadata,
ComponentMetadata,
SelfMetadata,
HostMetadata,
SkipSelfMetadata,
Provider,
PLATFORM_DIRECTIVES,
PLATFORM_PIPES,
Injectable,
Inject,
Optional,
ViewMetadata,
QueryMetadata,
resolveForwardRef,
InjectMetadata,
ViewQueryMetadata
} from '@angular/core';
import {LIFECYCLE_HOOKS_VALUES, ReflectorReader, reflector} from '../core_private';
import {
Type,
isBlank,
isPresent,
isArray,
stringify,
isString,
isStringMap
} from '../src/facade/lang';
import {AnimationAnimateMetadata, AnimationEntryMetadata, AnimationGroupMetadata, AnimationKeyframesSequenceMetadata, AnimationMetadata, AnimationStateDeclarationMetadata, AnimationStateMetadata, AnimationStateTransitionMetadata, AnimationStyleMetadata, AnimationWithStepsMetadata, AttributeMetadata, ComponentMetadata, HostMetadata, Inject, InjectMetadata, Injectable, Optional, OptionalMetadata, PLATFORM_DIRECTIVES, PLATFORM_PIPES, Provider, QueryMetadata, SelfMetadata, SkipSelfMetadata, ViewMetadata, ViewQueryMetadata, resolveForwardRef} from '@angular/core';
import {LIFECYCLE_HOOKS_VALUES, ReflectorReader, createProvider, isProviderLiteral, reflector} from '../core_private';
import {StringMapWrapper} from '../src/facade/collection';
import {BaseException} from '../src/facade/exceptions';
import {Type, isArray, isBlank, isPresent, isString, isStringMap, stringify} from '../src/facade/lang';
import {assertArrayOfStrings} from './assertions';
import * as cpl from './compile_metadata';
import {hasLifecycleHook} from './directive_lifecycle_reflector';
import {DirectiveResolver} from './directive_resolver';
import {PipeResolver} from './pipe_resolver';
import {ViewResolver} from './view_resolver';
import {hasLifecycleHook} from './directive_lifecycle_reflector';
import {MODULE_SUFFIX, sanitizeIdentifier, ValueTransformer, visitValue} from './util';
import {assertArrayOfStrings} from './assertions';
import {getUrlScheme} from './url_resolver';
import {createProvider, isProviderLiteral} from "../core_private";
import {MODULE_SUFFIX, ValueTransformer, sanitizeIdentifier, visitValue} from './util';
import {ViewResolver} from './view_resolver';
@Injectable()
@ -58,11 +23,12 @@ export class CompileMetadataResolver {
private _anonymousTypeIndex = 0;
private _reflector: ReflectorReader;
constructor(private _directiveResolver: DirectiveResolver, private _pipeResolver: PipeResolver,
private _viewResolver: ViewResolver,
@Optional() @Inject(PLATFORM_DIRECTIVES) private _platformDirectives: Type[],
@Optional() @Inject(PLATFORM_PIPES) private _platformPipes: Type[],
_reflector?: ReflectorReader) {
constructor(
private _directiveResolver: DirectiveResolver, private _pipeResolver: PipeResolver,
private _viewResolver: ViewResolver,
@Optional() @Inject(PLATFORM_DIRECTIVES) private _platformDirectives: Type[],
@Optional() @Inject(PLATFORM_PIPES) private _platformPipes: Type[],
_reflector?: ReflectorReader) {
if (isPresent(_reflector)) {
this._reflector = _reflector;
} else {
@ -94,7 +60,8 @@ export class CompileMetadataResolver {
var styles = this.getAnimationStyleMetadata(value.styles);
return new cpl.CompileAnimationStateDeclarationMetadata(value.stateNameExpr, styles);
} else if (value instanceof AnimationStateTransitionMetadata) {
return new cpl.CompileAnimationStateTransitionMetadata(value.stateChangeExpr, this.getAnimationMetadata(value.steps));
return new cpl.CompileAnimationStateTransitionMetadata(
value.stateChangeExpr, this.getAnimationMetadata(value.steps));
}
return null;
}
@ -107,9 +74,12 @@ export class CompileMetadataResolver {
if (value instanceof AnimationStyleMetadata) {
return this.getAnimationStyleMetadata(value);
} else if (value instanceof AnimationKeyframesSequenceMetadata) {
return new cpl.CompileAnimationKeyframesSequenceMetadata(value.steps.map(entry => this.getAnimationStyleMetadata(entry)));
return new cpl.CompileAnimationKeyframesSequenceMetadata(
value.steps.map(entry => this.getAnimationStyleMetadata(entry)));
} else if (value instanceof AnimationAnimateMetadata) {
let animateData = <cpl.CompileAnimationStyleMetadata|cpl.CompileAnimationKeyframesSequenceMetadata>this.getAnimationMetadata(value.styles);
let animateData =
<cpl.CompileAnimationStyleMetadata|cpl.CompileAnimationKeyframesSequenceMetadata>this
.getAnimationMetadata(value.styles);
return new cpl.CompileAnimationAnimateMetadata(value.timings, animateData);
} else if (value instanceof AnimationWithStepsMetadata) {
var steps = value.steps.map(step => this.getAnimationMetadata(step));
@ -135,9 +105,9 @@ export class CompileMetadataResolver {
var cmpMeta = <ComponentMetadata>dirMeta;
var viewMeta = this._viewResolver.resolve(directiveType);
assertArrayOfStrings('styles', viewMeta.styles);
var animations = isPresent(viewMeta.animations)
? viewMeta.animations.map(e => this.getAnimationEntryMetadata(e))
: null;
var animations = isPresent(viewMeta.animations) ?
viewMeta.animations.map(e => this.getAnimationEntryMetadata(e)) :
null;
templateMeta = new cpl.CompileTemplateMetadata({
encapsulation: viewMeta.encapsulation,
@ -258,8 +228,8 @@ export class CompileMetadataResolver {
return pipes.map(type => this.getPipeMetadata(type));
}
getDependenciesMetadata(typeOrFunc: Type | Function,
dependencies: any[]): cpl.CompileDiDependencyMetadata[] {
getDependenciesMetadata(typeOrFunc: Type|Function, dependencies: any[]):
cpl.CompileDiDependencyMetadata[] {
let hasUnknownDeps = false;
let params = isPresent(dependencies) ? dependencies : this._reflector.parameters(typeOrFunc);
if (isBlank(params)) {
@ -278,31 +248,30 @@ export class CompileMetadataResolver {
let viewQuery: ViewQueryMetadata = null;
var token: any /** TODO #9100 */ = null;
if (isArray(param)) {
(<any[]>param)
.forEach((paramEntry) => {
if (paramEntry instanceof HostMetadata) {
isHost = true;
} else if (paramEntry instanceof SelfMetadata) {
isSelf = true;
} else if (paramEntry instanceof SkipSelfMetadata) {
isSkipSelf = true;
} else if (paramEntry instanceof OptionalMetadata) {
isOptional = true;
} else if (paramEntry instanceof AttributeMetadata) {
isAttribute = true;
token = paramEntry.attributeName;
} else if (paramEntry instanceof QueryMetadata) {
if (paramEntry.isViewQuery) {
viewQuery = paramEntry;
} else {
query = paramEntry;
}
} else if (paramEntry instanceof InjectMetadata) {
token = paramEntry.token;
} else if (isValidType(paramEntry) && isBlank(token)) {
token = paramEntry;
}
});
(<any[]>param).forEach((paramEntry) => {
if (paramEntry instanceof HostMetadata) {
isHost = true;
} else if (paramEntry instanceof SelfMetadata) {
isSelf = true;
} else if (paramEntry instanceof SkipSelfMetadata) {
isSkipSelf = true;
} else if (paramEntry instanceof OptionalMetadata) {
isOptional = true;
} else if (paramEntry instanceof AttributeMetadata) {
isAttribute = true;
token = paramEntry.attributeName;
} else if (paramEntry instanceof QueryMetadata) {
if (paramEntry.isViewQuery) {
viewQuery = paramEntry;
} else {
query = paramEntry;
}
} else if (paramEntry instanceof InjectMetadata) {
token = paramEntry.token;
} else if (isValidType(paramEntry) && isBlank(token)) {
token = paramEntry;
}
});
} else {
token = param;
}
@ -324,10 +293,11 @@ export class CompileMetadataResolver {
});
if (hasUnknownDeps) {
let depsTokens = dependenciesMetadata.map((dep) => {
return dep ? stringify(dep.token) : '?';
}).join(', ');
throw new BaseException(`Can't resolve all parameters for ${stringify(typeOrFunc)}: (${depsTokens}).`);
let depsTokens =
dependenciesMetadata.map((dep) => { return dep ? stringify(dep.token) : '?'; })
.join(', ');
throw new BaseException(
`Can't resolve all parameters for ${stringify(typeOrFunc)}: (${depsTokens}).`);
}
return dependenciesMetadata;
@ -351,7 +321,7 @@ export class CompileMetadataResolver {
}
getProvidersMetadata(providers: any[]):
Array<cpl.CompileProviderMetadata | cpl.CompileTypeMetadata | any[]> {
Array<cpl.CompileProviderMetadata|cpl.CompileTypeMetadata|any[]> {
return providers.map((provider) => {
provider = resolveForwardRef(provider);
if (isArray(provider)) {
@ -375,15 +345,13 @@ export class CompileMetadataResolver {
}
return new cpl.CompileProviderMetadata({
token: this.getTokenMetadata(provider.token),
useClass:
isPresent(provider.useClass) ?
this.getTypeMetadata(provider.useClass, staticTypeModuleUrl(provider.useClass)) :
null,
useClass: isPresent(provider.useClass) ?
this.getTypeMetadata(provider.useClass, staticTypeModuleUrl(provider.useClass)) :
null,
useValue: convertToCompileValue(provider.useValue),
useFactory: isPresent(provider.useFactory) ?
this.getFactoryMetadata(provider.useFactory,
staticTypeModuleUrl(provider.useFactory)) :
null,
this.getFactoryMetadata(provider.useFactory, staticTypeModuleUrl(provider.useFactory)) :
null,
useExisting: isPresent(provider.useExisting) ? this.getTokenMetadata(provider.useExisting) :
null,
deps: compileDeps,
@ -391,24 +359,28 @@ export class CompileMetadataResolver {
});
}
getQueriesMetadata(queries: {[key: string]: QueryMetadata},
isViewQuery: boolean, directiveType: Type): cpl.CompileQueryMetadata[] {
getQueriesMetadata(
queries: {[key: string]: QueryMetadata}, isViewQuery: boolean,
directiveType: Type): cpl.CompileQueryMetadata[] {
var compileQueries: any[] /** TODO #9100 */ = [];
StringMapWrapper.forEach(queries, (query: any /** TODO #9100 */, propertyName: any /** TODO #9100 */) => {
if (query.isViewQuery === isViewQuery) {
compileQueries.push(this.getQueryMetadata(query, propertyName, directiveType));
}
});
StringMapWrapper.forEach(
queries, (query: any /** TODO #9100 */, propertyName: any /** TODO #9100 */) => {
if (query.isViewQuery === isViewQuery) {
compileQueries.push(this.getQueryMetadata(query, propertyName, directiveType));
}
});
return compileQueries;
}
getQueryMetadata(q: QueryMetadata, propertyName: string, typeOrFunc: Type | Function): cpl.CompileQueryMetadata {
getQueryMetadata(q: QueryMetadata, propertyName: string, typeOrFunc: Type|Function):
cpl.CompileQueryMetadata {
var selectors: any /** TODO #9100 */;
if (q.isVarBindingQuery) {
selectors = q.varBindings.map(varName => this.getTokenMetadata(varName));
} else {
if (!isPresent(q.selector)) {
throw new BaseException(`Can't construct a query for the property "${propertyName}" of "${stringify(typeOrFunc)}" since the query selector wasn't defined.`);
throw new BaseException(
`Can't construct a query for the property "${propertyName}" of "${stringify(typeOrFunc)}" since the query selector wasn't defined.`);
}
selectors = [this.getTokenMetadata(q.selector)];
}
@ -444,7 +416,7 @@ function flattenPipes(view: ViewMetadata, platformPipes: any[]): Type[] {
return pipes;
}
function flattenArray(tree: any[], out: Array<Type | any[]>): void {
function flattenArray(tree: any[], out: Array<Type|any[]>): void {
for (var i = 0; i < tree.length; i++) {
var item = resolveForwardRef(tree[i]);
if (isArray(item)) {
@ -467,8 +439,8 @@ function staticTypeModuleUrl(value: any): string {
return isStaticType(value) ? value['filePath'] : null;
}
function componentModuleUrl(reflector: ReflectorReader, type: any,
cmpMetadata: ComponentMetadata): string {
function componentModuleUrl(
reflector: ReflectorReader, type: any, cmpMetadata: ComponentMetadata): string {
if (isStaticType(type)) {
return staticTypeModuleUrl(type);
}

View File

@ -1,23 +1,16 @@
import {ComponentFactory} from '@angular/core';
import {
CompileDirectiveMetadata,
CompileIdentifierMetadata,
CompilePipeMetadata,
createHostComponentMeta
} from './compile_metadata';
import {BaseException} from './facade/exceptions';
import {ListWrapper} from './facade/collection';
import {StyleCompiler, StylesCompileResult} from './style_compiler';
import {ViewCompiler, ViewCompileResult} from './view_compiler/view_compiler';
import {TemplateParser} from './template_parser';
import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompilePipeMetadata, createHostComponentMeta} from './compile_metadata';
import {DirectiveNormalizer} from './directive_normalizer';
import {ListWrapper} from './facade/collection';
import {BaseException} from './facade/exceptions';
import {OutputEmitter} from './output/abstract_emitter';
import * as o from './output/output_ast';
import {XHR} from './xhr';
import {StyleCompiler, StylesCompileResult} from './style_compiler';
import {TemplateParser} from './template_parser';
import {assetUrl} from './util';
import {ViewCompileResult, ViewCompiler} from './view_compiler/view_compiler';
import {XHR} from './xhr';
var _COMPONENT_FACTORY_IDENTIFIER = new CompileIdentifierMetadata({
name: 'ComponentFactory',
@ -34,15 +27,16 @@ export class StyleSheetSourceWithImports {
}
export class NormalizedComponentWithViewDirectives {
constructor(public component: CompileDirectiveMetadata,
public directives: CompileDirectiveMetadata[], public pipes: CompilePipeMetadata[]) {}
constructor(
public component: CompileDirectiveMetadata, public directives: CompileDirectiveMetadata[],
public pipes: CompilePipeMetadata[]) {}
}
export class OfflineCompiler {
constructor(private _directiveNormalizer: DirectiveNormalizer,
private _templateParser: TemplateParser, private _styleCompiler: StyleCompiler,
private _viewCompiler: ViewCompiler, private _outputEmitter: OutputEmitter,
private _xhr: XHR) {}
constructor(
private _directiveNormalizer: DirectiveNormalizer, private _templateParser: TemplateParser,
private _styleCompiler: StyleCompiler, private _viewCompiler: ViewCompiler,
private _outputEmitter: OutputEmitter, private _xhr: XHR) {}
normalizeDirectiveMetadata(directive: CompileDirectiveMetadata):
Promise<CompileDirectiveMetadata> {
@ -59,8 +53,8 @@ export class OfflineCompiler {
components.forEach(componentWithDirs => {
var compMeta = <CompileDirectiveMetadata>componentWithDirs.component;
_assertComponent(compMeta);
var compViewFactoryVar = this._compileComponent(compMeta, componentWithDirs.directives,
componentWithDirs.pipes, statements);
var compViewFactoryVar = this._compileComponent(
compMeta, componentWithDirs.directives, componentWithDirs.pipes, statements);
exportedVars.push(compViewFactoryVar);
var hostMeta = createHostComponentMeta(compMeta.type, compMeta.selector);
@ -71,56 +65,56 @@ export class OfflineCompiler {
.set(o.importExpr(_COMPONENT_FACTORY_IDENTIFIER, [o.importType(compMeta.type)])
.instantiate(
[
o.literal(compMeta.selector),
o.variable(hostViewFactoryVar),
o.literal(compMeta.selector), o.variable(hostViewFactoryVar),
o.importExpr(compMeta.type)
],
o.importType(_COMPONENT_FACTORY_IDENTIFIER,
[o.importType(compMeta.type)], [o.TypeModifier.Const])))
o.importType(
_COMPONENT_FACTORY_IDENTIFIER, [o.importType(compMeta.type)],
[o.TypeModifier.Const])))
.toDeclStmt(null, [o.StmtModifier.Final]));
exportedVars.push(compFactoryVar);
});
return this._codegenSourceModule(moduleUrl, statements, exportedVars);
}
loadAndCompileStylesheet(stylesheetUrl: string, shim: boolean,
suffix: string): Promise<StyleSheetSourceWithImports> {
return this._xhr.get(stylesheetUrl)
.then((cssText) => {
var compileResult = this._styleCompiler.compileStylesheet(stylesheetUrl, cssText, shim);
var importedUrls: any[] /** TODO #9100 */ = [];
compileResult.dependencies.forEach((dep) => {
importedUrls.push(dep.moduleUrl);
dep.valuePlaceholder.moduleUrl = _stylesModuleUrl(dep.moduleUrl, dep.isShimmed, suffix);
});
return new StyleSheetSourceWithImports(
this._codgenStyles(stylesheetUrl, shim, suffix, compileResult), importedUrls);
});
loadAndCompileStylesheet(stylesheetUrl: string, shim: boolean, suffix: string):
Promise<StyleSheetSourceWithImports> {
return this._xhr.get(stylesheetUrl).then((cssText) => {
var compileResult = this._styleCompiler.compileStylesheet(stylesheetUrl, cssText, shim);
var importedUrls: any[] /** TODO #9100 */ = [];
compileResult.dependencies.forEach((dep) => {
importedUrls.push(dep.moduleUrl);
dep.valuePlaceholder.moduleUrl = _stylesModuleUrl(dep.moduleUrl, dep.isShimmed, suffix);
});
return new StyleSheetSourceWithImports(
this._codgenStyles(stylesheetUrl, shim, suffix, compileResult), importedUrls);
});
}
private _compileComponent(compMeta: CompileDirectiveMetadata,
directives: CompileDirectiveMetadata[], pipes: CompilePipeMetadata[],
targetStatements: o.Statement[]): string {
private _compileComponent(
compMeta: CompileDirectiveMetadata, directives: CompileDirectiveMetadata[],
pipes: CompilePipeMetadata[], targetStatements: o.Statement[]): string {
var styleResult = this._styleCompiler.compileComponent(compMeta);
var parsedTemplate = this._templateParser.parse(compMeta, compMeta.template.template,
directives, pipes, compMeta.type.name);
var viewResult = this._viewCompiler.compileComponent(compMeta, parsedTemplate,
o.variable(styleResult.stylesVar), pipes);
ListWrapper.addAll(targetStatements,
_resolveStyleStatements(compMeta.type.moduleUrl, styleResult));
var parsedTemplate = this._templateParser.parse(
compMeta, compMeta.template.template, directives, pipes, compMeta.type.name);
var viewResult = this._viewCompiler.compileComponent(
compMeta, parsedTemplate, o.variable(styleResult.stylesVar), pipes);
ListWrapper.addAll(
targetStatements, _resolveStyleStatements(compMeta.type.moduleUrl, styleResult));
ListWrapper.addAll(targetStatements, _resolveViewStatements(viewResult));
return viewResult.viewFactoryVar;
}
private _codgenStyles(inputUrl: string, shim: boolean, suffix: string,
stylesCompileResult: StylesCompileResult): SourceModule {
return this._codegenSourceModule(_stylesModuleUrl(inputUrl, shim, suffix),
stylesCompileResult.statements,
[stylesCompileResult.stylesVar]);
private _codgenStyles(
inputUrl: string, shim: boolean, suffix: string,
stylesCompileResult: StylesCompileResult): SourceModule {
return this._codegenSourceModule(
_stylesModuleUrl(inputUrl, shim, suffix), stylesCompileResult.statements,
[stylesCompileResult.stylesVar]);
}
private _codegenSourceModule(moduleUrl: string, statements: o.Statement[],
exportedVars: string[]): SourceModule {
private _codegenSourceModule(
moduleUrl: string, statements: o.Statement[], exportedVars: string[]): SourceModule {
return new SourceModule(
moduleUrl, this._outputEmitter.emitStatements(moduleUrl, statements, exportedVars));
}
@ -133,8 +127,8 @@ function _resolveViewStatements(compileResult: ViewCompileResult): o.Statement[]
}
function _resolveStyleStatements(containingModuleUrl: string,
compileResult: StylesCompileResult): o.Statement[] {
function _resolveStyleStatements(
containingModuleUrl: string, compileResult: StylesCompileResult): o.Statement[] {
var containingSuffix = _splitSuffix(containingModuleUrl)[1];
compileResult.dependencies.forEach((dep) => {
dep.valuePlaceholder.moduleUrl =

View File

@ -1,5 +1,6 @@
import {isPresent, isBlank, isString, StringWrapper} from '../facade/lang';
import {BaseException} from '../facade/exceptions';
import {StringWrapper, isBlank, isPresent, isString} from '../facade/lang';
import * as o from './output_ast';
var _SINGLE_QUOTE_ESCAPE_STRING_RE = /'|\\|\n|\r|\$/g;
@ -73,13 +74,14 @@ export class EmitterVisitorContext {
if (lines[lines.length - 1].parts.length === 0) {
lines = lines.slice(0, lines.length - 1);
}
return lines.map((line) => {
if (line.parts.length > 0) {
return _createIndent(line.indent) + line.parts.join('');
} else {
return '';
}
})
return lines
.map((line) => {
if (line.parts.length > 0) {
return _createIndent(line.indent) + line.parts.join('');
} else {
return '';
}
})
.join('\n');
}
}
@ -367,14 +369,17 @@ export abstract class AbstractEmitterVisitor implements o.StatementVisitor, o.Ex
return null;
}
visitAllExpressions(expressions: o.Expression[], ctx: EmitterVisitorContext, separator: string,
newLine: boolean = false): void {
this.visitAllObjects((expr: any /** TODO #9100 */) => expr.visitExpression(this, ctx), expressions, ctx, separator,
newLine);
visitAllExpressions(
expressions: o.Expression[], ctx: EmitterVisitorContext, separator: string,
newLine: boolean = false): void {
this.visitAllObjects(
(expr: any /** TODO #9100 */) => expr.visitExpression(this, ctx), expressions, ctx,
separator, newLine);
}
visitAllObjects(handler: Function, expressions: any, ctx: EmitterVisitorContext,
separator: string, newLine: boolean = false): void {
visitAllObjects(
handler: Function, expressions: any, ctx: EmitterVisitorContext, separator: string,
newLine: boolean = false): void {
for (var i = 0; i < expressions.length; i++) {
if (i > 0) {
ctx.print(separator, newLine);
@ -395,17 +400,18 @@ export function escapeSingleQuoteString(input: string, escapeDollar: boolean): a
if (isBlank(input)) {
return null;
}
var body = StringWrapper.replaceAllMapped(input, _SINGLE_QUOTE_ESCAPE_STRING_RE, (match: any /** TODO #9100 */) => {
if (match[0] == '$') {
return escapeDollar ? '\\$' : '$';
} else if (match[0] == '\n') {
return '\\n';
} else if (match[0] == '\r') {
return '\\r';
} else {
return `\\${match[0]}`;
}
});
var body = StringWrapper.replaceAllMapped(
input, _SINGLE_QUOTE_ESCAPE_STRING_RE, (match: any /** TODO #9100 */) => {
if (match[0] == '$') {
return escapeDollar ? '\\$' : '$';
} else if (match[0] == '\n') {
return '\\n';
} else if (match[0] == '\r') {
return '\\r';
} else {
return `\\${match[0]}`;
}
});
return `'${body}'`;
}

View File

@ -1,12 +1,8 @@
import {isPresent} from '../facade/lang';
import {BaseException} from '../facade/exceptions';
import {isPresent} from '../facade/lang';
import {AbstractEmitterVisitor, CATCH_ERROR_VAR, CATCH_STACK_VAR, EmitterVisitorContext} from './abstract_emitter';
import * as o from './output_ast';
import {
EmitterVisitorContext,
AbstractEmitterVisitor,
CATCH_ERROR_VAR,
CATCH_STACK_VAR
} from './abstract_emitter';
export abstract class AbstractJsEmitterVisitor extends AbstractEmitterVisitor {
constructor() { super(false); }
@ -130,10 +126,10 @@ export abstract class AbstractJsEmitterVisitor extends AbstractEmitterVisitor {
ctx.decIndent();
ctx.println(`} catch (${CATCH_ERROR_VAR.name}) {`);
ctx.incIndent();
var catchStmts = [
<o.Statement>CATCH_STACK_VAR.set(CATCH_ERROR_VAR.prop('stack'))
.toDeclStmt(null, [o.StmtModifier.Final])
].concat(stmt.catchStmts);
var catchStmts =
[<o.Statement>CATCH_STACK_VAR.set(CATCH_ERROR_VAR.prop('stack')).toDeclStmt(null, [
o.StmtModifier.Final
])].concat(stmt.catchStmts);
this.visitAllStatements(catchStmts, ctx);
ctx.decIndent();
ctx.println(`}`);

View File

@ -1,14 +1,10 @@
import {isPresent, isBlank, isArray} from '../facade/lang';
import {BaseException} from '../facade/exceptions';
import {CompileIdentifierMetadata} from '../compile_metadata';
import {BaseException} from '../facade/exceptions';
import {isArray, isBlank, isPresent} from '../facade/lang';
import * as o from './output_ast';
import {
OutputEmitter,
EmitterVisitorContext,
AbstractEmitterVisitor,
CATCH_ERROR_VAR,
CATCH_STACK_VAR,
} from './abstract_emitter';
import {OutputEmitter, EmitterVisitorContext, AbstractEmitterVisitor, CATCH_ERROR_VAR, CATCH_STACK_VAR,} from './abstract_emitter';
import {ImportGenerator} from './path_util';
var _debugModuleUrl = 'asset://debug/lib';
@ -332,8 +328,8 @@ class _DartEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisito
}, params, ctx, ',');
}
private _visitIdentifier(value: CompileIdentifierMetadata, typeParams: o.Type[],
ctx: EmitterVisitorContext): void {
private _visitIdentifier(
value: CompileIdentifierMetadata, typeParams: o.Type[], ctx: EmitterVisitorContext): void {
if (isBlank(value.name)) {
throw new BaseException(`Internal error: unknown identifier ${value}`);
}
@ -348,7 +344,8 @@ class _DartEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisito
ctx.print(value.name);
if (isPresent(typeParams) && typeParams.length > 0) {
ctx.print(`<`);
this.visitAllObjects((type: any /** TODO #9100 */) => type.visitType(this, ctx), typeParams, ctx, ',');
this.visitAllObjects(
(type: any /** TODO #9100 */) => type.visitType(this, ctx), typeParams, ctx, ',');
ctx.print(`>`);
}
}

View File

@ -1,7 +1,8 @@
import {BaseException} from '../facade/exceptions';
import {isPresent, isBlank, RegExpWrapper, Math} from '../facade/lang';
import {Injectable} from '@angular/core';
import {BaseException} from '../facade/exceptions';
import {Math, RegExpWrapper, isBlank, isPresent} from '../facade/lang';
import {AssetUrl, ImportGenerator} from './path_util';
var _PATH_SEP = '/';

View File

@ -1,12 +1,13 @@
import {AppElement, AppView, DebugAppView} from '../../core_private';
import {isPresent} from '../facade/lang';
import {BaseException} from '../facade/exceptions';
import {InstanceFactory, DynamicInstance} from './output_interpreter';
import {isPresent} from '../facade/lang';
import {DynamicInstance, InstanceFactory} from './output_interpreter';
export class InterpretiveAppViewInstanceFactory implements InstanceFactory {
createInstance(superClass: any, clazz: any, args: any[], props: Map<string, any>,
getters: Map<string, Function>, methods: Map<string, Function>): any {
createInstance(
superClass: any, clazz: any, args: any[], props: Map<string, any>,
getters: Map<string, Function>, methods: Map<string, Function>): any {
if (superClass === AppView) {
// We are always using DebugAppView as parent.
// However, in prod mode we generate a constructor call that does
@ -21,11 +22,12 @@ export class InterpretiveAppViewInstanceFactory implements InstanceFactory {
}
class _InterpretiveAppView extends DebugAppView<any> implements DynamicInstance {
constructor(args: any[], public props: Map<string, any>, public getters: Map<string, Function>,
public methods: Map<string, Function>) {
constructor(
args: any[], public props: Map<string, any>, public getters: Map<string, Function>,
public methods: Map<string, Function>) {
super(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]);
}
createInternal(rootSelector: string | any): AppElement {
createInternal(rootSelector: string|any): AppElement {
var m = this.methods.get('createInternal');
if (isPresent(m)) {
return m(rootSelector);

View File

@ -1,15 +1,10 @@
import * as o from './output_ast';
import {
isPresent,
isBlank,
isString,
evalExpression,
RegExpWrapper,
StringWrapper
} from '../facade/lang';
import {BaseException} from '@angular/core';
import {OutputEmitter, EmitterVisitorContext} from './abstract_emitter';
import {RegExpWrapper, StringWrapper, evalExpression, isBlank, isPresent, isString} from '../facade/lang';
import {EmitterVisitorContext, OutputEmitter} from './abstract_emitter';
import {AbstractJsEmitterVisitor} from './abstract_js_emitter';
import * as o from './output_ast';
import {ImportGenerator} from './path_util';
export class JavaScriptEmitter implements OutputEmitter {

View File

@ -1,5 +1,6 @@
import {isString, isPresent, isBlank} from '../facade/lang';
import {CompileIdentifierMetadata} from '../compile_metadata';
import {isBlank, isPresent, isString} from '../facade/lang';
//// Types
export enum TypeModifier {
@ -34,8 +35,9 @@ export class BuiltinType extends Type {
}
export class ExternalType extends Type {
constructor(public value: CompileIdentifierMetadata, public typeParams: Type[] = null,
modifiers: TypeModifier[] = null) {
constructor(
public value: CompileIdentifierMetadata, public typeParams: Type[] = null,
modifiers: TypeModifier[] = null) {
super(modifiers);
}
visitType(visitor: TypeVisitor, context: any): any {
@ -45,7 +47,7 @@ export class ExternalType extends Type {
export class ArrayType extends Type {
constructor(public of: Type, modifiers: TypeModifier[] = null) { super(modifiers); }
constructor(public of : Type, modifiers: TypeModifier[] = null) { super(modifiers); }
visitType(visitor: TypeVisitor, context: any): any {
return visitor.visitArrayType(this, context);
}
@ -104,7 +106,7 @@ export abstract class Expression {
return new ReadKeyExpr(this, index, type);
}
callMethod(name: string | BuiltinMethod, params: Expression[]): InvokeMethodExpr {
callMethod(name: string|BuiltinMethod, params: Expression[]): InvokeMethodExpr {
return new InvokeMethodExpr(this, name, params);
}
@ -182,7 +184,7 @@ export class ReadVarExpr extends Expression {
public name: any /** TODO #9100 */;
public builtin: BuiltinVar;
constructor(name: string | BuiltinVar, type: Type = null) {
constructor(name: string|BuiltinVar, type: Type = null) {
super(type);
if (isString(name)) {
this.name = <string>name;
@ -219,8 +221,8 @@ export class WriteVarExpr extends Expression {
export class WriteKeyExpr extends Expression {
public value: Expression;
constructor(public receiver: Expression, public index: Expression, value: Expression,
type: Type = null) {
constructor(
public receiver: Expression, public index: Expression, value: Expression, type: Type = null) {
super(isPresent(type) ? type : value.type);
this.value = value;
}
@ -232,8 +234,8 @@ export class WriteKeyExpr extends Expression {
export class WritePropExpr extends Expression {
public value: Expression;
constructor(public receiver: Expression, public name: string, value: Expression,
type: Type = null) {
constructor(
public receiver: Expression, public name: string, value: Expression, type: Type = null) {
super(isPresent(type) ? type : value.type);
this.value = value;
}
@ -251,8 +253,9 @@ export enum BuiltinMethod {
export class InvokeMethodExpr extends Expression {
public name: string;
public builtin: BuiltinMethod;
constructor(public receiver: Expression, method: string | BuiltinMethod,
public args: Expression[], type: Type = null) {
constructor(
public receiver: Expression, method: string|BuiltinMethod, public args: Expression[],
type: Type = null) {
super(type);
if (isString(method)) {
this.name = <string>method;
@ -293,8 +296,9 @@ export class LiteralExpr extends Expression {
export class ExternalExpr extends Expression {
constructor(public value: CompileIdentifierMetadata, type: Type = null,
public typeParams: Type[] = null) {
constructor(
public value: CompileIdentifierMetadata, type: Type = null,
public typeParams: Type[] = null) {
super(type);
}
visitExpression(visitor: ExpressionVisitor, context: any): any {
@ -305,8 +309,9 @@ export class ExternalExpr extends Expression {
export class ConditionalExpr extends Expression {
public trueCase: Expression;
constructor(public condition: Expression, trueCase: Expression,
public falseCase: Expression = null, type: Type = null) {
constructor(
public condition: Expression, trueCase: Expression, public falseCase: Expression = null,
type: Type = null) {
super(isPresent(type) ? type : trueCase.type);
this.trueCase = trueCase;
}
@ -352,8 +357,8 @@ export class FunctionExpr extends Expression {
export class BinaryOperatorExpr extends Expression {
public lhs: Expression;
constructor(public operator: BinaryOperator, lhs: Expression, public rhs: Expression,
type: Type = null) {
constructor(
public operator: BinaryOperator, lhs: Expression, public rhs: Expression, type: Type = null) {
super(isPresent(type) ? type : lhs.type);
this.lhs = lhs;
}
@ -401,7 +406,7 @@ export class LiteralArrayExpr extends Expression {
export class LiteralMapExpr extends Expression {
public valueType: Type = null;
constructor(public entries: Array<Array<string | Expression>>, type: MapType = null) {
constructor(public entries: Array<Array<string|Expression>>, type: MapType = null) {
super(type);
if (isPresent(type)) {
this.valueType = type.valueType;
@ -460,8 +465,9 @@ export abstract class Statement {
export class DeclareVarStmt extends Statement {
public type: Type;
constructor(public name: string, public value: Expression, type: Type = null,
modifiers: StmtModifier[] = null) {
constructor(
public name: string, public value: Expression, type: Type = null,
modifiers: StmtModifier[] = null) {
super(modifiers);
this.type = isPresent(type) ? type : value.type;
}
@ -472,8 +478,9 @@ export class DeclareVarStmt extends Statement {
}
export class DeclareFunctionStmt extends Statement {
constructor(public name: string, public params: FnParam[], public statements: Statement[],
public type: Type = null, modifiers: StmtModifier[] = null) {
constructor(
public name: string, public params: FnParam[], public statements: Statement[],
public type: Type = null, modifiers: StmtModifier[] = null) {
super(modifiers);
}
@ -515,25 +522,28 @@ export class ClassField extends AbstractClassPart {
export class ClassMethod extends AbstractClassPart {
constructor(public name: string, public params: FnParam[], public body: Statement[],
type: Type = null, modifiers: StmtModifier[] = null) {
constructor(
public name: string, public params: FnParam[], public body: Statement[], type: Type = null,
modifiers: StmtModifier[] = null) {
super(type, modifiers);
}
}
export class ClassGetter extends AbstractClassPart {
constructor(public name: string, public body: Statement[], type: Type = null,
modifiers: StmtModifier[] = null) {
constructor(
public name: string, public body: Statement[], type: Type = null,
modifiers: StmtModifier[] = null) {
super(type, modifiers);
}
}
export class ClassStmt extends Statement {
constructor(public name: string, public parent: Expression, public fields: ClassField[],
public getters: ClassGetter[], public constructorMethod: ClassMethod,
public methods: ClassMethod[], modifiers: StmtModifier[] = null) {
constructor(
public name: string, public parent: Expression, public fields: ClassField[],
public getters: ClassGetter[], public constructorMethod: ClassMethod,
public methods: ClassMethod[], modifiers: StmtModifier[] = null) {
super(modifiers);
}
visitStatement(visitor: StatementVisitor, context: any): any {
@ -543,8 +553,9 @@ export class ClassStmt extends Statement {
export class IfStmt extends Statement {
constructor(public condition: Expression, public trueCase: Statement[],
public falseCase: Statement[] = /*@ts2dart_const*/[]) {
constructor(
public condition: Expression, public trueCase: Statement[],
public falseCase: Statement[] = /*@ts2dart_const*/[]) {
super();
}
visitStatement(visitor: StatementVisitor, context: any): any {
@ -594,33 +605,37 @@ export class ExpressionTransformer implements StatementVisitor, ExpressionVisito
return new WriteVarExpr(expr.name, expr.value.visitExpression(this, context));
}
visitWriteKeyExpr(expr: WriteKeyExpr, context: any): any {
return new WriteKeyExpr(expr.receiver.visitExpression(this, context),
expr.index.visitExpression(this, context),
expr.value.visitExpression(this, context));
return new WriteKeyExpr(
expr.receiver.visitExpression(this, context), expr.index.visitExpression(this, context),
expr.value.visitExpression(this, context));
}
visitWritePropExpr(expr: WritePropExpr, context: any): any {
return new WritePropExpr(expr.receiver.visitExpression(this, context), expr.name,
expr.value.visitExpression(this, context));
return new WritePropExpr(
expr.receiver.visitExpression(this, context), expr.name,
expr.value.visitExpression(this, context));
}
visitInvokeMethodExpr(ast: InvokeMethodExpr, context: any): any {
var method = isPresent(ast.builtin) ? ast.builtin : ast.name;
return new InvokeMethodExpr(ast.receiver.visitExpression(this, context), method,
this.visitAllExpressions(ast.args, context), ast.type);
return new InvokeMethodExpr(
ast.receiver.visitExpression(this, context), method,
this.visitAllExpressions(ast.args, context), ast.type);
}
visitInvokeFunctionExpr(ast: InvokeFunctionExpr, context: any): any {
return new InvokeFunctionExpr(ast.fn.visitExpression(this, context),
this.visitAllExpressions(ast.args, context), ast.type);
return new InvokeFunctionExpr(
ast.fn.visitExpression(this, context), this.visitAllExpressions(ast.args, context),
ast.type);
}
visitInstantiateExpr(ast: InstantiateExpr, context: any): any {
return new InstantiateExpr(ast.classExpr.visitExpression(this, context),
this.visitAllExpressions(ast.args, context), ast.type);
return new InstantiateExpr(
ast.classExpr.visitExpression(this, context), this.visitAllExpressions(ast.args, context),
ast.type);
}
visitLiteralExpr(ast: LiteralExpr, context: any): any { return ast; }
visitExternalExpr(ast: ExternalExpr, context: any): any { return ast; }
visitConditionalExpr(ast: ConditionalExpr, context: any): any {
return new ConditionalExpr(ast.condition.visitExpression(this, context),
ast.trueCase.visitExpression(this, context),
ast.falseCase.visitExpression(this, context));
return new ConditionalExpr(
ast.condition.visitExpression(this, context), ast.trueCase.visitExpression(this, context),
ast.falseCase.visitExpression(this, context));
}
visitNotExpr(ast: NotExpr, context: any): any {
return new NotExpr(ast.condition.visitExpression(this, context));
@ -633,15 +648,17 @@ export class ExpressionTransformer implements StatementVisitor, ExpressionVisito
return ast;
}
visitBinaryOperatorExpr(ast: BinaryOperatorExpr, context: any): any {
return new BinaryOperatorExpr(ast.operator, ast.lhs.visitExpression(this, context),
ast.rhs.visitExpression(this, context), ast.type);
return new BinaryOperatorExpr(
ast.operator, ast.lhs.visitExpression(this, context),
ast.rhs.visitExpression(this, context), ast.type);
}
visitReadPropExpr(ast: ReadPropExpr, context: any): any {
return new ReadPropExpr(ast.receiver.visitExpression(this, context), ast.name, ast.type);
}
visitReadKeyExpr(ast: ReadKeyExpr, context: any): any {
return new ReadKeyExpr(ast.receiver.visitExpression(this, context),
ast.index.visitExpression(this, context), ast.type);
return new ReadKeyExpr(
ast.receiver.visitExpression(this, context), ast.index.visitExpression(this, context),
ast.type);
}
visitLiteralArrayExpr(ast: LiteralArrayExpr, context: any): any {
return new LiteralArrayExpr(this.visitAllExpressions(ast.entries, context));
@ -655,8 +672,8 @@ export class ExpressionTransformer implements StatementVisitor, ExpressionVisito
}
visitDeclareVarStmt(stmt: DeclareVarStmt, context: any): any {
return new DeclareVarStmt(stmt.name, stmt.value.visitExpression(this, context), stmt.type,
stmt.modifiers);
return new DeclareVarStmt(
stmt.name, stmt.value.visitExpression(this, context), stmt.type, stmt.modifiers);
}
visitDeclareFunctionStmt(stmt: DeclareFunctionStmt, context: any): any {
// Don't descend into nested functions
@ -673,13 +690,15 @@ export class ExpressionTransformer implements StatementVisitor, ExpressionVisito
return stmt;
}
visitIfStmt(stmt: IfStmt, context: any): any {
return new IfStmt(stmt.condition.visitExpression(this, context),
this.visitAllStatements(stmt.trueCase, context),
this.visitAllStatements(stmt.falseCase, context));
return new IfStmt(
stmt.condition.visitExpression(this, context),
this.visitAllStatements(stmt.trueCase, context),
this.visitAllStatements(stmt.falseCase, context));
}
visitTryCatchStmt(stmt: TryCatchStmt, context: any): any {
return new TryCatchStmt(this.visitAllStatements(stmt.bodyStmts, context),
this.visitAllStatements(stmt.catchStmts, context));
return new TryCatchStmt(
this.visitAllStatements(stmt.bodyStmts, context),
this.visitAllStatements(stmt.catchStmts, context));
}
visitThrowStmt(stmt: ThrowStmt, context: any): any {
return new ThrowStmt(stmt.error.visitExpression(this, context));
@ -807,8 +826,8 @@ export class RecursiveExpressionVisitor implements StatementVisitor, ExpressionV
}
}
export function replaceVarInExpression(varName: string, newValue: Expression,
expression: Expression): Expression {
export function replaceVarInExpression(
varName: string, newValue: Expression, expression: Expression): Expression {
var transformer = new _ReplaceVariableTransformer(varName, newValue);
return expression.visitExpression(transformer, null);
}
@ -842,8 +861,9 @@ export function importExpr(id: CompileIdentifierMetadata, typeParams: Type[] = n
return new ExternalExpr(id, null, typeParams);
}
export function importType(id: CompileIdentifierMetadata, typeParams: Type[] = null,
typeModifiers: TypeModifier[] = null): ExternalType {
export function importType(
id: CompileIdentifierMetadata, typeParams: Type[] = null,
typeModifiers: TypeModifier[] = null): ExternalType {
return isPresent(id) ? new ExternalType(id, typeParams, typeModifiers) : null;
}
@ -855,8 +875,8 @@ export function literalArr(values: Expression[], type: Type = null): LiteralArra
return new LiteralArrayExpr(values, type);
}
export function literalMap(values: Array<Array<string | Expression>>,
type: MapType = null): LiteralMapExpr {
export function literalMap(
values: Array<Array<string|Expression>>, type: MapType = null): LiteralMapExpr {
return new LiteralMapExpr(values, type);
}

View File

@ -1,27 +1,28 @@
import {reflector} from '../../core_private';
import {isPresent, IS_DART, FunctionWrapper} from '../facade/lang';
import {ObservableWrapper} from '../facade/async';
import {BaseException, unimplemented} from '../facade/exceptions';
import {ListWrapper} from '../facade/collection';
import {BaseException, unimplemented} from '../facade/exceptions';
import {FunctionWrapper, IS_DART, isPresent} from '../facade/lang';
import * as o from './output_ast';
import {debugOutputAstAsDart} from './dart_emitter';
import * as o from './output_ast';
import {debugOutputAstAsTypeScript} from './ts_emitter';
export function interpretStatements(statements: o.Statement[], resultVar: string,
instanceFactory: InstanceFactory): any {
export function interpretStatements(
statements: o.Statement[], resultVar: string, instanceFactory: InstanceFactory): any {
var stmtsWithReturn = statements.concat([new o.ReturnStatement(o.variable(resultVar))]);
var ctx = new _ExecutionContext(null, null, null, null, new Map<string, any>(),
new Map<string, any>(), new Map<string, Function>(),
new Map<string, Function>(), instanceFactory);
var ctx = new _ExecutionContext(
null, null, null, null, new Map<string, any>(), new Map<string, any>(),
new Map<string, Function>(), new Map<string, Function>(), instanceFactory);
var visitor = new StatementInterpreter();
var result = visitor.visitAllStatements(stmtsWithReturn, ctx);
return isPresent(result) ? result.value : null;
}
export interface InstanceFactory {
createInstance(superClass: any, clazz: any, constructorArgs: any[], props: Map<string, any>,
getters: Map<string, Function>, methods: Map<string, Function>): DynamicInstance;
createInstance(
superClass: any, clazz: any, constructorArgs: any[], props: Map<string, any>,
getters: Map<string, Function>, methods: Map<string, Function>): DynamicInstance;
}
export abstract class DynamicInstance {
@ -36,12 +37,13 @@ function isDynamicInstance(instance: any): any {
return instance instanceof DynamicInstance;
} else {
return isPresent(instance) && isPresent(instance.props) && isPresent(instance.getters) &&
isPresent(instance.methods);
isPresent(instance.methods);
}
}
function _executeFunctionStatements(varNames: string[], varValues: any[], statements: o.Statement[],
ctx: _ExecutionContext, visitor: StatementInterpreter): any {
function _executeFunctionStatements(
varNames: string[], varValues: any[], statements: o.Statement[], ctx: _ExecutionContext,
visitor: StatementInterpreter): any {
var childCtx = ctx.createChildWihtLocalVars();
for (var i = 0; i < varNames.length; i++) {
childCtx.vars.set(varNames[i], varValues[i]);
@ -51,15 +53,16 @@ function _executeFunctionStatements(varNames: string[], varValues: any[], statem
}
class _ExecutionContext {
constructor(public parent: _ExecutionContext, public superClass: any, public superInstance: any,
public className: string, public vars: Map<string, any>,
public props: Map<string, any>, public getters: Map<string, Function>,
public methods: Map<string, Function>, public instanceFactory: InstanceFactory) {}
constructor(
public parent: _ExecutionContext, public superClass: any, public superInstance: any,
public className: string, public vars: Map<string, any>, public props: Map<string, any>,
public getters: Map<string, Function>, public methods: Map<string, Function>,
public instanceFactory: InstanceFactory) {}
createChildWihtLocalVars(): _ExecutionContext {
return new _ExecutionContext(this, this.superClass, this.superInstance, this.className,
new Map<string, any>(), this.props, this.getters, this.methods,
this.instanceFactory);
return new _ExecutionContext(
this, this.superClass, this.superInstance, this.className, new Map<string, any>(),
this.props, this.getters, this.methods, this.instanceFactory);
}
}
@ -68,22 +71,24 @@ class ReturnValue {
}
class _DynamicClass {
constructor(private _classStmt: o.ClassStmt, private _ctx: _ExecutionContext,
private _visitor: StatementInterpreter) {}
constructor(
private _classStmt: o.ClassStmt, private _ctx: _ExecutionContext,
private _visitor: StatementInterpreter) {}
instantiate(args: any[]): DynamicInstance {
var props = new Map<string, any>();
var getters = new Map<string, Function>();
var methods = new Map<string, Function>();
var superClass = this._classStmt.parent.visitExpression(this._visitor, this._ctx);
var instanceCtx =
new _ExecutionContext(this._ctx, superClass, null, this._classStmt.name, this._ctx.vars,
props, getters, methods, this._ctx.instanceFactory);
var instanceCtx = new _ExecutionContext(
this._ctx, superClass, null, this._classStmt.name, this._ctx.vars, props, getters, methods,
this._ctx.instanceFactory);
this._classStmt.fields.forEach((field: o.ClassField) => { props.set(field.name, null); });
this._classStmt.getters.forEach((getter: o.ClassGetter) => {
getters.set(getter.name, () => _executeFunctionStatements([], [], getter.body, instanceCtx,
this._visitor));
getters.set(
getter.name,
() => _executeFunctionStatements([], [], getter.body, instanceCtx, this._visitor));
});
this._classStmt.methods.forEach((method: o.ClassMethod) => {
var paramNames = method.params.map(param => param.name);
@ -91,8 +96,8 @@ class _DynamicClass {
});
var ctorParamNames = this._classStmt.constructorMethod.params.map(param => param.name);
_executeFunctionStatements(ctorParamNames, args, this._classStmt.constructorMethod.body,
instanceCtx, this._visitor);
_executeFunctionStatements(
ctorParamNames, args, this._classStmt.constructorMethod.body, instanceCtx, this._visitor);
return instanceCtx.superInstance;
}
@ -100,7 +105,7 @@ class _DynamicClass {
}
class StatementInterpreter implements o.StatementVisitor, o.ExpressionVisitor {
debugAst(ast: o.Expression | o.Statement | o.Type): string {
debugAst(ast: o.Expression|o.Statement|o.Type): string {
return IS_DART ? debugOutputAstAsDart(ast) : debugOutputAstAsTypeScript(ast);
}
@ -207,8 +212,8 @@ class StatementInterpreter implements o.StatementVisitor, o.ExpressionVisitor {
var args = this.visitAllExpressions(stmt.args, ctx);
var fnExpr = stmt.fn;
if (fnExpr instanceof o.ReadVarExpr && fnExpr.builtin === o.BuiltinVar.Super) {
ctx.superInstance = ctx.instanceFactory.createInstance(ctx.superClass, ctx.className, args,
ctx.props, ctx.getters, ctx.methods);
ctx.superInstance = ctx.instanceFactory.createInstance(
ctx.superClass, ctx.className, args, ctx.props, ctx.getters, ctx.methods);
ctx.parent.superInstance = ctx.superInstance;
return null;
} else {
@ -352,8 +357,9 @@ class StatementInterpreter implements o.StatementVisitor, o.ExpressionVisitor {
}
visitLiteralMapExpr(ast: o.LiteralMapExpr, ctx: _ExecutionContext): any {
var result = {};
ast.entries.forEach((entry) => (result as any /** TODO #9100 */)[<string>entry[0]] =
(<o.Expression>entry[1]).visitExpression(this, ctx));
ast.entries.forEach(
(entry) => (result as any /** TODO #9100 */)[<string>entry[0]] =
(<o.Expression>entry[1]).visitExpression(this, ctx));
return result;
}
@ -373,39 +379,60 @@ class StatementInterpreter implements o.StatementVisitor, o.ExpressionVisitor {
}
}
function _declareFn(varNames: string[], statements: o.Statement[], ctx: _ExecutionContext,
visitor: StatementInterpreter): Function {
function _declareFn(
varNames: string[], statements: o.Statement[], ctx: _ExecutionContext,
visitor: StatementInterpreter): Function {
switch (varNames.length) {
case 0:
return () => _executeFunctionStatements(varNames, [], statements, ctx, visitor);
case 1:
return (d0: any /** TODO #9100 */) => _executeFunctionStatements(varNames, [d0], statements, ctx, visitor);
return (d0: any /** TODO #9100 */) =>
_executeFunctionStatements(varNames, [d0], statements, ctx, visitor);
case 2:
return (d0: any /** TODO #9100 */, d1: any /** TODO #9100 */) => _executeFunctionStatements(varNames, [d0, d1], statements, ctx, visitor);
return (d0: any /** TODO #9100 */, d1: any /** TODO #9100 */) =>
_executeFunctionStatements(varNames, [d0, d1], statements, ctx, visitor);
case 3:
return (d0: any /** TODO #9100 */, d1: any /** TODO #9100 */, d2: any /** TODO #9100 */) =>
_executeFunctionStatements(varNames, [d0, d1, d2], statements, ctx, visitor);
case 4:
return (d0: any /** TODO #9100 */, d1: any /** TODO #9100 */, d2: any /** TODO #9100 */, d3: any /** TODO #9100 */) =>
return (d0: any /** TODO #9100 */, d1: any /** TODO #9100 */, d2: any /** TODO #9100 */,
d3: any /** TODO #9100 */) =>
_executeFunctionStatements(varNames, [d0, d1, d2, d3], statements, ctx, visitor);
case 5:
return (d0: any /** TODO #9100 */, d1: any /** TODO #9100 */, d2: any /** TODO #9100 */, d3: any /** TODO #9100 */, d4: any /** TODO #9100 */) => _executeFunctionStatements(varNames, [d0, d1, d2, d3, d4],
statements, ctx, visitor);
return (d0: any /** TODO #9100 */, d1: any /** TODO #9100 */, d2: any /** TODO #9100 */,
d3: any /** TODO #9100 */, d4: any /** TODO #9100 */) =>
_executeFunctionStatements(
varNames, [d0, d1, d2, d3, d4], statements, ctx, visitor);
case 6:
return (d0: any /** TODO #9100 */, d1: any /** TODO #9100 */, d2: any /** TODO #9100 */, d3: any /** TODO #9100 */, d4: any /** TODO #9100 */, d5: any /** TODO #9100 */) => _executeFunctionStatements(
varNames, [d0, d1, d2, d3, d4, d5], statements, ctx, visitor);
return (d0: any /** TODO #9100 */, d1: any /** TODO #9100 */, d2: any /** TODO #9100 */,
d3: any /** TODO #9100 */, d4: any /** TODO #9100 */, d5: any /** TODO #9100 */) =>
_executeFunctionStatements(
varNames, [d0, d1, d2, d3, d4, d5], statements, ctx, visitor);
case 7:
return (d0: any /** TODO #9100 */, d1: any /** TODO #9100 */, d2: any /** TODO #9100 */, d3: any /** TODO #9100 */, d4: any /** TODO #9100 */, d5: any /** TODO #9100 */, d6: any /** TODO #9100 */) => _executeFunctionStatements(
varNames, [d0, d1, d2, d3, d4, d5, d6], statements, ctx, visitor);
return (d0: any /** TODO #9100 */, d1: any /** TODO #9100 */, d2: any /** TODO #9100 */,
d3: any /** TODO #9100 */, d4: any /** TODO #9100 */, d5: any /** TODO #9100 */,
d6: any /** TODO #9100 */) =>
_executeFunctionStatements(
varNames, [d0, d1, d2, d3, d4, d5, d6], statements, ctx, visitor);
case 8:
return (d0: any /** TODO #9100 */, d1: any /** TODO #9100 */, d2: any /** TODO #9100 */, d3: any /** TODO #9100 */, d4: any /** TODO #9100 */, d5: any /** TODO #9100 */, d6: any /** TODO #9100 */, d7: any /** TODO #9100 */) => _executeFunctionStatements(
varNames, [d0, d1, d2, d3, d4, d5, d6, d7], statements, ctx, visitor);
return (d0: any /** TODO #9100 */, d1: any /** TODO #9100 */, d2: any /** TODO #9100 */,
d3: any /** TODO #9100 */, d4: any /** TODO #9100 */, d5: any /** TODO #9100 */,
d6: any /** TODO #9100 */, d7: any /** TODO #9100 */) =>
_executeFunctionStatements(
varNames, [d0, d1, d2, d3, d4, d5, d6, d7], statements, ctx, visitor);
case 9:
return (d0: any /** TODO #9100 */, d1: any /** TODO #9100 */, d2: any /** TODO #9100 */, d3: any /** TODO #9100 */, d4: any /** TODO #9100 */, d5: any /** TODO #9100 */, d6: any /** TODO #9100 */, d7: any /** TODO #9100 */, d8: any /** TODO #9100 */) => _executeFunctionStatements(
varNames, [d0, d1, d2, d3, d4, d5, d6, d7, d8], statements, ctx, visitor);
return (d0: any /** TODO #9100 */, d1: any /** TODO #9100 */, d2: any /** TODO #9100 */,
d3: any /** TODO #9100 */, d4: any /** TODO #9100 */, d5: any /** TODO #9100 */,
d6: any /** TODO #9100 */, d7: any /** TODO #9100 */, d8: any /** TODO #9100 */) =>
_executeFunctionStatements(
varNames, [d0, d1, d2, d3, d4, d5, d6, d7, d8], statements, ctx, visitor);
case 10:
return (d0: any /** TODO #9100 */, d1: any /** TODO #9100 */, d2: any /** TODO #9100 */, d3: any /** TODO #9100 */, d4: any /** TODO #9100 */, d5: any /** TODO #9100 */, d6: any /** TODO #9100 */, d7: any /** TODO #9100 */, d8: any /** TODO #9100 */, d9: any /** TODO #9100 */) => _executeFunctionStatements(
varNames, [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], statements, ctx, visitor);
return (d0: any /** TODO #9100 */, d1: any /** TODO #9100 */, d2: any /** TODO #9100 */,
d3: any /** TODO #9100 */, d4: any /** TODO #9100 */, d5: any /** TODO #9100 */,
d6: any /** TODO #9100 */, d7: any /** TODO #9100 */, d8: any /** TODO #9100 */,
d9: any /** TODO #9100 */) =>
_executeFunctionStatements(
varNames, [d0, d1, d2, d3, d4, d5, d6, d7, d8, d9], statements, ctx, visitor);
default:
throw new BaseException(
'Declaring functions with more than 10 arguments is not supported right now');

View File

@ -1,14 +1,11 @@
import {
isPresent,
evalExpression,
} from '../facade/lang';
import {isPresent, evalExpression,} from '../facade/lang';
import * as o from './output_ast';
import {EmitterVisitorContext} from './abstract_emitter';
import {AbstractJsEmitterVisitor} from './abstract_js_emitter';
import {sanitizeIdentifier} from '../util';
export function jitStatements(sourceUrl: string, statements: o.Statement[],
resultVar: string): any {
export function jitStatements(
sourceUrl: string, statements: o.Statement[], resultVar: string): any {
var converter = new JitEmitterVisitor();
var ctx = EmitterVisitorContext.createRoot([resultVar]);
converter.visitAllStatements(statements, ctx);

View File

@ -1,7 +1,9 @@
import {BaseException} from '../facade/exceptions';
import {isPresent, isBlank, RegExpWrapper, Math} from '../facade/lang';
import {Injectable} from '@angular/core';
import {BaseException} from '../facade/exceptions';
import {Math, RegExpWrapper, isBlank, isPresent} from '../facade/lang';
// asset:<package-name>/<realm>/<path-to-module>
var _ASSET_URL_RE = /asset:([^\/]+)\/([^\/]+)\/(.+)/g;

View File

@ -1,20 +1,15 @@
import * as o from './output_ast';
import {isPresent, isBlank, isArray} from '../facade/lang';
import {BaseException} from '../facade/exceptions';
import {CompileIdentifierMetadata} from '../compile_metadata';
import {
OutputEmitter,
EmitterVisitorContext,
AbstractEmitterVisitor,
CATCH_ERROR_VAR,
CATCH_STACK_VAR
} from './abstract_emitter';
import {BaseException} from '../facade/exceptions';
import {isArray, isBlank, isPresent} from '../facade/lang';
import {AbstractEmitterVisitor, CATCH_ERROR_VAR, CATCH_STACK_VAR, EmitterVisitorContext, OutputEmitter} from './abstract_emitter';
import * as o from './output_ast';
import {ImportGenerator} from './path_util';
var _debugModuleUrl = 'asset://debug/lib';
export function debugOutputAstAsTypeScript(ast: o.Statement | o.Expression | o.Type |
any[]): string {
export function debugOutputAstAsTypeScript(ast: o.Statement | o.Expression | o.Type | any[]):
string {
var converter = new _TsEmitterVisitor(_debugModuleUrl);
var ctx = EmitterVisitorContext.createRoot([]);
var asts: any[];
@ -197,10 +192,10 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor
ctx.decIndent();
ctx.println(`} catch (${CATCH_ERROR_VAR.name}) {`);
ctx.incIndent();
var catchStmts = [
<o.Statement>CATCH_STACK_VAR.set(CATCH_ERROR_VAR.prop('stack'))
.toDeclStmt(null, [o.StmtModifier.Final])
].concat(stmt.catchStmts);
var catchStmts =
[<o.Statement>CATCH_STACK_VAR.set(CATCH_ERROR_VAR.prop('stack')).toDeclStmt(null, [
o.StmtModifier.Final
])].concat(stmt.catchStmts);
this.visitAllStatements(catchStmts, ctx);
ctx.decIndent();
ctx.println(`}`);
@ -277,8 +272,8 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor
}, params, ctx, ',');
}
private _visitIdentifier(value: CompileIdentifierMetadata, typeParams: o.Type[],
ctx: EmitterVisitorContext): void {
private _visitIdentifier(
value: CompileIdentifierMetadata, typeParams: o.Type[], ctx: EmitterVisitorContext): void {
if (isBlank(value.name)) {
throw new BaseException(`Internal error: unknown identifier ${value}`);
}
@ -293,7 +288,8 @@ class _TsEmitterVisitor extends AbstractEmitterVisitor implements o.TypeVisitor
ctx.print(value.name);
if (isPresent(typeParams) && typeParams.length > 0) {
ctx.print(`<`);
this.visitAllObjects((type: any /** TODO #9100 */) => type.visitType(this, ctx), typeParams, ctx, ',');
this.visitAllObjects(
(type: any /** TODO #9100 */) => type.visitType(this, ctx), typeParams, ctx, ',');
ctx.print(`>`);
}
}

View File

@ -1,6 +1,7 @@
export class ParseLocation {
constructor(public file: ParseSourceFile, public offset: number, public line: number,
public col: number) {}
constructor(
public file: ParseSourceFile, public offset: number, public line: number,
public col: number) {}
toString(): string { return `${this.file.url}@${this.line}:${this.col}`; }
}
@ -23,8 +24,9 @@ export enum ParseErrorLevel {
}
export abstract class ParseError {
constructor(public span: ParseSourceSpan, public msg: string,
public level: ParseErrorLevel = ParseErrorLevel.FATAL) {}
constructor(
public span: ParseSourceSpan, public msg: string,
public level: ParseErrorLevel = ParseErrorLevel.FATAL) {}
toString(): string {
var source = this.span.start.file.content;
@ -39,7 +41,7 @@ export abstract class ParseError {
while (ctxLen < 100 && ctxStart > 0) {
ctxStart--;
ctxLen++;
if (source[ctxStart] == "\n") {
if (source[ctxStart] == '\n') {
if (++ctxLines == 3) {
break;
}
@ -51,7 +53,7 @@ export abstract class ParseError {
while (ctxLen < 100 && ctxEnd < source.length - 1) {
ctxEnd++;
ctxLen++;
if (source[ctxEnd] == "\n") {
if (source[ctxEnd] == '\n') {
if (++ctxLines == 3) {
break;
}
@ -59,7 +61,7 @@ export abstract class ParseError {
}
let context = source.substring(ctxStart, this.span.start.offset) + '[ERROR ->]' +
source.substring(this.span.start.offset, ctxEnd + 1);
source.substring(this.span.start.offset, ctxEnd + 1);
return `${this.msg} ("${context}"): ${this.span.start}`;
}

View File

@ -1,9 +1,8 @@
import {resolveForwardRef, Injectable, PipeMetadata} from '@angular/core';
import {Injectable, PipeMetadata, resolveForwardRef} from '@angular/core';
import {ReflectorReader, reflector} from '../core_private';
import {Type, isPresent, stringify} from '../src/facade/lang';
import {BaseException} from '../src/facade/exceptions';
import {Type, isPresent, stringify} from '../src/facade/lang';
function _isPipeMetadata(type: any): boolean {
return type instanceof PipeMetadata;

View File

@ -1,24 +1,10 @@
import {isPresent, isBlank, isArray, normalizeBlank} from '../src/facade/lang';
import {ListWrapper} from '../src/facade/collection';
import {
VariableAst,
AttrAst,
DirectiveAst,
ProviderAst,
ProviderAstType,
ReferenceAst
} from './template_ast';
import {
CompileTypeMetadata,
CompileTokenMap,
CompileQueryMetadata,
CompileTokenMetadata,
CompileProviderMetadata,
CompileDirectiveMetadata,
CompileDiDependencyMetadata
} from './compile_metadata';
import {isArray, isBlank, isPresent, normalizeBlank} from '../src/facade/lang';
import {CompileDiDependencyMetadata, CompileDirectiveMetadata, CompileProviderMetadata, CompileQueryMetadata, CompileTokenMap, CompileTokenMetadata, CompileTypeMetadata} from './compile_metadata';
import {Identifiers, identifierToken} from './identifiers';
import {ParseSourceSpan, ParseError} from './parse_util';
import {ParseError, ParseSourceSpan} from './parse_util';
import {AttrAst, DirectiveAst, ProviderAst, ProviderAstType, ReferenceAst, VariableAst} from './template_ast';
export class ProviderError extends ParseError {
constructor(message: string, span: ParseSourceSpan) { super(span, message); }
@ -38,12 +24,11 @@ export class ProviderViewContext {
constructor(public component: CompileDirectiveMetadata, public sourceSpan: ParseSourceSpan) {
this.viewQueries = _getViewQueries(component);
this.viewProviders = new CompileTokenMap<boolean>();
_normalizeProviders(component.viewProviders, sourceSpan, this.errors)
.forEach((provider) => {
if (isBlank(this.viewProviders.get(provider.token))) {
this.viewProviders.add(provider.token, true);
}
});
_normalizeProviders(component.viewProviders, sourceSpan, this.errors).forEach((provider) => {
if (isBlank(this.viewProviders.get(provider.token))) {
this.viewProviders.add(provider.token, true);
}
});
}
}
@ -56,9 +41,10 @@ export class ProviderElementContext {
private _attrs: {[key: string]: string};
private _hasViewContainer: boolean = false;
constructor(private _viewContext: ProviderViewContext, private _parent: ProviderElementContext,
private _isViewRoot: boolean, private _directiveAsts: DirectiveAst[],
attrs: AttrAst[], refs: ReferenceAst[], private _sourceSpan: ParseSourceSpan) {
constructor(
private _viewContext: ProviderViewContext, private _parent: ProviderElementContext,
private _isViewRoot: boolean, private _directiveAsts: DirectiveAst[], attrs: AttrAst[],
refs: ReferenceAst[], private _sourceSpan: ParseSourceSpan) {
this._attrs = {};
attrs.forEach((attrAst) => this._attrs[attrAst.name] = attrAst.value);
var directivesMeta = _directiveAsts.map(directiveAst => directiveAst.directive);
@ -97,9 +83,9 @@ export class ProviderElementContext {
var sortedProviderTypes =
this._transformedProviders.values().map(provider => provider.token.identifier);
var sortedDirectives = ListWrapper.clone(this._directiveAsts);
ListWrapper.sort(sortedDirectives,
(dir1, dir2) => sortedProviderTypes.indexOf(dir1.directive.type) -
sortedProviderTypes.indexOf(dir2.directive.type));
ListWrapper.sort(
sortedDirectives, (dir1, dir2) => sortedProviderTypes.indexOf(dir1.directive.type) -
sortedProviderTypes.indexOf(dir2.directive.type));
return sortedDirectives;
}
@ -137,8 +123,9 @@ export class ProviderElementContext {
}
private _getOrCreateLocalProvider(requestingProviderType: ProviderAstType,
token: CompileTokenMetadata, eager: boolean): ProviderAst {
private _getOrCreateLocalProvider(
requestingProviderType: ProviderAstType, token: CompileTokenMetadata,
eager: boolean): ProviderAst {
var resolvedProvider = this._allProviders.get(token);
if (isBlank(resolvedProvider) ||
((requestingProviderType === ProviderAstType.Directive ||
@ -194,9 +181,9 @@ export class ProviderElementContext {
return transformedProviderAst;
}
private _getLocalDependency(requestingProviderType: ProviderAstType,
dep: CompileDiDependencyMetadata,
eager: boolean = null): CompileDiDependencyMetadata {
private _getLocalDependency(
requestingProviderType: ProviderAstType, dep: CompileDiDependencyMetadata,
eager: boolean = null): CompileDiDependencyMetadata {
if (dep.isAttribute) {
var attrValue = this._attrs[dep.token.value];
return new CompileDiDependencyMetadata({isValue: true, value: normalizeBlank(attrValue)});
@ -231,8 +218,9 @@ export class ProviderElementContext {
return null;
}
private _getDependency(requestingProviderType: ProviderAstType, dep: CompileDiDependencyMetadata,
eager: boolean = null): CompileDiDependencyMetadata {
private _getDependency(
requestingProviderType: ProviderAstType, dep: CompileDiDependencyMetadata,
eager: boolean = null): CompileDiDependencyMetadata {
var currElement: ProviderElementContext = this;
var currEager: boolean = eager;
var result: CompileDiDependencyMetadata = null;
@ -261,8 +249,8 @@ export class ProviderElementContext {
result = dep;
} else {
result = dep.isOptional ?
result = new CompileDiDependencyMetadata({isValue: true, value: null}) :
null;
result = new CompileDiDependencyMetadata({isValue: true, value: null}) :
null;
}
}
}
@ -292,12 +280,13 @@ function _transformProvider(
function _transformProviderAst(
provider: ProviderAst,
{eager, providers}: {eager: boolean, providers: CompileProviderMetadata[]}): ProviderAst {
return new ProviderAst(provider.token, provider.multiProvider, provider.eager || eager, providers,
provider.providerType, provider.sourceSpan);
return new ProviderAst(
provider.token, provider.multiProvider, provider.eager || eager, providers,
provider.providerType, provider.sourceSpan);
}
function _normalizeProviders(
providers: Array<CompileProviderMetadata | CompileTypeMetadata | any[]>,
providers: Array<CompileProviderMetadata|CompileTypeMetadata|any[]>,
sourceSpan: ParseSourceSpan, targetErrors: ParseError[],
targetProviders: CompileProviderMetadata[] = null): CompileProviderMetadata[] {
if (isBlank(targetProviders)) {
@ -327,35 +316,37 @@ function _normalizeProviders(
}
function _resolveProvidersFromDirectives(directives: CompileDirectiveMetadata[],
sourceSpan: ParseSourceSpan,
targetErrors: ParseError[]): CompileTokenMap<ProviderAst> {
function _resolveProvidersFromDirectives(
directives: CompileDirectiveMetadata[], sourceSpan: ParseSourceSpan,
targetErrors: ParseError[]): CompileTokenMap<ProviderAst> {
var providersByToken = new CompileTokenMap<ProviderAst>();
directives.forEach((directive) => {
var dirProvider = new CompileProviderMetadata(
{token: new CompileTokenMetadata({identifier: directive.type}), useClass: directive.type});
_resolveProviders([dirProvider],
directive.isComponent ? ProviderAstType.Component : ProviderAstType.Directive,
true, sourceSpan, targetErrors, providersByToken);
_resolveProviders(
[dirProvider],
directive.isComponent ? ProviderAstType.Component : ProviderAstType.Directive, true,
sourceSpan, targetErrors, providersByToken);
});
// Note: directives need to be able to overwrite providers of a component!
var directivesWithComponentFirst =
directives.filter(dir => dir.isComponent).concat(directives.filter(dir => !dir.isComponent));
directivesWithComponentFirst.forEach((directive) => {
_resolveProviders(_normalizeProviders(directive.providers, sourceSpan, targetErrors),
ProviderAstType.PublicService, false, sourceSpan, targetErrors,
providersByToken);
_resolveProviders(_normalizeProviders(directive.viewProviders, sourceSpan, targetErrors),
ProviderAstType.PrivateService, false, sourceSpan, targetErrors,
providersByToken);
_resolveProviders(
_normalizeProviders(directive.providers, sourceSpan, targetErrors),
ProviderAstType.PublicService, false, sourceSpan, targetErrors, providersByToken);
_resolveProviders(
_normalizeProviders(directive.viewProviders, sourceSpan, targetErrors),
ProviderAstType.PrivateService, false, sourceSpan, targetErrors, providersByToken);
});
return providersByToken;
}
function _resolveProviders(providers: CompileProviderMetadata[], providerType: ProviderAstType,
eager: boolean, sourceSpan: ParseSourceSpan, targetErrors: ParseError[],
targetProvidersByToken: CompileTokenMap<ProviderAst>) {
function _resolveProviders(
providers: CompileProviderMetadata[], providerType: ProviderAstType, eager: boolean,
sourceSpan: ParseSourceSpan, targetErrors: ParseError[],
targetProvidersByToken: CompileTokenMap<ProviderAst>) {
providers.forEach((provider) => {
var resolvedProvider = targetProvidersByToken.get(provider.token);
if (isPresent(resolvedProvider) && resolvedProvider.multiProvider !== provider.multi) {
@ -364,8 +355,8 @@ function _resolveProviders(providers: CompileProviderMetadata[], providerType: P
sourceSpan));
}
if (isBlank(resolvedProvider)) {
resolvedProvider = new ProviderAst(provider.token, provider.multi, eager, [provider],
providerType, sourceSpan);
resolvedProvider = new ProviderAst(
provider.token, provider.multi, eager, [provider], providerType, sourceSpan);
targetProvidersByToken.add(provider.token, resolvedProvider);
} else {
if (!provider.multi) {
@ -377,8 +368,8 @@ function _resolveProviders(providers: CompileProviderMetadata[], providerType: P
}
function _getViewQueries(
component: CompileDirectiveMetadata): CompileTokenMap<CompileQueryMetadata[]> {
function _getViewQueries(component: CompileDirectiveMetadata):
CompileTokenMap<CompileQueryMetadata[]> {
var viewQueries = new CompileTokenMap<CompileQueryMetadata[]>();
if (isPresent(component.viewQueries)) {
component.viewQueries.forEach((query) => _addQueryToTokenMap(viewQueries, query));
@ -391,8 +382,8 @@ function _getViewQueries(
return viewQueries;
}
function _getContentQueries(
directives: CompileDirectiveMetadata[]): CompileTokenMap<CompileQueryMetadata[]> {
function _getContentQueries(directives: CompileDirectiveMetadata[]):
CompileTokenMap<CompileQueryMetadata[]> {
var contentQueries = new CompileTokenMap<CompileQueryMetadata[]>();
directives.forEach(directive => {
if (isPresent(directive.queries)) {
@ -407,8 +398,8 @@ function _getContentQueries(
return contentQueries;
}
function _addQueryToTokenMap(map: CompileTokenMap<CompileQueryMetadata[]>,
query: CompileQueryMetadata) {
function _addQueryToTokenMap(
map: CompileTokenMap<CompileQueryMetadata[]>, query: CompileQueryMetadata) {
query.selectors.forEach((token: CompileTokenMetadata) => {
var entry = map.get(token);
if (isBlank(entry)) {

View File

@ -1,25 +1,12 @@
import {Injectable, ComponentFactory, ComponentResolver} from '@angular/core';
import {ComponentFactory, ComponentResolver, Injectable} from '@angular/core';
import {
IS_DART,
Type,
isBlank,
isString
} from '../src/facade/lang';
import {BaseException} from '../src/facade/exceptions';
import {
ListWrapper,
} from '../src/facade/collection';
import {IS_DART, Type, isBlank, isString} from '../src/facade/lang';
import {ListWrapper,} from '../src/facade/collection';
import {PromiseWrapper} from '../src/facade/async';
import {
createHostComponentMeta,
CompileDirectiveMetadata,
CompilePipeMetadata,
CompileIdentifierMetadata
} from './compile_metadata';
import {
TemplateAst,
} from './template_ast';
import {createHostComponentMeta, CompileDirectiveMetadata, CompilePipeMetadata, CompileIdentifierMetadata} from './compile_metadata';
import {TemplateAst,} from './template_ast';
import {StyleCompiler, StylesCompileDependency, StylesCompileResult} from './style_compiler';
import {ViewCompiler} from './view_compiler/view_compiler';
import {TemplateParser} from './template_parser';
@ -44,15 +31,16 @@ export class RuntimeCompiler implements ComponentResolver {
private _compiledTemplateCache = new Map<any, CompiledTemplate>();
private _compiledTemplateDone = new Map<any, Promise<CompiledTemplate>>();
constructor(private _metadataResolver: CompileMetadataResolver,
private _templateNormalizer: DirectiveNormalizer,
private _templateParser: TemplateParser, private _styleCompiler: StyleCompiler,
private _viewCompiler: ViewCompiler, private _xhr: XHR,
private _genConfig: CompilerConfig) {}
constructor(
private _metadataResolver: CompileMetadataResolver,
private _templateNormalizer: DirectiveNormalizer, private _templateParser: TemplateParser,
private _styleCompiler: StyleCompiler, private _viewCompiler: ViewCompiler, private _xhr: XHR,
private _genConfig: CompilerConfig) {}
resolveComponent(component: Type|string): Promise<ComponentFactory<any>> {
if (isString(component)) {
return PromiseWrapper.reject(new BaseException(`Cannot resolve component using '${component}'.`), null);
return PromiseWrapper.reject(
new BaseException(`Cannot resolve component using '${component}'.`), null);
}
let componentType = <Type>component;
@ -69,8 +57,9 @@ export class RuntimeCompiler implements ComponentResolver {
this._loadAndCompileComponent(hostCacheKey, hostMeta, [compMeta], [], []);
}
return this._compiledTemplateDone.get(hostCacheKey)
.then((compiledTemplate: CompiledTemplate) => new ComponentFactory(
compMeta.selector, compiledTemplate.viewFactory, componentType));
.then(
(compiledTemplate: CompiledTemplate) => new ComponentFactory(
compMeta.selector, compiledTemplate.viewFactory, componentType));
}
clearCache() {
@ -81,29 +70,29 @@ export class RuntimeCompiler implements ComponentResolver {
}
private _loadAndCompileComponent(cacheKey: any, compMeta: CompileDirectiveMetadata,
viewDirectives: CompileDirectiveMetadata[],
pipes: CompilePipeMetadata[],
compilingComponentsPath: any[]): CompiledTemplate {
private _loadAndCompileComponent(
cacheKey: any, compMeta: CompileDirectiveMetadata, viewDirectives: CompileDirectiveMetadata[],
pipes: CompilePipeMetadata[], compilingComponentsPath: any[]): CompiledTemplate {
var compiledTemplate = this._compiledTemplateCache.get(cacheKey);
var done = this._compiledTemplateDone.get(cacheKey);
if (isBlank(compiledTemplate)) {
compiledTemplate = new CompiledTemplate();
this._compiledTemplateCache.set(cacheKey, compiledTemplate);
done =
PromiseWrapper.all(
[<any>this._compileComponentStyles(compMeta)].concat(viewDirectives.map(
dirMeta => this._templateNormalizer.normalizeDirective(dirMeta))))
PromiseWrapper
.all([<any>this._compileComponentStyles(compMeta)].concat(viewDirectives.map(
dirMeta => this._templateNormalizer.normalizeDirective(dirMeta))))
.then((stylesAndNormalizedViewDirMetas: any[]) => {
var normalizedViewDirMetas = stylesAndNormalizedViewDirMetas.slice(1);
var styles = stylesAndNormalizedViewDirMetas[0];
var parsedTemplate =
this._templateParser.parse(compMeta, compMeta.template.template,
normalizedViewDirMetas, pipes, compMeta.type.name);
var parsedTemplate = this._templateParser.parse(
compMeta, compMeta.template.template, normalizedViewDirMetas, pipes,
compMeta.type.name);
var childPromises: any[] /** TODO #9100 */ = [];
compiledTemplate.init(this._compileComponent(compMeta, parsedTemplate, styles,
pipes, compilingComponentsPath, childPromises));
compiledTemplate.init(this._compileComponent(
compMeta, parsedTemplate, styles, pipes, compilingComponentsPath,
childPromises));
return PromiseWrapper.all(childPromises).then((_) => { return compiledTemplate; });
});
this._compiledTemplateDone.set(cacheKey, done);
@ -111,11 +100,10 @@ export class RuntimeCompiler implements ComponentResolver {
return compiledTemplate;
}
private _compileComponent(compMeta: CompileDirectiveMetadata, parsedTemplate: TemplateAst[],
styles: string[],
pipes: CompilePipeMetadata[],
compilingComponentsPath: any[],
childPromises: Promise<any>[]): Function {
private _compileComponent(
compMeta: CompileDirectiveMetadata, parsedTemplate: TemplateAst[], styles: string[],
pipes: CompilePipeMetadata[], compilingComponentsPath: any[],
childPromises: Promise<any>[]): Function {
var compileResult = this._viewCompiler.compileComponent(
compMeta, parsedTemplate,
new ir.ExternalExpr(new CompileIdentifierMetadata({runtime: styles})), pipes);
@ -130,9 +118,9 @@ export class RuntimeCompiler implements ComponentResolver {
var childIsRecursive = ListWrapper.contains(childCompilingComponentsPath, childCacheKey);
childCompilingComponentsPath.push(childCacheKey);
var childComp =
this._loadAndCompileComponent(dep.comp.type.runtime, dep.comp, childViewDirectives,
childViewPipes, childCompilingComponentsPath);
var childComp = this._loadAndCompileComponent(
dep.comp.type.runtime, dep.comp, childViewDirectives, childViewPipes,
childCompilingComponentsPath);
dep.factoryPlaceholder.runtime = childComp.proxyViewFactory;
dep.factoryPlaceholder.name = `viewFactory_${dep.comp.type.name}`;
if (!childIsRecursive) {
@ -142,11 +130,13 @@ export class RuntimeCompiler implements ComponentResolver {
});
var factory: any /** TODO #9100 */;
if (IS_DART || !this._genConfig.useJit) {
factory = interpretStatements(compileResult.statements, compileResult.viewFactoryVar,
new InterpretiveAppViewInstanceFactory());
factory = interpretStatements(
compileResult.statements, compileResult.viewFactoryVar,
new InterpretiveAppViewInstanceFactory());
} else {
factory = jitStatements(`${compMeta.type.name}.template.js`, compileResult.statements,
compileResult.viewFactoryVar);
factory = jitStatements(
`${compMeta.type.name}.template.js`, compileResult.statements,
compileResult.viewFactoryVar);
}
return factory;
}
@ -156,8 +146,8 @@ export class RuntimeCompiler implements ComponentResolver {
return this._resolveStylesCompileResult(compMeta.type.name, compileResult);
}
private _resolveStylesCompileResult(sourceUrl: string,
result: StylesCompileResult): Promise<string[]> {
private _resolveStylesCompileResult(sourceUrl: string, result: StylesCompileResult):
Promise<string[]> {
var promises = result.dependencies.map((dep) => this._loadStylesheetDep(dep));
return PromiseWrapper.all(promises)
.then((cssTexts) => {
@ -179,8 +169,8 @@ export class RuntimeCompiler implements ComponentResolver {
dep.valuePlaceholder.name = `importedStyles${i}`;
}
if (IS_DART || !this._genConfig.useJit) {
return interpretStatements(result.statements, result.stylesVar,
new InterpretiveAppViewInstanceFactory());
return interpretStatements(
result.statements, result.stylesVar, new InterpretiveAppViewInstanceFactory());
} else {
return jitStatements(`${sourceUrl}.css.js`, result.statements, result.stylesVar);
}
@ -202,8 +192,9 @@ class CompiledTemplate {
viewFactory: Function = null;
proxyViewFactory: Function;
constructor() {
this.proxyViewFactory = (viewUtils: any /** TODO #9100 */, childInjector: any /** TODO #9100 */, contextEl: any /** TODO #9100 */) =>
this.viewFactory(viewUtils, childInjector, contextEl);
this.proxyViewFactory =
(viewUtils: any /** TODO #9100 */, childInjector: any /** TODO #9100 */,
contextEl: any /** TODO #9100 */) => this.viewFactory(viewUtils, childInjector, contextEl);
}
init(viewFactory: Function) { this.viewFactory = viewFactory; }

View File

@ -1,9 +1,11 @@
import {Injectable} from '@angular/core';
import {SecurityContext} from '../../core_private';
import {isPresent} from '../facade/lang';
import {StringMapWrapper} from '../facade/collection';
import {ElementSchemaRegistry} from './element_schema_registry';
import {isPresent} from '../facade/lang';
import {SECURITY_SCHEMA} from './dom_security_schema';
import {ElementSchemaRegistry} from './element_schema_registry';
const EVENT = 'event';
const BOOLEAN = 'boolean';
@ -238,7 +240,8 @@ export class DomElementSchemaRegistry extends ElementSchemaRegistry {
typeName.split(',').forEach(tag => this.schema[tag] = type);
var superType = this.schema[typeParts[1]];
if (isPresent(superType)) {
StringMapWrapper.forEach(superType, (v: any /** TODO #9100 */, k: any /** TODO #9100 */) => type[k] = v);
StringMapWrapper.forEach(
superType, (v: any /** TODO #9100 */, k: any /** TODO #9100 */) => type[k] = v);
}
properties.forEach((property: string) => {
if (property == '') {

View File

@ -28,25 +28,10 @@ registerContext(SecurityContext.HTML, [
registerContext(SecurityContext.STYLE, ['*|style']);
// NB: no SCRIPT contexts here, they are never allowed due to the parser stripping them.
registerContext(SecurityContext.URL, [
'*|formAction',
'area|href',
'area|ping',
'audio|src',
'a|href',
'a|ping',
'blockquote|cite',
'body|background',
'del|cite',
'form|action',
'img|src',
'img|srcset',
'input|src',
'ins|cite',
'q|cite',
'source|src',
'source|srcset',
'video|poster',
'video|src',
'*|formAction', 'area|href', 'area|ping', 'audio|src', 'a|href',
'a|ping', 'blockquote|cite', 'body|background', 'del|cite', 'form|action',
'img|src', 'img|srcset', 'input|src', 'ins|cite', 'q|cite',
'source|src', 'source|srcset', 'video|poster', 'video|src',
]);
registerContext(SecurityContext.RESOURCE_URL, [
'applet|code',

View File

@ -1,12 +1,6 @@
import {Map, ListWrapper} from '../src/facade/collection';
import {
isPresent,
isBlank,
RegExpWrapper,
RegExpMatcherWrapper,
StringWrapper
} from '../src/facade/lang';
import {ListWrapper, Map} from '../src/facade/collection';
import {BaseException} from '../src/facade/exceptions';
import {RegExpMatcherWrapper, RegExpWrapper, StringWrapper, isBlank, isPresent} from '../src/facade/lang';
const _EMPTY_ATTR_VALUE = /*@ts2dart_const*/ '';
@ -36,7 +30,7 @@ export class CssSelector {
var _addResult = (res: CssSelector[], cssSel: any /** TODO #9100 */) => {
if (cssSel.notSelectors.length > 0 && isBlank(cssSel.element) &&
ListWrapper.isEmpty(cssSel.classNames) && ListWrapper.isEmpty(cssSel.attrs)) {
cssSel.element = "*";
cssSel.element = '*';
}
res.push(cssSel);
};
@ -81,7 +75,7 @@ export class CssSelector {
isElementSelector(): boolean {
return isPresent(this.element) && ListWrapper.isEmpty(this.classNames) &&
ListWrapper.isEmpty(this.attrs) && this.notSelectors.length === 0;
ListWrapper.isEmpty(this.attrs) && this.notSelectors.length === 0;
}
setElement(element: string = null) { this.element = element; }
@ -174,8 +168,8 @@ export class SelectorMatcher {
* @param cssSelector A css selector
* @param callbackCtxt An opaque object that will be given to the callback of the `match` function
*/
private _addSelectable(cssSelector: CssSelector, callbackCtxt: any,
listContext: SelectorListContext) {
private _addSelectable(
cssSelector: CssSelector, callbackCtxt: any, listContext: SelectorListContext) {
var matcher: SelectorMatcher = this;
var element = cssSelector.element;
var classNames = cssSelector.classNames;
@ -229,8 +223,8 @@ export class SelectorMatcher {
}
}
private _addTerminal(map: Map<string, SelectorContext[]>, name: string,
selectable: SelectorContext) {
private _addTerminal(
map: Map<string, SelectorContext[]>, name: string, selectable: SelectorContext) {
var terminalList = map.get(name);
if (isBlank(terminalList)) {
terminalList = [];
@ -267,7 +261,7 @@ export class SelectorMatcher {
result = this._matchTerminal(this._elementMap, element, cssSelector, matchedCallback) || result;
result = this._matchPartial(this._elementPartialMap, element, cssSelector, matchedCallback) ||
result;
result;
if (isPresent(classNames)) {
for (var index = 0; index < classNames.length; index++) {
@ -287,18 +281,18 @@ export class SelectorMatcher {
var terminalValuesMap = this._attrValueMap.get(attrName);
if (!StringWrapper.equals(attrValue, _EMPTY_ATTR_VALUE)) {
result = this._matchTerminal(terminalValuesMap, _EMPTY_ATTR_VALUE, cssSelector,
matchedCallback) ||
result;
result = this._matchTerminal(
terminalValuesMap, _EMPTY_ATTR_VALUE, cssSelector, matchedCallback) ||
result;
}
result = this._matchTerminal(terminalValuesMap, attrValue, cssSelector, matchedCallback) ||
result;
result;
var partialValuesMap = this._attrValuePartialMap.get(attrName);
if (!StringWrapper.equals(attrValue, _EMPTY_ATTR_VALUE)) {
result = this._matchPartial(partialValuesMap, _EMPTY_ATTR_VALUE, cssSelector,
matchedCallback) ||
result;
result = this._matchPartial(
partialValuesMap, _EMPTY_ATTR_VALUE, cssSelector, matchedCallback) ||
result;
}
result =
this._matchPartial(partialValuesMap, attrValue, cssSelector, matchedCallback) || result;
@ -308,14 +302,15 @@ export class SelectorMatcher {
}
/** @internal */
_matchTerminal(map: Map<string, SelectorContext[]>, name: any /** TODO #9100 */, cssSelector: CssSelector,
matchedCallback: (c: CssSelector, a: any) => void): boolean {
_matchTerminal(
map: Map<string, SelectorContext[]>, name: any /** TODO #9100 */, cssSelector: CssSelector,
matchedCallback: (c: CssSelector, a: any) => void): boolean {
if (isBlank(map) || isBlank(name)) {
return false;
}
var selectables = map.get(name);
var starSelectables = map.get("*");
var starSelectables = map.get('*');
if (isPresent(starSelectables)) {
selectables = selectables.concat(starSelectables);
}
@ -332,8 +327,9 @@ export class SelectorMatcher {
}
/** @internal */
_matchPartial(map: Map<string, SelectorMatcher>, name: any /** TODO #9100 */, cssSelector: CssSelector,
matchedCallback: any /** TODO #9100 */ /*: (c: CssSelector, a: any) => void*/): boolean {
_matchPartial(
map: Map<string, SelectorMatcher>, name: any /** TODO #9100 */, cssSelector: CssSelector,
matchedCallback: any /** TODO #9100 */ /*: (c: CssSelector, a: any) => void*/): boolean {
if (isBlank(map) || isBlank(name)) {
return false;
}
@ -359,8 +355,9 @@ export class SelectorListContext {
export class SelectorContext {
notSelectors: CssSelector[];
constructor(public selector: CssSelector, public cbContext: any,
public listContext: SelectorListContext) {
constructor(
public selector: CssSelector, public cbContext: any,
public listContext: SelectorListContext) {
this.notSelectors = selector.notSelectors;
}

View File

@ -1,12 +1,5 @@
import {ListWrapper} from '../src/facade/collection';
import {
StringWrapper,
RegExp,
RegExpWrapper,
RegExpMatcherWrapper,
isPresent,
isBlank
} from '../src/facade/lang';
import {RegExp, RegExpMatcherWrapper, RegExpWrapper, StringWrapper, isBlank, isPresent} from '../src/facade/lang';
/**
* This file is a port of shadowCSS from webcomponents.js to TypeScript.
@ -174,8 +167,9 @@ export class ShadowCss {
**/
private _insertPolyfillDirectivesInCssText(cssText: string): string {
// Difference with webcomponents.js: does not handle comments
return StringWrapper.replaceAllMapped(cssText, _cssContentNextSelectorRe,
function(m: any /** TODO #9100 */) { return m[1] + '{'; });
return StringWrapper.replaceAllMapped(
cssText, _cssContentNextSelectorRe,
function(m: any /** TODO #9100 */) { return m[1] + '{'; });
}
/*
@ -195,12 +189,13 @@ export class ShadowCss {
**/
private _insertPolyfillRulesInCssText(cssText: string): string {
// Difference with webcomponents.js: does not handle comments
return StringWrapper.replaceAllMapped(cssText, _cssContentRuleRe, function(m: any /** TODO #9100 */) {
var rule = m[0];
rule = StringWrapper.replace(rule, m[1], '');
rule = StringWrapper.replace(rule, m[2], '');
return m[3] + rule;
});
return StringWrapper.replaceAllMapped(
cssText, _cssContentRuleRe, function(m: any /** TODO #9100 */) {
var rule = m[0];
rule = StringWrapper.replace(rule, m[1], '');
rule = StringWrapper.replace(rule, m[2], '');
return m[3] + rule;
});
}
/* Ensure styles are scoped. Pseudo-scoping takes a rule like:
@ -279,8 +274,8 @@ export class ShadowCss {
* scopeName.foo .bar { ... }
*/
private _convertColonHostContext(cssText: string): string {
return this._convertColonRule(cssText, _cssColonHostContextRe,
this._colonHostContextPartReplacer);
return this._convertColonRule(
cssText, _cssColonHostContextRe, this._colonHostContextPartReplacer);
}
private _convertColonRule(cssText: string, regExp: RegExp, partReplacer: Function): string {
@ -339,8 +334,8 @@ export class ShadowCss {
});
}
private _scopeSelector(selector: string, scopeSelector: string, hostSelector: string,
strict: boolean): string {
private _scopeSelector(
selector: string, scopeSelector: string, hostSelector: string, strict: boolean): string {
var r: any[] /** TODO #9100 */ = [], parts = selector.split(',');
for (var i = 0; i < parts.length; i++) {
var p = parts[i].trim();
@ -348,8 +343,8 @@ export class ShadowCss {
var shallowPart = deepParts[0];
if (this._selectorNeedsScoping(shallowPart, scopeSelector)) {
deepParts[0] = strict && !StringWrapper.contains(shallowPart, _polyfillHostNoCombinator) ?
this._applyStrictSelectorScope(shallowPart, scopeSelector) :
this._applySelectorScope(shallowPart, scopeSelector, hostSelector);
this._applyStrictSelectorScope(shallowPart, scopeSelector) :
this._applySelectorScope(shallowPart, scopeSelector, hostSelector);
}
// replace /deep/ with a space for child selectors
r.push(deepParts.join(' '));
@ -370,15 +365,15 @@ export class ShadowCss {
return RegExpWrapper.create('^(' + scopeSelector + ')' + _selectorReSuffix, 'm');
}
private _applySelectorScope(selector: string, scopeSelector: string,
hostSelector: string): string {
private _applySelectorScope(selector: string, scopeSelector: string, hostSelector: string):
string {
// Difference from webcomponentsjs: scopeSelector could not be an array
return this._applySimpleSelectorScope(selector, scopeSelector, hostSelector);
}
// scope via name and [is=name]
private _applySimpleSelectorScope(selector: string, scopeSelector: string,
hostSelector: string): string {
private _applySimpleSelectorScope(selector: string, scopeSelector: string, hostSelector: string):
string {
if (isPresent(RegExpWrapper.firstMatch(_polyfillHostRe, selector))) {
var replaceBy = this.strictStyling ? `[${hostSelector}]` : scopeSelector;
selector = StringWrapper.replace(selector, _polyfillHostNoCombinator, replaceBy);
@ -392,24 +387,26 @@ export class ShadowCss {
// e.g. .foo.bar > .zot becomes .foo[name].bar[name] > .zot[name] /** @internal */
private _applyStrictSelectorScope(selector: string, scopeSelector: string): string {
var isRe = /\[is=([^\]]*)\]/g;
scopeSelector = StringWrapper.replaceAllMapped(scopeSelector, isRe, (m: any /** TODO #9100 */) => m[1]);
scopeSelector =
StringWrapper.replaceAllMapped(scopeSelector, isRe, (m: any /** TODO #9100 */) => m[1]);
var splits = [' ', '>', '+', '~'], scoped = selector, attrName = '[' + scopeSelector + ']';
for (var i = 0; i < splits.length; i++) {
var sep = splits[i];
var parts = scoped.split(sep);
scoped = parts.map(p => {
// remove :host since it should be unnecessary
var t = StringWrapper.replaceAll(p.trim(), _polyfillHostRe, '');
if (t.length > 0 && !ListWrapper.contains(splits, t) &&
!StringWrapper.contains(t, attrName)) {
var re = /([^:]*)(:*)(.*)/g;
var m = RegExpWrapper.firstMatch(re, t);
if (isPresent(m)) {
p = m[1] + attrName + m[2] + m[3];
}
}
return p;
})
scoped = parts
.map(p => {
// remove :host since it should be unnecessary
var t = StringWrapper.replaceAll(p.trim(), _polyfillHostRe, '');
if (t.length > 0 && !ListWrapper.contains(splits, t) &&
!StringWrapper.contains(t, attrName)) {
var re = /([^:]*)(:*)(.*)/g;
var m = RegExpWrapper.firstMatch(re, t);
if (isPresent(m)) {
p = m[1] + attrName + m[2] + m[3];
}
}
return p;
})
.join(sep);
}
return scoped;
@ -430,14 +427,13 @@ var _polyfillHost = '-shadowcsshost';
// note: :host-context pre-processed to -shadowcsshostcontext.
var _polyfillHostContext = '-shadowcsscontext';
var _parenSuffix = ')(?:\\((' +
'(?:\\([^)(]*\\)|[^)(]*)+?' +
')\\))?([^,{]*)';
'(?:\\([^)(]*\\)|[^)(]*)+?' +
')\\))?([^,{]*)';
var _cssColonHostRe = RegExpWrapper.create('(' + _polyfillHost + _parenSuffix, 'im');
var _cssColonHostContextRe = RegExpWrapper.create('(' + _polyfillHostContext + _parenSuffix, 'im');
var _polyfillHostNoCombinator = _polyfillHost + '-no-combinator';
var _shadowDOMSelectorsRe = [
/::shadow/g,
/::content/g,
/::shadow/g, /::content/g,
// Deprecated selectors
// TODO(vicb): see https://github.com/angular/clang-format/issues/16
// clang-format off

View File

@ -1,23 +1,27 @@
import {ViewEncapsulation, Injectable} from '@angular/core';
import {CompileIdentifierMetadata, CompileDirectiveMetadata} from './compile_metadata';
import {Injectable, ViewEncapsulation} from '@angular/core';
import {isPresent} from '../src/facade/lang';
import {CompileDirectiveMetadata, CompileIdentifierMetadata} from './compile_metadata';
import * as o from './output/output_ast';
import {ShadowCss} from './shadow_css';
import {UrlResolver} from './url_resolver';
import {extractStyleUrls} from './style_url_resolver';
import {isPresent} from '../src/facade/lang';
import {UrlResolver} from './url_resolver';
const COMPONENT_VARIABLE = '%COMP%';
const HOST_ATTR = /*@ts2dart_const*/ `_nghost-${COMPONENT_VARIABLE}`;
const CONTENT_ATTR = /*@ts2dart_const*/ `_ngcontent-${COMPONENT_VARIABLE}`;
export class StylesCompileDependency {
constructor(public moduleUrl: string, public isShimmed: boolean,
public valuePlaceholder: CompileIdentifierMetadata) {}
constructor(
public moduleUrl: string, public isShimmed: boolean,
public valuePlaceholder: CompileIdentifierMetadata) {}
}
export class StylesCompileResult {
constructor(public statements: o.Statement[], public stylesVar: string,
public dependencies: StylesCompileDependency[]) {}
constructor(
public statements: o.Statement[], public stylesVar: string,
public dependencies: StylesCompileDependency[]) {}
}
@Injectable()
@ -28,19 +32,20 @@ export class StyleCompiler {
compileComponent(comp: CompileDirectiveMetadata): StylesCompileResult {
var shim = comp.template.encapsulation === ViewEncapsulation.Emulated;
return this._compileStyles(getStylesVarName(comp), comp.template.styles,
comp.template.styleUrls, shim);
return this._compileStyles(
getStylesVarName(comp), comp.template.styles, comp.template.styleUrls, shim);
}
compileStylesheet(stylesheetUrl: string, cssText: string,
isShimmed: boolean): StylesCompileResult {
compileStylesheet(stylesheetUrl: string, cssText: string, isShimmed: boolean):
StylesCompileResult {
var styleWithImports = extractStyleUrls(this._urlResolver, stylesheetUrl, cssText);
return this._compileStyles(getStylesVarName(null), [styleWithImports.style],
styleWithImports.styleUrls, isShimmed);
return this._compileStyles(
getStylesVarName(null), [styleWithImports.style], styleWithImports.styleUrls, isShimmed);
}
private _compileStyles(stylesVar: string, plainStyles: string[], absUrls: string[],
shim: boolean): StylesCompileResult {
private _compileStyles(
stylesVar: string, plainStyles: string[], absUrls: string[],
shim: boolean): StylesCompileResult {
var styleExpressions =
plainStyles.map(plainStyle => o.literal(this._shimIfNeeded(plainStyle, shim)));
var dependencies: any[] /** TODO #9100 */ = [];
@ -52,8 +57,8 @@ export class StyleCompiler {
// styles variable contains plain strings and arrays of other styles arrays (recursive),
// so we set its type to dynamic.
var stmt = o.variable(stylesVar)
.set(o.literalArr(styleExpressions,
new o.ArrayType(o.DYNAMIC_TYPE, [o.TypeModifier.Const])))
.set(o.literalArr(
styleExpressions, new o.ArrayType(o.DYNAMIC_TYPE, [o.TypeModifier.Const])))
.toDeclStmt(null, [o.StmtModifier.Final]);
return new StylesCompileResult([stmt], stylesVar, dependencies);
}

View File

@ -1,7 +1,8 @@
// Some of the code comes from WebComponents.JS
// https://github.com/webcomponents/webcomponentsjs/blob/master/src/HTMLImports/path.js
import {RegExpWrapper, StringWrapper, isPresent, isBlank} from '../src/facade/lang';
import {RegExpWrapper, StringWrapper, isBlank, isPresent} from '../src/facade/lang';
import {UrlResolver} from './url_resolver';
export class StyleWithImports {
@ -18,18 +19,19 @@ export function isStyleUrlResolvable(url: string): boolean {
* Rewrites stylesheets by resolving and removing the @import urls that
* are either relative or don't have a `package:` scheme
*/
export function extractStyleUrls(resolver: UrlResolver, baseUrl: string,
cssText: string): StyleWithImports {
export function extractStyleUrls(
resolver: UrlResolver, baseUrl: string, cssText: string): StyleWithImports {
var foundUrls: any[] /** TODO #9100 */ = [];
var modifiedCssText = StringWrapper.replaceAllMapped(cssText, _cssImportRe, (m: any /** TODO #9100 */) => {
var url = isPresent(m[1]) ? m[1] : m[2];
if (!isStyleUrlResolvable(url)) {
// Do not attempt to resolve non-package absolute URLs with URI scheme
return m[0];
}
foundUrls.push(resolver.resolve(baseUrl, url));
return '';
});
var modifiedCssText =
StringWrapper.replaceAllMapped(cssText, _cssImportRe, (m: any /** TODO #9100 */) => {
var url = isPresent(m[1]) ? m[1] : m[2];
if (!isStyleUrlResolvable(url)) {
// Do not attempt to resolve non-package absolute URLs with URI scheme
return m[0];
}
foundUrls.push(resolver.resolve(baseUrl, url));
return '';
});
return new StyleWithImports(modifiedCssText, foundUrls);
}

View File

@ -1,10 +1,8 @@
import {AST} from './expression_parser/ast';
import {isPresent} from '../src/facade/lang';
import {
CompileDirectiveMetadata,
CompileTokenMetadata,
CompileProviderMetadata,
} from './compile_metadata';
import {AST} from './expression_parser/ast';
import {CompileDirectiveMetadata, CompileTokenMetadata, CompileProviderMetadata,} from './compile_metadata';
import {ParseSourceSpan} from './parse_util';
import {SecurityContext} from '../core_private';
@ -27,8 +25,8 @@ export interface TemplateAst {
* A segment of text within the template.
*/
export class TextAst implements TemplateAst {
constructor(public value: string, public ngContentIndex: number,
public sourceSpan: ParseSourceSpan) {}
constructor(
public value: string, public ngContentIndex: number, public sourceSpan: ParseSourceSpan) {}
visit(visitor: TemplateAstVisitor, context: any): any { return visitor.visitText(this, context); }
}
@ -36,8 +34,8 @@ export class TextAst implements TemplateAst {
* A bound expression within the text of a template.
*/
export class BoundTextAst implements TemplateAst {
constructor(public value: AST, public ngContentIndex: number,
public sourceSpan: ParseSourceSpan) {}
constructor(
public value: AST, public ngContentIndex: number, public sourceSpan: ParseSourceSpan) {}
visit(visitor: TemplateAstVisitor, context: any): any {
return visitor.visitBoundText(this, context);
}
@ -55,9 +53,10 @@ export class AttrAst implements TemplateAst {
* A binding for an element property (e.g. `[property]="expression"`).
*/
export class BoundElementPropertyAst implements TemplateAst {
constructor(public name: string, public type: PropertyBindingType,
public securityContext: SecurityContext, public value: AST, public unit: string,
public sourceSpan: ParseSourceSpan) {}
constructor(
public name: string, public type: PropertyBindingType,
public securityContext: SecurityContext, public value: AST, public unit: string,
public sourceSpan: ParseSourceSpan) {}
visit(visitor: TemplateAstVisitor, context: any): any {
return visitor.visitElementProperty(this, context);
}
@ -67,8 +66,9 @@ export class BoundElementPropertyAst implements TemplateAst {
* A binding for an element event (e.g. `(event)="handler()"`).
*/
export class BoundEventAst implements TemplateAst {
constructor(public name: string, public target: string, public handler: AST,
public sourceSpan: ParseSourceSpan) {}
constructor(
public name: string, public target: string, public handler: AST,
public sourceSpan: ParseSourceSpan) {}
visit(visitor: TemplateAstVisitor, context: any): any {
return visitor.visitEvent(this, context);
}
@ -85,8 +85,9 @@ export class BoundEventAst implements TemplateAst {
* A reference declaration on an element (e.g. `let someName="expression"`).
*/
export class ReferenceAst implements TemplateAst {
constructor(public name: string, public value: CompileTokenMetadata,
public sourceSpan: ParseSourceSpan) {}
constructor(
public name: string, public value: CompileTokenMetadata, public sourceSpan: ParseSourceSpan) {
}
visit(visitor: TemplateAstVisitor, context: any): any {
return visitor.visitReference(this, context);
}
@ -106,12 +107,12 @@ export class VariableAst implements TemplateAst {
* An element declaration in a template.
*/
export class ElementAst implements TemplateAst {
constructor(public name: string, public attrs: AttrAst[],
public inputs: BoundElementPropertyAst[], public outputs: BoundEventAst[],
public references: ReferenceAst[], public directives: DirectiveAst[],
public providers: ProviderAst[], public hasViewContainer: boolean,
public children: TemplateAst[], public ngContentIndex: number,
public sourceSpan: ParseSourceSpan) {}
constructor(
public name: string, public attrs: AttrAst[], public inputs: BoundElementPropertyAst[],
public outputs: BoundEventAst[], public references: ReferenceAst[],
public directives: DirectiveAst[], public providers: ProviderAst[],
public hasViewContainer: boolean, public children: TemplateAst[],
public ngContentIndex: number, public sourceSpan: ParseSourceSpan) {}
visit(visitor: TemplateAstVisitor, context: any): any {
return visitor.visitElement(this, context);
@ -122,11 +123,12 @@ export class ElementAst implements TemplateAst {
* A `<template>` element included in an Angular template.
*/
export class EmbeddedTemplateAst implements TemplateAst {
constructor(public attrs: AttrAst[], public outputs: BoundEventAst[],
public references: ReferenceAst[], public variables: VariableAst[],
public directives: DirectiveAst[], public providers: ProviderAst[],
public hasViewContainer: boolean, public children: TemplateAst[],
public ngContentIndex: number, public sourceSpan: ParseSourceSpan) {}
constructor(
public attrs: AttrAst[], public outputs: BoundEventAst[], public references: ReferenceAst[],
public variables: VariableAst[], public directives: DirectiveAst[],
public providers: ProviderAst[], public hasViewContainer: boolean,
public children: TemplateAst[], public ngContentIndex: number,
public sourceSpan: ParseSourceSpan) {}
visit(visitor: TemplateAstVisitor, context: any): any {
return visitor.visitEmbeddedTemplate(this, context);
@ -137,8 +139,9 @@ export class EmbeddedTemplateAst implements TemplateAst {
* A directive property with a bound value (e.g. `*ngIf="condition").
*/
export class BoundDirectivePropertyAst implements TemplateAst {
constructor(public directiveName: string, public templateName: string, public value: AST,
public sourceSpan: ParseSourceSpan) {}
constructor(
public directiveName: string, public templateName: string, public value: AST,
public sourceSpan: ParseSourceSpan) {}
visit(visitor: TemplateAstVisitor, context: any): any {
return visitor.visitDirectiveProperty(this, context);
}
@ -148,10 +151,10 @@ export class BoundDirectivePropertyAst implements TemplateAst {
* A directive declared on an element.
*/
export class DirectiveAst implements TemplateAst {
constructor(public directive: CompileDirectiveMetadata,
public inputs: BoundDirectivePropertyAst[],
public hostProperties: BoundElementPropertyAst[], public hostEvents: BoundEventAst[],
public sourceSpan: ParseSourceSpan) {}
constructor(
public directive: CompileDirectiveMetadata, public inputs: BoundDirectivePropertyAst[],
public hostProperties: BoundElementPropertyAst[], public hostEvents: BoundEventAst[],
public sourceSpan: ParseSourceSpan) {}
visit(visitor: TemplateAstVisitor, context: any): any {
return visitor.visitDirective(this, context);
}
@ -161,9 +164,10 @@ export class DirectiveAst implements TemplateAst {
* A provider declared on an element
*/
export class ProviderAst implements TemplateAst {
constructor(public token: CompileTokenMetadata, public multiProvider: boolean,
public eager: boolean, public providers: CompileProviderMetadata[],
public providerType: ProviderAstType, public sourceSpan: ParseSourceSpan) {}
constructor(
public token: CompileTokenMetadata, public multiProvider: boolean, public eager: boolean,
public providers: CompileProviderMetadata[], public providerType: ProviderAstType,
public sourceSpan: ParseSourceSpan) {}
visit(visitor: TemplateAstVisitor, context: any): any {
// No visit method in the visitor for now...
@ -183,8 +187,8 @@ export enum ProviderAstType {
* Position where content is to be projected (instance of `<ng-content>` in a template).
*/
export class NgContentAst implements TemplateAst {
constructor(public index: number, public ngContentIndex: number,
public sourceSpan: ParseSourceSpan) {}
constructor(
public index: number, public ngContentIndex: number, public sourceSpan: ParseSourceSpan) {}
visit(visitor: TemplateAstVisitor, context: any): any {
return visitor.visitNgContent(this, context);
}
@ -242,8 +246,8 @@ export interface TemplateAstVisitor {
/**
* Visit every node in a list of {@link TemplateAst}s with the given {@link TemplateAstVisitor}.
*/
export function templateVisitAll(visitor: TemplateAstVisitor, asts: TemplateAst[],
context: any = null): any[] {
export function templateVisitAll(
visitor: TemplateAstVisitor, asts: TemplateAst[], context: any = null): any[] {
var result: any[] /** TODO #9100 */ = [];
asts.forEach(ast => {
var astResult = ast.visit(visitor, context);

View File

@ -1,51 +1,18 @@
import {Injectable, Inject, OpaqueToken, Optional} from '@angular/core';
import {MAX_INTERPOLATION_VALUES, Console, SecurityContext} from '../core_private';
import {Inject, Injectable, OpaqueToken, Optional} from '@angular/core';
import {
ListWrapper,
StringMapWrapper,
SetWrapper,
} from '../src/facade/collection';
import {Console, MAX_INTERPOLATION_VALUES, SecurityContext} from '../core_private';
import {ListWrapper, StringMapWrapper, SetWrapper,} from '../src/facade/collection';
import {RegExpWrapper, isPresent, StringWrapper, isBlank, isArray} from '../src/facade/lang';
import {BaseException} from '../src/facade/exceptions';
import {
AST,
Interpolation,
ASTWithSource,
TemplateBinding,
RecursiveAstVisitor,
BindingPipe
} from './expression_parser/ast';
import {AST, Interpolation, ASTWithSource, TemplateBinding, RecursiveAstVisitor, BindingPipe} from './expression_parser/ast';
import {Parser} from './expression_parser/parser';
import {
CompileDirectiveMetadata,
CompilePipeMetadata,
CompileMetadataWithType,
} from './compile_metadata';
import {CompileDirectiveMetadata, CompilePipeMetadata, CompileMetadataWithType,} from './compile_metadata';
import {HtmlParser} from './html_parser';
import {splitNsName, mergeNsAndName} from './html_tags';
import {ParseSourceSpan, ParseError, ParseLocation, ParseErrorLevel} from './parse_util';
import {
ElementAst,
BoundElementPropertyAst,
BoundEventAst,
ReferenceAst,
TemplateAst,
TemplateAstVisitor,
templateVisitAll,
TextAst,
BoundTextAst,
EmbeddedTemplateAst,
AttrAst,
NgContentAst,
PropertyBindingType,
DirectiveAst,
BoundDirectivePropertyAst,
ProviderAst,
ProviderAstType,
VariableAst
} from './template_ast';
import {ElementAst, BoundElementPropertyAst, BoundEventAst, ReferenceAst, TemplateAst, TemplateAstVisitor, templateVisitAll, TextAst, BoundTextAst, EmbeddedTemplateAst, AttrAst, NgContentAst, PropertyBindingType, DirectiveAst, BoundDirectivePropertyAst, ProviderAst, ProviderAstType, VariableAst} from './template_ast';
import {CssSelector, SelectorMatcher} from './selector';
import {ElementSchemaRegistry} from './schema/element_schema_registry';
@ -53,16 +20,7 @@ import {preparseElement, PreparsedElementType} from './template_preparser';
import {isStyleUrlResolvable} from './style_url_resolver';
import {
HtmlAstVisitor,
HtmlElementAst,
HtmlAttrAst,
HtmlTextAst,
HtmlCommentAst,
HtmlExpansionAst,
HtmlExpansionCaseAst,
htmlVisitAll
} from './html_ast';
import {HtmlAstVisitor, HtmlElementAst, HtmlAttrAst, HtmlTextAst, HtmlCommentAst, HtmlExpansionAst, HtmlExpansionCaseAst, htmlVisitAll} from './html_ast';
import {splitAtColon} from './util';
import {identifierToken, Identifiers} from './identifiers';
@ -116,13 +74,14 @@ export class TemplateParseResult {
@Injectable()
export class TemplateParser {
constructor(private _exprParser: Parser, private _schemaRegistry: ElementSchemaRegistry,
private _htmlParser: HtmlParser, private _console: Console,
@Optional() @Inject(TEMPLATE_TRANSFORMS) public transforms: TemplateAstVisitor[]) {}
constructor(
private _exprParser: Parser, private _schemaRegistry: ElementSchemaRegistry,
private _htmlParser: HtmlParser, private _console: Console,
@Optional() @Inject(TEMPLATE_TRANSFORMS) public transforms: TemplateAstVisitor[]) {}
parse(component: CompileDirectiveMetadata, template: string,
directives: CompileDirectiveMetadata[], pipes: CompilePipeMetadata[],
templateUrl: string): TemplateAst[] {
parse(
component: CompileDirectiveMetadata, template: string, directives: CompileDirectiveMetadata[],
pipes: CompilePipeMetadata[], templateUrl: string): TemplateAst[] {
var result = this.tryParse(component, template, directives, pipes, templateUrl);
var warnings = result.errors.filter(error => error.level === ParseErrorLevel.WARNING);
var errors = result.errors.filter(error => error.level === ParseErrorLevel.FATAL);
@ -136,19 +95,19 @@ export class TemplateParser {
return result.templateAst;
}
tryParse(component: CompileDirectiveMetadata, template: string,
directives: CompileDirectiveMetadata[], pipes: CompilePipeMetadata[],
templateUrl: string): TemplateParseResult {
tryParse(
component: CompileDirectiveMetadata, template: string, directives: CompileDirectiveMetadata[],
pipes: CompilePipeMetadata[], templateUrl: string): TemplateParseResult {
var htmlAstWithErrors = this._htmlParser.parse(template, templateUrl);
var errors:ParseError[] = htmlAstWithErrors.errors;
var errors: ParseError[] = htmlAstWithErrors.errors;
var result: any /** TODO #???? */;
if (htmlAstWithErrors.rootNodes.length > 0) {
var uniqDirectives = <CompileDirectiveMetadata[]>removeDuplicates(directives);
var uniqPipes = <CompilePipeMetadata[]>removeDuplicates(pipes);
var providerViewContext =
new ProviderViewContext(component, htmlAstWithErrors.rootNodes[0].sourceSpan);
var parseVisitor = new TemplateParseVisitor(providerViewContext, uniqDirectives, uniqPipes,
this._exprParser, this._schemaRegistry);
new ProviderViewContext(component, htmlAstWithErrors.rootNodes[0].sourceSpan);
var parseVisitor = new TemplateParseVisitor(
providerViewContext, uniqDirectives, uniqPipes, this._exprParser, this._schemaRegistry);
result = htmlVisitAll(parseVisitor, htmlAstWithErrors.rootNodes, EMPTY_ELEMENT_CONTEXT);
errors = errors.concat(parseVisitor.errors).concat(providerViewContext.errors);
@ -169,23 +128,20 @@ export class TemplateParser {
}
/** @internal */
_assertNoReferenceDuplicationOnTemplate(result:any[], errors:TemplateParseError[]):void {
_assertNoReferenceDuplicationOnTemplate(result: any[], errors: TemplateParseError[]): void {
const existingReferences: any[] /** TODO #???? */ = [];
result
.filter(element => !!element.references)
.forEach(element => element.references.forEach((reference: any /** TODO #???? */)=> {
const name = reference.name;
if (existingReferences.indexOf(name) < 0) {
existingReferences.push(name);
}
else {
const error = new TemplateParseError(
`Reference "#${name}" is defined several times`,
reference.sourceSpan,
ParseErrorLevel.FATAL);
errors.push(error);
}
}));
result.filter(element => !!element.references)
.forEach(element => element.references.forEach((reference: any /** TODO #???? */) => {
const name = reference.name;
if (existingReferences.indexOf(name) < 0) {
existingReferences.push(name);
} else {
const error = new TemplateParseError(
`Reference "#${name}" is defined several times`, reference.sourceSpan,
ParseErrorLevel.FATAL);
errors.push(error);
}
}));
}
}
@ -196,22 +152,24 @@ class TemplateParseVisitor implements HtmlAstVisitor {
ngContentCount: number = 0;
pipesByName: Map<string, CompilePipeMetadata>;
constructor(public providerViewContext: ProviderViewContext,
directives: CompileDirectiveMetadata[], pipes: CompilePipeMetadata[],
private _exprParser: Parser, private _schemaRegistry: ElementSchemaRegistry) {
constructor(
public providerViewContext: ProviderViewContext, directives: CompileDirectiveMetadata[],
pipes: CompilePipeMetadata[], private _exprParser: Parser,
private _schemaRegistry: ElementSchemaRegistry) {
this.selectorMatcher = new SelectorMatcher();
ListWrapper.forEachWithIndex(directives,
(directive: CompileDirectiveMetadata, index: number) => {
var selector = CssSelector.parse(directive.selector);
this.selectorMatcher.addSelectables(selector, directive);
this.directivesIndex.set(directive, index);
});
ListWrapper.forEachWithIndex(
directives, (directive: CompileDirectiveMetadata, index: number) => {
var selector = CssSelector.parse(directive.selector);
this.selectorMatcher.addSelectables(selector, directive);
this.directivesIndex.set(directive, index);
});
this.pipesByName = new Map<string, CompilePipeMetadata>();
pipes.forEach(pipe => this.pipesByName.set(pipe.name, pipe));
}
private _reportError(message: string, sourceSpan: ParseSourceSpan,
level: ParseErrorLevel = ParseErrorLevel.FATAL) {
private _reportError(
message: string, sourceSpan: ParseSourceSpan,
level: ParseErrorLevel = ParseErrorLevel.FATAL) {
this.errors.push(new TemplateParseError(message, sourceSpan, level));
}
@ -340,9 +298,9 @@ class TemplateParseVisitor implements HtmlAstVisitor {
var isTemplateElement = lcElName == TEMPLATE_ELEMENT;
element.attrs.forEach(attr => {
var hasBinding =
this._parseAttr(isTemplateElement, attr, matchableAttrs, elementOrDirectiveProps, animationProps, events,
elementOrDirectiveRefs, elementVars);
var hasBinding = this._parseAttr(
isTemplateElement, attr, matchableAttrs, elementOrDirectiveProps, animationProps, events,
elementOrDirectiveRefs, elementVars);
var hasTemplateBinding = this._parseInlineTemplateBinding(
attr, templateMatchableAttrs, templateElementOrDirectiveProps, templateElementVars);
if (!hasBinding && !hasTemplateBinding) {
@ -358,24 +316,26 @@ class TemplateParseVisitor implements HtmlAstVisitor {
var elementCssSelector = createElementCssSelector(nodeName, matchableAttrs);
var directiveMetas = this._parseDirectives(this.selectorMatcher, elementCssSelector);
var references: ReferenceAst[] = [];
var directiveAsts = this._createDirectiveAsts(isTemplateElement, element.name, directiveMetas,
elementOrDirectiveProps, elementOrDirectiveRefs,
element.sourceSpan, references);
var directiveAsts = this._createDirectiveAsts(
isTemplateElement, element.name, directiveMetas, elementOrDirectiveProps,
elementOrDirectiveRefs, element.sourceSpan, references);
var elementProps: BoundElementPropertyAst[] =
this._createElementPropertyAsts(element.name, elementOrDirectiveProps, directiveAsts).concat(animationProps);
this._createElementPropertyAsts(element.name, elementOrDirectiveProps, directiveAsts)
.concat(animationProps);
var isViewRoot = parent.isTemplateElement || hasInlineTemplates;
var providerContext =
new ProviderElementContext(this.providerViewContext, parent.providerContext, isViewRoot,
directiveAsts, attrs, references, element.sourceSpan);
var providerContext = new ProviderElementContext(
this.providerViewContext, parent.providerContext, isViewRoot, directiveAsts, attrs,
references, element.sourceSpan);
var children = htmlVisitAll(
preparsedElement.nonBindable ? NON_BINDABLE_VISITOR : this, element.children,
ElementContext.create(isTemplateElement, directiveAsts,
isTemplateElement ? parent.providerContext : providerContext));
ElementContext.create(
isTemplateElement, directiveAsts,
isTemplateElement ? parent.providerContext : providerContext));
providerContext.afterElement();
// Override the actual selector when the `ngProjectAs` attribute is provided
var projectionSelector = isPresent(preparsedElement.projectAs) ?
CssSelector.parse(preparsedElement.projectAs)[0] :
elementCssSelector;
CssSelector.parse(preparsedElement.projectAs)[0] :
elementCssSelector;
var ngContentIndex = parent.findNgContentIndex(projectionSelector);
var parsedElement: any /** TODO #???? */;
@ -390,8 +350,8 @@ class TemplateParseVisitor implements HtmlAstVisitor {
this.ngContentCount++, hasInlineTemplates ? null : ngContentIndex, element.sourceSpan);
} else if (isTemplateElement) {
this._assertAllEventsPublishedByDirectives(directiveAsts, events);
this._assertNoComponentsNorElementBindingsOnTemplate(directiveAsts, elementProps,
element.sourceSpan);
this._assertNoComponentsNorElementBindingsOnTemplate(
directiveAsts, elementProps, element.sourceSpan);
parsedElement = new EmbeddedTemplateAst(
attrs, events, references, elementVars, providerContext.transformedDirectiveAsts,
@ -410,9 +370,9 @@ class TemplateParseVisitor implements HtmlAstVisitor {
if (hasInlineTemplates) {
var templateCssSelector = createElementCssSelector(TEMPLATE_ELEMENT, templateMatchableAttrs);
var templateDirectiveMetas = this._parseDirectives(this.selectorMatcher, templateCssSelector);
var templateDirectiveAsts =
this._createDirectiveAsts(true, element.name, templateDirectiveMetas,
templateElementOrDirectiveProps, [], element.sourceSpan, []);
var templateDirectiveAsts = this._createDirectiveAsts(
true, element.name, templateDirectiveMetas, templateElementOrDirectiveProps, [],
element.sourceSpan, []);
var templateElementProps: BoundElementPropertyAst[] = this._createElementPropertyAsts(
element.name, templateElementOrDirectiveProps, templateDirectiveAsts);
this._assertNoComponentsNorElementBindingsOnTemplate(
@ -422,18 +382,18 @@ class TemplateParseVisitor implements HtmlAstVisitor {
templateDirectiveAsts, [], [], element.sourceSpan);
templateProviderContext.afterElement();
parsedElement = new EmbeddedTemplateAst([], [], [], templateElementVars,
templateProviderContext.transformedDirectiveAsts,
templateProviderContext.transformProviders,
templateProviderContext.transformedHasViewContainer,
[parsedElement], ngContentIndex, element.sourceSpan);
parsedElement = new EmbeddedTemplateAst(
[], [], [], templateElementVars, templateProviderContext.transformedDirectiveAsts,
templateProviderContext.transformProviders,
templateProviderContext.transformedHasViewContainer, [parsedElement], ngContentIndex,
element.sourceSpan);
}
return parsedElement;
}
private _parseInlineTemplateBinding(attr: HtmlAttrAst, targetMatchableAttrs: string[][],
targetProps: BoundElementOrDirectiveProperty[],
targetVars: VariableAst[]): boolean {
private _parseInlineTemplateBinding(
attr: HtmlAttrAst, targetMatchableAttrs: string[][],
targetProps: BoundElementOrDirectiveProperty[], targetVars: VariableAst[]): boolean {
var templateBindingsSource: any /** TODO #???? */ = null;
if (attr.name == TEMPLATE_ATTR) {
templateBindingsSource = attr.value;
@ -448,8 +408,8 @@ class TemplateParseVisitor implements HtmlAstVisitor {
if (binding.keyIsVar) {
targetVars.push(new VariableAst(binding.key, binding.name, attr.sourceSpan));
} else if (isPresent(binding.expression)) {
this._parsePropertyAst(binding.key, binding.expression, attr.sourceSpan,
targetMatchableAttrs, targetProps);
this._parsePropertyAst(
binding.key, binding.expression, attr.sourceSpan, targetMatchableAttrs, targetProps);
} else {
targetMatchableAttrs.push([binding.key, '']);
this._parseLiteralAttr(binding.key, null, attr.sourceSpan, targetProps);
@ -460,12 +420,11 @@ class TemplateParseVisitor implements HtmlAstVisitor {
return false;
}
private _parseAttr(isTemplateElement: boolean, attr: HtmlAttrAst,
targetMatchableAttrs: string[][],
targetProps: BoundElementOrDirectiveProperty[],
targetAnimationProps: BoundElementPropertyAst[],
targetEvents: BoundEventAst[],
targetRefs: ElementOrDirectiveRef[], targetVars: VariableAst[]): boolean {
private _parseAttr(
isTemplateElement: boolean, attr: HtmlAttrAst, targetMatchableAttrs: string[][],
targetProps: BoundElementOrDirectiveProperty[],
targetAnimationProps: BoundElementPropertyAst[], targetEvents: BoundEventAst[],
targetRefs: ElementOrDirectiveRef[], targetVars: VariableAst[]): boolean {
var attrName = this._normalizeAttributeName(attr.name);
var attrValue = attr.value;
var bindParts = RegExpWrapper.firstMatch(BIND_NAME_REGEXP, attrName);
@ -473,18 +432,20 @@ class TemplateParseVisitor implements HtmlAstVisitor {
if (isPresent(bindParts)) {
hasBinding = true;
if (isPresent(bindParts[1])) { // match: bind-prop
this._parseProperty(bindParts[8], attrValue, attr.sourceSpan, targetMatchableAttrs,
targetProps);
this._parseProperty(
bindParts[8], attrValue, attr.sourceSpan, targetMatchableAttrs, targetProps);
} else if (isPresent(bindParts[2])) { // match: var-name / var-name="iden"
var identifier = bindParts[8];
if (isTemplateElement) {
this._reportError(`"var-" on <template> elements is deprecated. Use "let-" instead!`,
attr.sourceSpan, ParseErrorLevel.WARNING);
this._reportError(
`"var-" on <template> elements is deprecated. Use "let-" instead!`, attr.sourceSpan,
ParseErrorLevel.WARNING);
this._parseVariable(identifier, attrValue, attr.sourceSpan, targetVars);
} else {
this._reportError(`"var-" on non <template> elements is deprecated. Use "ref-" instead!`,
attr.sourceSpan, ParseErrorLevel.WARNING);
this._reportError(
`"var-" on non <template> elements is deprecated. Use "ref-" instead!`,
attr.sourceSpan, ParseErrorLevel.WARNING);
this._parseReference(identifier, attrValue, attr.sourceSpan, targetRefs);
}
@ -501,35 +462,35 @@ class TemplateParseVisitor implements HtmlAstVisitor {
this._parseReference(identifier, attrValue, attr.sourceSpan, targetRefs);
} else if (isPresent(bindParts[5])) { // match: on-event
this._parseEvent(bindParts[8], attrValue, attr.sourceSpan, targetMatchableAttrs,
targetEvents);
this._parseEvent(
bindParts[8], attrValue, attr.sourceSpan, targetMatchableAttrs, targetEvents);
} else if (isPresent(bindParts[6])) { // match: bindon-prop
this._parseProperty(bindParts[8], attrValue, attr.sourceSpan, targetMatchableAttrs,
targetProps);
this._parseAssignmentEvent(bindParts[8], attrValue, attr.sourceSpan, targetMatchableAttrs,
targetEvents);
this._parseProperty(
bindParts[8], attrValue, attr.sourceSpan, targetMatchableAttrs, targetProps);
this._parseAssignmentEvent(
bindParts[8], attrValue, attr.sourceSpan, targetMatchableAttrs, targetEvents);
} else if (isPresent(bindParts[7])) { // match: animate-name
this._parseAnimation(bindParts[8], attrValue, attr.sourceSpan, targetMatchableAttrs,
targetAnimationProps);
this._parseAnimation(
bindParts[8], attrValue, attr.sourceSpan, targetMatchableAttrs, targetAnimationProps);
} else if (isPresent(bindParts[9])) { // match: [(expr)]
this._parseProperty(bindParts[9], attrValue, attr.sourceSpan, targetMatchableAttrs,
targetProps);
this._parseAssignmentEvent(bindParts[9], attrValue, attr.sourceSpan, targetMatchableAttrs,
targetEvents);
this._parseProperty(
bindParts[9], attrValue, attr.sourceSpan, targetMatchableAttrs, targetProps);
this._parseAssignmentEvent(
bindParts[9], attrValue, attr.sourceSpan, targetMatchableAttrs, targetEvents);
} else if (isPresent(bindParts[10])) { // match: [expr]
this._parseProperty(bindParts[10], attrValue, attr.sourceSpan, targetMatchableAttrs,
targetProps);
this._parseProperty(
bindParts[10], attrValue, attr.sourceSpan, targetMatchableAttrs, targetProps);
} else if (isPresent(bindParts[11])) { // match: (event)
this._parseEvent(bindParts[11], attrValue, attr.sourceSpan, targetMatchableAttrs,
targetEvents);
this._parseEvent(
bindParts[11], attrValue, attr.sourceSpan, targetMatchableAttrs, targetEvents);
}
} else {
hasBinding = this._parsePropertyInterpolation(attrName, attrValue, attr.sourceSpan,
targetMatchableAttrs, targetProps);
hasBinding = this._parsePropertyInterpolation(
attrName, attrValue, attr.sourceSpan, targetMatchableAttrs, targetProps);
}
if (!hasBinding) {
this._parseLiteralAttr(attrName, attrValue, attr.sourceSpan, targetProps);
@ -541,9 +502,8 @@ class TemplateParseVisitor implements HtmlAstVisitor {
return attrName.toLowerCase().startsWith('data-') ? attrName.substring(5) : attrName;
}
private _parseVariable(identifier: string, value: string, sourceSpan: ParseSourceSpan,
targetVars: VariableAst[]) {
private _parseVariable(
identifier: string, value: string, sourceSpan: ParseSourceSpan, targetVars: VariableAst[]) {
if (identifier.indexOf('-') > -1) {
this._reportError(`"-" is not allowed in variable names`, sourceSpan);
}
@ -551,8 +511,9 @@ class TemplateParseVisitor implements HtmlAstVisitor {
targetVars.push(new VariableAst(identifier, value, sourceSpan));
}
private _parseReference(identifier: string, value: string, sourceSpan: ParseSourceSpan,
targetRefs: ElementOrDirectiveRef[]) {
private _parseReference(
identifier: string, value: string, sourceSpan: ParseSourceSpan,
targetRefs: ElementOrDirectiveRef[]) {
if (identifier.indexOf('-') > -1) {
this._reportError(`"-" is not allowed in reference names`, sourceSpan);
}
@ -560,24 +521,26 @@ class TemplateParseVisitor implements HtmlAstVisitor {
targetRefs.push(new ElementOrDirectiveRef(identifier, value, sourceSpan));
}
private _parseProperty(name: string, expression: string, sourceSpan: ParseSourceSpan,
targetMatchableAttrs: string[][],
targetProps: BoundElementOrDirectiveProperty[]) {
this._parsePropertyAst(name, this._parseBinding(expression, sourceSpan), sourceSpan,
targetMatchableAttrs, targetProps);
private _parseProperty(
name: string, expression: string, sourceSpan: ParseSourceSpan,
targetMatchableAttrs: string[][], targetProps: BoundElementOrDirectiveProperty[]) {
this._parsePropertyAst(
name, this._parseBinding(expression, sourceSpan), sourceSpan, targetMatchableAttrs,
targetProps);
}
private _parseAnimation(name: string, expression: string, sourceSpan: ParseSourceSpan,
targetMatchableAttrs: string[][],
targetAnimationProps: BoundElementPropertyAst[]) {
private _parseAnimation(
name: string, expression: string, sourceSpan: ParseSourceSpan,
targetMatchableAttrs: string[][], targetAnimationProps: BoundElementPropertyAst[]) {
var ast = this._parseBinding(expression, sourceSpan);
targetMatchableAttrs.push([name, ast.source]);
targetAnimationProps.push(new BoundElementPropertyAst(name, PropertyBindingType.Animation, SecurityContext.NONE, ast, null, sourceSpan));
targetAnimationProps.push(new BoundElementPropertyAst(
name, PropertyBindingType.Animation, SecurityContext.NONE, ast, null, sourceSpan));
}
private _parsePropertyInterpolation(name: string, value: string, sourceSpan: ParseSourceSpan,
targetMatchableAttrs: string[][],
targetProps: BoundElementOrDirectiveProperty[]): boolean {
private _parsePropertyInterpolation(
name: string, value: string, sourceSpan: ParseSourceSpan, targetMatchableAttrs: string[][],
targetProps: BoundElementOrDirectiveProperty[]): boolean {
var expr = this._parseInterpolation(value, sourceSpan);
if (isPresent(expr)) {
this._parsePropertyAst(name, expr, sourceSpan, targetMatchableAttrs, targetProps);
@ -586,21 +549,23 @@ class TemplateParseVisitor implements HtmlAstVisitor {
return false;
}
private _parsePropertyAst(name: string, ast: ASTWithSource, sourceSpan: ParseSourceSpan,
targetMatchableAttrs: string[][],
targetProps: BoundElementOrDirectiveProperty[]) {
private _parsePropertyAst(
name: string, ast: ASTWithSource, sourceSpan: ParseSourceSpan,
targetMatchableAttrs: string[][], targetProps: BoundElementOrDirectiveProperty[]) {
targetMatchableAttrs.push([name, ast.source]);
targetProps.push(new BoundElementOrDirectiveProperty(name, ast, false, sourceSpan));
}
private _parseAssignmentEvent(name: string, expression: string, sourceSpan: ParseSourceSpan,
targetMatchableAttrs: string[][], targetEvents: BoundEventAst[]) {
this._parseEvent(`${name}Change`, `${expression}=$event`, sourceSpan, targetMatchableAttrs,
targetEvents);
private _parseAssignmentEvent(
name: string, expression: string, sourceSpan: ParseSourceSpan,
targetMatchableAttrs: string[][], targetEvents: BoundEventAst[]) {
this._parseEvent(
`${name}Change`, `${expression}=$event`, sourceSpan, targetMatchableAttrs, targetEvents);
}
private _parseEvent(name: string, expression: string, sourceSpan: ParseSourceSpan,
targetMatchableAttrs: string[][], targetEvents: BoundEventAst[]) {
private _parseEvent(
name: string, expression: string, sourceSpan: ParseSourceSpan,
targetMatchableAttrs: string[][], targetEvents: BoundEventAst[]) {
// long format: 'target: eventName'
var parts = splitAtColon(name, [null, name]);
var target = parts[0];
@ -612,14 +577,15 @@ class TemplateParseVisitor implements HtmlAstVisitor {
// so don't add the event name to the matchableAttrs
}
private _parseLiteralAttr(name: string, value: string, sourceSpan: ParseSourceSpan,
targetProps: BoundElementOrDirectiveProperty[]) {
private _parseLiteralAttr(
name: string, value: string, sourceSpan: ParseSourceSpan,
targetProps: BoundElementOrDirectiveProperty[]) {
targetProps.push(new BoundElementOrDirectiveProperty(
name, this._exprParser.wrapLiteralPrimitive(value, ''), true, sourceSpan));
}
private _parseDirectives(selectorMatcher: SelectorMatcher,
elementCssSelector: CssSelector): CompileDirectiveMetadata[] {
private _parseDirectives(selectorMatcher: SelectorMatcher, elementCssSelector: CssSelector):
CompileDirectiveMetadata[] {
// Need to sort the directives so that we get consistent results throughout,
// as selectorMatcher uses Maps inside.
// Also dedupe directives as they might match more than one time!
@ -630,12 +596,10 @@ class TemplateParseVisitor implements HtmlAstVisitor {
return directives.filter(dir => isPresent(dir));
}
private _createDirectiveAsts(isTemplateElement: boolean, elementName: string,
directives: CompileDirectiveMetadata[],
props: BoundElementOrDirectiveProperty[],
elementOrDirectiveRefs: ElementOrDirectiveRef[],
sourceSpan: ParseSourceSpan,
targetReferences: ReferenceAst[]): DirectiveAst[] {
private _createDirectiveAsts(
isTemplateElement: boolean, elementName: string, directives: CompileDirectiveMetadata[],
props: BoundElementOrDirectiveProperty[], elementOrDirectiveRefs: ElementOrDirectiveRef[],
sourceSpan: ParseSourceSpan, targetReferences: ReferenceAst[]): DirectiveAst[] {
var matchedReferences = new Set<string>();
var component: CompileDirectiveMetadata = null;
var directiveAsts = directives.map((directive: CompileDirectiveMetadata) => {
@ -645,26 +609,27 @@ class TemplateParseVisitor implements HtmlAstVisitor {
var hostProperties: BoundElementPropertyAst[] = [];
var hostEvents: BoundEventAst[] = [];
var directiveProperties: BoundDirectivePropertyAst[] = [];
this._createDirectiveHostPropertyAsts(elementName, directive.hostProperties, sourceSpan,
hostProperties);
this._createDirectiveHostPropertyAsts(
elementName, directive.hostProperties, sourceSpan, hostProperties);
this._createDirectiveHostEventAsts(directive.hostListeners, sourceSpan, hostEvents);
this._createDirectivePropertyAsts(directive.inputs, props, directiveProperties);
elementOrDirectiveRefs.forEach((elOrDirRef) => {
if ((elOrDirRef.value.length === 0 && directive.isComponent) ||
(directive.exportAs == elOrDirRef.value)) {
targetReferences.push(new ReferenceAst(elOrDirRef.name, identifierToken(directive.type),
elOrDirRef.sourceSpan));
targetReferences.push(new ReferenceAst(
elOrDirRef.name, identifierToken(directive.type), elOrDirRef.sourceSpan));
matchedReferences.add(elOrDirRef.name);
}
});
return new DirectiveAst(directive, directiveProperties, hostProperties, hostEvents,
sourceSpan);
return new DirectiveAst(
directive, directiveProperties, hostProperties, hostEvents, sourceSpan);
});
elementOrDirectiveRefs.forEach((elOrDirRef) => {
if (elOrDirRef.value.length > 0) {
if (!SetWrapper.has(matchedReferences, elOrDirRef.name)) {
this._reportError(`There is no directive with "exportAs" set to "${elOrDirRef.value}"`,
elOrDirRef.sourceSpan);
this._reportError(
`There is no directive with "exportAs" set to "${elOrDirRef.value}"`,
elOrDirRef.sourceSpan);
};
} else if (isBlank(component)) {
var refToken: any /** TODO #???? */ = null;
@ -677,9 +642,9 @@ class TemplateParseVisitor implements HtmlAstVisitor {
return directiveAsts;
}
private _createDirectiveHostPropertyAsts(elementName: string, hostProps: {[key: string]: string},
sourceSpan: ParseSourceSpan,
targetPropertyAsts: BoundElementPropertyAst[]) {
private _createDirectiveHostPropertyAsts(
elementName: string, hostProps: {[key: string]: string}, sourceSpan: ParseSourceSpan,
targetPropertyAsts: BoundElementPropertyAst[]) {
if (isPresent(hostProps)) {
StringMapWrapper.forEach(hostProps, (expression: string, propName: string) => {
var exprAst = this._parseBinding(expression, sourceSpan);
@ -689,9 +654,9 @@ class TemplateParseVisitor implements HtmlAstVisitor {
}
}
private _createDirectiveHostEventAsts(hostListeners: {[key: string]: string},
sourceSpan: ParseSourceSpan,
targetEventAsts: BoundEventAst[]) {
private _createDirectiveHostEventAsts(
hostListeners: {[key: string]: string}, sourceSpan: ParseSourceSpan,
targetEventAsts: BoundEventAst[]) {
if (isPresent(hostListeners)) {
StringMapWrapper.forEach(hostListeners, (expression: string, propName: string) => {
this._parseEvent(propName, expression, sourceSpan, [], targetEventAsts);
@ -699,9 +664,9 @@ class TemplateParseVisitor implements HtmlAstVisitor {
}
}
private _createDirectivePropertyAsts(directiveProperties: {[key: string]: string},
boundProps: BoundElementOrDirectiveProperty[],
targetBoundDirectiveProps: BoundDirectivePropertyAst[]) {
private _createDirectivePropertyAsts(
directiveProperties: {[key: string]: string}, boundProps: BoundElementOrDirectiveProperty[],
targetBoundDirectiveProps: BoundDirectivePropertyAst[]) {
if (isPresent(directiveProperties)) {
var boundPropsByName = new Map<string, BoundElementOrDirectiveProperty>();
boundProps.forEach(boundProp => {
@ -724,8 +689,9 @@ class TemplateParseVisitor implements HtmlAstVisitor {
}
}
private _createElementPropertyAsts(elementName: string, props: BoundElementOrDirectiveProperty[],
directives: DirectiveAst[]): BoundElementPropertyAst[] {
private _createElementPropertyAsts(
elementName: string, props: BoundElementOrDirectiveProperty[],
directives: DirectiveAst[]): BoundElementPropertyAst[] {
var boundElementProps: BoundElementPropertyAst[] = [];
var boundDirectivePropsIndex = new Map<string, BoundDirectivePropertyAst>();
directives.forEach((directive: DirectiveAst) => {
@ -735,15 +701,16 @@ class TemplateParseVisitor implements HtmlAstVisitor {
});
props.forEach((prop: BoundElementOrDirectiveProperty) => {
if (!prop.isLiteral && isBlank(boundDirectivePropsIndex.get(prop.name))) {
boundElementProps.push(this._createElementPropertyAst(elementName, prop.name,
prop.expression, prop.sourceSpan));
boundElementProps.push(this._createElementPropertyAst(
elementName, prop.name, prop.expression, prop.sourceSpan));
}
});
return boundElementProps;
}
private _createElementPropertyAst(elementName: string, name: string, ast: AST,
sourceSpan: ParseSourceSpan): BoundElementPropertyAst {
private _createElementPropertyAst(
elementName: string, name: string, ast: AST,
sourceSpan: ParseSourceSpan): BoundElementPropertyAst {
var unit: any /** TODO #???? */ = null;
var bindingType: any /** TODO #???? */;
var boundPropertyName: string;
@ -755,8 +722,8 @@ class TemplateParseVisitor implements HtmlAstVisitor {
bindingType = PropertyBindingType.Property;
if (!this._schemaRegistry.hasProperty(elementName, boundPropertyName)) {
this._reportError(
`Can't bind to '${boundPropertyName}' since it isn't a known native property`,
sourceSpan);
`Can't bind to '${boundPropertyName}' since it isn't a known native property`,
sourceSpan);
}
} else {
if (parts[0] == ATTRIBUTE_PREFIX) {
@ -794,8 +761,8 @@ class TemplateParseVisitor implements HtmlAstVisitor {
}
}
return new BoundElementPropertyAst(boundPropertyName, bindingType, securityContext, ast, unit,
sourceSpan);
return new BoundElementPropertyAst(
boundPropertyName, bindingType, securityContext, ast, unit, sourceSpan);
}
@ -817,13 +784,13 @@ class TemplateParseVisitor implements HtmlAstVisitor {
}
}
private _assertNoComponentsNorElementBindingsOnTemplate(directives: DirectiveAst[],
elementProps: BoundElementPropertyAst[],
sourceSpan: ParseSourceSpan) {
private _assertNoComponentsNorElementBindingsOnTemplate(
directives: DirectiveAst[], elementProps: BoundElementPropertyAst[],
sourceSpan: ParseSourceSpan) {
var componentTypeNames: string[] = this._findComponentDirectiveNames(directives);
if (componentTypeNames.length > 0) {
this._reportError(`Components on an embedded template: ${componentTypeNames.join(',')}`,
sourceSpan);
this._reportError(
`Components on an embedded template: ${componentTypeNames.join(',')}`, sourceSpan);
}
elementProps.forEach(prop => {
this._reportError(
@ -832,12 +799,13 @@ class TemplateParseVisitor implements HtmlAstVisitor {
});
}
private _assertAllEventsPublishedByDirectives(directives: DirectiveAst[],
events: BoundEventAst[]) {
private _assertAllEventsPublishedByDirectives(
directives: DirectiveAst[], events: BoundEventAst[]) {
var allDirectiveEvents = new Set<string>();
directives.forEach(directive => {
StringMapWrapper.forEach(directive.directive.outputs,
(eventName: string, _: any /** TODO #???? */) => { allDirectiveEvents.add(eventName); });
StringMapWrapper.forEach(
directive.directive.outputs,
(eventName: string, _: any /** TODO #???? */) => { allDirectiveEvents.add(eventName); });
});
events.forEach(event => {
if (isPresent(event.target) || !SetWrapper.has(allDirectiveEvents, event.name)) {
@ -865,8 +833,9 @@ class NonBindableVisitor implements HtmlAstVisitor {
var selector = createElementCssSelector(ast.name, attrNameAndValues);
var ngContentIndex = parent.findNgContentIndex(selector);
var children = htmlVisitAll(this, ast.children, EMPTY_ELEMENT_CONTEXT);
return new ElementAst(ast.name, htmlVisitAll(this, ast.attrs), [], [], [], [], [], false,
children, ngContentIndex, ast.sourceSpan);
return new ElementAst(
ast.name, htmlVisitAll(this, ast.attrs), [], [], [], [], [], false, children,
ngContentIndex, ast.sourceSpan);
}
visitComment(ast: HtmlCommentAst, context: any): any { return null; }
visitAttr(ast: HtmlAttrAst, context: any): AttrAst {
@ -881,8 +850,9 @@ class NonBindableVisitor implements HtmlAstVisitor {
}
class BoundElementOrDirectiveProperty {
constructor(public name: string, public expression: AST, public isLiteral: boolean,
public sourceSpan: ParseSourceSpan) {}
constructor(
public name: string, public expression: AST, public isLiteral: boolean,
public sourceSpan: ParseSourceSpan) {}
}
class ElementOrDirectiveRef {
@ -894,8 +864,9 @@ export function splitClasses(classAttrValue: string): string[] {
}
class ElementContext {
static create(isTemplateElement: boolean, directives: DirectiveAst[],
providerContext: ProviderElementContext): ElementContext {
static create(
isTemplateElement: boolean, directives: DirectiveAst[],
providerContext: ProviderElementContext): ElementContext {
var matcher = new SelectorMatcher();
var wildcardNgContentIndex: any /** TODO #???? */ = null;
var component = directives.find(directive => directive.directive.isComponent);
@ -912,9 +883,9 @@ class ElementContext {
}
return new ElementContext(isTemplateElement, matcher, wildcardNgContentIndex, providerContext);
}
constructor(public isTemplateElement: boolean, private _ngContentIndexMatcher: SelectorMatcher,
private _wildcardNgContentIndex: number,
public providerContext: ProviderElementContext) {}
constructor(
public isTemplateElement: boolean, private _ngContentIndexMatcher: SelectorMatcher,
private _wildcardNgContentIndex: number, public providerContext: ProviderElementContext) {}
findNgContentIndex(selector: CssSelector): number {
var ngContentIndices: any[] /** TODO #???? */ = [];
@ -966,8 +937,9 @@ function removeDuplicates(items: CompileMetadataWithType[]): CompileMetadataWith
let res: any[] /** TODO #???? */ = [];
items.forEach(item => {
let hasMatch =
res.filter(r => r.type.name == item.type.name && r.type.moduleUrl == item.type.moduleUrl &&
r.type.runtime == item.type.runtime)
res.filter(
r => r.type.name == item.type.name && r.type.moduleUrl == item.type.moduleUrl &&
r.type.runtime == item.type.runtime)
.length > 0;
if (!hasMatch) {
res.push(item);

View File

@ -60,8 +60,9 @@ export enum PreparsedElementType {
}
export class PreparsedElement {
constructor(public type: PreparsedElementType, public selectAttr: string, public hrefAttr: string,
public nonBindable: boolean, public projectAs: string) {}
constructor(
public type: PreparsedElementType, public selectAttr: string, public hrefAttr: string,
public nonBindable: boolean, public projectAs: string) {}
}

View File

@ -1,10 +1,6 @@
import {Injectable, Inject, PACKAGE_ROOT_URL} from '@angular/core';
import {
StringWrapper,
isPresent,
isBlank,
RegExpWrapper,
} from '../src/facade/lang';
import {Inject, Injectable, PACKAGE_ROOT_URL} from '@angular/core';
import {StringWrapper, isPresent, isBlank, RegExpWrapper,} from '../src/facade/lang';
const _ASSET_SCHEME = 'asset:';
@ -25,7 +21,7 @@ export function createOfflineCompileUrlResolver(): UrlResolver {
*/
export var DEFAULT_PACKAGE_URL_PROVIDER = {
provide: PACKAGE_ROOT_URL,
useValue: "/"
useValue: '/'
};
/**
@ -59,7 +55,7 @@ export class UrlResolver {
var resolvedParts = _split(resolvedUrl);
var prefix = this._packagePrefix;
if (isPresent(prefix) && isPresent(resolvedParts) &&
resolvedParts[_ComponentIndex.Scheme] == "package") {
resolvedParts[_ComponentIndex.Scheme] == 'package') {
var path = resolvedParts[_ComponentIndex.Path];
if (this._packagePrefix === _ASSET_SCHEME) {
var pathSegements = path.split(/\//);
@ -79,7 +75,7 @@ export class UrlResolver {
*/
export function getUrlScheme(url: string): string {
var match = _split(url);
return (match && match[_ComponentIndex.Scheme]) || "";
return (match && match[_ComponentIndex.Scheme]) || '';
}
// The code below is adapted from Traceur:
@ -102,9 +98,9 @@ export function getUrlScheme(url: string): string {
* @param opt_fragment The URI-encoded fragment identifier.
* @return The fully combined URI.
*/
function _buildFromEncodedParts(opt_scheme?: string, opt_userInfo?: string, opt_domain?: string,
opt_port?: string, opt_path?: string, opt_queryData?: string,
opt_fragment?: string): string {
function _buildFromEncodedParts(
opt_scheme?: string, opt_userInfo?: string, opt_domain?: string, opt_port?: string,
opt_path?: string, opt_queryData?: string, opt_fragment?: string): string {
var out: any[] /** TODO #9100 */ = [];
if (isPresent(opt_scheme)) {
@ -202,24 +198,24 @@ function _buildFromEncodedParts(opt_scheme?: string, opt_userInfo?: string, opt_
* @type {!RegExp}
* @internal
*/
var _splitRe =
RegExpWrapper.create('^' +
'(?:' +
'([^:/?#.]+)' + // scheme - ignore special characters
// used by other URL parts such as :,
// ?, /, #, and .
':)?' +
'(?://' +
'(?:([^/?#]*)@)?' + // userInfo
'([\\w\\d\\-\\u0100-\\uffff.%]*)' + // domain - restrict to letters,
// digits, dashes, dots, percent
// escapes, and unicode characters.
'(?::([0-9]+))?' + // port
')?' +
'([^?#]+)?' + // path
'(?:\\?([^#]*))?' + // query
'(?:#(.*))?' + // fragment
'$');
var _splitRe = RegExpWrapper.create(
'^' +
'(?:' +
'([^:/?#.]+)' + // scheme - ignore special characters
// used by other URL parts such as :,
// ?, /, #, and .
':)?' +
'(?://' +
'(?:([^/?#]*)@)?' + // userInfo
'([\\w\\d\\-\\u0100-\\uffff.%]*)' + // domain - restrict to letters,
// digits, dashes, dots, percent
// escapes, and unicode characters.
'(?::([0-9]+))?' + // port
')?' +
'([^?#]+)?' + // path
'(?:\\?([^#]*))?' + // query
'(?:#(.*))?' + // fragment
'$');
/**
* The index of each URI component in the return value of goog.uri.utils.split.
@ -250,7 +246,7 @@ enum _ComponentIndex {
* on the browser's regular expression implementation. Never null, since
* arbitrary strings may still look like path names.
*/
function _split(uri: string): Array<string | any> {
function _split(uri: string): Array<string|any> {
return RegExpWrapper.firstMatch(_splitRe, uri);
}
@ -308,9 +304,10 @@ function _joinAndCanonicalizePath(parts: any[]): string {
path = isBlank(path) ? '' : _removeDotSegments(path);
parts[_ComponentIndex.Path] = path;
return _buildFromEncodedParts(parts[_ComponentIndex.Scheme], parts[_ComponentIndex.UserInfo],
parts[_ComponentIndex.Domain], parts[_ComponentIndex.Port], path,
parts[_ComponentIndex.QueryData], parts[_ComponentIndex.Fragment]);
return _buildFromEncodedParts(
parts[_ComponentIndex.Scheme], parts[_ComponentIndex.UserInfo], parts[_ComponentIndex.Domain],
parts[_ComponentIndex.Port], path, parts[_ComponentIndex.QueryData],
parts[_ComponentIndex.Fragment]);
}
/**

View File

@ -1,13 +1,5 @@
import {
IS_DART,
StringWrapper,
Math,
isBlank,
isArray,
isStrictStringMap,
isPrimitive
} from './facade/lang';
import {StringMapWrapper} from './facade/collection';
import {IS_DART, Math, StringWrapper, isArray, isBlank, isPrimitive, isStrictStringMap} from './facade/lang';
export var MODULE_SUFFIX = IS_DART ? '.dart' : '';
@ -15,13 +7,13 @@ var CAMEL_CASE_REGEXP = /([A-Z])/g;
var DASH_CASE_REGEXP = /-([a-z])/g;
export function camelCaseToDashCase(input: string): string {
return StringWrapper.replaceAllMapped(input, CAMEL_CASE_REGEXP,
(m: any /** TODO #9100 */) => { return '-' + m[1].toLowerCase(); });
return StringWrapper.replaceAllMapped(
input, CAMEL_CASE_REGEXP, (m: any /** TODO #9100 */) => { return '-' + m[1].toLowerCase(); });
}
export function dashCaseToCamelCase(input: string): string {
return StringWrapper.replaceAllMapped(input, DASH_CASE_REGEXP,
(m: any /** TODO #9100 */) => { return m[1].toUpperCase(); });
return StringWrapper.replaceAllMapped(
input, DASH_CASE_REGEXP, (m: any /** TODO #9100 */) => { return m[1].toUpperCase(); });
}
export function splitAtColon(input: string, defaultValues: string[]): string[] {
@ -62,8 +54,9 @@ export class ValueTransformer implements ValueVisitor {
}
visitStringMap(map: {[key: string]: any}, context: any): any {
var result = {};
StringMapWrapper.forEach(map,
(value: any /** TODO #9100 */, key: any /** TODO #9100 */) => { (result as any /** TODO #9100 */)[key] = visitValue(value, this, context); });
StringMapWrapper.forEach(map, (value: any /** TODO #9100 */, key: any /** TODO #9100 */) => {
(result as any /** TODO #9100 */)[key] = visitValue(value, this, context);
});
return result;
}
visitPrimitive(value: any, context: any): any { return value; }

View File

@ -1,6 +1,7 @@
import {CompileNode} from './compile_element';
import {TemplateAst} from '../template_ast';
import {CompileNode} from './compile_element';
export class CompileBinding {
constructor(public node: CompileNode, public sourceAst: TemplateAst) {}
}

View File

@ -1,29 +1,24 @@
import {BaseException} from '@angular/core';
import {isPresent, isBlank} from '../facade/lang';
import {ListWrapper, StringMapWrapper} from '../facade/collection';
import * as o from '../output/output_ast';
import {ListWrapper, StringMapWrapper} from '../facade/collection';
import {isBlank, isPresent} from '../facade/lang';
import {Identifiers, identifierToken} from '../identifiers';
import {InjectMethodVars} from './constants';
import * as o from '../output/output_ast';
import {ProviderAst, ProviderAstType, ReferenceAst, TemplateAst} from '../template_ast';
import {CompileView} from './compile_view';
import {TemplateAst, ProviderAst, ProviderAstType, ReferenceAst} from '../template_ast';
import {
CompileTokenMap,
CompileDirectiveMetadata,
CompileTokenMetadata,
CompileQueryMetadata,
CompileProviderMetadata,
CompileDiDependencyMetadata,
CompileIdentifierMetadata,
} from '../compile_metadata';
import {InjectMethodVars} from './constants';
import {CompileTokenMap, CompileDirectiveMetadata, CompileTokenMetadata, CompileQueryMetadata, CompileProviderMetadata, CompileDiDependencyMetadata, CompileIdentifierMetadata,} from '../compile_metadata';
import {getPropertyInView, createDiTokenExpression, injectFromViewParentInjector} from './util';
import {CompileQuery, createQueryList, addQueryToTokenMap} from './compile_query';
import {CompileMethod} from './compile_method';
import {ValueTransformer, visitValue} from '../util';
export class CompileNode {
constructor(public parent: CompileElement, public view: CompileView, public nodeIndex: number,
public renderNode: o.Expression, public sourceAst: TemplateAst) {}
constructor(
public parent: CompileElement, public view: CompileView, public nodeIndex: number,
public renderNode: o.Expression, public sourceAst: TemplateAst) {}
isNull(): boolean { return isBlank(this.renderNode); }
@ -51,12 +46,12 @@ export class CompileElement extends CompileNode {
public directiveInstances: o.Expression[];
public referenceTokens: {[key: string]: CompileTokenMetadata};
constructor(parent: CompileElement, view: CompileView, nodeIndex: number,
renderNode: o.Expression, sourceAst: TemplateAst,
public component: CompileDirectiveMetadata,
private _directives: CompileDirectiveMetadata[],
private _resolvedProvidersArray: ProviderAst[], public hasViewContainer: boolean,
public hasEmbeddedView: boolean, references: ReferenceAst[]) {
constructor(
parent: CompileElement, view: CompileView, nodeIndex: number, renderNode: o.Expression,
sourceAst: TemplateAst, public component: CompileDirectiveMetadata,
private _directives: CompileDirectiveMetadata[],
private _resolvedProvidersArray: ProviderAst[], public hasViewContainer: boolean,
public hasEmbeddedView: boolean, references: ReferenceAst[]) {
super(parent, view, nodeIndex, renderNode, sourceAst);
this.referenceTokens = {};
references.forEach(ref => this.referenceTokens[ref.name] = ref.value);
@ -75,17 +70,14 @@ export class CompileElement extends CompileNode {
var fieldName = `_appEl_${this.nodeIndex}`;
var parentNodeIndex = this.isRootElement() ? null : this.parent.nodeIndex;
// private is fine here as no child view will reference an AppElement
this.view.fields.push(new o.ClassField(fieldName, o.importType(Identifiers.AppElement),
[o.StmtModifier.Private]));
var statement = o.THIS_EXPR.prop(fieldName)
.set(o.importExpr(Identifiers.AppElement)
.instantiate([
o.literal(this.nodeIndex),
o.literal(parentNodeIndex),
o.THIS_EXPR,
this.renderNode
]))
.toStmt();
this.view.fields.push(new o.ClassField(
fieldName, o.importType(Identifiers.AppElement), [o.StmtModifier.Private]));
var statement =
o.THIS_EXPR.prop(fieldName)
.set(o.importExpr(Identifiers.AppElement).instantiate([
o.literal(this.nodeIndex), o.literal(parentNodeIndex), o.THIS_EXPR, this.renderNode
]))
.toStmt();
this.view.createMethod.addStmt(statement);
this.appElement = o.THIS_EXPR.prop(fieldName);
this._instances.add(identifierToken(Identifiers.AppElement), this.appElement);
@ -103,27 +95,27 @@ export class CompileElement extends CompileNode {
setEmbeddedView(embeddedView: CompileView) {
this.embeddedView = embeddedView;
if (isPresent(embeddedView)) {
var createTemplateRefExpr =
o.importExpr(Identifiers.TemplateRef_)
.instantiate([this.appElement, this.embeddedView.viewFactory]);
var createTemplateRefExpr = o.importExpr(Identifiers.TemplateRef_).instantiate([
this.appElement, this.embeddedView.viewFactory
]);
var provider = new CompileProviderMetadata(
{token: identifierToken(Identifiers.TemplateRef), useValue: createTemplateRefExpr});
// Add TemplateRef as first provider as it does not have deps on other providers
this._resolvedProvidersArray.unshift(new ProviderAst(provider.token, false, true, [provider],
ProviderAstType.Builtin,
this.sourceAst.sourceSpan));
this._resolvedProvidersArray.unshift(new ProviderAst(
provider.token, false, true, [provider], ProviderAstType.Builtin,
this.sourceAst.sourceSpan));
}
}
beforeChildren(): void {
if (this.hasViewContainer) {
this._instances.add(identifierToken(Identifiers.ViewContainerRef),
this.appElement.prop('vcRef'));
this._instances.add(
identifierToken(Identifiers.ViewContainerRef), this.appElement.prop('vcRef'));
}
this._resolvedProviders = new CompileTokenMap<ProviderAst>();
this._resolvedProvidersArray.forEach(provider =>
this._resolvedProviders.add(provider.token, provider));
this._resolvedProvidersArray.forEach(
provider => this._resolvedProviders.add(provider.token, provider));
// create all the provider instances, some in the view constructor,
// some as getters. We rely on the fact that they are already sorted topologically.
@ -147,9 +139,9 @@ export class CompileElement extends CompileNode {
}
});
var propName = `_${resolvedProvider.token.name}_${this.nodeIndex}_${this._instances.size}`;
var instance =
createProviderProperty(propName, resolvedProvider, providerValueExpressions,
resolvedProvider.multiProvider, resolvedProvider.eager, this);
var instance = createProviderProperty(
propName, resolvedProvider, providerValueExpressions, resolvedProvider.multiProvider,
resolvedProvider.eager, this);
this._instances.add(resolvedProvider.token, instance);
});
@ -167,19 +159,21 @@ export class CompileElement extends CompileNode {
queriesWithReads,
queriesForProvider.map(query => new _QueryWithRead(query, resolvedProvider.token)));
});
StringMapWrapper.forEach(this.referenceTokens, (_: any /** TODO #9100 */, varName: any /** TODO #9100 */) => {
var token = this.referenceTokens[varName];
var varValue: any /** TODO #9100 */;
if (isPresent(token)) {
varValue = this._instances.get(token);
} else {
varValue = this.renderNode;
}
this.view.locals.set(varName, varValue);
var varToken = new CompileTokenMetadata({value: varName});
ListWrapper.addAll(queriesWithReads, this._getQueriesFor(varToken)
.map(query => new _QueryWithRead(query, varToken)));
});
StringMapWrapper.forEach(
this.referenceTokens, (_: any /** TODO #9100 */, varName: any /** TODO #9100 */) => {
var token = this.referenceTokens[varName];
var varValue: any /** TODO #9100 */;
if (isPresent(token)) {
varValue = this._instances.get(token);
} else {
varValue = this.renderNode;
}
this.view.locals.set(varName, varValue);
var varToken = new CompileTokenMetadata({value: varName});
ListWrapper.addAll(
queriesWithReads,
this._getQueriesFor(varToken).map(query => new _QueryWithRead(query, varToken)));
});
queriesWithReads.forEach((queryWithRead) => {
var value: o.Expression;
if (isPresent(queryWithRead.read.identifier)) {
@ -200,14 +194,15 @@ export class CompileElement extends CompileNode {
});
if (isPresent(this.component)) {
var componentConstructorViewQueryList =
isPresent(this.component) ? o.literalArr(this._componentConstructorViewQueryLists) :
o.NULL_EXPR;
var componentConstructorViewQueryList = isPresent(this.component) ?
o.literalArr(this._componentConstructorViewQueryLists) :
o.NULL_EXPR;
var compExpr = isPresent(this.getComponent()) ? this.getComponent() : o.NULL_EXPR;
this.view.createMethod.addStmt(
this.appElement.callMethod(
'initComponent',
[compExpr, componentConstructorViewQueryList, this._compViewExpr])
this.appElement
.callMethod(
'initComponent',
[compExpr, componentConstructorViewQueryList, this._compViewExpr])
.toStmt());
}
}
@ -229,9 +224,9 @@ export class CompileElement extends CompileNode {
});
this._queries.values().forEach(
(queries) =>
queries.forEach((query) => query.afterChildren(this.view.createMethod,
this.view.updateContentQueriesMethod)));
(queries) => queries.forEach(
(query) =>
query.afterChildren(this.view.createMethod, this.view.updateContentQueriesMethod)));
}
addContentNode(ngContentIndex: number, nodeExpr: o.Expression) {
@ -256,8 +251,8 @@ export class CompileElement extends CompileNode {
while (!currentEl.isNull()) {
queries = currentEl._queries.get(token);
if (isPresent(queries)) {
ListWrapper.addAll(result,
queries.filter((query) => query.meta.descendants || distance <= 1));
ListWrapper.addAll(
result, queries.filter((query) => query.meta.descendants || distance <= 1));
}
if (currentEl._directives.length > 0) {
distance++;
@ -271,8 +266,8 @@ export class CompileElement extends CompileNode {
return result;
}
private _addQuery(queryMeta: CompileQueryMetadata,
directiveInstance: o.Expression): CompileQuery {
private _addQuery(queryMeta: CompileQueryMetadata, directiveInstance: o.Expression):
CompileQuery {
var propName = `_query_${queryMeta.selectors[0].name}_${this.nodeIndex}_${this._queryCount++}`;
var queryList = createQueryList(queryMeta, directiveInstance, propName, this.view);
var query = new CompileQuery(queryMeta, queryList, directiveInstance, this.view);
@ -280,8 +275,8 @@ export class CompileElement extends CompileNode {
return query;
}
private _getLocalDependency(requestingProviderType: ProviderAstType,
dep: CompileDiDependencyMetadata): o.Expression {
private _getLocalDependency(
requestingProviderType: ProviderAstType, dep: CompileDiDependencyMetadata): o.Expression {
var result: any /** TODO #9100 */ = null;
// constructor content query
if (isBlank(result) && isPresent(dep.query)) {
@ -316,8 +311,8 @@ export class CompileElement extends CompileNode {
return result;
}
private _getDependency(requestingProviderType: ProviderAstType,
dep: CompileDiDependencyMetadata): o.Expression {
private _getDependency(requestingProviderType: ProviderAstType, dep: CompileDiDependencyMetadata):
o.Expression {
var currElement: CompileElement = this;
var result: any /** TODO #9100 */ = null;
if (dep.isValue) {
@ -329,8 +324,8 @@ export class CompileElement extends CompileNode {
// check parent elements
while (isBlank(result) && !currElement.parent.isNull()) {
currElement = currElement.parent;
result = currElement._getLocalDependency(ProviderAstType.PublicService,
new CompileDiDependencyMetadata({token: dep.token}));
result = currElement._getLocalDependency(
ProviderAstType.PublicService, new CompileDiDependencyMetadata({token: dep.token}));
}
if (isBlank(result)) {
@ -343,9 +338,9 @@ export class CompileElement extends CompileNode {
}
}
function createInjectInternalCondition(nodeIndex: number, childNodeCount: number,
provider: ProviderAst,
providerExpr: o.Expression): o.Statement {
function createInjectInternalCondition(
nodeIndex: number, childNodeCount: number, provider: ProviderAst,
providerExpr: o.Expression): o.Statement {
var indexCondition: any /** TODO #9100 */;
if (childNodeCount > 0) {
indexCondition = o.literal(nodeIndex)
@ -360,9 +355,9 @@ function createInjectInternalCondition(nodeIndex: number, childNodeCount: number
[new o.ReturnStatement(providerExpr)]);
}
function createProviderProperty(propName: string, provider: ProviderAst,
providerValueExpressions: o.Expression[], isMulti: boolean,
isEager: boolean, compileElement: CompileElement): o.Expression {
function createProviderProperty(
propName: string, provider: ProviderAst, providerValueExpressions: o.Expression[],
isMulti: boolean, isEager: boolean, compileElement: CompileElement): o.Expression {
var view = compileElement.view;
var resolvedProviderValueExpr: any /** TODO #9100 */;
var type: any /** TODO #9100 */;
@ -385,9 +380,9 @@ function createProviderProperty(propName: string, provider: ProviderAst,
var getter = new CompileMethod(view);
getter.resetDebugInfo(compileElement.nodeIndex, compileElement.sourceAst);
// Note: Equals is important for JS so that it also checks the undefined case!
getter.addStmt(
new o.IfStmt(o.THIS_EXPR.prop(internalField).isBlank(),
[o.THIS_EXPR.prop(internalField).set(resolvedProviderValueExpr).toStmt()]));
getter.addStmt(new o.IfStmt(
o.THIS_EXPR.prop(internalField).isBlank(),
[o.THIS_EXPR.prop(internalField).set(resolvedProviderValueExpr).toStmt()]));
getter.addStmt(new o.ReturnStatement(o.THIS_EXPR.prop(internalField)));
view.getters.push(new o.ClassGetter(propName, getter.finish(), type));
}
@ -411,8 +406,9 @@ class _ValueOutputAstTransformer extends ValueTransformer {
}
visitStringMap(map: {[key: string]: any}, context: any): o.Expression {
var entries: any[] /** TODO #9100 */ = [];
StringMapWrapper.forEach(
map, (value: any /** TODO #9100 */, key: any /** TODO #9100 */) => { entries.push([key, visitValue(value, this, context)]); });
StringMapWrapper.forEach(map, (value: any /** TODO #9100 */, key: any /** TODO #9100 */) => {
entries.push([key, visitValue(value, this, context)]);
});
return o.literalMap(entries);
}
visitPrimitive(value: any, context: any): o.Expression { return o.literal(value); }

View File

@ -1,6 +1,5 @@
import {isPresent} from '../facade/lang';
import {ListWrapper} from '../facade/collection';
import {isPresent} from '../facade/lang';
import * as o from '../output/output_ast';
import {TemplateAst} from '../template_ast';

View File

@ -1,10 +1,11 @@
import {isBlank, isPresent} from '../facade/lang';
import {BaseException} from '../facade/exceptions';
import * as o from '../output/output_ast';
import {CompileView} from './compile_view';
import {CompilePipeMetadata} from '../compile_metadata';
import {BaseException} from '../facade/exceptions';
import {isBlank, isPresent} from '../facade/lang';
import {Identifiers, identifierToken} from '../identifiers';
import {injectFromViewParentInjector, createPureProxy, getPropertyInView} from './util';
import * as o from '../output/output_ast';
import {CompileView} from './compile_view';
import {createPureProxy, getPropertyInView, injectFromViewParentInjector} from './util';
class _PurePipeProxy {
constructor(public view: CompileView, public instance: o.ReadPropExpr, public argCount: number) {}
@ -55,9 +56,10 @@ export class CompilePipe {
this._purePipeProxies.forEach((purePipeProxy) => {
var pipeInstanceSeenFromPureProxy =
getPropertyInView(this.instance, purePipeProxy.view, this.view);
createPureProxy(pipeInstanceSeenFromPureProxy.prop('transform')
.callMethod(o.BuiltinMethod.bind, [pipeInstanceSeenFromPureProxy]),
purePipeProxy.argCount, purePipeProxy.instance, purePipeProxy.view);
createPureProxy(
pipeInstanceSeenFromPureProxy.prop('transform')
.callMethod(o.BuiltinMethod.bind, [pipeInstanceSeenFromPureProxy]),
purePipeProxy.argCount, purePipeProxy.instance, purePipeProxy.view);
});
}

View File

@ -1,25 +1,24 @@
import {isPresent, isBlank} from '../facade/lang';
import {ListWrapper} from '../facade/collection';
import * as o from '../output/output_ast';
import {Identifiers} from '../identifiers';
import {CompileQueryMetadata, CompileTokenMap} from '../compile_metadata';
import {ListWrapper} from '../facade/collection';
import {isBlank, isPresent} from '../facade/lang';
import {Identifiers} from '../identifiers';
import * as o from '../output/output_ast';
import {CompileView} from './compile_view';
import {CompileElement} from './compile_element';
import {CompileMethod} from './compile_method';
import {CompileView} from './compile_view';
import {getPropertyInView} from './util';
class ViewQueryValues {
constructor(public view: CompileView, public values: Array<o.Expression | ViewQueryValues>) {}
constructor(public view: CompileView, public values: Array<o.Expression|ViewQueryValues>) {}
}
export class CompileQuery {
private _values: ViewQueryValues;
constructor(public meta: CompileQueryMetadata, public queryList: o.Expression,
public ownerDirectiveExpression: o.Expression, public view: CompileView) {
constructor(
public meta: CompileQueryMetadata, public queryList: o.Expression,
public ownerDirectiveExpression: o.Expression, public view: CompileView) {
this._values = new ViewQueryValues(view, []);
}
@ -83,28 +82,30 @@ export class CompileQuery {
function createQueryValues(viewValues: ViewQueryValues): o.Expression[] {
return ListWrapper.flatten(viewValues.values.map((entry) => {
if (entry instanceof ViewQueryValues) {
return mapNestedViews(entry.view.declarationElement.appElement, entry.view,
createQueryValues(entry));
return mapNestedViews(
entry.view.declarationElement.appElement, entry.view, createQueryValues(entry));
} else {
return <o.Expression>entry;
}
}));
}
function mapNestedViews(declarationAppElement: o.Expression, view: CompileView,
expressions: o.Expression[]): o.Expression {
function mapNestedViews(
declarationAppElement: o.Expression, view: CompileView,
expressions: o.Expression[]): o.Expression {
var adjustedExpressions: o.Expression[] = expressions.map((expr) => {
return o.replaceVarInExpression(o.THIS_EXPR.name, o.variable('nestedView'), expr);
});
return declarationAppElement.callMethod('mapNestedViews', [
o.variable(view.className),
o.fn([new o.FnParam('nestedView', view.classType)],
[new o.ReturnStatement(o.literalArr(adjustedExpressions))])
o.variable(view.className), o.fn(
[new o.FnParam('nestedView', view.classType)],
[new o.ReturnStatement(o.literalArr(adjustedExpressions))])
]);
}
export function createQueryList(query: CompileQueryMetadata, directiveInstance: o.Expression,
propertyName: string, compileView: CompileView): o.Expression {
export function createQueryList(
query: CompileQueryMetadata, directiveInstance: o.Expression, propertyName: string,
compileView: CompileView): o.Expression {
compileView.fields.push(new o.ClassField(propertyName, o.importType(Identifiers.QueryList)));
var expr = o.THIS_EXPR.prop(propertyName);
compileView.createMethod.addStmt(o.THIS_EXPR.prop(propertyName)

View File

@ -1,33 +1,20 @@
import {ViewType} from '../../core_private';
import {isPresent, isBlank} from '../facade/lang';
import {CompiledAnimation} from '../animation/animation_compiler';
import {CompileDirectiveMetadata, CompileIdentifierMetadata, CompilePipeMetadata, CompileTokenMap} from '../compile_metadata';
import {CompilerConfig} from '../config';
import {ListWrapper} from '../facade/collection';
import {isBlank, isPresent} from '../facade/lang';
import {Identifiers} from '../identifiers';
import * as o from '../output/output_ast';
import {EventHandlerVars} from './constants';
import {CompileQuery, createQueryList, addQueryToTokenMap} from './compile_query';
import {NameResolver} from './expression_converter';
import {CompileBinding} from './compile_binding';
import {CompileElement, CompileNode} from './compile_element';
import {CompileMethod} from './compile_method';
import {CompilePipe} from './compile_pipe';
import {
CompileDirectiveMetadata,
CompilePipeMetadata,
CompileIdentifierMetadata,
CompileTokenMap
} from '../compile_metadata';
import {
getViewFactoryName,
injectFromViewParentInjector,
createDiTokenExpression,
getPropertyInView,
createPureProxy
} from './util';
import {CompilerConfig} from '../config';
import {CompileBinding} from './compile_binding';
import {Identifiers} from '../identifiers';
import {CompiledAnimation} from '../animation/animation_compiler';
import {CompileQuery, addQueryToTokenMap, createQueryList} from './compile_query';
import {EventHandlerVars} from './constants';
import {NameResolver} from './expression_converter';
import {createDiTokenExpression, createPureProxy, getPropertyInView, getViewFactoryName, injectFromViewParentInjector} from './util';
export class CompileView implements NameResolver {
public viewType: ViewType;
@ -73,12 +60,11 @@ export class CompileView implements NameResolver {
public componentContext: o.Expression;
constructor(public component: CompileDirectiveMetadata, public genConfig: CompilerConfig,
public pipeMetas: CompilePipeMetadata[],
public styles: o.Expression,
animations: CompiledAnimation[],
public viewIndex: number, public declarationElement: CompileElement,
public templateVariableBindings: string[][]) {
constructor(
public component: CompileDirectiveMetadata, public genConfig: CompilerConfig,
public pipeMetas: CompilePipeMetadata[], public styles: o.Expression,
animations: CompiledAnimation[], public viewIndex: number,
public declarationElement: CompileElement, public templateVariableBindings: string[][]) {
animations.forEach(entry => this.animations.set(entry.name, entry));
this.createMethod = new CompileMethod(this);
this.injectorGetMethod = new CompileMethod(this);
@ -167,19 +153,21 @@ export class CompileView implements NameResolver {
proxyParams.push(new o.FnParam(paramName));
proxyReturnEntries.push(o.variable(paramName));
}
createPureProxy(o.fn(proxyParams, [new o.ReturnStatement(o.literalArr(proxyReturnEntries))],
new o.ArrayType(o.DYNAMIC_TYPE)),
values.length, proxyExpr, this);
createPureProxy(
o.fn(
proxyParams, [new o.ReturnStatement(o.literalArr(proxyReturnEntries))],
new o.ArrayType(o.DYNAMIC_TYPE)),
values.length, proxyExpr, this);
return proxyExpr.callFn(values);
}
createLiteralMap(entries: Array<Array<string | o.Expression>>): o.Expression {
createLiteralMap(entries: Array<Array<string|o.Expression>>): o.Expression {
if (entries.length === 0) {
return o.importExpr(Identifiers.EMPTY_MAP);
}
var proxyExpr = o.THIS_EXPR.prop(`_map_${this.literalMapCount++}`);
var proxyParams: o.FnParam[] = [];
var proxyReturnEntries: Array<Array<string | o.Expression>> = [];
var proxyReturnEntries: Array<Array<string|o.Expression>> = [];
var values: o.Expression[] = [];
for (var i = 0; i < entries.length; i++) {
var paramName = `p${i}`;
@ -187,9 +175,11 @@ export class CompileView implements NameResolver {
proxyReturnEntries.push([entries[i][0], o.variable(paramName)]);
values.push(<o.Expression>entries[i][1]);
}
createPureProxy(o.fn(proxyParams, [new o.ReturnStatement(o.literalMap(proxyReturnEntries))],
new o.MapType(o.DYNAMIC_TYPE)),
entries.length, proxyExpr, this);
createPureProxy(
o.fn(
proxyParams, [new o.ReturnStatement(o.literalMap(proxyReturnEntries))],
new o.MapType(o.DYNAMIC_TYPE)),
entries.length, proxyExpr, this);
return proxyExpr.callFn(values);
}

View File

@ -1,10 +1,10 @@
import {ChangeDetectionStrategy, ViewEncapsulation} from '@angular/core';
import {ChangeDetectorState, ViewType} from '../../core_private';
import {isBlank, resolveEnumToken} from '../facade/lang';
import {ChangeDetectorState, ViewType} from '../../core_private';
import {CompileIdentifierMetadata} from '../compile_metadata';
import * as o from '../output/output_ast';
import {isBlank, resolveEnumToken} from '../facade/lang';
import {Identifiers} from '../identifiers';
import * as o from '../output/output_ast';
function _enumExpression(classIdentifier: CompileIdentifierMetadata, value: any): o.Expression {
if (isBlank(value)) return o.NULL_EXPR;

View File

@ -1,17 +1,14 @@
import {isBlank, isPresent, StringWrapper} from '../facade/lang';
import {CompileDirectiveMetadata} from '../compile_metadata';
import {ListWrapper, StringMapWrapper} from '../facade/collection';
import {EventHandlerVars, ViewProperties} from './constants';
import {StringWrapper, isBlank, isPresent} from '../facade/lang';
import * as o from '../output/output_ast';
import {BoundEventAst, DirectiveAst} from '../template_ast';
import {CompileBinding} from './compile_binding';
import {CompileElement} from './compile_element';
import {CompileMethod} from './compile_method';
import {BoundEventAst, DirectiveAst} from '../template_ast';
import {CompileDirectiveMetadata} from '../compile_metadata';
import {EventHandlerVars, ViewProperties} from './constants';
import {convertCdStatementToIr} from './expression_converter';
import {CompileBinding} from './compile_binding';
export class CompileEventListener {
private _method: CompileMethod;
@ -20,30 +17,33 @@ export class CompileEventListener {
private _eventParam: o.FnParam;
private _actionResultExprs: o.Expression[] = [];
static getOrCreate(compileElement: CompileElement, eventTarget: string, eventName: string,
targetEventListeners: CompileEventListener[]): CompileEventListener {
var listener = targetEventListeners.find(listener => listener.eventTarget == eventTarget &&
listener.eventName == eventName);
static getOrCreate(
compileElement: CompileElement, eventTarget: string, eventName: string,
targetEventListeners: CompileEventListener[]): CompileEventListener {
var listener = targetEventListeners.find(
listener => listener.eventTarget == eventTarget && listener.eventName == eventName);
if (isBlank(listener)) {
listener = new CompileEventListener(compileElement, eventTarget, eventName,
targetEventListeners.length);
listener = new CompileEventListener(
compileElement, eventTarget, eventName, targetEventListeners.length);
targetEventListeners.push(listener);
}
return listener;
}
constructor(public compileElement: CompileElement, public eventTarget: string,
public eventName: string, listenerIndex: number) {
constructor(
public compileElement: CompileElement, public eventTarget: string, public eventName: string,
listenerIndex: number) {
this._method = new CompileMethod(compileElement.view);
this._methodName =
`_handle_${santitizeEventName(eventName)}_${compileElement.nodeIndex}_${listenerIndex}`;
this._eventParam =
new o.FnParam(EventHandlerVars.event.name,
o.importType(this.compileElement.view.genConfig.renderTypes.renderEvent));
this._eventParam = new o.FnParam(
EventHandlerVars.event.name,
o.importType(this.compileElement.view.genConfig.renderTypes.renderEvent));
}
addAction(hostEvent: BoundEventAst, directive: CompileDirectiveMetadata,
directiveInstance: o.Expression) {
addAction(
hostEvent: BoundEventAst, directive: CompileDirectiveMetadata,
directiveInstance: o.Expression) {
if (isPresent(directive) && directive.isComponent) {
this._hasComponentHostListener = true;
}
@ -70,8 +70,8 @@ export class CompileEventListener {
finishMethod() {
var markPathToRootStart = this._hasComponentHostListener ?
this.compileElement.appElement.prop('componentView') :
o.THIS_EXPR;
this.compileElement.appElement.prop('componentView') :
o.THIS_EXPR;
var resultExpr: o.Expression = o.literal(true);
this._actionResultExprs.forEach((expr) => { resultExpr = resultExpr.and(expr); });
var stmts =
@ -109,27 +109,29 @@ export class CompileEventListener {
'eventHandler',
[o.THIS_EXPR.prop(this._methodName).callMethod(o.BuiltinMethod.bind, [o.THIS_EXPR])]);
this.compileElement.view.createMethod.addStmt(
subscription.set(directiveInstance.prop(observablePropName)
.callMethod(o.BuiltinMethod.SubscribeObservable, [eventListener]))
subscription
.set(directiveInstance.prop(observablePropName)
.callMethod(o.BuiltinMethod.SubscribeObservable, [eventListener]))
.toDeclStmt(null, [o.StmtModifier.Final]));
}
}
export function collectEventListeners(hostEvents: BoundEventAst[], dirs: DirectiveAst[],
compileElement: CompileElement): CompileEventListener[] {
export function collectEventListeners(
hostEvents: BoundEventAst[], dirs: DirectiveAst[],
compileElement: CompileElement): CompileEventListener[] {
var eventListeners: CompileEventListener[] = [];
hostEvents.forEach((hostEvent) => {
compileElement.view.bindings.push(new CompileBinding(compileElement, hostEvent));
var listener = CompileEventListener.getOrCreate(compileElement, hostEvent.target,
hostEvent.name, eventListeners);
var listener = CompileEventListener.getOrCreate(
compileElement, hostEvent.target, hostEvent.name, eventListeners);
listener.addAction(hostEvent, null, null);
});
ListWrapper.forEachWithIndex(dirs, (directiveAst, i) => {
var directiveInstance = compileElement.directiveInstances[i];
directiveAst.hostEvents.forEach((hostEvent) => {
compileElement.view.bindings.push(new CompileBinding(compileElement, hostEvent));
var listener = CompileEventListener.getOrCreate(compileElement, hostEvent.target,
hostEvent.name, eventListeners);
var listener = CompileEventListener.getOrCreate(
compileElement, hostEvent.target, hostEvent.name, eventListeners);
listener.addAction(hostEvent, directiveAst.directive, directiveInstance);
});
});
@ -137,13 +139,16 @@ export function collectEventListeners(hostEvents: BoundEventAst[], dirs: Directi
return eventListeners;
}
export function bindDirectiveOutputs(directiveAst: DirectiveAst, directiveInstance: o.Expression,
eventListeners: CompileEventListener[]) {
StringMapWrapper.forEach(directiveAst.directive.outputs, (eventName: any /** TODO #9100 */, observablePropName: any /** TODO #9100 */) => {
eventListeners.filter(listener => listener.eventName == eventName)
.forEach(
(listener) => { listener.listenToDirective(directiveInstance, observablePropName); });
});
export function bindDirectiveOutputs(
directiveAst: DirectiveAst, directiveInstance: o.Expression,
eventListeners: CompileEventListener[]) {
StringMapWrapper.forEach(
directiveAst.directive.outputs,
(eventName: any /** TODO #9100 */, observablePropName: any /** TODO #9100 */) => {
eventListeners.filter(listener => listener.eventName == eventName).forEach((listener) => {
listener.listenToDirective(directiveInstance, observablePropName);
});
});
}
export function bindRenderOutputs(eventListeners: CompileEventListener[]) {

View File

@ -1,9 +1,8 @@
import {BaseException} from '../facade/exceptions';
import {isBlank, isPresent, isArray} from '../facade/lang';
import * as cdAst from '../expression_parser/ast';
import * as o from '../output/output_ast';
import {BaseException} from '../facade/exceptions';
import {isArray, isBlank, isPresent} from '../facade/lang';
import {Identifiers} from '../identifiers';
import * as o from '../output/output_ast';
var IMPLICIT_RECEIVER = o.variable('#implicit');
@ -11,7 +10,7 @@ export interface NameResolver {
callPipe(name: string, input: o.Expression, args: o.Expression[]): o.Expression;
getLocal(name: string): o.Expression;
createLiteralArray(values: o.Expression[]): o.Expression;
createLiteralMap(values: Array<Array<string | o.Expression>>): o.Expression;
createLiteralMap(values: Array<Array<string|o.Expression>>): o.Expression;
}
export class ExpressionWithWrappedValueInfo {
@ -26,8 +25,8 @@ export function convertCdExpressionToIr(
return new ExpressionWithWrappedValueInfo(irAst, visitor.needsValueUnwrapper);
}
export function convertCdStatementToIr(nameResolver: NameResolver, implicitReceiver: o.Expression,
stmt: cdAst.AST): o.Statement[] {
export function convertCdStatementToIr(
nameResolver: NameResolver, implicitReceiver: o.Expression, stmt: cdAst.AST): o.Statement[] {
var visitor = new _AstToIrVisitor(nameResolver, implicitReceiver, null);
var statements: any[] /** TODO #9100 */ = [];
flattenStatements(stmt.visit(visitor, _Mode.Statement), statements);
@ -51,7 +50,7 @@ function ensureExpressionMode(mode: _Mode, ast: cdAst.AST) {
}
}
function convertToStatementIfNeeded(mode: _Mode, expr: o.Expression): o.Expression | o.Statement {
function convertToStatementIfNeeded(mode: _Mode, expr: o.Expression): o.Expression|o.Statement {
if (mode === _Mode.Statement) {
return expr.toStmt();
} else {
@ -62,8 +61,9 @@ function convertToStatementIfNeeded(mode: _Mode, expr: o.Expression): o.Expressi
class _AstToIrVisitor implements cdAst.AstVisitor {
public needsValueUnwrapper: boolean = false;
constructor(private _nameResolver: NameResolver, private _implicitReceiver: o.Expression,
private _valueUnwrapper: o.ReadVarExpr) {}
constructor(
private _nameResolver: NameResolver, private _implicitReceiver: o.Expression,
private _valueUnwrapper: o.ReadVarExpr) {}
visitBinary(ast: cdAst.Binary, mode: _Mode): any {
var op: any /** TODO #9100 */;
@ -118,8 +118,9 @@ class _AstToIrVisitor implements cdAst.AstVisitor {
}
return convertToStatementIfNeeded(
mode, new o.BinaryOperatorExpr(op, ast.left.visit(this, _Mode.Expression),
ast.right.visit(this, _Mode.Expression)));
mode,
new o.BinaryOperatorExpr(
op, ast.left.visit(this, _Mode.Expression), ast.right.visit(this, _Mode.Expression)));
}
visitChain(ast: cdAst.Chain, mode: _Mode): any {
ensureStatementMode(mode, ast);
@ -128,8 +129,9 @@ class _AstToIrVisitor implements cdAst.AstVisitor {
visitConditional(ast: cdAst.Conditional, mode: _Mode): any {
var value: o.Expression = ast.condition.visit(this, _Mode.Expression);
return convertToStatementIfNeeded(
mode, value.conditional(ast.trueExp.visit(this, _Mode.Expression),
ast.falseExp.visit(this, _Mode.Expression)));
mode,
value.conditional(
ast.trueExp.visit(this, _Mode.Expression), ast.falseExp.visit(this, _Mode.Expression)));
}
visitPipe(ast: cdAst.BindingPipe, mode: _Mode): any {
var input = ast.exp.visit(this, _Mode.Expression);
@ -139,8 +141,9 @@ class _AstToIrVisitor implements cdAst.AstVisitor {
return convertToStatementIfNeeded(mode, this._valueUnwrapper.callMethod('unwrap', [value]));
}
visitFunctionCall(ast: cdAst.FunctionCall, mode: _Mode): any {
return convertToStatementIfNeeded(mode, ast.target.visit(this, _Mode.Expression)
.callFn(this.visitAll(ast.args, _Mode.Expression)));
return convertToStatementIfNeeded(
mode,
ast.target.visit(this, _Mode.Expression).callFn(this.visitAll(ast.args, _Mode.Expression)));
}
visitImplicitReceiver(ast: cdAst.ImplicitReceiver, mode: _Mode): any {
ensureExpressionMode(mode, ast);

View File

@ -1,10 +1,11 @@
import {LifecycleHooks} from '../../core_private';
import * as o from '../output/output_ast';
import {DetectChangesVars, ChangeDetectorStateEnum} from './constants';
import {CompileDirectiveMetadata, CompilePipeMetadata} from '../compile_metadata';
import * as o from '../output/output_ast';
import {DirectiveAst} from '../template_ast';
import {CompileElement} from './compile_element';
import {CompileView} from './compile_view';
import {ChangeDetectorStateEnum, DetectChangesVars} from './constants';
@ -23,9 +24,9 @@ export function bindDirectiveDetectChangesLifecycleCallbacks(
[directiveInstance.callMethod('ngOnChanges', [DetectChangesVars.changes]).toStmt()]));
}
if (lifecycleHooks.indexOf(LifecycleHooks.OnInit) !== -1) {
detectChangesInInputsMethod.addStmt(
new o.IfStmt(STATE_IS_NEVER_CHECKED.and(NOT_THROW_ON_CHANGES),
[directiveInstance.callMethod('ngOnInit', []).toStmt()]));
detectChangesInInputsMethod.addStmt(new o.IfStmt(
STATE_IS_NEVER_CHECKED.and(NOT_THROW_ON_CHANGES),
[directiveInstance.callMethod('ngOnInit', []).toStmt()]));
}
if (lifecycleHooks.indexOf(LifecycleHooks.DoCheck) !== -1) {
detectChangesInInputsMethod.addStmt(new o.IfStmt(
@ -33,14 +34,14 @@ export function bindDirectiveDetectChangesLifecycleCallbacks(
}
}
export function bindDirectiveAfterContentLifecycleCallbacks(directiveMeta: CompileDirectiveMetadata,
directiveInstance: o.Expression,
compileElement: CompileElement) {
export function bindDirectiveAfterContentLifecycleCallbacks(
directiveMeta: CompileDirectiveMetadata, directiveInstance: o.Expression,
compileElement: CompileElement) {
var view = compileElement.view;
var lifecycleHooks = directiveMeta.lifecycleHooks;
var afterContentLifecycleCallbacksMethod = view.afterContentLifecycleCallbacksMethod;
afterContentLifecycleCallbacksMethod.resetDebugInfo(compileElement.nodeIndex,
compileElement.sourceAst);
afterContentLifecycleCallbacksMethod.resetDebugInfo(
compileElement.nodeIndex, compileElement.sourceAst);
if (lifecycleHooks.indexOf(LifecycleHooks.AfterContentInit) !== -1) {
afterContentLifecycleCallbacksMethod.addStmt(new o.IfStmt(
STATE_IS_NEVER_CHECKED, [directiveInstance.callMethod('ngAfterContentInit', []).toStmt()]));
@ -51,14 +52,14 @@ export function bindDirectiveAfterContentLifecycleCallbacks(directiveMeta: Compi
}
}
export function bindDirectiveAfterViewLifecycleCallbacks(directiveMeta: CompileDirectiveMetadata,
directiveInstance: o.Expression,
compileElement: CompileElement) {
export function bindDirectiveAfterViewLifecycleCallbacks(
directiveMeta: CompileDirectiveMetadata, directiveInstance: o.Expression,
compileElement: CompileElement) {
var view = compileElement.view;
var lifecycleHooks = directiveMeta.lifecycleHooks;
var afterViewLifecycleCallbacksMethod = view.afterViewLifecycleCallbacksMethod;
afterViewLifecycleCallbacksMethod.resetDebugInfo(compileElement.nodeIndex,
compileElement.sourceAst);
afterViewLifecycleCallbacksMethod.resetDebugInfo(
compileElement.nodeIndex, compileElement.sourceAst);
if (lifecycleHooks.indexOf(LifecycleHooks.AfterViewInit) !== -1) {
afterViewLifecycleCallbacksMethod.addStmt(new o.IfStmt(
STATE_IS_NEVER_CHECKED, [directiveInstance.callMethod('ngAfterViewInit', []).toStmt()]));
@ -69,9 +70,9 @@ export function bindDirectiveAfterViewLifecycleCallbacks(directiveMeta: CompileD
}
}
export function bindDirectiveDestroyLifecycleCallbacks(directiveMeta: CompileDirectiveMetadata,
directiveInstance: o.Expression,
compileElement: CompileElement) {
export function bindDirectiveDestroyLifecycleCallbacks(
directiveMeta: CompileDirectiveMetadata, directiveInstance: o.Expression,
compileElement: CompileElement) {
var onDestroyMethod = compileElement.view.destroyMethod;
onDestroyMethod.resetDebugInfo(compileElement.nodeIndex, compileElement.sourceAst);
if (directiveMeta.lifecycleHooks.indexOf(LifecycleHooks.OnDestroy) !== -1) {
@ -79,8 +80,8 @@ export function bindDirectiveDestroyLifecycleCallbacks(directiveMeta: CompileDir
}
}
export function bindPipeDestroyLifecycleCallbacks(pipeMeta: CompilePipeMetadata,
pipeInstance: o.Expression, view: CompileView) {
export function bindPipeDestroyLifecycleCallbacks(
pipeMeta: CompilePipeMetadata, pipeInstance: o.Expression, view: CompileView) {
var onDestroyMethod = view.destroyMethod;
if (pipeMeta.lifecycleHooks.indexOf(LifecycleHooks.OnDestroy) !== -1) {
onDestroyMethod.addStmt(pipeInstance.callMethod('ngOnDestroy', []).toStmt());

View File

@ -1,18 +1,12 @@
import {EMPTY_STATE as EMPTY_ANIMATION_STATE, LifecycleHooks, isDefaultChangeDetectionStrategy, SecurityContext} from '../../core_private';
import {isBlank, isPresent} from '../facade/lang';
import {EMPTY_STATE as EMPTY_ANIMATION_STATE, LifecycleHooks, SecurityContext, isDefaultChangeDetectionStrategy} from '../../core_private';
import * as cdAst from '../expression_parser/ast';
import * as o from '../output/output_ast';
import {isBlank, isPresent} from '../facade/lang';
import {Identifiers} from '../identifiers';
import * as o from '../output/output_ast';
import {DetectChangesVars, ViewProperties} from './constants';
import {
BoundTextAst,
BoundElementPropertyAst,
DirectiveAst,
PropertyBindingType,
} from '../template_ast';
import {BoundTextAst, BoundElementPropertyAst, DirectiveAst, PropertyBindingType,} from '../template_ast';
import {CompileView} from './compile_view';
import {CompileElement, CompileNode} from './compile_element';
@ -34,9 +28,10 @@ function createCurrValueExpr(exprIndex: number): o.ReadVarExpr {
return o.variable(`currVal_${exprIndex}`); // fix syntax highlighting: `
}
function bind(view: CompileView, currValExpr: o.ReadVarExpr, fieldExpr: o.ReadPropExpr,
parsedExpression: cdAst.AST, context: o.Expression, actions: o.Statement[],
method: CompileMethod) {
function bind(
view: CompileView, currValExpr: o.ReadVarExpr, fieldExpr: o.ReadPropExpr,
parsedExpression: cdAst.AST, context: o.Expression, actions: o.Statement[],
method: CompileMethod) {
var checkExpression =
convertCdExpressionToIr(view, context, parsedExpression, DetectChangesVars.valUnwrapper);
if (isBlank(checkExpression.expression)) {
@ -56,9 +51,9 @@ function bind(view: CompileView, currValExpr: o.ReadVarExpr, fieldExpr: o.ReadPr
method.addStmt(
currValExpr.set(checkExpression.expression).toDeclStmt(null, [o.StmtModifier.Final]));
var condition: o.Expression =
o.importExpr(Identifiers.checkBinding)
.callFn([DetectChangesVars.throwOnChange, fieldExpr, currValExpr]);
var condition: o.Expression = o.importExpr(Identifiers.checkBinding).callFn([
DetectChangesVars.throwOnChange, fieldExpr, currValExpr
]);
if (checkExpression.needsValueUnwrapper) {
condition = DetectChangesVars.valUnwrapper.prop('hasWrappedValue').or(condition);
}
@ -67,25 +62,24 @@ function bind(view: CompileView, currValExpr: o.ReadVarExpr, fieldExpr: o.ReadPr
actions.concat([<o.Statement>o.THIS_EXPR.prop(fieldExpr.name).set(currValExpr).toStmt()])));
}
export function bindRenderText(boundText: BoundTextAst, compileNode: CompileNode,
view: CompileView) {
export function bindRenderText(
boundText: BoundTextAst, compileNode: CompileNode, view: CompileView) {
var bindingIndex = view.bindings.length;
view.bindings.push(new CompileBinding(compileNode, boundText));
var currValExpr = createCurrValueExpr(bindingIndex);
var valueField = createBindFieldExpr(bindingIndex);
view.detectChangesRenderPropertiesMethod.resetDebugInfo(compileNode.nodeIndex, boundText);
bind(view, currValExpr, valueField, boundText.value, view.componentContext,
[
o.THIS_EXPR.prop('renderer')
.callMethod('setText', [compileNode.renderNode, currValExpr])
.toStmt()
],
view.detectChangesRenderPropertiesMethod);
bind(
view, currValExpr, valueField, boundText.value, view.componentContext,
[o.THIS_EXPR.prop('renderer')
.callMethod('setText', [compileNode.renderNode, currValExpr])
.toStmt()],
view.detectChangesRenderPropertiesMethod);
}
function bindAndWriteToRenderer(boundProps: BoundElementPropertyAst[], context: o.Expression,
compileElement: CompileElement) {
function bindAndWriteToRenderer(
boundProps: BoundElementPropertyAst[], context: o.Expression, compileElement: CompileElement) {
var view = compileElement.view;
var renderNode = compileElement.renderNode;
boundProps.forEach((boundProp) => {
@ -105,24 +99,24 @@ function bindAndWriteToRenderer(boundProps: BoundElementPropertyAst[], context:
}
updateStmts.push(
o.THIS_EXPR.prop('renderer')
.callMethod('setElementProperty', [renderNode, o.literal(boundProp.name), renderValue])
.toStmt()
);
.callMethod(
'setElementProperty', [renderNode, o.literal(boundProp.name), renderValue])
.toStmt());
break;
case PropertyBindingType.Attribute:
renderValue = renderValue.isBlank().conditional(o.NULL_EXPR, renderValue.callMethod('toString', []));
renderValue =
renderValue.isBlank().conditional(o.NULL_EXPR, renderValue.callMethod('toString', []));
updateStmts.push(
o.THIS_EXPR.prop('renderer')
.callMethod('setElementAttribute', [renderNode, o.literal(boundProp.name), renderValue])
.toStmt()
);
.callMethod(
'setElementAttribute', [renderNode, o.literal(boundProp.name), renderValue])
.toStmt());
break;
case PropertyBindingType.Class:
updateStmts.push(
o.THIS_EXPR.prop('renderer')
.callMethod('setElementClass', [renderNode, o.literal(boundProp.name), renderValue])
.toStmt()
);
.toStmt());
break;
case PropertyBindingType.Style:
var strValue: o.Expression = renderValue.callMethod('toString', []);
@ -133,14 +127,14 @@ function bindAndWriteToRenderer(boundProps: BoundElementPropertyAst[], context:
updateStmts.push(
o.THIS_EXPR.prop('renderer')
.callMethod('setElementStyle', [renderNode, o.literal(boundProp.name), renderValue])
.toStmt()
);
.toStmt());
break;
case PropertyBindingType.Animation:
var animationName = boundProp.name;
var animation = view.componentView.animations.get(animationName);
if (!isPresent(animation)) {
throw new BaseException(`Internal Error: couldn't find an animation entry for ${boundProp.name}`);
throw new BaseException(
`Internal Error: couldn't find an animation entry for ${boundProp.name}`);
}
// it's important to normalize the void value as `void` explicitly
@ -150,45 +144,36 @@ function bindAndWriteToRenderer(boundProps: BoundElementPropertyAst[], context:
// void => ...
var oldRenderVar = o.variable('oldRenderVar');
updateStmts.push(oldRenderVar.set(oldRenderValue).toDeclStmt());
updateStmts.push(
new o.IfStmt(oldRenderVar.equals(o.importExpr(Identifiers.uninitialized)), [
oldRenderVar.set(emptyStateValue).toStmt()
]));
updateStmts.push(new o.IfStmt(
oldRenderVar.equals(o.importExpr(Identifiers.uninitialized)),
[oldRenderVar.set(emptyStateValue).toStmt()]));
// ... => void
var newRenderVar = o.variable('newRenderVar');
updateStmts.push(newRenderVar.set(renderValue).toDeclStmt());
updateStmts.push(
new o.IfStmt(newRenderVar.equals(o.importExpr(Identifiers.uninitialized)), [
newRenderVar.set(emptyStateValue).toStmt()
]));
updateStmts.push(new o.IfStmt(
newRenderVar.equals(o.importExpr(Identifiers.uninitialized)),
[newRenderVar.set(emptyStateValue).toStmt()]));
updateStmts.push(
animation.fnVariable.callFn([
o.THIS_EXPR,
renderNode,
oldRenderVar,
newRenderVar
]).toStmt());
animation.fnVariable.callFn([o.THIS_EXPR, renderNode, oldRenderVar, newRenderVar])
.toStmt());
view.detachMethod.addStmt(
animation.fnVariable.callFn([
o.THIS_EXPR,
renderNode,
oldRenderValue,
emptyStateValue
]).toStmt());
animation.fnVariable.callFn([o.THIS_EXPR, renderNode, oldRenderValue, emptyStateValue])
.toStmt());
break;
}
bind(view, currValExpr, fieldExpr, boundProp.value, context, updateStmts,
view.detectChangesRenderPropertiesMethod);
bind(
view, currValExpr, fieldExpr, boundProp.value, context, updateStmts,
view.detectChangesRenderPropertiesMethod);
});
}
function sanitizedValue(boundProp: BoundElementPropertyAst,
renderValue: o.Expression): o.Expression {
function sanitizedValue(
boundProp: BoundElementPropertyAst, renderValue: o.Expression): o.Expression {
let enumValue: string;
switch (boundProp.securityContext) {
case SecurityContext.NONE:
@ -216,18 +201,19 @@ function sanitizedValue(boundProp: BoundElementPropertyAst,
return ctx.callMethod('sanitize', args);
}
export function bindRenderInputs(boundProps: BoundElementPropertyAst[],
compileElement: CompileElement): void {
export function bindRenderInputs(
boundProps: BoundElementPropertyAst[], compileElement: CompileElement): void {
bindAndWriteToRenderer(boundProps, compileElement.view.componentContext, compileElement);
}
export function bindDirectiveHostProps(directiveAst: DirectiveAst, directiveInstance: o.Expression,
compileElement: CompileElement): void {
export function bindDirectiveHostProps(
directiveAst: DirectiveAst, directiveInstance: o.Expression,
compileElement: CompileElement): void {
bindAndWriteToRenderer(directiveAst.hostProperties, directiveInstance, compileElement);
}
export function bindDirectiveInputs(directiveAst: DirectiveAst, directiveInstance: o.Expression,
compileElement: CompileElement) {
export function bindDirectiveInputs(
directiveAst: DirectiveAst, directiveInstance: o.Expression, compileElement: CompileElement) {
if (directiveAst.inputs.length === 0) {
return;
}
@ -238,7 +224,7 @@ export function bindDirectiveInputs(directiveAst: DirectiveAst, directiveInstanc
var lifecycleHooks = directiveAst.directive.lifecycleHooks;
var calcChangesMap = lifecycleHooks.indexOf(LifecycleHooks.OnChanges) !== -1;
var isOnPushComp = directiveAst.directive.isComponent &&
!isDefaultChangeDetectionStrategy(directiveAst.directive.changeDetection);
!isDefaultChangeDetectionStrategy(directiveAst.directive.changeDetection);
if (calcChangesMap) {
detectChangesInInputsMethod.addStmt(DetectChangesVars.changes.set(o.NULL_EXPR).toStmt());
}
@ -254,11 +240,11 @@ export function bindDirectiveInputs(directiveAst: DirectiveAst, directiveInstanc
var statements: o.Statement[] =
[directiveInstance.prop(input.directiveName).set(currValExpr).toStmt()];
if (calcChangesMap) {
statements.push(new o.IfStmt(DetectChangesVars.changes.identical(o.NULL_EXPR), [
DetectChangesVars.changes.set(o.literalMap([], new o.MapType(
o.importType(Identifiers.SimpleChange))))
.toStmt()
]));
statements.push(new o.IfStmt(
DetectChangesVars.changes.identical(o.NULL_EXPR),
[DetectChangesVars.changes
.set(o.literalMap([], new o.MapType(o.importType(Identifiers.SimpleChange))))
.toStmt()]));
statements.push(
DetectChangesVars.changes.key(o.literal(input.directiveName))
.set(o.importExpr(Identifiers.SimpleChange).instantiate([fieldExpr, currValExpr]))
@ -271,26 +257,25 @@ export function bindDirectiveInputs(directiveAst: DirectiveAst, directiveInstanc
statements.push(
logBindingUpdateStmt(compileElement.renderNode, input.directiveName, currValExpr));
}
bind(view, currValExpr, fieldExpr, input.value, view.componentContext, statements,
detectChangesInInputsMethod);
bind(
view, currValExpr, fieldExpr, input.value, view.componentContext, statements,
detectChangesInInputsMethod);
});
if (isOnPushComp) {
detectChangesInInputsMethod.addStmt(new o.IfStmt(DetectChangesVars.changed, [
compileElement.appElement.prop('componentView')
.callMethod('markAsCheckOnce', [])
.toStmt()
compileElement.appElement.prop('componentView').callMethod('markAsCheckOnce', []).toStmt()
]));
}
}
function logBindingUpdateStmt(renderNode: o.Expression, propName: string,
value: o.Expression): o.Statement {
function logBindingUpdateStmt(
renderNode: o.Expression, propName: string, value: o.Expression): o.Statement {
return o.THIS_EXPR.prop('renderer')
.callMethod('setBindingDebugInfo',
[
renderNode,
o.literal(`ng-reflect-${camelCaseToDashCase(propName)}`),
value.isBlank().conditional(o.NULL_EXPR, value.callMethod('toString', []))
])
.callMethod(
'setBindingDebugInfo',
[
renderNode, o.literal(`ng-reflect-${camelCaseToDashCase(propName)}`),
value.isBlank().conditional(o.NULL_EXPR, value.callMethod('toString', []))
])
.toStmt();
}

View File

@ -1,16 +1,13 @@
import {isPresent, isBlank} from '../facade/lang';
import {BaseException} from '../facade/exceptions';
import {isBlank, isPresent} from '../facade/lang';
import * as o from '../output/output_ast';
import {
CompileTokenMetadata,
CompileDirectiveMetadata,
} from '../compile_metadata';
import {CompileTokenMetadata, CompileDirectiveMetadata,} from '../compile_metadata';
import {CompileView} from './compile_view';
import {Identifiers} from '../identifiers';
export function getPropertyInView(property: o.Expression, callingView: CompileView,
definedView: CompileView): o.Expression {
export function getPropertyInView(
property: o.Expression, callingView: CompileView, definedView: CompileView): o.Expression {
if (callingView === definedView) {
return property;
} else {
@ -36,8 +33,8 @@ export function getPropertyInView(property: o.Expression, callingView: CompileVi
}
}
export function injectFromViewParentInjector(token: CompileTokenMetadata,
optional: boolean): o.Expression {
export function injectFromViewParentInjector(
token: CompileTokenMetadata, optional: boolean): o.Expression {
var args = [createDiTokenExpression(token)];
if (optional) {
args.push(o.NULL_EXPR);
@ -45,8 +42,8 @@ export function injectFromViewParentInjector(token: CompileTokenMetadata,
return o.THIS_EXPR.prop('parentInjector').callMethod('get', args);
}
export function getViewFactoryName(component: CompileDirectiveMetadata,
embeddedTemplateIndex: number): string {
export function getViewFactoryName(
component: CompileDirectiveMetadata, embeddedTemplateIndex: number): string {
return `viewFactory_${component.type.name}${embeddedTemplateIndex}`;
}
@ -85,8 +82,8 @@ export function createFlatArray(expressions: o.Expression[]): o.Expression {
return result;
}
export function createPureProxy(fn: o.Expression, argCount: number, pureProxyProp: o.ReadPropExpr,
view: CompileView) {
export function createPureProxy(
fn: o.Expression, argCount: number, pureProxyProp: o.ReadPropExpr, view: CompileView) {
view.fields.push(new o.ClassField(pureProxyProp.name, null));
var pureProxyId =
argCount < Identifiers.pureProxies.length ? Identifiers.pureProxies[argCount] : null;

View File

@ -1,37 +1,8 @@
import {
ListWrapper,
} from '../facade/collection';
import {
TemplateAst,
TemplateAstVisitor,
NgContentAst,
EmbeddedTemplateAst,
ElementAst,
ReferenceAst,
VariableAst,
BoundEventAst,
BoundElementPropertyAst,
AttrAst,
BoundTextAst,
TextAst,
DirectiveAst,
BoundDirectivePropertyAst,
templateVisitAll,
} from '../template_ast';
import {
bindRenderText,
bindRenderInputs,
bindDirectiveInputs,
bindDirectiveHostProps
} from './property_binder';
import {ListWrapper,} from '../facade/collection';
import {TemplateAst, TemplateAstVisitor, NgContentAst, EmbeddedTemplateAst, ElementAst, ReferenceAst, VariableAst, BoundEventAst, BoundElementPropertyAst, AttrAst, BoundTextAst, TextAst, DirectiveAst, BoundDirectivePropertyAst, templateVisitAll,} from '../template_ast';
import {bindRenderText, bindRenderInputs, bindDirectiveInputs, bindDirectiveHostProps} from './property_binder';
import {bindRenderOutputs, collectEventListeners, bindDirectiveOutputs} from './event_binder';
import {
bindDirectiveAfterContentLifecycleCallbacks,
bindDirectiveAfterViewLifecycleCallbacks,
bindDirectiveDestroyLifecycleCallbacks,
bindPipeDestroyLifecycleCallbacks,
bindDirectiveDetectChangesLifecycleCallbacks
} from './lifecycle_binder';
import {bindDirectiveAfterContentLifecycleCallbacks, bindDirectiveAfterViewLifecycleCallbacks, bindDirectiveDestroyLifecycleCallbacks, bindPipeDestroyLifecycleCallbacks, bindDirectiveDetectChangesLifecycleCallbacks} from './lifecycle_binder';
import {CompileView} from './compile_view';
import {CompileElement, CompileNode} from './compile_element';
@ -77,12 +48,12 @@ class ViewBinderVisitor implements TemplateAstVisitor {
// so that children are notified before parents
ListWrapper.forEachWithIndex(ast.directives, (directiveAst, index) => {
var directiveInstance = compileElement.directiveInstances[index];
bindDirectiveAfterContentLifecycleCallbacks(directiveAst.directive, directiveInstance,
compileElement);
bindDirectiveAfterViewLifecycleCallbacks(directiveAst.directive, directiveInstance,
compileElement);
bindDirectiveDestroyLifecycleCallbacks(directiveAst.directive, directiveInstance,
compileElement);
bindDirectiveAfterContentLifecycleCallbacks(
directiveAst.directive, directiveInstance, compileElement);
bindDirectiveAfterViewLifecycleCallbacks(
directiveAst.directive, directiveInstance, compileElement);
bindDirectiveDestroyLifecycleCallbacks(
directiveAst.directive, directiveInstance, compileElement);
});
return null;
}
@ -95,12 +66,12 @@ class ViewBinderVisitor implements TemplateAstVisitor {
bindDirectiveInputs(directiveAst, directiveInstance, compileElement);
bindDirectiveDetectChangesLifecycleCallbacks(directiveAst, directiveInstance, compileElement);
bindDirectiveOutputs(directiveAst, directiveInstance, eventListeners);
bindDirectiveAfterContentLifecycleCallbacks(directiveAst.directive, directiveInstance,
compileElement);
bindDirectiveAfterViewLifecycleCallbacks(directiveAst.directive, directiveInstance,
compileElement);
bindDirectiveDestroyLifecycleCallbacks(directiveAst.directive, directiveInstance,
compileElement);
bindDirectiveAfterContentLifecycleCallbacks(
directiveAst.directive, directiveInstance, compileElement);
bindDirectiveAfterViewLifecycleCallbacks(
directiveAst.directive, directiveInstance, compileElement);
bindDirectiveDestroyLifecycleCallbacks(
directiveAst.directive, directiveInstance, compileElement);
});
bindView(compileElement.embeddedView, ast.children);
return null;

View File

@ -1,49 +1,20 @@
import {ChangeDetectionStrategy, ViewEncapsulation} from '@angular/core';
import {isDefaultChangeDetectionStrategy, ViewType} from '../../core_private';
import {isPresent, StringWrapper} from '../facade/lang';
import {ListWrapper, StringMapWrapper, SetWrapper} from '../facade/collection';
import * as o from '../output/output_ast';
import {ViewType, isDefaultChangeDetectionStrategy} from '../../core_private';
import {ListWrapper, SetWrapper, StringMapWrapper} from '../facade/collection';
import {StringWrapper, isPresent} from '../facade/lang';
import {Identifiers, identifierToken} from '../identifiers';
import {
ViewConstructorVars,
InjectMethodVars,
DetectChangesVars,
ViewTypeEnum,
ViewEncapsulationEnum,
ChangeDetectionStrategyEnum,
ViewProperties
} from './constants';
import * as o from '../output/output_ast';
import {CompileView} from './compile_view';
import {CompileElement, CompileNode} from './compile_element';
import {CompileView} from './compile_view';
import {ChangeDetectionStrategyEnum, DetectChangesVars, InjectMethodVars, ViewConstructorVars, ViewEncapsulationEnum, ViewProperties, ViewTypeEnum} from './constants';
import {
TemplateAst,
TemplateAstVisitor,
NgContentAst,
EmbeddedTemplateAst,
ElementAst,
ReferenceAst,
VariableAst,
BoundEventAst,
BoundElementPropertyAst,
AttrAst,
BoundTextAst,
TextAst,
DirectiveAst,
BoundDirectivePropertyAst,
templateVisitAll,
} from '../template_ast';
import {TemplateAst, TemplateAstVisitor, NgContentAst, EmbeddedTemplateAst, ElementAst, ReferenceAst, VariableAst, BoundEventAst, BoundElementPropertyAst, AttrAst, BoundTextAst, TextAst, DirectiveAst, BoundDirectivePropertyAst, templateVisitAll,} from '../template_ast';
import {getViewFactoryName, createFlatArray, createDiTokenExpression} from './util';
import {
CompileIdentifierMetadata,
CompileDirectiveMetadata,
CompileTokenMetadata
} from '../compile_metadata';
import {CompileIdentifierMetadata, CompileDirectiveMetadata, CompileTokenMetadata} from '../compile_metadata';
import {AnimationCompiler} from '../animation/animation_compiler';
@ -55,16 +26,18 @@ var parentRenderNodeVar = o.variable('parentRenderNode');
var rootSelectorVar = o.variable('rootSelector');
export class ViewCompileDependency {
constructor(public comp: CompileDirectiveMetadata,
public factoryPlaceholder: CompileIdentifierMetadata) {}
constructor(
public comp: CompileDirectiveMetadata, public factoryPlaceholder: CompileIdentifierMetadata) {
}
}
export function buildView(view: CompileView, template: TemplateAst[],
targetDependencies: ViewCompileDependency[]): number {
export function buildView(
view: CompileView, template: TemplateAst[],
targetDependencies: ViewCompileDependency[]): number {
var builderVisitor = new ViewBuilderVisitor(view, targetDependencies);
templateVisitAll(builderVisitor, template, view.declarationElement.isNull() ?
view.declarationElement :
view.declarationElement.parent);
templateVisitAll(
builderVisitor, template,
view.declarationElement.isNull() ? view.declarationElement : view.declarationElement.parent);
return builderVisitor.nestedViewCount;
}
@ -87,8 +60,8 @@ class ViewBuilderVisitor implements TemplateAstVisitor {
private _isRootNode(parent: CompileElement): boolean { return parent.view !== this.view; }
private _addRootNodeAndProject(node: CompileNode, ngContentIndex: number,
parent: CompileElement) {
private _addRootNodeAndProject(
node: CompileNode, ngContentIndex: number, parent: CompileElement) {
var vcAppEl =
(node instanceof CompileElement && node.hasViewContainer) ? node.appElement : null;
if (this._isRootNode(parent)) {
@ -111,9 +84,9 @@ class ViewBuilderVisitor implements TemplateAstVisitor {
}
} else {
return isPresent(parent.component) &&
parent.component.template.encapsulation !== ViewEncapsulation.Native ?
o.NULL_EXPR :
parent.renderNode;
parent.component.template.encapsulation !== ViewEncapsulation.Native ?
o.NULL_EXPR :
parent.renderNode;
}
}
@ -123,8 +96,9 @@ class ViewBuilderVisitor implements TemplateAstVisitor {
visitText(ast: TextAst, parent: CompileElement): any {
return this._visitText(ast, ast.value, ast.ngContentIndex, parent);
}
private _visitText(ast: TemplateAst, value: string, ngContentIndex: number,
parent: CompileElement): o.Expression {
private _visitText(
ast: TemplateAst, value: string, ngContentIndex: number,
parent: CompileElement): o.Expression {
var fieldName = `_text_${this.view.nodes.length}`;
this.view.fields.push(
new o.ClassField(fieldName, o.importType(this.view.genConfig.renderTypes.renderText)));
@ -135,8 +109,7 @@ class ViewBuilderVisitor implements TemplateAstVisitor {
.set(ViewProperties.renderer.callMethod(
'createText',
[
this._getParentRenderNode(parent),
o.literal(value),
this._getParentRenderNode(parent), o.literal(value),
this.view.createMethod.resetDebugInfoExpr(this.view.nodes.length, ast)
]))
.toStmt();
@ -156,13 +129,13 @@ class ViewBuilderVisitor implements TemplateAstVisitor {
new o.ArrayType(o.importType(this.view.genConfig.renderTypes.renderNode)));
if (parentRenderNode !== o.NULL_EXPR) {
this.view.createMethod.addStmt(
ViewProperties.renderer.callMethod(
'projectNodes',
[
parentRenderNode,
o.importExpr(Identifiers.flattenNestedViewRenderNodes)
.callFn([nodesExpression])
])
ViewProperties.renderer
.callMethod(
'projectNodes',
[
parentRenderNode,
o.importExpr(Identifiers.flattenNestedViewRenderNodes).callFn([nodesExpression])
])
.toStmt());
} else if (this._isRootNode(parent)) {
if (this.view.viewType !== ViewType.COMPONENT) {
@ -204,14 +177,14 @@ class ViewBuilderVisitor implements TemplateAstVisitor {
var attrName = attrNameAndValues[i][0];
var attrValue = attrNameAndValues[i][1];
this.view.createMethod.addStmt(
ViewProperties.renderer.callMethod(
'setElementAttribute',
[renderNode, o.literal(attrName), o.literal(attrValue)])
ViewProperties.renderer
.callMethod(
'setElementAttribute', [renderNode, o.literal(attrName), o.literal(attrValue)])
.toStmt());
}
var compileElement =
new CompileElement(parent, this.view, nodeIndex, renderNode, ast, component, directives,
ast.providers, ast.hasViewContainer, false, ast.references);
var compileElement = new CompileElement(
parent, this.view, nodeIndex, renderNode, ast, component, directives, ast.providers,
ast.hasViewContainer, false, ast.references);
this.view.nodes.push(compileElement);
var compViewExpr: o.ReadVarExpr = null;
if (isPresent(component)) {
@ -220,13 +193,12 @@ class ViewBuilderVisitor implements TemplateAstVisitor {
this.targetDependencies.push(new ViewCompileDependency(component, nestedComponentIdentifier));
compViewExpr = o.variable(`compView_${nodeIndex}`); // fix highlighting: `
compileElement.setComponentView(compViewExpr);
this.view.createMethod.addStmt(compViewExpr.set(o.importExpr(nestedComponentIdentifier)
.callFn([
ViewProperties.viewUtils,
compileElement.injector,
compileElement.appElement
]))
.toDeclStmt());
this.view.createMethod.addStmt(
compViewExpr
.set(o.importExpr(nestedComponentIdentifier).callFn([
ViewProperties.viewUtils, compileElement.injector, compileElement.appElement
]))
.toDeclStmt());
}
compileElement.beforeChildren();
this._addRootNodeAndProject(compileElement, ast.ngContentIndex, parent);
@ -242,8 +214,9 @@ class ViewBuilderVisitor implements TemplateAstVisitor {
compileElement.contentNodesByNgContentIndex.map(nodes => createFlatArray(nodes)));
}
this.view.createMethod.addStmt(
compViewExpr.callMethod('create',
[compileElement.getComponent(), codeGenContentNodes, o.NULL_EXPR])
compViewExpr
.callMethod(
'create', [compileElement.getComponent(), codeGenContentNodes, o.NULL_EXPR])
.toStmt());
}
return null;
@ -269,17 +242,18 @@ class ViewBuilderVisitor implements TemplateAstVisitor {
varAst => [varAst.value.length > 0 ? varAst.value : IMPLICIT_TEMPLATE_VAR, varAst.name]);
var directives = ast.directives.map(directiveAst => directiveAst.directive);
var compileElement =
new CompileElement(parent, this.view, nodeIndex, renderNode, ast, null, directives,
ast.providers, ast.hasViewContainer, true, ast.references);
var compileElement = new CompileElement(
parent, this.view, nodeIndex, renderNode, ast, null, directives, ast.providers,
ast.hasViewContainer, true, ast.references);
this.view.nodes.push(compileElement);
var compiledAnimations = this._animationCompiler.compileComponent(this.view.component);
this.nestedViewCount++;
var embeddedView = new CompileView(
this.view.component, this.view.genConfig, this.view.pipeMetas, o.NULL_EXPR, compiledAnimations,
this.view.viewIndex + this.nestedViewCount, compileElement, templateVariableBindings);
this.view.component, this.view.genConfig, this.view.pipeMetas, o.NULL_EXPR,
compiledAnimations, this.view.viewIndex + this.nestedViewCount, compileElement,
templateVariableBindings);
this.nestedViewCount += buildView(embeddedView, ast.children, this.targetDependencies);
compileElement.beforeChildren();
@ -301,15 +275,20 @@ class ViewBuilderVisitor implements TemplateAstVisitor {
visitElementProperty(ast: BoundElementPropertyAst, context: any): any { return null; }
}
function _mergeHtmlAndDirectiveAttrs(declaredHtmlAttrs: {[key: string]: string},
directives: CompileDirectiveMetadata[]): string[][] {
function _mergeHtmlAndDirectiveAttrs(
declaredHtmlAttrs: {[key: string]: string},
directives: CompileDirectiveMetadata[]): string[][] {
var result: {[key: string]: string} = {};
StringMapWrapper.forEach(declaredHtmlAttrs, (value: any /** TODO #9100 */, key: any /** TODO #9100 */) => { result[key] = value; });
StringMapWrapper.forEach(
declaredHtmlAttrs,
(value: any /** TODO #9100 */, key: any /** TODO #9100 */) => { result[key] = value; });
directives.forEach(directiveMeta => {
StringMapWrapper.forEach(directiveMeta.hostAttributes, (value: any /** TODO #9100 */, name: any /** TODO #9100 */) => {
var prevValue = result[name];
result[name] = isPresent(prevValue) ? mergeAttributeValue(name, prevValue, value) : value;
});
StringMapWrapper.forEach(
directiveMeta.hostAttributes,
(value: any /** TODO #9100 */, name: any /** TODO #9100 */) => {
var prevValue = result[name];
result[name] = isPresent(prevValue) ? mergeAttributeValue(name, prevValue, value) : value;
});
});
return mapToKeyValueArray(result);
}
@ -330,7 +309,9 @@ function mergeAttributeValue(attrName: string, attrValue1: string, attrValue2: s
function mapToKeyValueArray(data: {[key: string]: string}): string[][] {
var entryArray: any[] /** TODO #9100 */ = [];
StringMapWrapper.forEach(data, (value: any /** TODO #9100 */, name: any /** TODO #9100 */) => { entryArray.push([name, value]); });
StringMapWrapper.forEach(data, (value: any /** TODO #9100 */, name: any /** TODO #9100 */) => {
entryArray.push([name, value]);
});
// We need to sort to get a defined output order
// for tests and for caching generated artifacts...
ListWrapper.sort(entryArray, (entry1, entry2) => StringWrapper.compare(entry1[0], entry2[0]));
@ -346,9 +327,10 @@ function createViewTopLevelStmts(view: CompileView, targetStatements: o.Statemen
`nodeDebugInfos_${view.component.type.name}${view.viewIndex}`); // fix highlighting: `
targetStatements.push(
(<o.ReadVarExpr>nodeDebugInfosVar)
.set(o.literalArr(view.nodes.map(createStaticNodeDebugInfo),
new o.ArrayType(new o.ExternalType(Identifiers.StaticNodeDebugInfo),
[o.TypeModifier.Const])))
.set(o.literalArr(
view.nodes.map(createStaticNodeDebugInfo),
new o.ArrayType(
new o.ExternalType(Identifiers.StaticNodeDebugInfo), [o.TypeModifier.Const])))
.toDeclStmt(null, [o.StmtModifier.Final]));
}
@ -375,10 +357,12 @@ function createStaticNodeDebugInfo(node: CompileNode): o.Expression {
if (isPresent(compileElement.component)) {
componentToken = createDiTokenExpression(identifierToken(compileElement.component.type));
}
StringMapWrapper.forEach(compileElement.referenceTokens, (token: any /** TODO #9100 */, varName: any /** TODO #9100 */) => {
varTokenEntries.push(
[varName, isPresent(token) ? createDiTokenExpression(token) : o.NULL_EXPR]);
});
StringMapWrapper.forEach(
compileElement.referenceTokens,
(token: any /** TODO #9100 */, varName: any /** TODO #9100 */) => {
varTokenEntries.push(
[varName, isPresent(token) ? createDiTokenExpression(token) : o.NULL_EXPR]);
});
}
return o.importExpr(Identifiers.StaticNodeDebugInfo)
.instantiate(
@ -390,31 +374,30 @@ function createStaticNodeDebugInfo(node: CompileNode): o.Expression {
o.importType(Identifiers.StaticNodeDebugInfo, null, [o.TypeModifier.Const]));
}
function createViewClass(view: CompileView, renderCompTypeVar: o.ReadVarExpr,
nodeDebugInfosVar: o.Expression): o.ClassStmt {
function createViewClass(
view: CompileView, renderCompTypeVar: o.ReadVarExpr,
nodeDebugInfosVar: o.Expression): o.ClassStmt {
var viewConstructorArgs = [
new o.FnParam(ViewConstructorVars.viewUtils.name, o.importType(Identifiers.ViewUtils)),
new o.FnParam(ViewConstructorVars.parentInjector.name, o.importType(Identifiers.Injector)),
new o.FnParam(ViewConstructorVars.declarationEl.name, o.importType(Identifiers.AppElement))
];
var superConstructorArgs = [
o.variable(view.className),
renderCompTypeVar,
ViewTypeEnum.fromValue(view.viewType),
ViewConstructorVars.viewUtils,
ViewConstructorVars.parentInjector,
o.variable(view.className), renderCompTypeVar, ViewTypeEnum.fromValue(view.viewType),
ViewConstructorVars.viewUtils, ViewConstructorVars.parentInjector,
ViewConstructorVars.declarationEl,
ChangeDetectionStrategyEnum.fromValue(getChangeDetectionMode(view))
];
if (view.genConfig.genDebugInfo) {
superConstructorArgs.push(nodeDebugInfosVar);
}
var viewConstructor = new o.ClassMethod(null, viewConstructorArgs,
[o.SUPER_EXPR.callFn(superConstructorArgs).toStmt()]);
var viewConstructor = new o.ClassMethod(
null, viewConstructorArgs, [o.SUPER_EXPR.callFn(superConstructorArgs).toStmt()]);
var viewMethods = [
new o.ClassMethod('createInternal', [new o.FnParam(rootSelectorVar.name, o.STRING_TYPE)],
generateCreateMethod(view), o.importType(Identifiers.AppElement)),
new o.ClassMethod(
'createInternal', [new o.FnParam(rootSelectorVar.name, o.STRING_TYPE)],
generateCreateMethod(view), o.importType(Identifiers.AppElement)),
new o.ClassMethod(
'injectorGetInternal',
[
@ -425,22 +408,22 @@ function createViewClass(view: CompileView, renderCompTypeVar: o.ReadVarExpr,
],
addReturnValuefNotEmpty(view.injectorGetMethod.finish(), InjectMethodVars.notFoundResult),
o.DYNAMIC_TYPE),
new o.ClassMethod('detectChangesInternal',
[new o.FnParam(DetectChangesVars.throwOnChange.name, o.BOOL_TYPE)],
generateDetectChangesMethod(view)),
new o.ClassMethod(
'detectChangesInternal', [new o.FnParam(DetectChangesVars.throwOnChange.name, o.BOOL_TYPE)],
generateDetectChangesMethod(view)),
new o.ClassMethod('dirtyParentQueriesInternal', [], view.dirtyParentQueriesMethod.finish()),
new o.ClassMethod('destroyInternal', [], view.destroyMethod.finish()),
new o.ClassMethod('detachInternal', [], view.detachMethod.finish())
].concat(view.eventHandlerMethods);
var superClass = view.genConfig.genDebugInfo ? Identifiers.DebugAppView : Identifiers.AppView;
var viewClass = new o.ClassStmt(view.className, o.importExpr(superClass, [getContextType(view)]),
view.fields, view.getters, viewConstructor,
viewMethods.filter((method) => method.body.length > 0));
var viewClass = new o.ClassStmt(
view.className, o.importExpr(superClass, [getContextType(view)]), view.fields, view.getters,
viewConstructor, viewMethods.filter((method) => method.body.length > 0));
return viewClass;
}
function createViewFactory(view: CompileView, viewClass: o.ClassStmt,
renderCompTypeVar: o.ReadVarExpr): o.Statement {
function createViewFactory(
view: CompileView, viewClass: o.ClassStmt, renderCompTypeVar: o.ReadVarExpr): o.Statement {
var viewFactoryArgs = [
new o.FnParam(ViewConstructorVars.viewUtils.name, o.importType(Identifiers.ViewUtils)),
new o.FnParam(ViewConstructorVars.parentInjector.name, o.importType(Identifiers.Injector)),
@ -455,29 +438,24 @@ function createViewFactory(view: CompileView, viewClass: o.ClassStmt,
templateUrlInfo = view.component.template.templateUrl;
}
if (view.viewIndex === 0) {
initRenderCompTypeStmts = [
new o.IfStmt(renderCompTypeVar.identical(o.NULL_EXPR),
[
renderCompTypeVar.set(ViewConstructorVars
.viewUtils.callMethod('createRenderComponentType',
[
o.literal(templateUrlInfo),
o.literal(view.component
.template.ngContentSelectors.length),
ViewEncapsulationEnum
.fromValue(view.component.template.encapsulation),
view.styles
]))
.toStmt()
])
];
initRenderCompTypeStmts = [new o.IfStmt(renderCompTypeVar.identical(o.NULL_EXPR), [
renderCompTypeVar
.set(ViewConstructorVars.viewUtils.callMethod(
'createRenderComponentType',
[
o.literal(templateUrlInfo),
o.literal(view.component.template.ngContentSelectors.length),
ViewEncapsulationEnum.fromValue(view.component.template.encapsulation), view.styles
]))
.toStmt()
])];
}
return o.fn(viewFactoryArgs, initRenderCompTypeStmts.concat([
new o.ReturnStatement(o.variable(viewClass.name)
.instantiate(viewClass.constructorMethod.params.map(
(param) => o.variable(param.name))))
]),
o.importType(Identifiers.AppView, [getContextType(view)]))
return o
.fn(viewFactoryArgs, initRenderCompTypeStmts.concat([new o.ReturnStatement(
o.variable(viewClass.name)
.instantiate(viewClass.constructorMethod.params.map(
(param) => o.variable(param.name))))]),
o.importType(Identifiers.AppView, [getContextType(view)]))
.toDeclStmt(view.viewFactory.name, [o.StmtModifier.Final]);
}
@ -487,10 +465,10 @@ function generateCreateMethod(view: CompileView): o.Statement[] {
if (view.viewType === ViewType.COMPONENT) {
parentRenderNodeExpr = ViewProperties.renderer.callMethod(
'createViewRoot', [o.THIS_EXPR.prop('declarationAppElement').prop('nativeElement')]);
parentRenderNodeStmts = [
parentRenderNodeVar.set(parentRenderNodeExpr)
.toDeclStmt(o.importType(view.genConfig.renderTypes.renderNode), [o.StmtModifier.Final])
];
parentRenderNodeStmts =
[parentRenderNodeVar.set(parentRenderNodeExpr)
.toDeclStmt(
o.importType(view.genConfig.renderTypes.renderNode), [o.StmtModifier.Final])];
}
var resultExpr: o.Expression;
if (view.viewType === ViewType.HOST) {
@ -498,18 +476,18 @@ function generateCreateMethod(view: CompileView): o.Statement[] {
} else {
resultExpr = o.NULL_EXPR;
}
return parentRenderNodeStmts.concat(view.createMethod.finish())
.concat([
o.THIS_EXPR.callMethod('init',
[
createFlatArray(view.rootNodesOrAppElements),
o.literalArr(view.nodes.map(node => node.renderNode)),
o.literalArr(view.disposables),
o.literalArr(view.subscriptions)
])
.toStmt(),
new o.ReturnStatement(resultExpr)
]);
return parentRenderNodeStmts.concat(view.createMethod.finish()).concat([
o.THIS_EXPR
.callMethod(
'init',
[
createFlatArray(view.rootNodesOrAppElements),
o.literalArr(view.nodes.map(node => node.renderNode)), o.literalArr(view.disposables),
o.literalArr(view.subscriptions)
])
.toStmt(),
new o.ReturnStatement(resultExpr)
]);
}
function generateDetectChangesMethod(view: CompileView): o.Statement[] {
@ -574,8 +552,8 @@ function getChangeDetectionMode(view: CompileView): ChangeDetectionStrategy {
var mode: ChangeDetectionStrategy;
if (view.viewType === ViewType.COMPONENT) {
mode = isDefaultChangeDetectionStrategy(view.component.changeDetection) ?
ChangeDetectionStrategy.CheckAlways :
ChangeDetectionStrategy.CheckOnce;
ChangeDetectionStrategy.CheckAlways :
ChangeDetectionStrategy.CheckOnce;
} else {
mode = ChangeDetectionStrategy.CheckAlways;
}

View File

@ -1,18 +1,20 @@
import {Injectable} from '@angular/core';
import * as o from '../output/output_ast';
import {CompileElement} from './compile_element';
import {CompileView} from './compile_view';
import {buildView, finishView, ViewCompileDependency} from './view_builder';
import {bindView} from './view_binder';
import {CompileDirectiveMetadata, CompilePipeMetadata} from '../compile_metadata';
import {TemplateAst} from '../template_ast';
import {CompilerConfig} from '../config';
import {AnimationCompiler} from '../animation/animation_compiler';
import {CompileDirectiveMetadata, CompilePipeMetadata} from '../compile_metadata';
import {CompilerConfig} from '../config';
import * as o from '../output/output_ast';
import {TemplateAst} from '../template_ast';
import {CompileElement} from './compile_element';
import {CompileView} from './compile_view';
import {bindView} from './view_binder';
import {ViewCompileDependency, buildView, finishView} from './view_builder';
export class ViewCompileResult {
constructor(public statements: o.Statement[], public viewFactoryVar: string,
public dependencies: ViewCompileDependency[]) {}
constructor(
public statements: o.Statement[], public viewFactoryVar: string,
public dependencies: ViewCompileDependency[]) {}
}
@Injectable()
@ -20,8 +22,9 @@ export class ViewCompiler {
private _animationCompiler = new AnimationCompiler();
constructor(private _genConfig: CompilerConfig) {}
compileComponent(component: CompileDirectiveMetadata, template: TemplateAst[],
styles: o.Expression, pipes: CompilePipeMetadata[]): ViewCompileResult {
compileComponent(
component: CompileDirectiveMetadata, template: TemplateAst[], styles: o.Expression,
pipes: CompilePipeMetadata[]): ViewCompileResult {
var dependencies: any[] /** TODO #9100 */ = [];
var compiledAnimations = this._animationCompiler.compileComponent(component);
var statements: any[] /** TODO #9100 */ = [];
@ -29,8 +32,9 @@ export class ViewCompiler {
statements.push(entry.statesMapStatement);
statements.push(entry.fnStatement);
});
var view = new CompileView(component, this._genConfig, pipes, styles, compiledAnimations, 0,
CompileElement.createNull(), []);
var view = new CompileView(
component, this._genConfig, pipes, styles, compiledAnimations, 0,
CompileElement.createNull(), []);
buildView(view, template, dependencies);
// Need to separate binding from creation to be able to refer to
// variables that have been declared after usage.

View File

@ -1,8 +1,4 @@
import {
Injectable,
ViewMetadata,
ComponentMetadata,
} from '@angular/core';
import {Injectable, ViewMetadata, ComponentMetadata,} from '@angular/core';
import {ReflectorReader, reflector} from '../core_private';
@ -67,9 +63,8 @@ export class ViewResolver {
});
}
} else {
throw new BaseException(
`Could not compile '${stringify(component)}' because it is not a component.`);
throw new BaseException(
`Could not compile '${stringify(component)}' because it is not a component.`);
}
}
}

View File

@ -1,34 +1,15 @@
import {
AsyncTestCompleter,
beforeEach,
ddescribe,
xdescribe,
describe,
expect,
iit,
inject,
it,
xit,
beforeEachProviders
} from '@angular/core/testing/testing_internal';
import {trigger, style, animate, group, sequence, transition, AnimationMetadata} from '@angular/core';
import {AnimationMetadata, animate, group, sequence, style, transition, trigger} from '@angular/core';
import {AsyncTestCompleter, beforeEach, beforeEachProviders, ddescribe, describe, expect, iit, inject, it, xdescribe, xit} from '@angular/core/testing/testing_internal';
import {AnimationCompiler, CompiledAnimation} from '../../src/animation/animation_compiler';
import {
CompileTemplateMetadata,
CompileDirectiveMetadata,
CompileTypeMetadata
} from '../../src/compile_metadata';
import {CompileDirectiveMetadata, CompileTemplateMetadata, CompileTypeMetadata} from '../../src/compile_metadata';
import {CompileMetadataResolver} from '../../src/metadata_resolver';
export function main() {
describe('RuntimeAnimationCompiler', () => {
var resolver: any /** TODO #9100 */;
beforeEach(inject([CompileMetadataResolver], (res: CompileMetadataResolver) => {
resolver = res;
}));
beforeEach(
inject([CompileMetadataResolver], (res: CompileMetadataResolver) => { resolver = res; }));
var compiler = new AnimationCompiler();
@ -37,18 +18,12 @@ export function main() {
};
var compile = (seq: AnimationMetadata) => {
var entry = trigger('myAnimation', [
transition('state1 => state2', seq)
]);
var entry = trigger('myAnimation', [transition('state1 => state2', seq)]);
var compiledAnimationEntry = resolver.getAnimationEntryMetadata(entry);
var component = CompileDirectiveMetadata.create({
type: new CompileTypeMetadata({
name: 'something'
}),
template: new CompileTemplateMetadata({
animations: [compiledAnimationEntry]
})
type: new CompileTypeMetadata({name: 'something'}),
template: new CompileTemplateMetadata({animations: [compiledAnimationEntry]})
});
return compileAnimations(component);
@ -56,12 +31,9 @@ export function main() {
it('should throw an exception containing all the inner animation parser errors', () => {
var animation = sequence([
style({"color": "red"}),
animate(1000, style({"font-size": "100px"})),
style({"color": "blue"}),
animate(1000, style(":missing_state")),
style({"color": "gold"}),
animate(1000, style("broken_state"))
style({'color': 'red'}), animate(1000, style({'font-size': '100px'})),
style({'color': 'blue'}), animate(1000, style(':missing_state')), style({'color': 'gold'}),
animate(1000, style('broken_state'))
]);
var capturedErrorMessage: string;
@ -72,8 +44,7 @@ export function main() {
}
expect(capturedErrorMessage)
.toMatchPattern(
/Unable to apply styles due to missing a state: "missing_state"/g);
.toMatchPattern(/Unable to apply styles due to missing a state: "missing_state"/g);
expect(capturedErrorMessage)
.toMatchPattern(/Animation states via styles must be prefixed with a ":"/);

View File

@ -1,64 +1,26 @@
import {
AsyncTestCompleter,
beforeEach,
ddescribe,
xdescribe,
describe,
expect,
iit,
inject,
it,
xit,
beforeEachProviders
} from '@angular/core/testing/testing_internal';
import {parseAnimationEntry} from '../../src/animation/animation_parser';
import {CompileMetadataResolver} from '../../src/metadata_resolver';
import {
style,
animate,
group,
sequence,
trigger,
keyframes,
transition,
state,
AnimationMetadata,
AnimationWithStepsMetadata,
AnimationStyleMetadata,
AnimationAnimateMetadata,
AnimationGroupMetadata,
AnimationSequenceMetadata
} from '@angular/core';
import {
AnimationAst,
AnimationStateTransitionAst,
AnimationEntryAst,
AnimationKeyframeAst,
AnimationStylesAst,
AnimationSequenceAst,
AnimationGroupAst,
AnimationStepAst
} from '../../src/animation/animation_ast';
import {AnimationAnimateMetadata, AnimationGroupMetadata, AnimationMetadata, AnimationSequenceMetadata, AnimationStyleMetadata, AnimationWithStepsMetadata, animate, group, keyframes, sequence, state, style, transition, trigger} from '@angular/core';
import {AsyncTestCompleter, beforeEach, beforeEachProviders, ddescribe, describe, expect, iit, inject, it, xdescribe, xit} from '@angular/core/testing/testing_internal';
import {FILL_STYLE_FLAG, flattenStyles} from '../../core_private';
import {AnimationAst, AnimationEntryAst, AnimationGroupAst, AnimationKeyframeAst, AnimationSequenceAst, AnimationStateTransitionAst, AnimationStepAst, AnimationStylesAst} from '../../src/animation/animation_ast';
import {parseAnimationEntry} from '../../src/animation/animation_parser';
import {StringMapWrapper} from '../../src/facade/collection';
import {CompileMetadataResolver} from '../../src/metadata_resolver';
export function main() {
describe('parseAnimationEntry', () => {
var combineStyles = (styles: AnimationStylesAst): {[key: string]: string | number} => {
var flatStyles: {[key: string]: string | number} = {};
styles.styles.forEach(entry => StringMapWrapper.forEach(entry, (val: any /** TODO #9100 */, prop: any /** TODO #9100 */) => { flatStyles[prop] = val; }));
styles.styles.forEach(
entry => StringMapWrapper.forEach(
entry, (val: any /** TODO #9100 */, prop: any /** TODO #9100 */) => {
flatStyles[prop] = val;
}));
return flatStyles;
};
var collectKeyframeStyles = (keyframe: AnimationKeyframeAst): {[key: string]: string | number} => {
return combineStyles(keyframe.styles);
};
var collectKeyframeStyles = (keyframe: AnimationKeyframeAst):
{[key: string]: string | number} => { return combineStyles(keyframe.styles); };
var collectStepStyles = (step: AnimationStepAst): Array<{[key: string]: string | number}> => {
var keyframes = step.keyframes;
@ -71,21 +33,17 @@ export function main() {
};
var resolver: any /** TODO #9100 */;
beforeEach(inject([CompileMetadataResolver], (res: CompileMetadataResolver) => {
resolver = res;
}));
beforeEach(
inject([CompileMetadataResolver], (res: CompileMetadataResolver) => { resolver = res; }));
var parseAnimation = (data: AnimationMetadata[]) => {
var entry = trigger('myAnimation', [
transition('state1 => state2', sequence(data))
]);
var entry = trigger('myAnimation', [transition('state1 => state2', sequence(data))]);
var compiledAnimationEntry = resolver.getAnimationEntryMetadata(entry);
return parseAnimationEntry(compiledAnimationEntry);
};
var getAnimationAstFromEntryAst = (ast: AnimationEntryAst) => {
return ast.stateTransitions[0].animation;
}
var getAnimationAstFromEntryAst =
(ast: AnimationEntryAst) => { return ast.stateTransitions[0].animation; }
var parseAnimationAst = (data: AnimationMetadata[]) => {
return getAnimationAstFromEntryAst(parseAnimation(data).ast);
@ -95,29 +53,27 @@ export function main() {
it('should merge repeated style steps into a single style ast step entry', () => {
var ast = parseAnimationAst([
style({"color": 'black'}),
style({"background": 'red'}),
style({"opacity": 0}),
animate(1000, style({"color": 'white', "background": 'black', "opacity": 1}))
style({'color': 'black'}), style({'background': 'red'}), style({'opacity': 0}),
animate(1000, style({'color': 'white', 'background': 'black', 'opacity': 1}))
]);
expect(ast.steps.length).toEqual(1);
var step = <AnimationStepAst>ast.steps[0];
expect(step.startingStyles.styles[0])
.toEqual({"color": 'black', "background": 'red', "opacity": 0});
.toEqual({'color': 'black', 'background': 'red', 'opacity': 0});
expect(step.keyframes[0].styles.styles[0])
.toEqual({"color": 'black', "background": 'red', "opacity": 0});
.toEqual({'color': 'black', 'background': 'red', 'opacity': 0});
expect(step.keyframes[1].styles.styles[0])
.toEqual({"color": 'white', "background": 'black', "opacity": 1});
.toEqual({'color': 'white', 'background': 'black', 'opacity': 1});
});
it('should animate only the styles requested within an animation step', () => {
var ast = parseAnimationAst([
style({"color": 'black', "background": 'blue'}),
animate(1000, style({"background": 'orange'}))
style({'color': 'black', 'background': 'blue'}),
animate(1000, style({'background': 'orange'}))
]);
expect(ast.steps.length).toEqual(1);
@ -125,18 +81,19 @@ export function main() {
var animateStep = <AnimationStepAst>ast.steps[0];
var fromKeyframe = animateStep.keyframes[0].styles.styles[0];
var toKeyframe = animateStep.keyframes[1].styles.styles[0];
expect(fromKeyframe).toEqual({"background": 'blue'});
expect(toKeyframe).toEqual({"background": 'orange'});
expect(fromKeyframe).toEqual({'background': 'blue'});
expect(toKeyframe).toEqual({'background': 'orange'});
});
it('should populate the starting and duration times propertly', () => {
var ast = parseAnimationAst([
style({"color": 'black', "opacity": 1}),
animate(1000, style({"color": 'red'})),
animate(4000, style({"color": 'yellow'})),
sequence([animate(1000, style({"color": 'blue'})), animate(1000, style({"color": 'grey'}))]),
group([animate(500, style({"color": 'pink'})), animate(1000, style({"opacity": '0.5'}))]),
animate(300, style({"color": 'black'})),
style({'color': 'black', 'opacity': 1}),
animate(1000, style({'color': 'red'})),
animate(4000, style({'color': 'yellow'})),
sequence(
[animate(1000, style({'color': 'blue'})), animate(1000, style({'color': 'grey'}))]),
group([animate(500, style({'color': 'pink'})), animate(1000, style({'opacity': '0.5'}))]),
animate(300, style({'color': 'black'})),
]);
expect(ast.steps.length).toEqual(5);
@ -181,13 +138,15 @@ export function main() {
it('should apply the correct animate() styles when parallel animations are active and use the same properties',
() => {
var details = parseAnimation([
style({"opacity": 0, "color": 'red'}),
group([
style({'opacity': 0, 'color': 'red'}), group([
sequence([
animate(2000, style({"color": "black"})),
animate(2000, style({"opacity": 0.5})),
animate(2000, style({'color': 'black'})),
animate(2000, style({'opacity': 0.5})),
]),
sequence([animate(2000, style({"opacity": 0.8})), animate(2000, style({"color": "blue"}))])
sequence([
animate(2000, style({'opacity': 0.8})),
animate(2000, style({'color': 'blue'}))
])
])
]);
@ -201,22 +160,22 @@ export function main() {
var sq2 = <AnimationSequenceAst>g1.steps[1];
var sq1a1 = <AnimationStepAst>sq1.steps[0];
expect(collectStepStyles(sq1a1)).toEqual([{"color": 'red'}, {"color": 'black'}]);
expect(collectStepStyles(sq1a1)).toEqual([{'color': 'red'}, {'color': 'black'}]);
var sq1a2 = <AnimationStepAst>sq1.steps[1];
expect(collectStepStyles(sq1a2)).toEqual([{"opacity": 0.8}, {"opacity": 0.5}]);
expect(collectStepStyles(sq1a2)).toEqual([{'opacity': 0.8}, {'opacity': 0.5}]);
var sq2a1 = <AnimationStepAst>sq2.steps[0];
expect(collectStepStyles(sq2a1)).toEqual([{"opacity": 0}, {"opacity": 0.8}]);
expect(collectStepStyles(sq2a1)).toEqual([{'opacity': 0}, {'opacity': 0.8}]);
var sq2a2 = <AnimationStepAst>sq2.steps[1];
expect(collectStepStyles(sq2a2)).toEqual([{"color": "black"}, {"color": "blue"}]);
expect(collectStepStyles(sq2a2)).toEqual([{'color': 'black'}, {'color': 'blue'}]);
});
it('should throw errors when animations animate a CSS property at the same time', () => {
var animation1 = parseAnimation([
style({"opacity": 0}),
group([animate(1000, style({"opacity": 1})), animate(2000, style({"opacity": 0.5}))])
style({'opacity': 0}),
group([animate(1000, style({'opacity': 1})), animate(2000, style({'opacity': 0.5}))])
]);
var errors1 = animation1.errors;
@ -226,11 +185,9 @@ export function main() {
'The animated CSS property "opacity" unexpectedly changes between steps "0ms" and "2000ms" at "1000ms"');
var animation2 = parseAnimation([
style({"color": "red"}),
group([
animate(5000, style({"color": "blue"})),
animate(2500, style({"color": "black"}))
])
style({'color': 'red'}),
group(
[animate(5000, style({'color': 'blue'})), animate(2500, style({'color': 'black'}))])
]);
var errors2 = animation2.errors;
@ -242,30 +199,23 @@ export function main() {
it('should return an error when an animation style contains an invalid timing value', () => {
var errors = parseAnimationAndGetErrors(
[style({"opacity": 0}), animate('one second', style({"opacity": 1}))]);
[style({'opacity': 0}), animate('one second', style({'opacity': 1}))]);
expect(errors[0].msg).toContainError(`The provided timing value "one second" is invalid.`);
});
it('should collect and return any errors collected when parsing the metadata', () => {
var errors = parseAnimationAndGetErrors([
style({"opacity": 0}),
animate('one second', style({"opacity": 1})),
style({"opacity": 0}),
animate('one second', null),
style({"background": 'red'})
style({'opacity': 0}), animate('one second', style({'opacity': 1})), style({'opacity': 0}),
animate('one second', null), style({'background': 'red'})
]);
expect(errors.length).toBeGreaterThan(1);
});
it('should normalize a series of keyframe styles into a list of offset steps', () => {
var ast = parseAnimationAst([
animate(1000, keyframes([
style({"width": 0}),
style({"width": 25}),
style({"width": 50}),
style({"width": 75})
]))
]);
var ast = parseAnimationAst([animate(1000, keyframes([
style({'width': 0}), style({'width': 25}),
style({'width': 50}), style({'width': 75})
]))]);
var step = <AnimationStepAst>ast.steps[0];
expect(step.keyframes.length).toEqual(4);
@ -277,14 +227,11 @@ export function main() {
});
it('should use an existing collection of offset steps if provided', () => {
var ast = parseAnimationAst([
animate(1000, keyframes([
style({"height": 0, "offset": 0}),
style({"height": 25, "offset": 0.6}),
style({"height": 50, "offset": 0.7}),
style({"height": 75, "offset": 1})
]))
]);
var ast = parseAnimationAst(
[animate(1000, keyframes([
style({'height': 0, 'offset': 0}), style({'height': 25, 'offset': 0.6}),
style({'height': 50, 'offset': 0.7}), style({'height': 75, 'offset': 1})
]))]);
var step = <AnimationStepAst>ast.steps[0];
expect(step.keyframes.length).toEqual(4);
@ -296,14 +243,11 @@ export function main() {
});
it('should sort the provided collection of steps that contain offsets', () => {
var ast = parseAnimationAst([
animate(1000, keyframes([
style({"opacity": 0, "offset": 0.9}),
style({"opacity": .25, "offset": 0}),
style({"opacity": .50, "offset": 1}),
style({"opacity": .75, "offset": 0.91})
]))
]);
var ast = parseAnimationAst([animate(
1000, keyframes([
style({'opacity': 0, 'offset': 0.9}), style({'opacity': .25, 'offset': 0}),
style({'opacity': .50, 'offset': 1}), style({'opacity': .75, 'offset': 0.91})
]))]);
var step = <AnimationStepAst>ast.steps[0];
expect(step.keyframes.length).toEqual(4);
@ -322,13 +266,11 @@ export function main() {
});
it('should throw an error if a partial amount of keyframes contain an offset', () => {
var errors = parseAnimationAndGetErrors([
animate(1000, keyframes([
style({"z-index": 0, "offset": 0}),
style({"z-index": 1}),
style({"z-index": 2, "offset": 1})
]))
]);
var errors = parseAnimationAndGetErrors(
[animate(1000, keyframes([
style({'z-index': 0, 'offset': 0}), style({'z-index': 1}),
style({'z-index': 2, 'offset': 1})
]))]);
expect(errors.length).toEqual(1);
var error = errors[0];
@ -336,106 +278,107 @@ export function main() {
expect(error.msg).toMatchPattern(/Not all style\(\) entries contain an offset/);
});
it('should use an existing style used earlier in the animation sequence if not defined in the first keyframe', () => {
var ast = parseAnimationAst([
animate(1000, keyframes([
style({"color": "red"}),
style({"background": "blue", "color": "white"})
]))
]);
it('should use an existing style used earlier in the animation sequence if not defined in the first keyframe',
() => {
var ast = parseAnimationAst([animate(
1000,
keyframes(
[style({'color': 'red'}), style({'background': 'blue', 'color': 'white'})]))]);
var keyframesStep = <AnimationStepAst>ast.steps[0];
var kf1 = keyframesStep.keyframes[0];
var kf2 = keyframesStep.keyframes[1];
var keyframesStep = <AnimationStepAst>ast.steps[0];
var kf1 = keyframesStep.keyframes[0];
var kf2 = keyframesStep.keyframes[1];
expect(flattenStyles(kf1.styles.styles)).toEqual({
"color": "red",
"background": FILL_STYLE_FLAG
});
});
expect(flattenStyles(kf1.styles.styles))
.toEqual({'color': 'red', 'background': FILL_STYLE_FLAG});
});
it('should copy over any missing styles to the final keyframe if not already defined', () => {
var ast = parseAnimationAst([
animate(1000, keyframes([
style({"color": "white", "border-color":"white"}),
style({"color": "red", "background": "blue"}),
style({"background": "blue" })
]))
]);
var ast = parseAnimationAst([animate(
1000, keyframes([
style({'color': 'white', 'border-color': 'white'}),
style({'color': 'red', 'background': 'blue'}), style({'background': 'blue'})
]))]);
var keyframesStep = <AnimationStepAst>ast.steps[0];
var kf1 = keyframesStep.keyframes[0];
var kf2 = keyframesStep.keyframes[1];
var kf3 = keyframesStep.keyframes[2];
expect(flattenStyles(kf3.styles.styles)).toEqual({
"background": "blue",
"color": "red",
"border-color": "white"
});
expect(flattenStyles(kf3.styles.styles))
.toEqual({'background': 'blue', 'color': 'red', 'border-color': 'white'});
});
it('should create an initial keyframe if not detected and place all keyframes styles there', () => {
var ast = parseAnimationAst([
animate(1000, keyframes([
style({"color": "white", "background": "black", "offset": 0.5}),
style({"color": "orange", "background": "red", "font-size": "100px", "offset": 1})
]))
]);
it('should create an initial keyframe if not detected and place all keyframes styles there',
() => {
var ast = parseAnimationAst(
[animate(1000, keyframes([
style({'color': 'white', 'background': 'black', 'offset': 0.5}), style({
'color': 'orange',
'background': 'red',
'font-size': '100px',
'offset': 1
})
]))]);
var keyframesStep = <AnimationStepAst>ast.steps[0];
expect(keyframesStep.keyframes.length).toEqual(3);
var kf1 = keyframesStep.keyframes[0];
var kf2 = keyframesStep.keyframes[1];
var kf3 = keyframesStep.keyframes[2];
var keyframesStep = <AnimationStepAst>ast.steps[0];
expect(keyframesStep.keyframes.length).toEqual(3);
var kf1 = keyframesStep.keyframes[0];
var kf2 = keyframesStep.keyframes[1];
var kf3 = keyframesStep.keyframes[2];
expect(kf1.offset).toEqual(0);
expect(flattenStyles(kf1.styles.styles)).toEqual({
"font-size": FILL_STYLE_FLAG,
"background": FILL_STYLE_FLAG,
"color": FILL_STYLE_FLAG
});
});
expect(kf1.offset).toEqual(0);
expect(flattenStyles(kf1.styles.styles)).toEqual({
'font-size': FILL_STYLE_FLAG,
'background': FILL_STYLE_FLAG,
'color': FILL_STYLE_FLAG
});
});
it('should create an destination keyframe if not detected and place all keyframes styles there', () => {
var ast = parseAnimationAst([
animate(1000, keyframes([
style({"color": "white", "background": "black", "transform": "rotate(360deg)", "offset": 0}),
style({"color": "orange", "background": "red", "font-size": "100px", "offset": 0.5})
]))
]);
it('should create an destination keyframe if not detected and place all keyframes styles there',
() => {
var ast = parseAnimationAst([animate(1000, keyframes([
style({
'color': 'white',
'background': 'black',
'transform': 'rotate(360deg)',
'offset': 0
}),
style({
'color': 'orange',
'background': 'red',
'font-size': '100px',
'offset': 0.5
})
]))]);
var keyframesStep = <AnimationStepAst>ast.steps[0];
expect(keyframesStep.keyframes.length).toEqual(3);
var kf1 = keyframesStep.keyframes[0];
var kf2 = keyframesStep.keyframes[1];
var kf3 = keyframesStep.keyframes[2];
var keyframesStep = <AnimationStepAst>ast.steps[0];
expect(keyframesStep.keyframes.length).toEqual(3);
var kf1 = keyframesStep.keyframes[0];
var kf2 = keyframesStep.keyframes[1];
var kf3 = keyframesStep.keyframes[2];
expect(kf3.offset).toEqual(1);
expect(flattenStyles(kf3.styles.styles)).toEqual({
"color": "orange",
"background": "red",
"transform": "rotate(360deg)",
"font-size": "100px"
});
});
expect(kf3.offset).toEqual(1);
expect(flattenStyles(kf3.styles.styles)).toEqual({
'color': 'orange',
'background': 'red',
'transform': 'rotate(360deg)',
'font-size': '100px'
});
});
describe('easing / duration / delay', () => {
it('should parse simple string-based values', () => {
var ast = parseAnimationAst([
animate("1s .5s ease-out", style({ "opacity": 1 }))
]);
var ast = parseAnimationAst([animate('1s .5s ease-out', style({'opacity': 1}))]);
var step = <AnimationStepAst>ast.steps[0];
expect(step.duration).toEqual(1000);
expect(step.delay).toEqual(500);
expect(step.easing).toEqual("ease-out");
expect(step.easing).toEqual('ease-out');
});
it('should parse a numeric duration value', () => {
var ast = parseAnimationAst([
animate(666, style({ "opacity": 1 }))
]);
var ast = parseAnimationAst([animate(666, style({'opacity': 1}))]);
var step = <AnimationStepAst>ast.steps[0];
expect(step.duration).toEqual(666);
@ -444,25 +387,22 @@ export function main() {
});
it('should parse an easing value without a delay', () => {
var ast = parseAnimationAst([
animate("5s linear", style({ "opacity": 1 }))
]);
var ast = parseAnimationAst([animate('5s linear', style({'opacity': 1}))]);
var step = <AnimationStepAst>ast.steps[0];
expect(step.duration).toEqual(5000);
expect(step.delay).toEqual(0);
expect(step.easing).toEqual("linear");
expect(step.easing).toEqual('linear');
});
it('should parse a complex easing value', () => {
var ast = parseAnimationAst([
animate("30ms cubic-bezier(0, 0,0, .69)", style({ "opacity": 1 }))
]);
var ast =
parseAnimationAst([animate('30ms cubic-bezier(0, 0,0, .69)', style({'opacity': 1}))]);
var step = <AnimationStepAst>ast.steps[0];
expect(step.duration).toEqual(30);
expect(step.delay).toEqual(0);
expect(step.easing).toEqual("cubic-bezier(0, 0,0, .69)");
expect(step.easing).toEqual('cubic-bezier(0, 0,0, .69)');
});
});
});

View File

@ -1,38 +1,12 @@
import {
beforeEach,
ddescribe,
describe,
expect,
iit,
inject,
it,
xit,
} from '@angular/core/testing/testing_internal';
import {beforeEach, ddescribe, describe, expect, iit, inject, it, xit,} from '@angular/core/testing/testing_internal';
import {
CompileDirectiveMetadata,
CompileTypeMetadata,
CompileTemplateMetadata,
CompileProviderMetadata,
CompileDiDependencyMetadata,
CompileQueryMetadata,
CompileIdentifierMetadata,
CompileFactoryMetadata,
CompileTokenMetadata,
CompileAnimationEntryMetadata,
CompileAnimationStyleMetadata,
CompileAnimationAnimateMetadata,
CompileAnimationSequenceMetadata,
CompileAnimationStateTransitionMetadata,
CompileAnimationKeyframesSequenceMetadata,
CompileAnimationGroupMetadata
} from '@angular/compiler/src/compile_metadata';
import {CompileDirectiveMetadata, CompileTypeMetadata, CompileTemplateMetadata, CompileProviderMetadata, CompileDiDependencyMetadata, CompileQueryMetadata, CompileIdentifierMetadata, CompileFactoryMetadata, CompileTokenMetadata, CompileAnimationEntryMetadata, CompileAnimationStyleMetadata, CompileAnimationAnimateMetadata, CompileAnimationSequenceMetadata, CompileAnimationStateTransitionMetadata, CompileAnimationKeyframesSequenceMetadata, CompileAnimationGroupMetadata} from '@angular/compiler/src/compile_metadata';
import {ViewEncapsulation} from '@angular/core/src/metadata/view';
import {ChangeDetectionStrategy} from '@angular/core/src/change_detection';
import {LifecycleHooks} from '@angular/core/src/metadata/lifecycle_hooks';
export function main() {
describe('CompileMetadata', () => {
describe('CompileMetadata', () => {
var fullTypeMeta: CompileTypeMetadata;
var fullTemplateMeta: CompileTemplateMetadata;
var fullDirectiveMeta: CompileDirectiveMetadata;
@ -67,17 +41,14 @@ export function main() {
templateUrl: 'someTemplateUrl',
styles: ['someStyle'],
styleUrls: ['someStyleUrl'],
animations: [
new CompileAnimationEntryMetadata('animation', [
new CompileAnimationStateTransitionMetadata('* => *',
new CompileAnimationSequenceMetadata([
new CompileAnimationStyleMetadata(0, [{ 'opacity': 0 }]),
new CompileAnimationAnimateMetadata(1000,
new CompileAnimationStyleMetadata(0, [{ 'opacity': 1 }]))
])
)
])
],
animations: [new CompileAnimationEntryMetadata(
'animation',
[new CompileAnimationStateTransitionMetadata(
'* => *', new CompileAnimationSequenceMetadata([
new CompileAnimationStyleMetadata(0, [{'opacity': 0}]),
new CompileAnimationAnimateMetadata(
1000, new CompileAnimationStyleMetadata(0, [{'opacity': 1}]))
]))])],
ngContentSelectors: ['*']
});
fullDirectiveMeta = CompileDirectiveMetadata.create({
@ -90,47 +61,39 @@ export function main() {
outputs: ['someEvent'],
host: {'(event1)': 'handler1', '[prop1]': 'expr1', 'attr1': 'attrValue2'},
lifecycleHooks: [LifecycleHooks.OnChanges],
providers: [
new CompileProviderMetadata({
token: new CompileTokenMetadata({value: 'token'}),
multi: true,
useClass: fullTypeMeta,
useExisting: new CompileTokenMetadata({
identifier: new CompileIdentifierMetadata({name: 'someName'}),
identifierIsInstance: true
}),
useFactory: new CompileFactoryMetadata({name: 'someName', diDeps: [diDep]}),
useValue: 'someValue',
})
],
viewProviders: [
new CompileProviderMetadata({
token: new CompileTokenMetadata({value: 'token'}),
useClass: fullTypeMeta,
useExisting: new CompileTokenMetadata(
{identifier: new CompileIdentifierMetadata({name: 'someName'})}),
useFactory: new CompileFactoryMetadata({name: 'someName', diDeps: [diDep]}),
useValue: 'someValue'
})
],
queries: [
new CompileQueryMetadata({
selectors: [new CompileTokenMetadata({value: 'selector'})],
descendants: true,
first: false,
propertyName: 'prop',
read: new CompileTokenMetadata({value: 'readToken'})
})
],
viewQueries: [
new CompileQueryMetadata({
selectors: [new CompileTokenMetadata({value: 'selector'})],
descendants: true,
first: false,
propertyName: 'prop',
read: new CompileTokenMetadata({value: 'readToken'})
})
]
providers: [new CompileProviderMetadata({
token: new CompileTokenMetadata({value: 'token'}),
multi: true,
useClass: fullTypeMeta,
useExisting: new CompileTokenMetadata({
identifier: new CompileIdentifierMetadata({name: 'someName'}),
identifierIsInstance: true
}),
useFactory: new CompileFactoryMetadata({name: 'someName', diDeps: [diDep]}),
useValue: 'someValue',
})],
viewProviders: [new CompileProviderMetadata({
token: new CompileTokenMetadata({value: 'token'}),
useClass: fullTypeMeta,
useExisting: new CompileTokenMetadata(
{identifier: new CompileIdentifierMetadata({name: 'someName'})}),
useFactory: new CompileFactoryMetadata({name: 'someName', diDeps: [diDep]}),
useValue: 'someValue'
})],
queries: [new CompileQueryMetadata({
selectors: [new CompileTokenMetadata({value: 'selector'})],
descendants: true,
first: false,
propertyName: 'prop',
read: new CompileTokenMetadata({value: 'readToken'})
})],
viewQueries: [new CompileQueryMetadata({
selectors: [new CompileTokenMetadata({value: 'selector'})],
descendants: true,
first: false,
propertyName: 'prop',
read: new CompileTokenMetadata({value: 'readToken'})
})]
});
});
@ -186,7 +149,7 @@ export function main() {
describe('CompileAnimationStyleMetadata', () => {
it('should serialize with full data', () => {
let full = new CompileAnimationStyleMetadata(0, [{ "opacity": 0, "color": "red" }]);
let full = new CompileAnimationStyleMetadata(0, [{'opacity': 0, 'color': 'red'}]);
expect(CompileAnimationStyleMetadata.fromJson(full.toJson())).toEqual(full);
});
@ -198,8 +161,8 @@ export function main() {
describe('CompileAnimationAnimateMetadata', () => {
it('should serialize with full data', () => {
let full = new CompileAnimationAnimateMetadata("1s linear",
new CompileAnimationStyleMetadata(0, [{ "opacity": 0.5, "color": "blue" }]))
let full = new CompileAnimationAnimateMetadata(
'1s linear', new CompileAnimationStyleMetadata(0, [{'opacity': 0.5, 'color': 'blue'}]))
expect(CompileAnimationAnimateMetadata.fromJson(full.toJson())).toEqual(full);
});
@ -212,9 +175,9 @@ export function main() {
describe('CompileAnimationSequenceMetadata', () => {
it('should serialize with full data', () => {
let full = new CompileAnimationSequenceMetadata([
new CompileAnimationStyleMetadata(0, [{ "opacity": 0.5, "width": 100 }]),
new CompileAnimationAnimateMetadata(1000,
new CompileAnimationStyleMetadata(0, [{ "opacity": 1, "width": 0 }]))
new CompileAnimationStyleMetadata(0, [{'opacity': 0.5, 'width': 100}]),
new CompileAnimationAnimateMetadata(
1000, new CompileAnimationStyleMetadata(0, [{'opacity': 1, 'width': 0}]))
]);
expect(CompileAnimationSequenceMetadata.fromJson(full.toJson())).toEqual(full);
});
@ -228,9 +191,10 @@ export function main() {
describe('CompileAnimationGroupMetadata', () => {
it('should serialize with full data', () => {
let full = new CompileAnimationGroupMetadata([
new CompileAnimationStyleMetadata(0, [{ "width": 100, "border": "1px solid red" }]),
new CompileAnimationAnimateMetadata(1000,
new CompileAnimationStyleMetadata(0, [{ "width": 900, "border": "10px solid blue" }]))
new CompileAnimationStyleMetadata(0, [{'width': 100, 'border': '1px solid red'}]),
new CompileAnimationAnimateMetadata(
1000, new CompileAnimationStyleMetadata(
0, [{'width': 900, 'border': '10px solid blue'}]))
]);
expect(CompileAnimationGroupMetadata.fromJson(full.toJson())).toEqual(full);
});
@ -244,9 +208,9 @@ export function main() {
describe('CompileAnimationKeyframesSequenceMetadata', () => {
it('should serialize with full data', () => {
let full = new CompileAnimationKeyframesSequenceMetadata([
new CompileAnimationStyleMetadata(0, [{ "width": 0 }]),
new CompileAnimationStyleMetadata(0.5, [{ "width": 100 }]),
new CompileAnimationStyleMetadata(1, [{ "width": 200 }]),
new CompileAnimationStyleMetadata(0, [{'width': 0}]),
new CompileAnimationStyleMetadata(0.5, [{'width': 100}]),
new CompileAnimationStyleMetadata(1, [{'width': 200}]),
]);
expect(CompileAnimationKeyframesSequenceMetadata.fromJson(full.toJson())).toEqual(full);
});
@ -259,15 +223,13 @@ export function main() {
describe('CompileAnimationEntryMetadata', () => {
it('should serialize with full data', () => {
let full = new CompileAnimationEntryMetadata('name', [
new CompileAnimationStateTransitionMetadata('key => value',
new CompileAnimationSequenceMetadata([
new CompileAnimationStyleMetadata(0, [{ "color": "red" }]),
new CompileAnimationAnimateMetadata(1000,
new CompileAnimationStyleMetadata(0, [{ "color": "blue" }]))
])
)
]);
let full = new CompileAnimationEntryMetadata(
'name', [new CompileAnimationStateTransitionMetadata(
'key => value', new CompileAnimationSequenceMetadata([
new CompileAnimationStyleMetadata(0, [{'color': 'red'}]),
new CompileAnimationAnimateMetadata(
1000, new CompileAnimationStyleMetadata(0, [{'color': 'blue'}]))
]))]);
expect(CompileAnimationEntryMetadata.fromJson(full.toJson())).toEqual(full);
});

View File

@ -1,27 +1,12 @@
import {
ddescribe,
describe,
it,
iit,
xit,
expect,
beforeEach,
afterEach
} from '@angular/core/testing/testing_internal';
import {CssLexer, CssLexerMode, CssScannerError, CssToken, CssTokenType} from '@angular/compiler/src/css/lexer';
import {afterEach, beforeEach, ddescribe, describe, expect, iit, it, xit} from '@angular/core/testing/testing_internal';
import {isPresent} from '../../src/facade/lang';
import {
CssToken,
CssScannerError,
CssLexer,
CssLexerMode,
CssTokenType
} from '@angular/compiler/src/css/lexer';
export function main() {
function tokenize(code: any /** TODO #9100 */, trackComments: boolean = false,
mode: CssLexerMode = CssLexerMode.ALL): CssToken[] {
function tokenize(
code: any /** TODO #9100 */, trackComments: boolean = false,
mode: CssLexerMode = CssLexerMode.ALL): CssToken[] {
var scanner = new CssLexer().scan(code, trackComments);
scanner.setMode(mode);
@ -41,7 +26,7 @@ export function main() {
describe('CssLexer', () => {
it('should lex newline characters as whitespace when whitespace mode is on', () => {
var newlines = ["\n", "\r\n", "\r", "\f"];
var newlines = ['\n', '\r\n', '\r', '\f'];
newlines.forEach((line) => {
var token = tokenize(line, false, CssLexerMode.ALL_TRACK_WS)[0];
expect(token.type).toEqual(CssTokenType.Whitespace);
@ -49,7 +34,7 @@ export function main() {
});
it('should combined newline characters as one newline token when whitespace mode is on', () => {
var newlines = ["\n", "\r\n", "\r", "\f"].join("");
var newlines = ['\n', '\r\n', '\r', '\f'].join('');
var tokens = tokenize(newlines, false, CssLexerMode.ALL_TRACK_WS);
expect(tokens.length).toEqual(1);
expect(tokens[0].type).toEqual(CssTokenType.Whitespace);
@ -57,13 +42,14 @@ export function main() {
it('should not consider whitespace or newline values at all when whitespace mode is off',
() => {
var newlines = ["\n", "\r\n", "\r", "\f"].join("");
var newlines = ['\n', '\r\n', '\r', '\f'].join('');
var tokens = tokenize(newlines);
expect(tokens.length).toEqual(0);
});
it('should lex simple selectors and their inner properties', () => {
var cssCode = "\n" + " .selector { my-prop: my-value; }\n";
var cssCode = '\n' +
' .selector { my-prop: my-value; }\n';
var tokens = tokenize(cssCode);
expect(tokens[0].type).toEqual(CssTokenType.Character);
@ -92,7 +78,9 @@ export function main() {
});
it('should capture the column and line values for each token', () => {
var cssCode = "#id {\n" + " prop:value;\n" + "}";
var cssCode = '#id {\n' +
' prop:value;\n' +
'}';
var tokens = tokenize(cssCode);
@ -138,13 +126,13 @@ export function main() {
});
it('should lex quoted strings and escape accordingly', () => {
var cssCode = "prop: 'some { value } \\' that is quoted'";
var cssCode = 'prop: \'some { value } \\\' that is quoted\'';
var tokens = tokenize(cssCode);
expect(tokens[0].type).toEqual(CssTokenType.Identifier);
expect(tokens[1].type).toEqual(CssTokenType.Character);
expect(tokens[2].type).toEqual(CssTokenType.String);
expect(tokens[2].strValue).toEqual("'some { value } \\' that is quoted'");
expect(tokens[2].strValue).toEqual('\'some { value } \\\' that is quoted\'');
});
it('should treat attribute operators as regular characters', () => {
@ -152,27 +140,27 @@ export function main() {
});
it('should lex numbers properly and set them as numbers', () => {
var cssCode = "0 1 -2 3.0 -4.001";
var cssCode = '0 1 -2 3.0 -4.001';
var tokens = tokenize(cssCode);
expect(tokens[0].type).toEqual(CssTokenType.Number);
expect(tokens[0].strValue).toEqual("0");
expect(tokens[0].strValue).toEqual('0');
expect(tokens[1].type).toEqual(CssTokenType.Number);
expect(tokens[1].strValue).toEqual("1");
expect(tokens[1].strValue).toEqual('1');
expect(tokens[2].type).toEqual(CssTokenType.Number);
expect(tokens[2].strValue).toEqual("-2");
expect(tokens[2].strValue).toEqual('-2');
expect(tokens[3].type).toEqual(CssTokenType.Number);
expect(tokens[3].strValue).toEqual("3.0");
expect(tokens[3].strValue).toEqual('3.0');
expect(tokens[4].type).toEqual(CssTokenType.Number);
expect(tokens[4].strValue).toEqual("-4.001");
expect(tokens[4].strValue).toEqual('-4.001');
});
it('should lex @keywords', () => {
var cssCode = "@import()@something";
var cssCode = '@import()@something';
var tokens = tokenize(cssCode);
expect(tokens[0].type).toEqual(CssTokenType.AtKeyword);
@ -189,7 +177,7 @@ export function main() {
});
it('should still lex a number even if it has a dimension suffix', () => {
var cssCode = "40% is 40 percent";
var cssCode = '40% is 40 percent';
var tokens = tokenize(cssCode);
expect(tokens[0].type).toEqual(CssTokenType.Number);
@ -206,7 +194,7 @@ export function main() {
});
it('should allow escaped character and unicode character-strings in CSS selectors', () => {
var cssCode = "\\123456 .some\\thing \{\}";
var cssCode = '\\123456 .some\\thing \{\}';
var tokens = tokenize(cssCode);
expect(tokens[0].type).toEqual(CssTokenType.Identifier);
@ -218,67 +206,67 @@ export function main() {
});
it('should distinguish identifiers and numbers from special characters', () => {
var cssCode = "one*two=-4+three-4-equals_value$";
var cssCode = 'one*two=-4+three-4-equals_value$';
var tokens = tokenize(cssCode);
expect(tokens[0].type).toEqual(CssTokenType.Identifier);
expect(tokens[0].strValue).toEqual("one");
expect(tokens[0].strValue).toEqual('one');
expect(tokens[1].type).toEqual(CssTokenType.Character);
expect(tokens[1].strValue).toEqual("*");
expect(tokens[1].strValue).toEqual('*');
expect(tokens[2].type).toEqual(CssTokenType.Identifier);
expect(tokens[2].strValue).toEqual("two");
expect(tokens[2].strValue).toEqual('two');
expect(tokens[3].type).toEqual(CssTokenType.Character);
expect(tokens[3].strValue).toEqual("=");
expect(tokens[3].strValue).toEqual('=');
expect(tokens[4].type).toEqual(CssTokenType.Number);
expect(tokens[4].strValue).toEqual("-4");
expect(tokens[4].strValue).toEqual('-4');
expect(tokens[5].type).toEqual(CssTokenType.Character);
expect(tokens[5].strValue).toEqual("+");
expect(tokens[5].strValue).toEqual('+');
expect(tokens[6].type).toEqual(CssTokenType.Identifier);
expect(tokens[6].strValue).toEqual("three-4-equals_value");
expect(tokens[6].strValue).toEqual('three-4-equals_value');
expect(tokens[7].type).toEqual(CssTokenType.Character);
expect(tokens[7].strValue).toEqual("$");
expect(tokens[7].strValue).toEqual('$');
});
it('should filter out comments and whitespace by default', () => {
var cssCode = ".selector /* comment */ { /* value */ }";
var cssCode = '.selector /* comment */ { /* value */ }';
var tokens = tokenize(cssCode);
expect(tokens[0].strValue).toEqual(".");
expect(tokens[1].strValue).toEqual("selector");
expect(tokens[2].strValue).toEqual("{");
expect(tokens[3].strValue).toEqual("}");
expect(tokens[0].strValue).toEqual('.');
expect(tokens[1].strValue).toEqual('selector');
expect(tokens[2].strValue).toEqual('{');
expect(tokens[3].strValue).toEqual('}');
});
it('should track comments when the flag is set to true', () => {
var cssCode = ".selector /* comment */ { /* value */ }";
var cssCode = '.selector /* comment */ { /* value */ }';
var trackComments = true;
var tokens = tokenize(cssCode, trackComments, CssLexerMode.ALL_TRACK_WS);
expect(tokens[0].strValue).toEqual(".");
expect(tokens[1].strValue).toEqual("selector");
expect(tokens[2].strValue).toEqual(" ");
expect(tokens[0].strValue).toEqual('.');
expect(tokens[1].strValue).toEqual('selector');
expect(tokens[2].strValue).toEqual(' ');
expect(tokens[3].type).toEqual(CssTokenType.Comment);
expect(tokens[3].strValue).toEqual("/* comment */");
expect(tokens[3].strValue).toEqual('/* comment */');
expect(tokens[4].strValue).toEqual(" ");
expect(tokens[5].strValue).toEqual("{");
expect(tokens[6].strValue).toEqual(" ");
expect(tokens[4].strValue).toEqual(' ');
expect(tokens[5].strValue).toEqual('{');
expect(tokens[6].strValue).toEqual(' ');
expect(tokens[7].type).toEqual(CssTokenType.Comment);
expect(tokens[7].strValue).toEqual("/* value */");
expect(tokens[7].strValue).toEqual('/* value */');
});
describe('Selector Mode', () => {
it('should throw an error if a selector is being parsed while in the wrong mode', () => {
var cssCode = ".class > tag";
var cssCode = '.class > tag';
var capturedMessage: any /** TODO #9100 */;
try {
@ -305,36 +293,38 @@ export function main() {
it('should consider attribute selectors as valid input and throw when an invalid modifier is used',
() => {
function tokenizeAttr(modifier: any /** TODO #9100 */) {
var cssCode = "value" + modifier + "='something'";
var cssCode = 'value' + modifier + '=\'something\'';
return tokenize(cssCode, false, CssLexerMode.ATTRIBUTE_SELECTOR);
}
expect(tokenizeAttr("*").length).toEqual(4);
expect(tokenizeAttr("|").length).toEqual(4);
expect(tokenizeAttr("^").length).toEqual(4);
expect(tokenizeAttr("$").length).toEqual(4);
expect(tokenizeAttr("~").length).toEqual(4);
expect(tokenizeAttr("").length).toEqual(3);
expect(tokenizeAttr('*').length).toEqual(4);
expect(tokenizeAttr('|').length).toEqual(4);
expect(tokenizeAttr('^').length).toEqual(4);
expect(tokenizeAttr('$').length).toEqual(4);
expect(tokenizeAttr('~').length).toEqual(4);
expect(tokenizeAttr('').length).toEqual(3);
expect(() => { tokenizeAttr("+"); }).toThrow();
expect(() => { tokenizeAttr('+'); }).toThrow();
});
});
describe('Media Query Mode', () => {
it('should validate media queries with a reduced subset of valid characters', () => {
function tokenizeQuery(code: any /** TODO #9100 */) { return tokenize(code, false, CssLexerMode.MEDIA_QUERY); }
function tokenizeQuery(code: any /** TODO #9100 */) {
return tokenize(code, false, CssLexerMode.MEDIA_QUERY);
}
// the reason why the numbers are so high is because MediaQueries keep
// track of the whitespace values
expect(tokenizeQuery("(prop: value)").length).toEqual(5);
expect(tokenizeQuery("(prop: value) and (prop2: value2)").length).toEqual(11);
expect(tokenizeQuery("tv and (prop: value)").length).toEqual(7);
expect(tokenizeQuery("print and ((prop: value) or (prop2: value2))").length).toEqual(15);
expect(tokenizeQuery("(content: 'something $ crazy inside &')").length).toEqual(5);
expect(tokenizeQuery('(prop: value)').length).toEqual(5);
expect(tokenizeQuery('(prop: value) and (prop2: value2)').length).toEqual(11);
expect(tokenizeQuery('tv and (prop: value)').length).toEqual(7);
expect(tokenizeQuery('print and ((prop: value) or (prop2: value2))').length).toEqual(15);
expect(tokenizeQuery('(content: \'something $ crazy inside &\')').length).toEqual(5);
expect(() => { tokenizeQuery("(max-height: 10 + 20)"); }).toThrow();
expect(() => { tokenizeQuery('(max-height: 10 + 20)'); }).toThrow();
expect(() => { tokenizeQuery("(max-height: fifty < 100)"); }).toThrow();
expect(() => { tokenizeQuery('(max-height: fifty < 100)'); }).toThrow();
});
});
@ -345,13 +335,13 @@ export function main() {
return tokenize(code, false, CssLexerMode.PSEUDO_SELECTOR);
}
expect(tokenizePseudo("lang(en-us)").length).toEqual(4);
expect(tokenizePseudo("hover").length).toEqual(1);
expect(tokenizePseudo("focus").length).toEqual(1);
expect(tokenizePseudo('lang(en-us)').length).toEqual(4);
expect(tokenizePseudo('hover').length).toEqual(1);
expect(tokenizePseudo('focus').length).toEqual(1);
expect(() => { tokenizePseudo("lang(something:broken)"); }).toThrow();
expect(() => { tokenizePseudo('lang(something:broken)'); }).toThrow();
expect(() => { tokenizePseudo("not(.selector)"); }).toThrow();
expect(() => { tokenizePseudo('not(.selector)'); }).toThrow();
});
});
@ -362,32 +352,35 @@ export function main() {
return tokenize(code, false, CssLexerMode.PSEUDO_SELECTOR);
}
expect(tokenizePseudo("lang(en-us)").length).toEqual(4);
expect(tokenizePseudo("hover").length).toEqual(1);
expect(tokenizePseudo("focus").length).toEqual(1);
expect(tokenizePseudo('lang(en-us)').length).toEqual(4);
expect(tokenizePseudo('hover').length).toEqual(1);
expect(tokenizePseudo('focus').length).toEqual(1);
expect(() => { tokenizePseudo("lang(something:broken)"); }).toThrow();
expect(() => { tokenizePseudo('lang(something:broken)'); }).toThrow();
expect(() => { tokenizePseudo("not(.selector)"); }).toThrow();
expect(() => { tokenizePseudo('not(.selector)'); }).toThrow();
});
});
describe('Style Block Mode', () => {
it('should style blocks with a reduced subset of valid characters', () => {
function tokenizeStyles(code: any /** TODO #9100 */) { return tokenize(code, false, CssLexerMode.STYLE_BLOCK); }
describe(
'Style Block Mode', () => {
it('should style blocks with a reduced subset of valid characters',
() => {
function tokenizeStyles(code: any /** TODO #9100 */) {
return tokenize(code, false, CssLexerMode.STYLE_BLOCK);
}
expect(tokenizeStyles(`
expect(tokenizeStyles(`
key: value;
prop: 100;
style: value3!important;
`).length)
.toEqual(14);
`).length).toEqual(14);
expect(() => tokenizeStyles(` key$: value; `)).toThrow();
expect(() => tokenizeStyles(` key: value$; `)).toThrow();
expect(() => tokenizeStyles(` key: value + 10; `)).toThrow();
expect(() => tokenizeStyles(` key: &value; `)).toThrow();
});
});
expect(() => tokenizeStyles(` key$: value; `)).toThrow();
expect(() => tokenizeStyles(` key: value$; `)).toThrow();
expect(() => tokenizeStyles(` key: value + 10; `)).toThrow();
expect(() => tokenizeStyles(` key: &value; `)).toThrow();
});
});
});
}

View File

@ -1,38 +1,9 @@
import {
ddescribe,
describe,
it,
iit,
xit,
expect,
beforeEach,
afterEach
} from '@angular/core/testing/testing_internal';
import {CssLexer} from '@angular/compiler/src/css/lexer';
import {BlockType, CssBlockAST, CssBlockDefinitionRuleAST, CssBlockRuleAST, CssDefinitionAST, CssInlineRuleAST, CssKeyframeDefinitionAST, CssKeyframeRuleAST, CssMediaQueryRuleAST, CssParseError, CssParser, CssRuleAST, CssSelectorAST, CssSelectorRuleAST, CssStyleSheetAST, CssStyleValueAST, ParsedCssResult} from '@angular/compiler/src/css/parser';
import {afterEach, beforeEach, ddescribe, describe, expect, iit, it, xit} from '@angular/core/testing/testing_internal';
import {BaseException} from '../../src/facade/exceptions';
import {
ParsedCssResult,
CssParser,
BlockType,
CssSelectorRuleAST,
CssKeyframeRuleAST,
CssKeyframeDefinitionAST,
CssBlockDefinitionRuleAST,
CssMediaQueryRuleAST,
CssBlockRuleAST,
CssInlineRuleAST,
CssStyleValueAST,
CssSelectorAST,
CssDefinitionAST,
CssStyleSheetAST,
CssRuleAST,
CssBlockAST,
CssParseError
} from '@angular/compiler/src/css/parser';
import {CssLexer} from '@angular/compiler/src/css/lexer';
export function assertTokens(tokens: any /** TODO #9100 */, valuesArr: any /** TODO #9100 */) {
for (var i = 0; i < tokens.length; i++) {
expect(tokens[i].strValue == valuesArr[i]);
@ -94,17 +65,17 @@ export function main() {
var rule = <CssSelectorRuleAST>ast.rules[0];
expect(rule.selectors.length).toBe(7);
assertTokens(rule.selectors[0].tokens, [".", "class"]);
assertTokens(rule.selectors[1].tokens, ["#", "id"]);
assertTokens(rule.selectors[2].tokens, ["tag"]);
assertTokens(rule.selectors[3].tokens, ["[", "attr", "]"]);
assertTokens(rule.selectors[4].tokens, ["key", " ", "+", " ", "value"]);
assertTokens(rule.selectors[5].tokens, ["*", " ", "value"]);
assertTokens(rule.selectors[6].tokens, [":", "-moz-any-link"]);
assertTokens(rule.selectors[0].tokens, ['.', 'class']);
assertTokens(rule.selectors[1].tokens, ['#', 'id']);
assertTokens(rule.selectors[2].tokens, ['tag']);
assertTokens(rule.selectors[3].tokens, ['[', 'attr', ']']);
assertTokens(rule.selectors[4].tokens, ['key', ' ', '+', ' ', 'value']);
assertTokens(rule.selectors[5].tokens, ['*', ' ', 'value']);
assertTokens(rule.selectors[6].tokens, [':', '-moz-any-link']);
var style1 = <CssDefinitionAST>rule.block.entries[0];
expect(style1.property.strValue).toEqual("prop");
assertTokens(style1.value.tokens, ["value123"]);
expect(style1.property.strValue).toEqual('prop');
assertTokens(style1.value.tokens, ['value123']);
});
it('should parse keyframe rules', () => {
@ -187,16 +158,16 @@ export function main() {
var importRule = <CssInlineRuleAST>ast.rules[0];
expect(importRule.type).toEqual(BlockType.Import);
assertTokens(importRule.value.tokens, ["url", "(", "remote", ".", "css", ")"]);
assertTokens(importRule.value.tokens, ['url', '(', 'remote', '.', 'css', ')']);
var charsetRule = <CssInlineRuleAST>ast.rules[1];
expect(charsetRule.type).toEqual(BlockType.Charset);
assertTokens(charsetRule.value.tokens, ["UTF-8"]);
assertTokens(charsetRule.value.tokens, ['UTF-8']);
var namespaceRule = <CssInlineRuleAST>ast.rules[2];
expect(namespaceRule.type).toEqual(BlockType.Namespace);
assertTokens(namespaceRule.value.tokens,
["ng", "url", "(", "http://angular.io/namespace/ng", ")"]);
assertTokens(
namespaceRule.value.tokens, ['ng', 'url', '(', 'http://angular.io/namespace/ng', ')']);
});
it('should parse CSS values that contain functions and leave the inner function data untokenized',
@ -217,11 +188,13 @@ export function main() {
expect(defs.length).toEqual(4);
assertTokens((<CssDefinitionAST>defs[0]).value.tokens, ['url', '(', 'matias.css', ')']);
assertTokens((<CssDefinitionAST>defs[1]).value.tokens,
['cubic-bezier', '(', '0.755, 0.050, 0.855, 0.060', ')']);
assertTokens(
(<CssDefinitionAST>defs[1]).value.tokens,
['cubic-bezier', '(', '0.755, 0.050, 0.855, 0.060', ')']);
assertTokens((<CssDefinitionAST>defs[2]).value.tokens, ['calc', '(', '100% - 50px', ')']);
assertTokens((<CssDefinitionAST>defs[3]).value.tokens,
['linear-gradient', '(', '45deg, rgba(100, 0, 0, 0.5), black', ')']);
assertTokens(
(<CssDefinitionAST>defs[3]).value.tokens,
['linear-gradient', '(', '45deg, rgba(100, 0, 0, 0.5), black', ')']);
});
it('should parse un-named block-level CSS values', () => {
@ -268,7 +241,7 @@ export function main() {
var importRule = <CssInlineRuleAST>ast.rules[0];
expect(importRule.type).toEqual(BlockType.Import);
assertTokens(importRule.value.tokens, ["url", "(", "something something", ")"]);
assertTokens(importRule.value.tokens, ['url', '(', 'something something', ')']);
var fontFaceRule = <CssBlockRuleAST>ast.rules[1];
expect(fontFaceRule.type).toEqual(BlockType.FontFace);
@ -333,7 +306,7 @@ export function main() {
expect(documentRule.type).toEqual(BlockType.Document);
var rule = <CssSelectorRuleAST>documentRule.block.entries[0];
expect(rule.strValue).toEqual("body");
expect(rule.strValue).toEqual('body');
});
it('should parse the @page rule', () => {
@ -351,11 +324,11 @@ export function main() {
var rules = ast.rules;
var pageRule1 = <CssBlockDefinitionRuleAST>rules[0];
expect(pageRule1.strValue).toEqual("one");
expect(pageRule1.strValue).toEqual('one');
expect(pageRule1.type).toEqual(BlockType.Page);
var pageRule2 = <CssBlockDefinitionRuleAST>rules[1];
expect(pageRule2.strValue).toEqual("two");
expect(pageRule2.strValue).toEqual('two');
expect(pageRule2.type).toEqual(BlockType.Page);
var selectorOne = <CssSelectorRuleAST>pageRule1.block.entries[0];
@ -411,15 +384,15 @@ export function main() {
expect(ast.rules.length).toEqual(3);
var rule1 = <CssSelectorRuleAST>ast.rules[0];
expect(rule1.selectors[0].strValue).toEqual("tag&");
expect(rule1.selectors[0].strValue).toEqual('tag&');
expect(rule1.block.entries.length).toEqual(1);
var rule2 = <CssSelectorRuleAST>ast.rules[1];
expect(rule2.selectors[0].strValue).toEqual(".%tag");
expect(rule2.selectors[0].strValue).toEqual('.%tag');
expect(rule2.block.entries.length).toEqual(1);
var rule3 = <CssSelectorRuleAST>ast.rules[2];
expect(rule3.selectors[0].strValue).toEqual("#tag$");
expect(rule3.selectors[0].strValue).toEqual('#tag$');
expect(rule3.block.entries.length).toEqual(1);
});

View File

@ -1,41 +1,9 @@
import {
ddescribe,
describe,
it,
iit,
xit,
expect,
beforeEach,
afterEach
} from '@angular/core/testing/testing_internal';
import {NumberWrapper, StringWrapper, isPresent} from '../../src/facade/lang';
import {BaseException} from '../../src/facade/exceptions';
import {
CssToken,
CssParser,
CssParseError,
BlockType,
CssAST,
CssSelectorRuleAST,
CssKeyframeRuleAST,
CssKeyframeDefinitionAST,
CssBlockDefinitionRuleAST,
CssMediaQueryRuleAST,
CssBlockRuleAST,
CssInlineRuleAST,
CssStyleValueAST,
CssSelectorAST,
CssDefinitionAST,
CssStyleSheetAST,
CssRuleAST,
CssBlockAST,
CssASTVisitor,
CssUnknownTokenListAST
} from '@angular/compiler/src/css/parser';
import {CssLexer} from '@angular/compiler/src/css/lexer';
import {BlockType, CssAST, CssASTVisitor, CssBlockAST, CssBlockDefinitionRuleAST, CssBlockRuleAST, CssDefinitionAST, CssInlineRuleAST, CssKeyframeDefinitionAST, CssKeyframeRuleAST, CssMediaQueryRuleAST, CssParseError, CssParser, CssRuleAST, CssSelectorAST, CssSelectorRuleAST, CssStyleSheetAST, CssStyleValueAST, CssToken, CssUnknownTokenListAST} from '@angular/compiler/src/css/parser';
import {afterEach, beforeEach, ddescribe, describe, expect, iit, it, xit} from '@angular/core/testing/testing_internal';
import {BaseException} from '../../src/facade/exceptions';
import {NumberWrapper, StringWrapper, isPresent} from '../../src/facade/lang';
function _assertTokens(tokens: any /** TODO #9100 */, valuesArr: any /** TODO #9100 */) {
for (var i = 0; i < tokens.length; i++) {
@ -46,56 +14,59 @@ function _assertTokens(tokens: any /** TODO #9100 */, valuesArr: any /** TODO #9
class MyVisitor implements CssASTVisitor {
captures: {[key: string]: any[]} = {};
_capture(method: any /** TODO #9100 */, ast: any /** TODO #9100 */, context: any /** TODO #9100 */) {
_capture(
method: any /** TODO #9100 */, ast: any /** TODO #9100 */, context: any /** TODO #9100 */) {
this.captures[method] = isPresent(this.captures[method]) ? this.captures[method] : [];
this.captures[method].push([ast, context]);
}
constructor(ast: CssStyleSheetAST, context?: any) { ast.visit(this, context); }
visitCssValue(ast: any /** TODO #9100 */, context?: any): void { this._capture("visitCssValue", ast, context); }
visitCssValue(ast: any /** TODO #9100 */, context?: any): void {
this._capture('visitCssValue', ast, context);
}
visitInlineCssRule(ast: any /** TODO #9100 */, context?: any): void {
this._capture("visitInlineCssRule", ast, context);
this._capture('visitInlineCssRule', ast, context);
}
visitCssKeyframeRule(ast: CssKeyframeRuleAST, context?: any): void {
this._capture("visitCssKeyframeRule", ast, context);
this._capture('visitCssKeyframeRule', ast, context);
ast.block.visit(this, context);
}
visitCssKeyframeDefinition(ast: CssKeyframeDefinitionAST, context?: any): void {
this._capture("visitCssKeyframeDefinition", ast, context);
this._capture('visitCssKeyframeDefinition', ast, context);
ast.block.visit(this, context);
}
visitCssMediaQueryRule(ast: CssMediaQueryRuleAST, context?: any): void {
this._capture("visitCssMediaQueryRule", ast, context);
this._capture('visitCssMediaQueryRule', ast, context);
ast.block.visit(this, context);
}
visitCssSelectorRule(ast: CssSelectorRuleAST, context?: any): void {
this._capture("visitCssSelectorRule", ast, context);
this._capture('visitCssSelectorRule', ast, context);
ast.selectors.forEach((selAST: CssSelectorAST) => { selAST.visit(this, context); });
ast.block.visit(this, context);
}
visitCssSelector(ast: CssSelectorAST, context?: any): void {
this._capture("visitCssSelector", ast, context);
this._capture('visitCssSelector', ast, context);
}
visitCssDefinition(ast: CssDefinitionAST, context?: any): void {
this._capture("visitCssDefinition", ast, context);
this._capture('visitCssDefinition', ast, context);
ast.value.visit(this, context);
}
visitCssBlock(ast: CssBlockAST, context?: any): void {
this._capture("visitCssBlock", ast, context);
this._capture('visitCssBlock', ast, context);
ast.entries.forEach((entryAST: CssAST) => { entryAST.visit(this, context); });
}
visitCssStyleSheet(ast: CssStyleSheetAST, context?: any): void {
this._capture("visitCssStyleSheet", ast, context);
this._capture('visitCssStyleSheet', ast, context);
ast.rules.forEach((ruleAST: CssRuleAST) => { ruleAST.visit(this, context); });
}
@ -208,7 +179,7 @@ export function main() {
expect(captures.length).toEqual(1);
var query1 = <CssMediaQueryRuleAST>captures[0][0];
_assertTokens(query1.query, ["all", "and", "(", "max-width", "100", "px", ")"]);
_assertTokens(query1.query, ['all', 'and', '(', 'max-width', '100', 'px', ')']);
expect(query1.block.entries.length).toEqual(1);
});

View File

@ -1,13 +1,4 @@
import {
beforeEach,
xdescribe,
ddescribe,
describe,
expect,
iit,
inject,
it,
} from '@angular/core/testing/testing_internal';
import {beforeEach, xdescribe, ddescribe, describe, expect, iit, inject, it,} from '@angular/core/testing/testing_internal';
import {hasLifecycleHook} from '@angular/compiler/src/directive_lifecycle_reflector';
import {LifecycleHooks} from '@angular/core/src/metadata/lifecycle_hooks';
@ -16,93 +7,93 @@ export function main() {
describe('Create DirectiveMetadata', () => {
describe('lifecycle', () => {
describe("ngOnChanges", () => {
it("should be true when the directive has the ngOnChanges method", () => {
describe('ngOnChanges', () => {
it('should be true when the directive has the ngOnChanges method', () => {
expect(hasLifecycleHook(LifecycleHooks.OnChanges, DirectiveWithOnChangesMethod))
.toBe(true);
});
it("should be false otherwise", () => {
it('should be false otherwise', () => {
expect(hasLifecycleHook(LifecycleHooks.OnChanges, DirectiveNoHooks)).toBe(false);
});
});
describe("ngOnDestroy", () => {
it("should be true when the directive has the ngOnDestroy method", () => {
describe('ngOnDestroy', () => {
it('should be true when the directive has the ngOnDestroy method', () => {
expect(hasLifecycleHook(LifecycleHooks.OnDestroy, DirectiveWithOnDestroyMethod))
.toBe(true);
});
it("should be false otherwise", () => {
it('should be false otherwise', () => {
expect(hasLifecycleHook(LifecycleHooks.OnDestroy, DirectiveNoHooks)).toBe(false);
});
});
describe("ngOnInit", () => {
it("should be true when the directive has the ngOnInit method", () => {
describe('ngOnInit', () => {
it('should be true when the directive has the ngOnInit method', () => {
expect(hasLifecycleHook(LifecycleHooks.OnInit, DirectiveWithOnInitMethod)).toBe(true);
});
it("should be false otherwise", () => {
it('should be false otherwise', () => {
expect(hasLifecycleHook(LifecycleHooks.OnInit, DirectiveNoHooks)).toBe(false);
});
});
describe("ngDoCheck", () => {
it("should be true when the directive has the ngDoCheck method", () => {
describe('ngDoCheck', () => {
it('should be true when the directive has the ngDoCheck method', () => {
expect(hasLifecycleHook(LifecycleHooks.DoCheck, DirectiveWithOnCheckMethod)).toBe(true);
});
it("should be false otherwise", () => {
it('should be false otherwise', () => {
expect(hasLifecycleHook(LifecycleHooks.DoCheck, DirectiveNoHooks)).toBe(false);
});
});
describe("ngAfterContentInit", () => {
it("should be true when the directive has the ngAfterContentInit method", () => {
expect(hasLifecycleHook(LifecycleHooks.AfterContentInit,
DirectiveWithAfterContentInitMethod))
describe('ngAfterContentInit', () => {
it('should be true when the directive has the ngAfterContentInit method', () => {
expect(hasLifecycleHook(
LifecycleHooks.AfterContentInit, DirectiveWithAfterContentInitMethod))
.toBe(true);
});
it("should be false otherwise", () => {
it('should be false otherwise', () => {
expect(hasLifecycleHook(LifecycleHooks.AfterContentInit, DirectiveNoHooks)).toBe(false);
});
});
describe("ngAfterContentChecked", () => {
it("should be true when the directive has the ngAfterContentChecked method", () => {
expect(hasLifecycleHook(LifecycleHooks.AfterContentChecked,
DirectiveWithAfterContentCheckedMethod))
describe('ngAfterContentChecked', () => {
it('should be true when the directive has the ngAfterContentChecked method', () => {
expect(hasLifecycleHook(
LifecycleHooks.AfterContentChecked, DirectiveWithAfterContentCheckedMethod))
.toBe(true);
});
it("should be false otherwise", () => {
it('should be false otherwise', () => {
expect(hasLifecycleHook(LifecycleHooks.AfterContentChecked, DirectiveNoHooks))
.toBe(false);
});
});
describe("ngAfterViewInit", () => {
it("should be true when the directive has the ngAfterViewInit method", () => {
describe('ngAfterViewInit', () => {
it('should be true when the directive has the ngAfterViewInit method', () => {
expect(hasLifecycleHook(LifecycleHooks.AfterViewInit, DirectiveWithAfterViewInitMethod))
.toBe(true);
});
it("should be false otherwise", () => {
it('should be false otherwise', () => {
expect(hasLifecycleHook(LifecycleHooks.AfterViewInit, DirectiveNoHooks)).toBe(false);
});
});
describe("ngAfterViewChecked", () => {
it("should be true when the directive has the ngAfterViewChecked method", () => {
expect(hasLifecycleHook(LifecycleHooks.AfterViewChecked,
DirectiveWithAfterViewCheckedMethod))
describe('ngAfterViewChecked', () => {
it('should be true when the directive has the ngAfterViewChecked method', () => {
expect(hasLifecycleHook(
LifecycleHooks.AfterViewChecked, DirectiveWithAfterViewCheckedMethod))
.toBe(true);
});
it("should be false otherwise", () => {
it('should be false otherwise', () => {
expect(hasLifecycleHook(LifecycleHooks.AfterViewChecked, DirectiveNoHooks)).toBe(false);
});
});

View File

@ -1,22 +1,12 @@
import {
beforeEach,
ddescribe,
describe,
expect,
iit,
inject,
it,
xit,
beforeEachProviders
} from '@angular/core/testing/testing_internal';
import {AsyncTestCompleter} from '@angular/core/testing/testing_internal';
import {CompileTypeMetadata, CompileTemplateMetadata} from '@angular/compiler/src/compile_metadata';
import {ViewEncapsulation} from '@angular/core/src/metadata/view';
import {CompilerConfig} from "@angular/compiler/src/config";
import {CompileTemplateMetadata, CompileTypeMetadata} from '@angular/compiler/src/compile_metadata';
import {CompilerConfig} from '@angular/compiler/src/config';
import {DirectiveNormalizer} from '@angular/compiler/src/directive_normalizer';
import {XHR} from '@angular/compiler/src/xhr';
import {MockXHR} from '@angular/compiler/testing';
import {ViewEncapsulation} from '@angular/core/src/metadata/view';
import {beforeEach, beforeEachProviders, ddescribe, describe, expect, iit, inject, it, xit} from '@angular/core/testing/testing_internal';
import {AsyncTestCompleter} from '@angular/core/testing/testing_internal';
import {TEST_PROVIDERS} from './test_bindings';
export function main() {
@ -35,154 +25,171 @@ export function main() {
describe('loadTemplate', () => {
describe('inline template', () => {
it('should store the template',
inject([AsyncTestCompleter, DirectiveNormalizer],
(async: AsyncTestCompleter, normalizer: DirectiveNormalizer) => {
normalizer.normalizeTemplate(dirType, new CompileTemplateMetadata({
encapsulation: null,
template: 'a',
templateUrl: null,
styles: [],
styleUrls: ['test.css']
}))
.then((template: CompileTemplateMetadata) => {
expect(template.template).toEqual('a');
expect(template.templateUrl).toEqual('package:some/module/a.js');
async.done();
});
}));
inject(
[AsyncTestCompleter, DirectiveNormalizer],
(async: AsyncTestCompleter, normalizer: DirectiveNormalizer) => {
normalizer
.normalizeTemplate(dirType, new CompileTemplateMetadata({
encapsulation: null,
template: 'a',
templateUrl: null,
styles: [],
styleUrls: ['test.css']
}))
.then((template: CompileTemplateMetadata) => {
expect(template.template).toEqual('a');
expect(template.templateUrl).toEqual('package:some/module/a.js');
async.done();
});
}));
it('should resolve styles on the annotation against the moduleUrl',
inject([AsyncTestCompleter, DirectiveNormalizer],
(async: AsyncTestCompleter, normalizer: DirectiveNormalizer) => {
normalizer.normalizeTemplate(dirType, new CompileTemplateMetadata({
encapsulation: null,
template: '',
templateUrl: null,
styles: [],
styleUrls: ['test.css']
}))
.then((template: CompileTemplateMetadata) => {
expect(template.styleUrls).toEqual(['package:some/module/test.css']);
async.done();
});
}));
inject(
[AsyncTestCompleter, DirectiveNormalizer],
(async: AsyncTestCompleter, normalizer: DirectiveNormalizer) => {
normalizer
.normalizeTemplate(dirType, new CompileTemplateMetadata({
encapsulation: null,
template: '',
templateUrl: null,
styles: [],
styleUrls: ['test.css']
}))
.then((template: CompileTemplateMetadata) => {
expect(template.styleUrls).toEqual(['package:some/module/test.css']);
async.done();
});
}));
it('should resolve styles in the template against the moduleUrl',
inject([AsyncTestCompleter, DirectiveNormalizer],
(async: AsyncTestCompleter, normalizer: DirectiveNormalizer) => {
normalizer.normalizeTemplate(dirType, new CompileTemplateMetadata({
encapsulation: null,
template: '<style>@import test.css</style>',
templateUrl: null,
styles: [],
styleUrls: []
}))
.then((template: CompileTemplateMetadata) => {
expect(template.styleUrls).toEqual(['package:some/module/test.css']);
async.done();
});
}));
inject(
[AsyncTestCompleter, DirectiveNormalizer],
(async: AsyncTestCompleter, normalizer: DirectiveNormalizer) => {
normalizer
.normalizeTemplate(dirType, new CompileTemplateMetadata({
encapsulation: null,
template: '<style>@import test.css</style>',
templateUrl: null,
styles: [],
styleUrls: []
}))
.then((template: CompileTemplateMetadata) => {
expect(template.styleUrls).toEqual(['package:some/module/test.css']);
async.done();
});
}));
it('should use ViewEncapsulation.Emulated by default',
inject([AsyncTestCompleter, DirectiveNormalizer],
(async: AsyncTestCompleter, normalizer: DirectiveNormalizer) => {
normalizer.normalizeTemplate(dirType, new CompileTemplateMetadata({
encapsulation: null,
template: '',
templateUrl: null,
styles: [],
styleUrls: ['test.css']
}))
.then((template: CompileTemplateMetadata) => {
expect(template.encapsulation).toEqual(ViewEncapsulation.Emulated);
async.done();
});
}));
inject(
[AsyncTestCompleter, DirectiveNormalizer],
(async: AsyncTestCompleter, normalizer: DirectiveNormalizer) => {
normalizer
.normalizeTemplate(dirType, new CompileTemplateMetadata({
encapsulation: null,
template: '',
templateUrl: null,
styles: [],
styleUrls: ['test.css']
}))
.then((template: CompileTemplateMetadata) => {
expect(template.encapsulation).toEqual(ViewEncapsulation.Emulated);
async.done();
});
}));
it('should use default encapsulation provided by CompilerConfig',
inject([AsyncTestCompleter, CompilerConfig , DirectiveNormalizer],
(async: AsyncTestCompleter, config: CompilerConfig, normalizer: DirectiveNormalizer) => {
config.defaultEncapsulation = ViewEncapsulation.None;
normalizer.normalizeTemplate(dirType, new CompileTemplateMetadata({
encapsulation: null,
template: '',
templateUrl: null,
styles: [],
styleUrls: ['test.css']
}))
.then((template: CompileTemplateMetadata) => {
expect(template.encapsulation).toEqual(ViewEncapsulation.None);
async.done();
});
}));
inject(
[AsyncTestCompleter, CompilerConfig, DirectiveNormalizer],
(async: AsyncTestCompleter, config: CompilerConfig,
normalizer: DirectiveNormalizer) => {
config.defaultEncapsulation = ViewEncapsulation.None;
normalizer
.normalizeTemplate(dirType, new CompileTemplateMetadata({
encapsulation: null,
template: '',
templateUrl: null,
styles: [],
styleUrls: ['test.css']
}))
.then((template: CompileTemplateMetadata) => {
expect(template.encapsulation).toEqual(ViewEncapsulation.None);
async.done();
});
}));
});
describe('templateUrl', () => {
it('should load a template from a url that is resolved against moduleUrl',
inject([AsyncTestCompleter, DirectiveNormalizer, XHR],
(async: AsyncTestCompleter, normalizer: DirectiveNormalizer, xhr: MockXHR) => {
xhr.expect('package:some/module/sometplurl.html', 'a');
normalizer.normalizeTemplate(dirType, new CompileTemplateMetadata({
encapsulation: null,
template: null,
templateUrl: 'sometplurl.html',
styles: [],
styleUrls: ['test.css']
}))
.then((template: CompileTemplateMetadata) => {
expect(template.template).toEqual('a');
expect(template.templateUrl)
.toEqual('package:some/module/sometplurl.html');
async.done();
});
xhr.flush();
}));
inject(
[AsyncTestCompleter, DirectiveNormalizer, XHR],
(async: AsyncTestCompleter, normalizer: DirectiveNormalizer, xhr: MockXHR) => {
xhr.expect('package:some/module/sometplurl.html', 'a');
normalizer
.normalizeTemplate(dirType, new CompileTemplateMetadata({
encapsulation: null,
template: null,
templateUrl: 'sometplurl.html',
styles: [],
styleUrls: ['test.css']
}))
.then((template: CompileTemplateMetadata) => {
expect(template.template).toEqual('a');
expect(template.templateUrl).toEqual('package:some/module/sometplurl.html');
async.done();
});
xhr.flush();
}));
it('should resolve styles on the annotation against the moduleUrl',
inject([AsyncTestCompleter, DirectiveNormalizer, XHR],
(async: AsyncTestCompleter, normalizer: DirectiveNormalizer, xhr: MockXHR) => {
xhr.expect('package:some/module/tpl/sometplurl.html', '');
normalizer.normalizeTemplate(dirType, new CompileTemplateMetadata({
encapsulation: null,
template: null,
templateUrl: 'tpl/sometplurl.html',
styles: [],
styleUrls: ['test.css']
}))
.then((template: CompileTemplateMetadata) => {
expect(template.styleUrls).toEqual(['package:some/module/test.css']);
async.done();
});
xhr.flush();
}));
inject(
[AsyncTestCompleter, DirectiveNormalizer, XHR],
(async: AsyncTestCompleter, normalizer: DirectiveNormalizer, xhr: MockXHR) => {
xhr.expect('package:some/module/tpl/sometplurl.html', '');
normalizer
.normalizeTemplate(dirType, new CompileTemplateMetadata({
encapsulation: null,
template: null,
templateUrl: 'tpl/sometplurl.html',
styles: [],
styleUrls: ['test.css']
}))
.then((template: CompileTemplateMetadata) => {
expect(template.styleUrls).toEqual(['package:some/module/test.css']);
async.done();
});
xhr.flush();
}));
it('should resolve styles in the template against the templateUrl',
inject([AsyncTestCompleter, DirectiveNormalizer, XHR],
(async: AsyncTestCompleter, normalizer: DirectiveNormalizer, xhr: MockXHR) => {
xhr.expect('package:some/module/tpl/sometplurl.html',
'<style>@import test.css</style>');
normalizer.normalizeTemplate(dirType, new CompileTemplateMetadata({
encapsulation: null,
template: null,
templateUrl: 'tpl/sometplurl.html',
styles: [],
styleUrls: []
}))
.then((template: CompileTemplateMetadata) => {
expect(template.styleUrls).toEqual(['package:some/module/tpl/test.css']);
async.done();
});
xhr.flush();
}));
inject(
[AsyncTestCompleter, DirectiveNormalizer, XHR],
(async: AsyncTestCompleter, normalizer: DirectiveNormalizer, xhr: MockXHR) => {
xhr.expect(
'package:some/module/tpl/sometplurl.html', '<style>@import test.css</style>');
normalizer
.normalizeTemplate(dirType, new CompileTemplateMetadata({
encapsulation: null,
template: null,
templateUrl: 'tpl/sometplurl.html',
styles: [],
styleUrls: []
}))
.then((template: CompileTemplateMetadata) => {
expect(template.styleUrls).toEqual(['package:some/module/tpl/test.css']);
async.done();
});
xhr.flush();
}));
});
it('should throw if no template was specified',
inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
expect(() => normalizer.normalizeTemplate(
dirType, new CompileTemplateMetadata(
{encapsulation: null, styles: [], styleUrls: []})))
expect(
() => normalizer.normalizeTemplate(
dirType,
new CompileTemplateMetadata({encapsulation: null, styles: [], styleUrls: []})))
.toThrowError('No template specified for component SomeComp');
}));

View File

@ -1,21 +1,6 @@
import {ddescribe, describe, it, iit, expect, beforeEach} from '@angular/core/testing';
import {DirectiveResolver} from '@angular/compiler/src/directive_resolver';
import {
DirectiveMetadata,
Directive,
Input,
Output,
HostBinding,
HostListener,
ContentChildren,
ContentChildrenMetadata,
ViewChildren,
ViewChildrenMetadata,
ContentChild,
ContentChildMetadata,
ViewChild,
ViewChildMetadata
} from '@angular/core/src/metadata';
import {ContentChild, ContentChildMetadata, ContentChildren, ContentChildrenMetadata, Directive, DirectiveMetadata, HostBinding, HostListener, Input, Output, ViewChild, ViewChildMetadata, ViewChildren, ViewChildrenMetadata} from '@angular/core/src/metadata';
import {beforeEach, ddescribe, describe, expect, iit, it} from '@angular/core/testing';
@Directive({selector: 'someDirective'})
class SomeDirective {
@ -28,14 +13,14 @@ class SomeChildDirective extends SomeDirective {
@Directive({selector: 'someDirective', inputs: ['c']})
class SomeDirectiveWithInputs {
@Input() a: any /** TODO #9100 */;
@Input("renamed") b: any /** TODO #9100 */;
@Input('renamed') b: any /** TODO #9100 */;
c: any /** TODO #9100 */;
}
@Directive({selector: 'someDirective', outputs: ['c']})
class SomeDirectiveWithOutputs {
@Output() a: any /** TODO #9100 */;
@Output("renamed") b: any /** TODO #9100 */;
@Output('renamed') b: any /** TODO #9100 */;
c: any /** TODO #9100 */;
}
@ -55,64 +40,59 @@ class SomeDirectiveWithEvents {
@Directive({selector: 'someDirective'})
class SomeDirectiveWithSetterProps {
@Input("renamed")
set a(value: any /** TODO #9100 */) {
}
@Input('renamed')
set a(value: any /** TODO #9100 */) {}
}
@Directive({selector: 'someDirective'})
class SomeDirectiveWithGetterOutputs {
@Output("renamed")
get a(): any /** TODO #9100 */ {
return null;
}
@Output('renamed')
get a(): any /** TODO #9100 */ { return null; }
}
@Directive({selector: 'someDirective', host: {'[c]': 'c'}})
class SomeDirectiveWithHostBindings {
@HostBinding() a: any /** TODO #9100 */;
@HostBinding("renamed") b: any /** TODO #9100 */;
@HostBinding('renamed') b: any /** TODO #9100 */;
c: any /** TODO #9100 */;
}
@Directive({selector: 'someDirective', host: {'(c)': 'onC()'}})
class SomeDirectiveWithHostListeners {
@HostListener('a')
onA() {
}
onA() {}
@HostListener('b', ['$event.value'])
onB(value: any /** TODO #9100 */) {
}
onB(value: any /** TODO #9100 */) {}
}
@Directive({selector: 'someDirective', queries: {"cs": new ContentChildren("c")}})
@Directive({selector: 'someDirective', queries: {'cs': new ContentChildren('c')}})
class SomeDirectiveWithContentChildren {
@ContentChildren("a") as: any;
@ContentChildren('a') as: any;
c: any /** TODO #9100 */;
}
@Directive({selector: 'someDirective', queries: {"cs": new ViewChildren("c")}})
@Directive({selector: 'someDirective', queries: {'cs': new ViewChildren('c')}})
class SomeDirectiveWithViewChildren {
@ViewChildren("a") as: any;
@ViewChildren('a') as: any;
c: any /** TODO #9100 */;
}
@Directive({selector: 'someDirective', queries: {"c": new ContentChild("c")}})
@Directive({selector: 'someDirective', queries: {'c': new ContentChild('c')}})
class SomeDirectiveWithContentChild {
@ContentChild("a") a: any;
@ContentChild('a') a: any;
c: any /** TODO #9100 */;
}
@Directive({selector: 'someDirective', queries: {"c": new ViewChild("c")}})
@Directive({selector: 'someDirective', queries: {'c': new ViewChild('c')}})
class SomeDirectiveWithViewChild {
@ViewChild("a") a: any;
@ViewChild('a') a: any;
c: any /** TODO #9100 */;
}
class SomeDirectiveWithoutMetadata {}
export function main() {
describe("DirectiveResolver", () => {
describe('DirectiveResolver', () => {
var resolver: DirectiveResolver;
beforeEach(() => { resolver = new DirectiveResolver(); });
@ -125,8 +105,9 @@ export function main() {
});
it('should throw if not matching metadata is found', () => {
expect(() => { resolver.resolve(SomeDirectiveWithoutMetadata); })
.toThrowError('No Directive annotation found on SomeDirectiveWithoutMetadata');
expect(() => {
resolver.resolve(SomeDirectiveWithoutMetadata);
}).toThrowError('No Directive annotation found on SomeDirectiveWithoutMetadata');
});
it('should not read parent class Directive metadata', function() {
@ -184,25 +165,25 @@ export function main() {
it('should append ContentChildren', () => {
var directiveMetadata = resolver.resolve(SomeDirectiveWithContentChildren);
expect(directiveMetadata.queries)
.toEqual({"cs": new ContentChildren("c"), "as": new ContentChildren("a")});
.toEqual({'cs': new ContentChildren('c'), 'as': new ContentChildren('a')});
});
it('should append ViewChildren', () => {
var directiveMetadata = resolver.resolve(SomeDirectiveWithViewChildren);
expect(directiveMetadata.queries)
.toEqual({"cs": new ViewChildren("c"), "as": new ViewChildren("a")});
.toEqual({'cs': new ViewChildren('c'), 'as': new ViewChildren('a')});
});
it('should append ContentChild', () => {
var directiveMetadata = resolver.resolve(SomeDirectiveWithContentChild);
expect(directiveMetadata.queries)
.toEqual({"c": new ContentChild("c"), "a": new ContentChild("a")});
.toEqual({'c': new ContentChild('c'), 'a': new ContentChild('a')});
});
it('should append ViewChild', () => {
var directiveMetadata = resolver.resolve(SomeDirectiveWithViewChild);
expect(directiveMetadata.queries)
.toEqual({"c": new ViewChild("c"), "a": new ViewChild("a")});
.toEqual({'c': new ViewChild('c'), 'a': new ViewChild('a')});
});
});
});

View File

@ -1,6 +1,5 @@
import {ddescribe, describe, it, expect} from '@angular/core/testing';
import {Lexer, Token} from '@angular/compiler/src/expression_parser/lexer';
import {ddescribe, describe, expect, it} from '@angular/core/testing';
import {StringWrapper} from '../../src/facade/lang';
@ -13,36 +12,42 @@ function expectToken(token: any /** TODO #9100 */, index: any /** TODO #9100 */)
expect(token.index).toEqual(index);
}
function expectCharacterToken(token: any /** TODO #9100 */, index: any /** TODO #9100 */, character: any /** TODO #9100 */) {
function expectCharacterToken(
token: any /** TODO #9100 */, index: any /** TODO #9100 */, character: any /** TODO #9100 */) {
expect(character.length).toBe(1);
expectToken(token, index);
expect(token.isCharacter(StringWrapper.charCodeAt(character, 0))).toBe(true);
}
function expectOperatorToken(token: any /** TODO #9100 */, index: any /** TODO #9100 */, operator: any /** TODO #9100 */) {
function expectOperatorToken(
token: any /** TODO #9100 */, index: any /** TODO #9100 */, operator: any /** TODO #9100 */) {
expectToken(token, index);
expect(token.isOperator(operator)).toBe(true);
}
function expectNumberToken(token: any /** TODO #9100 */, index: any /** TODO #9100 */, n: any /** TODO #9100 */) {
function expectNumberToken(
token: any /** TODO #9100 */, index: any /** TODO #9100 */, n: any /** TODO #9100 */) {
expectToken(token, index);
expect(token.isNumber()).toBe(true);
expect(token.toNumber()).toEqual(n);
}
function expectStringToken(token: any /** TODO #9100 */, index: any /** TODO #9100 */, str: any /** TODO #9100 */) {
function expectStringToken(
token: any /** TODO #9100 */, index: any /** TODO #9100 */, str: any /** TODO #9100 */) {
expectToken(token, index);
expect(token.isString()).toBe(true);
expect(token.toString()).toEqual(str);
}
function expectIdentifierToken(token: any /** TODO #9100 */, index: any /** TODO #9100 */, identifier: any /** TODO #9100 */) {
function expectIdentifierToken(
token: any /** TODO #9100 */, index: any /** TODO #9100 */, identifier: any /** TODO #9100 */) {
expectToken(token, index);
expect(token.isIdentifier()).toBe(true);
expect(token.toString()).toEqual(identifier);
}
function expectKeywordToken(token: any /** TODO #9100 */, index: any /** TODO #9100 */, keyword: any /** TODO #9100 */) {
function expectKeywordToken(
token: any /** TODO #9100 */, index: any /** TODO #9100 */, keyword: any /** TODO #9100 */) {
expectToken(token, index);
expect(token.isKeyword()).toBe(true);
expect(token.toString()).toEqual(keyword);
@ -52,13 +57,13 @@ export function main() {
describe('lexer', function() {
describe('token', function() {
it('should tokenize a simple identifier', function() {
var tokens: number[] = lex("j");
var tokens: number[] = lex('j');
expect(tokens.length).toEqual(1);
expectIdentifierToken(tokens[0], 0, 'j');
});
it('should tokenize a dotted identifier', function() {
var tokens: number[] = lex("j.k");
var tokens: number[] = lex('j.k');
expect(tokens.length).toEqual(3);
expectIdentifierToken(tokens[0], 0, 'j');
expectCharacterToken(tokens[1], 1, '.');
@ -66,35 +71,35 @@ export function main() {
});
it('should tokenize an operator', function() {
var tokens: number[] = lex("j-k");
var tokens: number[] = lex('j-k');
expect(tokens.length).toEqual(3);
expectOperatorToken(tokens[1], 1, '-');
});
it('should tokenize an indexed operator', function() {
var tokens: number[] = lex("j[k]");
var tokens: number[] = lex('j[k]');
expect(tokens.length).toEqual(4);
expectCharacterToken(tokens[1], 1, "[");
expectCharacterToken(tokens[3], 3, "]");
expectCharacterToken(tokens[1], 1, '[');
expectCharacterToken(tokens[3], 3, ']');
});
it('should tokenize numbers', function() {
var tokens: number[] = lex("88");
var tokens: number[] = lex('88');
expect(tokens.length).toEqual(1);
expectNumberToken(tokens[0], 0, 88);
});
it('should tokenize numbers within index ops',
function() { expectNumberToken(lex("a[22]")[2], 2, 22); });
function() { expectNumberToken(lex('a[22]')[2], 2, 22); });
it('should tokenize simple quoted strings',
function() { expectStringToken(lex('"a"')[0], 0, "a"); });
function() { expectStringToken(lex('"a"')[0], 0, 'a'); });
it('should tokenize quoted strings with escaped quotes',
function() { expectStringToken(lex('"a\\""')[0], 0, 'a"'); });
it('should tokenize a string', function() {
var tokens: Token[] = lex("j-a.bc[22]+1.3|f:'a\\\'c':\"d\\\"e\"");
var tokens: Token[] = lex('j-a.bc[22]+1.3|f:\'a\\\'c\':"d\\"e"');
expectIdentifierToken(tokens[0], 0, 'j');
expectOperatorToken(tokens[1], 1, '-');
expectIdentifierToken(tokens[2], 2, 'a');
@ -108,27 +113,27 @@ export function main() {
expectOperatorToken(tokens[10], 14, '|');
expectIdentifierToken(tokens[11], 15, 'f');
expectCharacterToken(tokens[12], 16, ':');
expectStringToken(tokens[13], 17, "a'c");
expectStringToken(tokens[13], 17, 'a\'c');
expectCharacterToken(tokens[14], 23, ':');
expectStringToken(tokens[15], 24, 'd"e');
});
it('should tokenize undefined', function() {
var tokens: Token[] = lex("undefined");
expectKeywordToken(tokens[0], 0, "undefined");
var tokens: Token[] = lex('undefined');
expectKeywordToken(tokens[0], 0, 'undefined');
expect(tokens[0].isKeywordUndefined()).toBe(true);
});
it('should ignore whitespace', function() {
var tokens: Token[] = lex("a \t \n \r b");
var tokens: Token[] = lex('a \t \n \r b');
expectIdentifierToken(tokens[0], 0, 'a');
expectIdentifierToken(tokens[1], 8, 'b');
});
it('should tokenize quoted string', () => {
var str = "['\\'', \"\\\"\"]";
var str = '[\'\\\'\', "\\""]';
var tokens: Token[] = lex(str);
expectStringToken(tokens[1], 1, "'");
expectStringToken(tokens[1], 1, '\'');
expectStringToken(tokens[3], 7, '"');
});
@ -146,7 +151,7 @@ export function main() {
});
it('should tokenize relation', function() {
var tokens: Token[] = lex("! == != < > <= >= === !==");
var tokens: Token[] = lex('! == != < > <= >= === !==');
expectOperatorToken(tokens[0], 0, '!');
expectOperatorToken(tokens[1], 2, '==');
expectOperatorToken(tokens[2], 5, '!=');
@ -159,7 +164,7 @@ export function main() {
});
it('should tokenize statements', function() {
var tokens: Token[] = lex("a;b;");
var tokens: Token[] = lex('a;b;');
expectIdentifierToken(tokens[0], 0, 'a');
expectCharacterToken(tokens[1], 1, ';');
expectIdentifierToken(tokens[2], 2, 'b');
@ -167,19 +172,19 @@ export function main() {
});
it('should tokenize function invocation', function() {
var tokens: Token[] = lex("a()");
var tokens: Token[] = lex('a()');
expectIdentifierToken(tokens[0], 0, 'a');
expectCharacterToken(tokens[1], 1, '(');
expectCharacterToken(tokens[2], 2, ')');
});
it('should tokenize simple method invocations', function() {
var tokens: Token[] = lex("a.method()");
var tokens: Token[] = lex('a.method()');
expectIdentifierToken(tokens[2], 2, 'method');
});
it('should tokenize method invocation', function() {
var tokens: Token[] = lex("a.b.c (d) - e.f()");
var tokens: Token[] = lex('a.b.c (d) - e.f()');
expectIdentifierToken(tokens[0], 0, 'a');
expectCharacterToken(tokens[1], 1, '.');
expectIdentifierToken(tokens[2], 2, 'b');
@ -197,7 +202,7 @@ export function main() {
});
it('should tokenize number', function() {
var tokens: Token[] = lex("0.5");
var tokens: Token[] = lex('0.5');
expectNumberToken(tokens[0], 0, 0.5);
});
@ -208,34 +213,36 @@ export function main() {
// });
it('should tokenize number with exponent', function() {
var tokens: Token[] = lex("0.5E-10");
var tokens: Token[] = lex('0.5E-10');
expect(tokens.length).toEqual(1);
expectNumberToken(tokens[0], 0, 0.5E-10);
tokens = lex("0.5E+10");
tokens = lex('0.5E+10');
expectNumberToken(tokens[0], 0, 0.5E+10);
});
it('should throws exception for invalid exponent', function() {
expect(() => { lex("0.5E-"); })
.toThrowError('Lexer Error: Invalid exponent at column 4 in expression [0.5E-]');
expect(() => {
lex('0.5E-');
}).toThrowError('Lexer Error: Invalid exponent at column 4 in expression [0.5E-]');
expect(() => { lex("0.5E-A"); })
.toThrowError('Lexer Error: Invalid exponent at column 4 in expression [0.5E-A]');
expect(() => {
lex('0.5E-A');
}).toThrowError('Lexer Error: Invalid exponent at column 4 in expression [0.5E-A]');
});
it('should tokenize number starting with a dot', function() {
var tokens: Token[] = lex(".5");
var tokens: Token[] = lex('.5');
expectNumberToken(tokens[0], 0, 0.5);
});
it('should throw error on invalid unicode', function() {
expect(() => { lex("'\\u1''bla'"); })
expect(() => { lex('\'\\u1\'\'bla\''); })
.toThrowError(
"Lexer Error: Invalid unicode escape [\\u1''b] at column 2 in expression ['\\u1''bla']");
'Lexer Error: Invalid unicode escape [\\u1\'\'b] at column 2 in expression [\'\\u1\'\'bla\']');
});
it('should tokenize hash as operator', function() {
var tokens: Token[] = lex("#");
var tokens: Token[] = lex('#');
expectOperatorToken(tokens[0], 0, '#');
});

View File

@ -1,9 +1,11 @@
import {ddescribe, describe, it, xit, iit, expect, beforeEach} from '@angular/core/testing';
import {isBlank, isPresent} from '../../src/facade/lang';
import {Parser} from '@angular/compiler/src/expression_parser/parser';
import {Unparser} from './unparser';
import {AST, BindingPipe, LiteralPrimitive} from '@angular/compiler/src/expression_parser/ast';
import {Lexer} from '@angular/compiler/src/expression_parser/lexer';
import {BindingPipe, LiteralPrimitive, AST} from '@angular/compiler/src/expression_parser/ast';
import {Parser} from '@angular/compiler/src/expression_parser/parser';
import {beforeEach, ddescribe, describe, expect, iit, it, xit} from '@angular/core/testing';
import {isBlank, isPresent} from '../../src/facade/lang';
import {Unparser} from './unparser';
export function main() {
function createParser() { return new Parser(new Lexer()); }
@ -16,15 +18,18 @@ export function main() {
return createParser().parseBinding(text, location);
}
function parseTemplateBindings(text: any /** TODO #9100 */, location: any /** TODO #9100 */ = null): any {
function parseTemplateBindings(
text: any /** TODO #9100 */, location: any /** TODO #9100 */ = null): any {
return createParser().parseTemplateBindings(text, location).templateBindings;
}
function parseInterpolation(text: any /** TODO #9100 */, location: any /** TODO #9100 */ = null): any {
function parseInterpolation(
text: any /** TODO #9100 */, location: any /** TODO #9100 */ = null): any {
return createParser().parseInterpolation(text, location);
}
function parseSimpleBinding(text: any /** TODO #9100 */, location: any /** TODO #9100 */ = null): any {
function parseSimpleBinding(
text: any /** TODO #9100 */, location: any /** TODO #9100 */ = null): any {
return createParser().parseSimpleBinding(text, location);
}
@ -48,60 +53,64 @@ export function main() {
expect(unparse(ast)).toEqual(expected);
}
function expectActionError(text: any /** TODO #9100 */) { return expect(() => parseAction(text)); }
function expectActionError(text: any /** TODO #9100 */) {
return expect(() => parseAction(text));
}
function expectBindingError(text: any /** TODO #9100 */) { return expect(() => parseBinding(text)); }
function expectBindingError(text: any /** TODO #9100 */) {
return expect(() => parseBinding(text));
}
describe("parser", () => {
describe("parseAction", () => {
it('should parse numbers', () => { checkAction("1"); });
describe('parser', () => {
describe('parseAction', () => {
it('should parse numbers', () => { checkAction('1'); });
it('should parse strings', () => {
checkAction("'1'", '"1"');
checkAction('\'1\'', '"1"');
checkAction('"1"');
});
it('should parse null', () => { checkAction("null"); });
it('should parse null', () => { checkAction('null'); });
it('should parse unary - expressions', () => {
checkAction("-1", "0 - 1");
checkAction("+1", "1");
checkAction('-1', '0 - 1');
checkAction('+1', '1');
});
it('should parse unary ! expressions', () => {
checkAction("!true");
checkAction("!!true");
checkAction("!!!true");
checkAction('!true');
checkAction('!!true');
checkAction('!!!true');
});
it('should parse multiplicative expressions',
() => { checkAction("3*4/2%5", "3 * 4 / 2 % 5"); });
() => { checkAction('3*4/2%5', '3 * 4 / 2 % 5'); });
it('should parse additive expressions', () => { checkAction("3 + 6 - 2"); });
it('should parse additive expressions', () => { checkAction('3 + 6 - 2'); });
it('should parse relational expressions', () => {
checkAction("2 < 3");
checkAction("2 > 3");
checkAction("2 <= 2");
checkAction("2 >= 2");
checkAction('2 < 3');
checkAction('2 > 3');
checkAction('2 <= 2');
checkAction('2 >= 2');
});
it('should parse equality expressions', () => {
checkAction("2 == 3");
checkAction("2 != 3");
checkAction('2 == 3');
checkAction('2 != 3');
});
it('should parse strict equality expressions', () => {
checkAction("2 === 3");
checkAction("2 !== 3");
checkAction('2 === 3');
checkAction('2 !== 3');
});
it('should parse expressions', () => {
checkAction("true && true");
checkAction("true || false");
checkAction('true && true');
checkAction('true || false');
});
it('should parse grouped expressions', () => { checkAction("(1 + 2) * 3", "1 + 2 * 3"); });
it('should parse grouped expressions', () => { checkAction('(1 + 2) * 3', '1 + 2 * 3'); });
it('should ignore comments in expressions', () => { checkAction('a //comment', 'a'); });
@ -110,33 +119,33 @@ export function main() {
it('should parse an empty string', () => { checkAction(''); });
describe("literals", () => {
describe('literals', () => {
it('should parse array', () => {
checkAction("[1][0]");
checkAction("[[1]][0][0]");
checkAction("[]");
checkAction("[].length");
checkAction("[1, 2].length");
checkAction('[1][0]');
checkAction('[[1]][0][0]');
checkAction('[]');
checkAction('[].length');
checkAction('[1, 2].length');
});
it('should parse map', () => {
checkAction("{}");
checkAction("{a: 1}[2]");
checkAction("{}[\"a\"]");
checkAction('{}');
checkAction('{a: 1}[2]');
checkAction('{}["a"]');
});
it('should only allow identifier, string, or keyword as map key', () => {
expectActionError('{(:0}')
.toThrowError(new RegExp('expected identifier, keyword, or string'));
expectActionError('{(:0}').toThrowError(
new RegExp('expected identifier, keyword, or string'));
expectActionError('{1234:0}')
.toThrowError(new RegExp('expected identifier, keyword, or string'));
});
});
describe("member access", () => {
it("should parse field access", () => {
checkAction("a");
checkAction("a.a");
describe('member access', () => {
it('should parse field access', () => {
checkAction('a');
checkAction('a.a');
});
it('should only allow identifier or keyword as member names', () => {
@ -151,46 +160,47 @@ export function main() {
});
});
describe("method calls", () => {
it("should parse method calls", () => {
checkAction("fn()");
checkAction("add(1, 2)");
checkAction("a.add(1, 2)");
checkAction("fn().add(1, 2)");
describe('method calls', () => {
it('should parse method calls', () => {
checkAction('fn()');
checkAction('add(1, 2)');
checkAction('a.add(1, 2)');
checkAction('fn().add(1, 2)');
});
});
describe("functional calls",
() => { it("should parse function calls", () => { checkAction("fn()(1, 2)"); }); });
describe('functional calls', () => {
it('should parse function calls', () => { checkAction('fn()(1, 2)'); });
});
describe("conditional", () => {
describe('conditional', () => {
it('should parse ternary/conditional expressions', () => {
checkAction("7 == 3 + 4 ? 10 : 20");
checkAction("false ? 10 : 20");
checkAction('7 == 3 + 4 ? 10 : 20');
checkAction('false ? 10 : 20');
});
it('should throw on incorrect ternary operator syntax', () => {
expectActionError("true?1").toThrowError(new RegExp(
expectActionError('true?1').toThrowError(new RegExp(
'Parser Error: Conditional expression true\\?1 requires all 3 expressions'));
});
});
describe("assignment", () => {
it("should support field assignments", () => {
checkAction("a = 12");
checkAction("a.a.a = 123");
checkAction("a = 123; b = 234;");
describe('assignment', () => {
it('should support field assignments', () => {
checkAction('a = 12');
checkAction('a.a.a = 123');
checkAction('a = 123; b = 234;');
});
it("should throw on safe field assignments", () => {
expectActionError("a?.a = 123")
it('should throw on safe field assignments', () => {
expectActionError('a?.a = 123')
.toThrowError(new RegExp('cannot be used in the assignment'));
});
it("should support array updates", () => { checkAction("a[0] = 200"); });
it('should support array updates', () => { checkAction('a[0] = 200'); });
});
it("should error when using pipes",
it('should error when using pipes',
() => { expectActionError('x|blah').toThrowError(new RegExp('Cannot have a pipe')); });
it('should store the source in the result',
@ -199,31 +209,31 @@ export function main() {
it('should store the passed-in location',
() => { expect(parseAction('someExpr', 'location').location).toBe('location'); });
it("should throw when encountering interpolation", () => {
expectActionError("{{a()}}")
.toThrowErrorWith('Got interpolation ({{}}) where expression was expected');
it('should throw when encountering interpolation', () => {
expectActionError('{{a()}}').toThrowErrorWith(
'Got interpolation ({{}}) where expression was expected');
});
});
describe("general error handling", () => {
it("should throw on an unexpected token", () => {
expectActionError("[1,2] trac").toThrowError(new RegExp('Unexpected token \'trac\''));
describe('general error handling', () => {
it('should throw on an unexpected token', () => {
expectActionError('[1,2] trac').toThrowError(new RegExp('Unexpected token \'trac\''));
});
it('should throw a reasonable error for unconsumed tokens', () => {
expectActionError(")")
.toThrowError(new RegExp("Unexpected token \\) at column 1 in \\[\\)\\]"));
expectActionError(')').toThrowError(
new RegExp('Unexpected token \\) at column 1 in \\[\\)\\]'));
});
it('should throw on missing expected token', () => {
expectActionError("a(b").toThrowError(
new RegExp("Missing expected \\) at the end of the expression \\[a\\(b\\]"));
expectActionError('a(b').toThrowError(
new RegExp('Missing expected \\) at the end of the expression \\[a\\(b\\]'));
});
});
describe("parseBinding", () => {
describe("pipes", () => {
it("should parse pipes", () => {
describe('parseBinding', () => {
describe('pipes', () => {
it('should parse pipes', () => {
checkBinding('a(b | c)', 'a((b | c))');
checkBinding('a.b(c.d(e) | f)', 'a.b((c.d(e) | f))');
checkBinding('[1, 2, 3] | a', '([1, 2, 3] | a)');
@ -261,16 +271,16 @@ export function main() {
() => { expect(parseBinding('someExpr', 'location').location).toBe('location'); });
it('should throw on chain expressions', () => {
expect(() => parseBinding("1;2")).toThrowError(new RegExp("contain chained expression"));
expect(() => parseBinding('1;2')).toThrowError(new RegExp('contain chained expression'));
});
it('should throw on assignment', () => {
expect(() => parseBinding("a=2")).toThrowError(new RegExp("contain assignments"));
expect(() => parseBinding('a=2')).toThrowError(new RegExp('contain assignments'));
});
it('should throw when encountering interpolation', () => {
expectBindingError("{{a.b}}")
.toThrowErrorWith('Got interpolation ({{}}) where expression was expected');
expectBindingError('{{a.b}}').toThrowErrorWith(
'Got interpolation ({{}}) where expression was expected');
});
it('should parse conditional expression', () => { checkBinding('a < b ? a : b'); });
@ -311,105 +321,109 @@ export function main() {
() => { expect(keys(parseTemplateBindings('a'))).toEqual(['a']); });
it('should only allow identifier, string, or keyword including dashes as keys', () => {
var bindings = parseTemplateBindings("a:'b'");
var bindings = parseTemplateBindings('a:\'b\'');
expect(keys(bindings)).toEqual(['a']);
bindings = parseTemplateBindings("'a':'b'");
bindings = parseTemplateBindings('\'a\':\'b\'');
expect(keys(bindings)).toEqual(['a']);
bindings = parseTemplateBindings("\"a\":'b'");
bindings = parseTemplateBindings('"a":\'b\'');
expect(keys(bindings)).toEqual(['a']);
bindings = parseTemplateBindings("a-b:'c'");
bindings = parseTemplateBindings('a-b:\'c\'');
expect(keys(bindings)).toEqual(['a-b']);
expect(() => { parseTemplateBindings('(:0'); })
.toThrowError(new RegExp('expected identifier, keyword, or string'));
expect(() => {
parseTemplateBindings('(:0');
}).toThrowError(new RegExp('expected identifier, keyword, or string'));
expect(() => { parseTemplateBindings('1234:0'); })
.toThrowError(new RegExp('expected identifier, keyword, or string'));
expect(() => {
parseTemplateBindings('1234:0');
}).toThrowError(new RegExp('expected identifier, keyword, or string'));
});
it('should detect expressions as value', () => {
var bindings = parseTemplateBindings("a:b");
var bindings = parseTemplateBindings('a:b');
expect(exprSources(bindings)).toEqual(['b']);
bindings = parseTemplateBindings("a:1+1");
bindings = parseTemplateBindings('a:1+1');
expect(exprSources(bindings)).toEqual(['1+1']);
});
it('should detect names as value', () => {
var bindings = parseTemplateBindings("a:let b");
var bindings = parseTemplateBindings('a:let b');
expect(keyValues(bindings)).toEqual(['a', 'let b=\$implicit']);
});
it('should allow space and colon as separators', () => {
var bindings = parseTemplateBindings("a:b");
var bindings = parseTemplateBindings('a:b');
expect(keys(bindings)).toEqual(['a']);
expect(exprSources(bindings)).toEqual(['b']);
bindings = parseTemplateBindings("a b");
bindings = parseTemplateBindings('a b');
expect(keys(bindings)).toEqual(['a']);
expect(exprSources(bindings)).toEqual(['b']);
});
it('should allow multiple pairs', () => {
var bindings = parseTemplateBindings("a 1 b 2");
var bindings = parseTemplateBindings('a 1 b 2');
expect(keys(bindings)).toEqual(['a', 'aB']);
expect(exprSources(bindings)).toEqual(['1 ', '2']);
});
it('should store the sources in the result', () => {
var bindings = parseTemplateBindings("a 1,b 2");
var bindings = parseTemplateBindings('a 1,b 2');
expect(bindings[0].expression.source).toEqual('1');
expect(bindings[1].expression.source).toEqual('2');
});
it('should store the passed-in location', () => {
var bindings = parseTemplateBindings("a 1,b 2", 'location');
var bindings = parseTemplateBindings('a 1,b 2', 'location');
expect(bindings[0].expression.location).toEqual('location');
});
it('should support var notation with a deprecation warning', () => {
var bindings = createParser().parseTemplateBindings("var i", null);
var bindings = createParser().parseTemplateBindings('var i', null);
expect(keyValues(bindings.templateBindings)).toEqual(['let i=\$implicit']);
expect(bindings.warnings)
.toEqual(['"var" inside of expressions is deprecated. Use "let" instead!']);
expect(bindings.warnings).toEqual([
'"var" inside of expressions is deprecated. Use "let" instead!'
]);
});
it('should support # notation with a deprecation warning', () => {
var bindings = createParser().parseTemplateBindings("#i", null);
var bindings = createParser().parseTemplateBindings('#i', null);
expect(keyValues(bindings.templateBindings)).toEqual(['let i=\$implicit']);
expect(bindings.warnings)
.toEqual(['"#" inside of expressions is deprecated. Use "let" instead!']);
expect(bindings.warnings).toEqual([
'"#" inside of expressions is deprecated. Use "let" instead!'
]);
});
it('should support let notation', () => {
var bindings = parseTemplateBindings("let i");
var bindings = parseTemplateBindings('let i');
expect(keyValues(bindings)).toEqual(['let i=\$implicit']);
bindings = parseTemplateBindings("let i");
bindings = parseTemplateBindings('let i');
expect(keyValues(bindings)).toEqual(['let i=\$implicit']);
bindings = parseTemplateBindings("let a; let b");
bindings = parseTemplateBindings('let a; let b');
expect(keyValues(bindings)).toEqual(['let a=\$implicit', 'let b=\$implicit']);
bindings = parseTemplateBindings("let a; let b;");
bindings = parseTemplateBindings('let a; let b;');
expect(keyValues(bindings)).toEqual(['let a=\$implicit', 'let b=\$implicit']);
bindings = parseTemplateBindings("let i-a = k-a");
bindings = parseTemplateBindings('let i-a = k-a');
expect(keyValues(bindings)).toEqual(['let i-a=k-a']);
bindings = parseTemplateBindings("keyword let item; let i = k");
bindings = parseTemplateBindings('keyword let item; let i = k');
expect(keyValues(bindings)).toEqual(['keyword', 'let item=\$implicit', 'let i=k']);
bindings = parseTemplateBindings("keyword: let item; let i = k");
bindings = parseTemplateBindings('keyword: let item; let i = k');
expect(keyValues(bindings)).toEqual(['keyword', 'let item=\$implicit', 'let i=k']);
bindings = parseTemplateBindings("directive: let item in expr; let a = b", 'location');
expect(keyValues(bindings))
.toEqual(
['directive', 'let item=\$implicit', 'directiveIn=expr in location', 'let a=b']);
bindings = parseTemplateBindings('directive: let item in expr; let a = b', 'location');
expect(keyValues(bindings)).toEqual([
'directive', 'let item=\$implicit', 'directiveIn=expr in location', 'let a=b'
]);
});
it('should parse pipes', () => {
@ -436,14 +450,14 @@ export function main() {
expect(new Unparser().unparse(ast)).toEqual(originalExp);
});
it("should throw on empty interpolation expressions", () => {
expect(() => parseInterpolation("{{}}"))
it('should throw on empty interpolation expressions', () => {
expect(() => parseInterpolation('{{}}'))
.toThrowErrorWith(
"Parser Error: Blank expressions are not allowed in interpolated strings");
'Parser Error: Blank expressions are not allowed in interpolated strings');
expect(() => parseInterpolation("foo {{ }}"))
expect(() => parseInterpolation('foo {{ }}'))
.toThrowErrorWith(
"Parser Error: Blank expressions are not allowed in interpolated strings");
'Parser Error: Blank expressions are not allowed in interpolated strings');
});
it('should parse conditional expression',
@ -453,7 +467,7 @@ export function main() {
checkInterpolation(`{{ 'foo' +\n 'bar' +\r 'baz' }}`, `{{ "foo" + "bar" + "baz" }}`);
});
describe("comments", () => {
describe('comments', () => {
it('should ignore comments in interpolation expressions',
() => { checkInterpolation('{{a //comment}}', '{{ a }}'); });
@ -469,29 +483,29 @@ export function main() {
() => { checkInterpolation(`{{ "a//b" //comment }}`, `{{ "a//b" }}`); });
it('should retain // in complex strings', () => {
checkInterpolation(`{{"//a\'//b\`//c\`//d\'//e" //comment}}`, `{{ "//a\'//b\`//c\`//d\'//e" }}`);
checkInterpolation(
`{{"//a\'//b\`//c\`//d\'//e" //comment}}`, `{{ "//a\'//b\`//c\`//d\'//e" }}`);
});
it('should retain // in nested, unterminated strings', () => {
checkInterpolation(`{{ "a\'b\`" //comment}}`, `{{ "a\'b\`" }}`);
});
it('should retain // in nested, unterminated strings',
() => { checkInterpolation(`{{ "a\'b\`" //comment}}`, `{{ "a\'b\`" }}`); });
});
});
describe("parseSimpleBinding", () => {
it("should parse a field access", () => {
var p = parseSimpleBinding("name");
expect(unparse(p)).toEqual("name");
describe('parseSimpleBinding', () => {
it('should parse a field access', () => {
var p = parseSimpleBinding('name');
expect(unparse(p)).toEqual('name');
});
it("should parse a constant", () => {
var p = parseSimpleBinding("[1, 2]");
expect(unparse(p)).toEqual("[1, 2]");
it('should parse a constant', () => {
var p = parseSimpleBinding('[1, 2]');
expect(unparse(p)).toEqual('[1, 2]');
});
it("should throw when the given expression is not just a field name", () => {
expect(() => parseSimpleBinding("name + 1"))
it('should throw when the given expression is not just a field name', () => {
expect(() => parseSimpleBinding('name + 1'))
.toThrowErrorWith(
'Host binding expression can only contain field access and constants');
});
@ -504,7 +518,7 @@ export function main() {
describe('wrapLiteralPrimitive', () => {
it('should wrap a literal primitive', () => {
expect(unparse(createParser().wrapLiteralPrimitive("foo", null))).toEqual('"foo"');
expect(unparse(createParser().wrapLiteralPrimitive('foo', null))).toEqual('"foo"');
});
});
});

View File

@ -1,29 +1,4 @@
import {
AST,
AstVisitor,
PropertyRead,
PropertyWrite,
Binary,
Chain,
Conditional,
EmptyExpr,
BindingPipe,
FunctionCall,
ImplicitReceiver,
Interpolation,
KeyedRead,
KeyedWrite,
LiteralArray,
LiteralMap,
LiteralPrimitive,
MethodCall,
PrefixNot,
Quote,
SafePropertyRead,
SafeMethodCall
} from '../../src/expression_parser/ast';
import {AST, AstVisitor, Binary, BindingPipe, Chain, Conditional, EmptyExpr, FunctionCall, ImplicitReceiver, Interpolation, KeyedRead, KeyedWrite, LiteralArray, LiteralMap, LiteralPrimitive, MethodCall, PrefixNot, PropertyRead, PropertyWrite, Quote, SafeMethodCall, SafePropertyRead} from '../../src/expression_parser/ast';
import {StringWrapper, isPresent, isString} from '../../src/facade/lang';
export class Unparser implements AstVisitor {

View File

@ -1,16 +1,7 @@
import {HtmlParser, HtmlParseTreeResult, HtmlTreeError} from '@angular/compiler/src/html_parser';
import {
HtmlAst,
HtmlAstVisitor,
HtmlElementAst,
HtmlAttrAst,
HtmlTextAst,
HtmlCommentAst,
HtmlExpansionAst,
HtmlExpansionCaseAst,
htmlVisitAll
} from '@angular/compiler/src/html_ast';
import {HtmlAst, HtmlAstVisitor, HtmlAttrAst, HtmlCommentAst, HtmlElementAst, HtmlExpansionAst, HtmlExpansionCaseAst, HtmlTextAst, htmlVisitAll} from '@angular/compiler/src/html_ast';
import {HtmlParseTreeResult, HtmlParser, HtmlTreeError} from '@angular/compiler/src/html_parser';
import {ParseError, ParseLocation} from '@angular/compiler/src/parse_util';
import {BaseException} from '../src/facade/exceptions';
export function humanizeDom(parseResult: HtmlParseTreeResult): any[] {

File diff suppressed because it is too large Load Diff

View File

@ -1,28 +1,9 @@
import {
ddescribe,
describe,
it,
iit,
xit,
expect,
beforeEach,
afterEach
} from '@angular/core/testing/testing_internal';
import {HtmlAst, HtmlAstVisitor, HtmlAttrAst, HtmlCommentAst, HtmlElementAst, HtmlExpansionAst, HtmlExpansionCaseAst, HtmlTextAst, htmlVisitAll} from '@angular/compiler/src/html_ast';
import {HtmlTokenType} from '@angular/compiler/src/html_lexer';
import {HtmlParser, HtmlParseTreeResult, HtmlTreeError} from '@angular/compiler/src/html_parser';
import {
HtmlAst,
HtmlAstVisitor,
HtmlElementAst,
HtmlAttrAst,
HtmlTextAst,
HtmlCommentAst,
htmlVisitAll,
HtmlExpansionAst,
HtmlExpansionCaseAst
} from '@angular/compiler/src/html_ast';
import {HtmlParseTreeResult, HtmlParser, HtmlTreeError} from '@angular/compiler/src/html_parser';
import {ParseError, ParseLocation} from '@angular/compiler/src/parse_util';
import {afterEach, beforeEach, ddescribe, describe, expect, iit, it, xit} from '@angular/core/testing/testing_internal';
import {humanizeDom, humanizeDomSourceSpans, humanizeLineColumn} from './html_ast_spec_utils';
export function main() {
@ -37,31 +18,36 @@ export function main() {
});
it('should parse text nodes inside regular elements', () => {
expect(humanizeDom(parser.parse('<div>a</div>', 'TestComp')))
.toEqual([[HtmlElementAst, 'div', 0], [HtmlTextAst, 'a', 1]]);
expect(humanizeDom(parser.parse('<div>a</div>', 'TestComp'))).toEqual([
[HtmlElementAst, 'div', 0], [HtmlTextAst, 'a', 1]
]);
});
it('should parse text nodes inside template elements', () => {
expect(humanizeDom(parser.parse('<template>a</template>', 'TestComp')))
.toEqual([[HtmlElementAst, 'template', 0], [HtmlTextAst, 'a', 1]]);
expect(humanizeDom(parser.parse('<template>a</template>', 'TestComp'))).toEqual([
[HtmlElementAst, 'template', 0], [HtmlTextAst, 'a', 1]
]);
});
it('should parse CDATA', () => {
expect(humanizeDom(parser.parse('<![CDATA[text]]>', 'TestComp')))
.toEqual([[HtmlTextAst, 'text', 0]]);
expect(humanizeDom(parser.parse('<![CDATA[text]]>', 'TestComp'))).toEqual([
[HtmlTextAst, 'text', 0]
]);
});
});
describe('elements', () => {
it('should parse root level elements', () => {
expect(humanizeDom(parser.parse('<div></div>', 'TestComp')))
.toEqual([[HtmlElementAst, 'div', 0]]);
expect(humanizeDom(parser.parse('<div></div>', 'TestComp'))).toEqual([
[HtmlElementAst, 'div', 0]
]);
});
it('should parse elements inside of regular elements', () => {
expect(humanizeDom(parser.parse('<div><span></span></div>', 'TestComp')))
.toEqual([[HtmlElementAst, 'div', 0], [HtmlElementAst, 'span', 1]]);
expect(humanizeDom(parser.parse('<div><span></span></div>', 'TestComp'))).toEqual([
[HtmlElementAst, 'div', 0], [HtmlElementAst, 'span', 1]
]);
});
it('should parse elements inside of template elements', () => {
@ -92,24 +78,22 @@ export function main() {
});
it('should close void elements on text nodes', () => {
expect(humanizeDom(parser.parse('<p>before<br>after</p>', 'TestComp')))
.toEqual([
[HtmlElementAst, 'p', 0],
[HtmlTextAst, 'before', 1],
[HtmlElementAst, 'br', 1],
[HtmlTextAst, 'after', 1],
]);
expect(humanizeDom(parser.parse('<p>before<br>after</p>', 'TestComp'))).toEqual([
[HtmlElementAst, 'p', 0],
[HtmlTextAst, 'before', 1],
[HtmlElementAst, 'br', 1],
[HtmlTextAst, 'after', 1],
]);
});
it('should support optional end tags', () => {
expect(humanizeDom(parser.parse('<div><p>1<p>2</div>', 'TestComp')))
.toEqual([
[HtmlElementAst, 'div', 0],
[HtmlElementAst, 'p', 1],
[HtmlTextAst, '1', 2],
[HtmlElementAst, 'p', 1],
[HtmlTextAst, '2', 2],
]);
expect(humanizeDom(parser.parse('<div><p>1<p>2</div>', 'TestComp'))).toEqual([
[HtmlElementAst, 'div', 0],
[HtmlElementAst, 'p', 1],
[HtmlTextAst, '1', 2],
[HtmlElementAst, 'p', 1],
[HtmlTextAst, '2', 2],
]);
});
it('should support nested elements', () => {
@ -128,63 +112,59 @@ export function main() {
'<table><thead><tr head></tr></thead><tr noparent></tr><tbody><tr body></tr></tbody><tfoot><tr foot></tr></tfoot></table>',
'TestComp')))
.toEqual([
[HtmlElementAst, 'table', 0],
[HtmlElementAst, 'thead', 1],
[HtmlElementAst, 'tr', 2],
[HtmlAttrAst, 'head', ''],
[HtmlElementAst, 'tbody', 1],
[HtmlElementAst, 'tr', 2],
[HtmlAttrAst, 'noparent', ''],
[HtmlElementAst, 'tbody', 1],
[HtmlElementAst, 'tr', 2],
[HtmlAttrAst, 'body', ''],
[HtmlElementAst, 'tfoot', 1],
[HtmlElementAst, 'tr', 2],
[HtmlElementAst, 'table', 0], [HtmlElementAst, 'thead', 1],
[HtmlElementAst, 'tr', 2], [HtmlAttrAst, 'head', ''], [HtmlElementAst, 'tbody', 1],
[HtmlElementAst, 'tr', 2], [HtmlAttrAst, 'noparent', ''],
[HtmlElementAst, 'tbody', 1], [HtmlElementAst, 'tr', 2], [HtmlAttrAst, 'body', ''],
[HtmlElementAst, 'tfoot', 1], [HtmlElementAst, 'tr', 2],
[HtmlAttrAst, 'foot', '']
]);
});
it('should not add the requiredParent when the parent is a template', () => {
expect(humanizeDom(parser.parse('<template><tr></tr></template>', 'TestComp')))
.toEqual([
[HtmlElementAst, 'template', 0],
[HtmlElementAst, 'tr', 1],
]);
expect(humanizeDom(parser.parse('<template><tr></tr></template>', 'TestComp'))).toEqual([
[HtmlElementAst, 'template', 0],
[HtmlElementAst, 'tr', 1],
]);
});
it('should support explicit mamespace', () => {
expect(humanizeDom(parser.parse('<myns:div></myns:div>', 'TestComp')))
.toEqual([[HtmlElementAst, ':myns:div', 0]]);
expect(humanizeDom(parser.parse('<myns:div></myns:div>', 'TestComp'))).toEqual([
[HtmlElementAst, ':myns:div', 0]
]);
});
it('should support implicit mamespace', () => {
expect(humanizeDom(parser.parse('<svg></svg>', 'TestComp')))
.toEqual([[HtmlElementAst, ':svg:svg', 0]]);
expect(humanizeDom(parser.parse('<svg></svg>', 'TestComp'))).toEqual([
[HtmlElementAst, ':svg:svg', 0]
]);
});
it('should propagate the namespace', () => {
expect(humanizeDom(parser.parse('<myns:div><p></p></myns:div>', 'TestComp')))
.toEqual([[HtmlElementAst, ':myns:div', 0], [HtmlElementAst, ':myns:p', 1]]);
expect(humanizeDom(parser.parse('<myns:div><p></p></myns:div>', 'TestComp'))).toEqual([
[HtmlElementAst, ':myns:div', 0], [HtmlElementAst, ':myns:p', 1]
]);
});
it('should match closing tags case sensitive', () => {
let errors = parser.parse('<DiV><P></p></dIv>', 'TestComp').errors;
expect(errors.length).toEqual(2);
expect(humanizeErrors(errors))
.toEqual([
['p', 'Unexpected closing tag "p"', '0:8'],
['dIv', 'Unexpected closing tag "dIv"', '0:12'],
]);
expect(humanizeErrors(errors)).toEqual([
['p', 'Unexpected closing tag "p"', '0:8'],
['dIv', 'Unexpected closing tag "dIv"', '0:12'],
]);
});
it('should support self closing void elements', () => {
expect(humanizeDom(parser.parse('<input />', 'TestComp')))
.toEqual([[HtmlElementAst, 'input', 0]]);
expect(humanizeDom(parser.parse('<input />', 'TestComp'))).toEqual([
[HtmlElementAst, 'input', 0]
]);
});
it('should support self closing foreign elements', () => {
expect(humanizeDom(parser.parse('<math />', 'TestComp')))
.toEqual([[HtmlElementAst, ':math:math', 0]]);
expect(humanizeDom(parser.parse('<math />', 'TestComp'))).toEqual([
[HtmlElementAst, ':math:math', 0]
]);
});
it('should ignore LF immediately after textarea, pre and listing', () => {
@ -206,108 +186,109 @@ export function main() {
describe('attributes', () => {
it('should parse attributes on regular elements case sensitive', () => {
expect(humanizeDom(parser.parse('<div kEy="v" key2=v2></div>', 'TestComp')))
.toEqual([
[HtmlElementAst, 'div', 0],
[HtmlAttrAst, 'kEy', 'v'],
[HtmlAttrAst, 'key2', 'v2'],
]);
expect(humanizeDom(parser.parse('<div kEy="v" key2=v2></div>', 'TestComp'))).toEqual([
[HtmlElementAst, 'div', 0],
[HtmlAttrAst, 'kEy', 'v'],
[HtmlAttrAst, 'key2', 'v2'],
]);
});
it('should parse attributes without values', () => {
expect(humanizeDom(parser.parse('<div k></div>', 'TestComp')))
.toEqual([[HtmlElementAst, 'div', 0], [HtmlAttrAst, 'k', '']]);
expect(humanizeDom(parser.parse('<div k></div>', 'TestComp'))).toEqual([
[HtmlElementAst, 'div', 0], [HtmlAttrAst, 'k', '']
]);
});
it('should parse attributes on svg elements case sensitive', () => {
expect(humanizeDom(parser.parse('<svg viewBox="0"></svg>', 'TestComp')))
.toEqual([[HtmlElementAst, ':svg:svg', 0], [HtmlAttrAst, 'viewBox', '0']]);
expect(humanizeDom(parser.parse('<svg viewBox="0"></svg>', 'TestComp'))).toEqual([
[HtmlElementAst, ':svg:svg', 0], [HtmlAttrAst, 'viewBox', '0']
]);
});
it('should parse attributes on template elements', () => {
expect(humanizeDom(parser.parse('<template k="v"></template>', 'TestComp')))
.toEqual([[HtmlElementAst, 'template', 0], [HtmlAttrAst, 'k', 'v']]);
expect(humanizeDom(parser.parse('<template k="v"></template>', 'TestComp'))).toEqual([
[HtmlElementAst, 'template', 0], [HtmlAttrAst, 'k', 'v']
]);
});
it('should support namespace', () => {
expect(humanizeDom(parser.parse('<svg:use xlink:href="Port" />', 'TestComp')))
.toEqual([[HtmlElementAst, ':svg:use', 0], [HtmlAttrAst, ':xlink:href', 'Port']]);
expect(humanizeDom(parser.parse('<svg:use xlink:href="Port" />', 'TestComp'))).toEqual([
[HtmlElementAst, ':svg:use', 0], [HtmlAttrAst, ':xlink:href', 'Port']
]);
});
});
describe('comments', () => {
it('should preserve comments', () => {
expect(humanizeDom(parser.parse('<!-- comment --><div></div>', 'TestComp')))
.toEqual([[HtmlCommentAst, 'comment', 0], [HtmlElementAst, 'div', 0]]);
expect(humanizeDom(parser.parse('<!-- comment --><div></div>', 'TestComp'))).toEqual([
[HtmlCommentAst, 'comment', 0], [HtmlElementAst, 'div', 0]
]);
});
});
describe("expansion forms", () => {
it("should parse out expansion forms", () => {
let parsed = parser.parse(`<div>before{messages.length, plural, =0 {You have <b>no</b> messages} =1 {One {{message}}}}after</div>`,
'TestComp', true);
describe('expansion forms', () => {
it('should parse out expansion forms', () => {
let parsed = parser.parse(
`<div>before{messages.length, plural, =0 {You have <b>no</b> messages} =1 {One {{message}}}}after</div>`,
'TestComp', true);
expect(humanizeDom(parsed))
.toEqual([
[HtmlElementAst, 'div', 0],
[HtmlTextAst, 'before', 1],
[HtmlExpansionAst, 'messages.length', 'plural'],
[HtmlExpansionCaseAst, '0'],
[HtmlExpansionCaseAst, '1'],
[HtmlTextAst, 'after', 1]
]);
expect(humanizeDom(parsed)).toEqual([
[HtmlElementAst, 'div', 0], [HtmlTextAst, 'before', 1],
[HtmlExpansionAst, 'messages.length', 'plural'], [HtmlExpansionCaseAst, '0'],
[HtmlExpansionCaseAst, '1'], [HtmlTextAst, 'after', 1]
]);
let cases = (<any>parsed.rootNodes[0]).children[1].cases;
expect(humanizeDom(new HtmlParseTreeResult(cases[0].expression, [])))
.toEqual([
[HtmlTextAst, 'You have ', 0],
[HtmlElementAst, 'b', 0],
[HtmlTextAst, 'no', 1],
[HtmlTextAst, ' messages', 0],
]);
expect(humanizeDom(new HtmlParseTreeResult(cases[0].expression, []))).toEqual([
[HtmlTextAst, 'You have ', 0],
[HtmlElementAst, 'b', 0],
[HtmlTextAst, 'no', 1],
[HtmlTextAst, ' messages', 0],
]);
expect(humanizeDom(new HtmlParseTreeResult(cases[1].expression, [])))
.toEqual([[HtmlTextAst, 'One {{message}}', 0]]);
expect(humanizeDom(new HtmlParseTreeResult(cases[1].expression, [
]))).toEqual([[HtmlTextAst, 'One {{message}}', 0]]);
});
it("should parse out nested expansion forms", () => {
let parsed = parser.parse(`{messages.length, plural, =0 { {p.gender, gender, =m {m}} }}`,
'TestComp', true);
it('should parse out nested expansion forms', () => {
let parsed = parser.parse(
`{messages.length, plural, =0 { {p.gender, gender, =m {m}} }}`, 'TestComp', true);
expect(humanizeDom(parsed))
.toEqual([
[HtmlExpansionAst, 'messages.length', 'plural'],
[HtmlExpansionCaseAst, '0'],
]);
expect(humanizeDom(parsed)).toEqual([
[HtmlExpansionAst, 'messages.length', 'plural'],
[HtmlExpansionCaseAst, '0'],
]);
let firstCase = (<any>parsed.rootNodes[0]).cases[0];
expect(humanizeDom(new HtmlParseTreeResult(firstCase.expression, [])))
.toEqual([
[HtmlExpansionAst, 'p.gender', 'gender'],
[HtmlExpansionCaseAst, 'm'],
[HtmlTextAst, ' ', 0],
]);
expect(humanizeDom(new HtmlParseTreeResult(firstCase.expression, []))).toEqual([
[HtmlExpansionAst, 'p.gender', 'gender'],
[HtmlExpansionCaseAst, 'm'],
[HtmlTextAst, ' ', 0],
]);
});
it("should error when expansion form is not closed", () => {
it('should error when expansion form is not closed', () => {
let p = parser.parse(`{messages.length, plural, =0 {one}`, 'TestComp', true);
expect(humanizeErrors(p.errors))
.toEqual([[null, "Invalid expansion form. Missing '}'.", '0:34']]);
expect(humanizeErrors(p.errors)).toEqual([
[null, 'Invalid expansion form. Missing \'}\'.', '0:34']
]);
});
it("should error when expansion case is not closed", () => {
it('should error when expansion case is not closed', () => {
let p = parser.parse(`{messages.length, plural, =0 {one`, 'TestComp', true);
expect(humanizeErrors(p.errors))
.toEqual([[null, "Invalid expansion form. Missing '}'.", '0:29']]);
expect(humanizeErrors(p.errors)).toEqual([
[null, 'Invalid expansion form. Missing \'}\'.', '0:29']
]);
});
it("should error when invalid html in the case", () => {
it('should error when invalid html in the case', () => {
let p = parser.parse(`{messages.length, plural, =0 {<b/>}`, 'TestComp', true);
expect(humanizeErrors(p.errors))
.toEqual([['b', 'Only void and foreign elements can be self closed "b"', '0:30']]);
expect(humanizeErrors(p.errors)).toEqual([
['b', 'Only void and foreign elements can be self closed "b"', '0:30']
]);
});
});
@ -352,34 +333,34 @@ export function main() {
it('should report closing tag for void elements', () => {
let errors = parser.parse('<input></input>', 'TestComp').errors;
expect(errors.length).toEqual(1);
expect(humanizeErrors(errors))
.toEqual([['input', 'Void elements do not have end tags "input"', '0:7']]);
expect(humanizeErrors(errors)).toEqual([
['input', 'Void elements do not have end tags "input"', '0:7']
]);
});
it('should report self closing html element', () => {
let errors = parser.parse('<p />', 'TestComp').errors;
expect(errors.length).toEqual(1);
expect(humanizeErrors(errors))
.toEqual([['p', 'Only void and foreign elements can be self closed "p"', '0:0']]);
expect(humanizeErrors(errors)).toEqual([
['p', 'Only void and foreign elements can be self closed "p"', '0:0']
]);
});
it('should report self closing custom element', () => {
let errors = parser.parse('<my-cmp />', 'TestComp').errors;
expect(errors.length).toEqual(1);
expect(humanizeErrors(errors))
.toEqual([
['my-cmp', 'Only void and foreign elements can be self closed "my-cmp"', '0:0']
]);
expect(humanizeErrors(errors)).toEqual([
['my-cmp', 'Only void and foreign elements can be self closed "my-cmp"', '0:0']
]);
});
it('should also report lexer errors', () => {
let errors = parser.parse('<!-err--><div></p></div>', 'TestComp').errors;
expect(errors.length).toEqual(2);
expect(humanizeErrors(errors))
.toEqual([
[HtmlTokenType.COMMENT_START, 'Unexpected character "e"', '0:3'],
['p', 'Unexpected closing tag "p"', '0:14']
]);
expect(humanizeErrors(errors)).toEqual([
[HtmlTokenType.COMMENT_START, 'Unexpected character "e"', '0:3'],
['p', 'Unexpected closing tag "p"', '0:14']
]);
});
});
});

View File

@ -1,59 +1,66 @@
import {describe, expect, it, iit, ddescribe} from "@angular/core/testing/testing_internal";
import {I18nHtmlParser} from "@angular/compiler/src/i18n/i18n_html_parser";
import {Message, id} from "@angular/compiler/src/i18n/message";
import {Parser} from "@angular/compiler/src/expression_parser/parser";
import {Lexer} from "@angular/compiler/src/expression_parser/lexer";
import {StringMapWrapper} from "../../src/facade/collection";
import {HtmlParser, HtmlParseTreeResult} from "@angular/compiler/src/html_parser";
import {HtmlElementAst, HtmlAttrAst, HtmlTextAst} from "@angular/compiler/src/html_ast";
import {deserializeXmb} from "@angular/compiler/src/i18n/xmb_serializer";
import {ParseError} from "@angular/compiler/src/parse_util";
import {humanizeDom} from "@angular/compiler/test/html_ast_spec_utils";
import {Lexer} from '@angular/compiler/src/expression_parser/lexer';
import {Parser} from '@angular/compiler/src/expression_parser/parser';
import {HtmlAttrAst, HtmlElementAst, HtmlTextAst} from '@angular/compiler/src/html_ast';
import {HtmlParseTreeResult, HtmlParser} from '@angular/compiler/src/html_parser';
import {I18nHtmlParser} from '@angular/compiler/src/i18n/i18n_html_parser';
import {Message, id} from '@angular/compiler/src/i18n/message';
import {deserializeXmb} from '@angular/compiler/src/i18n/xmb_serializer';
import {ParseError} from '@angular/compiler/src/parse_util';
import {humanizeDom} from '@angular/compiler/test/html_ast_spec_utils';
import {ddescribe, describe, expect, iit, it} from '@angular/core/testing/testing_internal';
import {StringMapWrapper} from '../../src/facade/collection';
export function main() {
describe('I18nHtmlParser', () => {
function parse(template: string, messages: {[key: string]: string}, implicitTags: string[] = [],
implicitAttrs: {[k: string]: string[]} = {}): HtmlParseTreeResult {
function parse(
template: string, messages: {[key: string]: string}, implicitTags: string[] = [],
implicitAttrs: {[k: string]: string[]} = {}): HtmlParseTreeResult {
var parser = new Parser(new Lexer());
let htmlParser = new HtmlParser();
let msgs = '';
StringMapWrapper.forEach(messages, (v: any /** TODO #9100 */, k: any /** TODO #9100 */) => msgs += `<msg id="${k}">${v}</msg>`);
StringMapWrapper.forEach(
messages, (v: any /** TODO #9100 */, k: any /** TODO #9100 */) => msgs +=
`<msg id="${k}">${v}</msg>`);
let res = deserializeXmb(`<message-bundle>${msgs}</message-bundle>`, 'someUrl');
return new I18nHtmlParser(htmlParser, parser, res.content, res.messages, implicitTags,
implicitAttrs)
.parse(template, "someurl", true);
return new I18nHtmlParser(
htmlParser, parser, res.content, res.messages, implicitTags, implicitAttrs)
.parse(template, 'someurl', true);
}
it("should delegate to the provided parser when no i18n", () => {
expect(humanizeDom(parse('<div>a</div>', {})))
.toEqual([[HtmlElementAst, 'div', 0], [HtmlTextAst, 'a', 1]]);
it('should delegate to the provided parser when no i18n', () => {
expect(humanizeDom(parse('<div>a</div>', {}))).toEqual([
[HtmlElementAst, 'div', 0], [HtmlTextAst, 'a', 1]
]);
});
it("should replace attributes", () => {
it('should replace attributes', () => {
let translations: {[key: string]: string} = {};
translations[id(new Message("some message", "meaning", null))] = "another message";
translations[id(new Message('some message', 'meaning', null))] = 'another message';
expect(humanizeDom(parse("<div value='some message' i18n-value='meaning|comment'></div>",
translations)))
expect(
humanizeDom(parse(
'<div value=\'some message\' i18n-value=\'meaning|comment\'></div>', translations)))
.toEqual([[HtmlElementAst, 'div', 0], [HtmlAttrAst, 'value', 'another message']]);
});
it("should replace elements with the i18n attr", () => {
it('should replace elements with the i18n attr', () => {
let translations: {[key: string]: string} = {};
translations[id(new Message("message", "meaning", null))] = "another message";
translations[id(new Message('message', 'meaning', null))] = 'another message';
expect(humanizeDom(parse("<div i18n='meaning|desc'>message</div>", translations)))
.toEqual([[HtmlElementAst, 'div', 0], [HtmlTextAst, 'another message', 1]]);
expect(humanizeDom(parse('<div i18n=\'meaning|desc\'>message</div>', translations))).toEqual([
[HtmlElementAst, 'div', 0], [HtmlTextAst, 'another message', 1]
]);
});
it("should handle interpolation", () => {
it('should handle interpolation', () => {
let translations: {[key: string]: string} = {};
translations[id(new Message('<ph name="0"/> and <ph name="1"/>', null, null))] =
'<ph name="1"/> or <ph name="0"/>';
expect(humanizeDom(parse("<div value='{{a}} and {{b}}' i18n-value></div>", translations)))
expect(humanizeDom(parse('<div value=\'{{a}} and {{b}}\' i18n-value></div>', translations)))
.toEqual([[HtmlElementAst, 'div', 0], [HtmlAttrAst, 'value', '{{b}} or {{a}}']]);
});
@ -87,37 +94,35 @@ export function main() {
]);
});
it("should handle nested html", () => {
it('should handle nested html', () => {
let translations: {[key: string]: string} = {};
translations[id(new Message('<ph name="e0">a</ph><ph name="e2">b</ph>', null, null))] =
'<ph name="e2">B</ph><ph name="e0">A</ph>';
expect(humanizeDom(parse('<div i18n><a>a</a><b>b</b></div>', translations)))
.toEqual([
[HtmlElementAst, 'div', 0],
[HtmlElementAst, 'b', 1],
[HtmlTextAst, 'B', 2],
[HtmlElementAst, 'a', 1],
[HtmlTextAst, 'A', 2],
]);
expect(humanizeDom(parse('<div i18n><a>a</a><b>b</b></div>', translations))).toEqual([
[HtmlElementAst, 'div', 0],
[HtmlElementAst, 'b', 1],
[HtmlTextAst, 'B', 2],
[HtmlElementAst, 'a', 1],
[HtmlTextAst, 'A', 2],
]);
});
it("should support interpolation", () => {
it('should support interpolation', () => {
let translations: {[key: string]: string} = {};
translations[id(new Message(
'<ph name="e0">a</ph><ph name="e2"><ph name="t3">b<ph name="0"/></ph></ph>', null,
null))] = '<ph name="e2"><ph name="t3"><ph name="0"/>B</ph></ph><ph name="e0">A</ph>';
expect(humanizeDom(parse('<div i18n><a>a</a><b>b{{i}}</b></div>', translations)))
.toEqual([
[HtmlElementAst, 'div', 0],
[HtmlElementAst, 'b', 1],
[HtmlTextAst, '{{i}}B', 2],
[HtmlElementAst, 'a', 1],
[HtmlTextAst, 'A', 2],
]);
expect(humanizeDom(parse('<div i18n><a>a</a><b>b{{i}}</b></div>', translations))).toEqual([
[HtmlElementAst, 'div', 0],
[HtmlElementAst, 'b', 1],
[HtmlTextAst, '{{i}}B', 2],
[HtmlElementAst, 'a', 1],
[HtmlTextAst, 'A', 2],
]);
});
it("should i18n attributes of placeholder elements", () => {
it('should i18n attributes of placeholder elements', () => {
let translations: {[key: string]: string} = {};
translations[id(new Message('<ph name="e0">a</ph>', null, null))] = '<ph name="e0">A</ph>';
translations[id(new Message('b', null, null))] = 'B';
@ -126,21 +131,19 @@ export function main() {
.toEqual([
[HtmlElementAst, 'div', 0],
[HtmlElementAst, 'a', 1],
[HtmlAttrAst, 'value', "B"],
[HtmlAttrAst, 'value', 'B'],
[HtmlTextAst, 'A', 2],
]);
});
it("should preserve non-i18n attributes", () => {
it('should preserve non-i18n attributes', () => {
let translations: {[key: string]: string} = {};
translations[id(new Message('message', null, null))] = 'another message';
expect(humanizeDom(parse('<div i18n value="b">message</div>', translations)))
.toEqual([
[HtmlElementAst, 'div', 0],
[HtmlAttrAst, 'value', "b"],
[HtmlTextAst, 'another message', 1]
]);
expect(humanizeDom(parse('<div i18n value="b">message</div>', translations))).toEqual([
[HtmlElementAst, 'div', 0], [HtmlAttrAst, 'value', 'b'],
[HtmlTextAst, 'another message', 1]
]);
});
it('should extract from partitions', () => {
@ -148,16 +151,17 @@ export function main() {
translations[id(new Message('message1', 'meaning1', null))] = 'another message1';
translations[id(new Message('message2', 'meaning2', null))] = 'another message2';
let res = parse(`<!-- i18n: meaning1|desc1 -->message1<!-- /i18n --><!-- i18n: meaning2|desc2 -->message2<!-- /i18n -->`, translations);
let res = parse(
`<!-- i18n: meaning1|desc1 -->message1<!-- /i18n --><!-- i18n: meaning2|desc2 -->message2<!-- /i18n -->`,
translations);
expect(humanizeDom(res))
.toEqual([
[HtmlTextAst, 'another message1', 0],
[HtmlTextAst, 'another message2', 0],
]);
expect(humanizeDom(res)).toEqual([
[HtmlTextAst, 'another message1', 0],
[HtmlTextAst, 'another message2', 0],
]);
});
it("should preserve original positions", () => {
it('should preserve original positions', () => {
let translations: {[key: string]: string} = {};
translations[id(new Message('<ph name="e0">a</ph><ph name="e2">b</ph>', null, null))] =
'<ph name="e2">B</ph><ph name="e0">A</ph>';
@ -169,54 +173,43 @@ export function main() {
expect(res[1].sourceSpan.start.offset).toEqual(10);
});
it("should handle the plural expansion form", () => {
it('should handle the plural expansion form', () => {
let translations: {[key: string]: string} = {};
translations[id(new Message('zero<ph name="e1">bold</ph>', "plural_0", null))] =
translations[id(new Message('zero<ph name="e1">bold</ph>', 'plural_0', null))] =
'ZERO<ph name="e1">BOLD</ph>';
let res = parse(`{messages.length, plural,=0 {zero<b>bold</b>}}`, translations);
expect(humanizeDom(res))
.toEqual([
[HtmlElementAst, 'ul', 0],
[HtmlAttrAst, '[ngPlural]', 'messages.length'],
[HtmlElementAst, 'template', 1],
[HtmlAttrAst, 'ngPluralCase', '0'],
[HtmlElementAst, 'li', 2],
[HtmlTextAst, 'ZERO', 3],
[HtmlElementAst, 'b', 3],
[HtmlTextAst, 'BOLD', 4]
]);
expect(humanizeDom(res)).toEqual([
[HtmlElementAst, 'ul', 0], [HtmlAttrAst, '[ngPlural]', 'messages.length'],
[HtmlElementAst, 'template', 1], [HtmlAttrAst, 'ngPluralCase', '0'],
[HtmlElementAst, 'li', 2], [HtmlTextAst, 'ZERO', 3], [HtmlElementAst, 'b', 3],
[HtmlTextAst, 'BOLD', 4]
]);
});
it("should handle nested expansion forms", () => {
it('should handle nested expansion forms', () => {
let translations: {[key: string]: string} = {};
translations[id(new Message('m', "gender_m", null))] = 'M';
translations[id(new Message('m', 'gender_m', null))] = 'M';
let res = parse(`{messages.length, plural, =0 { {p.gender, gender, =m {m}} }}`, translations);
expect(humanizeDom(res))
.toEqual([
[HtmlElementAst, 'ul', 0],
[HtmlAttrAst, '[ngPlural]', 'messages.length'],
[HtmlElementAst, 'template', 1],
[HtmlAttrAst, 'ngPluralCase', '0'],
[HtmlElementAst, 'li', 2],
expect(humanizeDom(res)).toEqual([
[HtmlElementAst, 'ul', 0], [HtmlAttrAst, '[ngPlural]', 'messages.length'],
[HtmlElementAst, 'template', 1], [HtmlAttrAst, 'ngPluralCase', '0'],
[HtmlElementAst, 'li', 2],
[HtmlElementAst, 'ul', 3],
[HtmlAttrAst, '[ngSwitch]', 'p.gender'],
[HtmlElementAst, 'template', 4],
[HtmlAttrAst, 'ngSwitchWhen', 'm'],
[HtmlElementAst, 'li', 5],
[HtmlTextAst, 'M', 6],
[HtmlElementAst, 'ul', 3], [HtmlAttrAst, '[ngSwitch]', 'p.gender'],
[HtmlElementAst, 'template', 4], [HtmlAttrAst, 'ngSwitchWhen', 'm'],
[HtmlElementAst, 'li', 5], [HtmlTextAst, 'M', 6],
[HtmlTextAst, ' ', 3]
]);
[HtmlTextAst, ' ', 3]
]);
});
it("should correctly set source code positions", () => {
it('should correctly set source code positions', () => {
let translations: {[key: string]: string} = {};
translations[id(new Message('<ph name="e0">bold</ph>', "plural_0", null))] =
translations[id(new Message('<ph name="e0">bold</ph>', 'plural_0', null))] =
'<ph name="e0">BOLD</ph>';
let nodes = parse(`{messages.length, plural,=0 {<b>bold</b>}}`, translations).rootNodes;
@ -253,101 +246,106 @@ export function main() {
expect(b.sourceSpan.end.col).toEqual(32);
});
it("should handle other special forms", () => {
it('should handle other special forms', () => {
let translations: {[key: string]: string} = {};
translations[id(new Message('m', "gender_male", null))] = 'M';
translations[id(new Message('m', 'gender_male', null))] = 'M';
let res = parse(`{person.gender, gender,=male {m}}`, translations);
expect(humanizeDom(res))
.toEqual([
[HtmlElementAst, 'ul', 0],
[HtmlAttrAst, '[ngSwitch]', 'person.gender'],
[HtmlElementAst, 'template', 1],
[HtmlAttrAst, 'ngSwitchWhen', 'male'],
[HtmlElementAst, 'li', 2],
[HtmlTextAst, 'M', 3],
]);
expect(humanizeDom(res)).toEqual([
[HtmlElementAst, 'ul', 0],
[HtmlAttrAst, '[ngSwitch]', 'person.gender'],
[HtmlElementAst, 'template', 1],
[HtmlAttrAst, 'ngSwitchWhen', 'male'],
[HtmlElementAst, 'li', 2],
[HtmlTextAst, 'M', 3],
]);
});
describe("errors", () => {
it("should error when giving an invalid template", () => {
expect(humanizeErrors(parse("<a>a</b>", {}).errors))
.toEqual(['Unexpected closing tag "b"']);
describe('errors', () => {
it('should error when giving an invalid template', () => {
expect(humanizeErrors(parse('<a>a</b>', {}).errors)).toEqual([
'Unexpected closing tag "b"'
]);
});
it("should error when no matching message (attr)", () => {
let mid = id(new Message("some message", null, null));
expect(humanizeErrors(parse("<div value='some message' i18n-value></div>", {}).errors))
it('should error when no matching message (attr)', () => {
let mid = id(new Message('some message', null, null));
expect(humanizeErrors(parse('<div value=\'some message\' i18n-value></div>', {}).errors))
.toEqual([`Cannot find message for id '${mid}', content 'some message'.`]);
});
it("should error when no matching message (text)", () => {
let mid = id(new Message("some message", null, null));
expect(humanizeErrors(parse("<div i18n>some message</div>", {}).errors))
.toEqual([`Cannot find message for id '${mid}', content 'some message'.`]);
it('should error when no matching message (text)', () => {
let mid = id(new Message('some message', null, null));
expect(humanizeErrors(parse('<div i18n>some message</div>', {}).errors)).toEqual([
`Cannot find message for id '${mid}', content 'some message'.`
]);
});
it("should error when a non-placeholder element appears in translation", () => {
it('should error when a non-placeholder element appears in translation', () => {
let translations: {[key: string]: string} = {};
translations[id(new Message("some message", null, null))] = "<a>a</a>";
translations[id(new Message('some message', null, null))] = '<a>a</a>';
expect(humanizeErrors(parse("<div i18n>some message</div>", translations).errors))
.toEqual([`Unexpected tag "a". Only "ph" tags are allowed.`]);
expect(humanizeErrors(parse('<div i18n>some message</div>', translations).errors)).toEqual([
`Unexpected tag "a". Only "ph" tags are allowed.`
]);
});
it("should error when a placeholder element does not have the name attribute", () => {
it('should error when a placeholder element does not have the name attribute', () => {
let translations: {[key: string]: string} = {};
translations[id(new Message("some message", null, null))] = "<ph>a</ph>";
translations[id(new Message('some message', null, null))] = '<ph>a</ph>';
expect(humanizeErrors(parse("<div i18n>some message</div>", translations).errors))
.toEqual([`Missing "name" attribute.`]);
expect(humanizeErrors(parse('<div i18n>some message</div>', translations).errors)).toEqual([
`Missing "name" attribute.`
]);
});
it("should error when the translation refers to an invalid expression", () => {
it('should error when the translation refers to an invalid expression', () => {
let translations: {[key: string]: string} = {};
translations[id(new Message('hi <ph name="0"/>', null, null))] = 'hi <ph name="99"/>';
expect(
humanizeErrors(parse("<div value='hi {{a}}' i18n-value></div>", translations).errors))
.toEqual(["Invalid interpolation name '99'"]);
humanizeErrors(parse('<div value=\'hi {{a}}\' i18n-value></div>', translations).errors))
.toEqual(['Invalid interpolation name \'99\'']);
});
describe('implicit translation', () => {
it("should support attributes", () => {
it('should support attributes', () => {
let translations: {[key: string]: string} = {};
translations[id(new Message("some message", null, null))] = "another message";
translations[id(new Message('some message', null, null))] = 'another message';
expect(humanizeDom(parse("<i18n-el value='some message'></i18n-el>", translations, [],
{'i18n-el': ['value']})))
expect(humanizeDom(parse('<i18n-el value=\'some message\'></i18n-el>', translations, [], {
'i18n-el': ['value']
}))).toEqual([[HtmlElementAst, 'i18n-el', 0], [HtmlAttrAst, 'value', 'another message']]);
});
it('should support attributes with meaning and description', () => {
let translations: {[key: string]: string} = {};
translations[id(new Message('some message', 'meaning', 'description'))] =
'another message';
expect(
humanizeDom(parse(
'<i18n-el value=\'some message\' i18n-value=\'meaning|description\'></i18n-el>',
translations, [], {'i18n-el': ['value']})))
.toEqual([[HtmlElementAst, 'i18n-el', 0], [HtmlAttrAst, 'value', 'another message']]);
});
it("should support attributes with meaning and description", () => {
it('should support elements', () => {
let translations: {[key: string]: string} = {};
translations[id(new Message("some message", "meaning", "description"))] =
"another message";
translations[id(new Message('message', null, null))] = 'another message';
expect(humanizeDom(parse(
"<i18n-el value='some message' i18n-value='meaning|description'></i18n-el>",
translations, [], {'i18n-el': ['value']})))
.toEqual([[HtmlElementAst, 'i18n-el', 0], [HtmlAttrAst, 'value', 'another message']]);
});
it("should support elements", () => {
let translations: {[key: string]: string} = {};
translations[id(new Message("message", null, null))] = "another message";
expect(humanizeDom(parse("<i18n-el>message</i18n-el>", translations, ['i18n-el'])))
expect(humanizeDom(parse('<i18n-el>message</i18n-el>', translations, ['i18n-el'])))
.toEqual([[HtmlElementAst, 'i18n-el', 0], [HtmlTextAst, 'another message', 1]]);
});
it("should support elements with meaning and description", () => {
it('should support elements with meaning and description', () => {
let translations: {[key: string]: string} = {};
translations[id(new Message("message", "meaning", "description"))] = "another message";
translations[id(new Message('message', 'meaning', 'description'))] = 'another message';
expect(humanizeDom(parse("<i18n-el i18n='meaning|description'>message</i18n-el>",
translations, ['i18n-el'])))
expect(humanizeDom(parse(
'<i18n-el i18n=\'meaning|description\'>message</i18n-el>', translations,
['i18n-el'])))
.toEqual([[HtmlElementAst, 'i18n-el', 0], [HtmlTextAst, 'another message', 1]]);
});
});

View File

@ -1,20 +1,9 @@
import {
beforeEach,
describe,
ddescribe,
expect,
iit,
inject,
it,
xdescribe,
xit
} from '@angular/core/testing/testing_internal';
import {HtmlParser} from '@angular/compiler/src/html_parser';
import {MessageExtractor, removeDuplicates} from '@angular/compiler/src/i18n/message_extractor';
import {Message} from '@angular/compiler/src/i18n/message';
import {Parser} from '@angular/compiler/src/expression_parser/parser';
import {Lexer} from '@angular/compiler/src/expression_parser/lexer';
import {Parser} from '@angular/compiler/src/expression_parser/parser';
import {HtmlParser} from '@angular/compiler/src/html_parser';
import {Message} from '@angular/compiler/src/i18n/message';
import {MessageExtractor, removeDuplicates} from '@angular/compiler/src/i18n/message_extractor';
import {beforeEach, ddescribe, describe, expect, iit, inject, it, xdescribe, xit} from '@angular/core/testing/testing_internal';
export function main() {
describe('MessageExtractor', () => {
@ -27,156 +16,144 @@ export function main() {
});
it('should extract from elements with the i18n attr', () => {
let res = extractor.extract("<div i18n='meaning|desc'>message</div>", "someurl");
expect(res.messages).toEqual([new Message("message", 'meaning', 'desc')]);
let res = extractor.extract('<div i18n=\'meaning|desc\'>message</div>', 'someurl');
expect(res.messages).toEqual([new Message('message', 'meaning', 'desc')]);
});
it('should extract from elements with the i18n attr without a desc', () => {
let res = extractor.extract("<div i18n='meaning'>message</div>", "someurl");
expect(res.messages).toEqual([new Message("message", 'meaning', null)]);
let res = extractor.extract('<div i18n=\'meaning\'>message</div>', 'someurl');
expect(res.messages).toEqual([new Message('message', 'meaning', null)]);
});
it('should extract from elements with the i18n attr without a meaning', () => {
let res = extractor.extract("<div i18n>message</div>", "someurl");
expect(res.messages).toEqual([new Message("message", null, null)]);
let res = extractor.extract('<div i18n>message</div>', 'someurl');
expect(res.messages).toEqual([new Message('message', null, null)]);
});
it('should extract from attributes', () => {
let res = extractor.extract(`
let res = extractor.extract(
`
<div
title1='message1' i18n-title1='meaning1|desc1'
title2='message2' i18n-title2='meaning2|desc2'>
</div>
`,
"someurl");
'someurl');
expect(res.messages)
.toEqual([
new Message("message1", "meaning1", "desc1"),
new Message("message2", "meaning2", "desc2")
]);
expect(res.messages).toEqual([
new Message('message1', 'meaning1', 'desc1'), new Message('message2', 'meaning2', 'desc2')
]);
});
it('should extract from partitions', () => {
let res = extractor.extract(`
let res = extractor.extract(
`
<!-- i18n: meaning1|desc1 -->message1<!-- /i18n -->
<!-- i18n: meaning2|desc2 -->message2<!-- /i18n -->`,
"someUrl");
'someUrl');
expect(res.messages)
.toEqual([
new Message("message1", "meaning1", "desc1"),
new Message("message2", "meaning2", "desc2")
]);
expect(res.messages).toEqual([
new Message('message1', 'meaning1', 'desc1'), new Message('message2', 'meaning2', 'desc2')
]);
});
it('should ignore other comments', () => {
let res = extractor.extract(`
let res = extractor.extract(
`
<!-- i18n: meaning1|desc1 --><!-- other -->message1<!-- /i18n -->`,
"someUrl");
'someUrl');
expect(res.messages).toEqual([new Message("message1", "meaning1", "desc1")]);
expect(res.messages).toEqual([new Message('message1', 'meaning1', 'desc1')]);
});
it('should replace interpolation with placeholders (text nodes)', () => {
let res = extractor.extract("<div i18n>Hi {{one}} and {{two}}</div>", "someurl");
expect(res.messages)
.toEqual(
[new Message('<ph name="t0">Hi <ph name="0"/> and <ph name="1"/></ph>', null, null)]);
let res = extractor.extract('<div i18n>Hi {{one}} and {{two}}</div>', 'someurl');
expect(res.messages).toEqual([new Message(
'<ph name="t0">Hi <ph name="0"/> and <ph name="1"/></ph>', null, null)]);
});
it('should replace interpolation with placeholders (attributes)', () => {
let res =
extractor.extract("<div title='Hi {{one}} and {{two}}' i18n-title></div>", "someurl");
expect(res.messages)
.toEqual([new Message('Hi <ph name="0"/> and <ph name="1"/>', null, null)]);
extractor.extract('<div title=\'Hi {{one}} and {{two}}\' i18n-title></div>', 'someurl');
expect(res.messages).toEqual([new Message(
'Hi <ph name="0"/> and <ph name="1"/>', null, null)]);
});
it('should replace interpolation with named placeholders if provided (text nodes)', () => {
let res = extractor.extract(`
let res = extractor.extract(
`
<div i18n>Hi {{one //i18n(ph="FIRST")}} and {{two //i18n(ph="SECOND")}}</div>`,
'someurl');
expect(res.messages)
.toEqual([
new Message('<ph name="t0">Hi <ph name="FIRST"/> and <ph name="SECOND"/></ph>', null,
null)
]);
'someurl');
expect(res.messages).toEqual([new Message(
'<ph name="t0">Hi <ph name="FIRST"/> and <ph name="SECOND"/></ph>', null, null)]);
});
it('should replace interpolation with named placeholders if provided (attributes)', () => {
let res = extractor.extract(`
let res = extractor.extract(
`
<div title='Hi {{one //i18n(ph="FIRST")}} and {{two //i18n(ph="SECOND")}}'
i18n-title></div>`,
'someurl');
expect(res.messages)
.toEqual([new Message('Hi <ph name="FIRST"/> and <ph name="SECOND"/>', null, null)]);
'someurl');
expect(res.messages).toEqual([new Message(
'Hi <ph name="FIRST"/> and <ph name="SECOND"/>', null, null)]);
});
it('should match named placeholders with extra spacing', () => {
let res = extractor.extract(`
let res = extractor.extract(
`
<div title='Hi {{one // i18n ( ph = "FIRST" )}} and {{two // i18n ( ph = "SECOND" )}}'
i18n-title></div>`,
'someurl');
expect(res.messages)
.toEqual([new Message('Hi <ph name="FIRST"/> and <ph name="SECOND"/>', null, null)]);
'someurl');
expect(res.messages).toEqual([new Message(
'Hi <ph name="FIRST"/> and <ph name="SECOND"/>', null, null)]);
});
it('should suffix duplicate placeholder names with numbers', () => {
let res = extractor.extract(`
let res = extractor.extract(
`
<div title='Hi {{one //i18n(ph="FIRST")}} and {{two //i18n(ph="FIRST")}} and {{three //i18n(ph="FIRST")}}'
i18n-title></div>`,
'someurl');
expect(res.messages)
.toEqual([
new Message('Hi <ph name="FIRST"/> and <ph name="FIRST_1"/> and <ph name="FIRST_2"/>',
null, null)
]);
'someurl');
expect(res.messages).toEqual([new Message(
'Hi <ph name="FIRST"/> and <ph name="FIRST_1"/> and <ph name="FIRST_2"/>', null, null)]);
});
it("should handle html content", () => {
it('should handle html content', () => {
let res = extractor.extract(
'<div i18n><div attr="value">zero<div>one</div></div><div>two</div></div>', "someurl");
expect(res.messages)
.toEqual([
new Message('<ph name="e0">zero<ph name="e2">one</ph></ph><ph name="e4">two</ph>', null,
null)
]);
'<div i18n><div attr="value">zero<div>one</div></div><div>two</div></div>', 'someurl');
expect(res.messages).toEqual([new Message(
'<ph name="e0">zero<ph name="e2">one</ph></ph><ph name="e4">two</ph>', null, null)]);
});
it("should handle html content with interpolation", () => {
it('should handle html content with interpolation', () => {
let res =
extractor.extract('<div i18n><div>zero{{a}}<div>{{b}}</div></div></div>', "someurl");
expect(res.messages)
.toEqual([
new Message(
'<ph name="e0"><ph name="t1">zero<ph name="0"/></ph><ph name="e2"><ph name="t3"><ph name="0"/></ph></ph></ph>',
null, null)
]);
extractor.extract('<div i18n><div>zero{{a}}<div>{{b}}</div></div></div>', 'someurl');
expect(res.messages).toEqual([new Message(
'<ph name="e0"><ph name="t1">zero<ph name="0"/></ph><ph name="e2"><ph name="t3"><ph name="0"/></ph></ph></ph>',
null, null)]);
});
it("should extract from nested elements", () => {
it('should extract from nested elements', () => {
let res = extractor.extract(
'<div title="message1" i18n-title="meaning1|desc1"><div i18n="meaning2|desc2">message2</div></div>',
"someurl");
expect(res.messages)
.toEqual([
new Message("message2", "meaning2", "desc2"),
new Message("message1", "meaning1", "desc1")
]);
'someurl');
expect(res.messages).toEqual([
new Message('message2', 'meaning2', 'desc2'), new Message('message1', 'meaning1', 'desc1')
]);
});
it("should extract messages from attributes in i18n blocks", () => {
it('should extract messages from attributes in i18n blocks', () => {
let res = extractor.extract(
'<div i18n><div attr="value" i18n-attr="meaning|desc">message</div></div>', "someurl");
expect(res.messages)
.toEqual([
new Message('<ph name="e0">message</ph>', null, null),
new Message('value', "meaning", "desc")
]);
'<div i18n><div attr="value" i18n-attr="meaning|desc">message</div></div>', 'someurl');
expect(res.messages).toEqual([
new Message('<ph name="e0">message</ph>', null, null),
new Message('value', 'meaning', 'desc')
]);
});
it("should extract messages from special forms", () => {
let res = extractor.extract(`
it('should extract messages from special forms', () => {
let res = extractor.extract(
`
<div>
{messages.length, plural,
=0 {You have <b>no</b> messages}
@ -184,75 +161,76 @@ export function main() {
}
</div>
`,
"someurl");
'someurl');
expect(res.messages)
.toEqual([
new Message('You have <ph name="e1">no</ph> messages', "plural_0", null),
new Message('You have one message', "plural_1", null)
]);
expect(res.messages).toEqual([
new Message('You have <ph name="e1">no</ph> messages', 'plural_0', null),
new Message('You have one message', 'plural_1', null)
]);
});
it("should remove duplicate messages", () => {
let res = extractor.extract(`
it('should remove duplicate messages', () => {
let res = extractor.extract(
`
<!-- i18n: meaning|desc1 -->message<!-- /i18n -->
<!-- i18n: meaning|desc2 -->message<!-- /i18n -->`,
"someUrl");
'someUrl');
expect(removeDuplicates(res.messages))
.toEqual([
new Message("message", "meaning", "desc1"),
]);
expect(removeDuplicates(res.messages)).toEqual([
new Message('message', 'meaning', 'desc1'),
]);
});
describe('implicit translation', () => {
it('should extract from elements', () => {
let res = extractor.extract("<i18n-tag>message</i18n-tag>", "someurl");
expect(res.messages).toEqual([new Message("message", null, null)]);
let res = extractor.extract('<i18n-tag>message</i18n-tag>', 'someurl');
expect(res.messages).toEqual([new Message('message', null, null)]);
});
it('should extract meaning and description from elements when present', () => {
let res =
extractor.extract("<i18n-tag i18n='meaning|description'>message</i18n-tag>", "someurl");
expect(res.messages).toEqual([new Message("message", "meaning", "description")]);
let res = extractor.extract(
'<i18n-tag i18n=\'meaning|description\'>message</i18n-tag>', 'someurl');
expect(res.messages).toEqual([new Message('message', 'meaning', 'description')]);
});
it('should extract from attributes', () => {
let res = extractor.extract(`<i18n-el trans='message'></i18n-el>`, "someurl");
expect(res.messages).toEqual([new Message("message", null, null)]);
let res = extractor.extract(`<i18n-el trans='message'></i18n-el>`, 'someurl');
expect(res.messages).toEqual([new Message('message', null, null)]);
});
it('should extract meaning and description from attributes when present', () => {
let res = extractor.extract(`<i18n-el trans='message' i18n-trans="meaning|desc"></i18n-el>`,
"someurl");
expect(res.messages).toEqual([new Message("message", "meaning", "desc")]);
let res = extractor.extract(
`<i18n-el trans='message' i18n-trans="meaning|desc"></i18n-el>`, 'someurl');
expect(res.messages).toEqual([new Message('message', 'meaning', 'desc')]);
});
});
describe("errors", () => {
describe('errors', () => {
it('should error on i18n attributes without matching "real" attributes', () => {
let res = extractor.extract(`
let res = extractor.extract(
`
<div
title1='message1' i18n-title1='meaning1|desc1' i18n-title2='meaning2|desc2'>
</div>
`,
"someurl");
'someurl');
expect(res.errors.length).toEqual(1);
expect(res.errors[0].msg).toEqual("Missing attribute 'title2'.");
expect(res.errors[0].msg).toEqual('Missing attribute \'title2\'.');
});
it('should error when cannot find a matching desc', () => {
let res = extractor.extract(`
let res = extractor.extract(
`
<!-- i18n: meaning1|desc1 -->message1`,
"someUrl");
'someUrl');
expect(res.errors.length).toEqual(1);
expect(res.errors[0].msg).toEqual("Missing closing 'i18n' comment.");
expect(res.errors[0].msg).toEqual('Missing closing \'i18n\' comment.');
});
it("should return parse errors when the template is invalid", () => {
let res = extractor.extract("<input&#Besfs", "someurl");
it('should return parse errors when the template is invalid', () => {
let res = extractor.extract('<input&#Besfs', 'someurl');
expect(res.errors.length).toEqual(1);
expect(res.errors[0].msg).toEqual('Unexpected character "s"');
});

View File

@ -1,23 +1,12 @@
import {
beforeEach,
ddescribe,
describe,
expect,
iit,
inject,
it,
xdescribe,
xit
} from '@angular/core/testing/testing_internal';
import {Message, id} from '@angular/compiler/src/i18n/message';
import {beforeEach, ddescribe, describe, expect, iit, inject, it, xdescribe, xit} from '@angular/core/testing/testing_internal';
export function main() {
describe('Message', () => {
describe("id", () => {
it("should return a different id for messages with and without the meaning", () => {
let m1 = new Message("content", "meaning", null);
let m2 = new Message("content", null, null);
describe('id', () => {
it('should return a different id for messages with and without the meaning', () => {
let m1 = new Message('content', 'meaning', null);
let m2 = new Message('content', null, null);
expect(id(m1)).toEqual(id(m1));
expect(id(m1)).not.toEqual(id(m2));
});

View File

@ -1,47 +1,36 @@
import {
beforeEach,
ddescribe,
describe,
expect,
iit,
inject,
it,
xdescribe,
xit
} from '@angular/core/testing/testing_internal';
import {HtmlAst} from '@angular/compiler/src/html_ast';
import {Message, id} from '@angular/compiler/src/i18n/message';
import {serializeXmb, deserializeXmb} from '@angular/compiler/src/i18n/xmb_serializer';
import {ParseSourceSpan, ParseError} from '@angular/compiler/src/parse_util';
import {deserializeXmb, serializeXmb} from '@angular/compiler/src/i18n/xmb_serializer';
import {ParseError, ParseSourceSpan} from '@angular/compiler/src/parse_util';
import {beforeEach, ddescribe, describe, expect, iit, inject, it, xdescribe, xit} from '@angular/core/testing/testing_internal';
export function main() {
describe("Xmb", () => {
describe('Xmb', () => {
describe('Xmb Serialization', () => {
it("should return an empty message bundle for an empty list of messages",
() => { expect(serializeXmb([])).toEqual("<message-bundle></message-bundle>"); });
it('should return an empty message bundle for an empty list of messages',
() => { expect(serializeXmb([])).toEqual('<message-bundle></message-bundle>'); });
it("should serializeXmb messages without desc", () => {
let m = new Message("content", "meaning", null);
it('should serializeXmb messages without desc', () => {
let m = new Message('content', 'meaning', null);
let expected = `<message-bundle><msg id='${id(m)}'>content</msg></message-bundle>`;
expect(serializeXmb([m])).toEqual(expected);
});
it("should serializeXmb messages with desc", () => {
let m = new Message("content", "meaning", "description");
it('should serializeXmb messages with desc', () => {
let m = new Message('content', 'meaning', 'description');
let expected =
`<message-bundle><msg id='${id(m)}' desc='description'>content</msg></message-bundle>`;
expect(serializeXmb([m])).toEqual(expected);
});
});
describe("Xmb Deserialization", () => {
it("should parse an empty bundle", () => {
let mb = "<message-bundle></message-bundle>";
expect(deserializeXmb(mb, "url").messages).toEqual({});
describe('Xmb Deserialization', () => {
it('should parse an empty bundle', () => {
let mb = '<message-bundle></message-bundle>';
expect(deserializeXmb(mb, 'url').messages).toEqual({});
});
it("should parse an non-empty bundle", () => {
it('should parse an non-empty bundle', () => {
let mb = `
<message-bundle>
<msg id="id1" desc="description1">content1</msg>
@ -49,59 +38,59 @@ export function main() {
</message-bundle>
`;
let parsed = deserializeXmb(mb, "url").messages;
expect(_serialize(parsed["id1"])).toEqual("content1");
expect(_serialize(parsed["id2"])).toEqual("content2");
let parsed = deserializeXmb(mb, 'url').messages;
expect(_serialize(parsed['id1'])).toEqual('content1');
expect(_serialize(parsed['id2'])).toEqual('content2');
});
it("should error when cannot parse the content", () => {
it('should error when cannot parse the content', () => {
let mb = `
<message-bundle>
<msg id="id1" desc="description1">content
</message-bundle>
`;
let res = deserializeXmb(mb, "url");
let res = deserializeXmb(mb, 'url');
expect(_serializeErrors(res.errors)).toEqual(['Unexpected closing tag "message-bundle"']);
});
it("should error when cannot find the id attribute", () => {
it('should error when cannot find the id attribute', () => {
let mb = `
<message-bundle>
<msg>content</msg>
</message-bundle>
`;
let res = deserializeXmb(mb, "url");
let res = deserializeXmb(mb, 'url');
expect(_serializeErrors(res.errors)).toEqual(['"id" attribute is missing']);
});
it("should error on empty content", () => {
it('should error on empty content', () => {
let mb = ``;
let res = deserializeXmb(mb, "url");
let res = deserializeXmb(mb, 'url');
expect(_serializeErrors(res.errors)).toEqual(['Missing element "message-bundle"']);
});
it("should error on an invalid element", () => {
it('should error on an invalid element', () => {
let mb = `
<message-bundle>
<invalid>content</invalid>
</message-bundle>
`;
let res = deserializeXmb(mb, "url");
let res = deserializeXmb(mb, 'url');
expect(_serializeErrors(res.errors)).toEqual(['Unexpected element "invalid"']);
});
it("should expand 'ph' elements", () => {
it('should expand \'ph\' elements', () => {
let mb = `
<message-bundle>
<msg id="id1">a<ph name="i0"/></msg>
</message-bundle>
`;
let res = deserializeXmb(mb, "url").messages["id1"];
expect((<any>res[1]).name).toEqual("ph");
let res = deserializeXmb(mb, 'url').messages['id1'];
expect((<any>res[1]).name).toEqual('ph');
});
});
});

View File

@ -1,5 +1,5 @@
import {Component} from '@angular/core';
@Component({styles:<any>('foo'), template: ''})
@Component({styles: <any>('foo'), template: ''})
export class MalformedStylesComponent {
}

View File

@ -1,35 +1,10 @@
import {
ddescribe,
describe,
xdescribe,
it,
iit,
xit,
expect,
beforeEach,
afterEach,
inject,
beforeEachProviders
} from '@angular/core/testing/testing_internal';
import {LIFECYCLE_HOOKS_VALUES} from '@angular/core/src/metadata/lifecycle_hooks';
import {afterEach, beforeEach, beforeEachProviders, ddescribe, describe, expect, iit, inject, it, xdescribe, xit} from '@angular/core/testing/testing_internal';
import {IS_DART, stringify} from '../src/facade/lang';
import {CompileMetadataResolver} from '../src/metadata_resolver';
import {LIFECYCLE_HOOKS_VALUES} from '@angular/core/src/metadata/lifecycle_hooks';
import {
Component,
Directive,
ViewEncapsulation,
ChangeDetectionStrategy,
OnChanges,
OnInit,
DoCheck,
OnDestroy,
AfterContentInit,
AfterContentChecked,
AfterViewInit,
AfterViewChecked,
SimpleChanges,
} from '@angular/core';
import {Component, Directive, ViewEncapsulation, ChangeDetectionStrategy, OnChanges, OnInit, DoCheck, OnDestroy, AfterContentInit, AfterContentChecked, AfterViewInit, AfterViewChecked, SimpleChanges,} from '@angular/core';
import {TEST_PROVIDERS} from './test_bindings';
import {PLATFORM_DIRECTIVES} from '@angular/core/src/platform_directives_and_pipes';
@ -96,7 +71,7 @@ export function main() {
.toContain(resolver.getDirectiveMetadata(SomeDirective));
}));
describe("platform directives", () => {
describe('platform directives', () => {
beforeEachProviders(
() => [{provide: PLATFORM_DIRECTIVES, useValue: [ADirective], multi: true}]);

View File

@ -1,11 +1,13 @@
// ATTENTION: This file will be overwritten with generated code by main()
import {print, IS_DART} from '../src/facade/lang';
import {TypeScriptEmitter} from '@angular/compiler/src/output/ts_emitter';
import {DartEmitter} from '@angular/compiler/src/output/dart_emitter';
import {DartImportGenerator} from '@angular/compiler/src/output/dart_imports';
import * as o from '@angular/compiler/src/output/output_ast';
import {compileComp, compAMetadata} from './offline_compiler_util';
import {TypeScriptEmitter} from '@angular/compiler/src/output/ts_emitter';
import {ComponentFactory} from '@angular/core/src/linker/component_factory';
import {IS_DART, print} from '../src/facade/lang';
import {compAMetadata, compileComp} from './offline_compiler_util';
import {CompA, SimpleJsImportGenerator} from './offline_compiler_util';
export const CompANgFactory: ComponentFactory<CompA> = null;

View File

@ -1,8 +1,10 @@
// ATTENTION: This file will be overwritten with generated code by main()
import {print} from '../src/facade/lang';
import {JavaScriptEmitter} from '@angular/compiler/src/output/js_emitter';
import {compileComp, compAMetadata} from './offline_compiler_util';
import {ComponentFactory} from '@angular/core/src/linker/component_factory';
import {print} from '../src/facade/lang';
import {compAMetadata, compileComp} from './offline_compiler_util';
import {CompA, SimpleJsImportGenerator} from './offline_compiler_util';
export const CompANgFactory: ComponentFactory<CompA> = null;

View File

@ -1,16 +1,4 @@
import {
ddescribe,
describe,
xdescribe,
it,
iit,
xit,
expect,
beforeEach,
afterEach,
inject,
beforeEachProviders,
} from '@angular/core/testing/testing_internal';
import {ddescribe, describe, xdescribe, it, iit, xit, expect, beforeEach, afterEach, inject, beforeEachProviders,} from '@angular/core/testing/testing_internal';
import {IS_DART} from '../src/facade/lang';
import {Injector} from '@angular/core';
@ -43,10 +31,12 @@ export function main() {
var injector: Injector;
var sharedStylesHost: SharedStylesHost;
beforeEach(inject([Injector, SharedStylesHost], (_injector: Injector, _sharedStylesHost: SharedStylesHost) => {
injector = _injector;
sharedStylesHost = _sharedStylesHost;
}));
beforeEach(inject(
[Injector, SharedStylesHost],
(_injector: Injector, _sharedStylesHost: SharedStylesHost) => {
injector = _injector;
sharedStylesHost = _sharedStylesHost;
}));
fixtures.forEach((fixture) => {
describe(`${fixture.name}`, () => {

View File

@ -1,31 +1,22 @@
import {print, isPresent, IS_DART} from '../src/facade/lang';
import {OutputEmitter} from '@angular/compiler/src/output/abstract_emitter';
import {Console} from '../core_private';
import {
OfflineCompiler,
NormalizedComponentWithViewDirectives,
SourceModule
} from '@angular/compiler/src/offline_compiler';
import {TemplateParser} from '@angular/compiler/src/template_parser';
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 {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 {CompileDirectiveMetadata, CompileTemplateMetadata, CompileTypeMetadata} from '@angular/compiler/src/compile_metadata';
import {CompilerConfig} from '@angular/compiler/src/config';
import {createOfflineCompileUrlResolver} from '@angular/compiler/src/url_resolver';
import {MockSchemaRegistry} from '../testing/schema_registry_mock';
import {MODULE_SUFFIX} from '@angular/compiler/src/util';
import {MockXHR} from '../testing/xhr_mock';
import {DirectiveNormalizer} from '@angular/compiler/src/directive_normalizer';
import {Lexer} from '@angular/compiler/src/expression_parser/lexer';
import {Parser} from '@angular/compiler/src/expression_parser/parser';
import {HtmlParser} from '@angular/compiler/src/html_parser';
import {NormalizedComponentWithViewDirectives, OfflineCompiler, SourceModule} from '@angular/compiler/src/offline_compiler';
import {OutputEmitter} from '@angular/compiler/src/output/abstract_emitter';
import {ImportGenerator} from '@angular/compiler/src/output/path_util';
import {StyleCompiler} from '@angular/compiler/src/style_compiler';
import {TemplateParser} from '@angular/compiler/src/template_parser';
import {createOfflineCompileUrlResolver} from '@angular/compiler/src/url_resolver';
import {MODULE_SUFFIX} from '@angular/compiler/src/util';
import {ViewCompiler} from '@angular/compiler/src/view_compiler/view_compiler';
import {
CompileDirectiveMetadata,
CompileTypeMetadata,
CompileTemplateMetadata
} from '@angular/compiler/src/compile_metadata';
import {Console} from '../core_private';
import {IS_DART, isPresent, print} from '../src/facade/lang';
import {MockSchemaRegistry} from '../testing/schema_registry_mock';
import {MockXHR} from '../testing/xhr_mock';
export class CompA { user: string; }
@ -50,16 +41,18 @@ function _createOfflineCompiler(xhr: MockXHR, emitter: OutputEmitter): OfflineCo
xhr.when(`${THIS_MODULE_PATH}/offline_compiler_compa.html`, 'Hello World {{user}}!');
var htmlParser = new HtmlParser();
var config = new CompilerConfig(true, true, true);
var normalizer = new DirectiveNormalizer(xhr, urlResolver, htmlParser, new CompilerConfig(true, true, true));
var normalizer =
new DirectiveNormalizer(xhr, urlResolver, htmlParser, new CompilerConfig(true, true, true));
return new OfflineCompiler(
normalizer, new TemplateParser(new Parser(new Lexer()), new MockSchemaRegistry({}, {}),
htmlParser, new Console(), []),
normalizer,
new TemplateParser(
new Parser(new Lexer()), new MockSchemaRegistry({}, {}), htmlParser, new Console(), []),
new StyleCompiler(urlResolver), new ViewCompiler(new CompilerConfig(true, true, true)),
emitter, xhr);
}
export function compileComp(emitter: OutputEmitter,
comp: CompileDirectiveMetadata): Promise<string> {
export function compileComp(
emitter: OutputEmitter, comp: CompileDirectiveMetadata): Promise<string> {
var xhr = new MockXHR();
var compiler = _createOfflineCompiler(xhr, emitter);
var result = compiler.normalizeDirectiveMetadata(comp).then((normComp) => {

View File

@ -1,13 +1,4 @@
import {
beforeEach,
ddescribe,
describe,
expect,
iit,
inject,
it,
xit,
} from '@angular/core/testing/testing_internal';
import {beforeEach, ddescribe, describe, expect, iit, inject, it, xit,} from '@angular/core/testing/testing_internal';
import {escapeSingleQuoteString} from '@angular/compiler/src/output/abstract_emitter';

Some files were not shown because too many files have changed in this diff Show More