Version 0.8.0.0 svn merge -r 27984:28200 https://dart.googlecode.com/svn/branches/bleeding_edge trunk git-svn-id: http://dart.googlecode.com/svn/trunk@28224 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/pkg/analyzer_experimental/bin/formatter.dart b/pkg/analyzer_experimental/bin/formatter.dart index 02dc8f1..a8ea0fe 100755 --- a/pkg/analyzer_experimental/bin/formatter.dart +++ b/pkg/analyzer_experimental/bin/formatter.dart
@@ -159,7 +159,11 @@ _toJson(formatResult) => // Actual JSON format TBD JSON.encode({'source': formatResult.source, - 'selection': formatResult.selection.toString()}); + 'selection': { + 'offset': formatResult.selection.offset, + 'length': formatResult.selection.length + } + }); /// Log the given [msg]. _log(String msg) {
diff --git a/pkg/analyzer_experimental/lib/options.dart b/pkg/analyzer_experimental/lib/options.dart index efa3b5f..9b3ffac 100644 --- a/pkg/analyzer_experimental/lib/options.dart +++ b/pkg/analyzer_experimental/lib/options.dart
@@ -26,6 +26,9 @@ /** Whether to display version information */ final bool displayVersion; + /** Whether to report hints */ + final bool disableHints; + /** Whether to ignore unrecognized flags */ final bool ignoreUnrecognizedFlags; @@ -57,6 +60,7 @@ : shouldBatch = args['batch'], machineFormat = args['machine'], displayVersion = args['version'], + disableHints = args['no-hints'], ignoreUnrecognizedFlags = args['ignore-unrecognized-flags'], perf = args['perf'], showPackageWarnings = args['show-package-warnings'], @@ -102,6 +106,8 @@ defaultsTo: false, negatable: false) ..addFlag('version', help: 'Print the analyzer version', defaultsTo: false, negatable: false) + ..addFlag('no-hints', help: 'Do not show hint results', + defaultsTo: false, negatable: false) ..addFlag('ignore-unrecognized-flags', help: 'Ignore unrecognized command line flags', defaultsTo: false, negatable: false)
diff --git a/pkg/analyzer_experimental/lib/src/analyzer_impl.dart b/pkg/analyzer_experimental/lib/src/analyzer_impl.dart index 40b436c..2104617 100644 --- a/pkg/analyzer_experimental/lib/src/analyzer_impl.dart +++ b/pkg/analyzer_experimental/lib/src/analyzer_impl.dart
@@ -86,6 +86,11 @@ sourceFactory = new SourceFactory.con1(contentCache, resolvers); context = AnalysisEngine.instance.createAnalysisContext(); context.sourceFactory = sourceFactory; + + // set options for context + AnalysisOptionsImpl contextOptions = new AnalysisOptionsImpl(); + contextOptions.hint = !options.disableHints; + context.analysisOptions = contextOptions; } /// Fills [sources]. @@ -139,6 +144,7 @@ /// Fills [errorInfos]. void prepareErrors() { for (Source source in sources) { + context.computeErrors(source); var sourceErrors = context.getErrors(source); errorInfos.add(sourceErrors); }
diff --git a/pkg/analyzer_experimental/lib/src/error_formatter.dart b/pkg/analyzer_experimental/lib/src/error_formatter.dart index 47d718d..c26aaa4 100644 --- a/pkg/analyzer_experimental/lib/src/error_formatter.dart +++ b/pkg/analyzer_experimental/lib/src/error_formatter.dart
@@ -46,41 +46,62 @@ // format errors int errorCount = 0; int warnCount = 0; + int hintCount = 0; for (AnalysisError error in errors) { - if (error.errorCode.errorSeverity == ErrorSeverity.ERROR) { + var severity = error.errorCode.errorSeverity; + if (severity == ErrorSeverity.ERROR) { errorCount++; - } else if (error.errorCode.errorSeverity == ErrorSeverity.WARNING) { + } else if (severity == ErrorSeverity.WARNING) { if (options.warningsAreFatal) { errorCount++; } else { - warnCount++; + if (error.errorCode.type == ErrorType.HINT) { + hintCount++; + } else { + warnCount++; + } } } formatError(errorToLine, error); } // print statistics if (!options.machineFormat) { - if (errorCount != 0 && warnCount != 0) { + var hasErrors = errorCount != 0; + var hasWarns = warnCount != 0; + var hasHints = hintCount != 0; + bool hasContent = false; + if (hasErrors) { out.write(errorCount); out.write(' '); out.write(pluralize("error", errorCount)); - out.write(' and '); + hasContent = true; + } + if (hasWarns) { + if (hasContent) { + if (!hasHints) { + out.write(' and '); + } else { + out.write(", "); + } + } out.write(warnCount); out.write(' '); out.write(pluralize("warning", warnCount)); - out.writeln(' found.'); - } else if (errorCount != 0) { - out.write(errorCount); + hasContent = true; + } + if (hasHints) { + if (hasContent) { + out.write(" and "); + } + out.write(hintCount); out.write(' '); - out.write(pluralize("error", errorCount)); - out.writeln(' found.'); - } else if (warnCount != 0) { - out.write(warnCount); - out.write(' '); - out.write(pluralize("warning", warnCount)); - out.writeln(' found.'); + out.write(pluralize("hint", hintCount)); + hasContent = true; + } + if (hasContent) { + out.writeln(" found."); } else { - out.writeln("No issues found."); + out.writeln("No issues found"); } } } @@ -110,8 +131,12 @@ out.write('|'); out.write(escapePipe(error.message)); } else { + String errorType = error.errorCode.errorSeverity.displayName; + if (error.errorCode.type == ErrorType.HINT) { + errorType = error.errorCode.type.displayName; + } // [warning] 'foo' is not a... (/Users/.../tmp/foo.dart, line 1, col 2) - out.write('[${severity.displayName}] ${error.message} '); + out.write('[$errorType] ${error.message} '); out.write('(${source.fullName}'); out.write(', line ${location.lineNumber}, col ${location.columnNumber})'); }
diff --git a/pkg/analyzer_experimental/lib/src/generated/ast.dart b/pkg/analyzer_experimental/lib/src/generated/ast.dart index dea447d..3acc231 100644 --- a/pkg/analyzer_experimental/lib/src/generated/ast.dart +++ b/pkg/analyzer_experimental/lib/src/generated/ast.dart
@@ -116,7 +116,7 @@ if (beginToken == null) { return -1; } - return beginToken.offset; + return this.beginToken.offset; } /** @@ -484,8 +484,8 @@ * * @param comment the documentation comment to be associated with this node */ - void set documentationComment(Comment comment2) { - this._comment = becomeParentOf(comment2); + void set documentationComment(Comment comment) { + this._comment = becomeParentOf(comment); } /** @@ -493,9 +493,9 @@ * * @param metadata the metadata to be associated with this node */ - void set metadata(List<Annotation> metadata2) { + void set metadata(List<Annotation> metadata) { this._metadata.clear(); - this._metadata.addAll(metadata2); + this._metadata.addAll(metadata); } void visitChildren(ASTVisitor visitor) { if (commentIsBeforeAnnotations()) { @@ -686,8 +686,8 @@ * * @param arguments the arguments to the constructor being invoked */ - void set arguments(ArgumentList arguments2) { - this._arguments = becomeParentOf(arguments2); + void set arguments(ArgumentList arguments) { + this._arguments = becomeParentOf(arguments); } /** @@ -695,8 +695,8 @@ * * @param constructorName the name of the constructor being invoked */ - void set constructorName(SimpleIdentifier constructorName2) { - this._constructorName = becomeParentOf(constructorName2); + void set constructorName(SimpleIdentifier constructorName) { + this._constructorName = becomeParentOf(constructorName); } /** @@ -704,8 +704,8 @@ * * @param element the element to be associated with this identifier */ - void set element(Element element2) { - this._element = element2; + void set element(Element element) { + this._element = element; } /** @@ -714,8 +714,8 @@ * * @param name the name of the constructor being invoked or the name of the field being referenced */ - void set name(Identifier name2) { - this._name = becomeParentOf(name2); + void set name(Identifier name) { + this._name = becomeParentOf(name); } void visitChildren(ASTVisitor visitor) { safelyVisitChild(_name, visitor); @@ -779,8 +779,8 @@ * * @param identifier the identifier representing the argument being tested */ - void set identifier(SimpleIdentifier identifier2) { - this._identifier = becomeParentOf(identifier2); + void set identifier(SimpleIdentifier identifier) { + this._identifier = becomeParentOf(identifier); } void visitChildren(ASTVisitor visitor) { safelyVisitChild(_identifier, visitor); @@ -1046,8 +1046,8 @@ * * @param expression the expression used to compute the value being cast */ - void set expression(Expression expression2) { - this._expression = becomeParentOf(expression2); + void set expression(Expression expression) { + this._expression = becomeParentOf(expression); } /** @@ -1143,8 +1143,8 @@ * * @param the condition that is being asserted to be `true` */ - void set condition(Expression condition2) { - this._condition = becomeParentOf(condition2); + void set condition(Expression condition) { + this._condition = becomeParentOf(condition); } void visitChildren(ASTVisitor visitor) { safelyVisitChild(_condition, visitor); @@ -1655,8 +1655,8 @@ * * @param block the block representing the body of the function */ - void set block(Block block2) { - this._block = becomeParentOf(block2); + void set block(Block block) { + this._block = becomeParentOf(block); } void visitChildren(ASTVisitor visitor) { safelyVisitChild(_block, visitor); @@ -1847,8 +1847,8 @@ * * @param target the target of the cascade sections */ - void set target(Expression target2) { - this._target = becomeParentOf(target2); + void set target(Expression target) { + this._target = becomeParentOf(target); } void visitChildren(ASTVisitor visitor) { safelyVisitChild(_target, visitor); @@ -2214,8 +2214,8 @@ * * @param extendsClause the extends clause for this class */ - void set extendsClause(ExtendsClause extendsClause2) { - this._extendsClause = becomeParentOf(extendsClause2); + void set extendsClause(ExtendsClause extendsClause) { + this._extendsClause = becomeParentOf(extendsClause); } /** @@ -2223,8 +2223,8 @@ * * @param implementsClause the implements clause for the class */ - void set implementsClause(ImplementsClause implementsClause2) { - this._implementsClause = becomeParentOf(implementsClause2); + void set implementsClause(ImplementsClause implementsClause) { + this._implementsClause = becomeParentOf(implementsClause); } /** @@ -2241,8 +2241,8 @@ * * @param withClause the with clause for the class */ - void set withClause(WithClause withClause2) { - this._withClause = becomeParentOf(withClause2); + void set withClause(WithClause withClause) { + this._withClause = becomeParentOf(withClause); } void visitChildren(ASTVisitor visitor) { super.visitChildren(visitor); @@ -2422,8 +2422,8 @@ * * @param implementsClause the implements clause for this class */ - void set implementsClause(ImplementsClause implementsClause2) { - this._implementsClause = becomeParentOf(implementsClause2); + void set implementsClause(ImplementsClause implementsClause) { + this._implementsClause = becomeParentOf(implementsClause); } /** @@ -2431,8 +2431,8 @@ * * @param name the name of the class being declared */ - void set name(SimpleIdentifier name2) { - this._name = becomeParentOf(name2); + void set name(SimpleIdentifier name) { + this._name = becomeParentOf(name); } /** @@ -2440,8 +2440,8 @@ * * @param superclass the name of the superclass of the class being declared */ - void set superclass(TypeName superclass2) { - this._superclass = becomeParentOf(superclass2); + void set superclass(TypeName superclass) { + this._superclass = becomeParentOf(superclass); } /** @@ -2449,8 +2449,8 @@ * * @param typeParameters the type parameters for the class */ - void set typeParameters(TypeParameterList typeParameters2) { - this._typeParameters = becomeParentOf(typeParameters2); + void set typeParameters(TypeParameterList typeParameters) { + this._typeParameters = becomeParentOf(typeParameters); } /** @@ -2458,8 +2458,8 @@ * * @param withClause the with clause for this class */ - void set withClause(WithClause withClause2) { - this._withClause = becomeParentOf(withClause2); + void set withClause(WithClause withClause) { + this._withClause = becomeParentOf(withClause); } void visitChildren(ASTVisitor visitor) { super.visitChildren(visitor); @@ -2711,8 +2711,8 @@ * * @param identifier the identifier being referenced */ - void set identifier(Identifier identifier2) { - identifier2 = becomeParentOf(identifier2); + void set identifier(Identifier identifier) { + identifier = becomeParentOf(identifier); } void visitChildren(ASTVisitor visitor) { safelyVisitChild(_identifier, visitor); @@ -2928,8 +2928,8 @@ * * @param scriptTag the script tag at the beginning of the compilation unit */ - void set scriptTag(ScriptTag scriptTag2) { - this._scriptTag = becomeParentOf(scriptTag2); + void set scriptTag(ScriptTag scriptTag) { + this._scriptTag = becomeParentOf(scriptTag); } void visitChildren(ASTVisitor visitor) { safelyVisitChild(_scriptTag, visitor); @@ -3345,8 +3345,8 @@ * * @param element the element associated with this constructor */ - void set element(ConstructorElement element2) { - this._element = element2; + void set element(ConstructorElement element) { + this._element = element; } /** @@ -3363,8 +3363,8 @@ * * @param parameters the parameters associated with the constructor */ - void set parameters(FormalParameterList parameters2) { - this._parameters = becomeParentOf(parameters2); + void set parameters(FormalParameterList parameters) { + this._parameters = becomeParentOf(parameters); } /** @@ -3374,8 +3374,8 @@ * @param redirectedConstructor the name of the constructor to which this constructor will be * redirected */ - void set redirectedConstructor(ConstructorName redirectedConstructor2) { - this._redirectedConstructor = becomeParentOf(redirectedConstructor2); + void set redirectedConstructor(ConstructorName redirectedConstructor) { + this._redirectedConstructor = becomeParentOf(redirectedConstructor); } /** @@ -3396,9 +3396,9 @@ safelyVisitChild(_body, visitor); } Token get firstTokenAfterCommentAndMetadata { - Token leftMost2 = leftMost([externalKeyword, constKeyword, factoryKeyword]); - if (leftMost2 != null) { - return leftMost2; + Token leftMost = this.leftMost([externalKeyword, constKeyword, factoryKeyword]); + if (leftMost != null) { + return leftMost; } return _returnType.beginToken; } @@ -3518,8 +3518,8 @@ * * @param expression the expression computing the value to which the field will be initialized */ - void set expression(Expression expression2) { - this._expression = becomeParentOf(expression2); + void set expression(Expression expression) { + this._expression = becomeParentOf(expression); } /** @@ -3644,8 +3644,8 @@ * * @param name the name of the constructor */ - void set name(SimpleIdentifier name2) { - this._name = becomeParentOf(name2); + void set name(SimpleIdentifier name) { + this._name = becomeParentOf(name); } /** @@ -3663,8 +3663,8 @@ * * @param type the name of the type defining the constructor */ - void set type(TypeName type2) { - this._type = becomeParentOf(type2); + void set type(TypeName type) { + this._type = becomeParentOf(type); } void visitChildren(ASTVisitor visitor) { safelyVisitChild(_type, visitor); @@ -3831,11 +3831,11 @@ DeclaredIdentifier({Comment comment, List<Annotation> metadata, Token keyword, TypeName type, SimpleIdentifier identifier}) : this.full(comment, metadata, keyword, type, identifier); accept(ASTVisitor visitor) => visitor.visitDeclaredIdentifier(this); LocalVariableElement get element { - SimpleIdentifier identifier2 = identifier; - if (identifier2 == null) { + SimpleIdentifier identifier = this.identifier; + if (identifier == null) { return null; } - return identifier2.staticElement as LocalVariableElement; + return identifier.staticElement as LocalVariableElement; } Token get endToken => identifier.endToken; @@ -3990,8 +3990,8 @@ * * @param kind the kind of this parameter */ - void set kind(ParameterKind kind2) { - this._kind = kind2; + void set kind(ParameterKind kind) { + this._kind = kind; } /** @@ -4381,9 +4381,9 @@ ExportDirective({Comment comment, List<Annotation> metadata, Token keyword, StringLiteral libraryUri, List<Combinator> combinators, Token semicolon}) : this.full(comment, metadata, keyword, libraryUri, combinators, semicolon); accept(ASTVisitor visitor) => visitor.visitExportDirective(this); LibraryElement get uriElement { - Element element2 = element; - if (element2 is ExportElement) { - return ((element2 as ExportElement)).exportedLibrary; + Element element = this.element; + if (element is ExportElement) { + return ((element as ExportElement)).exportedLibrary; } return null; } @@ -4605,8 +4605,8 @@ * * @param expression the expression representing the body of the function */ - void set expression(Expression expression2) { - this._expression = becomeParentOf(expression2); + void set expression(Expression expression) { + this._expression = becomeParentOf(expression); } void visitChildren(ASTVisitor visitor) { safelyVisitChild(_expression, visitor); @@ -4675,8 +4675,8 @@ * * @param expression the expression that comprises the statement */ - void set expression(Expression expression2) { - this._expression = becomeParentOf(expression2); + void set expression(Expression expression) { + this._expression = becomeParentOf(expression); } void visitChildren(ASTVisitor visitor) { safelyVisitChild(_expression, visitor); @@ -4946,8 +4946,8 @@ * * @param parameters the parameters of the function-typed parameter */ - void set parameters(FormalParameterList parameters2) { - this._parameters = becomeParentOf(parameters2); + void set parameters(FormalParameterList parameters) { + this._parameters = becomeParentOf(parameters); } /** @@ -5120,8 +5120,8 @@ * * @param body the body of the loop */ - void set body(Statement body2) { - this._body = becomeParentOf(body2); + void set body(Statement body) { + this._body = becomeParentOf(body); } /** @@ -5129,8 +5129,8 @@ * * @param identifier the loop variable */ - void set identifier(SimpleIdentifier identifier2) { - this._identifier = becomeParentOf(identifier2); + void set identifier(SimpleIdentifier identifier) { + this._identifier = becomeParentOf(identifier); } /** @@ -5312,8 +5312,8 @@ * * @param body the body of the loop */ - void set body(Statement body2) { - this._body = becomeParentOf(body2); + void set body(Statement body) { + this._body = becomeParentOf(body); } /** @@ -5330,8 +5330,8 @@ * * @param initialization the initialization expression */ - void set initialization(Expression initialization2) { - this._initialization = becomeParentOf(initialization2); + void set initialization(Expression initialization) { + this._initialization = becomeParentOf(initialization); } /** @@ -5722,8 +5722,8 @@ * * @param functionExpression the function expression being wrapped */ - void set functionExpression(FunctionExpression functionExpression2) { - functionExpression2 = becomeParentOf(functionExpression2); + void set functionExpression(FunctionExpression functionExpression) { + functionExpression = becomeParentOf(functionExpression); } /** @@ -5800,8 +5800,8 @@ * * @param functionDeclaration the function declaration being wrapped */ - void set functionExpression(FunctionDeclaration functionDeclaration2) { - this.functionDeclaration = becomeParentOf(functionDeclaration2); + void set functionExpression(FunctionDeclaration functionDeclaration) { + this.functionDeclaration = becomeParentOf(functionDeclaration); } void visitChildren(ASTVisitor visitor) { safelyVisitChild(functionDeclaration, visitor); @@ -5899,8 +5899,8 @@ * * @param parameters the parameters associated with the function */ - void set parameters(FormalParameterList parameters2) { - this._parameters = becomeParentOf(parameters2); + void set parameters(FormalParameterList parameters) { + this._parameters = becomeParentOf(parameters); } void visitChildren(ASTVisitor visitor) { safelyVisitChild(_parameters, visitor); @@ -6012,8 +6012,8 @@ * * @param argumentList the list of arguments to the method */ - void set argumentList(ArgumentList argumentList2) { - this._argumentList = becomeParentOf(argumentList2); + void set argumentList(ArgumentList argumentList) { + this._argumentList = becomeParentOf(argumentList); } /** @@ -6021,8 +6021,8 @@ * * @param function the expression producing the function being invoked */ - void set function(Expression function2) { - function2 = becomeParentOf(function2); + void set function(Expression function) { + function = becomeParentOf(function); } /** @@ -6146,8 +6146,8 @@ * * @param name the name of the function type being declared */ - void set name(SimpleIdentifier name2) { - this._name = becomeParentOf(name2); + void set name(SimpleIdentifier name) { + this._name = becomeParentOf(name); } /** @@ -6155,8 +6155,8 @@ * * @param parameters the parameters associated with the function type */ - void set parameters(FormalParameterList parameters2) { - this._parameters = becomeParentOf(parameters2); + void set parameters(FormalParameterList parameters) { + this._parameters = becomeParentOf(parameters); } /** @@ -6173,8 +6173,8 @@ * * @param typeParameters the type parameters for the function type */ - void set typeParameters(TypeParameterList typeParameters2) { - this._typeParameters = becomeParentOf(typeParameters2); + void set typeParameters(TypeParameterList typeParameters) { + this._typeParameters = becomeParentOf(typeParameters); } void visitChildren(ASTVisitor visitor) { super.visitChildren(visitor); @@ -6264,8 +6264,8 @@ * * @param parameters the parameters of the function-typed parameter */ - void set parameters(FormalParameterList parameters2) { - this._parameters = becomeParentOf(parameters2); + void set parameters(FormalParameterList parameters) { + this._parameters = becomeParentOf(parameters); } /** @@ -6273,8 +6273,8 @@ * * @param returnType the return type of the function */ - void set returnType(TypeName returnType2) { - this._returnType = becomeParentOf(returnType2); + void set returnType(TypeName returnType) { + this._returnType = becomeParentOf(returnType); } void visitChildren(ASTVisitor visitor) { super.visitChildren(visitor); @@ -6724,9 +6724,9 @@ */ SimpleIdentifier get prefix => _prefix; LibraryElement get uriElement { - Element element2 = element; - if (element2 is ImportElement) { - return ((element2 as ImportElement)).importedLibrary; + Element element = this.element; + if (element is ImportElement) { + return ((element as ImportElement)).importedLibrary; } return null; } @@ -6736,8 +6736,8 @@ * * @param prefix the prefix to be used with the imported names */ - void set prefix(SimpleIdentifier prefix2) { - this._prefix = becomeParentOf(prefix2); + void set prefix(SimpleIdentifier prefix) { + this._prefix = becomeParentOf(prefix); } void visitChildren(ASTVisitor visitor) { super.visitChildren(visitor); @@ -7184,8 +7184,8 @@ * * @param argumentList the list of arguments to the constructor */ - void set argumentList(ArgumentList argumentList2) { - this._argumentList = becomeParentOf(argumentList2); + void set argumentList(ArgumentList argumentList) { + this._argumentList = becomeParentOf(argumentList); } void visitChildren(ASTVisitor visitor) { safelyVisitChild(constructorName, visitor); @@ -7333,8 +7333,8 @@ * * @param expression the expression to be evaluated for the value to be converted into a string */ - void set expression(Expression expression2) { - this._expression = becomeParentOf(expression2); + void set expression(Expression expression) { + this._expression = becomeParentOf(expression); } void visitChildren(ASTVisitor visitor) { safelyVisitChild(_expression, visitor); @@ -7499,8 +7499,8 @@ * * @param expression the expression used to compute the value whose type is being tested */ - void set expression(Expression expression2) { - this._expression = becomeParentOf(expression2); + void set expression(Expression expression) { + this._expression = becomeParentOf(expression); } /** @@ -7572,8 +7572,8 @@ * * @param label the label being associated with the statement */ - void set label(SimpleIdentifier label2) { - this._label = becomeParentOf(label2); + void set label(SimpleIdentifier label) { + this._label = becomeParentOf(label); } void visitChildren(ASTVisitor visitor) { safelyVisitChild(_label, visitor); @@ -7642,8 +7642,8 @@ * * @param statement the statement with which the labels are being associated */ - void set statement(Statement statement2) { - this._statement = becomeParentOf(statement2); + void set statement(Statement statement) { + this._statement = becomeParentOf(statement); } void visitChildren(ASTVisitor visitor) { labels.accept(visitor); @@ -7718,8 +7718,8 @@ * * @param name the name of the library being defined */ - void set name(LibraryIdentifier name2) { - this._name = becomeParentOf(name2); + void set name(LibraryIdentifier name) { + this._name = becomeParentOf(name); } void visitChildren(ASTVisitor visitor) { super.visitChildren(visitor); @@ -7844,9 +7844,9 @@ if (token != null) { return token; } - TypeArgumentList typeArguments2 = typeArguments; - if (typeArguments2 != null) { - return typeArguments2.beginToken; + TypeArgumentList typeArguments = this.typeArguments; + if (typeArguments != null) { + return typeArguments.beginToken; } return _leftBracket; } @@ -7968,9 +7968,9 @@ if (token != null) { return token; } - TypeArgumentList typeArguments2 = typeArguments; - if (typeArguments2 != null) { - return typeArguments2.beginToken; + TypeArgumentList typeArguments = this.typeArguments; + if (typeArguments != null) { + return typeArguments.beginToken; } return _leftBracket; } @@ -8308,8 +8308,8 @@ * * @param parameters the parameters associated with the method */ - void set parameters(FormalParameterList parameters2) { - this._parameters = becomeParentOf(parameters2); + void set parameters(FormalParameterList parameters) { + this._parameters = becomeParentOf(parameters); } /** @@ -8474,8 +8474,8 @@ * * @param argumentList the list of arguments to the method */ - void set argumentList(ArgumentList argumentList2) { - this._argumentList = becomeParentOf(argumentList2); + void set argumentList(ArgumentList argumentList) { + this._argumentList = becomeParentOf(argumentList); } /** @@ -8580,8 +8580,8 @@ * * @param expression the expression with which the name is associated */ - void set expression(Expression expression2) { - this._expression = becomeParentOf(expression2); + void set expression(Expression expression) { + this._expression = becomeParentOf(expression); } /** @@ -8849,8 +8849,8 @@ * * @param comment the documentation comment to be associated with this parameter */ - void set documentationComment(Comment comment2) { - this._comment = becomeParentOf(comment2); + void set documentationComment(Comment comment) { + this._comment = becomeParentOf(comment); } /** @@ -8858,8 +8858,8 @@ * * @param identifier the name of the parameter being declared */ - void set identifier(SimpleIdentifier identifier2) { - this._identifier = becomeParentOf(identifier2); + void set identifier(SimpleIdentifier identifier) { + this._identifier = becomeParentOf(identifier); } void visitChildren(ASTVisitor visitor) { if (commentIsBeforeAnnotations()) { @@ -9017,8 +9017,8 @@ * * @param expression the expression within the parentheses */ - void set expression(Expression expression2) { - this._expression = becomeParentOf(expression2); + void set expression(Expression expression) { + this._expression = becomeParentOf(expression); } /** @@ -9170,8 +9170,8 @@ * * @param libraryName the name of the library that the containing compilation unit is part of */ - void set libraryName(LibraryIdentifier libraryName2) { - this._libraryName = becomeParentOf(libraryName2); + void set libraryName(LibraryIdentifier libraryName) { + this._libraryName = becomeParentOf(libraryName); } void visitChildren(ASTVisitor visitor) { super.visitChildren(visitor); @@ -9621,8 +9621,8 @@ * * @param identifier the identifier being prefixed */ - void set identifier(SimpleIdentifier identifier2) { - this._identifier = becomeParentOf(identifier2); + void set identifier(SimpleIdentifier identifier) { + this._identifier = becomeParentOf(identifier); } /** @@ -9863,8 +9863,8 @@ * * @param argumentList the list of arguments to the constructor */ - void set argumentList(ArgumentList argumentList2) { - this._argumentList = becomeParentOf(argumentList2); + void set argumentList(ArgumentList argumentList) { + this._argumentList = becomeParentOf(argumentList); } /** @@ -9984,8 +9984,8 @@ * * @param expression the expression computing the value to be returned */ - void set expression(Expression expression2) { - this._expression = becomeParentOf(expression2); + void set expression(Expression expression) { + this._expression = becomeParentOf(expression); } void visitChildren(ASTVisitor visitor) { safelyVisitChild(_expression, visitor); @@ -10710,8 +10710,8 @@ * * @param argumentList the list of arguments to the constructor */ - void set argumentList(ArgumentList argumentList2) { - this._argumentList = becomeParentOf(argumentList2); + void set argumentList(ArgumentList argumentList) { + this._argumentList = becomeParentOf(argumentList); } /** @@ -10819,8 +10819,8 @@ * * @param expression the expression controlling whether the statements will be executed */ - void set expression(Expression expression2) { - this._expression = becomeParentOf(expression2); + void set expression(Expression expression) { + this._expression = becomeParentOf(expression); } void visitChildren(ASTVisitor visitor) { labels.accept(visitor); @@ -11036,8 +11036,8 @@ * * @param expression the expression used to determine which of the switch members will be selected */ - void set expression(Expression expression2) { - this._expression = becomeParentOf(expression2); + void set expression(Expression expression) { + this._expression = becomeParentOf(expression); } void visitChildren(ASTVisitor visitor) { safelyVisitChild(_expression, visitor); @@ -11189,8 +11189,8 @@ * * @param expression the expression computing the exception to be thrown */ - void set expression(Expression expression2) { - this._expression = becomeParentOf(expression2); + void set expression(Expression expression) { + this._expression = becomeParentOf(expression); } void visitChildren(ASTVisitor visitor) { safelyVisitChild(_expression, visitor); @@ -11582,8 +11582,8 @@ * * @param typeArguments the type arguments associated with the type */ - void set typeArguments(TypeArgumentList typeArguments2) { - this._typeArguments = becomeParentOf(typeArguments2); + void set typeArguments(TypeArgumentList typeArguments) { + this._typeArguments = becomeParentOf(typeArguments); } void visitChildren(ASTVisitor visitor) { safelyVisitChild(_name, visitor); @@ -11858,8 +11858,8 @@ * * @param uri the URI referenced by this directive */ - void set uri(StringLiteral uri2) { - this._uri = becomeParentOf(uri2); + void set uri(StringLiteral uri) { + this._uri = becomeParentOf(uri); } void visitChildren(ASTVisitor visitor) { super.visitChildren(visitor); @@ -11990,8 +11990,8 @@ * * @param initializer the expression used to compute the initial value for the variable */ - void set initializer(Expression initializer2) { - this._initializer = becomeParentOf(initializer2); + void set initializer(Expression initializer) { + this._initializer = becomeParentOf(initializer); } /** @@ -11999,8 +11999,8 @@ * * @param name the name of the variable being declared */ - void set name(SimpleIdentifier name2) { - this._name = becomeParentOf(name2); + void set name(SimpleIdentifier name) { + this._name = becomeParentOf(name); } void visitChildren(ASTVisitor visitor) { super.visitChildren(visitor); @@ -12174,8 +12174,8 @@ * * @param variableList the variables being declared */ - void set variables(VariableDeclarationList variableList2) { - this._variableList = becomeParentOf(variableList2); + void set variables(VariableDeclarationList variableList) { + this._variableList = becomeParentOf(variableList); } void visitChildren(ASTVisitor visitor) { safelyVisitChild(_variableList, visitor); @@ -12336,8 +12336,8 @@ * * @param withKeyword the token representing the 'with' keyword */ - void set mixinKeyword(Token withKeyword2) { - this.withKeyword = withKeyword2; + void set mixinKeyword(Token withKeyword) { + this.withKeyword = withKeyword; } void visitChildren(ASTVisitor visitor) { mixinTypes.accept(visitor);
diff --git a/pkg/analyzer_experimental/lib/src/generated/constant.dart b/pkg/analyzer_experimental/lib/src/generated/constant.dart index ac6bf34..2403231 100644 --- a/pkg/analyzer_experimental/lib/src/generated/constant.dart +++ b/pkg/analyzer_experimental/lib/src/generated/constant.dart
@@ -1103,16 +1103,16 @@ return value.toString(); } EvaluationResultImpl addToError(BinaryExpression node, ErrorResult leftOperand) => leftOperand; - EvaluationResultImpl addToValid(BinaryExpression node, ValidResult leftOperand2) { - if (!isAnyNum || !leftOperand2.isAnyNum) { + EvaluationResultImpl addToValid(BinaryExpression node, ValidResult leftOperand) { + if (!isAnyNum || !leftOperand.isAnyNum) { return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM); } - if (isSomeInt || leftOperand2.isSomeInt) { + if (isSomeInt || leftOperand.isSomeInt) { return RESULT_INT; - } else if (isSomeNum || leftOperand2.isSomeNum) { + } else if (isSomeNum || leftOperand.isSomeNum) { return RESULT_NUM; } - Object leftValue = leftOperand2.value; + Object leftValue = leftOperand.value; if (leftValue == null) { return error(node.leftOperand); } else if (value == null) { @@ -1137,14 +1137,14 @@ return error(node); } EvaluationResultImpl bitAndError(BinaryExpression node, ErrorResult leftOperand) => leftOperand; - EvaluationResultImpl bitAndValid(BinaryExpression node, ValidResult leftOperand2) { - if (!isAnyInt || !leftOperand2.isAnyInt) { + EvaluationResultImpl bitAndValid(BinaryExpression node, ValidResult leftOperand) { + if (!isAnyInt || !leftOperand.isAnyInt) { return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_INT); } - if (isSomeInt || leftOperand2.isSomeInt) { + if (isSomeInt || leftOperand.isSomeInt) { return RESULT_INT; } - Object leftValue = leftOperand2.value; + Object leftValue = leftOperand.value; if (leftValue == null) { return error(node.leftOperand); } else if (value == null) { @@ -1161,14 +1161,14 @@ return union(error(node.leftOperand), error(node.rightOperand)); } EvaluationResultImpl bitOrError(BinaryExpression node, ErrorResult leftOperand) => leftOperand; - EvaluationResultImpl bitOrValid(BinaryExpression node, ValidResult leftOperand2) { - if (!isAnyInt || !leftOperand2.isAnyInt) { + EvaluationResultImpl bitOrValid(BinaryExpression node, ValidResult leftOperand) { + if (!isAnyInt || !leftOperand.isAnyInt) { return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_INT); } - if (isSomeInt || leftOperand2.isSomeInt) { + if (isSomeInt || leftOperand.isSomeInt) { return RESULT_INT; } - Object leftValue = leftOperand2.value; + Object leftValue = leftOperand.value; if (leftValue == null) { return error(node.leftOperand); } else if (value == null) { @@ -1185,14 +1185,14 @@ return union(error(node.leftOperand), error(node.rightOperand)); } EvaluationResultImpl bitXorError(BinaryExpression node, ErrorResult leftOperand) => leftOperand; - EvaluationResultImpl bitXorValid(BinaryExpression node, ValidResult leftOperand2) { - if (!isAnyInt || !leftOperand2.isAnyInt) { + EvaluationResultImpl bitXorValid(BinaryExpression node, ValidResult leftOperand) { + if (!isAnyInt || !leftOperand.isAnyInt) { return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_INT); } - if (isSomeInt || leftOperand2.isSomeInt) { + if (isSomeInt || leftOperand.isSomeInt) { return RESULT_INT; } - Object leftValue = leftOperand2.value; + Object leftValue = leftOperand.value; if (leftValue == null) { return error(node.leftOperand); } else if (value == null) { @@ -1217,14 +1217,14 @@ return error(node); } EvaluationResultImpl divideError(BinaryExpression node, ErrorResult leftOperand) => leftOperand; - EvaluationResultImpl divideValid(BinaryExpression node, ValidResult leftOperand2) { - if (!isAnyNum || !leftOperand2.isAnyNum) { + EvaluationResultImpl divideValid(BinaryExpression node, ValidResult leftOperand) { + if (!isAnyNum || !leftOperand.isAnyNum) { return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM); } - if (isSomeNum || leftOperand2.isSomeNum) { + if (isSomeNum || leftOperand.isSomeNum) { return RESULT_NUM; } - Object leftValue = leftOperand2.value; + Object leftValue = leftOperand.value; if (leftValue == null) { return error(node.leftOperand); } else if (value == null) { @@ -1286,14 +1286,14 @@ } EvaluationResultImpl greaterThanError(BinaryExpression node, ErrorResult leftOperand) => leftOperand; EvaluationResultImpl greaterThanOrEqualError(BinaryExpression node, ErrorResult leftOperand) => leftOperand; - EvaluationResultImpl greaterThanOrEqualValid(BinaryExpression node, ValidResult leftOperand2) { - if (!isAnyNum || !leftOperand2.isAnyNum) { + EvaluationResultImpl greaterThanOrEqualValid(BinaryExpression node, ValidResult leftOperand) { + if (!isAnyNum || !leftOperand.isAnyNum) { return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM); } - if (isSomeNum || leftOperand2.isSomeNum) { + if (isSomeNum || leftOperand.isSomeNum) { return RESULT_BOOL; } - Object leftValue = leftOperand2.value; + Object leftValue = leftOperand.value; if (leftValue == null) { return error(node.leftOperand); } else if (value == null) { @@ -1313,14 +1313,14 @@ } return error(node); } - EvaluationResultImpl greaterThanValid(BinaryExpression node, ValidResult leftOperand2) { - if (!isAnyNum || !leftOperand2.isAnyNum) { + EvaluationResultImpl greaterThanValid(BinaryExpression node, ValidResult leftOperand) { + if (!isAnyNum || !leftOperand.isAnyNum) { return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM); } - if (isSomeNum || leftOperand2.isSomeNum) { + if (isSomeNum || leftOperand.isSomeNum) { return RESULT_BOOL; } - Object leftValue = leftOperand2.value; + Object leftValue = leftOperand.value; if (leftValue == null) { return error(node.leftOperand); } else if (value == null) { @@ -1341,14 +1341,14 @@ return error(node); } EvaluationResultImpl integerDivideError(BinaryExpression node, ErrorResult leftOperand) => leftOperand; - EvaluationResultImpl integerDivideValid(BinaryExpression node, ValidResult leftOperand2) { - if (!isAnyNum || !leftOperand2.isAnyNum) { + EvaluationResultImpl integerDivideValid(BinaryExpression node, ValidResult leftOperand) { + if (!isAnyNum || !leftOperand.isAnyNum) { return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM); } - if (isSomeNum || leftOperand2.isSomeNum) { + if (isSomeNum || leftOperand.isSomeNum) { return RESULT_INT; } - Object leftValue = leftOperand2.value; + Object leftValue = leftOperand.value; if (leftValue == null) { return error(node.leftOperand); } else if (value == null) { @@ -1376,14 +1376,14 @@ } EvaluationResultImpl lessThanError(BinaryExpression node, ErrorResult leftOperand) => leftOperand; EvaluationResultImpl lessThanOrEqualError(BinaryExpression node, ErrorResult leftOperand) => leftOperand; - EvaluationResultImpl lessThanOrEqualValid(BinaryExpression node, ValidResult leftOperand2) { - if (!isAnyNum || !leftOperand2.isAnyNum) { + EvaluationResultImpl lessThanOrEqualValid(BinaryExpression node, ValidResult leftOperand) { + if (!isAnyNum || !leftOperand.isAnyNum) { return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM); } - if (isSomeNum || leftOperand2.isSomeNum) { + if (isSomeNum || leftOperand.isSomeNum) { return RESULT_BOOL; } - Object leftValue = leftOperand2.value; + Object leftValue = leftOperand.value; if (leftValue == null) { return error(node.leftOperand); } else if (value == null) { @@ -1403,14 +1403,14 @@ } return error(node); } - EvaluationResultImpl lessThanValid(BinaryExpression node, ValidResult leftOperand2) { - if (!isAnyNum || !leftOperand2.isAnyNum) { + EvaluationResultImpl lessThanValid(BinaryExpression node, ValidResult leftOperand) { + if (!isAnyNum || !leftOperand.isAnyNum) { return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM); } - if (isSomeNum || leftOperand2.isSomeNum) { + if (isSomeNum || leftOperand.isSomeNum) { return RESULT_BOOL; } - Object leftValue = leftOperand2.value; + Object leftValue = leftOperand.value; if (leftValue == null) { return error(node.leftOperand); } else if (value == null) { @@ -1462,16 +1462,16 @@ return booleanConversion(node.rightOperand, value); } EvaluationResultImpl minusError(BinaryExpression node, ErrorResult leftOperand) => leftOperand; - EvaluationResultImpl minusValid(BinaryExpression node, ValidResult leftOperand2) { - if (!isAnyNum || !leftOperand2.isAnyNum) { + EvaluationResultImpl minusValid(BinaryExpression node, ValidResult leftOperand) { + if (!isAnyNum || !leftOperand.isAnyNum) { return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM); } - if (isSomeInt || leftOperand2.isSomeInt) { + if (isSomeInt || leftOperand.isSomeInt) { return RESULT_INT; - } else if (isSomeNum || leftOperand2.isSomeNum) { + } else if (isSomeNum || leftOperand.isSomeNum) { return RESULT_NUM; } - Object leftValue = leftOperand2.value; + Object leftValue = leftOperand.value; if (leftValue == null) { return error(node.leftOperand); } else if (value == null) { @@ -1527,16 +1527,16 @@ return RESULT_TRUE; } EvaluationResultImpl remainderError(BinaryExpression node, ErrorResult leftOperand) => leftOperand; - EvaluationResultImpl remainderValid(BinaryExpression node, ValidResult leftOperand2) { - if (!isAnyNum || !leftOperand2.isAnyNum) { + EvaluationResultImpl remainderValid(BinaryExpression node, ValidResult leftOperand) { + if (!isAnyNum || !leftOperand.isAnyNum) { return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM); } - if (isSomeInt || leftOperand2.isSomeInt) { + if (isSomeInt || leftOperand.isSomeInt) { return RESULT_INT; - } else if (isSomeNum || leftOperand2.isSomeNum) { + } else if (isSomeNum || leftOperand.isSomeNum) { return RESULT_NUM; } - Object leftValue = leftOperand2.value; + Object leftValue = leftOperand.value; if (leftValue == null) { return error(node.leftOperand); } else if (value == null) { @@ -1560,14 +1560,14 @@ return error(node); } EvaluationResultImpl shiftLeftError(BinaryExpression node, ErrorResult leftOperand) => leftOperand; - EvaluationResultImpl shiftLeftValid(BinaryExpression node, ValidResult leftOperand2) { - if (!isAnyInt || !leftOperand2.isAnyInt) { + EvaluationResultImpl shiftLeftValid(BinaryExpression node, ValidResult leftOperand) { + if (!isAnyInt || !leftOperand.isAnyInt) { return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_INT); } - if (isSomeInt || leftOperand2.isSomeInt) { + if (isSomeInt || leftOperand.isSomeInt) { return RESULT_INT; } - Object leftValue = leftOperand2.value; + Object leftValue = leftOperand.value; if (leftValue == null) { return error(node.leftOperand); } else if (value == null) { @@ -1584,14 +1584,14 @@ return union(error(node.leftOperand), error(node.rightOperand)); } EvaluationResultImpl shiftRightError(BinaryExpression node, ErrorResult leftOperand) => leftOperand; - EvaluationResultImpl shiftRightValid(BinaryExpression node, ValidResult leftOperand2) { - if (!isAnyInt || !leftOperand2.isAnyInt) { + EvaluationResultImpl shiftRightValid(BinaryExpression node, ValidResult leftOperand) { + if (!isAnyInt || !leftOperand.isAnyInt) { return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_INT); } - if (isSomeInt || leftOperand2.isSomeInt) { + if (isSomeInt || leftOperand.isSomeInt) { return RESULT_INT; } - Object leftValue = leftOperand2.value; + Object leftValue = leftOperand.value; if (leftValue == null) { return error(node.leftOperand); } else if (value == null) { @@ -1608,16 +1608,16 @@ return union(error(node.leftOperand), error(node.rightOperand)); } EvaluationResultImpl timesError(BinaryExpression node, ErrorResult leftOperand) => leftOperand; - EvaluationResultImpl timesValid(BinaryExpression node, ValidResult leftOperand2) { - if (!isAnyNum || !leftOperand2.isAnyNum) { + EvaluationResultImpl timesValid(BinaryExpression node, ValidResult leftOperand) { + if (!isAnyNum || !leftOperand.isAnyNum) { return error2(node, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM); } - if (isSomeInt || leftOperand2.isSomeInt) { + if (isSomeInt || leftOperand.isSomeInt) { return RESULT_INT; - } else if (isSomeNum || leftOperand2.isSomeNum) { + } else if (isSomeNum || leftOperand.isSomeNum) { return RESULT_NUM; } - Object leftValue = leftOperand2.value; + Object leftValue = leftOperand.value; if (leftValue == null) { return error(node.leftOperand); } else if (value == null) {
diff --git a/pkg/analyzer_experimental/lib/src/generated/element.dart b/pkg/analyzer_experimental/lib/src/generated/element.dart index fa3c4be..776fbf2 100644 --- a/pkg/analyzer_experimental/lib/src/generated/element.dart +++ b/pkg/analyzer_experimental/lib/src/generated/element.dart
@@ -1812,29 +1812,29 @@ collectAllSupertypes(list); return new List.from(list); } - ElementImpl getChild(String identifier2) { + ElementImpl getChild(String identifier) { for (PropertyAccessorElement accessor in _accessors) { - if (((accessor as PropertyAccessorElementImpl)).identifier == identifier2) { + if (((accessor as PropertyAccessorElementImpl)).identifier == identifier) { return accessor as PropertyAccessorElementImpl; } } for (ConstructorElement constructor in _constructors) { - if (((constructor as ConstructorElementImpl)).identifier == identifier2) { + if (((constructor as ConstructorElementImpl)).identifier == identifier) { return constructor as ConstructorElementImpl; } } for (FieldElement field in _fields) { - if (((field as FieldElementImpl)).identifier == identifier2) { + if (((field as FieldElementImpl)).identifier == identifier) { return field as FieldElementImpl; } } for (MethodElement method in _methods) { - if (((method as MethodElementImpl)).identifier == identifier2) { + if (((method as MethodElementImpl)).identifier == identifier) { return method as MethodElementImpl; } } for (TypeParameterElement typeParameter in _typeParameters) { - if (((typeParameter as TypeParameterElementImpl)).identifier == identifier2) { + if (((typeParameter as TypeParameterElementImpl)).identifier == identifier) { return typeParameter as TypeParameterElementImpl; } } @@ -1849,9 +1849,9 @@ * @param name some name to lookup a field element with * @return the matching field element, or `null` if no such element was found */ - FieldElement getField(String name2) { + FieldElement getField(String name) { for (FieldElement fieldElement in _fields) { - if (name2 == fieldElement.name) { + if (name == fieldElement.name) { return fieldElement; } } @@ -1878,10 +1878,10 @@ } List<MethodElement> get methods => _methods; List<InterfaceType> get mixins => _mixins; - ConstructorElement getNamedConstructor(String name2) { + ConstructorElement getNamedConstructor(String name) { for (ConstructorElement element in constructors) { String elementName = element.name; - if (elementName != null && elementName == name2) { + if (elementName != null && elementName == name) { return element; } } @@ -2034,11 +2034,11 @@ * * @param accessors the accessors contained in this class */ - void set accessors(List<PropertyAccessorElement> accessors2) { - for (PropertyAccessorElement accessor in accessors2) { + void set accessors(List<PropertyAccessorElement> accessors) { + for (PropertyAccessorElement accessor in accessors) { ((accessor as PropertyAccessorElementImpl)).enclosingElement = this; } - this._accessors = accessors2; + this._accessors = accessors; } /** @@ -2046,11 +2046,11 @@ * * @param constructors the constructors contained in this class */ - void set constructors(List<ConstructorElement> constructors2) { - for (ConstructorElement constructor in constructors2) { + void set constructors(List<ConstructorElement> constructors) { + for (ConstructorElement constructor in constructors) { ((constructor as ConstructorElementImpl)).enclosingElement = this; } - this._constructors = constructors2; + this._constructors = constructors; } /** @@ -2058,11 +2058,11 @@ * * @param fields the fields contained in this class */ - void set fields(List<FieldElement> fields2) { - for (FieldElement field in fields2) { + void set fields(List<FieldElement> fields) { + for (FieldElement field in fields) { ((field as FieldElementImpl)).enclosingElement = this; } - this._fields = fields2; + this._fields = fields; } /** @@ -2079,8 +2079,8 @@ * * @param the interfaces that are implemented by this class */ - void set interfaces(List<InterfaceType> interfaces2) { - this._interfaces = interfaces2; + void set interfaces(List<InterfaceType> interfaces) { + this._interfaces = interfaces; } /** @@ -2088,11 +2088,11 @@ * * @param methods the methods contained in this class */ - void set methods(List<MethodElement> methods2) { - for (MethodElement method in methods2) { + void set methods(List<MethodElement> methods) { + for (MethodElement method in methods) { ((method as MethodElementImpl)).enclosingElement = this; } - this._methods = methods2; + this._methods = methods; } /** @@ -2101,8 +2101,8 @@ * * @param mixins the mixins that are applied to derive the superclass of this class */ - void set mixins(List<InterfaceType> mixins2) { - this._mixins = mixins2; + void set mixins(List<InterfaceType> mixins) { + this._mixins = mixins; } /** @@ -2110,8 +2110,8 @@ * * @param supertype the superclass of the class */ - void set supertype(InterfaceType supertype2) { - this._supertype = supertype2; + void set supertype(InterfaceType supertype) { + this._supertype = supertype; } /** @@ -2119,8 +2119,8 @@ * * @param type the type defined by the class */ - void set type(InterfaceType type2) { - this._type = type2; + void set type(InterfaceType type) { + this._type = type; } /** @@ -2137,11 +2137,11 @@ * * @param typeParameters the type parameters defined for this class */ - void set typeParameters(List<TypeParameterElement> typeParameters2) { - for (TypeParameterElement typeParameter in typeParameters2) { + void set typeParameters(List<TypeParameterElement> typeParameters) { + for (TypeParameterElement typeParameter in typeParameters) { ((typeParameter as TypeParameterElementImpl)).enclosingElement = this; } - this._typeParameters = typeParameters2; + this._typeParameters = typeParameters; } /** @@ -2267,29 +2267,29 @@ accept(ElementVisitor visitor) => visitor.visitCompilationUnitElement(this); bool operator ==(Object object) => object != null && runtimeType == object.runtimeType && _source == ((object as CompilationUnitElementImpl)).source; List<PropertyAccessorElement> get accessors => _accessors; - ElementImpl getChild(String identifier2) { + ElementImpl getChild(String identifier) { for (PropertyAccessorElement accessor in _accessors) { - if (((accessor as PropertyAccessorElementImpl)).identifier == identifier2) { + if (((accessor as PropertyAccessorElementImpl)).identifier == identifier) { return accessor as PropertyAccessorElementImpl; } } for (VariableElement variable in _variables) { - if (((variable as VariableElementImpl)).identifier == identifier2) { + if (((variable as VariableElementImpl)).identifier == identifier) { return variable as VariableElementImpl; } } for (ExecutableElement function in _functions) { - if (((function as ExecutableElementImpl)).identifier == identifier2) { + if (((function as ExecutableElementImpl)).identifier == identifier) { return function as ExecutableElementImpl; } } for (FunctionTypeAliasElement typeAlias in _typeAliases) { - if (((typeAlias as FunctionTypeAliasElementImpl)).identifier == identifier2) { + if (((typeAlias as FunctionTypeAliasElementImpl)).identifier == identifier) { return typeAlias as FunctionTypeAliasElementImpl; } } for (ClassElement type in _types) { - if (((type as ClassElementImpl)).identifier == identifier2) { + if (((type as ClassElementImpl)).identifier == identifier) { return type as ClassElementImpl; } } @@ -2320,11 +2320,11 @@ * * @param the top-level accessors (getters and setters) contained in this compilation unit */ - void set accessors(List<PropertyAccessorElement> accessors2) { - for (PropertyAccessorElement accessor in accessors2) { + void set accessors(List<PropertyAccessorElement> accessors) { + for (PropertyAccessorElement accessor in accessors) { ((accessor as PropertyAccessorElementImpl)).enclosingElement = this; } - this._accessors = accessors2; + this._accessors = accessors; } /** @@ -2332,11 +2332,11 @@ * * @param functions the top-level functions contained in this compilation unit */ - void set functions(List<FunctionElement> functions2) { - for (FunctionElement function in functions2) { + void set functions(List<FunctionElement> functions) { + for (FunctionElement function in functions) { ((function as FunctionElementImpl)).enclosingElement = this; } - this._functions = functions2; + this._functions = functions; } /** @@ -2344,8 +2344,8 @@ * * @param source the source that corresponds to this compilation unit */ - void set source(Source source2) { - this._source = source2; + void set source(Source source) { + this._source = source; } /** @@ -2353,11 +2353,11 @@ * * @param variables the top-level variables contained in this compilation unit */ - void set topLevelVariables(List<TopLevelVariableElement> variables2) { - for (TopLevelVariableElement field in variables2) { + void set topLevelVariables(List<TopLevelVariableElement> variables) { + for (TopLevelVariableElement field in variables) { ((field as TopLevelVariableElementImpl)).enclosingElement = this; } - this._variables = variables2; + this._variables = variables; } /** @@ -2365,11 +2365,11 @@ * * @param typeAliases the function type aliases contained in this compilation unit */ - void set typeAliases(List<FunctionTypeAliasElement> typeAliases2) { - for (FunctionTypeAliasElement typeAlias in typeAliases2) { + void set typeAliases(List<FunctionTypeAliasElement> typeAliases) { + for (FunctionTypeAliasElement typeAlias in typeAliases) { ((typeAlias as FunctionTypeAliasElementImpl)).enclosingElement = this; } - this._typeAliases = typeAliases2; + this._typeAliases = typeAliases; } /** @@ -2377,11 +2377,11 @@ * * @param types types contained in this compilation unit */ - void set types(List<ClassElement> types2) { - for (ClassElement type in types2) { + void set types(List<ClassElement> types) { + for (ClassElement type in types) { ((type as ClassElementImpl)).enclosingElement = this; } - this._types = types2; + this._types = types; } /** @@ -2389,8 +2389,8 @@ * * @param uri the URI that is specified by the "part" directive in the enclosing library. */ - void set uri(String uri2) { - this._uri = uri2; + void set uri(String uri) { + this._uri = uri; } void visitChildren(ElementVisitor visitor) { super.visitChildren(visitor); @@ -2426,8 +2426,8 @@ */ ConstFieldElementImpl(Identifier name) : super.con1(name); EvaluationResultImpl get evaluationResult => _result; - void set evaluationResult(EvaluationResultImpl result2) { - this._result = result2; + void set evaluationResult(EvaluationResultImpl result) { + this._result = result; } } /** @@ -2450,8 +2450,8 @@ */ ConstLocalVariableElementImpl(Identifier name) : super(name); EvaluationResultImpl get evaluationResult => _result; - void set evaluationResult(EvaluationResultImpl result2) { - this._result = result2; + void set evaluationResult(EvaluationResultImpl result) { + this._result = result; } } /** @@ -2472,8 +2472,8 @@ */ ConstTopLevelVariableElementImpl(Identifier name) : super.con1(name); EvaluationResultImpl get evaluationResult => _result; - void set evaluationResult(EvaluationResultImpl result2) { - this._result = result2; + void set evaluationResult(EvaluationResultImpl result) { + this._result = result; } } /** @@ -2542,8 +2542,8 @@ * * @param redirectedConstructor the constructor to which this constructor is redirecting */ - void set redirectedConstructor(ConstructorElement redirectedConstructor2) { - this._redirectedConstructor = redirectedConstructor2; + void set redirectedConstructor(ConstructorElement redirectedConstructor) { + this._redirectedConstructor = redirectedConstructor; } void appendTo(JavaStringBuilder builder) { builder.append(enclosingElement.displayName); @@ -2575,8 +2575,8 @@ */ DefaultFieldFormalParameterElementImpl(Identifier name) : super(name); EvaluationResultImpl get evaluationResult => _result; - void set evaluationResult(EvaluationResultImpl result2) { - this._result = result2; + void set evaluationResult(EvaluationResultImpl result) { + this._result = result; } } /** @@ -2599,8 +2599,8 @@ */ DefaultParameterElementImpl(Identifier name) : super.con1(name); EvaluationResultImpl get evaluationResult => _result; - void set evaluationResult(EvaluationResultImpl result2) { - this._result = result2; + void set evaluationResult(EvaluationResultImpl result) { + this._result = result; } } /** @@ -2770,9 +2770,9 @@ } return _cachedHashCode; } - bool isAccessibleIn(LibraryElement library2) { + bool isAccessibleIn(LibraryElement library) { if (Identifier.isPrivateName(_name)) { - return library2 == library; + return library == this.library; } return true; } @@ -2783,8 +2783,8 @@ * * @param metadata the metadata to be associated with this element */ - void set metadata(List<ElementAnnotation> metadata2) { - this._metadata = metadata2; + void set metadata(List<ElementAnnotation> metadata) { + this._metadata = metadata; } /** @@ -2794,8 +2794,8 @@ * * @param nameOffset the offset to the beginning of the name */ - void set nameOffset(int nameOffset2) { - this._nameOffset = nameOffset2; + void set nameOffset(int nameOffset) { + this._nameOffset = nameOffset; } /** @@ -3092,9 +3092,9 @@ * * @param scriptLibrary the library or `null` if none */ - void set scriptLibrary(LibraryElementImpl scriptLibrary2) { - scriptLibrary2.enclosingElement = this; - this._scriptLibrary = scriptLibrary2; + void set scriptLibrary(LibraryElementImpl scriptLibrary) { + scriptLibrary.enclosingElement = this; + this._scriptLibrary = scriptLibrary; } void visitChildren(ElementVisitor visitor) { safelyVisitChild(_scriptLibrary, visitor); @@ -3158,24 +3158,24 @@ * declaration of this element */ ExecutableElementImpl.con2(String name, int nameOffset) : super.con2(name, nameOffset); - ElementImpl getChild(String identifier2) { + ElementImpl getChild(String identifier) { for (ExecutableElement function in _functions) { - if (((function as ExecutableElementImpl)).identifier == identifier2) { + if (((function as ExecutableElementImpl)).identifier == identifier) { return function as ExecutableElementImpl; } } for (LabelElement label in _labels) { - if (((label as LabelElementImpl)).identifier == identifier2) { + if (((label as LabelElementImpl)).identifier == identifier) { return label as LabelElementImpl; } } for (VariableElement variable in _localVariables) { - if (((variable as VariableElementImpl)).identifier == identifier2) { + if (((variable as VariableElementImpl)).identifier == identifier) { return variable as VariableElementImpl; } } for (ParameterElement parameter in _parameters) { - if (((parameter as ParameterElementImpl)).identifier == identifier2) { + if (((parameter as ParameterElementImpl)).identifier == identifier) { return parameter as ParameterElementImpl; } } @@ -3194,11 +3194,11 @@ * * @param functions the functions defined within this executable element */ - void set functions(List<FunctionElement> functions2) { - for (FunctionElement function in functions2) { + void set functions(List<FunctionElement> functions) { + for (FunctionElement function in functions) { ((function as FunctionElementImpl)).enclosingElement = this; } - this._functions = functions2; + this._functions = functions; } /** @@ -3206,11 +3206,11 @@ * * @param labels the labels defined within this executable element */ - void set labels(List<LabelElement> labels2) { - for (LabelElement label in labels2) { + void set labels(List<LabelElement> labels) { + for (LabelElement label in labels) { ((label as LabelElementImpl)).enclosingElement = this; } - this._labels = labels2; + this._labels = labels; } /** @@ -3218,11 +3218,11 @@ * * @param localVariables the local variables defined within this executable element */ - void set localVariables(List<LocalVariableElement> localVariables2) { - for (LocalVariableElement variable in localVariables2) { + void set localVariables(List<LocalVariableElement> localVariables) { + for (LocalVariableElement variable in localVariables) { ((variable as LocalVariableElementImpl)).enclosingElement = this; } - this._localVariables = localVariables2; + this._localVariables = localVariables; } /** @@ -3230,11 +3230,11 @@ * * @param parameters the parameters defined by this executable element */ - void set parameters(List<ParameterElement> parameters2) { - for (ParameterElement parameter in parameters2) { + void set parameters(List<ParameterElement> parameters) { + for (ParameterElement parameter in parameters) { ((parameter as ParameterElementImpl)).enclosingElement = this; } - this._parameters = parameters2; + this._parameters = parameters; } /** @@ -3242,8 +3242,8 @@ * * @param returnType the return type defined by this executable element */ - void set returnType(Type2 returnType2) { - this._returnType = returnType2; + void set returnType(Type2 returnType) { + this._returnType = returnType; } /** @@ -3251,8 +3251,8 @@ * * @param type the type of function defined by this executable element */ - void set type(FunctionType type2) { - this._type = type2; + void set type(FunctionType type) { + this._type = type; } void visitChildren(ElementVisitor visitor) { super.visitChildren(visitor); @@ -3316,8 +3316,8 @@ * * @param combinators the combinators that were specified as part of the export directive */ - void set combinators(List<NamespaceCombinator> combinators2) { - this._combinators = combinators2; + void set combinators(List<NamespaceCombinator> combinators) { + this._combinators = combinators; } /** @@ -3326,8 +3326,8 @@ * * @param exportedLibrary the library that is exported from this library */ - void set exportedLibrary(LibraryElement exportedLibrary2) { - this._exportedLibrary = exportedLibrary2; + void set exportedLibrary(LibraryElement exportedLibrary) { + this._exportedLibrary = exportedLibrary; } /** @@ -3335,8 +3335,8 @@ * * @param uri the URI that is specified by this directive. */ - void set uri(String uri2) { - this._uri = uri2; + void set uri(String uri) { + this._uri = uri; } void appendTo(JavaStringBuilder builder) { builder.append("export "); @@ -3372,8 +3372,8 @@ * * @param scriptSource the script source or `null` if unspecified */ - void set scriptSource(Source scriptSource2) { - this._scriptSource = scriptSource2; + void set scriptSource(Source scriptSource) { + this._scriptSource = scriptSource; } } /** @@ -3444,8 +3444,8 @@ * * @param field the new field element */ - void set field(FieldElement field2) { - this._field = field2; + void set field(FieldElement field) { + this._field = field; } } /** @@ -3564,14 +3564,14 @@ */ FunctionTypeAliasElementImpl(Identifier name) : super.con1(name); accept(ElementVisitor visitor) => visitor.visitFunctionTypeAliasElement(this); - ElementImpl getChild(String identifier2) { + ElementImpl getChild(String identifier) { for (VariableElement parameter in _parameters) { - if (((parameter as VariableElementImpl)).identifier == identifier2) { + if (((parameter as VariableElementImpl)).identifier == identifier) { return parameter as VariableElementImpl; } } for (TypeParameterElement typeParameter in _typeParameters) { - if (((typeParameter as TypeParameterElementImpl)).identifier == identifier2) { + if (((typeParameter as TypeParameterElementImpl)).identifier == identifier) { return typeParameter as TypeParameterElementImpl; } } @@ -3589,13 +3589,13 @@ * * @param parameters the parameters defined by this type alias */ - void set parameters(List<ParameterElement> parameters2) { - if (parameters2 != null) { - for (ParameterElement parameter in parameters2) { + void set parameters(List<ParameterElement> parameters) { + if (parameters != null) { + for (ParameterElement parameter in parameters) { ((parameter as ParameterElementImpl)).enclosingElement = this; } } - this._parameters = parameters2; + this._parameters = parameters; } /** @@ -3603,8 +3603,8 @@ * * @param returnType the return type defined by this type alias */ - void set returnType(Type2 returnType2) { - this._returnType = returnType2; + void set returnType(Type2 returnType) { + this._returnType = returnType; } /** @@ -3612,8 +3612,8 @@ * * @param type the type of function defined by this type alias */ - void set type(FunctionType type2) { - this._type = type2; + void set type(FunctionType type) { + this._type = type; } /** @@ -3621,11 +3621,11 @@ * * @param typeParameters the type parameters defined for this type */ - void set typeParameters(List<TypeParameterElement> typeParameters2) { - for (TypeParameterElement typeParameter in typeParameters2) { + void set typeParameters(List<TypeParameterElement> typeParameters) { + for (TypeParameterElement typeParameter in typeParameters) { ((typeParameter as TypeParameterElementImpl)).enclosingElement = this; } - this._typeParameters = typeParameters2; + this._typeParameters = typeParameters; } /** @@ -3635,8 +3635,8 @@ * * @param parameters the parameters defined by this type alias */ - void shareParameters(List<ParameterElement> parameters2) { - this._parameters = parameters2; + void shareParameters(List<ParameterElement> parameters) { + this._parameters = parameters; } /** @@ -3646,8 +3646,8 @@ * * @param typeParameters the type parameters defined for this type */ - void shareTypeParameters(List<TypeParameterElement> typeParameters2) { - this._typeParameters = typeParameters2; + void shareTypeParameters(List<TypeParameterElement> typeParameters) { + this._typeParameters = typeParameters; } void visitChildren(ElementVisitor visitor) { super.visitChildren(visitor); @@ -3704,8 +3704,8 @@ * * @param hiddenNames the names that are not to be made visible in the importing library */ - void set hiddenNames(List<String> hiddenNames2) { - this._hiddenNames = hiddenNames2; + void set hiddenNames(List<String> hiddenNames) { + this._hiddenNames = hiddenNames; } String toString() { JavaStringBuilder builder = new JavaStringBuilder(); @@ -3769,14 +3769,14 @@ * * @param scripts the scripts */ - void set scripts(List<HtmlScriptElement> scripts2) { - if (scripts2.length == 0) { - scripts2 = HtmlScriptElementImpl.EMPTY_ARRAY; + void set scripts(List<HtmlScriptElement> scripts) { + if (scripts.length == 0) { + scripts = HtmlScriptElementImpl.EMPTY_ARRAY; } - for (HtmlScriptElement script in scripts2) { + for (HtmlScriptElement script in scripts) { ((script as HtmlScriptElementImpl)).enclosingElement = this; } - this._scripts = scripts2; + this._scripts = scripts; } /** @@ -3784,8 +3784,8 @@ * * @param source the source that corresponds to this HTML file */ - void set source(Source source2) { - this._source = source2; + void set source(Source source) { + this._source = source; } void visitChildren(ElementVisitor visitor) { super.visitChildren(visitor); @@ -3864,8 +3864,8 @@ * * @param combinators the combinators that were specified as part of the import directive */ - void set combinators(List<NamespaceCombinator> combinators2) { - this._combinators = combinators2; + void set combinators(List<NamespaceCombinator> combinators) { + this._combinators = combinators; } /** @@ -3874,8 +3874,8 @@ * * @param importedLibrary the library that is imported into this library */ - void set importedLibrary(LibraryElement importedLibrary2) { - this._importedLibrary = importedLibrary2; + void set importedLibrary(LibraryElement importedLibrary) { + this._importedLibrary = importedLibrary; } /** @@ -3883,8 +3883,8 @@ * * @param prefix the prefix that was specified as part of the import directive */ - void set prefix(PrefixElement prefix2) { - this._prefix = prefix2; + void set prefix(PrefixElement prefix) { + this._prefix = prefix; } /** @@ -3892,8 +3892,8 @@ * * @param uri the URI that is specified by this directive. */ - void set uri(String uri2) { - this._uri = uri2; + void set uri(String uri) { + this._uri = uri; } void visitChildren(ElementVisitor visitor) { super.visitChildren(visitor); @@ -4030,22 +4030,22 @@ } accept(ElementVisitor visitor) => visitor.visitLibraryElement(this); bool operator ==(Object object) => object != null && runtimeType == object.runtimeType && _definingCompilationUnit == ((object as LibraryElementImpl)).definingCompilationUnit; - ElementImpl getChild(String identifier2) { - if (((_definingCompilationUnit as CompilationUnitElementImpl)).identifier == identifier2) { + ElementImpl getChild(String identifier) { + if (((_definingCompilationUnit as CompilationUnitElementImpl)).identifier == identifier) { return _definingCompilationUnit as CompilationUnitElementImpl; } for (CompilationUnitElement part in _parts) { - if (((part as CompilationUnitElementImpl)).identifier == identifier2) { + if (((part as CompilationUnitElementImpl)).identifier == identifier) { return part as CompilationUnitElementImpl; } } for (ImportElement importElement in _imports) { - if (((importElement as ImportElementImpl)).identifier == identifier2) { + if (((importElement as ImportElementImpl)).identifier == identifier) { return importElement as ImportElementImpl; } } for (ExportElement exportElement in _exports) { - if (((exportElement as ExportElementImpl)).identifier == identifier2) { + if (((exportElement as ExportElementImpl)).identifier == identifier) { return exportElement as ExportElementImpl; } } @@ -4123,9 +4123,9 @@ * * @param definingCompilationUnit the compilation unit that defines this library */ - void set definingCompilationUnit(CompilationUnitElement definingCompilationUnit2) { - ((definingCompilationUnit2 as CompilationUnitElementImpl)).enclosingElement = this; - this._definingCompilationUnit = definingCompilationUnit2; + void set definingCompilationUnit(CompilationUnitElement definingCompilationUnit) { + ((definingCompilationUnit as CompilationUnitElementImpl)).enclosingElement = this; + this._definingCompilationUnit = definingCompilationUnit; } /** @@ -4133,8 +4133,8 @@ * * @param entryPoint the entry point for this library */ - void set entryPoint(FunctionElement entryPoint2) { - this._entryPoint = entryPoint2; + void set entryPoint(FunctionElement entryPoint) { + this._entryPoint = entryPoint; } /** @@ -4142,11 +4142,11 @@ * * @param exports the specifications of all of the exports defined in this library */ - void set exports(List<ExportElement> exports2) { - for (ExportElement exportElement in exports2) { + void set exports(List<ExportElement> exports) { + for (ExportElement exportElement in exports) { ((exportElement as ExportElementImpl)).enclosingElement = this; } - this._exports = exports2; + this._exports = exports; } /** @@ -4154,15 +4154,15 @@ * * @param imports the specifications of all of the imports defined in this library */ - void set imports(List<ImportElement> imports2) { - for (ImportElement importElement in imports2) { + void set imports(List<ImportElement> imports) { + for (ImportElement importElement in imports) { ((importElement as ImportElementImpl)).enclosingElement = this; PrefixElementImpl prefix = importElement.prefix as PrefixElementImpl; if (prefix != null) { prefix.enclosingElement = this; } } - this._imports = imports2; + this._imports = imports; } /** @@ -4171,11 +4171,11 @@ * @param parts the compilation units that are included in this library using a `part` * directive */ - void set parts(List<CompilationUnitElement> parts2) { - for (CompilationUnitElement compilationUnit in parts2) { + void set parts(List<CompilationUnitElement> parts) { + for (CompilationUnitElement compilationUnit in parts) { ((compilationUnit as CompilationUnitElementImpl)).enclosingElement = this; } - this._parts = parts2; + this._parts = parts; } void visitChildren(ElementVisitor visitor) { super.visitChildren(visitor); @@ -4593,8 +4593,8 @@ * * @param parameterKind the new kind of this parameter */ - void set parameterKind(ParameterKind parameterKind2) { - this._parameterKind = parameterKind2; + void set parameterKind(ParameterKind parameterKind) { + this._parameterKind = parameterKind; } /** @@ -4602,11 +4602,11 @@ * * @param parameters the parameters defined by this executable element */ - void set parameters(List<ParameterElement> parameters2) { - for (ParameterElement parameter in parameters2) { + void set parameters(List<ParameterElement> parameters) { + for (ParameterElement parameter in parameters) { ((parameter as ParameterElementImpl)).enclosingElement = this; } - this._parameters = parameters2; + this._parameters = parameters; } /** @@ -4678,16 +4678,17 @@ * * @param importedLibraries the libraries that are imported using this prefix */ - void set importedLibraries(List<LibraryElement> importedLibraries2) { - for (LibraryElement library in importedLibraries2) { + void set importedLibraries(List<LibraryElement> importedLibraries) { + for (LibraryElement library in importedLibraries) { ((library as LibraryElementImpl)).enclosingElement = this; } - this._importedLibraries = importedLibraries2; + this._importedLibraries = importedLibraries; } void appendTo(JavaStringBuilder builder) { builder.append("as "); super.appendTo(builder); } + String get identifier => "_${super.identifier}"; } /** * Instances of the class `PropertyAccessorElementImpl` implement a @@ -4797,8 +4798,8 @@ * * @param variable the variable associated with this accessor */ - void set variable(PropertyInducingElement variable2) { - this._variable = variable2; + void set variable(PropertyInducingElement variable) { + this._variable = variable; } void appendTo(JavaStringBuilder builder) { builder.append(isGetter ? "get " : "set "); @@ -4853,8 +4854,8 @@ * * @param getter the getter associated with this element */ - void set getter(PropertyAccessorElement getter2) { - this._getter = getter2; + void set getter(PropertyAccessorElement getter) { + this._getter = getter; } /** @@ -4862,8 +4863,8 @@ * * @param setter the setter associated with this element */ - void set setter(PropertyAccessorElement setter2) { - this._setter = setter2; + void set setter(PropertyAccessorElement setter) { + this._setter = setter; } } /** @@ -4887,8 +4888,8 @@ * * @param shownNames the names that are to be made visible in the importing library */ - void set shownNames(List<String> shownNames2) { - this._shownNames = shownNames2; + void set shownNames(List<String> shownNames) { + this._shownNames = shownNames; } String toString() { JavaStringBuilder builder = new JavaStringBuilder(); @@ -4972,8 +4973,8 @@ * * @param bound the type representing the bound associated with this parameter */ - void set bound(Type2 bound2) { - this._bound = bound2; + void set bound(Type2 bound) { + this._bound = bound; } /** @@ -4981,8 +4982,8 @@ * * @param type the type defined by this type parameter */ - void set type(TypeParameterType type2) { - this._type = type2; + void set type(TypeParameterType type) { + this._type = type; } void appendTo(JavaStringBuilder builder) { builder.append(displayName); @@ -5077,11 +5078,11 @@ * * @param initializer the function representing this variable's initializer */ - void set initializer(FunctionElement initializer2) { - if (initializer2 != null) { - ((initializer2 as FunctionElementImpl)).enclosingElement = this; + void set initializer(FunctionElement initializer) { + if (initializer != null) { + ((initializer as FunctionElementImpl)).enclosingElement = this; } - this._initializer = initializer2; + this._initializer = initializer; } /** @@ -5089,8 +5090,8 @@ * * @param type the declared type of this variable */ - void set type(Type2 type2) { - this._type = type2; + void set type(Type2 type) { + this._type = type; } void visitChildren(ElementVisitor visitor) { super.visitChildren(visitor); @@ -6013,8 +6014,8 @@ * * @param typeArguments the actual types of the type arguments */ - void set typeArguments(List<Type2> typeArguments2) { - this._typeArguments = typeArguments2; + void set typeArguments(List<Type2> typeArguments) { + this._typeArguments = typeArguments; } FunctionTypeImpl substitute3(List<Type2> argumentTypes) => substitute2(argumentTypes, typeArguments); FunctionTypeImpl substitute2(List<Type2> argumentTypes, List<Type2> parameterTypes) { @@ -6480,24 +6481,24 @@ return isMoreSpecificThan2(type as InterfaceType, new Set<ClassElement>()); } bool get isObject => element.supertype == null; - bool isSubtypeOf(Type2 type2) { - if (identical(type2, DynamicTypeImpl.instance)) { + bool isSubtypeOf(Type2 type) { + if (identical(type, DynamicTypeImpl.instance)) { return true; - } else if (type2 is TypeParameterType) { + } else if (type is TypeParameterType) { return true; - } else if (type2 is FunctionType) { + } else if (type is FunctionType) { ClassElement element = this.element; MethodElement callMethod = element.lookUpMethod("call", element.library); if (callMethod != null) { - return callMethod.type.isSubtypeOf(type2); + return callMethod.type.isSubtypeOf(type); } return false; - } else if (type2 is! InterfaceType) { + } else if (type is! InterfaceType) { return false; - } else if (this == type2) { + } else if (this == type) { return true; } - return isSubtypeOf2(type2 as InterfaceType, new Set<ClassElement>()); + return isSubtypeOf2(type as InterfaceType, new Set<ClassElement>()); } ConstructorElement lookUpConstructor(String constructorName, LibraryElement library) { ConstructorElement constructorElement; @@ -6619,8 +6620,8 @@ * * @param typeArguments the actual types of the type arguments */ - void set typeArguments(List<Type2> typeArguments2) { - this._typeArguments = typeArguments2; + void set typeArguments(List<Type2> typeArguments) { + this._typeArguments = typeArguments; } InterfaceTypeImpl substitute4(List<Type2> argumentTypes) => substitute2(argumentTypes, typeArguments); InterfaceTypeImpl substitute2(List<Type2> argumentTypes, List<Type2> parameterTypes) { @@ -6659,7 +6660,7 @@ if (s.isDirectSupertypeOf(this)) { return true; } - ClassElement tElement = element; + ClassElement tElement = this.element; ClassElement sElement = s.element; if (tElement == sElement) { List<Type2> tArguments = typeArguments; @@ -6695,9 +6696,9 @@ } return false; } - bool isSubtypeOf2(InterfaceType type2, Set<ClassElement> visitedClasses) { + bool isSubtypeOf2(InterfaceType type, Set<ClassElement> visitedClasses) { InterfaceType typeT = this; - InterfaceType typeS = type2; + InterfaceType typeS = type; ClassElement elementT = element; if (elementT == null || visitedClasses.contains(elementT)) { return false;
diff --git a/pkg/analyzer_experimental/lib/src/generated/engine.dart b/pkg/analyzer_experimental/lib/src/generated/engine.dart index 1d8b5f8..84f6f56 100644 --- a/pkg/analyzer_experimental/lib/src/generated/engine.dart +++ b/pkg/analyzer_experimental/lib/src/generated/engine.dart
@@ -101,8 +101,8 @@ * @param logger the logger that should receive information about errors within the analysis * engine */ - void set logger(Logger logger2) { - this._logger = logger2 == null ? Logger.NULL : logger2; + void set logger(Logger logger) { + this._logger = logger == null ? Logger.NULL : logger; } } /** @@ -1440,10 +1440,10 @@ return super.getState(descriptor); } } - CacheState getState2(DataDescriptor descriptor, Source librarySource2) { + CacheState getState2(DataDescriptor descriptor, Source librarySource) { DartEntryImpl_ResolutionState state = _resolutionState; while (state != null) { - if (librarySource2 == state._librarySource) { + if (librarySource == state._librarySource) { if (identical(descriptor, DartEntry.RESOLUTION_ERRORS)) { return state._resolutionErrorsState; } else if (identical(descriptor, DartEntry.RESOLVED_UNIT)) { @@ -1488,10 +1488,10 @@ } return super.getValue(descriptor); } - Object getValue2(DataDescriptor descriptor, Source librarySource2) { + Object getValue2(DataDescriptor descriptor, Source librarySource) { DartEntryImpl_ResolutionState state = _resolutionState; while (state != null) { - if (librarySource2 == state._librarySource) { + if (librarySource == state._librarySource) { if (identical(descriptor, DartEntry.RESOLUTION_ERRORS)) { return state._resolutionErrors as Object; } else if (identical(descriptor, DartEntry.RESOLVED_UNIT)) { @@ -1676,9 +1676,9 @@ * @param librarySource the source of the defining compilation unit of the library that used to * contain this part but no longer does */ - void removeResolution(Source librarySource2) { - if (librarySource2 != null) { - if (librarySource2 == _resolutionState._librarySource) { + void removeResolution(Source librarySource) { + if (librarySource != null) { + if (librarySource == _resolutionState._librarySource) { if (_resolutionState._nextState == null) { _resolutionState.invalidateAllResolutionInformation(); } else { @@ -1688,7 +1688,7 @@ DartEntryImpl_ResolutionState priorState = _resolutionState; DartEntryImpl_ResolutionState state = _resolutionState._nextState; while (state != null) { - if (librarySource2 == state._librarySource) { + if (librarySource == state._librarySource) { priorState._nextState = state._nextState; break; } @@ -1904,16 +1904,16 @@ * @param librarySource the library source (not `null`) * @return the resolution state (not `null`) */ - DartEntryImpl_ResolutionState getOrCreateResolutionState(Source librarySource2) { + DartEntryImpl_ResolutionState getOrCreateResolutionState(Source librarySource) { DartEntryImpl_ResolutionState state = _resolutionState; if (state._librarySource == null) { - state._librarySource = librarySource2; + state._librarySource = librarySource; return state; } - while (state._librarySource != librarySource2) { + while (state._librarySource != librarySource) { if (state._nextState == null) { DartEntryImpl_ResolutionState newState = new DartEntryImpl_ResolutionState(); - newState._librarySource = librarySource2; + newState._librarySource = librarySource; state._nextState = newState; return newState; } @@ -2484,8 +2484,8 @@ * * @param exception the exception that caused one or more values to be uncomputable */ - void set exception(AnalysisException exception2) { - this._exception = exception2; + void set exception(AnalysisException exception) { + this._exception = exception; } /** @@ -2779,6 +2779,7 @@ return null; } List<AnalysisError> computeErrors(Source source) { + bool enableHints = analysisOptions.hint; SourceEntry sourceEntry = getReadableSourceEntry(source); if (sourceEntry is DartEntry) { List<AnalysisError> errors = new List<AnalysisError>(); @@ -2787,12 +2788,16 @@ dartEntry = getReadableDartEntry(source); if (identical(dartEntry.getValue(DartEntry.SOURCE_KIND), SourceKind.LIBRARY)) { ListUtilities.addAll(errors, getDartResolutionData(source, source, dartEntry, DartEntry.RESOLUTION_ERRORS)); - ListUtilities.addAll(errors, getDartHintData(source, source, dartEntry, DartEntry.HINTS)); + if (enableHints) { + ListUtilities.addAll(errors, getDartHintData(source, source, dartEntry, DartEntry.HINTS)); + } } else { List<Source> libraries = getLibrariesContaining(source); for (Source librarySource in libraries) { ListUtilities.addAll(errors, getDartResolutionData(source, librarySource, dartEntry, DartEntry.RESOLUTION_ERRORS)); - ListUtilities.addAll(errors, getDartHintData(source, librarySource, dartEntry, DartEntry.HINTS)); + if (enableHints) { + ListUtilities.addAll(errors, getDartHintData(source, librarySource, dartEntry, DartEntry.HINTS)); + } } } if (errors.isEmpty) { @@ -3305,9 +3310,9 @@ } CompilationUnit resolveCompilationUnit2(Source unitSource, Source librarySource) => getDartResolutionData2(unitSource, librarySource, DartEntry.RESOLVED_UNIT, null); HtmlUnit resolveHtmlUnit(Source htmlSource) => parseHtmlUnit(htmlSource); - void set analysisOptions(AnalysisOptions options2) { + void set analysisOptions(AnalysisOptions options) { { - this._options = options2; + this._options = options; invalidateAllResolutionInformation(); } } @@ -3983,11 +3988,11 @@ * @param kind the kind of sources to be returned * @return all of the sources known to this context that have the given kind */ - List<Source> getSources(SourceKind kind2) { + List<Source> getSources(SourceKind kind) { List<Source> sources = new List<Source>(); { for (MapEntry<Source, SourceEntry> entry in _cache.entrySet()) { - if (identical(entry.getValue().kind, kind2)) { + if (identical(entry.getValue().kind, kind)) { sources.add(entry.getKey()); } } @@ -4102,7 +4107,7 @@ */ DartEntry recordGenerateDartHintsTask(GenerateDartHintsTask task) { Source librarySource = task.libraryElement.source; - AnalysisException thrownException = task.thrownException; + AnalysisException thrownException = task.exception; DartEntry libraryEntry = null; Map<Source, TimestampedData<List<AnalysisError>>> hintMap = task.hintMap; if (hintMap == null) { @@ -4186,7 +4191,7 @@ */ DartEntry recordParseDartTaskResults(ParseDartTask task) { Source source = task.source; - AnalysisException thrownException = task.thrownException; + AnalysisException thrownException = task.exception; DartEntry dartEntry = null; { SourceEntry sourceEntry = _cache.get(source); @@ -4253,7 +4258,7 @@ */ HtmlEntry recordParseHtmlTaskResults(ParseHtmlTask task) { Source source = task.source; - AnalysisException thrownException = task.thrownException; + AnalysisException thrownException = task.exception; HtmlEntry htmlEntry = null; { SourceEntry sourceEntry = _cache.get(source); @@ -4327,7 +4332,7 @@ */ DartEntry recordResolveDartLibraryTaskResults(ResolveDartLibraryTask task) { LibraryResolver resolver = task.libraryResolver; - AnalysisException thrownException = task.thrownException; + AnalysisException thrownException = task.exception; DartEntry unitEntry = null; Source unitSource = task.unitSource; if (resolver != null) { @@ -4419,7 +4424,7 @@ SourceEntry recordResolveDartUnitTaskResults(ResolveDartUnitTask task) { Source unitSource = task.source; Source librarySource = task.librarySource; - AnalysisException thrownException = task.thrownException; + AnalysisException thrownException = task.exception; DartEntry dartEntry = null; { SourceEntry sourceEntry = _cache.get(unitSource); @@ -4477,7 +4482,7 @@ */ SourceEntry recordResolveHtmlTaskResults(ResolveHtmlTask task) { Source source = task.source; - AnalysisException thrownException = task.thrownException; + AnalysisException thrownException = task.exception; HtmlEntry htmlEntry = null; { SourceEntry sourceEntry = _cache.get(source); @@ -4700,8 +4705,8 @@ * * @param hint `true` if analysis is to generate hint results */ - void set hint(bool hint2) { - this._hint = hint2; + void set hint(bool hint) { + this._hint = hint; } /** @@ -4794,8 +4799,8 @@ * * @param compilationUnit the fully resolved AST that changed as a result of the analysis */ - void set compilationUnit(CompilationUnit compilationUnit2) { - this._compilationUnit = compilationUnit2; + void set compilationUnit(CompilationUnit compilationUnit) { + this._compilationUnit = compilationUnit; } /** @@ -4805,9 +4810,9 @@ * @param errors the errors that changed as a result of the analysis * @param lineInfo the line information associated with the source */ - void setErrors(List<AnalysisError> errors2, LineInfo lineInfo2) { - this._errors = errors2; - this._lineInfo = lineInfo2; + void setErrors(List<AnalysisError> errors, LineInfo lineInfo) { + this._errors = errors; + this._lineInfo = lineInfo; } } /** @@ -5927,7 +5932,7 @@ * The exception that was thrown while performing this task, or `null` if the task completed * successfully. */ - AnalysisException thrownException; + AnalysisException exception; /** * Initialize a newly created task to perform analysis within the given context. @@ -5958,7 +5963,7 @@ try { safelyPerform(); } on AnalysisException catch (exception) { - thrownException = exception; + this.exception = exception; AnalysisEngine.instance.logger.logInformation2("Task failed: ${taskDescription}", exception); } return accept(visitor); @@ -6325,14 +6330,14 @@ RecordingErrorListener errorListener; List<Token> token; Source_ContentReceiver_9(this.ParseDartTask_this, this.errorListener, this.token); - void accept(CharBuffer contents, int modificationTime2) { - ParseDartTask_this.modificationTime = modificationTime2; + void accept(CharBuffer contents, int modificationTime) { + ParseDartTask_this.modificationTime = modificationTime; CharBufferScanner scanner = new CharBufferScanner(ParseDartTask_this.source, contents, errorListener); token[0] = scanner.tokenize(); ParseDartTask_this.lineInfo = new LineInfo(scanner.lineStarts); } - void accept2(String contents, int modificationTime2) { - ParseDartTask_this.modificationTime = modificationTime2; + void accept2(String contents, int modificationTime) { + ParseDartTask_this.modificationTime = modificationTime; StringScanner scanner = new StringScanner(ParseDartTask_this.source, contents, errorListener); token[0] = scanner.tokenize(); ParseDartTask_this.lineInfo = new LineInfo(scanner.lineStarts);
diff --git a/pkg/analyzer_experimental/lib/src/generated/error.dart b/pkg/analyzer_experimental/lib/src/generated/error.dart index b57ab78..7c5d24d 100644 --- a/pkg/analyzer_experimental/lib/src/generated/error.dart +++ b/pkg/analyzer_experimental/lib/src/generated/error.dart
@@ -206,8 +206,8 @@ * * @param source the source to be used when reporting errors */ - void set source(Source source2) { - this._source = source2 == null ? _defaultSource : source2; + void set source(Source source) { + this._source = source == null ? _defaultSource : source; } } /** @@ -478,24 +478,68 @@ static final HintCode TYPE_CHECK_IS_NULL = new HintCode.con1('TYPE_CHECK_IS_NULL', 12, "Tests for null should be done with '== null'"); /** + * This hint is generated anywhere where the [StaticTypeWarningCode#UNDEFINED_GETTER] or + * [StaticWarningCode#UNDEFINED_GETTER] would have been generated, if we used propagated + * information for the warnings. + * + * @param getterName the name of the getter + * @param enclosingType the name of the enclosing type where the getter is being looked for + * @see StaticTypeWarningCode#UNDEFINED_GETTER + * @see StaticWarningCode#UNDEFINED_GETTER + */ + static final HintCode UNDEFINED_GETTER = new HintCode.con1('UNDEFINED_GETTER', 13, StaticTypeWarningCode.UNDEFINED_GETTER.message); + + /** + * This hint is generated anywhere where the [StaticTypeWarningCode#UNDEFINED_METHOD] would + * have been generated, if we used propagated information for the warnings. + * + * @param methodName the name of the method that is undefined + * @param typeName the resolved type name that the method lookup is happening on + * @see StaticTypeWarningCode#UNDEFINED_METHOD + */ + static final HintCode UNDEFINED_METHOD = new HintCode.con1('UNDEFINED_METHOD', 14, StaticTypeWarningCode.UNDEFINED_METHOD.message); + + /** + * This hint is generated anywhere where the [StaticTypeWarningCode#UNDEFINED_OPERATOR] + * would have been generated, if we used propagated information for the warnings. + * + * @param operator the name of the operator + * @param enclosingType the name of the enclosing type where the operator is being looked for + * @see StaticTypeWarningCode#UNDEFINED_OPERATOR + */ + static final HintCode UNDEFINED_OPERATOR = new HintCode.con1('UNDEFINED_OPERATOR', 15, StaticTypeWarningCode.UNDEFINED_OPERATOR.message); + + /** + * This hint is generated anywhere where the [StaticTypeWarningCode#UNDEFINED_SETTER] or + * [StaticWarningCode#UNDEFINED_SETTER] would have been generated, if we used propagated + * information for the warnings. + * + * @param setterName the name of the setter + * @param enclosingType the name of the enclosing type where the setter is being looked for + * @see StaticTypeWarningCode#UNDEFINED_SETTER + * @see StaticWarningCode#UNDEFINED_SETTER + */ + static final HintCode UNDEFINED_SETTER = new HintCode.con1('UNDEFINED_SETTER', 16, StaticTypeWarningCode.UNDEFINED_SETTER.message); + + /** * Unnecessary cast. */ - static final HintCode UNNECESSARY_CAST = new HintCode.con1('UNNECESSARY_CAST', 13, "Unnecessary cast"); + static final HintCode UNNECESSARY_CAST = new HintCode.con1('UNNECESSARY_CAST', 17, "Unnecessary cast"); /** * Unnecessary type checks, the result is always true. */ - static final HintCode UNNECESSARY_TYPE_CHECK_FALSE = new HintCode.con1('UNNECESSARY_TYPE_CHECK_FALSE', 14, "Unnecessary type check, the result is always false"); + static final HintCode UNNECESSARY_TYPE_CHECK_FALSE = new HintCode.con1('UNNECESSARY_TYPE_CHECK_FALSE', 18, "Unnecessary type check, the result is always false"); /** * Unnecessary type checks, the result is always false. */ - static final HintCode UNNECESSARY_TYPE_CHECK_TRUE = new HintCode.con1('UNNECESSARY_TYPE_CHECK_TRUE', 15, "Unnecessary type check, the result is always true"); + static final HintCode UNNECESSARY_TYPE_CHECK_TRUE = new HintCode.con1('UNNECESSARY_TYPE_CHECK_TRUE', 19, "Unnecessary type check, the result is always true"); /** * Unused imports are imports which are never not used. */ - static final HintCode UNUSED_IMPORT = new HintCode.con1('UNUSED_IMPORT', 16, "Unused import"); + static final HintCode UNUSED_IMPORT = new HintCode.con1('UNUSED_IMPORT', 20, "Unused import"); static final List<HintCode> values = [ DEAD_CODE, DEAD_CODE_CATCH_FOLLOWING_CATCH, @@ -510,6 +554,10 @@ OVERRIDE_EQUALS_BUT_NOT_HASH_CODE, TYPE_CHECK_IS_NOT_NULL, TYPE_CHECK_IS_NULL, + UNDEFINED_GETTER, + UNDEFINED_METHOD, + UNDEFINED_OPERATOR, + UNDEFINED_SETTER, UNNECESSARY_CAST, UNNECESSARY_TYPE_CHECK_FALSE, UNNECESSARY_TYPE_CHECK_TRUE, @@ -2793,6 +2841,8 @@ * <i>id</i> occurs inside a top level or static function (be it function, method, getter, or * setter) or variable initializer and there is no declaration <i>d</i> with name <i>id</i> in the * lexical scope enclosing the expression. + * + * @param name the name of the identifier */ static final StaticWarningCode UNDEFINED_IDENTIFIER = new StaticWarningCode.con1('UNDEFINED_IDENTIFIER', 72, "Undefined name '%s'");
diff --git a/pkg/analyzer_experimental/lib/src/generated/html.dart b/pkg/analyzer_experimental/lib/src/generated/html.dart index a6c4a4e..f5286bc 100644 --- a/pkg/analyzer_experimental/lib/src/generated/html.dart +++ b/pkg/analyzer_experimental/lib/src/generated/html.dart
@@ -210,7 +210,7 @@ if (beginToken == null) { return -1; } - return beginToken.offset; + return this.beginToken.offset; } /** @@ -397,8 +397,8 @@ /** * Set array of element tags for which the content between tags should be consider a single token. */ - void set passThroughElements(List<String> passThroughElements2) { - this._passThroughElements = passThroughElements2 != null ? passThroughElements2 : _NO_PASS_THROUGH_ELEMENTS; + void set passThroughElements(List<String> passThroughElements) { + this._passThroughElements = passThroughElements != null ? passThroughElements : _NO_PASS_THROUGH_ELEMENTS; } /** @@ -694,8 +694,8 @@ this._charOffset = -1; } int get offset => _charOffset; - void set offset(int offset2) { - _charOffset = offset2; + void set offset(int offset) { + _charOffset = offset; } int advance() { if (++_charOffset < _stringLength) { @@ -999,14 +999,14 @@ HtmlScanner(Source source) { this._source = source; } - void accept(CharBuffer contents, int modificationTime2) { - this._modificationTime = modificationTime2; + void accept(CharBuffer contents, int modificationTime) { + this._modificationTime = modificationTime; _scanner = new CharBufferScanner(_source, contents); _scanner.passThroughElements = _SCRIPT_TAG; _token = _scanner.tokenize(); } - void accept2(String contents, int modificationTime2) { - this._modificationTime = modificationTime2; + void accept2(String contents, int modificationTime) { + this._modificationTime = modificationTime; _scanner = new StringScanner(_source, contents); _scanner.passThroughElements = _SCRIPT_TAG; _token = _scanner.tokenize(); @@ -1354,9 +1354,9 @@ * @param name the attribute name * @return the attribute or `null` if no matching attribute is found */ - XmlAttributeNode getAttribute(String name2) { + XmlAttributeNode getAttribute(String name) { for (XmlAttributeNode attribute in attributes) { - if (attribute.name.lexeme == name2) { + if (attribute.name.lexeme == name) { return attribute; } }
diff --git a/pkg/analyzer_experimental/lib/src/generated/instrumentation.dart b/pkg/analyzer_experimental/lib/src/generated/instrumentation.dart index 8af2198..32f7498 100644 --- a/pkg/analyzer_experimental/lib/src/generated/instrumentation.dart +++ b/pkg/analyzer_experimental/lib/src/generated/instrumentation.dart
@@ -85,8 +85,8 @@ * * @param logger the logger that should receive instrumentation information */ - static void set logger(InstrumentationLogger logger2) { - _CURRENT_LOGGER = logger2 == null ? _NULL_LOGGER : logger2; + static void set logger(InstrumentationLogger logger) { + _CURRENT_LOGGER = logger == null ? _NULL_LOGGER : logger; } } class InstrumentationBuilder_15 implements InstrumentationBuilder {
diff --git a/pkg/analyzer_experimental/lib/src/generated/parser.dart b/pkg/analyzer_experimental/lib/src/generated/parser.dart index 2264972..a7cb7de 100644 --- a/pkg/analyzer_experimental/lib/src/generated/parser.dart +++ b/pkg/analyzer_experimental/lib/src/generated/parser.dart
@@ -259,8 +259,8 @@ instrumentation.log(); } } - void set currentToken(Token currentToken2) { - this._currentToken = currentToken2; + void set currentToken(Token currentToken) { + this._currentToken = currentToken; } /** @@ -818,7 +818,7 @@ * @param keyword the keyword that is being tested for * @return `true` if the given token matches the given keyword */ - bool matches3(Token token, Keyword keyword2) => identical(token.type, TokenType.KEYWORD) && identical(((token as KeywordToken)).keyword, keyword2); + bool matches3(Token token, Keyword keyword) => identical(token.type, TokenType.KEYWORD) && identical(((token as KeywordToken)).keyword, keyword); /** * Return `true` if the given token has the given type. @@ -827,7 +827,7 @@ * @param type the type of token that is being tested for * @return `true` if the given token has the given type */ - bool matches4(Token token, TokenType type2) => identical(token.type, type2); + bool matches4(Token token, TokenType type) => identical(token.type, type); /** * Return `true` if the current token has the given type. Note that this method, unlike @@ -838,10 +838,10 @@ * @param type the type of token that can optionally appear in the current location * @return `true` if the current token has the given type */ - bool matches5(TokenType type2) { + bool matches5(TokenType type) { TokenType currentType = _currentToken.type; - if (currentType != type2) { - if (identical(type2, TokenType.GT)) { + if (currentType != type) { + if (identical(type, TokenType.GT)) { if (identical(currentType, TokenType.GT_GT)) { int offset = _currentToken.offset; Token first = new Token(TokenType.GT, offset); @@ -4861,8 +4861,7 @@ if (matcher.find()) { int offset = commentToken.offset + matcher.start() + matcher.group(1).length; int length = matcher.group(2).length; - // TODO(scheglov) analyzer_experimental users don't expect it -// _errorListener.onError(new AnalysisError.con2(_source, offset, length, TodoCode.TODO, [matcher.group(2)])); + // _errorListener.onError(new AnalysisError.con2(_source, offset, length, TodoCode.TODO, [matcher.group(2)])); } }
diff --git a/pkg/analyzer_experimental/lib/src/generated/resolver.dart b/pkg/analyzer_experimental/lib/src/generated/resolver.dart index 3860b21..535ce2e 100644 --- a/pkg/analyzer_experimental/lib/src/generated/resolver.dart +++ b/pkg/analyzer_experimental/lib/src/generated/resolver.dart
@@ -33,7 +33,7 @@ * @return the compilation unit element that was built * @throws AnalysisException if the analysis could not be performed */ - CompilationUnitElementImpl buildCompilationUnit(Source source2, CompilationUnit unit) { + CompilationUnitElementImpl buildCompilationUnit(Source source, CompilationUnit unit) { TimeCounter_TimeCounterHandle timeCounter = PerformanceStatistics.resolve.start(); if (unit == null) { return null; @@ -41,10 +41,10 @@ ElementHolder holder = new ElementHolder(); ElementBuilder builder = new ElementBuilder(holder); unit.accept(builder); - CompilationUnitElementImpl element = new CompilationUnitElementImpl(source2.shortName); + CompilationUnitElementImpl element = new CompilationUnitElementImpl(source.shortName); element.accessors = holder.accessors; element.functions = holder.functions; - element.source = source2; + element.source = source; element.typeAliases = holder.typeAliases; element.types = holder.types; element.topLevelVariables = holder.topLevelVariables; @@ -693,7 +693,7 @@ * @param keyword the keyword being tested for * @return `true` if the given token is a token for the given keyword */ - bool matches(sc.Token token, sc.Keyword keyword2) => token != null && identical(token.type, sc.TokenType.KEYWORD) && identical(((token as sc.KeywordToken)).keyword, keyword2); + bool matches(sc.Token token, sc.Keyword keyword) => token != null && identical(token.type, sc.TokenType.KEYWORD) && identical(((token as sc.KeywordToken)).keyword, keyword); /** * Sets the visible source range for formal parameter. @@ -1117,11 +1117,11 @@ * @param unit the AST structure representing the HTML * @throws AnalysisException if the analysis could not be performed */ - HtmlElementImpl buildHtmlElement2(Source source2, int modificationStamp2, ht.HtmlUnit unit) { - this._modificationStamp = modificationStamp2; - _lineInfo = _context.computeLineInfo(source2); - HtmlElementImpl result = new HtmlElementImpl(_context, source2.shortName); - result.source = source2; + HtmlElementImpl buildHtmlElement2(Source source, int modificationStamp, ht.HtmlUnit unit) { + this._modificationStamp = modificationStamp; + _lineInfo = _context.computeLineInfo(source); + HtmlElementImpl result = new HtmlElementImpl(_context, source.shortName); + result.source = source; _htmlElement = result; unit.accept(this); _htmlElement = null; @@ -1296,7 +1296,6 @@ static String _HASHCODE_GETTER_NAME = "hashCode"; static String _METHOD = "method"; static String _NULL_TYPE_NAME = "Null"; - static String _OBJECT_TYPE_NAME = "Object"; static String _SETTER = "setter"; static String _TO_INT_METHOD_NAME = "toInt"; @@ -1394,7 +1393,7 @@ Element rhsElement = rhsType.element; LibraryElement libraryElement = rhsElement != null ? rhsElement.library : null; if (libraryElement != null && libraryElement.isDartCore) { - if ((rhsType.isObject && rhsNameStr == _OBJECT_TYPE_NAME) || (expression is NullLiteral && rhsNameStr == _NULL_TYPE_NAME)) { + if (rhsType.isObject || (expression is NullLiteral && rhsNameStr == _NULL_TYPE_NAME)) { if (node.notOperator == null) { _errorReporter.reportError2(HintCode.UNNECESSARY_TYPE_CHECK_TRUE, node, []); } else { @@ -2055,9 +2054,18 @@ } return super.visitCompilationUnit(node); } - Object visitExportDirective(ExportDirective node) => null; - Object visitImportDirective(ImportDirective node) => null; - Object visitLibraryDirective(LibraryDirective node) => null; + Object visitExportDirective(ExportDirective node) { + visitMetadata(node.metadata); + return null; + } + Object visitImportDirective(ImportDirective node) { + visitMetadata(node.metadata); + return null; + } + Object visitLibraryDirective(LibraryDirective node) { + visitMetadata(node.metadata); + return null; + } Object visitPrefixedIdentifier(PrefixedIdentifier node) { SimpleIdentifier prefixIdentifier = node.prefix; Element element = prefixIdentifier.staticElement; @@ -2068,8 +2076,8 @@ return visitIdentifier(element, prefixIdentifier.name); } Object visitSimpleIdentifier(SimpleIdentifier node) => visitIdentifier(node.staticElement, node.name); - void set inDefiningCompilationUnit(bool inDefiningCompilationUnit2) { - this._inDefiningCompilationUnit = inDefiningCompilationUnit2; + void set inDefiningCompilationUnit(bool inDefiningCompilationUnit) { + this._inDefiningCompilationUnit = inDefiningCompilationUnit; } /** @@ -2159,6 +2167,20 @@ } return null; } + + /** + * Given some [NodeList] of [Annotation]s, ensure that the identifiers are visited by + * this visitor. Specifically, this covers the cases where AST nodes don't have their identifiers + * visited by this visitor, but still need their annotations visited. + * + * @param annotations the list of annotations to visit + */ + void visitMetadata(NodeList<Annotation> annotations) { + for (Annotation annotation in annotations) { + Identifier name = annotation.name; + visitIdentifier(name.staticElement, name.name); + } + } } /** * Instances of the class `PubVerifier` traverse an AST structure looking for deviations from @@ -2354,9 +2376,9 @@ * @param unit the compilation unit to be resolved * @param element the root of the element model used to resolve the AST nodes */ - void resolve(CompilationUnit unit, CompilationUnitElement element2) { - _enclosingUnit = element2; - unit.element = element2; + void resolve(CompilationUnit unit, CompilationUnitElement element) { + _enclosingUnit = element; + unit.element = element; unit.accept(this); } Object visitCatchClause(CatchClause node) { @@ -2714,9 +2736,9 @@ * for * @return the export element whose library has the given source */ - ExportElement find5(List<ExportElement> exports, Source source2) { + ExportElement find5(List<ExportElement> exports, Source source) { for (ExportElement export in exports) { - if (export.exportedLibrary.source == source2) { + if (export.exportedLibrary.source == source) { return export; } } @@ -2733,16 +2755,16 @@ * @param prefix the prefix with which the library was imported * @return the import element whose library has the given source and prefix */ - ImportElement find6(List<ImportElement> imports, Source source2, SimpleIdentifier prefix2) { + ImportElement find6(List<ImportElement> imports, Source source, SimpleIdentifier prefix) { for (ImportElement element in imports) { - if (element.importedLibrary.source == source2) { + if (element.importedLibrary.source == source) { PrefixElement prefixElement = element.prefix; - if (prefix2 == null) { + if (prefix == null) { if (prefixElement == null) { return element; } } else { - if (prefixElement != null && prefix2.name == prefixElement.displayName) { + if (prefixElement != null && prefix.name == prefixElement.displayName) { return element; } } @@ -2919,6 +2941,11 @@ bool _strictMode = false; /** + * A flag indicating whether we should generate hints. + */ + bool _enableHints = false; + + /** * The type representing the type 'dynamic'. */ Type2 _dynamicType; @@ -2947,7 +2974,9 @@ */ ElementResolver(ResolverVisitor resolver) { this._resolver = resolver; - _strictMode = resolver.definingLibrary.context.analysisOptions.strictMode; + AnalysisOptions options = resolver.definingLibrary.context.analysisOptions; + _strictMode = options.strictMode; + _enableHints = options.hint; _dynamicType = resolver.typeProvider.dynamicType; _typeType = resolver.typeProvider.typeType; } @@ -2965,8 +2994,13 @@ Type2 propagatedType = getPropagatedType(leftHandSide); MethodElement propagatedMethod = lookUpMethod(leftHandSide, propagatedType, methodName); node.propagatedElement = propagatedMethod; - if (shouldReportMissingMember(staticType, staticMethod) && (_strictMode || propagatedType == null || shouldReportMissingMember(propagatedType, propagatedMethod))) { - _resolver.reportErrorProxyConditionalAnalysisError3(staticType.element, StaticTypeWarningCode.UNDEFINED_METHOD, operator, [methodName, staticType.displayName]); + bool shouldReportMissingMember_static = shouldReportMissingMember(staticType, staticMethod) && (_strictMode || shouldReportMissingMember(propagatedType, propagatedMethod)); + bool shouldReportMissingMember_propagated = _enableHints ? shouldReportMissingMember(propagatedType, propagatedMethod) : false; + if (shouldReportMissingMember_static || shouldReportMissingMember_propagated) { + ErrorCode errorCode = (shouldReportMissingMember_static ? StaticTypeWarningCode.UNDEFINED_METHOD : HintCode.UNDEFINED_METHOD) as ErrorCode; + _resolver.reportErrorProxyConditionalAnalysisError3(staticType.element, errorCode, operator, [ + methodName, + shouldReportMissingMember_static ? staticType.displayName : propagatedType.displayName]); } } } @@ -2984,8 +3018,13 @@ Type2 propagatedType = getPropagatedType(leftOperand); MethodElement propagatedMethod = lookUpMethod(leftOperand, propagatedType, methodName); node.propagatedElement = propagatedMethod; - if (shouldReportMissingMember(staticType, staticMethod) && (_strictMode || propagatedType == null || shouldReportMissingMember(propagatedType, propagatedMethod))) { - _resolver.reportErrorProxyConditionalAnalysisError3(staticType.element, StaticTypeWarningCode.UNDEFINED_OPERATOR, operator, [methodName, staticType.displayName]); + bool shouldReportMissingMember_static = shouldReportMissingMember(staticType, staticMethod) && (_strictMode || shouldReportMissingMember(propagatedType, propagatedMethod)); + bool shouldReportMissingMember_propagated = _enableHints ? shouldReportMissingMember(propagatedType, propagatedMethod) : false; + if (shouldReportMissingMember_static || shouldReportMissingMember_propagated) { + ErrorCode errorCode = (shouldReportMissingMember_static ? StaticTypeWarningCode.UNDEFINED_OPERATOR : HintCode.UNDEFINED_OPERATOR) as ErrorCode; + _resolver.reportErrorProxyConditionalAnalysisError3(staticType.element, errorCode, operator, [ + methodName, + shouldReportMissingMember_static ? staticType.displayName : propagatedType.displayName]); } } } @@ -3311,7 +3350,15 @@ argumentList.correspondingPropagatedParameters = parameters; } } - ErrorCode errorCode = checkForInvocationError(target, staticElement); + ErrorCode errorCode = checkForInvocationError(target, true, staticElement); + bool generatedWithTypePropagation = false; + if (_enableHints && errorCode == null && staticElement == null) { + errorCode = checkForInvocationError(target, false, propagatedElement); + generatedWithTypePropagation = true; + } + if (errorCode == null) { + return null; + } if (identical(errorCode, StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION)) { _resolver.reportError5(StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION, methodName, [methodName.name]); } else if (identical(errorCode, CompileTimeErrorCode.UNDEFINED_FUNCTION)) { @@ -3321,20 +3368,27 @@ if (target == null) { ClassElement enclosingClass = _resolver.enclosingClass; targetTypeName = enclosingClass.displayName; - _resolver.reportErrorProxyConditionalAnalysisError(_resolver.enclosingClass, StaticTypeWarningCode.UNDEFINED_METHOD, methodName, [methodName.name, targetTypeName]); + ErrorCode proxyErrorCode = (generatedWithTypePropagation ? HintCode.UNDEFINED_METHOD : StaticTypeWarningCode.UNDEFINED_METHOD) as ErrorCode; + _resolver.reportErrorProxyConditionalAnalysisError(_resolver.enclosingClass, proxyErrorCode, methodName, [methodName.name, targetTypeName]); } else { - Type2 targetType = getStaticType(target); + Type2 targetType = null; + if (!generatedWithTypePropagation) { + targetType = getStaticType(target); + } else { + targetType = getPropagatedType(target); + if (targetType == null) { + targetType = getStaticType(target); + } + } if (targetType != null && targetType.isDartCoreFunction && methodName.name == CALL_METHOD_NAME) { return null; } targetTypeName = targetType == null ? null : targetType.displayName; - _resolver.reportErrorProxyConditionalAnalysisError(targetType.element, StaticTypeWarningCode.UNDEFINED_METHOD, methodName, [methodName.name, targetTypeName]); + ErrorCode proxyErrorCode = (generatedWithTypePropagation ? HintCode.UNDEFINED_METHOD : StaticTypeWarningCode.UNDEFINED_METHOD) as ErrorCode; + _resolver.reportErrorProxyConditionalAnalysisError(targetType.element, proxyErrorCode, methodName, [methodName.name, targetTypeName]); } } else if (identical(errorCode, StaticTypeWarningCode.UNDEFINED_SUPER_METHOD)) { - Type2 targetType = getPropagatedType(target); - if (targetType == null) { - targetType = getStaticType(target); - } + Type2 targetType = getStaticType(target); String targetTypeName = targetType == null ? null : targetType.name; _resolver.reportError5(StaticTypeWarningCode.UNDEFINED_SUPER_METHOD, methodName, [methodName.name, targetTypeName]); } @@ -3357,8 +3411,13 @@ Type2 propagatedType = getPropagatedType(operand); MethodElement propagatedMethod = lookUpMethod(operand, propagatedType, methodName); node.propagatedElement = propagatedMethod; - if (shouldReportMissingMember(staticType, staticMethod) && (_strictMode || propagatedType == null || shouldReportMissingMember(propagatedType, propagatedMethod))) { - _resolver.reportErrorProxyConditionalAnalysisError3(staticType.element, StaticTypeWarningCode.UNDEFINED_OPERATOR, node.operator, [methodName, staticType.displayName]); + bool shouldReportMissingMember_static = shouldReportMissingMember(staticType, staticMethod) && (_strictMode || shouldReportMissingMember(propagatedType, propagatedMethod)); + bool shouldReportMissingMember_propagated = _enableHints ? shouldReportMissingMember(propagatedType, propagatedMethod) : false; + if (shouldReportMissingMember_static || shouldReportMissingMember_propagated) { + ErrorCode errorCode = (shouldReportMissingMember_static ? StaticTypeWarningCode.UNDEFINED_OPERATOR : HintCode.UNDEFINED_OPERATOR) as ErrorCode; + _resolver.reportErrorProxyConditionalAnalysisError3(staticType.element, errorCode, node.operator, [ + methodName, + shouldReportMissingMember_static ? staticType.displayName : propagatedType.displayName]); } return null; } @@ -3415,8 +3474,13 @@ Type2 propagatedType = getPropagatedType(operand); MethodElement propagatedMethod = lookUpMethod(operand, propagatedType, methodName); node.propagatedElement = propagatedMethod; - if (shouldReportMissingMember(staticType, staticMethod) && (_strictMode || propagatedType == null || shouldReportMissingMember(propagatedType, propagatedMethod))) { - _resolver.reportErrorProxyConditionalAnalysisError3(staticType.element, StaticTypeWarningCode.UNDEFINED_OPERATOR, operator, [methodName, staticType.displayName]); + bool shouldReportMissingMember_static = shouldReportMissingMember(staticType, staticMethod) && (_strictMode || shouldReportMissingMember(propagatedType, propagatedMethod)); + bool shouldReportMissingMember_propagated = _enableHints ? shouldReportMissingMember(propagatedType, propagatedMethod) : false; + if (shouldReportMissingMember_static || shouldReportMissingMember_propagated) { + ErrorCode errorCode = (shouldReportMissingMember_static ? StaticTypeWarningCode.UNDEFINED_OPERATOR : HintCode.UNDEFINED_OPERATOR) as ErrorCode; + _resolver.reportErrorProxyConditionalAnalysisError3(staticType.element, errorCode, operator, [ + methodName, + shouldReportMissingMember_static ? staticType.displayName : propagatedType.displayName]); } } return null; @@ -3573,10 +3637,11 @@ * reported, or `null` if no error should be reported. * * @param target the target of the invocation, or `null` if there was no target + * @param useStaticContext * @param element the element to be invoked * @return the error code that should be reported */ - ErrorCode checkForInvocationError(Expression target, Element element) { + ErrorCode checkForInvocationError(Expression target, bool useStaticContext, Element element) { if (element is PrefixElement) { element = null; } @@ -3618,7 +3683,15 @@ return StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION; } } else { - Type2 targetType = getStaticType(target); + Type2 targetType; + if (useStaticContext) { + targetType = getStaticType(target); + } else { + targetType = getPropagatedType(target); + if (targetType == null) { + targetType = getStaticType(target); + } + } if (targetType == null) { return CompileTimeErrorCode.UNDEFINED_FUNCTION; } else if (!targetType.isDynamic) { @@ -3641,15 +3714,22 @@ * @return `true` if and only if an error code is generated on the passed node */ bool checkForUndefinedIndexOperator(IndexExpression node, Expression target, String methodName, MethodElement staticMethod, MethodElement propagatedMethod, Type2 staticType, Type2 propagatedType) { - if (shouldReportMissingMember(staticType, staticMethod) && (_strictMode || propagatedType == null || shouldReportMissingMember(propagatedType, propagatedMethod))) { + bool shouldReportMissingMember_static = shouldReportMissingMember(staticType, staticMethod) && (_strictMode || shouldReportMissingMember(propagatedType, propagatedMethod)); + bool shouldReportMissingMember_propagated = _enableHints ? shouldReportMissingMember(propagatedType, propagatedMethod) : false; + if (shouldReportMissingMember_static || shouldReportMissingMember_propagated) { sc.Token leftBracket = node.leftBracket; sc.Token rightBracket = node.rightBracket; + ErrorCode errorCode = (shouldReportMissingMember_static ? StaticTypeWarningCode.UNDEFINED_OPERATOR : HintCode.UNDEFINED_OPERATOR) as ErrorCode; if (leftBracket == null || rightBracket == null) { - _resolver.reportErrorProxyConditionalAnalysisError(staticType.element, StaticTypeWarningCode.UNDEFINED_OPERATOR, node, [methodName, staticType.displayName]); + _resolver.reportErrorProxyConditionalAnalysisError(staticType.element, errorCode, node, [ + methodName, + shouldReportMissingMember_static ? staticType.displayName : propagatedType.displayName]); } else { int offset = leftBracket.offset; int length = rightBracket.offset - offset + 1; - _resolver.reportErrorProxyConditionalAnalysisError2(staticType.element, StaticTypeWarningCode.UNDEFINED_OPERATOR, offset, length, [methodName, staticType.displayName]); + _resolver.reportErrorProxyConditionalAnalysisError2(staticType.element, errorCode, offset, length, [ + methodName, + shouldReportMissingMember_static ? staticType.displayName : propagatedType.displayName]); } return true; } @@ -3665,9 +3745,9 @@ * @param executableElement the element that will be invoked with the arguments * @return the parameters that correspond to the arguments */ - List<ParameterElement> computeCorrespondingParameters(ArgumentList argumentList, Element element2) { - if (element2 is PropertyAccessorElement) { - FunctionType getterType = ((element2 as PropertyAccessorElement)).type; + List<ParameterElement> computeCorrespondingParameters(ArgumentList argumentList, Element element) { + if (element is PropertyAccessorElement) { + FunctionType getterType = ((element as PropertyAccessorElement)).type; if (getterType != null) { Type2 getterReturnType = getterType.returnType; if (getterReturnType is InterfaceType) { @@ -3682,10 +3762,10 @@ } } } - } else if (element2 is ExecutableElement) { - return resolveArgumentsToParameters(false, argumentList, element2 as ExecutableElement); - } else if (element2 is VariableElement) { - VariableElement variable = element2 as VariableElement; + } else if (element is ExecutableElement) { + return resolveArgumentsToParameters(false, argumentList, element as ExecutableElement); + } else if (element is VariableElement) { + VariableElement variable = element as VariableElement; Type2 type = variable.type; if (type is FunctionType) { FunctionType functionType = type as FunctionType; @@ -4262,9 +4342,9 @@ * @param nameNode the name of the invoked constructor, may be `null` if unnamed constructor * or not a constructor invocation */ - void resolveAnnotationElement(Annotation annotation, Element element2, SimpleIdentifier nameNode) { - if (element2 is PropertyAccessorElement) { - PropertyAccessorElement accessorElement = element2 as PropertyAccessorElement; + void resolveAnnotationElement(Annotation annotation, Element element, SimpleIdentifier nameNode) { + if (element is PropertyAccessorElement) { + PropertyAccessorElement accessorElement = element as PropertyAccessorElement; if (!accessorElement.isSynthetic) { _resolver.reportError5(CompileTimeErrorCode.INVALID_ANNOTATION, annotation, []); return; @@ -4275,14 +4355,14 @@ } return; } - if (element2 is ClassElement) { + if (element is ClassElement) { if (nameNode == null) { nameNode = annotation.constructorName; } String name = nameNode != null ? nameNode.name : null; ConstructorElement constructor; { - InterfaceType interfaceType = new InterfaceTypeImpl.con1(element2 as ClassElement); + InterfaceType interfaceType = new InterfaceTypeImpl.con1(element as ClassElement); LibraryElement definingLibrary = _resolver.definingLibrary; constructor = interfaceType.lookUpConstructor(name, definingLibrary); } @@ -4297,7 +4377,7 @@ resolveAnnotationConstructorInvocationArguments(annotation, constructor); return; } - if (element2 != null) { + if (element != null) { _resolver.reportError5(CompileTimeErrorCode.INVALID_ANNOTATION, annotation, []); } } @@ -4507,20 +4587,34 @@ Type2 propagatedType = getPropagatedType(target); ExecutableElement propagatedElement = resolveProperty(target, propagatedType, propertyName); propertyName.propagatedElement = propagatedElement; - if (shouldReportMissingMember(staticType, staticElement) && (_strictMode || propagatedType == null || shouldReportMissingMember(propagatedType, propagatedElement))) { + bool shouldReportMissingMember_static = shouldReportMissingMember(staticType, staticElement) && (_strictMode || shouldReportMissingMember(propagatedType, propagatedElement)); + bool shouldReportMissingMember_propagated = _enableHints ? shouldReportMissingMember(propagatedType, propagatedElement) : false; + if (shouldReportMissingMember_static || shouldReportMissingMember_propagated) { Element selectedElement = select(staticElement, propagatedElement); bool isStaticProperty = isStatic(selectedElement); if (propertyName.inSetterContext()) { if (isStaticProperty) { - _resolver.reportErrorProxyConditionalAnalysisError(staticType.element, StaticWarningCode.UNDEFINED_SETTER, propertyName, [propertyName.name, staticType.displayName]); + ErrorCode errorCode = (shouldReportMissingMember_static ? StaticWarningCode.UNDEFINED_SETTER : HintCode.UNDEFINED_SETTER) as ErrorCode; + _resolver.reportErrorProxyConditionalAnalysisError(staticType.element, errorCode, propertyName, [ + propertyName.name, + shouldReportMissingMember_static ? staticType.displayName : propagatedType.displayName]); } else { - _resolver.reportErrorProxyConditionalAnalysisError(staticType.element, StaticTypeWarningCode.UNDEFINED_SETTER, propertyName, [propertyName.name, staticType.displayName]); + ErrorCode errorCode = (shouldReportMissingMember_static ? StaticTypeWarningCode.UNDEFINED_SETTER : HintCode.UNDEFINED_SETTER) as ErrorCode; + _resolver.reportErrorProxyConditionalAnalysisError(staticType.element, errorCode, propertyName, [ + propertyName.name, + shouldReportMissingMember_static ? staticType.displayName : propagatedType.displayName]); } } else if (propertyName.inGetterContext()) { if (isStaticProperty) { - _resolver.reportErrorProxyConditionalAnalysisError(staticType.element, StaticWarningCode.UNDEFINED_GETTER, propertyName, [propertyName.name, staticType.displayName]); + ErrorCode errorCode = (shouldReportMissingMember_static ? StaticWarningCode.UNDEFINED_GETTER : HintCode.UNDEFINED_GETTER) as ErrorCode; + _resolver.reportErrorProxyConditionalAnalysisError(staticType.element, errorCode, propertyName, [ + propertyName.name, + shouldReportMissingMember_static ? staticType.displayName : propagatedType.displayName]); } else { - _resolver.reportErrorProxyConditionalAnalysisError(staticType.element, StaticTypeWarningCode.UNDEFINED_GETTER, propertyName, [propertyName.name, staticType.displayName]); + ErrorCode errorCode = (shouldReportMissingMember_static ? StaticTypeWarningCode.UNDEFINED_GETTER : HintCode.UNDEFINED_GETTER) as ErrorCode; + _resolver.reportErrorProxyConditionalAnalysisError(staticType.element, errorCode, propertyName, [ + propertyName.name, + shouldReportMissingMember_static ? staticType.displayName : propagatedType.displayName]); } } else { _resolver.reportErrorProxyConditionalAnalysisError(staticType.element, StaticWarningCode.UNDEFINED_IDENTIFIER, propertyName, [propertyName.name]); @@ -4811,8 +4905,8 @@ * * @param library the new library element */ - void set libraryElement(LibraryElement library2) { - this._library = library2; + void set libraryElement(LibraryElement library) { + this._library = library; } /** @@ -5353,7 +5447,7 @@ try { _libraryElement = _analysisContext.computeLibraryElement(librarySource) as LibraryElementImpl; } on AnalysisException catch (exception) { - AnalysisEngine.instance.logger.logError2("Could not compute ilbrary element for ${librarySource.fullName}", exception); + AnalysisEngine.instance.logger.logError2("Could not compute library element for ${librarySource.fullName}", exception); } } return _libraryElement; @@ -5439,8 +5533,8 @@ * * @param exportedLibraries the libraries that are exported by this library */ - void set exportedLibraries(List<Library> exportedLibraries2) { - this.exports = exportedLibraries2; + void set exportedLibraries(List<Library> exportedLibraries) { + this.exports = exportedLibraries; } /** @@ -5448,8 +5542,8 @@ * * @param importedLibraries the libraries that are imported into this library */ - void set importedLibraries(List<Library> importedLibraries2) { - this.imports = importedLibraries2; + void set importedLibraries(List<Library> importedLibraries) { + this.imports = importedLibraries; } /** @@ -5457,10 +5551,10 @@ * * @param libraryElement the library element representing this library */ - void set libraryElement(LibraryElementImpl libraryElement2) { - this._libraryElement = libraryElement2; + void set libraryElement(LibraryElementImpl libraryElement) { + this._libraryElement = libraryElement; if (_inheritanceManager != null) { - _inheritanceManager.libraryElement = libraryElement2; + _inheritanceManager.libraryElement = libraryElement; } } String toString() => librarySource.shortName; @@ -6349,9 +6443,9 @@ * @param element the class being tested * @return `true` if the given element represents a class that has the proxy annotation */ - static bool classHasProxyAnnotation(Element element2) { - if (element2 is ClassElement) { - ClassElement classElement = element2 as ClassElement; + static bool classHasProxyAnnotation(Element element) { + if (element is ClassElement) { + ClassElement classElement = element as ClassElement; List<ElementAnnotation> annotations = classElement.metadata; for (ElementAnnotation annotation in annotations) { Element elementAnnotation = annotation.element; @@ -7112,11 +7206,11 @@ * @param expression the expression being tested * @return `true` if the given expression terminates abruptly */ - bool isAbruptTermination(Expression expression2) { - while (expression2 is ParenthesizedExpression) { - expression2 = ((expression2 as ParenthesizedExpression)).expression; + bool isAbruptTermination(Expression expression) { + while (expression is ParenthesizedExpression) { + expression = ((expression as ParenthesizedExpression)).expression; } - return expression2 is ThrowExpression || expression2 is RethrowExpression; + return expression is ThrowExpression || expression is RethrowExpression; } /** @@ -7404,6 +7498,16 @@ } return null; } + Object visitFormalParameterList(FormalParameterList node) { + super.visitFormalParameterList(node); + if (nameScope is FunctionScope) { + ((nameScope as FunctionScope)).defineParameters(); + } + if (nameScope is FunctionTypeScope) { + ((nameScope as FunctionTypeScope)).defineParameters(); + } + return null; + } Object visitForStatement(ForStatement node) { Scope outerNameScope = nameScope; LabelScope outerLabelScope = labelScope; @@ -7813,8 +7917,8 @@ * * @param thisType the type representing the class containing the nodes being analyzed */ - void set thisType(InterfaceType thisType2) { - this._thisType = thisType2; + void set thisType(InterfaceType thisType) { + this._thisType = thisType; } /** @@ -9943,12 +10047,12 @@ TypeArgumentList argumentList = node.typeArguments; Element element = nameScope.lookup(typeName, definingLibrary); if (element == null) { - if (typeName.name == _dynamicType.name) { - setElement(typeName, _dynamicType.element); + if (typeName.name == this._dynamicType.name) { + setElement(typeName, this._dynamicType.element); if (argumentList != null) { } - typeName.staticType = _dynamicType; - node.type = _dynamicType; + typeName.staticType = this._dynamicType; + node.type = this._dynamicType; return null; } VoidTypeImpl voidType = VoidTypeImpl.instance; @@ -10024,10 +10128,10 @@ if (element is MultiplyDefinedElement) { setElement(typeName, element); } else { - setElement(typeName, _dynamicType.element); + setElement(typeName, this._dynamicType.element); } - typeName.staticType = _dynamicType; - node.type = _dynamicType; + typeName.staticType = this._dynamicType; + node.type = this._dynamicType; return null; } Type2 type = null; @@ -10069,9 +10173,9 @@ reportError5(StaticWarningCode.NOT_A_TYPE, typeName, [typeName.name]); } } - setElement(typeName, _dynamicType.element); - typeName.staticType = _dynamicType; - node.type = _dynamicType; + setElement(typeName, this._dynamicType.element); + typeName.staticType = this._dynamicType; + node.type = this._dynamicType; return null; } if (argumentList != null) { @@ -10093,7 +10197,7 @@ argumentCount = typeArguments.length; if (argumentCount < parameterCount) { for (int i = argumentCount; i < parameterCount; i++) { - typeArguments.add(_dynamicType); + typeArguments.add(this._dynamicType); } } if (type is InterfaceTypeImpl) { @@ -10513,12 +10617,12 @@ * @param returnType the (possibly `null`) return type of the function * @param parameterList the list of parameters to the function */ - void setFunctionTypedParameterType(ParameterElementImpl element, TypeName returnType2, FormalParameterList parameterList) { + void setFunctionTypedParameterType(ParameterElementImpl element, TypeName returnType, FormalParameterList parameterList) { List<ParameterElement> parameters = getElements(parameterList); FunctionTypeAliasElementImpl aliasElement = new FunctionTypeAliasElementImpl(null); aliasElement.synthetic = true; aliasElement.shareParameters(parameters); - aliasElement.returnType = computeReturnType(returnType2); + aliasElement.returnType = computeReturnType(returnType); FunctionTypeImpl type = new FunctionTypeImpl.con2(aliasElement); ClassElement definingClass = element.getAncestor(ClassElement); if (definingClass != null) { @@ -10655,6 +10759,8 @@ * @coverage dart.engine.resolver */ class FunctionScope extends EnclosedScope { + ExecutableElement _functionElement; + bool _parametersDefined = false; /** * Initialize a newly created scope enclosed within another scope. @@ -10663,23 +10769,25 @@ * @param functionElement the element representing the type represented by this scope */ FunctionScope(Scope enclosingScope, ExecutableElement functionElement) : super(new EnclosedScope(enclosingScope)) { - defineParameters(functionElement); + this._functionElement = functionElement; } /** * Define the parameters for the given function in the scope that encloses this function. - * - * @param functionElement the element representing the function represented by this scope */ - void defineParameters(ExecutableElement functionElement) { + void defineParameters() { + if (_parametersDefined) { + return; + } + _parametersDefined = true; Scope parameterScope = enclosingScope; - if (functionElement.enclosingElement is ExecutableElement) { - String name = functionElement.name; + if (_functionElement.enclosingElement is ExecutableElement) { + String name = _functionElement.name; if (name != null && !name.isEmpty) { - parameterScope.define(functionElement); + parameterScope.define(_functionElement); } } - for (ParameterElement parameter in functionElement.parameters) { + for (ParameterElement parameter in _functionElement.parameters) { if (!parameter.isInitializingFormal) { parameterScope.define(parameter); } @@ -10693,6 +10801,8 @@ * @coverage dart.engine.resolver */ class FunctionTypeScope extends EnclosedScope { + FunctionTypeAliasElement _typeElement; + bool _parametersDefined = false; /** * Initialize a newly created scope enclosed within another scope. @@ -10701,8 +10811,8 @@ * @param typeElement the element representing the type alias represented by this scope */ FunctionTypeScope(Scope enclosingScope, FunctionTypeAliasElement typeElement) : super(new EnclosedScope(enclosingScope)) { - defineTypeParameters(typeElement); - defineParameters(typeElement); + this._typeElement = typeElement; + defineTypeParameters(); } /** @@ -10710,8 +10820,12 @@ * * @param typeElement the element representing the type represented by this scope */ - void defineParameters(FunctionTypeAliasElement typeElement) { - for (ParameterElement parameter in typeElement.parameters) { + void defineParameters() { + if (_parametersDefined) { + return; + } + _parametersDefined = true; + for (ParameterElement parameter in _typeElement.parameters) { define(parameter); } } @@ -10721,9 +10835,9 @@ * * @param typeElement the element representing the type represented by this scope */ - void defineTypeParameters(FunctionTypeAliasElement typeElement) { + void defineTypeParameters() { Scope typeParameterScope = enclosingScope; - for (TypeParameterElement typeParameter in typeElement.typeParameters) { + for (TypeParameterElement typeParameter in _typeElement.typeParameters) { typeParameterScope.define(typeParameter); } } @@ -10884,7 +10998,7 @@ if (enclosingLibrary != null) { libName2 = enclosingLibrary.definingCompilationUnit.displayName; } - _errorListener.onError(new AnalysisError.con2(source2, identifier.offset, identifier.length, StaticWarningCode.AMBIGUOUS_IMPORT, [foundEltName, libName1, libName2])); + _errorListener.onError(new AnalysisError.con2(source, identifier.offset, identifier.length, StaticWarningCode.AMBIGUOUS_IMPORT, [foundEltName, libName1, libName2])); return foundElement; } if (foundElement != null) { @@ -10927,6 +11041,9 @@ return foundElement; } else if (to == 1) { return conflictingMembers[0]; + } else if (to == 0) { + AnalysisEngine.instance.logger.logInformation("Multiply defined SDK element: ${foundElement}"); + return foundElement; } List<Element> remaining = new List<Element>(to); JavaSystem.arraycopy(conflictingMembers, 0, remaining, 0, to); @@ -10959,7 +11076,7 @@ offset = accessor.variable.nameOffset; } } - return new AnalysisError.con2(source2, offset, duplicate.displayName.length, CompileTimeErrorCode.PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER, [existing.displayName]); + return new AnalysisError.con2(source, offset, duplicate.displayName.length, CompileTimeErrorCode.PREFIX_COLLIDES_WITH_TOP_LEVEL_MEMBER, [existing.displayName]); } return super.getErrorForDuplicate(existing, duplicate); } @@ -11129,9 +11246,9 @@ * @param definedNames the mapping table to which the names in the given namespace are to be added * @param namespace the namespace containing the names to be added to this namespace */ - void addAll2(Map<String, Element> definedNames2, Namespace namespace) { + void addAll2(Map<String, Element> definedNames, Namespace namespace) { if (namespace != null) { - addAll(definedNames2, namespace.definedNames); + addAll(definedNames, namespace.definedNames); } } @@ -11379,7 +11496,7 @@ AnalysisError getErrorForDuplicate(Element existing, Element duplicate) { Source source = duplicate.source; if (source == null) { - source = source2; + source = this.source; } return new AnalysisError.con2(source, duplicate.nameOffset, duplicate.displayName.length, CompileTimeErrorCode.DUPLICATE_DEFINITION, [existing.displayName]); } @@ -11397,7 +11514,7 @@ * * @return the source object with which errors should be associated */ - Source get source2 => definingLibrary.definingCompilationUnit.source; + Source get source => definingLibrary.definingCompilationUnit.source; /** * Return the element with which the given name is associated, or `null` if the name is not @@ -11602,14 +11719,14 @@ * @param result the result containing any errors that need to be reported * @param errorCode the error code to be used if the result represents an error */ - void reportErrors(EvaluationResultImpl result, ErrorCode errorCode2) { + void reportErrors(EvaluationResultImpl result, ErrorCode errorCode) { if (result is ErrorResult) { for (ErrorResult_ErrorData data in ((result as ErrorResult)).errorData) { ErrorCode dataErrorCode = data.errorCode; if (identical(dataErrorCode, CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION) || identical(dataErrorCode, CompileTimeErrorCode.CONST_EVAL_THROWS_IDBZE) || identical(dataErrorCode, CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING) || identical(dataErrorCode, CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL) || identical(dataErrorCode, CompileTimeErrorCode.CONST_EVAL_TYPE_INT) || identical(dataErrorCode, CompileTimeErrorCode.CONST_EVAL_TYPE_NUM)) { _errorReporter.reportError2(dataErrorCode, data.node, []); } else { - _errorReporter.reportError2(errorCode2, data.node, []); + _errorReporter.reportError2(errorCode, data.node, []); } } } @@ -11666,11 +11783,11 @@ * * @param parameters the list of parameters to be validated */ - void validateDefaultValues(FormalParameterList parameters2) { - if (parameters2 == null) { + void validateDefaultValues(FormalParameterList parameters) { + if (parameters == null) { return; } - for (FormalParameter parameter in parameters2.parameters) { + for (FormalParameter parameter in parameters.parameters) { if (parameter is DefaultFormalParameter) { DefaultFormalParameter defaultParameter = parameter as DefaultFormalParameter; Expression defaultValue = defaultParameter.defaultValue; @@ -12555,7 +12672,7 @@ * @see StaticWarningCode#INVALID_METHOD_OVERRIDE_NAMED_PARAM_TYPE * @see StaticWarningCode#INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES */ - bool checkForAllInvalidOverrideErrorCodes(ExecutableElement executableElement, List<ParameterElement> parameters2, List<ASTNode> parameterLocations, SimpleIdentifier errorNameTarget) { + bool checkForAllInvalidOverrideErrorCodes(ExecutableElement executableElement, List<ParameterElement> parameters, List<ASTNode> parameterLocations, SimpleIdentifier errorNameTarget) { String executableElementName = executableElement.name; ExecutableElement overriddenExecutable = _inheritanceManager.lookupInheritance(_enclosingClass, executableElementName); bool isGetter = false; @@ -12675,8 +12792,8 @@ if (!overriddenNamedPTEntry.getValue().isAssignableTo(overridingType)) { ParameterElement parameterToSelect = null; ASTNode parameterLocationToSelect = null; - for (int i = 0; i < parameters2.length; i++) { - ParameterElement parameter = parameters2[i]; + for (int i = 0; i < parameters.length; i++) { + ParameterElement parameter = parameters[i]; if (identical(parameter.parameterKind, ParameterKind.NAMED) && overriddenNamedPTEntry.getKey() == parameter.name) { parameterToSelect = parameter; parameterLocationToSelect = parameterLocations[i]; @@ -12697,8 +12814,8 @@ List<ParameterElementImpl> parameterElts = new List<ParameterElementImpl>(); List<ParameterElementImpl> overriddenParameterElts = new List<ParameterElementImpl>(); List<ParameterElement> overriddenPEs = overriddenExecutable.parameters; - for (int i = 0; i < parameters2.length; i++) { - ParameterElement parameter = parameters2[i]; + for (int i = 0; i < parameters.length; i++) { + ParameterElement parameter = parameters[i]; if (parameter.parameterKind.isOptional) { formalParameters.add(parameterLocations[i]); parameterElts.add(parameter as ParameterElementImpl); @@ -13250,11 +13367,11 @@ * @return `true` if and only if an error code is generated on the passed node * @see CompileTimeErrorCode#CASE_EXPRESSION_TYPE_IMPLEMENTS_EQUALS */ - bool checkForCaseExpressionTypeImplementsEquals(SwitchStatement node, Type2 type2) { - if (type2 == null || type2 == _typeProvider.intType || type2 == _typeProvider.stringType) { + bool checkForCaseExpressionTypeImplementsEquals(SwitchStatement node, Type2 type) { + if (type == null || type == _typeProvider.intType || type == _typeProvider.stringType) { return false; } - Element element = type2.element; + Element element = type.element; if (element is! ClassElement) { return false; } @@ -14258,14 +14375,14 @@ * @return `true` if and only if an error code is generated on the passed node * @see StaticTypeWarningCode#INSTANCE_ACCESS_TO_STATIC_MEMBER */ - bool checkForInstanceAccessToStaticMember(Expression target, SimpleIdentifier name2) { + bool checkForInstanceAccessToStaticMember(Expression target, SimpleIdentifier name) { if (target == null) { return false; } if (_isInComment) { return false; } - Element element = name2.staticElement; + Element element = name.staticElement; if (element is! ExecutableElement) { return false; } @@ -14279,7 +14396,7 @@ if (isTypeReference(target)) { return false; } - _errorReporter.reportError2(StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER, name2, [name2.name]); + _errorReporter.reportError2(StaticTypeWarningCode.INSTANCE_ACCESS_TO_STATIC_MEMBER, name, [name.name]); return true; } @@ -15274,8 +15391,8 @@ * @return `true` if and only if an error code is generated on the passed node * @see StaticWarningCode#STATIC_ACCESS_TO_INSTANCE_MEMBER */ - bool checkForStaticAccessToInstanceMember(Expression target, SimpleIdentifier name2) { - Element element = name2.staticElement; + bool checkForStaticAccessToInstanceMember(Expression target, SimpleIdentifier name) { + Element element = name.staticElement; if (element is! ExecutableElement) { return false; } @@ -15286,7 +15403,7 @@ if (!isTypeReference(target)) { return false; } - _errorReporter.reportError2(StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER, name2, [name2.name]); + _errorReporter.reportError2(StaticWarningCode.STATIC_ACCESS_TO_INSTANCE_MEMBER, name, [name.name]); return true; } @@ -15475,8 +15592,8 @@ * @return `true` if and only if an error code is generated on the passed node * @see StaticTypeWarningCode#UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER */ - bool checkForUnqualifiedReferenceToNonLocalStaticMember(SimpleIdentifier name2) { - Element element = name2.staticElement; + bool checkForUnqualifiedReferenceToNonLocalStaticMember(SimpleIdentifier name) { + Element element = name.staticElement; if (element == null || element is TypeParameterElement) { return false; } @@ -15490,7 +15607,7 @@ if (identical(enclosingElement, _enclosingClass)) { return false; } - _errorReporter.reportError2(StaticTypeWarningCode.UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER, name2, [name2.name]); + _errorReporter.reportError2(StaticTypeWarningCode.UNQUALIFIED_REFERENCE_TO_NON_LOCAL_STATIC_MEMBER, name, [name.name]); return true; }
diff --git a/pkg/analyzer_experimental/lib/src/generated/scanner.dart b/pkg/analyzer_experimental/lib/src/generated/scanner.dart index 67ffec0..7ee43be 100644 --- a/pkg/analyzer_experimental/lib/src/generated/scanner.dart +++ b/pkg/analyzer_experimental/lib/src/generated/scanner.dart
@@ -38,13 +38,13 @@ * @param length the number of strings in the array that pass through the state being built * @return the state that was created */ - static KeywordState computeKeywordStateTable(int start, List<String> strings, int offset, int length2) { + static KeywordState computeKeywordStateTable(int start, List<String> strings, int offset, int length) { List<KeywordState> result = new List<KeywordState>(26); - assert(length2 != 0); + assert(length != 0); int chunk = 0x0; int chunkStart = -1; bool isLeaf = false; - for (int i = offset; i < offset + length2; i++) { + for (int i = offset; i < offset + length; i++) { if (strings[i].length == start) { isLeaf = true; } @@ -61,9 +61,9 @@ } if (chunkStart != -1) { assert(result[chunk - 0x61] == null); - result[chunk - 0x61] = computeKeywordStateTable(start + 1, strings, chunkStart, offset + length2 - chunkStart); + result[chunk - 0x61] = computeKeywordStateTable(start + 1, strings, chunkStart, offset + length - chunkStart); } else { - assert(length2 == 1); + assert(length == 1); return new KeywordState(_EMPTY_TABLE, strings[offset]); } if (isLeaf) { @@ -544,12 +544,12 @@ _lastComment = _lastComment.setNext(new StringToken(type, value, _tokenStart)); } } - void appendEndToken(TokenType type2, TokenType beginType) { + void appendEndToken(TokenType type, TokenType beginType) { Token token; if (_firstComment == null) { - token = new Token(type2, _tokenStart); + token = new Token(type, _tokenStart); } else { - token = new TokenWithComment(type2, _tokenStart, _firstComment); + token = new TokenWithComment(type, _tokenStart, _firstComment); _firstComment = null; _lastComment = null; } @@ -643,8 +643,8 @@ return advance(); } if (next == 0x72) { - int peek2 = peek(); - if (peek2 == 0x22 || peek2 == 0x27) { + int peek = this.peek(); + if (peek == 0x22 || peek == 0x27) { int start = offset; return tokenizeString(advance(), start, true); } @@ -1017,23 +1017,23 @@ beginToken(); return next; } - int tokenizeKeywordOrIdentifier(int next2, bool allowDollar) { + int tokenizeKeywordOrIdentifier(int next, bool allowDollar) { KeywordState state = KeywordState.KEYWORD_STATE; int start = offset; - while (state != null && 0x61 <= next2 && next2 <= 0x7A) { - state = state.next(next2 as int); - next2 = advance(); + while (state != null && 0x61 <= next && next <= 0x7A) { + state = state.next(next as int); + next = advance(); } if (state == null || state.keyword() == null) { - return tokenizeIdentifier(next2, start, allowDollar); + return tokenizeIdentifier(next, start, allowDollar); } - if ((0x41 <= next2 && next2 <= 0x5A) || (0x30 <= next2 && next2 <= 0x39) || next2 == 0x5F || next2 == 0x24) { - return tokenizeIdentifier(next2, start, allowDollar); - } else if (next2 < 128) { + if ((0x41 <= next && next <= 0x5A) || (0x30 <= next && next <= 0x39) || next == 0x5F || next == 0x24) { + return tokenizeIdentifier(next, start, allowDollar); + } else if (next < 128) { appendKeywordToken(state.keyword()); - return next2; + return next; } else { - return tokenizeIdentifier(next2, start, allowDollar); + return tokenizeIdentifier(next, start, allowDollar); } } int tokenizeLessThan(int next) {
diff --git a/pkg/analyzer_experimental/lib/src/generated/sdk.dart b/pkg/analyzer_experimental/lib/src/generated/sdk.dart index 2accc54..234742f 100644 --- a/pkg/analyzer_experimental/lib/src/generated/sdk.dart +++ b/pkg/analyzer_experimental/lib/src/generated/sdk.dart
@@ -157,8 +157,8 @@ * * @param category the name of the category containing the library */ - void set category(String category2) { - this._category = category2; + void set category(String category) { + this._category = category; } /** @@ -173,8 +173,8 @@ * * @param documented `true` if the library is documented */ - void set documented(bool documented2) { - this._documented = documented2; + void set documented(bool documented) { + this._documented = documented; } /** @@ -182,8 +182,8 @@ * * @param implementation `true` if the library is an implementation library */ - void set implementation(bool implementation2) { - this._implementation = implementation2; + void set implementation(bool implementation) { + this._implementation = implementation; } /** @@ -192,8 +192,8 @@ * * @param path the path to the file defining the library */ - void set path(String path2) { - this._path = path2; + void set path(String path) { + this._path = path; } /**
diff --git a/pkg/analyzer_experimental/lib/src/services/formatter_impl.dart b/pkg/analyzer_experimental/lib/src/services/formatter_impl.dart index 032d5e7..6d3d7e9 100644 --- a/pkg/analyzer_experimental/lib/src/services/formatter_impl.dart +++ b/pkg/analyzer_experimental/lib/src/services/formatter_impl.dart
@@ -195,7 +195,9 @@ advance(); } - if (!isEOF(token2)) { + // TODO(pquitslund): consider a better way to notice trailing synthetics + if (!isEOF(token2) && + !(isCLOSE_CURLY_BRACKET(token2) && isEOF(token2.next))) { throw new FormatterException( 'Expected "EOF" but got "${token2}".'); } @@ -261,6 +263,11 @@ return true; } } + // Advance past synthetic { } tokens + if (isOPEN_CURLY_BRACKET(token2) || isCLOSE_CURLY_BRACKET(token2)) { + token2 = token2.next; + return checkTokens(); + } return false; } @@ -286,6 +293,14 @@ /// Test if this token is an INDEX token. bool isINDEX(Token token) => tokenIs(token, TokenType.INDEX); +/// Test if this token is a OPEN_CURLY_BRACKET token. +bool isOPEN_CURLY_BRACKET(Token token) => + tokenIs(token, TokenType.OPEN_CURLY_BRACKET); + +/// Test if this token is a CLOSE_CURLY_BRACKET token. +bool isCLOSE_CURLY_BRACKET(Token token) => + tokenIs(token, TokenType.CLOSE_CURLY_BRACKET); + /// Test if this token is a OPEN_SQUARE_BRACKET token. bool isOPEN_SQ_BRACKET(Token token) => tokenIs(token, TokenType.OPEN_SQUARE_BRACKET); @@ -294,8 +309,19 @@ bool isCLOSE_SQUARE_BRACKET(Token token) => tokenIs(token, TokenType.CLOSE_SQUARE_BRACKET); + /// An AST visitor that drives formatting heuristics. class SourceVisitor implements ASTVisitor { + + static final OPEN_CURLY = syntheticToken(TokenType.OPEN_CURLY_BRACKET, '{'); + static final CLOSE_CURLY = syntheticToken(TokenType.CLOSE_CURLY_BRACKET, '}'); + + static const SYNTH_OFFSET = -13; + + static StringToken syntheticToken(TokenType type, String value) => + new StringToken(type, value, SYNTH_OFFSET); + + static bool isSynthetic(Token token) => token.offset == SYNTH_OFFSET; /// The writer to which the source is to be written. final SourceWriter writer; @@ -308,6 +334,9 @@ /// A flag to indicate that a newline should be emitted before the next token. bool needsNewline = false; + + /// A counter for spaces that should be emitted preceding the next token. + int leadingSpaces = 0; /// Used for matching EOL comments final twoSlashes = new RegExp(r'//[^/]'); @@ -514,13 +543,41 @@ token(node.period); visit(node.name); visit(node.parameters); - token(node.separator /* = or : */, precededBy: space, followedBy: space); - visitNodes(node.initializers, separatedBy: commaSeperator); - visit(node.redirectedConstructor); + + // Check for redirects or initializer lists + if (node.separator != null) { + if (node.redirectedConstructor != null) { + visitConstructorRedirects(node); + } else { + visitConstructorInitializers(node); + } + } visitPrefixedBody(space, node.body); } + visitConstructorInitializers(ConstructorDeclaration node) { + newlines(); + indent(2); + token(node.separator /* : */); + space(); + for (var i = 0; i < node.initializers.length; i++) { + if (i > 0) { + comma(); + newlines(); + space(2); + } + node.initializers[i].accept(this); + } + unindent(2); + } + + visitConstructorRedirects(ConstructorDeclaration node) { + token(node.separator /* = */, precededBy: space, followedBy: space); + visitNodes(node.initializers, separatedBy: commaSeperator); + visit(node.redirectedConstructor); + } + visitConstructorFieldInitializer(ConstructorFieldInitializer node) { token(node.keyword); token(node.period); @@ -730,24 +787,26 @@ space(); visitNodes(node.hiddenNames, separatedBy: commaSeperator); } - + visitIfStatement(IfStatement node) { + var hasElse = node.elseStatement != null; token(node.ifKeyword); space(); token(node.leftParenthesis); visit(node.condition); token(node.rightParenthesis); space(); - visit(node.thenStatement); - //visitPrefixed(' else ', node.elseStatement); - if (node.elseStatement != null) { + if (hasElse) { + printAsBlock(node.thenStatement); space(); token(node.elseKeyword); space(); - visit(node.elseStatement); + printAsBlock(node.elseStatement); + } else { + visit(node.thenStatement); } } - + visitImplementsClause(ImplementsClause node) { token(node.keyword); space(); @@ -1226,6 +1285,13 @@ } } + emitSpaces() { + while (leadingSpaces > 0) { + writer.print(' '); + leadingSpaces--; + } + } + checkForSelectionUpdate(Token token) { // Cache the first token on or AFTER the selection offset if (preSelection != null && selection == null) { @@ -1233,7 +1299,8 @@ var overshot = token.offset - preSelection.offset; if (overshot >= 0) { //TODO(pquitslund): update length (may need truncating) - selection = new Selection(writer.toString().length - overshot, + selection = new Selection( + writer.toString().length + leadingSpaces - overshot, preSelection.length); } } @@ -1245,15 +1312,16 @@ } comma() { - append(','); + writer.print(','); } + /// Emit a non-breakable space. - space() { + space([n = 1]) { //TODO(pquitslund): replace with a proper space token - append(' '); + leadingSpaces+=n; } - + /// Emit a breakable space breakableSpace() { //Implement @@ -1262,21 +1330,40 @@ /// Append the given [string] to the source writer if it's non-null. append(String string) { if (string != null && !string.isEmpty) { + emitSpaces(); writer.print(string); } } /// Indent. - indent() { - writer.indent(); + indent([n = 1]) { + while (n-- > 0) { + writer.indent(); + } } - + /// Unindent - unindent() { - writer.unindent(); + unindent([n = 1]) { + while (n-- > 0) { + writer.unindent(); + } } - - + + /// Print this statement as if it were a block (e.g., surrounded by braces). + printAsBlock(Statement statement) { + if (statement is! Block) { + token(OPEN_CURLY); + indent(); + newlines(); + visit(statement); + newlines(); + unindent(); + token(CLOSE_CURLY); + } else { + visit(statement); + } + } + /// Emit any detected comments and newlines or a minimum as specified /// by [min]. int emitPrecedingCommentsAndNewlines(Token token, {min: 0}) { @@ -1294,7 +1381,7 @@ var lines = max(min, countNewlinesBetween(previousToken, currentToken)); writer.newlines(lines); - var previousToken = currentToken.previous; + previousToken = currentToken.previous; while (comment != null) { @@ -1306,7 +1393,7 @@ writer.newlines(newlines); lines += newlines; } else if (!isEOF(token)) { - space(); + append(' '); } previousToken = comment; @@ -1336,7 +1423,7 @@ var ws = countSpacesBetween(previousToken, comment); // Preserve one space but no more if (ws > 0) { - space(); + append(' '); } } @@ -1361,7 +1448,7 @@ /// Count the blanks between these two tokens. int countNewlinesBetween(Token last, Token current) { - if (last == null || current == null) { + if (last == null || current == null || isSynthetic(last)) { return 0; }
diff --git a/pkg/analyzer_experimental/test/generated/ast_test.dart b/pkg/analyzer_experimental/test/generated/ast_test.dart index 36380ec..0c07d4c 100644 --- a/pkg/analyzer_experimental/test/generated/ast_test.dart +++ b/pkg/analyzer_experimental/test/generated/ast_test.dart
@@ -262,7 +262,7 @@ static CompilationUnit compilationUnit5(String scriptTag) => compilationUnit8(scriptTag, null, null); static CompilationUnit compilationUnit6(String scriptTag, List<CompilationUnitMember> declarations) => compilationUnit8(scriptTag, null, list(declarations)); static CompilationUnit compilationUnit7(String scriptTag, List<Directive> directives) => compilationUnit8(scriptTag, list(directives), null); - static CompilationUnit compilationUnit8(String scriptTag2, List<Directive> directives, List<CompilationUnitMember> declarations) => new CompilationUnit.full(TokenFactory.token3(TokenType.EOF), scriptTag2 == null ? null : scriptTag(scriptTag2), directives == null ? new List<Directive>() : directives, declarations == null ? new List<CompilationUnitMember>() : declarations, TokenFactory.token3(TokenType.EOF)); + static CompilationUnit compilationUnit8(String scriptTag, List<Directive> directives, List<CompilationUnitMember> declarations) => new CompilationUnit.full(TokenFactory.token3(TokenType.EOF), scriptTag == null ? null : ASTFactory.scriptTag(scriptTag), directives == null ? new List<Directive>() : directives, declarations == null ? new List<CompilationUnitMember>() : declarations, TokenFactory.token3(TokenType.EOF)); static ConditionalExpression conditionalExpression(Expression condition, Expression thenExpression, Expression elseExpression) => new ConditionalExpression.full(condition, TokenFactory.token3(TokenType.QUESTION), thenExpression, TokenFactory.token3(TokenType.COLON), elseExpression); static ConstructorDeclaration constructorDeclaration(Identifier returnType, String name, FormalParameterList parameters, List<ConstructorInitializer> initializers) => new ConstructorDeclaration.full(null, null, TokenFactory.token(Keyword.EXTERNAL), null, null, returnType, name == null ? null : TokenFactory.token3(TokenType.PERIOD), name == null ? null : identifier3(name), parameters, initializers == null || initializers.isEmpty ? null : TokenFactory.token3(TokenType.PERIOD), initializers == null ? new List<ConstructorInitializer>() : initializers, null, emptyFunctionBody()); static ConstructorDeclaration constructorDeclaration2(Keyword constKeyword, Keyword factoryKeyword, Identifier returnType, String name, FormalParameterList parameters, List<ConstructorInitializer> initializers, FunctionBody body) => new ConstructorDeclaration.full(null, null, null, constKeyword == null ? null : TokenFactory.token(constKeyword), factoryKeyword == null ? null : TokenFactory.token(factoryKeyword), returnType, name == null ? null : TokenFactory.token3(TokenType.PERIOD), name == null ? null : identifier3(name), parameters, initializers == null || initializers.isEmpty ? null : TokenFactory.token3(TokenType.PERIOD), initializers == null ? new List<ConstructorInitializer>() : initializers, null, body); @@ -306,7 +306,7 @@ } return new HideCombinator.full(TokenFactory.token2("hide"), identifierList); } - static PrefixedIdentifier identifier(SimpleIdentifier prefix, SimpleIdentifier identifier2) => new PrefixedIdentifier.full(prefix, TokenFactory.token3(TokenType.PERIOD), identifier2); + static PrefixedIdentifier identifier(SimpleIdentifier prefix, SimpleIdentifier identifier) => new PrefixedIdentifier.full(prefix, TokenFactory.token3(TokenType.PERIOD), identifier); static SimpleIdentifier identifier3(String lexeme) => new SimpleIdentifier.full(TokenFactory.token4(TokenType.IDENTIFIER, lexeme)); static PrefixedIdentifier identifier4(String prefix, SimpleIdentifier identifier) => new PrefixedIdentifier.full(identifier3(prefix), TokenFactory.token3(TokenType.PERIOD), identifier); static PrefixedIdentifier identifier5(String prefix, String identifier) => new PrefixedIdentifier.full(identifier3(prefix), TokenFactory.token3(TokenType.PERIOD), identifier3(identifier)); @@ -324,8 +324,8 @@ static InterpolationExpression interpolationExpression2(String identifier) => new InterpolationExpression.full(TokenFactory.token3(TokenType.STRING_INTERPOLATION_IDENTIFIER), identifier3(identifier), null); static InterpolationString interpolationString(String contents, String value) => new InterpolationString.full(TokenFactory.token2(contents), value); static IsExpression isExpression(Expression expression, bool negated, TypeName type) => new IsExpression.full(expression, TokenFactory.token(Keyword.IS), negated ? TokenFactory.token3(TokenType.BANG) : null, type); - static Label label(SimpleIdentifier label2) => new Label.full(label2, TokenFactory.token3(TokenType.COLON)); - static Label label2(String label22) => label(identifier3(label22)); + static Label label(SimpleIdentifier label) => new Label.full(label, TokenFactory.token3(TokenType.COLON)); + static Label label2(String label) => ASTFactory.label(identifier3(label)); static LabeledStatement labeledStatement(List<Label> labels, Statement statement) => new LabeledStatement.full(labels, statement); static LibraryDirective libraryDirective(List<Annotation> metadata, LibraryIdentifier libraryName) => new LibraryDirective.full(null, metadata, TokenFactory.token(Keyword.LIBRARY), libraryName, TokenFactory.token3(TokenType.SEMICOLON)); static LibraryDirective libraryDirective2(String libraryName) => libraryDirective(new List<Annotation>(), libraryIdentifier2([libraryName])); @@ -374,7 +374,7 @@ static RethrowExpression rethrowExpression() => new RethrowExpression.full(TokenFactory.token(Keyword.RETHROW)); static ReturnStatement returnStatement() => returnStatement2(null); static ReturnStatement returnStatement2(Expression expression) => new ReturnStatement.full(TokenFactory.token(Keyword.RETURN), expression, TokenFactory.token3(TokenType.SEMICOLON)); - static ScriptTag scriptTag(String scriptTag2) => new ScriptTag.full(TokenFactory.token2(scriptTag2)); + static ScriptTag scriptTag(String scriptTag) => new ScriptTag.full(TokenFactory.token2(scriptTag)); static ShowCombinator showCombinator(List<SimpleIdentifier> identifiers) => new ShowCombinator.full(TokenFactory.token2("show"), list(identifiers)); static ShowCombinator showCombinator2(List<String> identifiers) { List<SimpleIdentifier> identifierList = new List<SimpleIdentifier>(); @@ -1420,7 +1420,7 @@ assertSource("library l;", ASTFactory.compilationUnit3([ASTFactory.libraryDirective2("l")])); } void test_visitCompilationUnit_directive_declaration() { - assertSource("library l; var a;", ASTFactory.compilationUnit4(ASTFactory.list([(ASTFactory.libraryDirective2("l") as Directive)]), ASTFactory.list([(ASTFactory.topLevelVariableDeclaration2(Keyword.VAR, [ASTFactory.variableDeclaration("a")]) as CompilationUnitMember)]))); + assertSource("library l; var a;", ASTFactory.compilationUnit4(ASTFactory.list([ASTFactory.libraryDirective2("l") as Directive]), ASTFactory.list([ASTFactory.topLevelVariableDeclaration2(Keyword.VAR, [ASTFactory.variableDeclaration("a")]) as CompilationUnitMember]))); } void test_visitCompilationUnit_empty() { assertSource("", ASTFactory.compilationUnit()); @@ -1435,7 +1435,7 @@ assertSource("!#/bin/dartvm library l;", ASTFactory.compilationUnit7("!#/bin/dartvm", [ASTFactory.libraryDirective2("l")])); } void test_visitCompilationUnit_script_directives_declarations() { - assertSource("!#/bin/dartvm library l; var a;", ASTFactory.compilationUnit8("!#/bin/dartvm", ASTFactory.list([(ASTFactory.libraryDirective2("l") as Directive)]), ASTFactory.list([(ASTFactory.topLevelVariableDeclaration2(Keyword.VAR, [ASTFactory.variableDeclaration("a")]) as CompilationUnitMember)]))); + assertSource("!#/bin/dartvm library l; var a;", ASTFactory.compilationUnit8("!#/bin/dartvm", ASTFactory.list([ASTFactory.libraryDirective2("l") as Directive]), ASTFactory.list([ASTFactory.topLevelVariableDeclaration2(Keyword.VAR, [ASTFactory.variableDeclaration("a")]) as CompilationUnitMember]))); } void test_visitConditionalExpression() { assertSource("a ? b : c", ASTFactory.conditionalExpression(ASTFactory.identifier3("a"), ASTFactory.identifier3("b"), ASTFactory.identifier3("c"))); @@ -1451,7 +1451,7 @@ } void test_visitConstructorDeclaration_multipleInitializers() { assertSource("C() : a = b, c = d {}", ASTFactory.constructorDeclaration2(null, null, ASTFactory.identifier3("C"), null, ASTFactory.formalParameterList([]), ASTFactory.list([ - (ASTFactory.constructorFieldInitializer(false, "a", ASTFactory.identifier3("b")) as ConstructorInitializer), + ASTFactory.constructorFieldInitializer(false, "a", ASTFactory.identifier3("b")) as ConstructorInitializer, ASTFactory.constructorFieldInitializer(false, "c", ASTFactory.identifier3("d"))]), ASTFactory.blockFunctionBody2([]))); } void test_visitConstructorDeclaration_multipleParameters() { @@ -1463,7 +1463,7 @@ assertSource("C.m() {}", ASTFactory.constructorDeclaration2(null, null, ASTFactory.identifier3("C"), "m", ASTFactory.formalParameterList([]), null, ASTFactory.blockFunctionBody2([]))); } void test_visitConstructorDeclaration_singleInitializer() { - assertSource("C() : a = b {}", ASTFactory.constructorDeclaration2(null, null, ASTFactory.identifier3("C"), null, ASTFactory.formalParameterList([]), ASTFactory.list([(ASTFactory.constructorFieldInitializer(false, "a", ASTFactory.identifier3("b")) as ConstructorInitializer)]), ASTFactory.blockFunctionBody2([]))); + assertSource("C() : a = b {}", ASTFactory.constructorDeclaration2(null, null, ASTFactory.identifier3("C"), null, ASTFactory.formalParameterList([]), ASTFactory.list([ASTFactory.constructorFieldInitializer(false, "a", ASTFactory.identifier3("b")) as ConstructorInitializer]), ASTFactory.blockFunctionBody2([]))); } void test_visitConstructorFieldInitializer_withoutThis() { assertSource("a = b", ASTFactory.constructorFieldInitializer(false, "a", ASTFactory.identifier3("b"))); @@ -1511,7 +1511,7 @@ assertSource(";", ASTFactory.emptyStatement()); } void test_visitExportDirective_combinator() { - assertSource("export 'a.dart' show A;", ASTFactory.exportDirective2("a.dart", [(ASTFactory.showCombinator([ASTFactory.identifier3("A")]) as Combinator)])); + assertSource("export 'a.dart' show A;", ASTFactory.exportDirective2("a.dart", [ASTFactory.showCombinator([ASTFactory.identifier3("A")]) as Combinator])); } void test_visitExportDirective_combinators() { assertSource("export 'a.dart' show A hide B;", ASTFactory.exportDirective2("a.dart", [ @@ -1630,7 +1630,7 @@ assertSource("for (; c;) {}", ASTFactory.forStatement(null as Expression, ASTFactory.identifier3("c"), null, ASTFactory.block([]))); } void test_visitForStatement_cu() { - assertSource("for (; c; u) {}", ASTFactory.forStatement(null as Expression, ASTFactory.identifier3("c"), ASTFactory.list([(ASTFactory.identifier3("u") as Expression)]), ASTFactory.block([]))); + assertSource("for (; c; u) {}", ASTFactory.forStatement(null as Expression, ASTFactory.identifier3("c"), ASTFactory.list([ASTFactory.identifier3("u") as Expression]), ASTFactory.block([]))); } void test_visitForStatement_e() { assertSource("for (e;;) {}", ASTFactory.forStatement(ASTFactory.identifier3("e"), null, null, ASTFactory.block([]))); @@ -1639,10 +1639,10 @@ assertSource("for (e; c;) {}", ASTFactory.forStatement(ASTFactory.identifier3("e"), ASTFactory.identifier3("c"), null, ASTFactory.block([]))); } void test_visitForStatement_ecu() { - assertSource("for (e; c; u) {}", ASTFactory.forStatement(ASTFactory.identifier3("e"), ASTFactory.identifier3("c"), ASTFactory.list([(ASTFactory.identifier3("u") as Expression)]), ASTFactory.block([]))); + assertSource("for (e; c; u) {}", ASTFactory.forStatement(ASTFactory.identifier3("e"), ASTFactory.identifier3("c"), ASTFactory.list([ASTFactory.identifier3("u") as Expression]), ASTFactory.block([]))); } void test_visitForStatement_eu() { - assertSource("for (e;; u) {}", ASTFactory.forStatement(ASTFactory.identifier3("e"), null, ASTFactory.list([(ASTFactory.identifier3("u") as Expression)]), ASTFactory.block([]))); + assertSource("for (e;; u) {}", ASTFactory.forStatement(ASTFactory.identifier3("e"), null, ASTFactory.list([ASTFactory.identifier3("u") as Expression]), ASTFactory.block([]))); } void test_visitForStatement_i() { assertSource("for (var i;;) {}", ASTFactory.forStatement2(ASTFactory.variableDeclarationList2(Keyword.VAR, [ASTFactory.variableDeclaration("i")]), null, null, ASTFactory.block([]))); @@ -1651,13 +1651,13 @@ assertSource("for (var i; c;) {}", ASTFactory.forStatement2(ASTFactory.variableDeclarationList2(Keyword.VAR, [ASTFactory.variableDeclaration("i")]), ASTFactory.identifier3("c"), null, ASTFactory.block([]))); } void test_visitForStatement_icu() { - assertSource("for (var i; c; u) {}", ASTFactory.forStatement2(ASTFactory.variableDeclarationList2(Keyword.VAR, [ASTFactory.variableDeclaration("i")]), ASTFactory.identifier3("c"), ASTFactory.list([(ASTFactory.identifier3("u") as Expression)]), ASTFactory.block([]))); + assertSource("for (var i; c; u) {}", ASTFactory.forStatement2(ASTFactory.variableDeclarationList2(Keyword.VAR, [ASTFactory.variableDeclaration("i")]), ASTFactory.identifier3("c"), ASTFactory.list([ASTFactory.identifier3("u") as Expression]), ASTFactory.block([]))); } void test_visitForStatement_iu() { - assertSource("for (var i;; u) {}", ASTFactory.forStatement2(ASTFactory.variableDeclarationList2(Keyword.VAR, [ASTFactory.variableDeclaration("i")]), null, ASTFactory.list([(ASTFactory.identifier3("u") as Expression)]), ASTFactory.block([]))); + assertSource("for (var i;; u) {}", ASTFactory.forStatement2(ASTFactory.variableDeclarationList2(Keyword.VAR, [ASTFactory.variableDeclaration("i")]), null, ASTFactory.list([ASTFactory.identifier3("u") as Expression]), ASTFactory.block([]))); } void test_visitForStatement_u() { - assertSource("for (;; u) {}", ASTFactory.forStatement(null as Expression, null, ASTFactory.list([(ASTFactory.identifier3("u") as Expression)]), ASTFactory.block([]))); + assertSource("for (;; u) {}", ASTFactory.forStatement(null as Expression, null, ASTFactory.list([ASTFactory.identifier3("u") as Expression]), ASTFactory.block([]))); } void test_visitFunctionDeclaration_getter() { assertSource("get f() {}", ASTFactory.functionDeclaration(null, Keyword.GET, "f", ASTFactory.functionExpression()));
diff --git a/pkg/analyzer_experimental/test/generated/element_test.dart b/pkg/analyzer_experimental/test/generated/element_test.dart index d2571ca..954592e 100644 --- a/pkg/analyzer_experimental/test/generated/element_test.dart +++ b/pkg/analyzer_experimental/test/generated/element_test.dart
@@ -1716,24 +1716,24 @@ constructor.type = constructorType; return constructor; } - static ExportElementImpl exportFor(LibraryElement exportedLibrary2, List<NamespaceCombinator> combinators2) { + static ExportElementImpl exportFor(LibraryElement exportedLibrary, List<NamespaceCombinator> combinators) { ExportElementImpl spec = new ExportElementImpl(); - spec.exportedLibrary = exportedLibrary2; - spec.combinators = combinators2; + spec.exportedLibrary = exportedLibrary; + spec.combinators = combinators; return spec; } - static FieldElementImpl fieldElement(String name, bool isStatic, bool isFinal, bool isConst, Type2 type2) { + static FieldElementImpl fieldElement(String name, bool isStatic, bool isFinal, bool isConst, Type2 type) { FieldElementImpl field = new FieldElementImpl.con1(ASTFactory.identifier3(name)); field.const3 = isConst; field.final2 = isFinal; field.static = isStatic; - field.type = type2; + field.type = type; PropertyAccessorElementImpl getter = new PropertyAccessorElementImpl.con2(field); getter.getter = true; getter.static = isStatic; getter.synthetic = true; getter.variable = field; - getter.returnType = type2; + getter.returnType = type; field.getter = getter; FunctionTypeImpl getterType = new FunctionTypeImpl.con1(getter); getter.type = getterType; @@ -1743,7 +1743,7 @@ setter.static = isStatic; setter.synthetic = true; setter.variable = field; - setter.parameters = <ParameterElement> [requiredParameter2("_${name}", type2)]; + setter.parameters = <ParameterElement> [requiredParameter2("_${name}", type)]; setter.returnType = VoidTypeImpl.instance; setter.type = new FunctionTypeImpl.con1(setter); field.setter = setter; @@ -1822,26 +1822,26 @@ } return _objectElement; } - static PropertyAccessorElementImpl getterElement(String name, bool isStatic, Type2 type2) { + static PropertyAccessorElementImpl getterElement(String name, bool isStatic, Type2 type) { FieldElementImpl field = new FieldElementImpl.con1(ASTFactory.identifier3(name)); field.static = isStatic; field.synthetic = true; - field.type = type2; + field.type = type; PropertyAccessorElementImpl getter = new PropertyAccessorElementImpl.con2(field); getter.getter = true; getter.static = isStatic; getter.variable = field; - getter.returnType = type2; + getter.returnType = type; field.getter = getter; FunctionTypeImpl getterType = new FunctionTypeImpl.con1(getter); getter.type = getterType; return getter; } - static ImportElementImpl importFor(LibraryElement importedLibrary2, PrefixElement prefix2, List<NamespaceCombinator> combinators2) { + static ImportElementImpl importFor(LibraryElement importedLibrary, PrefixElement prefix, List<NamespaceCombinator> combinators) { ImportElementImpl spec = new ImportElementImpl(); - spec.importedLibrary = importedLibrary2; - spec.prefix = prefix2; - spec.combinators = combinators2; + spec.importedLibrary = importedLibrary; + spec.prefix = prefix; + spec.combinators = combinators; return spec; } static LibraryElementImpl library(AnalysisContext context, String libraryName) { @@ -1855,7 +1855,7 @@ } static LocalVariableElementImpl localVariableElement(Identifier name) => new LocalVariableElementImpl(name); static LocalVariableElementImpl localVariableElement2(String name) => new LocalVariableElementImpl(ASTFactory.identifier3(name)); - static MethodElementImpl methodElement(String methodName, Type2 returnType2, List<Type2> argumentTypes) { + static MethodElementImpl methodElement(String methodName, Type2 returnType, List<Type2> argumentTypes) { MethodElementImpl method = new MethodElementImpl.con1(ASTFactory.identifier3(methodName)); int count = argumentTypes.length; List<ParameterElement> parameters = new List<ParameterElement>(count); @@ -1866,7 +1866,7 @@ parameters[i] = parameter; } method.parameters = parameters; - method.returnType = returnType2; + method.returnType = returnType; FunctionTypeImpl methodType = new FunctionTypeImpl.con1(method); method.type = methodType; return method; @@ -1876,10 +1876,10 @@ parameter.parameterKind = ParameterKind.NAMED; return parameter; } - static ParameterElementImpl namedParameter2(String name, Type2 type2) { + static ParameterElementImpl namedParameter2(String name, Type2 type) { ParameterElementImpl parameter = new ParameterElementImpl.con1(ASTFactory.identifier3(name)); parameter.parameterKind = ParameterKind.NAMED; - parameter.type = type2; + parameter.type = type; return parameter; } static ParameterElementImpl positionalParameter(String name) { @@ -1887,10 +1887,10 @@ parameter.parameterKind = ParameterKind.POSITIONAL; return parameter; } - static ParameterElementImpl positionalParameter2(String name, Type2 type2) { + static ParameterElementImpl positionalParameter2(String name, Type2 type) { ParameterElementImpl parameter = new ParameterElementImpl.con1(ASTFactory.identifier3(name)); parameter.parameterKind = ParameterKind.POSITIONAL; - parameter.type = type2; + parameter.type = type; return parameter; } static PrefixElementImpl prefix(String name) => new PrefixElementImpl(ASTFactory.identifier3(name)); @@ -1899,26 +1899,26 @@ parameter.parameterKind = ParameterKind.REQUIRED; return parameter; } - static ParameterElementImpl requiredParameter2(String name, Type2 type2) { + static ParameterElementImpl requiredParameter2(String name, Type2 type) { ParameterElementImpl parameter = new ParameterElementImpl.con1(ASTFactory.identifier3(name)); parameter.parameterKind = ParameterKind.REQUIRED; - parameter.type = type2; + parameter.type = type; return parameter; } - static PropertyAccessorElementImpl setterElement(String name, bool isStatic, Type2 type2) { + static PropertyAccessorElementImpl setterElement(String name, bool isStatic, Type2 type) { FieldElementImpl field = new FieldElementImpl.con1(ASTFactory.identifier3(name)); field.static = isStatic; field.synthetic = true; - field.type = type2; + field.type = type; PropertyAccessorElementImpl getter = new PropertyAccessorElementImpl.con2(field); getter.getter = true; getter.static = isStatic; getter.variable = field; - getter.returnType = type2; + getter.returnType = type; field.getter = getter; FunctionTypeImpl getterType = new FunctionTypeImpl.con1(getter); getter.type = getterType; - ParameterElementImpl parameter = requiredParameter2("a", type2); + ParameterElementImpl parameter = requiredParameter2("a", type); PropertyAccessorElementImpl setter = new PropertyAccessorElementImpl.con2(field); setter.setter = true; setter.static = isStatic; @@ -1932,7 +1932,7 @@ } static TopLevelVariableElementImpl topLevelVariableElement(Identifier name) => new TopLevelVariableElementImpl.con1(name); static TopLevelVariableElementImpl topLevelVariableElement2(String name) => new TopLevelVariableElementImpl.con2(name); - static TopLevelVariableElementImpl topLevelVariableElement3(String name, bool isFinal, Type2 type2) { + static TopLevelVariableElementImpl topLevelVariableElement3(String name, bool isFinal, Type2 type) { TopLevelVariableElementImpl variable = new TopLevelVariableElementImpl.con2(name); variable.final2 = isFinal; PropertyAccessorElementImpl getter = new PropertyAccessorElementImpl.con2(variable); @@ -1940,7 +1940,7 @@ getter.static = true; getter.synthetic = true; getter.variable = variable; - getter.returnType = type2; + getter.returnType = type; variable.getter = getter; FunctionTypeImpl getterType = new FunctionTypeImpl.con1(getter); getter.type = getterType; @@ -1950,7 +1950,7 @@ setter.static = true; setter.synthetic = true; setter.variable = variable; - setter.parameters = <ParameterElement> [requiredParameter2("_${name}", type2)]; + setter.parameters = <ParameterElement> [requiredParameter2("_${name}", type)]; setter.returnType = VoidTypeImpl.instance; setter.type = new FunctionTypeImpl.con1(setter); variable.setter = setter;
diff --git a/pkg/analyzer_experimental/test/generated/resolver_test.dart b/pkg/analyzer_experimental/test/generated/resolver_test.dart index 0e21d4b..6229a06 100644 --- a/pkg/analyzer_experimental/test/generated/resolver_test.dart +++ b/pkg/analyzer_experimental/test/generated/resolver_test.dart
@@ -1290,6 +1290,16 @@ assertNoErrors(source); verify([source]); } + void test_constructorDeclaration_scope_signature() { + Source source = addSource(EngineTestCase.createSource([ + "const app = 0;", + "class A {", + " A(@app int app) {}", + "}"])); + resolve(source); + assertNoErrors(source); + verify([source]); + } void test_constWithNonConstantArgument_literals() { Source source = addSource(EngineTestCase.createSource([ "class A {", @@ -1533,6 +1543,30 @@ assertNoErrors(source); verify([source]); } + void test_functionDeclaration_scope_returnType() { + Source source = addSource(EngineTestCase.createSource(["int f(int) {}"])); + resolve(source); + assertNoErrors(source); + verify([source]); + } + void test_functionDeclaration_scope_signature() { + Source source = addSource(EngineTestCase.createSource(["const app = 0;", "f(@app int app) {}"])); + resolve(source); + assertNoErrors(source); + verify([source]); + } + void test_functionTypeAlias_scope_returnType() { + Source source = addSource(EngineTestCase.createSource(["typedef int f(int);"])); + resolve(source); + assertNoErrors(source); + verify([source]); + } + void test_functionTypeAlias_scope_signature() { + Source source = addSource(EngineTestCase.createSource(["const app = 0;", "typedef int f(@app int app);"])); + resolve(source); + assertNoErrors(source); + verify([source]); + } void test_implicitThisReferenceInInitializer_constructorName() { Source source = addSource(EngineTestCase.createSource([ "class A {", @@ -1684,6 +1718,21 @@ assertNoErrors(source); verify([source]); } + void test_importPrefixes_withFirstLetterDifference() { + Source source = addSource(EngineTestCase.createSource([ + "library L;", + "import 'lib1.dart' as math;", + "import 'lib2.dart' as path;", + "main() {", + " math.test1();", + " path.test2();", + "}"])); + addSource2("/lib1.dart", EngineTestCase.createSource(["library lib1;", "test1() {}"])); + addSource2("/lib2.dart", EngineTestCase.createSource(["library lib2;", "test2() {}"])); + resolve(source); + assertNoErrors(source); + verify([source]); + } void test_inconsistentCaseExpressionTypes() { Source source = addSource(EngineTestCase.createSource([ "f(var p) {", @@ -2204,6 +2253,16 @@ assertNoErrors(source); verify([source]); } + void test_methodDeclaration_scope_signature() { + Source source = addSource(EngineTestCase.createSource([ + "const app = 0;", + "class A {", + " foo(@app int app) {}", + "}"])); + resolve(source); + assertNoErrors(source); + verify([source]); + } void test_misMatchedGetterAndSetterTypes_instance_sameTypes() { Source source = addSource(EngineTestCase.createSource([ "class C {", @@ -3452,6 +3511,10 @@ final __test = new NonErrorResolverTest(); runJUnitTest(__test, __test.test_constWithUndefinedConstructorDefault); }); + _ut.test('test_constructorDeclaration_scope_signature', () { + final __test = new NonErrorResolverTest(); + runJUnitTest(__test, __test.test_constructorDeclaration_scope_signature); + }); _ut.test('test_defaultValueInFunctionTypeAlias', () { final __test = new NonErrorResolverTest(); runJUnitTest(__test, __test.test_defaultValueInFunctionTypeAlias); @@ -3560,6 +3623,22 @@ final __test = new NonErrorResolverTest(); runJUnitTest(__test, __test.test_finalNotInitialized_redirectingConstructor); }); + _ut.test('test_functionDeclaration_scope_returnType', () { + final __test = new NonErrorResolverTest(); + runJUnitTest(__test, __test.test_functionDeclaration_scope_returnType); + }); + _ut.test('test_functionDeclaration_scope_signature', () { + final __test = new NonErrorResolverTest(); + runJUnitTest(__test, __test.test_functionDeclaration_scope_signature); + }); + _ut.test('test_functionTypeAlias_scope_returnType', () { + final __test = new NonErrorResolverTest(); + runJUnitTest(__test, __test.test_functionTypeAlias_scope_returnType); + }); + _ut.test('test_functionTypeAlias_scope_signature', () { + final __test = new NonErrorResolverTest(); + runJUnitTest(__test, __test.test_functionTypeAlias_scope_signature); + }); _ut.test('test_implicitThisReferenceInInitializer_constructorName', () { final __test = new NonErrorResolverTest(); runJUnitTest(__test, __test.test_implicitThisReferenceInInitializer_constructorName); @@ -3616,6 +3695,10 @@ final __test = new NonErrorResolverTest(); runJUnitTest(__test, __test.test_importOfNonLibrary_libraryNotDeclared); }); + _ut.test('test_importPrefixes_withFirstLetterDifference', () { + final __test = new NonErrorResolverTest(); + runJUnitTest(__test, __test.test_importPrefixes_withFirstLetterDifference); + }); _ut.test('test_inconsistentCaseExpressionTypes', () { final __test = new NonErrorResolverTest(); runJUnitTest(__test, __test.test_inconsistentCaseExpressionTypes); @@ -3812,6 +3895,10 @@ final __test = new NonErrorResolverTest(); runJUnitTest(__test, __test.test_memberWithClassName_setter); }); + _ut.test('test_methodDeclaration_scope_signature', () { + final __test = new NonErrorResolverTest(); + runJUnitTest(__test, __test.test_methodDeclaration_scope_signature); + }); _ut.test('test_misMatchedGetterAndSetterTypes_instance_sameTypes', () { final __test = new NonErrorResolverTest(); runJUnitTest(__test, __test.test_misMatchedGetterAndSetterTypes_instance_sameTypes); @@ -4906,6 +4993,18 @@ resolve(source); assertErrors(source, [StaticTypeWarningCode.UNDEFINED_METHOD]); } + void test_undefinedMethod_assignmentExpression() { + Source source = addSource(EngineTestCase.createSource([ + "class A {}", + "class B {", + " f(A a) {", + " A a2 = new A();", + " a += a2;", + " }", + "}"])); + resolve(source); + assertErrors(source, [StaticTypeWarningCode.UNDEFINED_METHOD]); + } void test_undefinedMethod_ignoreTypePropagation() { Source source = addSource(EngineTestCase.createSource([ "class A {}", @@ -4913,7 +5012,7 @@ " m() {}", "}", "class C {", - "f() {", + " f() {", " A a = new B();", " a.m();", " }", @@ -4943,6 +5042,16 @@ resolve(source); assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]); } + void test_undefinedOperator_postfixExpression() { + Source source = addSource(EngineTestCase.createSource(["class A {}", "f(A a) {", " a++;", "}"])); + resolve(source); + assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]); + } + void test_undefinedOperator_prefixExpression() { + Source source = addSource(EngineTestCase.createSource(["class A {}", "f(A a) {", " ++a;", "}"])); + resolve(source); + assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]); + } void test_undefinedSetter() { Source source = addSource(EngineTestCase.createSource(["class T {}", "f(T e1) { e1.m = 0; }"])); resolve(source); @@ -5280,6 +5389,10 @@ final __test = new StaticTypeWarningCodeTest(); runJUnitTest(__test, __test.test_undefinedMethod); }); + _ut.test('test_undefinedMethod_assignmentExpression', () { + final __test = new StaticTypeWarningCodeTest(); + runJUnitTest(__test, __test.test_undefinedMethod_assignmentExpression); + }); _ut.test('test_undefinedMethod_ignoreTypePropagation', () { final __test = new StaticTypeWarningCodeTest(); runJUnitTest(__test, __test.test_undefinedMethod_ignoreTypePropagation); @@ -5300,6 +5413,14 @@ final __test = new StaticTypeWarningCodeTest(); runJUnitTest(__test, __test.test_undefinedOperator_plus); }); + _ut.test('test_undefinedOperator_postfixExpression', () { + final __test = new StaticTypeWarningCodeTest(); + runJUnitTest(__test, __test.test_undefinedOperator_postfixExpression); + }); + _ut.test('test_undefinedOperator_prefixExpression', () { + final __test = new StaticTypeWarningCodeTest(); + runJUnitTest(__test, __test.test_undefinedOperator_prefixExpression); + }); _ut.test('test_undefinedSetter', () { final __test = new StaticTypeWarningCodeTest(); runJUnitTest(__test, __test.test_undefinedSetter); @@ -5705,6 +5826,122 @@ assertErrors(source, [HintCode.TYPE_CHECK_IS_NOT_NULL]); verify([source]); } + void test_undefinedGetter() { + Source source = addSource(EngineTestCase.createSource([ + "class A {}", + "f(var a) {", + " if(a is A) {", + " return a.m;", + " }", + "}"])); + resolve(source); + assertErrors(source, [HintCode.UNDEFINED_GETTER]); + } + void test_undefinedGetter_message() { + JUnitTestCase.assertEquals(StaticTypeWarningCode.UNDEFINED_GETTER.message, StaticWarningCode.UNDEFINED_GETTER.message); + } + void test_undefinedMethod() { + Source source = addSource(EngineTestCase.createSource([ + "f() {", + " var a = 'str';", + " a.notAMethodOnString();", + "}"])); + resolve(source); + assertErrors(source, [HintCode.UNDEFINED_METHOD]); + } + void test_undefinedMethod_assignmentExpression() { + Source source = addSource(EngineTestCase.createSource([ + "class A {}", + "class B {", + " f(var a, var a2) {", + " a = new A();", + " a2 = new A();", + " a += a2;", + " }", + "}"])); + resolve(source); + assertErrors(source, [HintCode.UNDEFINED_METHOD]); + } + void test_undefinedOperator_indexBoth() { + Source source = addSource(EngineTestCase.createSource([ + "class A {}", + "f(var a) {", + " if(a is A) {", + " a[0]++;", + " }", + "}"])); + resolve(source); + assertErrors(source, [HintCode.UNDEFINED_OPERATOR, HintCode.UNDEFINED_OPERATOR]); + } + void test_undefinedOperator_indexGetter() { + Source source = addSource(EngineTestCase.createSource([ + "class A {}", + "f(var a) {", + " if(a is A) {", + " a[0];", + " }", + "}"])); + resolve(source); + assertErrors(source, [HintCode.UNDEFINED_OPERATOR]); + } + void test_undefinedOperator_indexSetter() { + Source source = addSource(EngineTestCase.createSource([ + "class A {}", + "f(var a) {", + " if(a is A) {", + " a[0] = 1;", + " }", + "}"])); + resolve(source); + assertErrors(source, [HintCode.UNDEFINED_OPERATOR]); + } + void test_undefinedOperator_plus() { + Source source = addSource(EngineTestCase.createSource([ + "class A {}", + "f(var a) {", + " if(a is A) {", + " a + 1;", + " }", + "}"])); + resolve(source); + assertErrors(source, [HintCode.UNDEFINED_OPERATOR]); + } + void test_undefinedOperator_postfixExpression() { + Source source = addSource(EngineTestCase.createSource([ + "class A {}", + "f(var a) {", + " if(a is A) {", + " a++;", + " }", + "}"])); + resolve(source); + assertErrors(source, [HintCode.UNDEFINED_OPERATOR]); + } + void test_undefinedOperator_prefixExpression() { + Source source = addSource(EngineTestCase.createSource([ + "class A {}", + "f(var a) {", + " if(a is A) {", + " ++a;", + " }", + "}"])); + resolve(source); + assertErrors(source, [HintCode.UNDEFINED_OPERATOR]); + } + void test_undefinedSetter() { + Source source = addSource(EngineTestCase.createSource([ + "class A {}", + "f(var a) {", + " if(a is A) {", + " a.m = 0;", + " }", + "}"])); + resolve(source); + assertErrors(source, [HintCode.UNDEFINED_SETTER]); + } + void test_undefinedSetter_message() { + JUnitTestCase.assertEquals(StaticTypeWarningCode.UNDEFINED_SETTER.message, StaticWarningCode.UNDEFINED_SETTER.message); + } void test_unnecessaryCast_type_supertype() { Source source = addSource(EngineTestCase.createSource(["m(int i) {", " var b = i as Object;", "}"])); resolve(source); @@ -5959,6 +6196,54 @@ final __test = new HintCodeTest(); runJUnitTest(__test, __test.test_typeCheck_type_not_Null); }); + _ut.test('test_undefinedGetter', () { + final __test = new HintCodeTest(); + runJUnitTest(__test, __test.test_undefinedGetter); + }); + _ut.test('test_undefinedGetter_message', () { + final __test = new HintCodeTest(); + runJUnitTest(__test, __test.test_undefinedGetter_message); + }); + _ut.test('test_undefinedMethod', () { + final __test = new HintCodeTest(); + runJUnitTest(__test, __test.test_undefinedMethod); + }); + _ut.test('test_undefinedMethod_assignmentExpression', () { + final __test = new HintCodeTest(); + runJUnitTest(__test, __test.test_undefinedMethod_assignmentExpression); + }); + _ut.test('test_undefinedOperator_indexBoth', () { + final __test = new HintCodeTest(); + runJUnitTest(__test, __test.test_undefinedOperator_indexBoth); + }); + _ut.test('test_undefinedOperator_indexGetter', () { + final __test = new HintCodeTest(); + runJUnitTest(__test, __test.test_undefinedOperator_indexGetter); + }); + _ut.test('test_undefinedOperator_indexSetter', () { + final __test = new HintCodeTest(); + runJUnitTest(__test, __test.test_undefinedOperator_indexSetter); + }); + _ut.test('test_undefinedOperator_plus', () { + final __test = new HintCodeTest(); + runJUnitTest(__test, __test.test_undefinedOperator_plus); + }); + _ut.test('test_undefinedOperator_postfixExpression', () { + final __test = new HintCodeTest(); + runJUnitTest(__test, __test.test_undefinedOperator_postfixExpression); + }); + _ut.test('test_undefinedOperator_prefixExpression', () { + final __test = new HintCodeTest(); + runJUnitTest(__test, __test.test_undefinedOperator_prefixExpression); + }); + _ut.test('test_undefinedSetter', () { + final __test = new HintCodeTest(); + runJUnitTest(__test, __test.test_undefinedSetter); + }); + _ut.test('test_undefinedSetter_message', () { + final __test = new HintCodeTest(); + runJUnitTest(__test, __test.test_undefinedSetter_message); + }); _ut.test('test_unnecessaryCast_type_supertype', () { final __test = new HintCodeTest(); runJUnitTest(__test, __test.test_unnecessaryCast_type_supertype); @@ -6420,7 +6705,7 @@ * @throws AssertionFailedError if any errors have been reported */ void assertNoErrors(Source source) { - EngineTestCase.assertLength(0, analysisContext.computeErrors(source)); + assertErrors(source, []); } /** @@ -16466,16 +16751,16 @@ * @param body the body of the function * @return a resolved function expression */ - FunctionExpression resolvedFunctionExpression(FormalParameterList parameters2, FunctionBody body) { + FunctionExpression resolvedFunctionExpression(FormalParameterList parameters, FunctionBody body) { List<ParameterElement> parameterElements = new List<ParameterElement>(); - for (FormalParameter parameter in parameters2.parameters) { + for (FormalParameter parameter in parameters.parameters) { ParameterElementImpl element = new ParameterElementImpl.con1(parameter.identifier); element.parameterKind = parameter.kind; element.type = _typeProvider.dynamicType; parameter.identifier.staticElement = element; parameterElements.add(element); } - FunctionExpression node = ASTFactory.functionExpression2(parameters2, body); + FunctionExpression node = ASTFactory.functionExpression2(parameters, body); FunctionElementImpl element = new FunctionElementImpl.con1(null); element.parameters = new List.from(parameterElements); element.type = new FunctionTypeImpl.con1(element); @@ -16514,12 +16799,12 @@ * @param variableName the name of the variable * @return a simple identifier that has been resolved to a variable element with the given type */ - SimpleIdentifier resolvedVariable(InterfaceType type2, String variableName) { + SimpleIdentifier resolvedVariable(InterfaceType type, String variableName) { SimpleIdentifier identifier = ASTFactory.identifier3(variableName); VariableElementImpl element = ElementFactory.localVariableElement(identifier); - element.type = type2; + element.type = type; identifier.staticElement = element; - identifier.staticType = type2; + identifier.staticType = type; return identifier; } @@ -16529,14 +16814,14 @@ * @param parameter the parameter whose type is to be set * @param type the new type of the given parameter */ - void setType(FormalParameter parameter, Type2 type2) { + void setType(FormalParameter parameter, Type2 type) { SimpleIdentifier identifier = parameter.identifier; Element element = identifier.staticElement; if (element is! ParameterElement) { element = new ParameterElementImpl.con1(identifier); identifier.staticElement = element; } - ((element as ParameterElementImpl)).type = type2; + ((element as ParameterElementImpl)).type = type; } static dartSuite() { _ut.group('StaticTypeAnalyzerTest', () { @@ -17035,6 +17320,13 @@ assertNoErrors(source); verify([source]); } + void test_unusedImport_annotationOnDirective() { + Source source = addSource(EngineTestCase.createSource(["library L;", "@A()", "import 'lib1.dart';"])); + Source source2 = addSource2("/lib1.dart", EngineTestCase.createSource(["library lib1;", "class A {", " const A() {}", "}"])); + resolve(source); + assertErrors(source, []); + verify([source, source2]); + } void test_unusedImport_core_library() { Source source = addSource(EngineTestCase.createSource(["library L;", "import 'dart:core';"])); resolve(source); @@ -17169,6 +17461,10 @@ final __test = new NonHintCodeTest(); runJUnitTest(__test, __test.test_unnecessaryCast_type_dynamic); }); + _ut.test('test_unusedImport_annotationOnDirective', () { + final __test = new NonHintCodeTest(); + runJUnitTest(__test, __test.test_unusedImport_annotationOnDirective); + }); _ut.test('test_unusedImport_core_library', () { final __test = new NonHintCodeTest(); runJUnitTest(__test, __test.test_unusedImport_core_library);
diff --git a/pkg/analyzer_experimental/test/generated/scanner_test.dart b/pkg/analyzer_experimental/test/generated/scanner_test.dart index aa74c46..e709c47 100644 --- a/pkg/analyzer_experimental/test/generated/scanner_test.dart +++ b/pkg/analyzer_experimental/test/generated/scanner_test.dart
@@ -2089,7 +2089,7 @@ void assertError(ScannerErrorCode expectedError, int expectedOffset, String source) { GatheringErrorListener listener = new GatheringErrorListener(); scan(source, listener); - listener.assertErrors([new AnalysisError.con2(null, expectedOffset, 1, expectedError, [(source.codeUnitAt(expectedOffset) as int)])]); + listener.assertErrors([new AnalysisError.con2(null, expectedOffset, 1, expectedError, [source.codeUnitAt(expectedOffset) as int])]); } /**
diff --git a/pkg/analyzer_experimental/test/generated/test_support.dart b/pkg/analyzer_experimental/test/generated/test_support.dart index d0977be..90af45a 100644 --- a/pkg/analyzer_experimental/test/generated/test_support.dart +++ b/pkg/analyzer_experimental/test/generated/test_support.dart
@@ -232,9 +232,9 @@ * @param errorCode the error code being searched for * @return `true` if an error with the given error code has been gathered */ - bool hasError(ErrorCode errorCode2) { + bool hasError(ErrorCode errorCode) { for (AnalysisError error in errors) { - if (identical(error.errorCode, errorCode2)) { + if (identical(error.errorCode, errorCode)) { return true; } }
diff --git a/pkg/analyzer_experimental/test/services/formatter_test.dart b/pkg/analyzer_experimental/test/services/formatter_test.dart index 51187f3..c2e1f18 100644 --- a/pkg/analyzer_experimental/test/services/formatter_test.dart +++ b/pkg/analyzer_experimental/test/services/formatter_test.dart
@@ -598,7 +598,8 @@ '}\n', 'class A {\n' ' int _a;\n' - ' A(a) : _a = a;\n' + ' A(a)\n' + ' : _a = a;\n' '}\n' ); }); @@ -622,6 +623,20 @@ 'part of foo;\n' ); }); + + test('CU (cons inits)', () { + expectCUFormatsTo('class X {\n' + ' var x, y;\n' + ' X() : x = 1, y = 2;\n' + '}\n', + 'class X {\n' + ' var x, y;\n' + ' X()\n' + ' : x = 1,\n' + ' y = 2;\n' + '}\n' + ); + }); test('stmt', () { expectStmtFormatsTo( @@ -763,6 +778,21 @@ '}' ); }); + + test('Statement (if)', () { + expectStmtFormatsTo('if (true) print("true!");', + 'if (true) print("true!");'); + expectStmtFormatsTo('if (true) { print("true!"); }', + 'if (true) {\n' + ' print("true!");\n' + '}'); + expectStmtFormatsTo('if (true) print("true!"); else print("false!");', + 'if (true) {\n' + ' print("true!");\n' + '} else {\n' + ' print("false!");\n' + '}'); + }); test('initialIndent', () { var formatter = new CodeFormatter(
diff --git a/pkg/browser/lib/interop.js b/pkg/browser/lib/interop.js index 40e1700..8577e4f 100644 --- a/pkg/browser/lib/interop.js +++ b/pkg/browser/lib/interop.js
@@ -224,7 +224,9 @@ (function() { // Proxy support for js.dart. - var globalContext = window; + // We don't use 'window' because we might be in a web worker, but we don't + // use 'self' because not all browsers support it + var globalContext = function() { return this; }(); // Table for local objects and functions that are proxied. function ProxiedObjectTable() {
diff --git a/pkg/custom_element/lib/custom-elements.debug.js b/pkg/custom_element/lib/custom-elements.debug.js index 843e8a7..a391b8a 100644 --- a/pkg/custom_element/lib/custom-elements.debug.js +++ b/pkg/custom_element/lib/custom-elements.debug.js
@@ -1207,8 +1207,8 @@ changeAttribute.call(this, name, value, setAttribute); } var removeAttribute = prototype.removeAttribute; - prototype.removeAttribute = function(name, value) { - changeAttribute.call(this, name, value, removeAttribute); + prototype.removeAttribute = function(name) { + changeAttribute.call(this, name, null, removeAttribute); } } @@ -1217,7 +1217,7 @@ operation.apply(this, arguments); if (this.attributeChangedCallback && (this.getAttribute(name) !== oldValue)) { - this.attributeChangedCallback(name, oldValue); + this.attributeChangedCallback(name, oldValue, value); } }
diff --git a/pkg/custom_element/lib/custom-elements.min.js b/pkg/custom_element/lib/custom-elements.min.js index fdec66a..8ecb7a4 100644 --- a/pkg/custom_element/lib/custom-elements.min.js +++ b/pkg/custom_element/lib/custom-elements.min.js
@@ -25,4 +25,4 @@ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -window.CustomElements={flags:{}};var SideTable;if("undefined"!=typeof WeakMap&&navigator.userAgent.indexOf("Firefox/")<0?SideTable=WeakMap:function(){var a=Object.defineProperty,b=Date.now()%1e9;SideTable=function(){this.name="__st"+(1e9*Math.random()>>>0)+(b++ +"__")},SideTable.prototype={set:function(b,c){var d=b[this.name];d&&d[0]===b?d[1]=c:a(b,this.name,{value:[b,c],writable:!0})},get:function(a){var b;return(b=a[this.name])&&b[0]===a?b[1]:void 0},"delete":function(a){this.set(a,void 0)}}}(),function(a){function b(a){u.push(a),t||(t=!0,q(d))}function c(a){return window.ShadowDOMPolyfill&&window.ShadowDOMPolyfill.wrapIfNeeded(a)||a}function d(){t=!1;var a=u;u=[],a.sort(function(a,b){return a.uid_-b.uid_});var b=!1;a.forEach(function(a){var c=a.takeRecords();e(a),c.length&&(a.callback_(c,a),b=!0)}),b&&d()}function e(a){a.nodes_.forEach(function(b){var c=p.get(b);c&&c.forEach(function(b){b.observer===a&&b.removeTransientObservers()})})}function f(a,b){for(var c=a;c;c=c.parentNode){var d=p.get(c);if(d)for(var e=0;e<d.length;e++){var f=d[e],g=f.options;if(c===a||g.subtree){var h=b(g);h&&f.enqueue(h)}}}}function g(a){this.callback_=a,this.nodes_=[],this.records_=[],this.uid_=++v}function h(a,b){this.type=a,this.target=b,this.addedNodes=[],this.removedNodes=[],this.previousSibling=null,this.nextSibling=null,this.attributeName=null,this.attributeNamespace=null,this.oldValue=null}function i(a){var b=new h(a.type,a.target);return b.addedNodes=a.addedNodes.slice(),b.removedNodes=a.removedNodes.slice(),b.previousSibling=a.previousSibling,b.nextSibling=a.nextSibling,b.attributeName=a.attributeName,b.attributeNamespace=a.attributeNamespace,b.oldValue=a.oldValue,b}function j(a,b){return w=new h(a,b)}function k(a){return x?x:(x=i(w),x.oldValue=a,x)}function l(){w=x=void 0}function m(a){return a===x||a===w}function n(a,b){return a===b?a:x&&m(a)?x:null}function o(a,b,c){this.observer=a,this.target=b,this.options=c,this.transientObservedNodes=[]}var p=new SideTable,q=window.msSetImmediate;if(!q){var r=[],s=String(Math.random());window.addEventListener("message",function(a){if(a.data===s){var b=r;r=[],b.forEach(function(a){a()})}}),q=function(a){r.push(a),window.postMessage(s,"*")}}var t=!1,u=[],v=0;g.prototype={observe:function(a,b){if(a=c(a),!b.childList&&!b.attributes&&!b.characterData||b.attributeOldValue&&!b.attributes||b.attributeFilter&&b.attributeFilter.length&&!b.attributes||b.characterDataOldValue&&!b.characterData)throw new SyntaxError;var d=p.get(a);d||p.set(a,d=[]);for(var e,f=0;f<d.length;f++)if(d[f].observer===this){e=d[f],e.removeListeners(),e.options=b;break}e||(e=new o(this,a,b),d.push(e),this.nodes_.push(a)),e.addListeners()},disconnect:function(){this.nodes_.forEach(function(a){for(var b=p.get(a),c=0;c<b.length;c++){var d=b[c];if(d.observer===this){d.removeListeners(),b.splice(c,1);break}}},this),this.records_=[]},takeRecords:function(){var a=this.records_;return this.records_=[],a}};var w,x;o.prototype={enqueue:function(a){var c=this.observer.records_,d=c.length;if(c.length>0){var e=c[d-1],f=n(e,a);if(f)return c[d-1]=f,void 0}else b(this.observer);c[d]=a},addListeners:function(){this.addListeners_(this.target)},addListeners_:function(a){var b=this.options;b.attributes&&a.addEventListener("DOMAttrModified",this,!0),b.characterData&&a.addEventListener("DOMCharacterDataModified",this,!0),b.childList&&a.addEventListener("DOMNodeInserted",this,!0),(b.childList||b.subtree)&&a.addEventListener("DOMNodeRemoved",this,!0)},removeListeners:function(){this.removeListeners_(this.target)},removeListeners_:function(a){var b=this.options;b.attributes&&a.removeEventListener("DOMAttrModified",this,!0),b.characterData&&a.removeEventListener("DOMCharacterDataModified",this,!0),b.childList&&a.removeEventListener("DOMNodeInserted",this,!0),(b.childList||b.subtree)&&a.removeEventListener("DOMNodeRemoved",this,!0)},addTransientObserver:function(a){if(a!==this.target){this.addListeners_(a),this.transientObservedNodes.push(a);var b=p.get(a);b||p.set(a,b=[]),b.push(this)}},removeTransientObservers:function(){var a=this.transientObservedNodes;this.transientObservedNodes=[],a.forEach(function(a){this.removeListeners_(a);for(var b=p.get(a),c=0;c<b.length;c++)if(b[c]===this){b.splice(c,1);break}},this)},handleEvent:function(a){switch(a.stopImmediatePropagation(),a.type){case"DOMAttrModified":var b=a.attrName,c=a.relatedNode.namespaceURI,d=a.target,e=new j("attributes",d);e.attributeName=b,e.attributeNamespace=c;var g=a.attrChange===MutationEvent.ADDITION?null:a.prevValue;f(d,function(a){return!a.attributes||a.attributeFilter&&a.attributeFilter.length&&-1===a.attributeFilter.indexOf(b)&&-1===a.attributeFilter.indexOf(c)?void 0:a.attributeOldValue?k(g):e});break;case"DOMCharacterDataModified":var d=a.target,e=j("characterData",d),g=a.prevValue;f(d,function(a){return a.characterData?a.characterDataOldValue?k(g):e:void 0});break;case"DOMNodeRemoved":this.addTransientObserver(a.target);case"DOMNodeInserted":var h,i,d=a.relatedNode,m=a.target;"DOMNodeInserted"===a.type?(h=[m],i=[]):(h=[],i=[m]);var n=m.previousSibling,o=m.nextSibling,e=j("childList",d);e.addedNodes=h,e.removedNodes=i,e.previousSibling=n,e.nextSibling=o,f(d,function(a){return a.childList?e:void 0})}l()}},a.JsMutationObserver=g}(this),!window.MutationObserver&&(window.MutationObserver=window.WebKitMutationObserver||window.JsMutationObserver,!MutationObserver))throw new Error("no mutation observer support");!function(a){function b(a,c,d){var e=a.firstElementChild;if(!e)for(e=a.firstChild;e&&e.nodeType!==Node.ELEMENT_NODE;)e=e.nextSibling;for(;e;)c(e,d)!==!0&&b(e,c,d),e=e.nextElementSibling;return null}function c(a,b){for(var c=a.shadowRoot;c;)d(c,b),c=c.olderShadowRoot}function d(a,d){b(a,function(a){return d(a)?!0:(c(a,d),void 0)}),c(a,d)}function e(a){return h(a)?(i(a),!0):(l(a),void 0)}function f(a){d(a,function(a){return e(a)?!0:void 0})}function g(a){return e(a)||f(a)}function h(b){if(!b.__upgraded__&&b.nodeType===Node.ELEMENT_NODE){var c=b.getAttribute("is")||b.localName,d=a.registry[c];if(d)return y.dom&&console.group("upgrade:",b.localName),a.upgrade(b),y.dom&&console.groupEnd(),!0}}function i(a){l(a),p(a)&&d(a,function(a){l(a)})}function j(a){if(B.push(a),!A){A=!0;var b=window.Platform&&window.Platform.endOfMicrotask||setTimeout;b(k)}}function k(){A=!1;for(var a,b=B,c=0,d=b.length;d>c&&(a=b[c]);c++)a();B=[]}function l(a){z?j(function(){m(a)}):m(a)}function m(a){(a.enteredViewCallback||a.__upgraded__&&y.dom)&&(y.dom&&console.group("inserted:",a.localName),p(a)&&(a.__inserted=(a.__inserted||0)+1,a.__inserted<1&&(a.__inserted=1),a.__inserted>1?y.dom&&console.warn("inserted:",a.localName,"insert/remove count:",a.__inserted):a.enteredViewCallback&&(y.dom&&console.log("inserted:",a.localName),a.enteredViewCallback())),y.dom&&console.groupEnd())}function n(a){o(a),d(a,function(a){o(a)})}function o(a){z?j(function(){_removed(a)}):_removed(a)}function o(a){(a.leftViewCallback||a.__upgraded__&&y.dom)&&(y.dom&&console.log("removed:",a.localName),p(a)||(a.__inserted=(a.__inserted||0)-1,a.__inserted>0&&(a.__inserted=0),a.__inserted<0?y.dom&&console.warn("removed:",a.localName,"insert/remove count:",a.__inserted):a.leftViewCallback&&a.leftViewCallback()))}function p(a){for(var b=a,c=window.ShadowDOMPolyfill&&window.ShadowDOMPolyfill.wrapIfNeeded(document)||document;b;){if(b==c)return!0;b=b.parentNode||b.host}}function q(a){if(a.shadowRoot&&!a.shadowRoot.__watched){y.dom&&console.log("watching shadow-root for: ",a.localName);for(var b=a.shadowRoot;b;)r(b),b=b.olderShadowRoot}}function r(a){a.__watched||(v(a),a.__watched=!0)}function s(a){switch(a.localName){case"style":case"script":case"template":case void 0:return!0}}function t(a){if(y.dom){var b=a[0];if(b&&"childList"===b.type&&b.addedNodes&&b.addedNodes){for(var c=b.addedNodes[0];c&&c!==document&&!c.host;)c=c.parentNode;var d=c&&(c.URL||c._URL||c.host&&c.host.localName)||"";d=d.split("/?").shift().split("/").pop()}console.group("mutations (%d) [%s]",a.length,d||"")}a.forEach(function(a){"childList"===a.type&&(D(a.addedNodes,function(a){s(a)||g(a)}),D(a.removedNodes,function(a){s(a)||n(a)}))}),y.dom&&console.groupEnd()}function u(){t(C.takeRecords()),k()}function v(a){C.observe(a,{childList:!0,subtree:!0})}function w(a){v(a)}function x(a){y.dom&&console.group("upgradeDocument: ",(a.URL||a._URL||"").split("/").pop()),g(a),y.dom&&console.groupEnd()}var y=window.logFlags||{},z=!window.MutationObserver||window.MutationObserver===window.JsMutationObserver;a.hasPolyfillMutations=z;var A=!1,B=[],C=new MutationObserver(t),D=Array.prototype.forEach.call.bind(Array.prototype.forEach);a.watchShadow=q,a.upgradeAll=g,a.upgradeSubtree=f,a.observeDocument=w,a.upgradeDocument=x,a.takeRecords=u}(window.CustomElements),function(a){function b(b,f){var g=f||{};if(!b)throw new Error("document.register: first argument `name` must not be empty");if(b.indexOf("-")<0)throw new Error("document.register: first argument ('name') must contain a dash ('-'). Argument provided was '"+String(b)+"'.");if(g.name=b,!g.prototype)throw new Error("Options missing required prototype property");return g.lifecycle=g.lifecycle||{},g.ancestry=c(g.extends),d(g),e(g),k(g.prototype),m(b,g),g.ctor=n(g),g.ctor.prototype=g.prototype,g.prototype.constructor=g.ctor,a.ready&&a.upgradeAll(document),g.ctor}function c(a){var b=v[a];return b?c(b.extends).concat([b]):[]}function d(a){for(var b,c=a.extends,d=0;b=a.ancestry[d];d++)c=b.is&&b.tag;a.tag=c||a.name,c&&(a.is=a.name)}function e(a){if(!Object.__proto__){var b=HTMLElement.prototype;if(a.is){var c=document.createElement(a.tag);b=Object.getPrototypeOf(c)}for(var d,e=a.prototype;e&&e!==b;){var d=Object.getPrototypeOf(e);e.__proto__=d,e=d}}a.native=b}function f(a){return g(w(a.tag),a)}function g(b,c){return c.is&&b.setAttribute("is",c.is),h(b,c),b.__upgraded__=!0,a.upgradeSubtree(b),j(b),b}function h(a,b){Object.__proto__?a.__proto__=b.prototype:(i(a,b.prototype,b.native),a.__proto__=b.prototype)}function i(a,b,c){for(var d={},e=b;e!==c&&e!==HTMLUnknownElement.prototype;){for(var f,g=Object.getOwnPropertyNames(e),h=0;f=g[h];h++)d[f]||(Object.defineProperty(a,f,Object.getOwnPropertyDescriptor(e,f)),d[f]=1);e=Object.getPrototypeOf(e)}}function j(a){a.createdCallback&&a.createdCallback()}function k(a){var b=a.setAttribute;a.setAttribute=function(a,c){l.call(this,a,c,b)};var c=a.removeAttribute;a.removeAttribute=function(a,b){l.call(this,a,b,c)}}function l(a,b,c){var d=this.getAttribute(a);c.apply(this,arguments),this.attributeChangedCallback&&this.getAttribute(a)!==d&&this.attributeChangedCallback(a,d)}function m(a,b){if(v[a])throw new Error("Cannot register a tag more than once");v[a]=b}function n(a){return function(){return f(a)}}function o(a,b){var c=v[b||a];if(c){if(a==c.tag&&b==c.is)return new c.ctor;if(!b&&!c.is)return new c.ctor}if(b){var d=o(a);return d.setAttribute("is",b),d}var d=w(a);return a.indexOf("-")>=0&&h(d,HTMLElement),d}function p(a){if(!a.__upgraded__&&a.nodeType===Node.ELEMENT_NODE){var b=a.getAttribute("is"),c=v[b||a.localName];if(c){if(b&&c.tag==a.localName)return g(a,c);if(!b&&!c.extends)return g(a,c)}}}function q(b){var c=x.call(this,b);return a.upgradeAll(c),c}a||(a=window.CustomElements={flags:{}});var r=a.flags,s=Boolean(document.register),t=!r.register&&s;if(t){var u=function(){};a.registry={},a.upgradeElement=u,a.watchShadow=u,a.upgrade=u,a.upgradeAll=u,a.upgradeSubtree=u,a.observeDocument=u,a.upgradeDocument=u,a.takeRecords=u}else{var v={},w=document.createElement.bind(document),x=Node.prototype.cloneNode;document.register=b,document.createElement=o,Node.prototype.cloneNode=q,a.registry=v,a.upgrade=p}a.hasNative=s,a.useNative=t}(window.CustomElements),function(){function a(a){return"link"===a.localName&&a.getAttribute("rel")===b}var b=window.HTMLImports?HTMLImports.IMPORT_LINK_TYPE:"none",c={selectors:["link[rel="+b+"]"],map:{link:"parseLink"},parse:function(a){if(!a.__parsed){a.__parsed=!0;var b=a.querySelectorAll(c.selectors);d(b,function(a){c[c.map[a.localName]](a)}),CustomElements.upgradeDocument(a),CustomElements.observeDocument(a)}},parseLink:function(b){a(b)&&this.parseImport(b)},parseImport:function(a){a.content&&c.parse(a.content)}},d=Array.prototype.forEach.call.bind(Array.prototype.forEach);CustomElements.parser=c}(),function(){function a(){CustomElements.parser.parse(document),CustomElements.upgradeDocument(document);var a=window.Platform&&Platform.endOfMicrotask?Platform.endOfMicrotask:setTimeout;a(function(){CustomElements.ready=!0,CustomElements.readyTime=Date.now(),window.HTMLImports&&(CustomElements.elapsed=CustomElements.readyTime-HTMLImports.readyTime),document.body.dispatchEvent(new CustomEvent("WebComponentsReady",{bubbles:!0}))})}if("function"!=typeof window.CustomEvent&&(window.CustomEvent=function(a){var b=document.createEvent("HTMLEvents");return b.initEvent(a,!0,!0),b}),"complete"===document.readyState)a();else{var b=window.HTMLImports?"HTMLImportsLoaded":"loading"==document.readyState?"DOMContentLoaded":"load";window.addEventListener(b,a)}}(),function(){if(HTMLElement.prototype.createShadowRoot){var a=HTMLElement.prototype.createShadowRoot;HTMLElement.prototype.createShadowRoot=function(){var b=a.call(this);return b.host=this,b}}}(); +window.CustomElements={flags:{}};var SideTable;if("undefined"!=typeof WeakMap&&navigator.userAgent.indexOf("Firefox/")<0?SideTable=WeakMap:function(){var a=Object.defineProperty,b=Date.now()%1e9;SideTable=function(){this.name="__st"+(1e9*Math.random()>>>0)+(b++ +"__")},SideTable.prototype={set:function(b,c){var d=b[this.name];d&&d[0]===b?d[1]=c:a(b,this.name,{value:[b,c],writable:!0})},get:function(a){var b;return(b=a[this.name])&&b[0]===a?b[1]:void 0},"delete":function(a){this.set(a,void 0)}}}(),function(a){function b(a){u.push(a),t||(t=!0,q(d))}function c(a){return window.ShadowDOMPolyfill&&window.ShadowDOMPolyfill.wrapIfNeeded(a)||a}function d(){t=!1;var a=u;u=[],a.sort(function(a,b){return a.uid_-b.uid_});var b=!1;a.forEach(function(a){var c=a.takeRecords();e(a),c.length&&(a.callback_(c,a),b=!0)}),b&&d()}function e(a){a.nodes_.forEach(function(b){var c=p.get(b);c&&c.forEach(function(b){b.observer===a&&b.removeTransientObservers()})})}function f(a,b){for(var c=a;c;c=c.parentNode){var d=p.get(c);if(d)for(var e=0;e<d.length;e++){var f=d[e],g=f.options;if(c===a||g.subtree){var h=b(g);h&&f.enqueue(h)}}}}function g(a){this.callback_=a,this.nodes_=[],this.records_=[],this.uid_=++v}function h(a,b){this.type=a,this.target=b,this.addedNodes=[],this.removedNodes=[],this.previousSibling=null,this.nextSibling=null,this.attributeName=null,this.attributeNamespace=null,this.oldValue=null}function i(a){var b=new h(a.type,a.target);return b.addedNodes=a.addedNodes.slice(),b.removedNodes=a.removedNodes.slice(),b.previousSibling=a.previousSibling,b.nextSibling=a.nextSibling,b.attributeName=a.attributeName,b.attributeNamespace=a.attributeNamespace,b.oldValue=a.oldValue,b}function j(a,b){return w=new h(a,b)}function k(a){return x?x:(x=i(w),x.oldValue=a,x)}function l(){w=x=void 0}function m(a){return a===x||a===w}function n(a,b){return a===b?a:x&&m(a)?x:null}function o(a,b,c){this.observer=a,this.target=b,this.options=c,this.transientObservedNodes=[]}var p=new SideTable,q=window.msSetImmediate;if(!q){var r=[],s=String(Math.random());window.addEventListener("message",function(a){if(a.data===s){var b=r;r=[],b.forEach(function(a){a()})}}),q=function(a){r.push(a),window.postMessage(s,"*")}}var t=!1,u=[],v=0;g.prototype={observe:function(a,b){if(a=c(a),!b.childList&&!b.attributes&&!b.characterData||b.attributeOldValue&&!b.attributes||b.attributeFilter&&b.attributeFilter.length&&!b.attributes||b.characterDataOldValue&&!b.characterData)throw new SyntaxError;var d=p.get(a);d||p.set(a,d=[]);for(var e,f=0;f<d.length;f++)if(d[f].observer===this){e=d[f],e.removeListeners(),e.options=b;break}e||(e=new o(this,a,b),d.push(e),this.nodes_.push(a)),e.addListeners()},disconnect:function(){this.nodes_.forEach(function(a){for(var b=p.get(a),c=0;c<b.length;c++){var d=b[c];if(d.observer===this){d.removeListeners(),b.splice(c,1);break}}},this),this.records_=[]},takeRecords:function(){var a=this.records_;return this.records_=[],a}};var w,x;o.prototype={enqueue:function(a){var c=this.observer.records_,d=c.length;if(c.length>0){var e=c[d-1],f=n(e,a);if(f)return c[d-1]=f,void 0}else b(this.observer);c[d]=a},addListeners:function(){this.addListeners_(this.target)},addListeners_:function(a){var b=this.options;b.attributes&&a.addEventListener("DOMAttrModified",this,!0),b.characterData&&a.addEventListener("DOMCharacterDataModified",this,!0),b.childList&&a.addEventListener("DOMNodeInserted",this,!0),(b.childList||b.subtree)&&a.addEventListener("DOMNodeRemoved",this,!0)},removeListeners:function(){this.removeListeners_(this.target)},removeListeners_:function(a){var b=this.options;b.attributes&&a.removeEventListener("DOMAttrModified",this,!0),b.characterData&&a.removeEventListener("DOMCharacterDataModified",this,!0),b.childList&&a.removeEventListener("DOMNodeInserted",this,!0),(b.childList||b.subtree)&&a.removeEventListener("DOMNodeRemoved",this,!0)},addTransientObserver:function(a){if(a!==this.target){this.addListeners_(a),this.transientObservedNodes.push(a);var b=p.get(a);b||p.set(a,b=[]),b.push(this)}},removeTransientObservers:function(){var a=this.transientObservedNodes;this.transientObservedNodes=[],a.forEach(function(a){this.removeListeners_(a);for(var b=p.get(a),c=0;c<b.length;c++)if(b[c]===this){b.splice(c,1);break}},this)},handleEvent:function(a){switch(a.stopImmediatePropagation(),a.type){case"DOMAttrModified":var b=a.attrName,c=a.relatedNode.namespaceURI,d=a.target,e=new j("attributes",d);e.attributeName=b,e.attributeNamespace=c;var g=a.attrChange===MutationEvent.ADDITION?null:a.prevValue;f(d,function(a){return!a.attributes||a.attributeFilter&&a.attributeFilter.length&&-1===a.attributeFilter.indexOf(b)&&-1===a.attributeFilter.indexOf(c)?void 0:a.attributeOldValue?k(g):e});break;case"DOMCharacterDataModified":var d=a.target,e=j("characterData",d),g=a.prevValue;f(d,function(a){return a.characterData?a.characterDataOldValue?k(g):e:void 0});break;case"DOMNodeRemoved":this.addTransientObserver(a.target);case"DOMNodeInserted":var h,i,d=a.relatedNode,m=a.target;"DOMNodeInserted"===a.type?(h=[m],i=[]):(h=[],i=[m]);var n=m.previousSibling,o=m.nextSibling,e=j("childList",d);e.addedNodes=h,e.removedNodes=i,e.previousSibling=n,e.nextSibling=o,f(d,function(a){return a.childList?e:void 0})}l()}},a.JsMutationObserver=g}(this),!window.MutationObserver&&(window.MutationObserver=window.WebKitMutationObserver||window.JsMutationObserver,!MutationObserver))throw new Error("no mutation observer support");!function(a){function b(a,c,d){var e=a.firstElementChild;if(!e)for(e=a.firstChild;e&&e.nodeType!==Node.ELEMENT_NODE;)e=e.nextSibling;for(;e;)c(e,d)!==!0&&b(e,c,d),e=e.nextElementSibling;return null}function c(a,b){for(var c=a.shadowRoot;c;)d(c,b),c=c.olderShadowRoot}function d(a,d){b(a,function(a){return d(a)?!0:(c(a,d),void 0)}),c(a,d)}function e(a){return h(a)?(i(a),!0):(l(a),void 0)}function f(a){d(a,function(a){return e(a)?!0:void 0})}function g(a){return e(a)||f(a)}function h(b){if(!b.__upgraded__&&b.nodeType===Node.ELEMENT_NODE){var c=b.getAttribute("is")||b.localName,d=a.registry[c];if(d)return y.dom&&console.group("upgrade:",b.localName),a.upgrade(b),y.dom&&console.groupEnd(),!0}}function i(a){l(a),p(a)&&d(a,function(a){l(a)})}function j(a){if(B.push(a),!A){A=!0;var b=window.Platform&&window.Platform.endOfMicrotask||setTimeout;b(k)}}function k(){A=!1;for(var a,b=B,c=0,d=b.length;d>c&&(a=b[c]);c++)a();B=[]}function l(a){z?j(function(){m(a)}):m(a)}function m(a){(a.enteredViewCallback||a.__upgraded__&&y.dom)&&(y.dom&&console.group("inserted:",a.localName),p(a)&&(a.__inserted=(a.__inserted||0)+1,a.__inserted<1&&(a.__inserted=1),a.__inserted>1?y.dom&&console.warn("inserted:",a.localName,"insert/remove count:",a.__inserted):a.enteredViewCallback&&(y.dom&&console.log("inserted:",a.localName),a.enteredViewCallback())),y.dom&&console.groupEnd())}function n(a){o(a),d(a,function(a){o(a)})}function o(a){z?j(function(){_removed(a)}):_removed(a)}function o(a){(a.leftViewCallback||a.__upgraded__&&y.dom)&&(y.dom&&console.log("removed:",a.localName),p(a)||(a.__inserted=(a.__inserted||0)-1,a.__inserted>0&&(a.__inserted=0),a.__inserted<0?y.dom&&console.warn("removed:",a.localName,"insert/remove count:",a.__inserted):a.leftViewCallback&&a.leftViewCallback()))}function p(a){for(var b=a,c=window.ShadowDOMPolyfill&&window.ShadowDOMPolyfill.wrapIfNeeded(document)||document;b;){if(b==c)return!0;b=b.parentNode||b.host}}function q(a){if(a.shadowRoot&&!a.shadowRoot.__watched){y.dom&&console.log("watching shadow-root for: ",a.localName);for(var b=a.shadowRoot;b;)r(b),b=b.olderShadowRoot}}function r(a){a.__watched||(v(a),a.__watched=!0)}function s(a){switch(a.localName){case"style":case"script":case"template":case void 0:return!0}}function t(a){if(y.dom){var b=a[0];if(b&&"childList"===b.type&&b.addedNodes&&b.addedNodes){for(var c=b.addedNodes[0];c&&c!==document&&!c.host;)c=c.parentNode;var d=c&&(c.URL||c._URL||c.host&&c.host.localName)||"";d=d.split("/?").shift().split("/").pop()}console.group("mutations (%d) [%s]",a.length,d||"")}a.forEach(function(a){"childList"===a.type&&(D(a.addedNodes,function(a){s(a)||g(a)}),D(a.removedNodes,function(a){s(a)||n(a)}))}),y.dom&&console.groupEnd()}function u(){t(C.takeRecords()),k()}function v(a){C.observe(a,{childList:!0,subtree:!0})}function w(a){v(a)}function x(a){y.dom&&console.group("upgradeDocument: ",(a.URL||a._URL||"").split("/").pop()),g(a),y.dom&&console.groupEnd()}var y=window.logFlags||{},z=!window.MutationObserver||window.MutationObserver===window.JsMutationObserver;a.hasPolyfillMutations=z;var A=!1,B=[],C=new MutationObserver(t),D=Array.prototype.forEach.call.bind(Array.prototype.forEach);a.watchShadow=q,a.upgradeAll=g,a.upgradeSubtree=f,a.observeDocument=w,a.upgradeDocument=x,a.takeRecords=u}(window.CustomElements),function(a){function b(b,f){var g=f||{};if(!b)throw new Error("document.register: first argument `name` must not be empty");if(b.indexOf("-")<0)throw new Error("document.register: first argument ('name') must contain a dash ('-'). Argument provided was '"+String(b)+"'.");if(g.name=b,!g.prototype)throw new Error("Options missing required prototype property");return g.lifecycle=g.lifecycle||{},g.ancestry=c(g.extends),d(g),e(g),k(g.prototype),m(b,g),g.ctor=n(g),g.ctor.prototype=g.prototype,g.prototype.constructor=g.ctor,a.ready&&a.upgradeAll(document),g.ctor}function c(a){var b=v[a];return b?c(b.extends).concat([b]):[]}function d(a){for(var b,c=a.extends,d=0;b=a.ancestry[d];d++)c=b.is&&b.tag;a.tag=c||a.name,c&&(a.is=a.name)}function e(a){if(!Object.__proto__){var b=HTMLElement.prototype;if(a.is){var c=document.createElement(a.tag);b=Object.getPrototypeOf(c)}for(var d,e=a.prototype;e&&e!==b;){var d=Object.getPrototypeOf(e);e.__proto__=d,e=d}}a.native=b}function f(a){return g(w(a.tag),a)}function g(b,c){return c.is&&b.setAttribute("is",c.is),h(b,c),b.__upgraded__=!0,a.upgradeSubtree(b),j(b),b}function h(a,b){Object.__proto__?a.__proto__=b.prototype:(i(a,b.prototype,b.native),a.__proto__=b.prototype)}function i(a,b,c){for(var d={},e=b;e!==c&&e!==HTMLUnknownElement.prototype;){for(var f,g=Object.getOwnPropertyNames(e),h=0;f=g[h];h++)d[f]||(Object.defineProperty(a,f,Object.getOwnPropertyDescriptor(e,f)),d[f]=1);e=Object.getPrototypeOf(e)}}function j(a){a.createdCallback&&a.createdCallback()}function k(a){var b=a.setAttribute;a.setAttribute=function(a,c){l.call(this,a,c,b)};var c=a.removeAttribute;a.removeAttribute=function(a){l.call(this,a,null,c)}}function l(a,b,c){var d=this.getAttribute(a);c.apply(this,arguments),this.attributeChangedCallback&&this.getAttribute(a)!==d&&this.attributeChangedCallback(a,d,b)}function m(a,b){if(v[a])throw new Error("Cannot register a tag more than once");v[a]=b}function n(a){return function(){return f(a)}}function o(a,b){var c=v[b||a];if(c){if(a==c.tag&&b==c.is)return new c.ctor;if(!b&&!c.is)return new c.ctor}if(b){var d=o(a);return d.setAttribute("is",b),d}var d=w(a);return a.indexOf("-")>=0&&h(d,HTMLElement),d}function p(a){if(!a.__upgraded__&&a.nodeType===Node.ELEMENT_NODE){var b=a.getAttribute("is"),c=v[b||a.localName];if(c){if(b&&c.tag==a.localName)return g(a,c);if(!b&&!c.extends)return g(a,c)}}}function q(b){var c=x.call(this,b);return a.upgradeAll(c),c}a||(a=window.CustomElements={flags:{}});var r=a.flags,s=Boolean(document.register),t=!r.register&&s;if(t){var u=function(){};a.registry={},a.upgradeElement=u,a.watchShadow=u,a.upgrade=u,a.upgradeAll=u,a.upgradeSubtree=u,a.observeDocument=u,a.upgradeDocument=u,a.takeRecords=u}else{var v={},w=document.createElement.bind(document),x=Node.prototype.cloneNode;document.register=b,document.createElement=o,Node.prototype.cloneNode=q,a.registry=v,a.upgrade=p}a.hasNative=s,a.useNative=t}(window.CustomElements),function(){function a(a){return"link"===a.localName&&a.getAttribute("rel")===b}var b=window.HTMLImports?HTMLImports.IMPORT_LINK_TYPE:"none",c={selectors:["link[rel="+b+"]"],map:{link:"parseLink"},parse:function(a){if(!a.__parsed){a.__parsed=!0;var b=a.querySelectorAll(c.selectors);d(b,function(a){c[c.map[a.localName]](a)}),CustomElements.upgradeDocument(a),CustomElements.observeDocument(a)}},parseLink:function(b){a(b)&&this.parseImport(b)},parseImport:function(a){a.content&&c.parse(a.content)}},d=Array.prototype.forEach.call.bind(Array.prototype.forEach);CustomElements.parser=c}(),function(){function a(){CustomElements.parser.parse(document),CustomElements.upgradeDocument(document);var a=window.Platform&&Platform.endOfMicrotask?Platform.endOfMicrotask:setTimeout;a(function(){CustomElements.ready=!0,CustomElements.readyTime=Date.now(),window.HTMLImports&&(CustomElements.elapsed=CustomElements.readyTime-HTMLImports.readyTime),document.body.dispatchEvent(new CustomEvent("WebComponentsReady",{bubbles:!0}))})}if("function"!=typeof window.CustomEvent&&(window.CustomEvent=function(a){var b=document.createEvent("HTMLEvents");return b.initEvent(a,!0,!0),b}),"complete"===document.readyState)a();else{var b=window.HTMLImports?"HTMLImportsLoaded":"loading"==document.readyState?"DOMContentLoaded":"load";window.addEventListener(b,a)}}(),function(){if(HTMLElement.prototype.createShadowRoot){var a=HTMLElement.prototype.createShadowRoot;HTMLElement.prototype.createShadowRoot=function(){var b=a.call(this);return b.host=this,b}}}();
diff --git a/pkg/custom_element/lib/custom_element.dart b/pkg/custom_element/lib/custom_element.dart index 98bef74..19824cf 100644 --- a/pkg/custom_element/lib/custom_element.dart +++ b/pkg/custom_element/lib/custom_element.dart
@@ -23,6 +23,8 @@ import 'package:meta/meta.dart'; import 'src/custom_tag_name.dart'; +part 'src/attribute_map.dart'; + // TODO(jmesserly): replace with a real custom element polyfill. // This is just something temporary. /** @@ -115,6 +117,7 @@ /** The web component element wrapped by this class. */ Element _host; List _shadowRoots; + _AttributeMap _attributes; /** * Shadow roots generated by dwc for each custom element, indexed by the @@ -171,6 +174,9 @@ * Note that [root] will be a [ShadowRoot] if the browser supports Shadow DOM. */ void created() {} + // Added for analyzer warnings + @deprecated + void createdCallback() {} /** Invoked when this component gets inserted in the DOM tree. */ void inserted() {} @@ -182,10 +188,8 @@ @deprecated void leftView() {} - // TODO(jmesserly): how do we implement this efficiently? - // See https://github.com/dart-lang/web-ui/issues/37 /** Invoked when any attribute of the component is modified. */ - void attributeChanged(String name, String oldValue, String newValue) {} + void attributeChanged(String name, String oldValue) {} get model => host.model; @@ -272,9 +276,12 @@ Node insertAllBefore(Iterable<Node> newChild, Node refChild) => host.insertAllBefore(newChild, refChild); - Map<String, String> get attributes => host.attributes; + Map<String, String> get attributes { + if (_attributes == null) _attributes = new _AttributeMap(this); + return _attributes; + } set attributes(Map<String, String> value) { - host.attributes = value; + (attributes as _AttributeMap)._replaceAll(value); } List<Element> get elements => host.children; @@ -316,10 +323,7 @@ String get nodeValue => host.nodeValue; - @deprecated - // TODO(sigmund): restore the old return type and call host.on when - // dartbug.com/8131 is fixed. - dynamic get on { throw new UnsupportedError('on is deprecated'); } + Events get on => host.on; String get contentEditable => host.contentEditable; set contentEditable(String v) { host.contentEditable = v; }
diff --git a/pkg/custom_element/lib/src/attribute_map.dart b/pkg/custom_element/lib/src/attribute_map.dart new file mode 100644 index 0000000..8af62c3 --- /dev/null +++ b/pkg/custom_element/lib/src/attribute_map.dart
@@ -0,0 +1,85 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of custom_element; + +/** + * Represents an attribute map of model values. If any items are added, + * removed, or replaced, then observers that are listening to [changes] + * will be notified. + */ +class _AttributeMap implements Map<String, String> { + final CustomElement _element; + final Map<String, String> _map; + + /** Creates an attribute map wrapping the host attributes. */ + _AttributeMap(CustomElement element) + : _element = element, _map = element.host.attributes; + + // Forward all read methods: + Iterable<String> get keys => _map.keys; + Iterable<String> get values => _map.values; + int get length =>_map.length; + bool get isEmpty => _map.isEmpty; + bool get isNotEmpty => _map.isNotEmpty; + bool containsValue(Object value) => _map.containsValue(value); + bool containsKey(Object key) => _map.containsKey(key); + String operator [](Object key) => _map[key]; + void forEach(void f(String key, String value)) => _map.forEach(f); + String toString() => _map.toString(); + + // Override the write methods and ensure attributeChanged is called: + void operator []=(String key, String value) { + int len = _map.length; + String oldValue = _map[key]; + _map[key] = value; + if (len != _map.length || !identical(oldValue, value)) { + _element.attributeChanged(key, oldValue); + } + } + + void addAll(Map<String, String> other) { + other.forEach((String key, String value) { this[key] = value; }); + } + + String putIfAbsent(String key, String ifAbsent()) { + int len = _map.length; + String result = _map.putIfAbsent(key, ifAbsent); + if (len != _map.length) { + _element.attributeChanged(key, null); + } + return result; + } + + String remove(Object key) { + int len = _map.length; + String result = _map.remove(key); + if (len != _map.length) { + _element.attributeChanged(key, result); + } + return result; + } + + void clear() { + int len = _map.length; + if (len > 0) { + _map.forEach((key, value) { + _element.attributeChanged(key, value); + }); + } + _map.clear(); + } + + /** + * This is not a [Map] method. We use it to implement "set attributes", which + * is a global replace operation. Rather than [clear] followed by [addAll], + * we try to be a bit smarter. + */ + void _replaceAll(Map<String, String> other) { + for (var key in keys) { + if (!other.containsKey(key)) remove(key); + } + addAll(other); + } +}
diff --git a/pkg/docgen/test/single_library_test.dart b/pkg/docgen/test/single_library_test.dart index 78c8a5d..dd4044e 100644 --- a/pkg/docgen/test/single_library_test.dart +++ b/pkg/docgen/test/single_library_test.dart
@@ -10,7 +10,7 @@ main() { group('Generate docs for', () { test('one simple file.', () { - var temporaryDir = new Directory('single_library').createTempSync(); + var temporaryDir = Directory.createSystemTempSync('single_library_'); var fileName = path.join(temporaryDir.path, 'temp.dart'); var file = new File(fileName); file.writeAsStringSync('''
diff --git a/pkg/observe/lib/src/bind_property.dart b/pkg/observe/lib/src/bind_property.dart index c8524e7..c35bfb9 100644 --- a/pkg/observe/lib/src/bind_property.dart +++ b/pkg/observe/lib/src/bind_property.dart
@@ -13,7 +13,7 @@ * * MyModel() { * ... - * _sub = bindProperty(_otherModel, const Symbol('value'), + * _sub = onPropertyChange(_otherModel, const Symbol('value'), * () => notifyProperty(this, const Symbol('prop')); * } * @@ -23,7 +23,8 @@ * * See also [notifyProperty]. */ -StreamSubscription bindProperty(Observable source, Symbol sourceName, +// TODO(jmesserly): make this an instance method? +StreamSubscription onPropertyChange(Observable source, Symbol sourceName, void callback()) { return source.changes.listen((records) { for (var record in records) {
diff --git a/pkg/observe/lib/src/observable.dart b/pkg/observe/lib/src/observable.dart index d39f84a..c5c56ab 100644 --- a/pkg/observe/lib/src/observable.dart +++ b/pkg/observe/lib/src/observable.dart
@@ -7,7 +7,7 @@ /** * Use `@observable` to make a field automatically observable. */ -const Object observable = const _ObservableAnnotation(); +const ObservableProperty observable = const ObservableProperty(); /** * Interface representing an observable object. This is used by data in @@ -124,7 +124,7 @@ if (field.isFinal || field.isStatic || field.isPrivate) continue; for (var meta in field.metadata) { - if (identical(observable, meta.reflectee)) { + if (meta.reflectee is ObservableProperty) { var name = field.simpleName; // Note: since this is a field, getting the value shouldn't execute // user code, so we don't need to worry about errors. @@ -220,12 +220,16 @@ /** - * The type of the `@observable` annotation. + * An annotation that is used to make a property observable. + * Normally this is used via the [observable] constant, for example: * - * Library private because you should be able to use the [observable] field - * to get the one and only instance. We could make it public though, if anyone - * needs it for some reason. + * class Monster { + * @observable int health; + * } + * + * If needed, you can subclass this to create another annotation that will also + * be treated as observable. */ -class _ObservableAnnotation { - const _ObservableAnnotation(); +class ObservableProperty { + const ObservableProperty(); }
diff --git a/pkg/observe/lib/transform.dart b/pkg/observe/lib/transform.dart index 029a017..d1e8139 100644 --- a/pkg/observe/lib/transform.dart +++ b/pkg/observe/lib/transform.dart
@@ -34,7 +34,8 @@ // as much work as applying the transform. We rather have some false // positives here, and then generate no outputs when we apply this // transform. - return input.readAsString().then((c) => c.contains("@observable")); + return input.readAsString().then( + (c) => c.contains("@observable") || c.contains("@published")); } Future apply(Transform transform) { @@ -102,8 +103,12 @@ _getSpan(SourceFile file, ASTNode node) => file.span(node.offset, node.end); -/** True if the node has the `@observable` annotation. */ -bool _hasObservable(AnnotatedNode node) => _hasAnnotation(node, 'observable'); +/** True if the node has the `@observable` or `@published` annotation. */ +// TODO(jmesserly): it is not good to be hard coding these. We should do a +// resolve and do a proper ObservableProperty subtype check. However resolve +// is very expensive in analyzer_experimental, so it isn't feasible yet. +bool _hasObservable(AnnotatedNode node) => + _hasAnnotation(node, 'observable') || _hasAnnotation(node, 'published'); bool _hasAnnotation(AnnotatedNode node, String name) { // TODO(jmesserly): this isn't correct if the annotation has been imported @@ -134,7 +139,7 @@ declaresObservable = true; } else if (id.name == 'ChangeNotifierBase') { declaresObservable = true; - } else if (id.name != 'PolymerElement' && id.name != 'CustomElement' + } else if (id.name != 'HtmlElement' && id.name != 'CustomElement' && id.name != 'Object') { // TODO(sigmund): this is conservative, consider using type-resolution to // improve this check. @@ -183,14 +188,13 @@ } if (_hasObservable(member)) { if (!declaresObservable) { - logger.warning('Observable fields should be put in an observable' - ' objects. Please declare that this class extends from ' + logger.warning('Observable fields should be put in an observable ' + 'objects. Please declare that this class extends from ' 'ObservableBase, includes ObservableMixin, or implements ' 'Observable.', _getSpan(file, member)); - } - _transformFields(member.fields, code, member.offset, member.end); + _transformFields(file, member, code, logger); var names = member.fields.variables.map((v) => v.name.name); @@ -289,40 +293,89 @@ _hasKeyword(fields.keyword, Keyword.FINAL); } -void _transformFields(VariableDeclarationList fields, TextEditTransaction code, - int begin, int end) { +void _transformFields(SourceFile file, FieldDeclaration member, + TextEditTransaction code, TransformLogger logger) { + final fields = member.fields; if (_isReadOnly(fields)) return; - var indent = guessIndent(code.original, begin); - var replace = new StringBuffer(); + // Private fields aren't supported: + for (var field in fields.variables) { + final name = field.name.name; + if (Identifier.isPrivateName(name)) { + logger.warning('Cannot make private field $name observable.', + _getSpan(file, field)); + return; + } + } // Unfortunately "var" doesn't work in all positions where type annotations // are allowed, such as "var get name". So we use "dynamic" instead. var type = 'dynamic'; if (fields.type != null) { type = _getOriginalCode(code, fields.type); + } else if (_hasKeyword(fields.keyword, Keyword.VAR)) { + // Replace 'var' with 'dynamic' + code.edit(fields.keyword.offset, fields.keyword.end, type); } - for (var field in fields.variables) { - var initializer = ''; - if (field.initializer != null) { - initializer = ' = ${_getOriginalCode(code, field.initializer)}'; - } + // Note: the replacements here are a bit subtle. It needs to support multiple + // fields declared via the same @observable, as well as preserving newlines. + // (Preserving newlines is important because it allows the generated code to + // be debugged without needing a source map.) + // + // For example: + // + // @observable + // @otherMetaData + // Foo + // foo = 1, bar = 2, + // baz; + // + // Will be transformed into something like: + // + // @observable + // @OtherMetaData() + // Foo + // get foo => __foo; Foo __foo = 1; set foo ...; ... bar ... + // @observable @OtherMetaData() Foo get baz => __baz; Foo baz; ... + // + // Metadata is moved to the getter. - var name = field.name.name; + String metadata = ''; + if (fields.variables.length > 1) { + metadata = member.metadata + .map((m) => _getOriginalCode(code, m)) + .join(' '); + } - // TODO(jmesserly): should we generate this one one line, so source maps - // don't break? - if (replace.length > 0) replace.write('\n\n$indent'); - replace.write(''' -$type __\$$name$initializer; -$type get $name => __\$$name; -set $name($type value) { - __\$$name = notifyPropertyChange(const Symbol('$name'), __\$$name, value); + for (int i = 0; i < fields.variables.length; i++) { + final field = fields.variables[i]; + final name = field.name.name; + + var beforeInit = 'get $name => __\$$name; $type __\$$name'; + + // The first field is expanded differently from subsequent fields, because + // we can reuse the metadata and type annotation. + if (i > 0) beforeInit = '$metadata $type $beforeInit'; + + code.edit(field.name.offset, field.name.end, beforeInit); + + // Replace comma with semicolon + final end = _findFieldSeperator(field.endToken.next); + if (end.type == TokenType.COMMA) code.edit(end.offset, end.end, ';'); + + code.edit(end.end, end.end, ' set $name($type value) { ' + '__\$$name = notifyPropertyChange(#$name, __\$$name, value); }'); + } } -'''.replaceAll('\n', '\n$indent')); - } - code.edit(begin, end, '$replace'); +Token _findFieldSeperator(Token token) { + while (token != null) { + if (token.type == TokenType.COMMA || token.type == TokenType.SEMICOLON) { + break; + } + token = token.next; + } + return token; }
diff --git a/pkg/observe/test/transform_test.dart b/pkg/observe/test/transform_test.dart index 9a64fac..5a4b138 100644 --- a/pkg/observe/test/transform_test.dart +++ b/pkg/observe/test/transform_test.dart
@@ -47,17 +47,24 @@ _testInitializers('this.a, {this.b}', '(a, {b}) : __\$a = a, __\$b = b'); }); - group('test full text', () { - test('with changes', () { - return _transform(_sampleObservable('A', 'foo')) - .then((output) => expect(output, _sampleObservableOutput('A', 'foo'))); - }); + for (var annotation in ['observable', 'published']) { + group('@$annotation full text', () { + test('with changes', () { + return _transform(_sampleObservable(annotation)).then( + (out) => expect(out, _sampleObservableOutput(annotation))); + }); - test('no changes', () { - var input = 'class A {/*@observable annotation to trigger transform */;}'; - return _transform(input).then((output) => expect(output, input)); + test('complex with changes', () { + return _transform(_complexObservable(annotation)).then( + (out) => expect(out, _complexObservableOutput(annotation))); + }); + + test('no changes', () { + var input = 'class A {/*@$annotation annotation to trigger transform */;}'; + return _transform(input).then((output) => expect(output, input)); + }); }); - }); + } } _testClause(String clauses, String expected) { @@ -121,37 +128,64 @@ Asset get primaryInput => _asset; _MockTransform(this._asset); - Future<Asset> getInput(Asset id) { + Future<Asset> getInput(AssetId id) { if (id == primaryInput.id) return new Future.value(primaryInput); - fail(); + fail('_MockTransform fail'); } void addOutput(Asset output) { outs.add(output); } + + readInput(id) => throw new UnimplementedError(); + readInputAsString(id, {encoding}) => throw new UnimplementedError(); } -String _sampleObservable(String className, String fieldName) => ''' -library ${className}_$fieldName; +String _sampleObservable(String annotation) => ''' +library A_foo; import 'package:observe/observe.dart'; -class $className extends ObservableBase { - @observable int $fieldName; - $className(this.$fieldName); +class A extends ObservableBase { + @$annotation int foo; + A(this.foo); } '''; -String _sampleObservableOutput(String className, String fieldName) => ''' -library ${className}_$fieldName; -import 'package:observe/observe.dart'; +String _sampleObservableOutput(String annotation) => + "library A_foo;\n" + "import 'package:observe/observe.dart';\n\n" + "class A extends ChangeNotifierBase {\n" + " @$annotation int get foo => __\$foo; int __\$foo; " + "${_makeSetter('int', 'foo')}\n" + " A(foo) : __\$foo = foo;\n" + "}\n"; -class $className extends ChangeNotifierBase { - int __\$$fieldName; - int get $fieldName => __\$$fieldName; - set $fieldName(int value) { - __\$$fieldName = notifyPropertyChange(const Symbol('$fieldName'), __\$$fieldName, value); - } - - $className($fieldName) : __\$$fieldName = $fieldName; +_makeSetter(type, name) => 'set $name($type value) { ' + '__\$$name = notifyPropertyChange(#$name, __\$$name, value); }'; + +String _complexObservable(String annotation) => ''' +class Foo extends ObservableBase { + @$annotation + @otherMetadata + Foo + foo/*D*/= 1, bar =/*A*/2/*B*/, + quux/*C*/; + + @$annotation var baz; } '''; + +String _complexObservableOutput(String annotation) => + "class Foo extends ChangeNotifierBase {\n" + " @$annotation\n" + " @otherMetadata\n" + " Foo\n" + " get foo => __\$foo; Foo __\$foo/*D*/= 1; " + "${_makeSetter('Foo', 'foo')} " + "@$annotation @otherMetadata Foo get bar => __\$bar; " + "Foo __\$bar =/*A*/2/*B*/; ${_makeSetter('Foo', 'bar')}\n" + " @$annotation @otherMetadata Foo get quux => __\$quux; " + "Foo __\$quux/*C*/; ${_makeSetter('Foo', 'quux')}\n\n" + " @$annotation dynamic get baz => __\$baz; dynamic __\$baz; " + "${_makeSetter('dynamic', 'baz')}\n" + "}\n";
diff --git a/pkg/pkg.status b/pkg/pkg.status index 9ff7d8d..d5c5205 100644 --- a/pkg/pkg.status +++ b/pkg/pkg.status
@@ -57,24 +57,42 @@ stack_trace/test/trace_test: Fail # http://dartbug.com/12380 crypto/test/sha256_test: Pass, Fail # Issue 12502 crypto/test/hmac_sha256_test: Pass, Fail # Issue 12502 -polymer/test/events_test: Fail # Issue 12865, 13197 +polymer/test/attr_deserialize_test: Fail # Issue 12865, 13197 +polymer/test/attr_mustache_test: Fail # Issue 12865, 13197 polymer/test/event_path_test: Fail # Issue 12865, 13197 +polymer/test/events_test: Fail # Issue 12865, 13197 +polymer/test/prop_attr_reflection_test: Fail # Issue 12865, 13197 [ $runtime == ie9 || $runtime == ie10 ] -polymer/test/events_test: Fail, Timeout # Issue 12865, 13197, 13260 +polymer/test/attr_deserialize_test: Fail, Timeout # Issue 12865, 13197, 13260 +polymer/test/attr_mustache_test: Fail, Timeout # Issue 12865, 13197, 13260 polymer/test/event_path_test: Fail, Timeout # Issue 12865, 13197, 13260 +polymer/test/events_test: Fail, Timeout # Issue 12865, 13197, 13260 +polymer/test/prop_attr_reflection_test: Fail, Timeout # Issue 12865, 13197, 13260 +polymer/test/publish_attributes_test: Fail, Timeout # Issue 12865, 13197, 13260 +polymer/test/take_attributes_test: Fail, Timeout # Issue 12865, 13197, 13260 [ $system == windows && ($runtime == chrome || $runtime == ff) ] -polymer/test/events_test: Pass, Timeout # Issue 13260 +polymer/test/attr_deserialize_test: Pass, Timeout # Issue 13260 +polymer/test/attr_mustache_test: Pass, Timeout # Issue 13260 polymer/test/event_path_test: Pass, Timeout # Issue 13260 +polymer/test/events_test: Pass, Timeout # Issue 13260 +polymer/test/prop_attr_reflection_test: Pass, Timeout # Issue 13260 +polymer/test/publish_attributes_test: Pass, Timeout # Issue 13260 +polymer/test/take_attributes_test: Pass, Timeout # Issue 13260 # Skip browser-specific tests on VM [ $runtime == vm ] path/test/browser_test: Fail, OK # Uses dart:html intl/test/find_default_locale_browser_test: Skip intl/test/date_time_format_http_request_test: Skip -polymer/test/events_test: Fail, OK # Uses dart:html +polymer/test/attr_deserialize_test: Fail, OK # Uses dart:html +polymer/test/attr_mustache_test: Fail, OK # Uses dart:html polymer/test/event_path_test: Fail, OK # Uses dart:html +polymer/test/events_test: Fail, OK # Uses dart:html +polymer/test/prop_attr_reflection_test: Fail, OK # Uses dart:html +polymer/test/publish_attributes_test: Fail, OK # Uses dart:html +polymer/test/take_attributes_test: Fail, OK # Uses dart:html polymer/example: Fail, OK # Uses dart:html [ $runtime == vm && $system == windows ] @@ -140,7 +158,6 @@ observe/test/transform_test: Fail, OK # Uses dart:io. path/test/io_test: Fail, OK # Uses dart:io. polymer/test/build/*: Fail, OK # Uses dart:io. -polymer/test/utils_test: Fail, OK # Uses dart:io. watcher/test/*: Fail, OK # Uses dart:io. scheduled_test/test/descriptor/async_test: Fail # http://dartbug.com/8440 @@ -182,17 +199,17 @@ # not minified. unittest/test/*_minified_test: Skip # DO NOT COPY THIS UNLESS YOU WORK ON DART2JS +[ $arch == mips ] +*: Skip # Issue 13650 + [ $arch == arm ] -*: Skip +*: Skip # Issue 13624 [ $arch == simarm ] -*: Skip +watcher/test/no_subscription_test: Pass, Fail # Issue 13705. -[ $arch == mips ] -*: Skip - -[ $arch == simmips ] -*: Skip +[ $arch == simarm || $arch == simmips ] +third_party/html5lib/test/tokenizer_test: Pass, Slow # Skip serialization test that explicitly has no library declaration in the # test on Dartium, which requires all tests to have a library.
diff --git a/pkg/polymer/example/component/news/web/news-component.html b/pkg/polymer/example/component/news/web/news-component.html index 7f63f54..70254b8 100644 --- a/pkg/polymer/example/component/news/web/news-component.html +++ b/pkg/polymer/example/component/news/web/news-component.html
@@ -31,7 +31,7 @@ @initMethod _init() { - registerPolymerElement('x-news', () => new XNews()); + Polymer.register('x-news', XNews); } </script> </polymer-element>
diff --git a/pkg/polymer/lib/boot.js b/pkg/polymer/lib/boot.js index 0a3fe62..2bcb590 100644 --- a/pkg/polymer/lib/boot.js +++ b/pkg/polymer/lib/boot.js
@@ -56,8 +56,30 @@ ' tool to compile a depolyable JavaScript version') return; } - document.write( - '<script src="packages/html_import/html_import.min.js"></script>'); + + + // Load HTML Imports: + var htmlImportsSrc = 'src="packages/html_import/html_import.min.js"'; + document.write('<script ' + htmlImportsSrc + '></script>'); + var importScript = document.querySelector('script[' + htmlImportsSrc + ']'); + importScript.addEventListener('load', function() { + // NOTE: this is from polymer/src/lib/dom.js + window.HTMLImports.importer.preloadSelectors += + ', polymer-element link[rel=stylesheet]'; + }); + + // TODO(jmesserly): we need this in deploy tool too. + // NOTE: this is from polymer/src/boot.js: + // FOUC prevention tactic + var style = document.createElement('style'); + style.textContent = 'body {opacity: 0;}'; + var head = document.querySelector('head'); + head.insertBefore(style, head.firstChild); + + window.addEventListener('WebComponentsReady', function() { + document.body.style.webkitTransition = 'opacity 0.3s'; + document.body.style.opacity = 1; + }); // Extract a Dart import URL from a script tag, which is the 'src' attribute // of the script tag, or a data-url with the script contents for inlined code.
diff --git a/pkg/polymer/lib/component_build.dart b/pkg/polymer/lib/component_build.dart index 6a923f0..cdd0820 100644 --- a/pkg/polymer/lib/component_build.dart +++ b/pkg/polymer/lib/component_build.dart
@@ -6,6 +6,7 @@ @deprecated library build_utils; +import 'dart:async'; import 'package:meta/meta.dart'; import 'builder.dart' as builder; @@ -18,5 +19,5 @@ Future build(List<String> arguments, List<String> entryPoints, {bool printTime: true, bool shouldPrint: true}) { return builder.build( - entryPoints: entryPoints, options: parseOptions(arguments)); + entryPoints: entryPoints, options: builder.parseOptions(arguments)); }
diff --git a/pkg/polymer/lib/deserialize.dart b/pkg/polymer/lib/deserialize.dart new file mode 100644 index 0000000..7f72c2c --- /dev/null +++ b/pkg/polymer/lib/deserialize.dart
@@ -0,0 +1,51 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +library polymer.deserialize; + +import 'dart:convert' show JSON; +import 'dart:mirrors' show reflect, TypeMirror; + +final _typeHandlers = () { + // TODO(jmesserly): switch to map and symbol literal form when supported. + var m = new Map(); + m[const Symbol('dart.core.String')] = (x, _) => x; + m[const Symbol('dart.core.Null')] = (x, _) => x; + m[const Symbol('dart.core.DateTime')] = (x, _) { + // TODO(jmesserly): shouldn't need to try-catch here + // See: https://code.google.com/p/dart/issues/detail?id=1878 + try { + return DateTime.parse(x); + } catch (e) { + return new DateTime.now(); + } + }; + m[const Symbol('dart.core.bool')] = (x, _) => x != 'false'; + m[const Symbol('dart.core.int')] = + (x, def) => int.parse(x, onError: (_) => def); + m[const Symbol('dart.core.double')] = + (x, def) => double.parse(x, (_) => def); + return m; +}(); + +/** + * Convert representation of [value] based on type of [defaultValue]. + */ +Object deserializeValue(String value, Object defaultValue, TypeMirror type) { + var handler = _typeHandlers[type.qualifiedName]; + if (handler != null) return handler(value, defaultValue); + + try { + // If the string is an object, we can parse is with the JSON library. + // include convenience replace for single-quotes. If the author omits + // quotes altogether, parse will fail. + return JSON.decode(value.replaceAll("'", '"')); + + // TODO(jmesserly): deserialized JSON is not assignable to most objects in + // Dart. We should attempt to convert it appropriately. + } catch(e) { + // The object isn't valid JSON, return the raw value + return value; + } +}
diff --git a/pkg/polymer/lib/job.dart b/pkg/polymer/lib/job.dart new file mode 100644 index 0000000..677784a --- /dev/null +++ b/pkg/polymer/lib/job.dart
@@ -0,0 +1,53 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +library polymer.job; + +import 'dart:async' show Timer; + +/** + * Invoke [callback] in [wait], unless the job is re-registered, + * which resets the timer. For example: + * + * _myJob = runJob(_myJob, callback, const Duration(milliseconds: 100)); + * + * Returns a job handle which can be used to re-register a job. + */ +// Dart note: renamed to runJob to avoid conflict with instance member "job". +Job runJob(Job job, void callback(), Duration wait) { + if (job != null) { + job.stop(); + } else { + job = new Job(); + } + job.go(callback, wait); + return job; +} + +// TODO(jmesserly): it isn't clear to me what is supposed to be public API here. +// Or what name we should use. "Job" is awfully generic. +// (The type itself is not exported in Polymer.) +class Job { + Function _callback; + Timer _timer; + + void go(void callback(), Duration wait) { + this._callback = callback; + _timer = new Timer(wait, complete); + } + + void stop() { + if (_timer != null) { + _timer.cancel(); + _timer = null; + } + } + + void complete() { + if (_timer != null) { + stop(); + _callback(); + } + } +}
diff --git a/pkg/polymer/lib/platform.dart b/pkg/polymer/lib/platform.dart new file mode 100644 index 0000000..5dc5c3e --- /dev/null +++ b/pkg/polymer/lib/platform.dart
@@ -0,0 +1,41 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/** + * Exposes helper functionality for interacting with the platform. Similar to + * the [Platform] class from dart:html. + */ +// TODO(jmesserly): in Polymer this is a static class called "Platform", but +// that conflicts with dart:html. What should we do? Does this functionality +// belong in html's Platform instead? +library polymer.platform; + +import 'dart:html' show Text, MutationObserver; +import 'dart:collection' show Queue; +import 'package:observe/src/microtask.dart' show performMicrotaskCheckpoint; + +void flush() { + endOfMicrotask(performMicrotaskCheckpoint); +} + +int _iterations = 0; +final Queue _callbacks = new Queue(); +final Text _twiddle = () { + var twiddle = new Text(''); + new MutationObserver((x, y) { + while (_callbacks.isNotEmpty) { + try { + _callbacks.removeFirst()(); + } catch (e) { // Dart note: fire the error async. + new Completer().completeError(e); + } + } + }).observe(twiddle, characterData: true); + return twiddle; +}(); + +void endOfMicrotask(void callback()) { + _twiddle.text = '${_iterations++}'; + _callbacks.add(callback); +}
diff --git a/pkg/polymer/lib/polymer.dart b/pkg/polymer/lib/polymer.dart index e417fe5..a7ae73f 100644 --- a/pkg/polymer/lib/polymer.dart +++ b/pkg/polymer/lib/polymer.dart
@@ -40,136 +40,31 @@ library polymer; import 'dart:async'; +import 'dart:collection' show HashMap; +import 'dart:html'; +import 'dart:js' as js; import 'dart:mirrors'; +import 'package:custom_element/custom_element.dart'; +import 'package:logging/logging.dart' show Logger, Level; import 'package:mdv/mdv.dart' as mdv; +import 'package:mdv/mdv.dart' show NodeBinding; +import 'package:meta/meta.dart' show deprecated; +import 'package:observe/observe.dart'; import 'package:observe/src/microtask.dart'; import 'package:path/path.dart' as path; -import 'polymer_element.dart' show registerPolymerElement; +import 'package:polymer_expressions/polymer_expressions.dart' + show PolymerExpressions; + +import 'deserialize.dart' as deserialize; +import 'job.dart'; +import 'platform.dart' as platform; export 'package:custom_element/custom_element.dart'; export 'package:observe/observe.dart'; export 'package:observe/html.dart'; export 'package:observe/src/microtask.dart'; -export 'polymer_element.dart'; - - -/** Annotation used to automatically register polymer elements. */ -class CustomTag { - final String tagName; - const CustomTag(this.tagName); -} - -/** - * Metadata used to label static or top-level methods that are called - * automatically when loading the library of a custom element. - */ -const initMethod = const _InitMethodAnnotation(); - -/** - * Initializes a polymer application as follows: - * * set up up polling for observable changes - * * initialize MDV - * * for each library in [libraries], register custom elements labeled with - * [CustomTag] and invoke the initialization method on it. - * - * The initialization on each library is either a method named `main` or - * a top-level function and annotated with [initMethod]. - * - * The urls in [libraries] can be absolute or relative to [srcUrl]. - */ -void initPolymer(List<String> libraries, [String srcUrl]) { - wrapMicrotask(() { - // DOM events don't yet go through microtasks, so we catch those here. - new Timer.periodic(new Duration(milliseconds: 125), - (_) => performMicrotaskCheckpoint()); - - // TODO(jmesserly): mdv should use initMdv instead of mdv.initialize. - mdv.initialize(); - for (var lib in libraries) { - _loadLibrary(lib, srcUrl); - } - })(); -} - -/** All libraries in the current isolate. */ -final _libs = currentMirrorSystem().libraries; - -/** - * Reads the library at [uriString] (which can be an absolute URI or a relative - * URI from [srcUrl]), and: - * - * * If present, invokes `main`. - * - * * If present, invokes any top-level and static functions marked - * with the [initMethod] annotation (in the order they appear). - * - * * Registers any [PolymerElement] that is marked with the [CustomTag] - * annotation. - */ -void _loadLibrary(String uriString, [String srcUrl]) { - var uri = Uri.parse(uriString); - if (uri.scheme == '' && srcUrl != null) { - uri = Uri.parse(path.normalize(path.join(path.dirname(srcUrl), uriString))); - } - var lib = _libs[uri]; - if (lib == null) { - print('warning: $uri library not found'); - return; - } - - // Invoke `main`, if present. - if (lib.functions[const Symbol('main')] != null) { - lib.invoke(const Symbol('main'), const []); - } - - // Search top-level functions marked with @initMethod - for (var f in lib.functions.values) { - _maybeInvoke(lib, f); - } - - for (var c in lib.classes.values) { - // Search for @CustomTag on classes - for (var m in c.metadata) { - var meta = m.reflectee; - if (meta is CustomTag) { - registerPolymerElement(meta.tagName, - () => c.newInstance(const Symbol(''), const []).reflectee); - } - } - - // TODO(sigmund): check also static methods marked with @initMethod. - // This is blocked on two bugs: - // - dartbug.com/12133 (static methods are incorrectly listed as top-level - // in dart2js, so they end up being called twice) - // - dartbug.com/12134 (sometimes "method.metadata" throws an exception, - // we could wrap and hide those exceptions, but it's not ideal). - } -} - -void _maybeInvoke(ObjectMirror obj, MethodMirror method) { - var annotationFound = false; - for (var meta in method.metadata) { - if (identical(meta.reflectee, initMethod)) { - annotationFound = true; - break; - } - } - if (!annotationFound) return; - if (!method.isStatic) { - print("warning: methods marked with @initMethod should be static," - " ${method.simpleName} is not."); - return; - } - if (!method.parameters.where((p) => !p.isOptional).isEmpty) { - print("warning: methods marked with @initMethod should take no " - "arguments, ${method.simpleName} expects some."); - return; - } - obj.invoke(method.simpleName, const []); -} - -class _InitMethodAnnotation { - const _InitMethodAnnotation(); -} +part 'src/declaration.dart'; +part 'src/instance.dart'; +part 'src/loader.dart';
diff --git a/pkg/polymer/lib/polymer_element.dart b/pkg/polymer/lib/polymer_element.dart index a7ade34..c004985 100644 --- a/pkg/polymer/lib/polymer_element.dart +++ b/pkg/polymer/lib/polymer_element.dart
@@ -4,555 +4,4 @@ library polymer.polymer_element; -import 'dart:async'; -import 'dart:html'; -import 'dart:mirrors'; -import 'dart:js' as js; - -import 'package:custom_element/custom_element.dart'; -import 'package:mdv/mdv.dart' show NodeBinding; -import 'package:observe/observe.dart'; -import 'package:observe/src/microtask.dart'; -import 'package:polymer_expressions/polymer_expressions.dart'; - -import 'src/utils.dart' show toCamelCase, toHyphenedName; - -/** - * Registers a [PolymerElement]. This is similar to [registerCustomElement] - * but it is designed to work with the `<element>` element and adds additional - * features. - */ -void registerPolymerElement(String localName, PolymerElement create()) { - registerCustomElement(localName, () => create().._initialize(localName)); -} - -/** - * *Warning*: many features of this class are not fully implemented. - * - * The base class for Polymer elements. It provides convience features on top - * of the custom elements web standard. - * - * Currently it supports publishing attributes via: - * - * <element name="..." attributes="foo, bar, baz"> - * - * Any attribute published this way can be used in a data binding expression, - * and it should contain a corresponding DOM field. - * - * *Warning*: due to dart2js mirror limititations, the mapping from HTML - * attribute to element property is a conversion from `dash-separated-words` - * to camelCase, rather than searching for a property with the same name. - */ -// TODO(jmesserly): fix the dash-separated-words issue. Polymer uses lowercase. -class PolymerElement extends CustomElement with _EventsMixin { - // This is a partial port of: - // https://github.com/Polymer/polymer/blob/stable/src/attrs.js - // https://github.com/Polymer/polymer/blob/stable/src/bindProperties.js - // https://github.com/Polymer/polymer/blob/7936ff8/src/declaration/events.js - // https://github.com/Polymer/polymer/blob/7936ff8/src/instance/events.js - // TODO(jmesserly): we still need to port more of the functionality - - /// The one syntax to rule them all. - static BindingDelegate _polymerSyntax = new PolymerExpressions(); - // TODO(sigmund): delete. The next line is only added to avoid warnings from - // the analyzer (see http://dartbug.com/11672) - Element get host => super.host; - - bool get applyAuthorStyles => false; - bool get resetStyleInheritance => false; - - /** - * The declaration of this polymer-element, used to extract template contents - * and other information. - */ - static Map<String, Element> _declarations = {}; - static Element getDeclaration(String localName) { - if (localName == null) return null; - var element = _declarations[localName]; - if (element == null) { - element = document.query('polymer-element[name="$localName"]'); - _declarations[localName] = element; - } - return element; - } - - Map<String, PathObserver> _publishedAttrs; - Map<String, StreamSubscription> _bindings; - final List<String> _localNames = []; - - void _initialize(String localName) { - if (localName == null) return; - - var declaration = getDeclaration(localName); - if (declaration == null) return; - - var extendee = declaration.attributes['extends']; - if (extendee != null) { - // Skip normal tags, only initialize parent custom elements. - if (extendee.contains('-')) _initialize(extendee); - } - - _parseHostEvents(declaration); - _parseLocalEvents(declaration); - _publishAttributes(declaration); - - var templateContent = declaration.query('template').content; - _shimStyling(templateContent, localName); - - _localNames.add(localName); - } - - void _publishAttributes(elementElement) { - _bindings = {}; - _publishedAttrs = {}; - - var attrs = elementElement.attributes['attributes']; - if (attrs != null) { - // attributes='a b c' or attributes='a,b,c' - for (var name in attrs.split(attrs.contains(',') ? ',' : ' ')) { - name = name.trim(); - - // TODO(jmesserly): PathObserver is overkill here; it helps avoid - // "new Symbol" and other mirrors-related warnings. - _publishedAttrs[name] = new PathObserver(this, toCamelCase(name)); - } - } - } - - void created() { - // TODO(jmesserly): this breaks until we get some kind of type conversion. - // _publishedAttrs.forEach((name, propObserver) { - // var value = attributes[name]; - // if (value != null) propObserver.value = value; - // }); - _initShadowRoot(); - _addHostListeners(); - } - - /** - * Creates the document fragment to use for each instance of the custom - * element, given the `<template>` node. By default this is equivalent to: - * - * template.createInstance(this, polymerSyntax); - * - * Where polymerSyntax is a singleton `PolymerExpressions` instance from the - * [polymer_expressions](https://pub.dartlang.org/packages/polymer_expressions) - * package. - * - * You can override this method to change the instantiation behavior of the - * template, for example to use a different data-binding syntax. - */ - DocumentFragment instanceTemplate(Element template) => - template.createInstance(this, _polymerSyntax); - - void _initShadowRoot() { - for (var localName in _localNames) { - var declaration = getDeclaration(localName); - var root = createShadowRoot(localName); - _addInstanceListeners(root, localName); - - root.applyAuthorStyles = applyAuthorStyles; - root.resetStyleInheritance = resetStyleInheritance; - - var templateNode = declaration.query('template'); - if (templateNode == null) return; - - // Create the contents of the element's ShadowRoot, and add them. - root.nodes.add(instanceTemplate(templateNode)); - } - } - - NodeBinding createBinding(String name, model, String path) { - var propObserver = _publishedAttrs[name]; - if (propObserver != null) { - return new _PolymerBinding(this, name, model, path, propObserver); - } - return super.createBinding(name, model, path); - } - - /** - * Using Polymer's platform/src/ShadowCSS.js passing the style tag's content. - */ - void _shimStyling(DocumentFragment template, String localName) { - if (js.context == null) return; - - var platform = js.context['Platform']; - if (platform == null) return; - - var style = template.query('style'); - if (style == null) return; - - var shadowCss = platform['ShadowCSS']; - if (shadowCss == null) return; - - // TODO(terry): Remove calls to shimShadowDOMStyling2 and replace with - // shimShadowDOMStyling when we support unwrapping dart:html - // Element to a JS DOM node. - var shimShadowDOMStyling2 = shadowCss['shimShadowDOMStyling2']; - if (shimShadowDOMStyling2 == null) return; - - var scopedCSS = shimShadowDOMStyling2.apply(shadowCss, - [style.text, localName]); - - // TODO(terry): Remove when shimShadowDOMStyling is called we don't need to - // replace original CSS with scoped CSS shimShadowDOMStyling - // does that. - style.text = scopedCSS; - } -} - -class _PolymerBinding extends NodeBinding { - final PathObserver _publishedAttr; - - _PolymerBinding(node, property, model, path, PathObserver this._publishedAttr) - : super(node, property, model, path); - - void boundValueChanged(newValue) { - _publishedAttr.value = newValue; - } -} - -/** - * Polymer features to handle the syntactic sugar on-* to declare to - * automatically map event handlers to instance methods of the [PolymerElement]. - * This mixin is a port of: - * https://github.com/Polymer/polymer/blob/7936ff8/src/declaration/events.js - * https://github.com/Polymer/polymer/blob/7936ff8/src/instance/events.js - */ -abstract class _EventsMixin { - // TODO(sigmund): implement the Dart equivalent of 'inheritDelegates' - // Notes about differences in the implementation below: - // - _templateDelegates: polymer stores the template delegates directly on - // the template node (see in parseLocalEvents: 't.delegates = {}'). Here we - // simply use a separate map, where keys are the name of the - // custom-element. - // - _listenLocal we return true/false and propagate that up, JS - // implementation does't forward the return value. - // - we don't keep the side-table (weak hash map) of unhandled events (see - // handleIfNotHandled) - // - we don't use event.type to dispatch events, instead we save the event - // name with the event listeners. We do so to avoid translating back and - // forth between Dom and Dart event names. - - // --------------------------------------------------------------------------- - // The following section was ported from: - // https://github.com/Polymer/polymer/blob/7936ff8/src/declaration/events.js - // --------------------------------------------------------------------------- - - /** Maps event names and their associated method in the element class. */ - final Map<String, String> _delegates = {}; - - /** Expected events per element node. */ - // TODO(sigmund): investigate whether we need more than 1 set of local events - // per element (why does the js implementation stores 1 per template node?) - final Map<String, Set<String>> _templateDelegates = - new Map<String, Set<String>>(); - - /** [host] is needed by this mixin, but not defined here. */ - Element get host; - - /** Attribute prefix used for declarative event handlers. */ - static const _eventPrefix = 'on-'; - - /** Whether an attribute declares an event. */ - static bool _isEvent(String attr) => attr.startsWith(_eventPrefix); - - /** Extracts events from the element tag attributes. */ - void _parseHostEvents(elementElement) { - for (var attr in elementElement.attributes.keys.where(_isEvent)) { - _delegates[toCamelCase(attr)] = elementElement.attributes[attr]; - } - } - - /** Extracts events under the element's <template>. */ - void _parseLocalEvents(elementElement) { - var name = elementElement.attributes["name"]; - if (name == null) return; - var events = null; - for (var template in elementElement.queryAll('template')) { - var content = template.content; - if (content != null) { - for (var child in content.children) { - events = _accumulateEvents(child, events); - } - } - } - if (events != null) { - _templateDelegates[name] = events; - } - } - - /** Returns all events names listened by [element] and it's children. */ - static Set<String> _accumulateEvents(Element element, [Set<String> events]) { - events = events == null ? new Set<String>() : events; - - // from: accumulateAttributeEvents, accumulateEvent - events.addAll(element.attributes.keys.where(_isEvent).map(toCamelCase)); - - // from: accumulateChildEvents - for (var child in element.children) { - _accumulateEvents(child, events); - } - - // from: accumulateTemplatedEvents - if (element.isTemplate) { - var content = element.content; - if (content != null) { - for (var child in content.children) { - _accumulateEvents(child, events); - } - } - } - return events; - } - - // --------------------------------------------------------------------------- - // The following section was ported from: - // https://github.com/Polymer/polymer/blob/7936ff8/src/instance/events.js - // --------------------------------------------------------------------------- - - /** Attaches event listeners on the [host] element. */ - void _addHostListeners() { - for (var eventName in _delegates.keys) { - _addNodeListener(host, eventName, - (e) => _hostEventListener(eventName, e)); - } - } - - void _addNodeListener(node, String onEvent, Function listener) { - // If [node] is an element (typically when listening for host events) we - // use directly the '.onFoo' event stream of the element instance. - if (node is Element) { - reflect(node).getField(new Symbol(onEvent)).reflectee.listen(listener); - return; - } - - // When [node] is not an element, most commonly when [node] is the - // shadow-root of the polymer-element, we find the appropriate static event - // stream providers and attach it to [node]. - var eventProvider = _eventStreamProviders[onEvent]; - if (eventProvider != null) { - eventProvider.forTarget(node).listen(listener); - return; - } - - // When no provider is available, mainly because of custom-events, we use - // the underlying event listeners from the DOM. - var eventName = onEvent.substring(2).toLowerCase(); // onOneTwo => onetwo - // Most events names in Dart match those in JS in lowercase except for some - // few events listed in this map. We expect these cases to be handled above, - // but just in case we include them as a safety net here. - var jsNameFixes = const { - 'animationend': 'webkitAnimationEnd', - 'animationiteration': 'webkitAnimationIteration', - 'animationstart': 'webkitAnimationStart', - 'doubleclick': 'dblclick', - 'fullscreenchange': 'webkitfullscreenchange', - 'fullscreenerror': 'webkitfullscreenerror', - 'keyadded': 'webkitkeyadded', - 'keyerror': 'webkitkeyerror', - 'keymessage': 'webkitkeymessage', - 'needkey': 'webkitneedkey', - 'speechchange': 'webkitSpeechChange', - }; - var fixedName = jsNameFixes[eventName]; - node.on[fixedName != null ? fixedName : eventName].listen(listener); - } - - void _addInstanceListeners(ShadowRoot root, String elementName) { - var events = _templateDelegates[elementName]; - if (events == null) return; - for (var eventName in events) { - _addNodeListener(root, eventName, - (e) => _instanceEventListener(eventName, e)); - } - } - - void _hostEventListener(String eventName, Event event) { - var method = _delegates[eventName]; - if (event.bubbles && method != null) { - _dispatchMethod(this, method, event, host); - } - } - - void _dispatchMethod(Object receiver, String methodName, Event event, - Node target) { - var detail = event is CustomEvent ? (event as CustomEvent).detail : null; - var args = [event, detail, target]; - - var method = new Symbol(methodName); - // TODO(sigmund): consider making event listeners list all arguments - // explicitly. Unless VM mirrors are optimized first, this reflectClass call - // will be expensive once custom elements extend directly from Element (see - // dartbug.com/11108). - var methodDecl = reflectClass(receiver.runtimeType).methods[method]; - if (methodDecl != null) { - // This will either truncate the argument list or extend it with extra - // null arguments, so it will match the signature. - // TODO(sigmund): consider accepting optional arguments when we can tell - // them appart from named arguments (see http://dartbug.com/11334) - args.length = methodDecl.parameters.where((p) => !p.isOptional).length; - } - reflect(receiver).invoke(method, args); - performMicrotaskCheckpoint(); - } - - bool _instanceEventListener(String eventName, Event event) { - if (event.bubbles) { - if (event.path == null || !ShadowRoot.supported) { - return _listenLocalNoEventPath(eventName, event); - } else { - return _listenLocal(eventName, event); - } - } - return false; - } - - bool _listenLocal(String eventName, Event event) { - var controller = null; - for (var target in event.path) { - // if we hit host, stop - if (target == host) return true; - - // find a controller for the target, unless we already found `host` - // as a controller - controller = (controller == host) ? controller : _findController(target); - - // if we have a controller, dispatch the event, and stop if the handler - // returns true - if (controller != null - && handleEvent(controller, eventName, event, target)) { - return true; - } - } - return false; - } - - // TODO(sorvell): remove when ShadowDOM polyfill supports event path. - // Note that _findController will not return the expected controller when the - // event target is a distributed node. This is because we cannot traverse - // from a composed node to a node in shadowRoot. - // This will be addressed via an event path api - // https://www.w3.org/Bugs/Public/show_bug.cgi?id=21066 - bool _listenLocalNoEventPath(String eventName, Event event) { - var target = event.target; - var controller = null; - while (target != null && target != host) { - controller = (controller == host) ? controller : _findController(target); - if (controller != null - && handleEvent(controller, eventName, event, target)) { - return true; - } - target = target.parent; - } - return false; - } - - // TODO(sigmund): investigate if this implementation is correct. Polymer looks - // up the shadow-root that contains [node] and uses a weak-hashmap to find the - // host associated with that root. This implementation assumes that the - // [node] is under [host]'s shadow-root. - Element _findController(Node node) => host.xtag; - - bool handleEvent( - Element controller, String eventName, Event event, Element element) { - // Note: local events are listened only in the shadow root. This dynamic - // lookup is used to distinguish determine whether the target actually has a - // listener, and if so, to determine lazily what's the target method. - var methodName = element.attributes[toHyphenedName(eventName)]; - if (methodName != null) { - _dispatchMethod(controller, methodName, event, element); - } - return event.bubbles; - } -} - - -/** Event stream providers per event name. */ -// TODO(sigmund): after dartbug.com/11108 is fixed, consider eliminating this -// table and using reflection instead. -const Map<String, EventStreamProvider> _eventStreamProviders = const { - 'onMouseWheel': Element.mouseWheelEvent, - 'onTransitionEnd': Element.transitionEndEvent, - 'onAbort': Element.abortEvent, - 'onBeforeCopy': Element.beforeCopyEvent, - 'onBeforeCut': Element.beforeCutEvent, - 'onBeforePaste': Element.beforePasteEvent, - 'onBlur': Element.blurEvent, - 'onChange': Element.changeEvent, - 'onClick': Element.clickEvent, - 'onContextMenu': Element.contextMenuEvent, - 'onCopy': Element.copyEvent, - 'onCut': Element.cutEvent, - 'onDoubleClick': Element.doubleClickEvent, - 'onDrag': Element.dragEvent, - 'onDragEnd': Element.dragEndEvent, - 'onDragEnter': Element.dragEnterEvent, - 'onDragLeave': Element.dragLeaveEvent, - 'onDragOver': Element.dragOverEvent, - 'onDragStart': Element.dragStartEvent, - 'onDrop': Element.dropEvent, - 'onError': Element.errorEvent, - 'onFocus': Element.focusEvent, - 'onInput': Element.inputEvent, - 'onInvalid': Element.invalidEvent, - 'onKeyDown': Element.keyDownEvent, - 'onKeyPress': Element.keyPressEvent, - 'onKeyUp': Element.keyUpEvent, - 'onLoad': Element.loadEvent, - 'onMouseDown': Element.mouseDownEvent, - 'onMouseMove': Element.mouseMoveEvent, - 'onMouseOut': Element.mouseOutEvent, - 'onMouseOver': Element.mouseOverEvent, - 'onMouseUp': Element.mouseUpEvent, - 'onPaste': Element.pasteEvent, - 'onReset': Element.resetEvent, - 'onScroll': Element.scrollEvent, - 'onSearch': Element.searchEvent, - 'onSelect': Element.selectEvent, - 'onSelectStart': Element.selectStartEvent, - 'onSubmit': Element.submitEvent, - 'onTouchCancel': Element.touchCancelEvent, - 'onTouchEnd': Element.touchEndEvent, - 'onTouchEnter': Element.touchEnterEvent, - 'onTouchLeave': Element.touchLeaveEvent, - 'onTouchMove': Element.touchMoveEvent, - 'onTouchStart': Element.touchStartEvent, - 'onFullscreenChange': Element.fullscreenChangeEvent, - 'onFullscreenError': Element.fullscreenErrorEvent, - 'onAutocomplete': FormElement.autocompleteEvent, - 'onAutocompleteError': FormElement.autocompleteErrorEvent, - 'onSpeechChange': InputElement.speechChangeEvent, - 'onCanPlay': MediaElement.canPlayEvent, - 'onCanPlayThrough': MediaElement.canPlayThroughEvent, - 'onDurationChange': MediaElement.durationChangeEvent, - 'onEmptied': MediaElement.emptiedEvent, - 'onEnded': MediaElement.endedEvent, - 'onLoadStart': MediaElement.loadStartEvent, - 'onLoadedData': MediaElement.loadedDataEvent, - 'onLoadedMetadata': MediaElement.loadedMetadataEvent, - 'onPause': MediaElement.pauseEvent, - 'onPlay': MediaElement.playEvent, - 'onPlaying': MediaElement.playingEvent, - 'onProgress': MediaElement.progressEvent, - 'onRateChange': MediaElement.rateChangeEvent, - 'onSeeked': MediaElement.seekedEvent, - 'onSeeking': MediaElement.seekingEvent, - 'onShow': MediaElement.showEvent, - 'onStalled': MediaElement.stalledEvent, - 'onSuspend': MediaElement.suspendEvent, - 'onTimeUpdate': MediaElement.timeUpdateEvent, - 'onVolumeChange': MediaElement.volumeChangeEvent, - 'onWaiting': MediaElement.waitingEvent, - 'onKeyAdded': MediaElement.keyAddedEvent, - 'onKeyError': MediaElement.keyErrorEvent, - 'onKeyMessage': MediaElement.keyMessageEvent, - 'onNeedKey': MediaElement.needKeyEvent, - 'onWebGlContextLost': CanvasElement.webGlContextLostEvent, - 'onWebGlContextRestored': CanvasElement.webGlContextRestoredEvent, - 'onPointerLockChange': Document.pointerLockChangeEvent, - 'onPointerLockError': Document.pointerLockErrorEvent, - 'onReadyStateChange': Document.readyStateChangeEvent, - 'onSelectionChange': Document.selectionChangeEvent, - 'onSecurityPolicyViolation': Document.securityPolicyViolationEvent, -}; +export 'polymer.dart' show PolymerElement, registerPolymerElement;
diff --git a/pkg/polymer/lib/src/build/linter.dart b/pkg/polymer/lib/src/build/linter.dart index 3ed9c50..6542df7 100644 --- a/pkg/polymer/lib/src/build/linter.dart +++ b/pkg/polymer/lib/src/build/linter.dart
@@ -16,8 +16,10 @@ import 'package:barback/barback.dart'; import 'package:html5lib/dom.dart'; import 'package:html5lib/dom_parsing.dart'; +import 'package:source_maps/span.dart'; import 'common.dart'; +import 'utils.dart'; typedef String MessageFormatter(String kind, String message, Span span); @@ -191,6 +193,9 @@ /** * Information needed about other polymer-element tags in order to validate * how they are used and extended. + * + * Note: these are only created for polymer-element, because pure custom + * elements don't have a declarative form. */ class _ElementSummary { final String tagName; @@ -284,6 +289,19 @@ node.sourceSpan); } + var attrs = node.attributes['attributes']; + if (attrs != null) { + var attrsSpan = node.attributeSpans['attributes']; + + // names='a b c' or names='a,b,c' + // record each name for publishing + for (var attr in attrs.split(attrs.contains(',') ? ',' : ' ')) { + // remove excess ws + attr = attr.trim(); + if (!_validateCustomAttributeName(attr, attrsSpan)) break; + } + } + var oldValue = _inPolymerElement; _inPolymerElement = true; super.visitElement(node); @@ -369,10 +387,13 @@ var info = _elements[customTagName]; if (info == null) { - _logger.warning('definition for custom element with tag name ' + // TODO(jmesserly): this warning is wrong if someone is using raw custom + // elements. Is there another way we can handle this warning that won't + // generate false positives? + _logger.warning('definition for Polymer element with tag name ' '"$customTagName" not found.', node.sourceSpan); return; - } + } var baseTag = info.baseExtendsTag; if (baseTag != null && !hasIsAttribute) { @@ -384,7 +405,7 @@ 'the custom element declaration.', node.sourceSpan); return; } - + if (hasIsAttribute && baseTag == null) { _logger.warning( 'custom element "$customTagName" doesn\'t declare any type ' @@ -393,7 +414,7 @@ 'the custom element declaration.', node.sourceSpan); return; } - + if (hasIsAttribute && baseTag != nodeTag) { _logger.warning( 'custom element "$customTagName" extends from "$baseTag". ' @@ -402,6 +423,20 @@ } } + /** + * Validate an attribute on a custom-element. Returns true if valid. + */ + bool _validateCustomAttributeName(String name, FileSpan span) { + if (name.contains('-')) { + var newName = toCamelCase(name); + _logger.warning('PolymerElement no longer recognizes attribute names with ' + 'dashes such as "$name". Use "$newName" or "${newName.toLowerCase()}" ' + 'instead (both forms are equivalent in HTML).', span); + return false; + } + return true; + } + /** Validate event handlers are used correctly. */ void _validateEventHandler(Element node, String name, String value) { if (!name.startsWith('on-')) { @@ -409,20 +444,29 @@ ' JavaScript event handler. Use the form ' 'on-event-name="handlerName" if you want a Dart handler ' 'that will automatically update the UI based on model changes.', - node.sourceSpan); + node.attributeSpans[name]); return; } if (!_inPolymerElement) { _logger.warning('Inline event handlers are only supported inside ' - 'declarations of <polymer-element>.', node.sourceSpan); + 'declarations of <polymer-element>.', node.attributeSpans[name]); + } + + var eventName = name.substring('on-'.length); + if (eventName.contains('-')) { + var newEvent = toCamelCase(eventName); + _logger.warning('Invalid event name "$name". After the "on-" the event ' + 'name should not use dashes. For example use "on-$newEvent" or ' + '"on-${newEvent.toLowerCase()}" (both forms are equivalent in HTML).', + node.attributeSpans[name]); } if (value.contains('.') || value.contains('(')) { _logger.warning('Invalid event handler body "$value". Declare a method ' 'in your custom element "void handlerName(event, detail, target)" ' 'and use the form $name="handlerName".', - node.sourceSpan); + node.attributeSpans[name]); } } }
diff --git a/pkg/polymer/lib/src/build/runner.dart b/pkg/polymer/lib/src/build/runner.dart index d940c18..3596e92 100644 --- a/pkg/polymer/lib/src/build/runner.dart +++ b/pkg/polymer/lib/src/build/runner.dart
@@ -105,7 +105,7 @@ final Set<String> _polymerPackageDependencies = [ 'analyzer_experimental', 'args', 'barback', 'browser', 'csslib', 'custom_element', 'fancy_syntax', 'html5lib', 'html_import', 'js', - 'logging', 'mdv', 'meta', 'mutation_observer', 'observe', 'path', 'polymer', + 'logging', 'mdv', 'meta', 'mutation_observer', 'observe', 'path' 'polymer_expressions', 'serialization', 'shadow_dom', 'source_maps', 'stack_trace', 'unittest', 'unmodifiable_collection', 'yaml'].toSet(); @@ -149,7 +149,9 @@ } for (var package in options.packageDirs.keys) { - // There is nothing to do in the 'polymer' package and its dependencies. + // There is nothing to do in the polymer package dependencies. + // However: in Polymer package *itself*, we need to replace ObservableMixin + // with ChangeNotifierMixin. if (!options.transformPolymerDependencies && _polymerPackageDependencies.contains(package)) continue; barback.updateTransformers(package, options.phases);
diff --git a/pkg/polymer/lib/src/utils.dart b/pkg/polymer/lib/src/build/utils.dart similarity index 100% rename from pkg/polymer/lib/src/utils.dart rename to pkg/polymer/lib/src/build/utils.dart
diff --git a/pkg/polymer/lib/src/declaration.dart b/pkg/polymer/lib/src/declaration.dart new file mode 100644 index 0000000..a7584b6 --- /dev/null +++ b/pkg/polymer/lib/src/declaration.dart
@@ -0,0 +1,713 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of polymer; + +/** + * **Deprecated**: use [Polymer.register] instead. + * + * Registers a [PolymerElement]. This is similar to [registerCustomElement] + * but it is designed to work with the `<element>` element and adds additional + * features. + */ +@deprecated +void registerPolymerElement(String localName, PolymerElement create()) { + Polymer._registerClassMirror(localName, reflect(create()).type); +} + +/** + * **Warning**: this class is experiental and subject to change. + * + * The implementation for the `polymer-element` element. + * + * Normally you do not need to use this class directly, see [PolymerElement]. + */ +class PolymerDeclaration extends CustomElement { + // Fully ported from revision: + // https://github.com/Polymer/polymer/blob/4dc481c11505991a7c43228d3797d28f21267779 + // + // src/declaration/attributes.js + // src/declaration/events.js + // src/declaration/polymer-element.js + // src/declaration/properties.js + // src/declaration/prototype.js (note: most code not needed in Dart) + // src/declaration/styles.js + // + // Not yet ported: + // src/declaration/path.js - blocked on HTMLImports.getDocumentUrl + + // TODO(jmesserly): these should be Type not ClassMirror. But we can't get + // from ClassMirror to Type yet in dart2js, so we use ClassMirror for now. + // See https://code.google.com/p/dart/issues/detail?id=12607 + ClassMirror _type; + ClassMirror get type => _type; + + // TODO(jmesserly): this is a cache, because it's tricky in Dart to get from + // ClassMirror -> Supertype. + ClassMirror _supertype; + ClassMirror get supertype => _supertype; + + // TODO(jmesserly): this is also a cache, since we can't store .element on + // each level of the __proto__ like JS does. + PolymerDeclaration _super; + PolymerDeclaration get superDeclaration => _super; + + String _name; + String get name => _name; + + /** + * Map of publish properties. Can be a [VariableMirror] or a [MethodMirror] + * representing a getter. If it is a getter, there will also be a setter. + */ + Map<String, DeclarationMirror> _publish; + + /** The names of published properties for this polymer-element. */ + Iterable<String> get publishedProperties => + _publish != null ? _publish.keys : const []; + + /** Same as [_publish] but with lower case names. */ + Map<String, DeclarationMirror> _publishLC; + + Map<String, Symbol> _observe; + + Map<Symbol, Object> _instanceAttributes; + + List<Element> _sheets; + List<Element> get sheets => _sheets; + + List<Element> _styles; + List<Element> get styles => _styles; + + DocumentFragment get templateContent { + final template = query('template'); + return template != null ? template.content : null; + } + + /** Maps event names and their associated method in the element class. */ + final Map<String, String> _eventDelegates = {}; + + /** Expected events per element node. */ + // TODO(sigmund): investigate whether we need more than 1 set of local events + // per element (why does the js implementation stores 1 per template node?) + Expando<Set<String>> _templateDelegates; + + void created() { + super.created(); + + // fetch the element name + _name = attributes['name']; + // install element definition, if ready + registerWhenReady(); + } + + void registerWhenReady() { + // if we have no prototype, wait + if (waitingForType(name)) { + return; + } + // fetch our extendee name + var extendee = attributes['extends']; + if (waitingForExtendee(extendee)) { + //console.warn(name + ': waitingForExtendee:' + extendee); + return; + } + // TODO(sjmiles): HTMLImports polyfill awareness: + // elements in the main document are likely to parse + // in advance of elements in imports because the + // polyfill parser is simulated + // therefore, wait for imports loaded before + // finalizing elements in the main document + // TODO(jmesserly): Polymer.dart waits for HTMLImportsLoaded, so I've + // removed "whenImportsLoaded" for now. Restore the workaround if needed. + _register(extendee); + } + + void _register(extendee) { + //console.group('registering', name); + register(name, extendee); + //console.groupEnd(); + // subclasses may now register themselves + _notifySuper(name); + } + + bool waitingForType(String name) { + if (_getRegisteredType(name) != null) return false; + + // then wait for a prototype + _waitType[name] = this; + // if explicitly marked as 'noscript' + if (attributes.containsKey('noscript')) { + // TODO(sorvell): CustomElements polyfill awareness: + // noscript elements should upgrade in logical order + // script injection ensures this under native custom elements; + // under imports + ce polyfills, scripts run before upgrades. + // dependencies should be ready at upgrade time so register + // prototype at this time. + // TODO(jmesserly): I'm not sure how to port this; since script + // injection doesn't work for Dart, we'll just call Polymer.register + // here and hope for the best. + Polymer.register(name); + } + return true; + } + + bool waitingForExtendee(String extendee) { + // if extending a custom element... + if (extendee != null && extendee.indexOf('-') >= 0) { + // wait for the extendee to be _registered first + if (!_isRegistered(extendee)) { + _waitSuper.putIfAbsent(extendee, () => []).add(this); + return true; + } + } + return false; + } + + void register(String name, String extendee) { + // build prototype combining extendee, Polymer base, and named api + buildType(name, extendee); + + // back reference declaration element + // TODO(sjmiles): replace `element` with `elementElement` or `declaration` + _declarations[_type] = this; + + // more declarative features + desugar(); + + // TODO(sorvell): install a helper method this.resolvePath to aid in + // setting resource paths. e.g. + // this.$.image.src = this.resolvePath('images/foo.png') + // Potentially remove when spec bug is addressed. + // https://www.w3.org/Bugs/Public/show_bug.cgi?id=21407 + // TODO(jmesserly): resolvePath not ported, see first comment in this class. + + // under ShadowDOMPolyfill, transforms to approximate missing CSS features + _shimShadowDomStyling(templateContent, name); + + // register our custom element + registerType(name); + + // NOTE: skip in Dart because we don't have mutable global scope. + // reference constructor in a global named by 'constructor' attribute + // publishConstructor(); + } + + /** + * Gets the Dart type registered for this name, and sets up declarative + * features. Fills in the [type] and [supertype] fields. + * + * *Note*: unlike the JavaScript version, we do not have to metaprogram the + * prototype, which simplifies this method. + */ + void buildType(String name, String extendee) { + // get our custom type + _type = _getRegisteredType(name); + + // get basal prototype + _supertype = _getRegisteredType(extendee); + if (supertype != null) _super = _getDeclaration(supertype); + + // transcribe `attributes` declarations onto own prototype's `publish` + publishAttributes(type, _super); + + publishProperties(type); + + inferObservers(type); + + // Skip the rest in Dart: + // chain various meta-data objects to inherited versions + // chain custom api to inherited + // build side-chained lists to optimize iterations + // inherit publishing meta-data + //this.inheritAttributesObjects(prototype); + //this.inheritDelegates(prototype); + // x-platform fixups + } + + /** Implement various declarative features. */ + void desugar() { + // compile list of attributes to copy to instances + accumulateInstanceAttributes(); + // parse on-* delegates declared on `this` element + parseHostEvents(); + // parse on-* delegates declared in templates + parseLocalEvents(); + // install external stylesheets as if they are inline + installSheets(); + // TODO(jmesserly): this feels unnatrual in Dart. Since we have convenient + // lazy static initialization, can we get by without it? + var registered = type.methods[const Symbol('registerCallback')]; + if (registered != null && registered.isStatic && + registered.isRegularMethod) { + type.invoke(const Symbol('registerCallback'), [this]); + } + + } + + void registerType(String name) { + // TODO(jmesserly): document.register + registerCustomElement(name, () => + type.newInstance(const Symbol(''), const []).reflectee); + } + + void publishAttributes(ClassMirror type, PolymerDeclaration superDecl) { + // get properties to publish + if (superDecl != null && superDecl._publish != null) { + _publish = new Map.from(superDecl._publish); + } + _publish = _getProperties(type, _publish, (x) => x is PublishedProperty); + + // merge names from 'attributes' attribute + var attrs = attributes['attributes']; + if (attrs != null) { + // names='a b c' or names='a,b,c' + // record each name for publishing + for (var attr in attrs.split(attrs.contains(',') ? ',' : ' ')) { + // remove excess ws + attr = attr.trim(); + + // do not override explicit entries + if (_publish != null && _publish.containsKey(attr)) continue; + + var property = new Symbol(attr); + var mirror = type.variables[property]; + if (mirror == null) { + mirror = type.getters[property]; + if (mirror != null && !_hasSetter(type, mirror)) mirror = null; + } + if (mirror == null) { + window.console.warn('property for attribute $attr of polymer-element ' + 'name=$name not found.'); + continue; + } + if (_publish == null) _publish = {}; + _publish[attr] = mirror; + } + } + + // NOTE: the following is not possible in Dart; fields must be declared. + // install 'attributes' as properties on the prototype, + // but don't override + } + + void accumulateInstanceAttributes() { + // inherit instance attributes + _instanceAttributes = new Map<Symbol, Object>(); + if (_super != null) _instanceAttributes.addAll(_super._instanceAttributes); + + // merge attributes from element + attributes.forEach((name, value) { + if (isInstanceAttribute(name)) { + _instanceAttributes[new Symbol(name)] = value; + } + }); + } + + static bool isInstanceAttribute(name) { + // do not clone these attributes onto instances + final blackList = const { + 'name': 1, 'extends': 1, 'constructor': 1, 'noscript': 1, + 'attributes': 1}; + + return !blackList.containsKey(name) && !name.startsWith('on-'); + } + + /** Extracts events from the element tag attributes. */ + void parseHostEvents() { + addAttributeDelegates(_eventDelegates); + } + + void addAttributeDelegates(Map<String, String> delegates) { + attributes.forEach((name, value) { + if (_hasEventPrefix(name)) { + delegates[_removeEventPrefix(name)] = value; + } + }); + } + + /** Extracts events under the element's <template>. */ + void parseLocalEvents() { + for (var t in queryAll('template')) { + final events = new Set<String>(); + // acquire delegates from entire subtree at t + accumulateTemplatedEvents(t, events); + if (events.isNotEmpty) { + // store delegate information directly on template + if (_templateDelegates == null) { + _templateDelegates = new Expando<Set<String>>(); + } + _templateDelegates[t] = events; + } + } + } + + void accumulateTemplatedEvents(Element node, Set<String> events) { + if (node.localName == 'template' && node.content != null) { + accumulateChildEvents(node.content, events); + } + } + + void accumulateChildEvents(node, Set<String> events) { + assert(node is Element || node is DocumentFragment); + for (var n in node.children) { + accumulateEvents(n, events); + } + } + + void accumulateEvents(Element node, Set<String> events) { + accumulateAttributeEvents(node, events); + accumulateChildEvents(node, events); + accumulateTemplatedEvents(node, events); + } + + void accumulateAttributeEvents(Element node, Set<String> events) { + for (var name in node.attributes.keys) { + if (_hasEventPrefix(name)) { + accumulateEvent(_removeEventPrefix(name), events); + } + } + } + + void accumulateEvent(String name, Set<String> events) { + var translated = _eventTranslations[name]; + events.add(translated != null ? translated : name); + } + + String urlToPath(String url) { + if (url == null) return ''; + return (url.split('/')..removeLast()..add('')).join('/'); + } + + /** + * Install external stylesheets loaded in <element> elements into the + * element's template. + */ + void installSheets() { + cacheSheets(); + cacheStyles(); + installLocalSheets(); + installGlobalStyles(); + } + + void cacheSheets() { + _sheets = findNodes(_SHEET_SELECTOR); + for (var s in sheets) s.remove(); + } + + void cacheStyles() { + _styles = findNodes('$_STYLE_SELECTOR[$_SCOPE_ATTR]'); + for (var s in styles) s.remove(); + } + + /** + * Takes external stylesheets loaded in an `<element>` element and moves + * their content into a style element inside the `<element>`'s template. + * The sheet is then removed from the `<element>`. This is done only so + * that if the element is loaded in the main document, the sheet does + * not become active. + * Note, ignores sheets with the attribute 'polymer-scope'. + */ + void installLocalSheets() { + var sheets = this.sheets.where( + (s) => !s.attributes.containsKey(_SCOPE_ATTR)); + var content = this.templateContent; + if (content != null) { + var cssText = new StringBuffer(); + for (var sheet in sheets) { + cssText..write(_cssTextFromSheet(sheet))..write('\n'); + } + if (cssText.length > 0) { + content.insertBefore( + new StyleElement()..text = '$cssText', + content.firstChild); + } + } + } + + List<Element> findNodes(String selector, [bool matcher(Element e)]) { + var nodes = this.queryAll(selector).toList(); + var content = this.templateContent; + if (content != null) { + nodes = nodes..addAll(content.queryAll(selector)); + } + if (matcher != null) return nodes.where(matcher).toList(); + return nodes; + } + + /** + * Promotes external stylesheets and style elements with the attribute + * polymer-scope='global' into global scope. + * This is particularly useful for defining @keyframe rules which + * currently do not function in scoped or shadow style elements. + * (See wkb.ug/72462) + */ + // TODO(sorvell): remove when wkb.ug/72462 is addressed. + void installGlobalStyles() { + var style = styleForScope(_STYLE_GLOBAL_SCOPE); + _applyStyleToScope(style, document.head); + } + + String cssTextForScope(String scopeDescriptor) { + var cssText = new StringBuffer(); + // handle stylesheets + var selector = '[$_SCOPE_ATTR=$scopeDescriptor]'; + matcher(s) => s.matches(selector); + + for (var sheet in sheets.where(matcher)) { + cssText..write(_cssTextFromSheet(sheet))..write('\n\n'); + } + // handle cached style elements + for (var style in styles.where(matcher)) { + cssText..write(style.textContent)..write('\n\n'); + } + return cssText.toString(); + } + + StyleElement styleForScope(String scopeDescriptor) { + var cssText = cssTextForScope(scopeDescriptor); + return cssTextToScopeStyle(cssText, scopeDescriptor); + } + + StyleElement cssTextToScopeStyle(String cssText, String scopeDescriptor) { + if (cssText == '') return null; + + return new StyleElement() + ..text = cssText + ..attributes[_STYLE_SCOPE_ATTRIBUTE] = '$name-$scopeDescriptor'; + } + + /** + * fetch a list of all observable properties names in our inheritance chain + * above Polymer. + */ + // TODO(sjmiles): perf: reflection is slow, relatively speaking + // If an element may take 6us to create, getCustomPropertyNames might + // cost 1.6us more. + void inferObservers(ClassMirror type) { + for (var method in type.methods.values) { + if (method.isStatic || !method.isRegularMethod) continue; + + String name = MirrorSystem.getName(method.simpleName); + if (name.endsWith('Changed')) { + if (_observe == null) _observe = {}; + name = name.substring(0, name.length - 7); + _observe[name] = method.simpleName; + } + } + } + + void publishProperties(ClassMirror type) { + // Dart note: _publish was already populated by publishAttributes + if (_publish != null) _publishLC = _lowerCaseMap(_publish); + } + + Map<String, dynamic> _lowerCaseMap(Map<String, dynamic> properties) { + final map = new Map<String, dynamic>(); + properties.forEach((name, value) { + map[name.toLowerCase()] = value; + }); + return map; + } +} + +/// maps tag names to prototypes +final Map _typesByName = new Map<String, ClassMirror>(); + +ClassMirror _getRegisteredType(String name) => _typesByName[name]; + +/// elements waiting for prototype, by name +final Map _waitType = new Map<String, PolymerDeclaration>(); + +void _notifyType(String name) { + var waiting = _waitType.remove(name); + if (waiting != null) waiting.registerWhenReady(); +} + +/// elements waiting for super, by name +final Map _waitSuper = new Map<String, List<PolymerDeclaration>>(); + +void _notifySuper(String name) { + _registered.add(name); + var waiting = _waitSuper.remove(name); + if (waiting != null) { + for (var w in waiting) { + w.registerWhenReady(); + } + } +} + +/// track document.register'ed tag names +final Set _registered = new Set<String>(); + +bool _isRegistered(name) => _registered.contains(name); + +final Map _declarations = new Map<ClassMirror, PolymerDeclaration>(); + +PolymerDeclaration _getDeclaration(ClassMirror type) => _declarations[type]; + +final _objectType = reflectClass(Object); + +Map _getProperties(ClassMirror type, Map props, bool matches(metadata)) { + for (var field in type.variables.values) { + if (field.isFinal || field.isStatic || field.isPrivate) continue; + + for (var meta in field.metadata) { + if (matches(meta.reflectee)) { + if (props == null) props = {}; + props[MirrorSystem.getName(field.simpleName)] = field; + break; + } + } + } + + for (var getter in type.getters.values) { + if (getter.isStatic || getter.isPrivate) continue; + + for (var meta in getter.metadata) { + if (matches(meta.reflectee)) { + if (_hasSetter(type, getter)) { + if (props == null) props = {}; + props[MirrorSystem.getName(getter.simpleName)] = getter; + } + break; + } + } + } + + return props; +} + +bool _hasSetter(ClassMirror type, MethodMirror getter) { + var setterName = new Symbol('${MirrorSystem.getName(getter.simpleName)}='); + return type.setters.containsKey(setterName); +} + +bool _inDartHtml(ClassMirror type) => + type.owner.simpleName == const Symbol('dart.dom.html'); + + +/** Attribute prefix used for declarative event handlers. */ +const _EVENT_PREFIX = 'on-'; + +/** Whether an attribute declares an event. */ +bool _hasEventPrefix(String attr) => attr.startsWith(_EVENT_PREFIX); + +String _removeEventPrefix(String name) => name.substring(_EVENT_PREFIX.length); + +/** + * Using Polymer's platform/src/ShadowCSS.js passing the style tag's content. + */ +void _shimShadowDomStyling(DocumentFragment template, String localName) { + if (js.context == null || template == null) return; + + var platform = js.context['Platform']; + if (platform == null) return; + + var style = template.query('style'); + if (style == null) return; + + var shadowCss = platform['ShadowCSS']; + if (shadowCss == null) return; + + // TODO(terry): Remove calls to shimShadowDOMStyling2 and replace with + // shimShadowDOMStyling when we support unwrapping dart:html + // Element to a JS DOM node. + var shimShadowDOMStyling2 = shadowCss['shimShadowDOMStyling2']; + if (shimShadowDOMStyling2 == null) return; + + var scopedCSS = shimShadowDOMStyling2.apply(shadowCss, + [style.text, localName]); + + // TODO(terry): Remove when shimShadowDOMStyling is called we don't need to + // replace original CSS with scoped CSS shimShadowDOMStyling + // does that. + style.text = scopedCSS; +} + +const _STYLE_SELECTOR = 'style'; +const _SHEET_SELECTOR = '[rel=stylesheet]'; +const _STYLE_GLOBAL_SCOPE = 'global'; +const _SCOPE_ATTR = 'polymer-scope'; +const _STYLE_SCOPE_ATTRIBUTE = 'element'; + +void _applyStyleToScope(StyleElement style, Node scope) { + if (style == null) return; + + // TODO(sorvell): necessary for IE + // see https://connect.microsoft.com/IE/feedback/details/790212/ + // cloning-a-style-element-and-adding-to-document-produces + // -unexpected-result#details + // var clone = style.cloneNode(true); + var clone = new StyleElement()..text = style.text; + + var attr = style.attributes[_STYLE_SCOPE_ATTRIBUTE]; + if (attr != null) { + clone.attributes[_STYLE_SCOPE_ATTRIBUTE] = attr; + } + + scope.append(clone); +} + +String _cssTextFromSheet(Element sheet) { + if (sheet == null || js.context == null) return ''; + + // TODO(jmesserly): this is a hacky way to communcate with HTMLImports... + + // Remove rel=stylesheet, href to keep this inert. + var href = sheet.attributes.remove('href'); + var rel = sheet.attributes.remove('rel'); + document.body.append(sheet); + String resource; + try { + resource = js.context['document']['body']['lastChild']['__resource']; + } finally { + sheet.remove(); + if (href != null) sheet.attributes['href'] = href; + if (rel != null) sheet.attributes['rel'] = rel; + } + return resource != null ? resource : ''; +} + +const _OBSERVE_SUFFIX = 'Changed'; + +// TODO(jmesserly): is this list complete? +final _eventTranslations = const { + // TODO(jmesserly): these three Polymer.js translations won't work in Dart, + // because we strip the webkit prefix (below). Reconcile. + 'webkitanimationstart': 'webkitAnimationStart', + 'webkitanimationend': 'webkitAnimationEnd', + 'webkittransitionend': 'webkitTransitionEnd', + + 'domfocusout': 'DOMFocusOut', + 'domfocusin': 'DOMFocusIn', + + // TODO(jmesserly): Dart specific renames. Reconcile with Polymer.js + 'animationend': 'webkitAnimationEnd', + 'animationiteration': 'webkitAnimationIteration', + 'animationstart': 'webkitAnimationStart', + 'doubleclick': 'dblclick', + 'fullscreenchange': 'webkitfullscreenchange', + 'fullscreenerror': 'webkitfullscreenerror', + 'keyadded': 'webkitkeyadded', + 'keyerror': 'webkitkeyerror', + 'keymessage': 'webkitkeymessage', + 'needkey': 'webkitneedkey', + 'speechchange': 'webkitSpeechChange', +}; + +final _reverseEventTranslations = () { + final map = new Map<String, String>(); + _eventTranslations.forEach((onName, eventType) { + map[eventType] = onName; + }); + return map; +}(); + +// Dart note: we need this function because we have additional renames JS does +// not have. The JS renames are simply case differences, whereas we have ones +// like doubleclick -> dblclick and stripping the webkit prefix. +String _eventNameFromType(String eventType) { + final result = _reverseEventTranslations[eventType]; + return result != null ? result : eventType; +}
diff --git a/pkg/polymer/lib/src/instance.dart b/pkg/polymer/lib/src/instance.dart new file mode 100644 index 0000000..f0bff99 --- /dev/null +++ b/pkg/polymer/lib/src/instance.dart
@@ -0,0 +1,930 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of polymer; + +/** + * Use this annotation to publish a field as an attribute. For example: + * + * class MyPlaybackElement extends PolymerElement { + * // This will be available as an HTML attribute, for example: + * // <my-playback volume="11"> + * @published double volume; + * } + */ +// TODO(jmesserly): does @published imply @observable or vice versa? +const published = const PublishedProperty(); + +/** An annotation used to publish a field as an attribute. See [published]. */ +class PublishedProperty extends ObservableProperty { + const PublishedProperty(); +} + +// TODO(jmesserly): make this the mixin so we can have Polymer type extensions, +// and move the implementation of PolymerElement in here. Once done it will look +// like: +// abstract class Polymer { ... all the things ... } +// typedef PolymerElement = HtmlElement with Polymer, Observable; +abstract class Polymer { + // TODO(jmesserly): should this really be public? + /** Regular expression that matches data-bindings. */ + static final bindPattern = new RegExp(r'\{\{([^{}]*)}}'); + + /** + * Like [document.register] but for Polymer elements. + * + * Use the [name] to specify custom elment's tag name, for example: + * "fancy-button" if the tag is used as `<fancy-button>`. + * + * The [type] is the type to construct. If not supplied, it defaults to + * [PolymerElement]. + */ + // NOTE: this is called "element" in src/declaration/polymer-element.js, and + // exported as "Polymer". + static void register(String name, [Type type]) { + //console.log('registering [' + name + ']'); + if (type == null) type = PolymerElement; + _registerClassMirror(name, reflectClass(type)); + } + + // TODO(jmesserly): we use ClassMirror internall for now, until it is possible + // to get from ClassMirror -> Type. + static void _registerClassMirror(String name, ClassMirror type) { + _typesByName[name] = type; + // notify the registrar waiting for 'name', if any + _notifyType(name); + } +} + +/** + * The base class for Polymer elements. It provides convience features on top + * of the custom elements web standard. + */ +class PolymerElement extends CustomElement with ObservableMixin { + // Fully ported from revision: + // https://github.com/Polymer/polymer/blob/4dc481c11505991a7c43228d3797d28f21267779 + // + // src/instance/attributes.js + // src/instance/base.js + // src/instance/events.js + // src/instance/mdv.js + // src/instance/properties.js + // src/instance/utils.js + // + // Not yet ported: + // src/instance/style.js -- blocked on ShadowCSS.shimPolyfillDirectives + + /// The one syntax to rule them all. + static final BindingDelegate _polymerSyntax = new PolymerExpressions(); + + static int _preparingElements = 0; + + PolymerDeclaration _declaration; + + /** The most derived `<polymer-element>` declaration for this element. */ + PolymerDeclaration get declaration => _declaration; + + Map<String, StreamSubscription> _elementObservers; + bool _unbound; // lazy-initialized + Job _unbindAllJob; + + bool get _elementPrepared => _declaration != null; + + bool get applyAuthorStyles => false; + bool get resetStyleInheritance => false; + bool get alwaysPrepare => false; + + /** + * Shadow roots created by [parseElement]. See [getShadowRoot]. + */ + final _shadowRoots = new HashMap<String, ShadowRoot>(); + + /** Map of items in the shadow root(s) by their [Element.id]. */ + // TODO(jmesserly): various issues: + // * wrap in UnmodifiableMapView? + // * should we have an object that implements noSuchMethod? + // * should the map have a key order (e.g. LinkedHash or SplayTree)? + // * should this be a live list? Polymer doesn't, maybe due to JS limitations? + // For now I picked the most performant choice: non-live HashMap. + final Map<String, Element> $ = new HashMap<String, Element>(); + + /** + * Gets the shadow root associated with the corresponding custom element. + * + * This is identical to [shadowRoot], unless there are multiple levels of + * inheritance and they each have their own shadow root. For example, + * this can happen if the base class and subclass both have `<template>` tags + * in their `<polymer-element>` tags. + */ + // TODO(jmesserly): Polymer does not have this feature. Reconcile. + ShadowRoot getShadowRoot(String customTagName) => _shadowRoots[customTagName]; + + ShadowRoot createShadowRoot([name]) { + if (name != null) { + throw new ArgumentError('name argument must not be supplied.'); + } + + // Provides ability to traverse from ShadowRoot to the host. + // TODO(jmessery): remove once we have this ability on the DOM. + final root = super.createShadowRoot(); + _shadowHost[root] = host; + return root; + } + + /** + * Invoke [callback] in [wait], unless the job is re-registered, + * which resets the timer. For example: + * + * _myJob = job(_myJob, callback, const Duration(milliseconds: 100)); + * + * Returns a job handle which can be used to re-register a job. + */ + Job job(Job job, void callback(), Duration wait) => + runJob(job, callback, wait); + + // TODO(jmesserly): I am not sure if we should have the + // created/createdCallback distinction. See post here: + // https://groups.google.com/d/msg/polymer-dev/W0ZUpU5caIM/v5itFnvnehEJ + // Same issue with inserted and removed. + void created() { + if (document.window != null || alwaysPrepare || _preparingElements > 0) { + prepareElement(); + } + } + + void prepareElement() { + // Dart note: get the _declaration, which also marks _elementPrepared + _declaration = _getDeclaration(reflect(this).type); + // do this first so we can observe changes during initialization + observeProperties(); + // install boilerplate attributes + copyInstanceAttributes(); + // process input attributes + takeAttributes(); + // add event listeners + addHostListeners(); + // guarantees that while preparing, any sub-elements will also be prepared + _preparingElements++; + // process declarative resources + parseDeclarations(_declaration); + _preparingElements--; + // user entry point + ready(); + } + + /** Called when [prepareElement] is finished. */ + void ready() {} + + void inserted() { + if (!_elementPrepared) { + prepareElement(); + } + cancelUnbindAll(preventCascade: true); + } + + void removed() { + asyncUnbindAll(); + } + + /** Recursive ancestral <element> initialization, oldest first. */ + void parseDeclarations(PolymerDeclaration declaration) { + if (declaration != null) { + parseDeclarations(declaration.superDeclaration); + parseDeclaration(declaration.host); + } + } + + /** + * Parse input `<polymer-element>` as needed, override for custom behavior. + */ + void parseDeclaration(Element elementElement) { + var root = shadowFromTemplate(fetchTemplate(elementElement)); + + // Dart note: this is extra code compared to Polymer to support + // the getShadowRoot method. + if (root == null) return; + + var name = elementElement.attributes['name']; + if (name == null) return; + _shadowRoots[name] = root; + } + + /** + * Return a shadow-root template (if desired), override for custom behavior. + */ + Element fetchTemplate(Element elementElement) => + elementElement.query('template'); + + /** Utility function that creates a shadow root from a `<template>`. */ + ShadowRoot shadowFromTemplate(Element template) { + if (template == null) return null; + // cache elder shadow root (if any) + var elderRoot = this.shadowRoot; + // make a shadow root + var root = createShadowRoot(); + // migrate flag(s)( + root.applyAuthorStyles = applyAuthorStyles; + root.resetStyleInheritance = resetStyleInheritance; + // stamp template + // which includes parsing and applying MDV bindings before being + // inserted (to avoid {{}} in attribute values) + // e.g. to prevent <img src="images/{{icon}}"> from generating a 404. + var dom = instanceTemplate(template); + // append to shadow dom + root.append(dom); + // perform post-construction initialization tasks on shadow root + shadowRootReady(root, template); + // return the created shadow root + return root; + } + + void shadowRootReady(ShadowRoot root, Element template) { + // locate nodes with id and store references to them in this.$ hash + marshalNodeReferences(root); + // add local events of interest... + addInstanceListeners(root, template); + // TODO(jmesserly): port this + // set up pointer gestures + // PointerGestures.register(root); + } + + /** Locate nodes with id and store references to them in [$] hash. */ + void marshalNodeReferences(ShadowRoot root) { + if (root == null) return; + for (var n in root.queryAll('[id]')) { + $[n.id] = n; + } + } + + void attributeChanged(String name, String oldValue) { + if (name != 'class' && name != 'style') { + attributeToProperty(name, attributes[name]); + } + } + + // TODO(jmesserly): use stream or future here? + void onMutation(Node node, void listener(MutationObserver obs)) { + new MutationObserver((records, MutationObserver observer) { + listener(observer); + observer.disconnect(); + })..observe(node, childList: true, subtree: true); + } + + void copyInstanceAttributes() { + _declaration._instanceAttributes.forEach((name, value) { + attributes[name] = value; + }); + } + + void takeAttributes() { + if (_declaration._publishLC == null) return; + attributes.forEach(attributeToProperty); + } + + /** + * If attribute [name] is mapped to a property, deserialize + * [value] into that property. + */ + void attributeToProperty(String name, String value) { + // try to match this attribute to a property (attributes are + // all lower-case, so this is case-insensitive search) + var property = propertyForAttribute(name); + if (property == null) return; + + // filter out 'mustached' values, these are to be + // replaced with bound-data and are not yet values + // themselves. + if (value == null || value.contains(Polymer.bindPattern)) return; + + // get original value + final self = reflect(this); + final defaultValue = self.getField(property.simpleName).reflectee; + + // deserialize Boolean or Number values from attribute + final newValue = deserializeValue(value, defaultValue, + _inferPropertyType(defaultValue, property)); + + // only act if the value has changed + if (!identical(newValue, defaultValue)) { + // install new value (has side-effects) + self.setField(property.simpleName, newValue); + } + } + + /** Return the published property matching name, or null. */ + // TODO(jmesserly): should we just return Symbol here? + DeclarationMirror propertyForAttribute(String name) { + final publishLC = _declaration._publishLC; + if (publishLC == null) return null; + //console.log('propertyForAttribute:', name, 'matches', match); + return publishLC[name]; + } + + /** + * Convert representation of [value] based on [type] and [defaultValue]. + */ + // TODO(jmesserly): this should probably take a ClassMirror instead of + // TypeMirror, but it is currently impossible to get from a TypeMirror to a + // ClassMirror. + Object deserializeValue(String value, Object defaultValue, TypeMirror type) => + deserialize.deserializeValue(value, defaultValue, type); + + String serializeValue(Object value, TypeMirror inferredType) { + if (value == null) return null; + + final type = inferredType.qualifiedName; + if (type == const Symbol('dart.core.bool')) { + return _toBoolean(value) ? '' : null; + } else if (type == const Symbol('dart.core.String') + || type == const Symbol('dart.core.int') + || type == const Symbol('dart.core.double')) { + return '$value'; + } + return null; + } + + void reflectPropertyToAttribute(String name) { + // TODO(sjmiles): consider memoizing this + final self = reflect(this); + // try to intelligently serialize property value + // TODO(jmesserly): cache symbol? + final propValue = self.getField(new Symbol(name)).reflectee; + final property = _declaration._publish[name]; + var inferredType = _inferPropertyType(propValue, property); + final serializedValue = serializeValue(propValue, inferredType); + // boolean properties must reflect as boolean attributes + if (serializedValue != null) { + attributes[name] = serializedValue; + // TODO(sorvell): we should remove attr for all properties + // that have undefined serialization; however, we will need to + // refine the attr reflection system to achieve this; pica, for example, + // relies on having inferredType object properties not removed as + // attrs. + } else if (inferredType.qualifiedName == const Symbol('dart.core.bool')) { + attributes.remove(name); + } + } + + /** + * Creates the document fragment to use for each instance of the custom + * element, given the `<template>` node. By default this is equivalent to: + * + * template.createInstance(this, polymerSyntax); + * + * Where polymerSyntax is a singleton `PolymerExpressions` instance from the + * [polymer_expressions](https://pub.dartlang.org/packages/polymer_expressions) + * package. + * + * You can override this method to change the instantiation behavior of the + * template, for example to use a different data-binding syntax. + */ + DocumentFragment instanceTemplate(Element template) => + template.createInstance(this, _polymerSyntax); + + NodeBinding bind(String name, model, String path) { + // note: binding is a prepare signal. This allows us to be sure that any + // property changes that occur as a result of binding will be observed. + if (!_elementPrepared) prepareElement(); + + var property = propertyForAttribute(name); + if (property != null) { + unbind(name); + // use n-way Polymer binding + var observer = bindProperty(property.simpleName, model, path); + // reflect bound property to attribute when binding + // to ensure binding is not left on attribute if property + // does not update due to not changing. + reflectPropertyToAttribute(name); + return bindings[name] = observer; + } else { + return super.bind(name, model, path); + } + } + + void asyncUnbindAll() { + if (_unbound == true) return; + _unbindLog.info('[$localName] asyncUnbindAll'); + _unbindAllJob = job(_unbindAllJob, unbindAll, const Duration(seconds: 0)); + } + + void unbindAll() { + if (_unbound == true) return; + + unbindAllProperties(); + super.unbindAll(); + _unbindNodeTree(shadowRoot); + // TODO(sjmiles): must also unbind inherited shadow roots + _unbound = true; + } + + void cancelUnbindAll({bool preventCascade}) { + if (_unbound == true) { + _unbindLog.warning( + '[$localName] already unbound, cannot cancel unbindAll'); + return; + } + _unbindLog.info('[$localName] cancelUnbindAll'); + if (_unbindAllJob != null) { + _unbindAllJob.stop(); + _unbindAllJob = null; + } + + // cancel unbinding our shadow tree iff we're not in the process of + // cascading our tree (as we do, for example, when the element is inserted). + if (preventCascade == true) return; + _forNodeTree(shadowRoot, (n) { + if (n is PolymerElement) { + (n as PolymerElement).cancelUnbindAll(); + } + }); + } + + static void _unbindNodeTree(Node node) { + _forNodeTree(node, (node) => node.unbindAll()); + } + + static void _forNodeTree(Node node, void callback(Node node)) { + if (node == null) return; + + callback(node); + for (var child = node.firstChild; child != null; child = child.nextNode) { + _forNodeTree(child, callback); + } + } + + /** Set up property observers. */ + void observeProperties() { + // TODO(sjmiles): + // we observe published properties so we can reflect them to attributes + // ~100% of our team's applications would work without this reflection, + // perhaps we can make it optional somehow + // + // add user's observers + final observe = _declaration._observe; + final publish = _declaration._publish; + if (observe != null) { + observe.forEach((name, value) { + if (publish != null && publish.containsKey(name)) { + observeBoth(name, value); + } else { + observeProperty(name, value); + } + }); + } + // add observers for published properties + if (publish != null) { + publish.forEach((name, value) { + if (observe == null || !observe.containsKey(name)) { + observeAttributeProperty(name); + } + }); + } + } + + void _observe(String name, void callback(newValue, oldValue)) { + _observeLog.info('[$localName] watching [$name]'); + // TODO(jmesserly): this is a little different than the JS version so we + // can pass the oldValue, which is missing from Dart's PathObserver. + // This probably gives us worse performance. + var path = new PathObserver(this, name); + Object oldValue = null; + _registerObserver(name, path.changes.listen((_) { + final newValue = path.value; + final old = oldValue; + oldValue = newValue; + callback(newValue, old); + })); + } + + void _registerObserver(String name, StreamSubscription sub) { + if (_elementObservers == null) { + _elementObservers = new Map<String, StreamSubscription>(); + } + _elementObservers[name] = sub; + } + + void observeAttributeProperty(String name) { + _observe(name, (value, old) => reflectPropertyToAttribute(name)); + } + + void observeProperty(String name, Symbol method) { + final self = reflect(this); + _observe(name, (value, old) => self.invoke(method, [old])); + } + + void observeBoth(String name, Symbol methodName) { + final self = reflect(this); + _observe(name, (value, old) { + reflectPropertyToAttribute(name); + self.invoke(methodName, [old]); + }); + } + + void unbindProperty(String name) { + if (_elementObservers == null) return; + var sub = _elementObservers.remove(name); + if (sub != null) sub.cancel(); + } + + void unbindAllProperties() { + if (_elementObservers == null) return; + for (var sub in _elementObservers.values) sub.cancel(); + _elementObservers.clear(); + } + + /** + * Bind a [property] in this object to a [path] in model. *Note* in Dart it + * is necessary to also define the field: + * + * var myProperty; + * + * created() { + * super.created(); + * bindProperty(#myProperty, this, 'myModel.path.to.otherProp'); + * } + */ + // TODO(jmesserly): replace with something more localized, like: + // @ComputedField('myModel.path.to.otherProp'); + NodeBinding bindProperty(Symbol name, Object model, String path) => + // apply Polymer two-way reference binding + _bindProperties(this, name, model, path); + + /** + * bind a property in A to a path in B by converting A[property] to a + * getter/setter pair that accesses B[...path...] + */ + static NodeBinding _bindProperties(PolymerElement inA, Symbol inProperty, + Object inB, String inPath) { + + if (_bindLog.isLoggable(Level.INFO)) { + _bindLog.info('[$inB]: bindProperties: [$inPath] to ' + '[${inA.localName}].[$inProperty]'); + } + + // Dart note: normally we only reach this code when we know it's a + // property, but if someone uses bindProperty directly they might get a + // NoSuchMethodError either from the getField below, or from the setField + // inside PolymerBinding. That doesn't seem unreasonable, but it's a slight + // difference from Polymer.js behavior. + + // capture A's value if B's value is null or undefined, + // otherwise use B's value + var path = new PathObserver(inB, inPath); + if (path.value == null) { + path.value = reflect(inA).getField(inProperty).reflectee; + } + return new _PolymerBinding(inA, inProperty, inB, inPath); + } + + /** Attach event listeners on the host (this) element. */ + void addHostListeners() { + var events = _declaration._eventDelegates; + if (events.isEmpty) return; + + if (_eventsLog.isLoggable(Level.INFO)) { + _eventsLog.info('[$localName] addHostListeners: $events'); + } + addNodeListeners(this, events.keys, hostEventListener); + } + + /** Attach event listeners inside a shadow [root]. */ + void addInstanceListeners(ShadowRoot root, Element template) { + var templateDelegates = _declaration._templateDelegates; + if (templateDelegates == null) return; + var events = templateDelegates[template]; + if (events == null) return; + + if (_eventsLog.isLoggable(Level.INFO)) { + _eventsLog.info('[$localName] addInstanceListeners: $events'); + } + addNodeListeners(root, events, instanceEventListener); + } + + void addNodeListeners(Node node, Iterable<String> events, + void listener(Event e)) { + + for (var name in events) { + addNodeListener(node, name, listener); + } + } + + void addNodeListener(Node node, String event, void listener(Event e)) { + node.on[event].listen(listener); + } + + void hostEventListener(Event event) { + // TODO(jmesserly): do we need this check? It was using cancelBubble, see: + // https://github.com/Polymer/polymer/issues/292 + if (!event.bubbles) return; + + bool log = _eventsLog.isLoggable(Level.INFO); + if (log) { + _eventsLog.info('>>> [$localName]: hostEventListener(${event.type})'); + } + + var h = findEventDelegate(event); + if (h != null) { + if (log) _eventsLog.info('[$localName] found host handler name [$h]'); + var detail = event is CustomEvent ? + (event as CustomEvent).detail : null; + // TODO(jmesserly): cache the symbols? + dispatchMethod(new Symbol(h), [event, detail, this]); + } + + if (log) { + _eventsLog.info('<<< [$localName]: hostEventListener(${event.type})'); + } + } + + String findEventDelegate(Event event) => + _declaration._eventDelegates[_eventNameFromType(event.type)]; + + /** Call [methodName] method on [this] with [args], if the method exists. */ + // TODO(jmesserly): I removed the [node] argument as it was unused. Reconcile. + void dispatchMethod(Symbol methodName, List args) { + bool log = _eventsLog.isLoggable(Level.INFO); + if (log) _eventsLog.info('>>> [$localName]: dispatch $methodName'); + + // TODO(sigmund): consider making event listeners list all arguments + // explicitly. Unless VM mirrors are optimized first, this reflectClass call + // will be expensive once custom elements extend directly from Element (see + // dartbug.com/11108). + var self = reflect(this); + var method = self.type.methods[methodName]; + if (method != null) { + // This will either truncate the argument list or extend it with extra + // null arguments, so it will match the signature. + // TODO(sigmund): consider accepting optional arguments when we can tell + // them appart from named arguments (see http://dartbug.com/11334) + args.length = method.parameters.where((p) => !p.isOptional).length; + } + self.invoke(methodName, args); + + if (log) _eventsLog.info('<<< [$localName]: dispatch $methodName'); + + // TODO(jmesserly): workaround for HTML events not supporting zones. + performMicrotaskCheckpoint(); + } + + void instanceEventListener(Event event) { + _listenLocal(host, event); + } + + // TODO(sjmiles): much of the below privatized only because of the vague + // notion this code is too fiddly and we need to revisit the core feature + void _listenLocal(Element host, Event event) { + // TODO(jmesserly): do we need this check? It was using cancelBubble, see: + // https://github.com/Polymer/polymer/issues/292 + if (!event.bubbles) return; + + bool log = _eventsLog.isLoggable(Level.INFO); + if (log) _eventsLog.info('>>> [$localName]: listenLocal [${event.type}]'); + + final eventOn = '$_EVENT_PREFIX${_eventNameFromType(event.type)}'; + if (event.path == null) { + _listenLocalNoEventPath(host, event, eventOn); + } else { + _listenLocalEventPath(host, event, eventOn); + } + + if (log) _eventsLog.info('<<< [$localName]: listenLocal [${event.type}]'); + } + + static void _listenLocalEventPath(Element host, Event event, String eventOn) { + var c = null; + for (var target in event.path) { + // if we hit host, stop + if (identical(target, host)) return; + + // find a controller for the target, unless we already found `host` + // as a controller + c = identical(c, host) ? c : _findController(target); + + // if we have a controller, dispatch the event, and stop if the handler + // returns true + if (c != null && _handleEvent(c, target, event, eventOn)) { + return; + } + } + } + + // TODO(sorvell): remove when ShadowDOM polyfill supports event path. + // Note that _findController will not return the expected controller when the + // event target is a distributed node. This is because we cannot traverse + // from a composed node to a node in shadowRoot. + // This will be addressed via an event path api + // https://www.w3.org/Bugs/Public/show_bug.cgi?id=21066 + static void _listenLocalNoEventPath(Element host, Event event, + String eventOn) { + + if (_eventsLog.isLoggable(Level.INFO)) { + _eventsLog.info('event.path() not supported for ${event.type}'); + } + + var target = event.target; + var c = null; + // if we hit dirt or host, stop + while (target != null && target != host) { + // find a controller for target `t`, unless we already found `host` + // as a controller + c = identical(c, host) ? c : _findController(target); + + // if we have a controller, dispatch the event, return 'true' if + // handler returns true + if (c != null && _handleEvent(c, target, event, eventOn)) { + return; + } + target = target.parent; + } + } + + // TODO(jmesserly): this won't find the correct host unless the ShadowRoot + // was created on a PolymerElement. + static Element _findController(Node node) { + while (node.parentNode != null) { + node = node.parentNode; + } + return _shadowHost[node]; + } + + static bool _handleEvent(Element ctrlr, Node node, Event event, + String eventOn) { + + // Note: local events are listened only in the shadow root. This dynamic + // lookup is used to distinguish determine whether the target actually has a + // listener, and if so, to determine lazily what's the target method. + var name = node is Element ? (node as Element).attributes[eventOn] : null; + if (name != null && _handleIfNotHandled(node, event)) { + if (_eventsLog.isLoggable(Level.INFO)) { + _eventsLog.info('[${ctrlr.localName}] found handler name [$name]'); + } + var detail = event is CustomEvent ? + (event as CustomEvent).detail : null; + + if (node != null) { + // TODO(jmesserly): cache symbols? + ctrlr.xtag.dispatchMethod(new Symbol(name), [event, detail, node]); + } + } + + // TODO(jmesserly): do we need this? It was using cancelBubble, see: + // https://github.com/Polymer/polymer/issues/292 + return !event.bubbles; + } + + // TODO(jmesserly): I don't understand this bit. It seems to be a duplicate + // delivery prevention mechanism? + static bool _handleIfNotHandled(Node node, Event event) { + var list = _eventHandledTable[event]; + if (list == null) _eventHandledTable[event] = list = new Set<Node>(); + if (!list.contains(node)) { + list.add(node); + return true; + } + return false; + } + + /** + * Invokes a function asynchronously. + * This will call `Platform.flush()` and then return a `new Timer` + * with the provided [method] and [timeout]. + * + * If you would prefer to run the callback using + * [window.requestAnimationFrame], see the [async] method. + */ + // Dart note: "async" is split into 2 methods so it can have a sensible type + // signatures. Also removed the various features that don't make sense in a + // Dart world, like binding to "this" and taking arguments list. + Timer asyncTimer(void method(), Duration timeout) { + // when polyfilling Object.observe, ensure changes + // propagate before executing the async method + platform.flush(); + return new Timer(timeout, method); + } + + /** + * Invokes a function asynchronously. + * This will call `Platform.flush()` and then call + * [window.requestAnimationFrame] with the provided [method] and return the + * result. + * + * If you would prefer to run the callback after a given duration, see + * the [asyncTimer] method. + */ + int async(RequestAnimationFrameCallback method) { + // when polyfilling Object.observe, ensure changes + // propagate before executing the async method + platform.flush(); + return window.requestAnimationFrame(method); + } + + /** + * Fire a [CustomEvent] targeting [toNode], or this if toNode is not + * supplied. Returns the [detail] object. + */ + Object fire(String type, {Object detail, Node toNode, bool canBubble}) { + var node = toNode != null ? toNode : this; + //log.events && console.log('[%s]: sending [%s]', node.localName, inType); + node.dispatchEvent(new CustomEvent( + type, + canBubble: canBubble != null ? canBubble : true, + detail: detail + )); + return detail; + } + + /** + * Fire an event asynchronously. See [async] and [fire]. + */ + asyncFire(String type, {Object detail, Node toNode, bool canBubble}) { + // TODO(jmesserly): I'm not sure this method adds much in Dart, it's easy to + // add "() =>" + async((x) => fire( + type, detail: detail, toNode: toNode, canBubble: canBubble)); + } + + /** + * Remove [className] from [old], add class to [anew], if they exist. + */ + void classFollows(Element anew, Element old, String className) { + if (old != null) { + old.classes.remove(className); + } + if (anew != null) { + anew.classes.add(className); + } + } +} + +// Dart note: Polymer addresses n-way bindings by metaprogramming: redefine +// the property on the PolymerElement instance to always get its value from the +// model@path. We can't replicate this in Dart so we do the next best thing: +// listen to changes on both sides and update the values. +// TODO(jmesserly): our approach leads to race conditions in the bindings. +// See http://code.google.com/p/dart/issues/detail?id=13567 +class _PolymerBinding extends NodeBinding { + final InstanceMirror _target; + final Symbol _property; + StreamSubscription _sub; + Object _lastValue; + + _PolymerBinding(PolymerElement node, Symbol property, model, path) + : _target = reflect(node), + _property = property, + super(node, MirrorSystem.getName(property), model, path) { + + _sub = node.changes.listen(_propertyValueChanged); + } + + void close() { + if (closed) return; + _sub.cancel(); + super.close(); + } + + void boundValueChanged(newValue) { + _lastValue = newValue; + _target.setField(_property, newValue); + } + + void _propertyValueChanged(List<ChangeRecord> records) { + for (var record in records) { + if (record.changes(_property)) { + final newValue = _target.getField(_property).reflectee; + if (!identical(_lastValue, newValue)) { + value = newValue; + } + return; + } + } + } +} + +bool _toBoolean(value) => null != value && false != value; + +TypeMirror _propertyType(DeclarationMirror property) => + property is VariableMirror + ? (property as VariableMirror).type + : (property as MethodMirror).returnType; + +TypeMirror _inferPropertyType(Object value, DeclarationMirror property) { + var type = _propertyType(property); + if (type.qualifiedName == const Symbol('dart.core.Object') || + type.qualifiedName == const Symbol('dynamic')) { + // Attempt to infer field type from the default value. + if (value != null) { + type = reflect(value).type; + } + } + return type; +} + +final Logger _observeLog = new Logger('polymer.observe'); +final Logger _eventsLog = new Logger('polymer.events'); +final Logger _unbindLog = new Logger('polymer.unbind'); +final Logger _bindLog = new Logger('polymer.bind'); + +final Expando _shadowHost = new Expando<Element>(); + +final Expando _eventHandledTable = new Expando<Set<Node>>();
diff --git a/pkg/polymer/lib/src/loader.dart b/pkg/polymer/lib/src/loader.dart new file mode 100644 index 0000000..e8cbb90 --- /dev/null +++ b/pkg/polymer/lib/src/loader.dart
@@ -0,0 +1,130 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of polymer; + +/** Annotation used to automatically register polymer elements. */ +class CustomTag { + final String tagName; + const CustomTag(this.tagName); +} + +/** + * Metadata used to label static or top-level methods that are called + * automatically when loading the library of a custom element. + */ +const initMethod = const _InitMethodAnnotation(); + +/** + * Initializes a polymer application as follows: + * * set up up polling for observable changes + * * initialize MDV + * * for each library in [libraries], register custom elements labeled with + * [CustomTag] and invoke the initialization method on it. + * + * The initialization on each library is either a method named `main` or + * a top-level function and annotated with [initMethod]. + * + * The urls in [libraries] can be absolute or relative to [srcUrl]. + */ +void initPolymer(List<String> libraries, [String srcUrl]) { + runMicrotask(() { + // DOM events don't yet go through microtasks, so we catch those here. + new Timer.periodic(new Duration(milliseconds: 125), + (_) => performMicrotaskCheckpoint()); + + // TODO(jmesserly): mdv should use initMdv instead of mdv.initialize. + mdv.initialize(); + registerCustomElement('polymer-element', () => new PolymerDeclaration()); + + for (var lib in libraries) { + _loadLibrary(lib, srcUrl); + } + + // TODO(jmesserly): this should be in the custom_element polyfill, not here. + // notify the system that we are bootstrapped + document.body.dispatchEvent( + new CustomEvent('WebComponentsReady', canBubble: true)); + }); +} + +/** All libraries in the current isolate. */ +final _libs = currentMirrorSystem().libraries; + +/** + * Reads the library at [uriString] (which can be an absolute URI or a relative + * URI from [srcUrl]), and: + * + * * If present, invokes `main`. + * + * * If present, invokes any top-level and static functions marked + * with the [initMethod] annotation (in the order they appear). + * + * * Registers any [PolymerElement] that is marked with the [CustomTag] + * annotation. + */ +void _loadLibrary(String uriString, [String srcUrl]) { + var uri = Uri.parse(uriString); + if (uri.scheme == '' && srcUrl != null) { + uri = Uri.parse(path.normalize(path.join(path.dirname(srcUrl), uriString))); + } + var lib = _libs[uri]; + if (lib == null) { + print('warning: $uri library not found'); + return; + } + + // Invoke `main`, if present. + if (lib.functions[const Symbol('main')] != null) { + lib.invoke(const Symbol('main'), const []); + } + + // Search top-level functions marked with @initMethod + for (var f in lib.functions.values) { + _maybeInvoke(lib, f); + } + + for (var c in lib.classes.values) { + // Search for @CustomTag on classes + for (var m in c.metadata) { + var meta = m.reflectee; + if (meta is CustomTag) { + Polymer._registerClassMirror(meta.tagName, c); + } + } + + // TODO(sigmund): check also static methods marked with @initMethod. + // This is blocked on two bugs: + // - dartbug.com/12133 (static methods are incorrectly listed as top-level + // in dart2js, so they end up being called twice) + // - dartbug.com/12134 (sometimes "method.metadata" throws an exception, + // we could wrap and hide those exceptions, but it's not ideal). + } +} + +void _maybeInvoke(ObjectMirror obj, MethodMirror method) { + var annotationFound = false; + for (var meta in method.metadata) { + if (identical(meta.reflectee, initMethod)) { + annotationFound = true; + break; + } + } + if (!annotationFound) return; + if (!method.isStatic) { + print("warning: methods marked with @initMethod should be static," + " ${method.simpleName} is not."); + return; + } + if (!method.parameters.where((p) => !p.isOptional).isEmpty) { + print("warning: methods marked with @initMethod should take no " + "arguments, ${method.simpleName} expects some."); + return; + } + obj.invoke(method.simpleName, const []); +} + +class _InitMethodAnnotation { + const _InitMethodAnnotation(); +}
diff --git a/pkg/polymer/lib/transformer.dart b/pkg/polymer/lib/transformer.dart index 5f4dc02..26d5678 100644 --- a/pkg/polymer/lib/transformer.dart +++ b/pkg/polymer/lib/transformer.dart
@@ -6,6 +6,7 @@ // TODO(sigmund): move into a plugin directory when pub supports it. library polymer.src.transform; +import 'package:barback/barback.dart'; import 'package:observe/transform.dart'; import 'src/build/code_extractor.dart'; import 'src/build/import_inliner.dart';
diff --git a/pkg/polymer/pubspec.yaml b/pkg/polymer/pubspec.yaml index 4d93ad5..acd745f 100644 --- a/pkg/polymer/pubspec.yaml +++ b/pkg/polymer/pubspec.yaml
@@ -1,5 +1,5 @@ name: polymer -author: Web UI Authors <web-ui-dev@dartlang.org> +author: Polymer.dart Authors <web-ui-dev@dartlang.org> description: > Polymer.dart is a new type of library for the web, built on top of Web Components, and designed to leverage the evolving web platform on modern @@ -16,11 +16,12 @@ html_import: any logging: any mdv: any + meta: any observe: any path: any polymer_expressions: any shadow_dom: any source_maps: any - # TODO(jmesserly): make this a dev_dependency - unittest: any yaml: any +dev_dependencies: + unittest: any
diff --git a/pkg/polymer/test/attr_deserialize_test.dart b/pkg/polymer/test/attr_deserialize_test.dart new file mode 100644 index 0000000..8497752 --- /dev/null +++ b/pkg/polymer/test/attr_deserialize_test.dart
@@ -0,0 +1,45 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:html'; +import 'package:unittest/unittest.dart'; +import 'package:unittest/html_config.dart'; +import 'package:polymer/polymer.dart'; + +@CustomTag('my-element') +class MyElement extends PolymerElement { + @published double volume; + @published int factor; + @published bool crankIt; + @published String msg; + @published DateTime time; + @published Object json; +} + +main() { + useHtmlConfiguration(); + + test('attributes were deserialized', () { + MyElement elem = query('my-element').xtag; + final msg = 'property should match attribute.'; + expect(elem.volume, 11.0, reason: '"volume" should match attribute'); + expect(elem.factor, 3, reason: '"factor" should match attribute'); + expect(elem.crankIt, true, reason: '"crankIt" should match attribute'); + expect(elem.msg, "Yo!", reason: '"msg" should match attribute'); + expect(elem.time, DateTime.parse('2013-08-08T18:34Z'), + reason: '"time" should match attribute'); + expect(elem.json, {'here': 'is', 'some': 'json', 'x': 123}, + reason: '"json" should match attribute'); + + var text = elem.shadowRoot.text; + // Collapse adjacent whitespace like a browser would: + text = text.replaceAll('\n', ' ').replaceAll(new RegExp(r'\s+'), ' '); + + // Note: using "${33.0}" because the toString differs in JS vs Dart VM. + expect(text, " Yo! The volume is ${33.0} !! The time is " + "2013-08-08 18:34:00.000Z and here's some JSON: " + "{here: is, some: json, x: 123} ", + reason: 'text should match expected HTML template'); + }); +}
diff --git a/pkg/polymer/test/attr_deserialize_test.html b/pkg/polymer/test/attr_deserialize_test.html new file mode 100644 index 0000000..de10fac --- /dev/null +++ b/pkg/polymer/test/attr_deserialize_test.html
@@ -0,0 +1,29 @@ +<!DOCTYPE html> +<!-- +Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +for details. All rights reserved. Use of this source code is governed by a +BSD-style license that can be found in the LICENSE file. +--> +<html> + <head> + <title>Polymer.dart attribute deserialization test</title> + <script src="packages/polymer/boot.js"></script> + <script src="packages/unittest/test_controller.js"></script> + </head> + <body> + <polymer-element name="my-element"> + <template> + <h1>{{msg}} The volume is {{volume * factor}} + <template if="{{crankIt}}">!!</template></h1> + <h3>The time is {{time}} and here's some JSON: {{json}}</h3> + </template> + </polymer-element> + + <my-element volume="11" crankit msg="Yo!" factor="3" + time="2013-08-08T18:34Z" + json="{'here': 'is', 'some': 'json', 'x': 123}"> + </my-element> + + <script type="application/dart" src="attr_deserialize_test.dart"></script> + </body> +</html>
diff --git a/pkg/polymer/test/attr_mustache_test.dart b/pkg/polymer/test/attr_mustache_test.dart new file mode 100644 index 0000000..fba0171 --- /dev/null +++ b/pkg/polymer/test/attr_mustache_test.dart
@@ -0,0 +1,50 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:async'; +import 'dart:html'; +import 'package:unittest/unittest.dart'; +import 'package:unittest/html_config.dart'; +import 'package:polymer/polymer.dart'; + +@CustomTag('x-target') +class XTarget extends PolymerElement { + final Completer _found = new Completer(); + Future get foundSrc => _found.future; + + // force an mdv binding + bind(name, model, path) => + TemplateElement.mdvPackage(this).bind(name, model, path); + + inserted() { + testSrcForMustache(); + } + + attributeChanged(name, oldValue) { + testSrcForMustache(); + if (attributes[name] == '../testSource') { + _found.complete(); + } + } + + testSrcForMustache() { + expect(attributes['src'], isNot(matches(Polymer.bindPattern)), + reason: 'attribute does not contain {{...}}'); + } +} + +@CustomTag('x-test') +class XTest extends PolymerElement { + @observable var src = 'testSource'; +} + +main() { + useHtmlConfiguration(); + + test('mustache attributes', () { + final xtest = document.query('#test').xtag; + final xtarget = xtest.shadowRoot.query('#target').xtag; + return xtarget.foundSrc; + }); +}
diff --git a/pkg/polymer/test/attr_mustache_test.html b/pkg/polymer/test/attr_mustache_test.html new file mode 100644 index 0000000..df9f9ee --- /dev/null +++ b/pkg/polymer/test/attr_mustache_test.html
@@ -0,0 +1,27 @@ +<!doctype html> +<!-- +Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +for details. All rights reserved. Use of this source code is governed by a +BSD-style license that can be found in the LICENSE file. +--> +<html> + <head> + <title>take attributes</title> + <script src="packages/polymer/boot.js"></script> + <script src="packages/unittest/test_controller.js"></script> + </head> + <body> + <x-test id="test"></x-test> + + <polymer-element name="x-target" attributes="src"> + </polymer-element> + + <polymer-element name="x-test"> + <template> + <x-target id="target" src="../{{src}}"></x-target> + </template> + </polymer-element> + + <script type="application/dart" src="attr_mustache_test.dart"></script> + </body> +</html>
diff --git a/pkg/polymer/test/build/all_phases_test.dart b/pkg/polymer/test/build/all_phases_test.dart index 1c2dccc..9e6a9b7 100644 --- a/pkg/polymer/test/build/all_phases_test.dart +++ b/pkg/polymer/test/build/all_phases_test.dart
@@ -198,17 +198,14 @@ } '''; -String _sampleObservableOutput(String className, String fieldName) => ''' -library ${className}_$fieldName; -import 'package:observe/observe.dart'; - -class $className extends ChangeNotifierBase { - int __\$$fieldName; - int get $fieldName => __\$$fieldName; - set $fieldName(int value) { - __\$$fieldName = notifyPropertyChange(const Symbol('$fieldName'), __\$$fieldName, value); - } - - $className($fieldName) : __\$$fieldName = $fieldName; -} -'''; +String _sampleObservableOutput(String className, String field) => + "library ${className}_$field;\n" + "import 'package:observe/observe.dart';\n\n" + "class $className extends ChangeNotifierBase {\n" + " @observable int get $field => __\$$field; " + "int __\$$field; " + "set $field(int value) { " + "__\$$field = notifyPropertyChange(#$field, __\$$field, value); " + "}\n" + " $className($field) : __\$$field = $field;\n" + "}\n";
diff --git a/pkg/polymer/test/build/linter_test.dart b/pkg/polymer/test/build/linter_test.dart index e4f3630..17975a8 100644 --- a/pkg/polymer/test/build/linter_test.dart +++ b/pkg/polymer/test/build/linter_test.dart
@@ -261,7 +261,7 @@ 'JavaScript event handler. Use the form ' 'on-event-name="handlerName" if you want a Dart handler ' 'that will automatically update the UI based on model changes. ' - '(lib/test.html 1 0)' + '(lib/test.html 1 5)' }); _testLinter('on-foo is only supported in polymer elements', { @@ -272,7 +272,7 @@ 'a|lib/test.html.messages': 'warning: Inline event handlers are only supported inside ' 'declarations of <polymer-element>. ' - '(lib/test.html 1 0)' + '(lib/test.html 1 5)' }); _testLinter('on-foo is not an expression', { @@ -285,7 +285,20 @@ 'warning: Invalid event handler body "bar()". Declare a method ' 'in your custom element "void handlerName(event, detail, target)" ' 'and use the form on-foo="handlerName". ' - '(lib/test.html 1 28)' + '(lib/test.html 1 33)' + }); + + _testLinter('on-foo-bar is no longer supported', { + 'a|lib/test.html': '''<html><body> + <polymer-element name="x-a"><div on-foo-bar="quux"></div> + </polymer-element> + '''.replaceAll(' ', ''), + }, { + 'a|lib/test.html.messages': + 'warning: Invalid event name "on-foo-bar". After the "on-" the ' + 'event name should not use dashes. For example use "on-fooBar" or ' + '"on-foobar" (both forms are equivalent in HTML). ' + '(lib/test.html 1 33)' }); }); @@ -294,7 +307,7 @@ 'a|lib/test.html': '<x-foo></x-foo>', }, { 'a|lib/test.html.messages': - 'warning: definition for custom element with tag name "x-foo" not ' + 'warning: definition for Polymer element with tag name "x-foo" not ' 'found. (lib/test.html 0 0)' }); @@ -302,7 +315,7 @@ 'a|lib/test.html': '<div is="x-foo"></div>', }, { 'a|lib/test.html.messages': - 'warning: definition for custom element with tag name "x-foo" not ' + 'warning: definition for Polymer element with tag name "x-foo" not ' 'found. (lib/test.html 0 0)' }); @@ -409,6 +422,20 @@ 'to write <li is="x-a">? (lib/test.html 1 0)' }); }); + + group('custom attributes', () { + _testLinter('foo-bar is no longer supported in attributes', { + 'a|lib/test.html': '''<html><body> + <polymer-element name="x-a" attributes="foo-bar"> + </polymer-element> + '''.replaceAll(' ', ''), + }, { + 'a|lib/test.html.messages': + 'warning: PolymerElement no longer recognizes attribute names with ' + 'dashes such as "foo-bar". Use "fooBar" or "foobar" instead (both ' + 'forms are equivalent in HTML). (lib/test.html 1 28)' + }); + }); } _testLinter(String name, Map inputFiles, Map outputMessages) {
diff --git a/pkg/polymer/test/utils_test.dart b/pkg/polymer/test/build/utils_test.dart similarity index 98% rename from pkg/polymer/test/utils_test.dart rename to pkg/polymer/test/build/utils_test.dart index 335e538..cd99656 100644 --- a/pkg/polymer/test/utils_test.dart +++ b/pkg/polymer/test/build/utils_test.dart
@@ -7,7 +7,7 @@ import 'package:unittest/compact_vm_config.dart'; import 'package:unittest/unittest.dart'; -import 'package:polymer/src/utils.dart'; +import 'package:polymer/src/build/utils.dart'; main() { useCompactVMConfiguration();
diff --git a/pkg/polymer/test/prop_attr_reflection_test.dart b/pkg/polymer/test/prop_attr_reflection_test.dart new file mode 100644 index 0000000..d74f5e4 --- /dev/null +++ b/pkg/polymer/test/prop_attr_reflection_test.dart
@@ -0,0 +1,110 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:html'; +import 'package:unittest/unittest.dart'; +import 'package:unittest/html_config.dart'; +import 'package:polymer/platform.dart' as Platform; +import 'package:polymer/polymer.dart'; + +class XFoo extends PolymerElement { + @observable var foo = ''; + @observable String baz = ''; +} + +class XBar extends XFoo { + @observable int zot = 3; + @observable bool zim = false; + @observable String str = 'str'; + @observable Object obj; +} + +class XCompose extends PolymerElement { + @observable bool zim = false; +} + +main() { + useHtmlConfiguration(); + + // Most tests use @CustomTag, here we test out the impertive register: + Polymer.register('x-foo', XFoo); + Polymer.register('x-bar', XBar); + Polymer.register('x-compose', XCompose); + + test('property attribute reflection', () { + var xcompose = query('x-compose').xtag; + var xfoo = query('x-foo').xtag; + xfoo.foo = 5; + Platform.flush(); + Platform.endOfMicrotask(expectAsync0(() { + expect(xcompose.$['bar'].attributes.containsKey('zim'), false, + reason: 'attribute bound to property updates when binding is made'); + + expect('${xfoo.foo}', xfoo.attributes['foo'], + reason: 'attribute reflects property as string'); + xfoo.attributes['foo'] = '27'; + // TODO(jmesserly): why is JS leaving this as a String? From the code it + // looks like it should use the type of 5 and parse it as a number. + expect('${xfoo.foo}', xfoo.attributes['foo'], + reason: 'property reflects attribute'); + // + xfoo.baz = 'Hello'; + Platform.flush(); + Platform.endOfMicrotask(expectAsync0(() { + expect(xfoo.baz, xfoo.attributes['baz'], + reason: 'attribute reflects property'); + // + var xbar = query('x-bar').xtag; + // + xbar.foo = 'foo!'; + xbar.zot = 27; + xbar.zim = true; + xbar.str = 'str!'; + xbar.obj = {'hello': 'world'}; + Platform.flush(); + Platform.endOfMicrotask(expectAsync0(() { + expect(xbar.foo, xbar.attributes['foo'], + reason: 'inherited published property is reflected'); + expect('${xbar.zot}', xbar.attributes['zot'], + reason: 'attribute reflects property as number'); + expect(xbar.attributes['zim'], '', reason: + 'attribute reflects true valued boolean property as ' + 'having attribute'); + expect(xbar.str, xbar.attributes['str'], + reason: 'attribute reflects property as published string'); + expect(xbar.attributes.containsKey('obj'), false, + reason: 'attribute does not reflect object property'); + xbar.attributes['zim'] = 'false'; + xbar.attributes['foo'] = 'foo!!'; + xbar.attributes['zot'] = '54'; + xbar.attributes['str'] = 'str!!'; + xbar.attributes['obj'] = "{'hello': 'world'}"; + expect(xbar.foo, xbar.attributes['foo'], + reason: 'property reflects attribute as string'); + expect(xbar.zot, 54, + reason: 'property reflects attribute as number'); + expect(xbar.zim, false, + reason: 'property reflects attribute as boolean'); + expect(xbar.str, 'str!!', + reason: 'property reflects attribute as published string'); + expect(xbar.obj, {'hello': 'world'}, + reason: 'property reflects attribute as object'); + xbar.zim = false; + Platform.flush(); + Platform.endOfMicrotask(expectAsync0(() { + expect(xbar.attributes.containsKey('zim'), false, reason: + 'attribute reflects false valued boolean property as NOT ' + 'having attribute'); + var objAttr = xbar.attributes['obj']; + xbar.obj = 'hi'; + Platform.endOfMicrotask(expectAsync0(() { + expect(xbar.attributes['obj'], objAttr, reason: + 'do not reflect property with default type of object'); + })); + })); + })); + })); + })); + }); +}
diff --git a/pkg/polymer/test/prop_attr_reflection_test.html b/pkg/polymer/test/prop_attr_reflection_test.html new file mode 100644 index 0000000..e4466d3 --- /dev/null +++ b/pkg/polymer/test/prop_attr_reflection_test.html
@@ -0,0 +1,32 @@ +<!doctype html> +<!-- +Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +for details. All rights reserved. Use of this source code is governed by a +BSD-style license that can be found in the LICENSE file. +--> +<html> + <head> + <title>publish attributes</title> + <script src="packages/polymer/boot.js"></script> + <script src="packages/unittest/test_controller.js"></script> + </head> + <body> + + <x-foo></x-foo> + <polymer-element name="x-foo" attributes="foo baz"> + </polymer-element> + + <x-bar></x-bar> + <polymer-element name="x-bar" extends="x-foo" attributes="zot zim str obj"> + </polymer-element> + + <x-compose></x-compose> + <polymer-element name="x-compose"> + <template> + <x-bar id="bar" zim="{{zim}}"></x-bar> + </template> + </polymer-element> + + <script type="application/dart" src="prop_attr_reflection_test.dart"></script> + </body> +</html> \ No newline at end of file
diff --git a/pkg/polymer/test/publish_attributes_test.dart b/pkg/polymer/test/publish_attributes_test.dart new file mode 100644 index 0000000..e31b74f --- /dev/null +++ b/pkg/polymer/test/publish_attributes_test.dart
@@ -0,0 +1,53 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:html'; +import 'package:unittest/unittest.dart'; +import 'package:unittest/html_config.dart'; +import 'package:polymer/polymer.dart'; + +// Dart note: unlike JS, you can't publish something that doesn't +// have a corresponding field because we can't dynamically add properties. +// So we define XFoo and XBar types here. +@CustomTag('x-foo') +class XFoo extends PolymerElement { + @observable var Foo; + @observable var baz; +} + +@CustomTag('x-bar') +class XBar extends XFoo { + @observable var Bar; +} + +@CustomTag('x-zot') +class XZot extends XBar { + @published int zot = 3; +} + +@CustomTag('x-squid') +class XSquid extends XZot { + @published int baz = 13; + @published int zot = 5; + @published int squid = 7; +} + +main() { + useHtmlConfiguration(); + + test('published properties', () { + published(tag) => + query('polymer-element[name=$tag]').xtag.publishedProperties; + + print(published('x-foo')); + print(published('x-bar')); + print(published('x-zot')); + print(published('x-squid')); + + expect(published('x-foo'), ['Foo', 'baz']); + expect(published('x-bar'), ['Foo', 'baz', 'Bar']); + expect(published('x-zot'), ['Foo', 'baz', 'Bar', 'zot']); + expect(published('x-squid'), ['Foo', 'baz', 'Bar', 'zot', 'squid']); + }); +}
diff --git a/pkg/polymer/test/publish_attributes_test.html b/pkg/polymer/test/publish_attributes_test.html new file mode 100644 index 0000000..6b9347a --- /dev/null +++ b/pkg/polymer/test/publish_attributes_test.html
@@ -0,0 +1,29 @@ +<!doctype html> +<!-- +Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +for details. All rights reserved. Use of this source code is governed by a +BSD-style license that can be found in the LICENSE file. +--> +<html> + <head> + <title>publish attributes</title> + <script src="packages/polymer/boot.js"></script> + <script src="packages/unittest/test_controller.js"></script> + </head> + <body> + + <polymer-element name="x-foo" attributes="Foo baz"> + </polymer-element> + + <polymer-element name="x-bar" extends="x-foo" attributes="Bar"> + </polymer-element> + + <polymer-element name="x-zot" extends="x-bar"> + </polymer-element> + + <polymer-element name="x-squid" extends="x-zot" attributes="squid"> + </polymer-element> + + <script type="application/dart" src="publish_attributes_test.dart"></script> + </body> +</html>
diff --git a/pkg/polymer/test/take_attributes_test.dart b/pkg/polymer/test/take_attributes_test.dart new file mode 100644 index 0000000..a9e409f --- /dev/null +++ b/pkg/polymer/test/take_attributes_test.dart
@@ -0,0 +1,109 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:html'; +import 'package:unittest/unittest.dart'; +import 'package:unittest/html_config.dart'; +import 'package:polymer/polymer.dart'; + +@CustomTag('x-foo') +class XFoo extends PolymerElement { + @published bool boolean = false; + @published num number = 42; + @published String str = "don't panic"; +} + +@CustomTag('x-bar') +class XBar extends PolymerElement { + @observable bool boolean = false; + @observable num number = 42; + @observable String str = "don't panic"; +} + +@CustomTag('x-zot') +class XZot extends XBar { + @observable num number = 84; +} + +@CustomTag('x-date') +class XDate extends PolymerElement { + @observable var value = new DateTime(2013, 9, 25); +} + +@CustomTag('x-array') +class XArray extends PolymerElement { + @observable List values; +} + +@CustomTag('x-obj') +class XObj extends PolymerElement { + @observable var values = {}; +} + +main() { + useHtmlConfiguration(); + + test('take attributes', () { + queryXTag(x) => document.query(x).xtag; + + expect(queryXTag("#foo0").boolean, true); + expect(queryXTag("#foo1").boolean, false); + expect(queryXTag("#foo2").boolean, true); + expect(queryXTag("#foo3").boolean, false); + // this one is only 'truthy' + expect(queryXTag("#foo4").boolean, true); + // this one is also 'truthy', but should it be? + expect(queryXTag("#foo5").boolean, true); + // + expect(queryXTag("#foo0").number, 42); + expect(queryXTag("#foo0").str, "don't panic"); + // + expect(queryXTag("#bar0").boolean, true); + expect(queryXTag("#bar1").boolean, false); + expect(queryXTag("#bar2").boolean, true); + expect(queryXTag("#bar3").boolean, false); + // this one is only 'truthy' + expect(queryXTag("#bar4").boolean, true); + // this one is also 'truthy', but should it be? + expect(queryXTag("#bar5").boolean, true); + // + expect(queryXTag("#bar0").number, 42); + expect(queryXTag("#bar0").str, "don't panic"); + // + expect(queryXTag("#zot0").boolean, true); + expect(queryXTag("#zot1").boolean, false); + expect(queryXTag("#zot2").boolean, true); + expect(queryXTag("#zot3").boolean, false); + // this one is only 'truthy' + expect(queryXTag("#zot4").boolean, true); + // this one is also 'truthy', but should it be? + expect(queryXTag("#zot5").boolean, true); + // + expect(queryXTag("#zot0").number, 84); + expect(queryXTag("#zot6").number, 185); + expect(queryXTag("#zot0").str, "don't panic"); + // + // Date deserialization tests + expect(queryXTag("#date1").value, new DateTime(2014, 12, 25)); + expect(queryXTag("#date2").value, isNot(equals(new DateTime(2014, 12, 25))), + reason: 'Dart does not support this format'); + expect(queryXTag("#date3").value, new DateTime(2014, 12, 25, 11, 45)); + expect(queryXTag("#date4").value, new DateTime(2014, 12, 25, 11, 45, 30)); + // Failures on Firefox. Need to fix this with custom parsing + //expect(String(queryXTag("#date5").value), String(new Date(2014, 11, 25, 11, 45, 30))); + // + // milliseconds in the Date string not supported on Firefox + //expect(queryXTag("#date5").value.getMilliseconds(), new Date(2014, 11, 25, 11, 45, 30, 33).getMilliseconds()); + // + // Array deserialization tests + expect(queryXTag("#arr1").values, [0, 1, 2]); + expect(queryXTag("#arr2").values, [33]); + // Object deserialization tests + expect(queryXTag("#obj1").values, { 'name': 'Brandon', + 'nums': [1, 22, 33] }); + expect(queryXTag("#obj2").values, { "color": "Red" }); + expect(queryXTag("#obj3").values, { 'movie': 'Buckaroo Banzai', + 'DOB': '07/31/1978' }); + }); +}
diff --git a/pkg/polymer/test/take_attributes_test.html b/pkg/polymer/test/take_attributes_test.html new file mode 100644 index 0000000..c65f604 --- /dev/null +++ b/pkg/polymer/test/take_attributes_test.html
@@ -0,0 +1,75 @@ +<!doctype html> +<!-- +Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +for details. All rights reserved. Use of this source code is governed by a +BSD-style license that can be found in the LICENSE file. +--> +<html> + <head> + <title>take attributes</title> + <script src="packages/polymer/boot.js"></script> + <script src="packages/unittest/test_controller.js"></script> + </head> + <body> + + <polymer-element name="x-foo"></polymer-element> + + <x-foo id="foo0" boolean="true"></x-foo> + <x-foo id="foo1" boolean="false"></x-foo> + <x-foo id="foo2" boolean></x-foo> + <x-foo id="foo3"></x-foo> + <x-foo id="foo4" boolean="squid"></x-foo> + <x-foo id="foo5" boolean="0"></x-foo> + + <polymer-element name="x-bar" attributes="boolean number str"> + </polymer-element> + + <x-bar id="bar0" boolean="true"></x-bar> + <x-bar id="bar1" boolean="false"></x-bar> + <x-bar id="bar2" boolean></x-bar> + <x-bar id="bar3"></x-bar> + <x-bar id="bar4" boolean="squid"></x-bar> + <x-bar id="bar5" boolean="0"></x-bar> + + <polymer-element name="x-zot" extends="x-bar" attributes="boolean"> + </polymer-element> + + <x-zot id="zot0" boolean="true"></x-zot> + <x-zot id="zot1" boolean="false"></x-zot> + <x-zot id="zot2" boolean></x-zot> + <x-zot id="zot3"></x-zot> + <x-zot id="zot4" boolean="squid"></x-zot> + <x-zot id="zot5" boolean="0"></x-zot> + <x-zot id="zot6" number="185"></x-zot> + + <polymer-element name="x-date" attributes="value"></polymer-element> + + <!-- + TODO(jmesserly): Dart note: I changed these to dash "-" instead of slash "/" + as the year-month-day separator. Also the form "December 25, 2014" is not + supported in Dart. + --> + <x-date id="date1" value="2014-12-25"></x-date> + <x-date id="date2" value="December 25, 2014"></x-date> + <x-date id="date3" value="2014-12-25 11:45"></x-date> + <x-date id="date4" value="2014-12-25 11:45:30"></x-date> + <x-date id="date5" value="2014-12-25 11:45:30:33"></x-date> + <x-date id="dated" value="2014-12-25T11:45:30:33"></x-date> + + <polymer-element name="x-array" attributes="values"></polymer-element> + + <x-array id="arr1" values="[0, 1, 2]"></x-array> + <x-array id="arr2" values="[33]"></x-array> + + <polymer-element name="x-obj" attributes="values"></polymer-element> + + <x-obj id="obj1" values='{ "name": "Brandon", "nums": [1, 22, 33] }'> + </x-obj> + <x-obj id="obj2" values='{ "color": "Red" }'></x-obj> + <x-obj id="obj3" + values="{ 'movie': 'Buckaroo Banzai', 'DOB': '07/31/1978' }"> + </x-obj> + + <script type="application/dart" src="take_attributes_test.dart"></script> + </body> +</html>
diff --git a/pkg/polymer_expressions/lib/expression.dart b/pkg/polymer_expressions/lib/expression.dart index 0a5bb82..60b7548 100644 --- a/pkg/polymer_expressions/lib/expression.dart +++ b/pkg/polymer_expressions/lib/expression.dart
@@ -8,7 +8,7 @@ // Helper functions for building expression trees programmatically -EmptyExpression empty() => new EmptyExpression(); +EmptyExpression empty() => const EmptyExpression(); Literal literal(v) => new Literal(v); MapLiteral mapLiteral(List<MapLiteralEntry> entries) => new MapLiteral(entries); MapLiteralEntry mapLiteralEntry(Literal key, Expression value) => @@ -24,7 +24,7 @@ class AstFactory { - EmptyExpression empty() => new EmptyExpression(); + EmptyExpression empty() => const EmptyExpression(); Literal literal(v) => new Literal(v); @@ -52,12 +52,13 @@ /// Base class for all expressions abstract class Expression { + const Expression(); accept(Visitor v); } class EmptyExpression extends Expression { + const EmptyExpression(); accept(Visitor v) => v.visitEmptyExpression(this); - bool operator ==(o) => o is EmptyExpression; } class Literal<T> extends Expression {
diff --git a/pkg/scheduled_test/lib/scheduled_process.dart b/pkg/scheduled_test/lib/scheduled_process.dart index 4b28309..b0ceaa3 100644 --- a/pkg/scheduled_test/lib/scheduled_process.dart +++ b/pkg/scheduled_test/lib/scheduled_process.dart
@@ -17,7 +17,9 @@ /// synchronously. All operations on this class are scheduled. /// /// Before running the test, either [shouldExit] or [kill] must be called on -/// this to ensure that the process terminates when expected. +/// this to ensure that the process terminates when expected. Note that [kill] +/// is using SIGKILL, to ensure the process is killed on Mac OS X (an early +/// SIGTERM on Mac OS X may be ignored). /// /// If the test fails, this will automatically print out any stdout and stderr /// from the process to aid debugging. @@ -220,7 +222,7 @@ if (!_exitCode.hasValue) { killedPrematurely = true; _endExpected = true; - _process.value.kill(); + _process.value.kill(ProcessSignal.SIGKILL); // Ensure that the onException queue waits for the process to actually // exit after being killed. wrapFuture(_process.value.exitCode, "waiting for process " @@ -328,7 +330,9 @@ _taskBeforeEnd = currentSchedule.tasks.contents.last; schedule(() { _endExpected = true; - return _process.then((p) => p.kill()).then((_) => _exitCode); + return _process + .then((p) => p.kill(ProcessSignal.SIGKILL)) + .then((_) => _exitCode); }, "waiting for process '$description' to die"); }
diff --git a/pkg/unittest/lib/html_config.dart b/pkg/unittest/lib/html_config.dart index e4eba0f..860ec4f 100644 --- a/pkg/unittest/lib/html_config.dart +++ b/pkg/unittest/lib/html_config.dart
@@ -10,6 +10,7 @@ import 'dart:async'; import 'dart:convert'; import 'dart:html'; +import 'dart:js' as js; import 'unittest.dart'; /** Creates a table showing tests results in HTML. */ @@ -100,7 +101,12 @@ void _installHandlers() { if (_onErrorSubscription == null) { _onErrorSubscription = window.onError.listen( - (e) => handleExternalError(e, '(DOM callback has errors)')); + (e) { + // Some tests may expect this and have no way to suppress the error. + if (js.context['testExpectsGlobalError'] != true) { + handleExternalError(e, '(DOM callback has errors)'); + } + }); } if (_onMessageSubscription == null) { _onMessageSubscription = window.onMessage.listen(
diff --git a/pkg/unittest/lib/test_controller.js b/pkg/unittest/lib/test_controller.js index 4862e03..7cf6699 100644 --- a/pkg/unittest/lib/test_controller.js +++ b/pkg/unittest/lib/test_controller.js
@@ -11,9 +11,20 @@ if (typeof console == "object" && typeof console.clear == "function") { console.clear(); } + +// Some tests may expect and have no way to suppress global errors. +var testExpectsGlobalError = false; +var testSuppressedGlobalErrors = []; + // Set window onerror to make sure that we catch test harness errors across all // browsers. window.onerror = function (message, url, lineNumber) { + if (testExpectsGlobalError) { + testSuppressedGlobalErrors.push({ + message: message + }); + return; + } if (url) { showErrorAndExit( "\n\n" + url + ":" + lineNumber + ":\n" + message + "\n\n"); @@ -67,7 +78,7 @@ // TODO(ricow): REMOVE, debug info, see issue 13292 if (!testRunner) { - dartPrint('Calling notifyDone()'); + printMessage('Calling notifyDone()'); } // To support in browser launching of tests we post back start and result // messages to the window.opener. @@ -80,7 +91,7 @@ function processMessage(msg) { // TODO(ricow): REMOVE, debug info, see issue 13292 if (!testRunner) { - dartPrint('processMessage(): ' + msg); + printMessage('processMessage(): ' + msg); } if (typeof msg != 'string') return; if (msg == 'unittest-suite-done') { @@ -95,7 +106,7 @@ window.postMessage('unittest-suite-success', '*'); } } else if (msg == 'unittest-suite-success') { - dartPrint('PASS'); + printMessage('PASS'); notifyDone(); } else if (msg == 'unittest-suite-fail') { showErrorAndExit('Some tests failed.'); @@ -114,11 +125,11 @@ function showErrorAndExit(message) { if (message) { - dartPrint('Error: ' + String(message)); + printMessage('Error: ' + String(message)); } // dart/tools/testing/run_selenium.py is looking for either PASS or // FAIL and will continue polling until one of these words show up. - dartPrint('FAIL'); + printMessage('FAIL'); notifyDone(); } @@ -158,27 +169,50 @@ }); // dart2js will generate code to call this function to handle the Dart -// [print] method. The base [Configuration] (config.html) calls -// [print] with the secret messages "unittest-suite-success" and -// "unittest-suite-wait-for-done". These messages are then posted so -// processMessage above will see them. +// [print] method. +// +// dartium will invoke this method for [print] calls if the environment variable +// "DART_FORWARDING_PRINT" was set when launching dartium. +// +// Our tests will be wrapped, so we can detect when [main] is called and when +// it has ended. +// The wrapping happens either via "dartMainRunner" (for dart2js) or wrapped +// tests for dartium. +// +// The following messages are handled specially: +// dart-calling-main: signals that the dart [main] function will be invoked +// dart-main-done: signals that the dart [main] function has finished +// unittest-suite-wait-for-done: signals the start of an asynchronous test +// unittest-suite-success: signals the end of an asynchrounous test +// +// These messages are used to communicate with the test and will be posted so +// [processMessage] above can see it. function dartPrint(msg) { if ((msg === 'unittest-suite-success') || (msg === 'unittest-suite-done') - || (msg === 'unittest-suite-wait-for-done')) { + || (msg === 'unittest-suite-wait-for-done') + || (msg === 'dart-calling-main') + || (msg === 'dart-main-done')) { window.postMessage(msg, '*'); return; } + printMessage(msg); +} + +// Prints 'msg' to the console (if available) and to the body of the html +// document. +function printMessage(msg) { if (typeof console === 'object') console.warn(msg); - var pre = document.createElement("pre"); + var pre = document.createElement('pre'); pre.appendChild(document.createTextNode(String(msg))); document.body.appendChild(pre); + document.body.appendChild(document.createTextNode('\n')); } // dart2js will generate code to call this function instead of calling // Dart [main] directly. The argument is a closure that invokes main. function dartMainRunner(main) { - window.postMessage('dart-calling-main', '*'); + dartPrint('dart-calling-main'); try { main(); } catch (e) { @@ -187,5 +221,5 @@ window.postMessage('unittest-suite-fail', '*'); return; } - window.postMessage('dart-main-done', '*'); + dartPrint('dart-main-done'); }
diff --git a/pkg/unittest/lib/vm_config.dart b/pkg/unittest/lib/vm_config.dart index 962ca97..e37cf72 100644 --- a/pkg/unittest/lib/vm_config.dart +++ b/pkg/unittest/lib/vm_config.dart
@@ -21,8 +21,9 @@ // We make this public so the user can turn it off if they want. bool useColor; - VMConfiguration() : - super(), useColor = stdioType(stdout) == StdioType.TERMINAL; + VMConfiguration() + : super(), + useColor = stdioType(stdout) == StdioType.TERMINAL; String formatResult(TestCase testCase) { String result = super.formatResult(testCase);
diff --git a/runtime/bin/builtin.cc b/runtime/bin/builtin.cc index 182f2ff..2486c5b 100644 --- a/runtime/bin/builtin.cc +++ b/runtime/bin/builtin.cc
@@ -35,7 +35,7 @@ Dart_Handle patch_file_uri = DartUtils::NewString(patch_filename); free(patch_filename); - DART_CHECK_VALID(Dart_LoadPatch(library, patch_file_uri, patch_src)); + DART_CHECK_VALID(Dart_LibraryLoadPatch(library, patch_file_uri, patch_src)); } }
diff --git a/runtime/bin/builtin_natives.cc b/runtime/bin/builtin_natives.cc index 07cc545..48c10fb 100644 --- a/runtime/bin/builtin_natives.cc +++ b/runtime/bin/builtin_natives.cc
@@ -13,6 +13,7 @@ #include "bin/builtin.h" #include "bin/dartutils.h" #include "bin/io_natives.h" +#include "bin/platform.h" namespace dart { namespace bin { @@ -26,7 +27,7 @@ V(Directory_Create, 1) \ V(Directory_Current, 0) \ V(Directory_SetCurrent, 1) \ - V(Directory_CreateTemp, 1) \ + V(Directory_CreateTemp, 2) \ V(Directory_Delete, 2) \ V(Directory_Rename, 2) \ V(Directory_List, 3) \ @@ -108,12 +109,10 @@ // an isolate gets interrupted by the embedder in the middle of // Dart_StringToUTF8? We need to make sure not to swallow the // interrupt. - fputs(Dart_GetError(result), stdout); + Platform::PrintBlocking(stdout, "%s\n", Dart_GetError(result)); } else { - fwrite(chars, sizeof(*chars), length, stdout); + Platform::PrintBlocking(stdout, "%.*s\n", static_cast<int>(length), chars); } - fputc('\n', stdout); - fflush(stdout); } } // namespace bin
diff --git a/runtime/bin/directory.cc b/runtime/bin/directory.cc index 323b4a9..6aa4d09 100644 --- a/runtime/bin/directory.cc +++ b/runtime/bin/directory.cc
@@ -78,7 +78,14 @@ void FUNCTION_NAME(Directory_CreateTemp)(Dart_NativeArguments args) { Dart_Handle path = Dart_GetNativeArgument(args, 0); - char* result = Directory::CreateTemp(DartUtils::GetStringValue(path)); + Dart_Handle system = Dart_GetNativeArgument(args, 1); + if (!Dart_IsString(path)) { + Dart_SetReturnValue(args, DartUtils::NewDartArgumentError( + "Template argument of CreateSystemTempSync is not a String")); + return; + } + char* result = Directory::CreateTemp(DartUtils::GetStringValue(path), + DartUtils::GetBooleanValue(system)); if (result != NULL) { Dart_SetReturnValue(args, DartUtils::NewString(result)); free(result); @@ -188,7 +195,7 @@ CObject* Directory::CreateTempRequest(const CObjectArray& request) { if (request.Length() == 1 && request[0]->IsString()) { CObjectString path(request[0]); - char* result = Directory::CreateTemp(path.CString()); + char* result = Directory::CreateTemp(path.CString(), false); if (result != NULL) { CObject* temp_dir = new CObjectString(CObject::NewString(result)); free(result); @@ -200,6 +207,23 @@ return CObject::IllegalArgumentError(); } + +CObject* Directory::CreateSystemTempRequest(const CObjectArray& request) { + if (request.Length() == 1 && request[0]->IsString()) { + CObjectString path(request[0]); + char* result = Directory::CreateTemp(path.CString(), true); + if (result != NULL) { + CObject* temp_dir = new CObjectString(CObject::NewString(result)); + free(result); + return temp_dir; + } else { + return CObject::NewOSError(); + } + } + return CObject::IllegalArgumentError(); +} + + static CObject* CreateIllegalArgumentError() { // Respond with an illegal argument list error message. CObjectArray* error = new CObjectArray(CObject::NewArray(3)); @@ -210,6 +234,7 @@ return error; } + CObject* Directory::ListStartRequest(const CObjectArray& request) { if (request.Length() == 3 && request[0]->IsString() &&
diff --git a/runtime/bin/directory.h b/runtime/bin/directory.h index 210739e..57302a2 100644 --- a/runtime/bin/directory.h +++ b/runtime/bin/directory.h
@@ -252,25 +252,12 @@ DOES_NOT_EXIST }; - // This enum must be kept in sync with the request values in - // directory_impl.dart. - enum DirectoryRequest { - kCreateRequest = 0, - kDeleteRequest = 1, - kExistsRequest = 2, - kCreateTempRequest = 3, - kListStartRequest = 4, - kListNextRequest = 5, - kListStopRequest = 6, - kRenameRequest = 7 - }; - static void List(DirectoryListing* listing); static ExistsResult Exists(const char* path); static char* Current(); static bool SetCurrent(const char* path); static bool Create(const char* path); - static char* CreateTemp(const char* const_template); + static char* CreateTemp(const char* const_template, bool system); static bool Delete(const char* path, bool recursive); static bool Rename(const char* path, const char* new_path); @@ -278,6 +265,7 @@ static CObject* DeleteRequest(const CObjectArray& request); static CObject* ExistsRequest(const CObjectArray& request); static CObject* CreateTempRequest(const CObjectArray& request); + static CObject* CreateSystemTempRequest(const CObjectArray& request); static CObject* ListStartRequest(const CObjectArray& request); static CObject* ListNextRequest(const CObjectArray& request); static CObject* ListStopRequest(const CObjectArray& request);
diff --git a/runtime/bin/directory_android.cc b/runtime/bin/directory_android.cc index b48474d..6a2646a 100644 --- a/runtime/bin/directory_android.cc +++ b/runtime/bin/directory_android.cc
@@ -382,33 +382,34 @@ } -char* Directory::CreateTemp(const char* const_template) { +char* Directory::CreateTemp(const char* const_template, bool system) { // Returns a new, unused directory name, modifying the contents of // dir_template. Creates the directory with the permissions specified // by the process umask. // The return value must be freed by the caller. PathBuffer path; - path.Add(const_template); - if (path.length() == 0) { + if (system) { // Android does not have a /tmp directory. A partial substitute, // suitable for bring-up work and tests, is to create a tmp // directory in /data/local/tmp. // // TODO(4413): In the long run, when running in an application we should - // probably use android.content.Context.getCacheDir(). + // probably use the appropriate directory from the Android API, + // probably what File.createTempFile uses. #define ANDROID_TEMP_DIR "/data/local/tmp" struct stat st; if (stat(ANDROID_TEMP_DIR, &st) != 0) { mkdir(ANDROID_TEMP_DIR, 0777); } - path.Add(ANDROID_TEMP_DIR "/temp_dir1_"); - } else if ((path.AsString())[path.length() - 1] == '/') { - path.Add("temp_dir_"); + path.Add(ANDROID_TEMP_DIR "/"); } + + path.Add(const_template); if (!path.Add("XXXXXX")) { // Pattern has overflowed. return NULL; } + char* result; do { result = MakeTempDirectory(path.AsString());
diff --git a/runtime/bin/directory_linux.cc b/runtime/bin/directory_linux.cc index 88c6f7c..e12dbfd 100644 --- a/runtime/bin/directory_linux.cc +++ b/runtime/bin/directory_linux.cc
@@ -9,6 +9,7 @@ #include <dirent.h> // NOLINT #include <errno.h> // NOLINT +#include <stdlib.h> // NOLINT #include <string.h> // NOLINT #include <sys/param.h> // NOLINT #include <sys/stat.h> // NOLINT @@ -372,18 +373,27 @@ } -char* Directory::CreateTemp(const char* const_template) { +char* Directory::CreateTemp(const char* const_template, bool system) { // Returns a new, unused directory name, modifying the contents of // dir_template. Creates the directory with the permissions specified // by the process umask. // The return value must be freed by the caller. PathBuffer path; - path.Add(const_template); - if (path.length() == 0) { - path.Add("/tmp/temp_dir1_"); - } else if ((path.AsString())[path.length() - 1] == '/') { - path.Add("temp_dir_"); + if (system) { + const char* temp_dir = getenv("TMPDIR"); + if (temp_dir == NULL) { + temp_dir = getenv("TMP"); + } + if (temp_dir != NULL) { + path.Add(temp_dir); + if (temp_dir[strlen(temp_dir) - 1] != '/') { + path.Add("/"); + } + } else { + path.Add("/tmp/"); + } } + path.Add(const_template); if (!path.Add("XXXXXX")) { // Pattern has overflowed. return NULL;
diff --git a/runtime/bin/directory_macos.cc b/runtime/bin/directory_macos.cc index 08232d5..5757a9c 100644 --- a/runtime/bin/directory_macos.cc +++ b/runtime/bin/directory_macos.cc
@@ -361,18 +361,27 @@ } -char* Directory::CreateTemp(const char* const_template) { +char* Directory::CreateTemp(const char* const_template, bool system) { // Returns a new, unused directory name, modifying the contents of // dir_template. Creates the directory with the permissions specified // by the process umask. // The return value must be freed by the caller. PathBuffer path; - path.Add(const_template); - if (path.length() == 0) { - path.Add("/tmp/temp_dir1_"); - } else if ((path.AsString())[path.length() - 1] == '/') { - path.Add("temp_dir_"); + if (system) { + const char* temp_dir = getenv("TMPDIR"); + if (temp_dir == NULL) { + temp_dir = getenv("TMP"); + } + if (temp_dir != NULL) { + path.Add(temp_dir); + if (temp_dir[strlen(temp_dir) - 1] != '/') { + path.Add("/"); + } + } else { + path.Add("/tmp/"); + } } + path.Add(const_template); if (!path.Add("XXXXXX")) { // Pattern has overflowed. return NULL;
diff --git a/runtime/bin/directory_patch.dart b/runtime/bin/directory_patch.dart index da4e014..f5961b9 100644 --- a/runtime/bin/directory_patch.dart +++ b/runtime/bin/directory_patch.dart
@@ -5,7 +5,8 @@ patch class _Directory { /* patch */ static _current() native "Directory_Current"; /* patch */ static _setCurrent(path) native "Directory_SetCurrent"; - /* patch */ static _createTemp(String template) native "Directory_CreateTemp"; + /* patch */ static _createTemp(String template, bool system) + native "Directory_CreateTemp"; /* patch */ static int _exists(String path) native "Directory_Exists"; /* patch */ static _create(String path) native "Directory_Create"; /* patch */ static _deleteNative(String path, bool recursive)
diff --git a/runtime/bin/directory_win.cc b/runtime/bin/directory_win.cc index f5f77bd..c72f4ef 100644 --- a/runtime/bin/directory_win.cc +++ b/runtime/bin/directory_win.cc
@@ -383,30 +383,26 @@ } -char* Directory::CreateTemp(const char* const_template) { +char* Directory::CreateTemp(const char* const_template, bool system) { // Returns a new, unused directory name, modifying the contents of // dir_template. Creates this directory, with a default security // descriptor inherited from its parent directory. // The return value must be freed by the caller. PathBuffer path; - if (0 == strncmp(const_template, "", 1)) { + if (system) { path.Reset(GetTempPathW(MAX_PATH, path.AsStringW())); if (path.length() == 0) { return NULL; } - } else { - const wchar_t* system_template = StringUtils::Utf8ToWide(const_template); - path.AddW(system_template); - free(const_cast<wchar_t*>(system_template)); } - // Length of tempdir-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx is 44. - if (path.length() > MAX_PATH - 44) { + const wchar_t* system_template = StringUtils::Utf8ToWide(const_template); + path.AddW(system_template); + free(const_cast<wchar_t*>(system_template)); + + // Length of xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx is 36. + if (path.length() > MAX_PATH - 36) { return NULL; } - if ((path.AsStringW())[path.length() - 1] == L'\\') { - // No base name for the directory - use "tempdir". - path.AddW(L"tempdir"); - } UUID uuid; RPC_STATUS status = UuidCreateSequential(&uuid); @@ -419,7 +415,6 @@ return NULL; } - path.AddW(L"-"); // RPC_WSTR is an unsigned short*, so we cast to wchar_t*. path.AddW(reinterpret_cast<wchar_t*>(uuid_string)); RpcStringFreeW(&uuid_string);
diff --git a/runtime/bin/eventhandler_win.cc b/runtime/bin/eventhandler_win.cc index 59b2207..51e98ac 100644 --- a/runtime/bin/eventhandler_win.cc +++ b/runtime/bin/eventhandler_win.cc
@@ -7,7 +7,6 @@ #include "bin/eventhandler.h" -#include <process.h> // NOLINT #include <winsock2.h> // NOLINT #include <ws2tcpip.h> // NOLINT #include <mswsock.h> // NOLINT @@ -19,7 +18,7 @@ #include "bin/log.h" #include "bin/socket.h" #include "bin/utils.h" -#include "platform/thread.h" +#include "vm/thread.h" namespace dart { @@ -107,7 +106,6 @@ pending_read_(NULL), pending_write_(NULL), last_error_(NOERROR), - thread_wrote_(0), flags_(0) { InitializeCriticalSection(&cs_); } @@ -123,7 +121,6 @@ pending_read_(NULL), pending_write_(NULL), last_error_(NOERROR), - thread_wrote_(0), flags_(0) { InitializeCriticalSection(&cs_); } @@ -211,10 +208,9 @@ } -static unsigned int __stdcall ReadFileThread(void* args) { +static void ReadFileThread(uword args) { Handle* handle = reinterpret_cast<Handle*>(args); handle->ReadSyncCompleteAsync(); - return 0; } @@ -273,11 +269,10 @@ } else { // Completing asynchronously through thread. pending_read_ = buffer; - uint32_t tid; - uintptr_t thread_handle = - _beginthreadex(NULL, 32 * 1024, ReadFileThread, this, 0, &tid); - if (thread_handle == -1) { - FATAL("Failed to start read file thread"); + int result = dart::Thread::Start(ReadFileThread, + reinterpret_cast<uword>(this)); + if (result != 0) { + FATAL1("Failed to start read file thread %d", result); } return true; } @@ -333,18 +328,6 @@ } -void FileHandle::DoClose() { - if (handle_ == GetStdHandle(STD_OUTPUT_HANDLE)) { - int fd = _open("NUL", _O_WRONLY); - ASSERT(fd >= 0); - _dup2(fd, _fileno(stdout)); - close(fd); - } else { - Handle::DoClose(); - } -} - - void DirectoryWatchHandle::EnsureInitialized( EventHandlerImplementation* event_handler) { ScopedLock lock(this); @@ -560,14 +543,46 @@ } -static unsigned int __stdcall WriteFileThread(void* args) { - Handle* handle = reinterpret_cast<Handle*>(args); - handle->WriteSyncCompleteAsync(); - return 0; +int Handle::Write(const void* buffer, int num_bytes) { + ScopedLock lock(this); + if (pending_write_ != NULL) return 0; + if (num_bytes > kBufferSize) num_bytes = kBufferSize; + ASSERT(SupportsOverlappedIO()); + if (completion_port_ == INVALID_HANDLE_VALUE) return 0; + pending_write_ = OverlappedBuffer::AllocateWriteBuffer(num_bytes); + pending_write_->Write(buffer, num_bytes); + if (!IssueWrite()) return -1; + return num_bytes; } -void Handle::WriteSyncCompleteAsync() { +static void WriteFileThread(uword args) { + StdHandle* handle = reinterpret_cast<StdHandle*>(args); + handle->RunWriteLoop(); +} + + +void StdHandle::RunWriteLoop() { + write_monitor_->Enter(); + write_thread_running_ = true; + // Notify we have started. + write_monitor_->Notify(); + + while (write_thread_running_) { + write_monitor_->Wait(Monitor::kNoTimeout); + if (pending_write_ != NULL) { + // We woke up and had a pending write. Execute it. + WriteSyncCompleteAsync(); + } + } + + write_thread_exists_ = false; + write_monitor_->Notify(); + write_monitor_->Exit(); +} + + +void StdHandle::WriteSyncCompleteAsync() { ASSERT(pending_write_ != NULL); DWORD bytes_written = -1; @@ -593,39 +608,57 @@ } } - -int Handle::Write(const void* buffer, int num_bytes) { +int StdHandle::Write(const void* buffer, int num_bytes) { ScopedLock lock(this); if (pending_write_ != NULL) return 0; if (num_bytes > kBufferSize) num_bytes = kBufferSize; - if (SupportsOverlappedIO()) { - if (completion_port_ == INVALID_HANDLE_VALUE) return 0; - pending_write_ = OverlappedBuffer::AllocateWriteBuffer(num_bytes); - pending_write_->Write(buffer, num_bytes); - if (!IssueWrite()) return -1; + // In the case of stdout and stderr, OverlappedIO is not supported. + // Here we'll instead use a thread, to make it async. + // This code is actually never exposed to the user, as stdout and stderr is + // not available as a RawSocket, but only wrapped in a Socket. + // Note that we return '0', unless a thread have already completed a write. + MonitorLocker locker(write_monitor_); + if (thread_wrote_ > 0) { + if (num_bytes > thread_wrote_) num_bytes = thread_wrote_; + thread_wrote_ -= num_bytes; return num_bytes; + } + if (!write_thread_exists_) { + write_thread_exists_ = true; + int result = dart::Thread::Start(WriteFileThread, + reinterpret_cast<uword>(this)); + if (result != 0) { + FATAL1("Failed to start write file thread %d", result); + } + while (!write_thread_running_) { + // Wait until we the thread is running. + locker.Wait(Monitor::kNoTimeout); + } + } + // Create buffer and notify thread about the new handle. + pending_write_ = OverlappedBuffer::AllocateWriteBuffer(num_bytes); + pending_write_->Write(buffer, num_bytes); + locker.Notify(); + return 0; +} + + +void StdHandle::DoClose() { + MonitorLocker locker(write_monitor_); + if (write_thread_exists_) { + write_thread_running_ = false; + locker.Notify(); + while (write_thread_exists_) { + locker.Wait(Monitor::kNoTimeout); + } + } + if (handle_ == GetStdHandle(STD_OUTPUT_HANDLE)) { + int fd = _open("NUL", _O_WRONLY); + ASSERT(fd >= 0); + _dup2(fd, _fileno(stdout)); + close(fd); } else { - // In the case of stdout and stderr, OverlappedIO is not supported. - // Here we'll instead spawn a new thread for each write, to make it async. - // This code is actually never exposed to the user, as stdout and stderr is - // not available as a RawSocket, but only wrapped in a Socket. - // Note that we return '0', unless a thread have already completed a write. - // TODO(ajohnsen): Don't spawn a new thread per write. Issue 13541. - if (thread_wrote_ > 0) { - if (num_bytes > thread_wrote_) num_bytes = thread_wrote_; - thread_wrote_ -= num_bytes; - return num_bytes; - } - pending_write_ = OverlappedBuffer::AllocateWriteBuffer(num_bytes); - pending_write_->Write(buffer, num_bytes); - // Completing asynchronously through thread. - uint32_t tid; - uintptr_t thread_handle = - _beginthreadex(NULL, 32 * 1024, WriteFileThread, this, 0, &tid); - if (thread_handle == -1) { - FATAL("Failed to start write file thread"); - } - return 0; + Handle::DoClose(); } }
diff --git a/runtime/bin/eventhandler_win.h b/runtime/bin/eventhandler_win.h index 945277b..43562cd 100644 --- a/runtime/bin/eventhandler_win.h +++ b/runtime/bin/eventhandler_win.h
@@ -13,6 +13,7 @@ #include <mswsock.h> #include "bin/builtin.h" +#include "platform/thread.h" namespace dart { @@ -132,6 +133,7 @@ public: enum Type { kFile, + kStd, kDirectoryWatch, kClientSocket, kListenSocket @@ -156,7 +158,7 @@ // Socket interface exposing normal socket operations. int Available(); int Read(void* buffer, int num_bytes); - int Write(const void* buffer, int num_bytes); + virtual int Write(const void* buffer, int num_bytes); // Internal interface used by the event handler. virtual bool IssueRead(); @@ -211,7 +213,6 @@ } void ReadSyncCompleteAsync(); - void WriteSyncCompleteAsync(); DWORD last_error() { return last_error_; } void set_last_error(DWORD last_error) { last_error_ = last_error; } @@ -242,7 +243,6 @@ OverlappedBuffer* pending_write_; // Buffer for pending write DWORD last_error_; - DWORD thread_wrote_; private: int flags_; @@ -259,7 +259,35 @@ virtual void EnsureInitialized(EventHandlerImplementation* event_handler); virtual bool IsClosed(); +}; + + +class StdHandle : public FileHandle { + public: + explicit StdHandle(HANDLE handle) + : FileHandle(handle), + thread_wrote_(0), + write_thread_exists_(false), + write_thread_running_(false), + write_monitor_(new Monitor()) { + type_ = kStd; + } + + ~StdHandle() { + delete write_monitor_; + } + virtual void DoClose(); + virtual int Write(const void* buffer, int num_bytes); + + void WriteSyncCompleteAsync(); + void RunWriteLoop(); + + private: + DWORD thread_wrote_; + bool write_thread_exists_; + bool write_thread_running_; + dart::Monitor* write_monitor_; };
diff --git a/runtime/bin/file.h b/runtime/bin/file.h index 6eec87a..41efb4c 100644 --- a/runtime/bin/file.h +++ b/runtime/bin/file.h
@@ -60,35 +60,6 @@ kOther = 4 }; - enum FileRequest { - kExistsRequest = 0, - kCreateRequest = 1, - kDeleteRequest = 2, - kRenameRequest = 3, - kOpenRequest = 4, - kResolveSymbolicLinksRequest = 5, - kCloseRequest = 6, - kPositionRequest = 7, - kSetPositionRequest = 8, - kTruncateRequest = 9, - kLengthRequest = 10, - kLengthFromPathRequest = 11, - kLastModifiedRequest = 12, - kFlushRequest = 13, - kReadByteRequest = 14, - kWriteByteRequest = 15, - kReadRequest = 16, - kReadIntoRequest = 17, - kWriteFromRequest = 18, - kCreateLinkRequest = 19, - kDeleteLinkRequest = 20, - kRenameLinkRequest = 21, - kLinkTargetRequest = 22, - kTypeRequest = 23, - kIdenticalRequest = 24, - kStatRequest = 25 - }; - enum FileStat { // These match the constants in FileStat in file_system_entity.dart. kType = 0,
diff --git a/runtime/bin/file_system_watcher_win.cc b/runtime/bin/file_system_watcher_win.cc index 014d861..e08c28d 100644 --- a/runtime/bin/file_system_watcher_win.cc +++ b/runtime/bin/file_system_watcher_win.cc
@@ -49,8 +49,13 @@ } if (events & kModifyContent) list_events |= FILE_NOTIFY_CHANGE_LAST_WRITE; - return reinterpret_cast<intptr_t>( - new DirectoryWatchHandle(dir, list_events, recursive)); + DirectoryWatchHandle* handle = + new DirectoryWatchHandle(dir, list_events, recursive); + // Issue a read directly, to be sure events are tracked from now on. This is + // okay, since in Dart, we create the socket and start reading immidiately. + handle->EnsureInitialized(EventHandler::delegate()); + handle->IssueRead(); + return reinterpret_cast<intptr_t>(handle); }
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc index 0612f15..9f70743 100644 --- a/runtime/bin/gen_snapshot.cc +++ b/runtime/bin/gen_snapshot.cc
@@ -143,8 +143,8 @@ static void WriteSnapshotFile(const uint8_t* buffer, const intptr_t size) { File* file = File::Open(snapshot_filename, File::kWriteTruncate); ASSERT(file != NULL); - for (intptr_t i = 0; i < size; i++) { - file->WriteByte(buffer[i]); + if (!file->WriteFully(buffer, size)) { + Log::PrintErr("Error: Failed to write full snapshot.\n\n"); } delete file; }
diff --git a/runtime/bin/io_service.h b/runtime/bin/io_service.h index 0559039..8c1ba9f 100644 --- a/runtime/bin/io_service.h +++ b/runtime/bin/io_service.h
@@ -12,6 +12,7 @@ namespace dart { namespace bin { +// This list must be kept in sync with the list in sdk/lib/io/io_service.dart #define IO_SERVICE_REQUEST_LIST(V) \ V(File, Exists, 0) \ V(File, Create, 1) \ @@ -46,11 +47,12 @@ V(Directory, Delete, 30) \ V(Directory, Exists, 31) \ V(Directory, CreateTemp, 32) \ - V(Directory, ListStart, 33) \ - V(Directory, ListNext, 34) \ - V(Directory, ListStop, 35) \ - V(Directory, Rename, 36) \ - V(SSLFilter, ProcessFilter, 37) + V(Directory, CreateSystemTemp, 33) \ + V(Directory, ListStart, 34) \ + V(Directory, ListNext, 35) \ + V(Directory, ListStop, 36) \ + V(Directory, Rename, 37) \ + V(SSLFilter, ProcessFilter, 38) #define DECLARE_REQUEST(type, method, id) \ k##type##method##Request = id, @@ -68,4 +70,3 @@ } // namespace dart #endif // BIN_IO_SERVICE_H_ -
diff --git a/runtime/bin/platform.h b/runtime/bin/platform.h index ca723ae3..16be960 100644 --- a/runtime/bin/platform.h +++ b/runtime/bin/platform.h
@@ -62,6 +62,9 @@ return argv_; } + static void PrintBlocking(FILE* file, const char* format, ...) + PRINTF_ATTRIBUTE(2, 3); + private: static const char* executable_name_; static const char* package_root_;
diff --git a/runtime/bin/platform_android.cc b/runtime/bin/platform_android.cc index dfa2e27..445ea01 100644 --- a/runtime/bin/platform_android.cc +++ b/runtime/bin/platform_android.cc
@@ -11,6 +11,8 @@ #include <string.h> // NOLINT #include <unistd.h> // NOLINT +#include "bin/fdutils.h" + namespace dart { namespace bin { @@ -64,6 +66,18 @@ delete[] env; } + +void Platform::PrintBlocking(FILE* file, const char* format, ...) { + int fd = fileno(file); + FDUtils::SetBlocking(fd); + va_list args; + va_start(args, format); + vfprintf(file, format, args); + fflush(file); + va_end(args); + FDUtils::SetNonBlocking(fd); +} + } // namespace bin } // namespace dart
diff --git a/runtime/bin/platform_linux.cc b/runtime/bin/platform_linux.cc index af557af..80aa0af 100644 --- a/runtime/bin/platform_linux.cc +++ b/runtime/bin/platform_linux.cc
@@ -11,6 +11,8 @@ #include <string.h> // NOLINT #include <unistd.h> // NOLINT +#include "bin/fdutils.h" + namespace dart { namespace bin { @@ -64,6 +66,18 @@ delete[] env; } + +void Platform::PrintBlocking(FILE* file, const char* format, ...) { + int fd = fileno(file); + FDUtils::SetBlocking(fd); + va_list args; + va_start(args, format); + vfprintf(file, format, args); + fflush(file); + va_end(args); + FDUtils::SetNonBlocking(fd); +} + } // namespace bin } // namespace dart
diff --git a/runtime/bin/platform_macos.cc b/runtime/bin/platform_macos.cc index 0576c34..5af6c5a 100644 --- a/runtime/bin/platform_macos.cc +++ b/runtime/bin/platform_macos.cc
@@ -12,6 +12,8 @@ #include <string.h> // NOLINT #include <unistd.h> // NOLINT +#include "bin/fdutils.h" + namespace dart { namespace bin { @@ -68,6 +70,18 @@ delete[] env; } + +void Platform::PrintBlocking(FILE* file, const char* format, ...) { + int fd = fileno(file); + FDUtils::SetBlocking(fd); + va_list args; + va_start(args, format); + vfprintf(file, format, args); + fflush(file); + va_end(args); + FDUtils::SetNonBlocking(fd); +} + } // namespace bin } // namespace dart
diff --git a/runtime/bin/platform_win.cc b/runtime/bin/platform_win.cc index 85b6694..cd0f0f2 100644 --- a/runtime/bin/platform_win.cc +++ b/runtime/bin/platform_win.cc
@@ -64,6 +64,16 @@ delete[] env; } + +void Platform::PrintBlocking(FILE* file, const char* format, ...) { + // No need to set blocking, as it's always blocking on Windows. + va_list args; + va_start(args, format); + vfprintf(file, format, args); + fflush(file); + va_end(args); +} + } // namespace bin } // namespace dart
diff --git a/runtime/bin/socket.h b/runtime/bin/socket.h index d6f9b0d..63fc5ef 100644 --- a/runtime/bin/socket.h +++ b/runtime/bin/socket.h
@@ -52,7 +52,7 @@ ADDRESS_LAST = ADDRESS_ANY_IP_V6, }; - explicit SocketAddress(struct sockaddr* sockaddr); + explicit SocketAddress(struct sockaddr* sa); ~SocketAddress() {} @@ -101,9 +101,9 @@ class InterfaceSocketAddress { public: - explicit InterfaceSocketAddress(struct sockaddr* sockaddr, + explicit InterfaceSocketAddress(struct sockaddr* sa, const char* interface_name) - : socket_address_(new SocketAddress(sockaddr)), + : socket_address_(new SocketAddress(sa)), interface_name_(interface_name) {} ~InterfaceSocketAddress() {
diff --git a/runtime/bin/socket_android.cc b/runtime/bin/socket_android.cc index 18b2bd8..38c1c7f 100644 --- a/runtime/bin/socket_android.cc +++ b/runtime/bin/socket_android.cc
@@ -22,26 +22,19 @@ namespace dart { namespace bin { -SocketAddress::SocketAddress(struct sockaddr* sockaddr) { +SocketAddress::SocketAddress(struct sockaddr* sa) { ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN); - RawAddr* raw = reinterpret_cast<RawAddr*>(sockaddr); - const char* result; - if (sockaddr->sa_family == AF_INET) { - result = inet_ntop(sockaddr->sa_family, - &raw->in.sin_addr, - as_string_, - INET_ADDRSTRLEN); - } else { - ASSERT(sockaddr->sa_family == AF_INET6); - result = inet_ntop(sockaddr->sa_family, - &raw->in6.sin6_addr, - as_string_, - INET6_ADDRSTRLEN); + socklen_t salen = GetAddrLength(reinterpret_cast<RawAddr*>(sa)); + if (TEMP_FAILURE_RETRY(getnameinfo(sa, + salen, + as_string_, + INET6_ADDRSTRLEN, + NULL, + 0, + NI_NUMERICHOST)) != 0) { + as_string_[0] = 0; } - if (result == NULL) as_string_[0] = 0; - memmove(reinterpret_cast<void *>(&addr_), - sockaddr, - GetAddrLength(raw)); + memmove(reinterpret_cast<void *>(&addr_), sa, salen); } @@ -157,20 +150,17 @@ Log::PrintErr("Error getpeername: %s\n", error_message); return false; } - const void* src; - if (raw.ss.ss_family == AF_INET6) { - src = reinterpret_cast<const void*>(&raw.in6.sin6_addr); - } else { - src = reinterpret_cast<const void*>(&raw.in.sin_addr); - } - if (inet_ntop(raw.ss.ss_family, - src, - host, - INET_ADDRSTRLEN) == NULL) { + if (TEMP_FAILURE_RETRY(getnameinfo(&raw.addr, + size, + host, + INET6_ADDRSTRLEN, + NULL, + 0, + NI_NUMERICHOST)) != 0) { const int kBufferSize = 1024; char error_message[kBufferSize]; strerror_r(errno, error_message, kBufferSize); - Log::PrintErr("Error inet_ntop: %s\n", error_message); + Log::PrintErr("Error getnameinfo: %s\n", error_message); return false; } *port = SocketAddress::GetAddrPort(&raw);
diff --git a/runtime/bin/socket_linux.cc b/runtime/bin/socket_linux.cc index 24e688d..b9431e1 100644 --- a/runtime/bin/socket_linux.cc +++ b/runtime/bin/socket_linux.cc
@@ -23,26 +23,19 @@ namespace dart { namespace bin { -SocketAddress::SocketAddress(struct sockaddr* sockaddr) { +SocketAddress::SocketAddress(struct sockaddr* sa) { ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN); - RawAddr* raw = reinterpret_cast<RawAddr*>(sockaddr); - const char* result; - if (sockaddr->sa_family == AF_INET) { - result = inet_ntop(sockaddr->sa_family, - &raw->in.sin_addr, - as_string_, - INET_ADDRSTRLEN); - } else { - ASSERT(sockaddr->sa_family == AF_INET6); - result = inet_ntop(sockaddr->sa_family, - &raw->in6.sin6_addr, - as_string_, - INET6_ADDRSTRLEN); + socklen_t salen = GetAddrLength(reinterpret_cast<RawAddr*>(sa)); + if (TEMP_FAILURE_RETRY(getnameinfo(sa, + salen, + as_string_, + INET6_ADDRSTRLEN, + NULL, + 0, + NI_NUMERICHOST)) != 0) { + as_string_[0] = 0; } - if (result == NULL) as_string_[0] = 0; - memmove(reinterpret_cast<void *>(&addr_), - sockaddr, - GetAddrLength(raw)); + memmove(reinterpret_cast<void *>(&addr_), sa, salen); } @@ -158,19 +151,16 @@ strerror_r(errno, error_buf, kBufferSize)); return false; } - const void* src; - if (raw.ss.ss_family == AF_INET6) { - src = reinterpret_cast<const void*>(&raw.in6.sin6_addr); - } else { - src = reinterpret_cast<const void*>(&raw.in.sin_addr); - } - if (inet_ntop(raw.ss.ss_family, - src, - host, - INET_ADDRSTRLEN) == NULL) { + if (TEMP_FAILURE_RETRY(getnameinfo(&raw.addr, + size, + host, + INET6_ADDRSTRLEN, + NULL, + 0, + NI_NUMERICHOST)) != 0) { const int kBufferSize = 1024; char error_buf[kBufferSize]; - Log::PrintErr("Error inet_ntop: %s\n", + Log::PrintErr("Error getnameinfo: %s\n", strerror_r(errno, error_buf, kBufferSize)); return false; }
diff --git a/runtime/bin/socket_macos.cc b/runtime/bin/socket_macos.cc index 2b6138f..be7beca 100644 --- a/runtime/bin/socket_macos.cc +++ b/runtime/bin/socket_macos.cc
@@ -23,26 +23,19 @@ namespace dart { namespace bin { -SocketAddress::SocketAddress(struct sockaddr* sockaddr) { +SocketAddress::SocketAddress(struct sockaddr* sa) { ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN); - RawAddr* raw = reinterpret_cast<RawAddr*>(sockaddr); - const char* result; - if (sockaddr->sa_family == AF_INET) { - result = inet_ntop(sockaddr->sa_family, - &raw->in.sin_addr, - as_string_, - INET_ADDRSTRLEN); - } else { - ASSERT(sockaddr->sa_family == AF_INET6); - result = inet_ntop(sockaddr->sa_family, - &raw->in6.sin6_addr, - as_string_, - INET6_ADDRSTRLEN); + socklen_t salen = GetAddrLength(reinterpret_cast<RawAddr*>(sa)); + if (TEMP_FAILURE_RETRY(getnameinfo(sa, + salen, + as_string_, + INET6_ADDRSTRLEN, + NULL, + 0, + NI_NUMERICHOST)) != 0) { + as_string_[0] = 0; } - if (result == NULL) as_string_[0] = 0; - memmove(reinterpret_cast<void *>(&addr_), - sockaddr, - GetAddrLength(raw)); + memmove(reinterpret_cast<void *>(&addr_), sa, salen); } @@ -158,20 +151,17 @@ Log::PrintErr("Error getpeername: %s\n", error_message); return false; } - const void* src; - if (raw.ss.ss_family == AF_INET6) { - src = reinterpret_cast<const void*>(&raw.in6.sin6_addr); - } else { - src = reinterpret_cast<const void*>(&raw.in.sin_addr); - } - if (inet_ntop(raw.ss.ss_family, - src, - host, - INET_ADDRSTRLEN) == NULL) { + if (TEMP_FAILURE_RETRY(getnameinfo(&raw.addr, + size, + host, + INET6_ADDRSTRLEN, + NULL, + 0, + NI_NUMERICHOST)) != 0) { const int kBufferSize = 1024; char error_message[kBufferSize]; strerror_r(errno, error_message, kBufferSize); - Log::PrintErr("Error inet_ntop: %s\n", error_message); + Log::PrintErr("Error getnameinfo: %s\n", error_message); return false; } *port = SocketAddress::GetAddrPort(&raw);
diff --git a/runtime/bin/socket_patch.dart b/runtime/bin/socket_patch.dart index 0042aed..4fffbf7 100644 --- a/runtime/bin/socket_patch.dart +++ b/runtime/bin/socket_patch.dart
@@ -484,7 +484,9 @@ continue; } if (i == ERROR_EVENT) { - reportError(nativeGetError(), ""); + if (!isClosing) { + reportError(nativeGetError(), ""); + } } else if (!isClosed) { // If the connection is closed right after it's accepted, there's a // chance the close-handler is not set. @@ -711,6 +713,8 @@ int get port => _socket.port; + InternetAddress get address => _socket.address; + Future close() => _socket.close().then((_) => this); void _pause() { @@ -921,6 +925,8 @@ int get port => _socket.port; + InternetAddress get address => _socket.address; + Future close() => _socket.close().then((_) => this); }
diff --git a/runtime/bin/socket_win.cc b/runtime/bin/socket_win.cc index 87a0b30..a5d55a9 100644 --- a/runtime/bin/socket_win.cc +++ b/runtime/bin/socket_win.cc
@@ -198,11 +198,11 @@ if (handle == INVALID_HANDLE_VALUE) { return -1; } - FileHandle* file_handle = new FileHandle(handle); - if (file_handle == NULL) return -1; - file_handle->MarkDoesNotSupportOverlappedIO(); - file_handle->EnsureInitialized(EventHandler::delegate()); - return reinterpret_cast<intptr_t>(file_handle); + StdHandle* std_handle = new StdHandle(handle); + if (std_handle == NULL) return -1; + std_handle->MarkDoesNotSupportOverlappedIO(); + std_handle->EnsureInitialized(EventHandler::delegate()); + return reinterpret_cast<intptr_t>(std_handle); }
diff --git a/runtime/dart-runtime.gyp b/runtime/dart-runtime.gyp index 7c4f4c4..f89950a 100644 --- a/runtime/dart-runtime.gyp +++ b/runtime/dart-runtime.gyp
@@ -15,20 +15,9 @@ 'version_in_cc_file': 'vm/version_in.cc', 'version_cc_file': '<(gen_source_dir)/version.cc', - # Disable the OpenGLUI embedder by default on desktop OSes. Note, - # to build this on the desktop, you need GLUT installed. - 'enable_openglui%': 0, 'libdart_deps': ['libdart_lib_withcore', 'libdart_lib', 'libdart_vm', 'libjscre', 'libdouble_conversion',], }, - 'conditions': [ - ['OS=="android" or enable_openglui==1', { - 'includes': [ - 'embedders/openglui/openglui_embedder.gypi', - ], - }, - ], - ], 'targets': [ { 'target_name': 'libdart',
diff --git a/runtime/embedders/openglui/android/android_graphics_handler.cc b/runtime/embedders/openglui/android/android_graphics_handler.cc deleted file mode 100644 index f2c0ea2..0000000 --- a/runtime/embedders/openglui/android/android_graphics_handler.cc +++ /dev/null
@@ -1,87 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#include "embedders/openglui/android/android_graphics_handler.h" -#include "embedders/openglui/common/log.h" - -AndroidGraphicsHandler::AndroidGraphicsHandler(android_app* application, - const char* resource_path) - : GraphicsHandler(resource_path), - application_(application), - display_(EGL_NO_DISPLAY), - surface_(EGL_NO_SURFACE), - context_(EGL_NO_CONTEXT) { -} - -int32_t AndroidGraphicsHandler::Start() { - EGLint format, numConfigs; - EGLConfig config; - const EGLint attributes[] = { - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, - EGL_NONE - }; - static const EGLint ctx_attribs[] = { - EGL_CONTEXT_CLIENT_VERSION, 2, - EGL_NONE - }; - - display_ = eglGetDisplay(EGL_DEFAULT_DISPLAY); - if (display_ != EGL_NO_DISPLAY) { - LOGI("eglInitialize"); - if (eglInitialize(display_, NULL, NULL)) { - LOGI("eglChooseConfig"); - if (eglChooseConfig(display_, attributes, &config, 1, &numConfigs) && - numConfigs > 0) { - LOGI("eglGetConfigAttrib returned %d configs\n", numConfigs); - if (eglGetConfigAttrib(display_, config, - EGL_NATIVE_VISUAL_ID, &format)) { - ANativeWindow_setBuffersGeometry(application_->window, 0, 0, format); - surface_ = eglCreateWindowSurface(display_, config, - (EGLNativeWindowType)application_->window, NULL); - if (surface_ != EGL_NO_SURFACE) { - LOGI("eglCreateContext"); - context_ = eglCreateContext(display_, config, EGL_NO_CONTEXT, - ctx_attribs); - if (context_ != EGL_NO_CONTEXT) { - if (eglMakeCurrent(display_, surface_, surface_, context_) && - eglQuerySurface(display_, surface_, EGL_WIDTH, &width_) && - width_ > 0 && - eglQuerySurface(display_, surface_, EGL_HEIGHT, &height_) && - height_ > 0) { - LOGI("Got dimensions %d x %d\n", width_, height_); - SetViewport(0, 0, width_, height_); - LOGI("GL version %s\n", glGetString(GL_VERSION)); - LOGI("GLSL version: %s\n", - glGetString(GL_SHADING_LANGUAGE_VERSION)); - return GraphicsHandler::Start(); - } - } - } - } - } - } - } - LOGE("Error starting graphics"); - Stop(); - return -1; -} - -void AndroidGraphicsHandler::Stop() { - LOGI("Stopping graphics"); - GraphicsHandler::Stop(); - if (display_ != EGL_NO_DISPLAY) { - eglMakeCurrent(display_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - if (context_ != EGL_NO_CONTEXT) { - eglDestroyContext(display_, context_); - context_ = EGL_NO_CONTEXT; - } - if (surface_ != EGL_NO_SURFACE) { - eglDestroySurface(display_, surface_); - surface_ = EGL_NO_SURFACE; - } - eglTerminate(display_); - display_ = EGL_NO_DISPLAY; - } -} -
diff --git a/runtime/embedders/openglui/android/android_graphics_handler.h b/runtime/embedders/openglui/android/android_graphics_handler.h deleted file mode 100644 index c157d95..0000000 --- a/runtime/embedders/openglui/android/android_graphics_handler.h +++ /dev/null
@@ -1,27 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#ifndef EMBEDDERS_OPENGLUI_ANDROID_ANDROID_GRAPHICS_HANDLER_H_ -#define EMBEDDERS_OPENGLUI_ANDROID_ANDROID_GRAPHICS_HANDLER_H_ - -#include <android_native_app_glue.h> -#include "embedders/openglui/common/graphics_handler.h" - -class AndroidGraphicsHandler : public GraphicsHandler { - public: - AndroidGraphicsHandler(android_app* application, - const char* resource_path); - - int32_t Start(); - void Stop(); - - private: - android_app* application_; - EGLDisplay display_; - EGLSurface surface_; - EGLContext context_; -}; - -#endif // EMBEDDERS_OPENGLUI_ANDROID_ANDROID_GRAPHICS_HANDLER_H_ -
diff --git a/runtime/embedders/openglui/android/android_input_handler.h b/runtime/embedders/openglui/android/android_input_handler.h deleted file mode 100644 index 420e459..0000000 --- a/runtime/embedders/openglui/android/android_input_handler.h +++ /dev/null
@@ -1,36 +0,0 @@ -// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#ifndef EMBEDDERS_OPENGLUI_ANDROID_ANDROID_INPUT_HANDLER_H_ -#define EMBEDDERS_OPENGLUI_ANDROID_ANDROID_INPUT_HANDLER_H_ - -#include "embedders/openglui/common/graphics_handler.h" -#include "embedders/openglui/common/input_handler.h" - -class AndroidInputHandler : public InputHandler { - public: - AndroidInputHandler(VMGlue* vm_glue, - GraphicsHandler* graphics_handler) - : InputHandler(vm_glue), - graphics_handler_(graphics_handler) { - } - - public: - int32_t Start() { - if (graphics_handler_->width() == 0 || - graphics_handler_->height() == 0) { - return -1; - } - return 0; - } - - void Stop() { - } - - private: - GraphicsHandler* graphics_handler_; -}; - -#endif // EMBEDDERS_OPENGLUI_ANDROID_ANDROID_INPUT_HANDLER_H_ -
diff --git a/runtime/embedders/openglui/android/android_log.h b/runtime/embedders/openglui/android/android_log.h deleted file mode 100644 index ff82d0b..0000000 --- a/runtime/embedders/openglui/android/android_log.h +++ /dev/null
@@ -1,17 +0,0 @@ -// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#ifndef EMBEDDERS_OPENGLUI_ANDROID_ANDROID_LOG_H_ -#define EMBEDDERS_OPENGLUI_ANDROID_ANDROID_LOG_H_ - -#include <android/log.h> - -#define LOGX(LOG_LEVEL, ...) do { \ - __android_log_print(LOG_LEVEL, "DartExt", __VA_ARGS__); \ - } while (0) -#define LOGI(...) LOGX(ANDROID_LOG_INFO, __VA_ARGS__) -#define LOGE(...) LOGX(ANDROID_LOG_ERROR, __VA_ARGS__) - -#endif // EMBEDDERS_OPENGLUI_ANDROID_ANDROID_LOG_H_ -
diff --git a/runtime/embedders/openglui/android/android_resource.h b/runtime/embedders/openglui/android/android_resource.h deleted file mode 100644 index 85e0614..0000000 --- a/runtime/embedders/openglui/android/android_resource.h +++ /dev/null
@@ -1,67 +0,0 @@ -// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#ifndef EMBEDDERS_OPENGLUI_ANDROID_ANDROID_RESOURCE_H_ -#define EMBEDDERS_OPENGLUI_ANDROID_ANDROID_RESOURCE_H_ - -#include <android_native_app_glue.h> - -#include "embedders/openglui/common/log.h" -#include "embedders/openglui/common/resource.h" - -class AndroidResource : public Resource { - public: - AndroidResource(android_app* application, const char* path) - : Resource(path), - asset_manager_(application->activity->assetManager), - asset_(NULL) { - } - - int32_t descriptor() { - if (Open() == 0) { - descriptor_ = AAsset_openFileDescriptor(asset_, &start_, &length_); - LOGI("%s has start %d, length %d, fd %d", - path_, static_cast<int>(start_), static_cast<int>(length_), - descriptor_); - return descriptor_; - } - return -1; - } - - off_t length() { - if (length_ < 0) { - length_ = AAsset_getLength(asset_); - } - return length_; - } - - int32_t Open() { - LOGI("Attempting to open asset %s", path_); - asset_ = AAssetManager_open(asset_manager_, path_, AASSET_MODE_UNKNOWN); - if (asset_ != NULL) { - return 0; - } - LOGE("Could not open asset %s", path_); - return -1; - } - - void Close() { - if (asset_ != NULL) { - AAsset_close(asset_); - asset_ = NULL; - } - } - - int32_t Read(void* buffer, size_t count) { - size_t actual = AAsset_read(asset_, buffer, count); - return (actual == count) ? 0 : -1; - } - - private: - AAssetManager* asset_manager_; - AAsset* asset_; -}; - -#endif // EMBEDDERS_OPENGLUI_ANDROID_ANDROID_RESOURCE_H_ -
diff --git a/runtime/embedders/openglui/android/android_sound_handler.cc b/runtime/embedders/openglui/android/android_sound_handler.cc deleted file mode 100644 index de9e977..0000000 --- a/runtime/embedders/openglui/android/android_sound_handler.cc +++ /dev/null
@@ -1,277 +0,0 @@ -// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#include "embedders/openglui/android/android_sound_handler.h" - -#include "embedders/openglui/android/android_resource.h" -#include "embedders/openglui/common/log.h" - -AndroidSoundHandler::AndroidSoundHandler(android_app* application) - : SoundHandler(), - application_(application), - engine_(NULL), - engine_if_(NULL), - output_mix_(NULL), - background_player_(NULL), - background_player_if_(NULL), - background_player_seek_if_(NULL), - sample_player_(NULL), - sample_player_if_(NULL), - sample_player_queue_(NULL) { -} - -int32_t AndroidSoundHandler::Start() { - LOGI("Starting SoundService"); - - const SLInterfaceID k_engine_mix_IIDs[] = { SL_IID_ENGINE }; - const SLboolean k_engine_mix_reqs[] = { SL_BOOLEAN_TRUE }; - const SLInterfaceID k_output_mix_IIDs[] = {}; - const SLboolean k_output_mix_reqs[] = {}; - int32_t res = slCreateEngine(&engine_, 0, NULL, 1, - k_engine_mix_IIDs, k_engine_mix_reqs); - if (res == SL_RESULT_SUCCESS) { - res = (*engine_)->Realize(engine_, SL_BOOLEAN_FALSE); - if (res == SL_RESULT_SUCCESS) { - res = (*engine_)->GetInterface(engine_, SL_IID_ENGINE, &engine_if_); - if (res == SL_RESULT_SUCCESS) { - res = (*engine_if_)->CreateOutputMix(engine_if_, &output_mix_, 0, - k_output_mix_IIDs, k_output_mix_reqs); - if (res == SL_RESULT_SUCCESS) { - res = (*output_mix_)->Realize(output_mix_, SL_BOOLEAN_FALSE); - if (res == SL_RESULT_SUCCESS) { - if (StartSamplePlayer() == 0) { - return 0; - } - } - } - } - } - } - LOGI("Failed to start SoundService"); - Stop(); - return -1; -} - -void AndroidSoundHandler::Stop() { - LOGI("Stopping SoundService"); - if (sample_player_ != NULL) { - LOGI("Destroying sample player"); - (*sample_player_)->Destroy(sample_player_); - sample_player_ = NULL; - sample_player_if_ = NULL; - sample_player_queue_ = NULL; - } - samples_.clear(); - if (output_mix_ != NULL) { - LOGI("Destroying output mix"); - (*output_mix_)->Destroy(output_mix_); - output_mix_ = NULL; - } - if (engine_ != NULL) { - LOGI("Destroying engine"); - (*engine_)->Destroy(engine_); - engine_ = NULL; - engine_if_ = NULL; - } -} - -int32_t AndroidSoundHandler::SetBackgroundPlayerState(int state) { - if (background_player_if_ != NULL) { - SLuint32 state; - (*background_player_)->GetState(background_player_, &state); - if (state == SL_OBJECT_STATE_REALIZED) { - (*background_player_if_)->SetPlayState(background_player_if_, - state); - return 0; - } - } - return -1; -} - -int32_t AndroidSoundHandler::Pause() { - return SetBackgroundPlayerState(SL_PLAYSTATE_PAUSED); -} - - -int32_t AndroidSoundHandler::Resume() { - return SetBackgroundPlayerState(SL_PLAYSTATE_PLAYING); -} - -int32_t AndroidSoundHandler::CreateAudioPlayer(SLEngineItf engine_if, - const SLInterfaceID extra_if, - SLDataSource data_source, - SLDataSink data_sink, - SLObjectItf& player_out, - SLPlayItf& player_if_out) { - const SLuint32 SoundPlayerIIDCount = 2; - const SLInterfaceID SoundPlayerIIDs[] = { SL_IID_PLAY, extra_if }; - const SLboolean SoundPlayerReqs[] = { SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE }; - int32_t res = (*engine_if)->CreateAudioPlayer(engine_if, - &player_out, - &data_source, - &data_sink, - SoundPlayerIIDCount, - SoundPlayerIIDs, - SoundPlayerReqs); - - if (res == SL_RESULT_SUCCESS) { - res = (*player_out)->Realize(player_out, SL_BOOLEAN_FALSE); - if (res == SL_RESULT_SUCCESS) { - res = (*player_out)->GetInterface(sample_player_, - SL_IID_PLAY, - &player_if_out); - if (res == SL_RESULT_SUCCESS) { - return 0; - } - } - } - return -1; -} - -int32_t AndroidSoundHandler::PlayBackground(const char* path) { - LOGI("Creating audio player"); - - Resource resource(path); - int fd = resource.descriptor(); - if (fd < 0) { - LOGI("Could not open file %s", path); - return -1; - } - - SLDataLocator_AndroidFD data_locator_in = { - SL_DATALOCATOR_ANDROIDFD, - fd, - resource.start(), - resource.length() - }; - SLDataFormat_MIME data_format = { - SL_DATAFORMAT_MIME, - NULL, - SL_CONTAINERTYPE_UNSPECIFIED - }; - SLDataSource data_source = { &data_locator_in, &data_format }; - - resource.Close(); - - SLDataLocator_OutputMix data_locator_out = - { SL_DATALOCATOR_OUTPUTMIX, output_mix_ }; - SLDataSink data_sink = { &data_locator_out, NULL }; - - int32_t res = CreateAudioPlayer(engine_if_, - SL_IID_SEEK, - data_source, - data_sink, - background_player_, - background_player_if_); - - if (res != SL_RESULT_SUCCESS) { - LOGE("Couldn't create audio player"); - return -1; - } - - if ((*background_player_)-> - GetInterface(background_player_, SL_IID_SEEK, - &background_player_seek_if_) != SL_RESULT_SUCCESS) { - LOGE("Couldn't get seek interface"); - return -1; - } - LOGI("Got seek interface"); - if ((*background_player_seek_if_)-> - SetLoop(background_player_seek_if_, SL_BOOLEAN_TRUE, 0, - SL_TIME_UNKNOWN) != SL_RESULT_SUCCESS) { - LOGE("Couldn't set loop"); - return -1; - } - LOGI("Set loop"); - if ((*background_player_if_)-> - SetPlayState(background_player_if_, SL_PLAYSTATE_PLAYING) != - SL_RESULT_SUCCESS) { - LOGE("Couldn't start playing"); - return -1; - } - LOGI("Started playing"); - return 0; -} - -void AndroidSoundHandler::StopBackground() { - if (Pause() == 0) { - (*background_player_)->Destroy(background_player_); - background_player_ = NULL; - background_player_if_ = NULL; - background_player_seek_if_ = NULL; - } -} - -int32_t AndroidSoundHandler::StartSamplePlayer() { - SLDataLocator_AndroidSimpleBufferQueue data_locator_in = { - SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, - 1 - }; - - SLDataFormat_PCM data_format= { - SL_DATAFORMAT_PCM, - 1, - SL_SAMPLINGRATE_44_1, - SL_PCMSAMPLEFORMAT_FIXED_16, - SL_PCMSAMPLEFORMAT_FIXED_16, - SL_SPEAKER_FRONT_CENTER, - SL_BYTEORDER_LITTLEENDIAN - }; - - SLDataSource data_source = { &data_locator_in, &data_format }; - - SLDataLocator_OutputMix data_locator_out = - { SL_DATALOCATOR_OUTPUTMIX, output_mix_ }; - SLDataSink data_sink = { &data_locator_out, NULL }; - - int32_t res = CreateAudioPlayer(engine_if_, SL_IID_BUFFERQUEUE, - data_source, - data_sink, - sample_player_, sample_player_if_); - - if (res == SL_RESULT_SUCCESS) { - res = (*sample_player_)->GetInterface(sample_player_, - SL_IID_BUFFERQUEUE, - &sample_player_queue_); - if (res == SL_RESULT_SUCCESS) { - res = (*sample_player_if_)->SetPlayState(sample_player_if_, - SL_PLAYSTATE_PLAYING); - if (res == SL_RESULT_SUCCESS) { - return 0; - } - } - } - LOGE("Error while starting sample player"); - return -1; -} - -int32_t AndroidSoundHandler::PlaySample(const char* path) { - SLuint32 state; - (*sample_player_)->GetState(sample_player_, &state); - if (state != SL_OBJECT_STATE_REALIZED) { - LOGE("Sample player has not been realized"); - } else { - Sample* sample = GetSample(path); - if (sample != NULL) { - int16_t* buffer = reinterpret_cast<int16_t*>(sample->buffer()); - off_t len = sample->length(); - - // Remove any current sample. - int32_t res = (*sample_player_queue_)->Clear(sample_player_queue_); - if (res == SL_RESULT_SUCCESS) { - res = (*sample_player_queue_)->Enqueue(sample_player_queue_, - buffer, len); - if (res == SL_RESULT_SUCCESS) { - LOGE("Enqueued sample %s of length %d", path, - static_cast<int>(len)); - return 0; - } - LOGE("Enqueueing sample failed"); - } - } - } - return -1; -} - -
diff --git a/runtime/embedders/openglui/android/android_sound_handler.h b/runtime/embedders/openglui/android/android_sound_handler.h deleted file mode 100644 index e699a69..0000000 --- a/runtime/embedders/openglui/android/android_sound_handler.h +++ /dev/null
@@ -1,55 +0,0 @@ -// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#ifndef EMBEDDERS_OPENGLUI_ANDROID_ANDROID_SOUND_HANDLER_H_ -#define EMBEDDERS_OPENGLUI_ANDROID_ANDROID_SOUND_HANDLER_H_ - -#include <android_native_app_glue.h> -#include <SLES/OpenSLES.h> -#include <SLES/OpenSLES_Android.h> -#include <SLES/OpenSLES_AndroidConfiguration.h> -#include <vector> - -#include "embedders/openglui/common/sample.h" -#include "embedders/openglui/common/sound_handler.h" -#include "embedders/openglui/common/types.h" - -class AndroidSoundHandler : public SoundHandler { - public: - explicit AndroidSoundHandler(android_app* application); - int32_t Start(); - void Stop(); - int32_t Pause(); - int32_t Resume(); - - int32_t PlayBackground(const char* path); - void StopBackground(); - - int32_t PlaySample(const char* path); - - private: - int32_t CreateAudioPlayer(SLEngineItf engine_if, - const SLInterfaceID extra_if, - SLDataSource data_source, - SLDataSink data_sink, - SLObjectItf& player_out, - SLPlayItf& player_if_out); - - int32_t SetBackgroundPlayerState(int state); - int32_t StartSamplePlayer(); - - android_app* application_; - SLObjectItf engine_; - SLEngineItf engine_if_; - SLObjectItf output_mix_; - SLObjectItf background_player_; - SLPlayItf background_player_if_; - SLSeekItf background_player_seek_if_; - SLObjectItf sample_player_; - SLPlayItf sample_player_if_; - SLBufferQueueItf sample_player_queue_; -}; - -#endif // EMBEDDERS_OPENGLUI_ANDROID_ANDROID_SOUND_HANDLER_H_ -
diff --git a/runtime/embedders/openglui/android/eventloop.cc b/runtime/embedders/openglui/android/eventloop.cc deleted file mode 100644 index ed1645e..0000000 --- a/runtime/embedders/openglui/android/eventloop.cc +++ /dev/null
@@ -1,464 +0,0 @@ -// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#include "embedders/openglui/android/eventloop.h" - -#include <time.h> -#include "embedders/openglui/common/log.h" - -/* - * The Android lifecycle events are: - * - * OnCreate: In NDK this is the call to android_main - * - * OnStart: technically, called to initiate the “visible” lifespan of the - * app; at any time between OnStart and OnStop, the app may be visible. - * We can either be OnResume’d or OnStop’ped from this state. Note that - * there is also an event for OnRestart, which is called before OnStart - * if the application is transitioning from OnStop to OnStart instead of - * being started from scratch. - * - * OnResume: technically, the start of the “foreground” lifespan of the app, - * but this does not mean that the app is fully visible and should be - * rendering – more on that later - * - * OnPause: the app is losing its foregrounded state; this is normally an - * indication that something is fully covering the app. On versions of - * Android before Honeycomb, once we returned from this callback, we - * could be killed at any time with no further app code called. We can - * either be OnResume’d or OnStop’ped from this state. OnPause halts the - * visible UI thread and so should be handled as quickly as possible. - * - * OnStop: the end of the current visible lifespan of the app – we may - * transition to On(Re)Start to become visible again, or to OnDestroy if - * we are shutting down entirely. Once we return from this callback, we - * can be killed at any time with no further app code called on any - * version of Android. - * - * OnDestroy: this can only be followed by the application being killed or - * restarted with OnCreate. - * - * The above events occur in fixed orders. The events below can occur at - * various times: - * - * OnGainedFocus: happens between OnResume and OnPause. - * OnLostFocus: may occur at arbitrary times, and may in fact not happen - * at all if the app is being destroyed. So OnPause and OnGainedFocus/ - * OnLostFocus must be used together to determine the visible and - * interactable state of the app. - * - * OnCreateWindow: usually happens in the resumed state - * OnDestroyWindow: can happen after OnPause or OnDestroy, so apps may - * need to handle shutting down EGL before their surfaces are - * destroyed. - * OnConfigurationChanged: typically means the size has changed - * - * An application's EGL surface may only exist between the OnCreateWindow - * and OnDestroyWindow callbacks. - * - * An application is "killable" after OnStop or OnDestroy (in earlier - * Android versions, after OnPause too). That means any critical state - * or resources must be handled by any of these callbacks. - * - * These callbacks run on the main thread. If they block any event - * processing for more than 5 seconds this will result in an ANR - * (Application Not Responding message). - * - * On application launch, this sequence will occur: - * - * - OnCreate - * - OnStart - * - OnResume - * - OnCreateWindow - * - OnConfigurationChanged - * - OnGainedFocus - * - * If the back button is pressed, and the app does not handle it, - * Android will pop the app of the UI stack and destroy the application's - * activity: - * - * - OnPause - * - OnLostFocus - * - OnDestroyWindow - * - OnStop - * - OnDestroy - * - * If the home button is pressed, the app is sent down in the UI stack. - * The app's Activity still exists but may be killed at any time, and - * it loses its rendering surface: - * - * - OnPause - * - OnLostFocus - * - OnDestroyWindow - * - OnStop - * - * If the app is then restarted (without having been killed in between): - * - * - OnRestart - * - OnStart - * - OnResume - * - OnCreateWindow - * - OnConfigurationChanged - * - OnGainedFocus - * - * If a status icon pop up is opened, the app is still visible and can render - * but is not focused and cannot receive input: - * - * - OnLostFocus - * - * When the popup is dismissed, the app regains focus: - * - * - OnGainedFocus - * - * When the device is suspended (power button or screen saver), the application - * will typically be paused and lose focus: - * - * - OnPause - * - OnLostFocus (sometimes this will only come when the device is resumed - * to the lock screen) - * - * The application should have stopped all rendering and sound and any - * non-critical background processing. - * - * When the device is resumed but not yet unlocked, the app will be resumed: - * - * - OnResume - * - * The application should not perform sound or graphics yet. If the lock - * screen times out, the app will be paused again. If the screen is - * unlocked, the app will regain focus. - * - * Turning all of this into a general framework, we can use the following: - * - * 1. In OnCreate/android_main, set up the main classes and possibly - * load some lightweight resources. - * 2. In OnCreateWindow, create the EGLSurface, bind the context, load - * OpenGL resources. No rendering. - * 3. When we are between OnResume and OnPause, and between OnCreateWindow - * and OnDestroyWindow, and between OnGainedFocus and OnLostFocus, - * we can render and process input. - * 4. In OnLostFocus, stop sounds from playing, and stop rendering. - * 5. In OnPause, stop all rendering - * 6. In OnResume, prepare to start rendering again, but don't render. - * 7. In OnGainedFocus after OnResume, start rendering and sound again. - * 8. In OnStop, free all graphic resources, either through GLES calls - * if the EGLContext is still bound, or via eglDestroyContext if the - * context has been unbound because the rendering surface was destroyed. - * 9. In OnDestroy, release all other resources. - */ -EventLoop::EventLoop(android_app* application) - : enabled_(false), - quit_(false), - isResumed_(false), - hasSurface_(false), - hasFocus_(false), - application_(application), - lifecycle_handler_(NULL), - input_handler_(NULL), - sensor_manager_(NULL), - sensor_event_queue_(NULL), - sensor_poll_source_() { - application_->onAppCmd = ActivityCallback; - application_->onInputEvent = InputCallback; - application_->userData = this; -} - -static int64_t getTimeInMillis() { - struct timespec res; - clock_gettime(CLOCK_REALTIME, &res); - return 1000 * res.tv_sec + res.tv_nsec / 1000000; -} - -void EventLoop::Run(LifeCycleHandler* lifecycle_handler, - InputHandler* input_handler) { - int32_t result; - int32_t events; - android_poll_source* source; - - lifecycle_handler_ = lifecycle_handler; - input_handler_ = input_handler; - int64_t last_frame_time = getTimeInMillis(); - if (lifecycle_handler_->OnStart() == 0) { - LOGI("Starting event loop"); - while (!quit_) { - // If not enabled, block indefinitely on events. If enabled, block - // briefly so we can do useful work in onStep, but only long - // enough that we can still do work at 60fps if possible. - int64_t next_frame_time = last_frame_time + (1000/60); - int64_t next_frame_delay = next_frame_time - getTimeInMillis(); - if (next_frame_delay < 0) next_frame_delay = 0; - while ((result = ALooper_pollAll(enabled_ ? next_frame_delay : -1, NULL, - &events, reinterpret_cast<void**>(&source))) >= 0) { - if (source != NULL) { - source->process(application_, source); - } - if (application_->destroyRequested) { - return; - } - } - if (enabled_ && !quit_) { - int64_t now = getTimeInMillis(); - if (now >= next_frame_time) { - LOGI("step"); - last_frame_time = now; - if (lifecycle_handler_->OnStep() != 0) { - quit_ = true; - } - } - } - } - } - ANativeActivity_finish(application_->activity); -} - -void EventLoop::EnableSensorEvents() { - sensor_poll_source_.id = LOOPER_ID_USER; - sensor_poll_source_.app = application_; - sensor_poll_source_.process = SensorCallback; - sensor_manager_ = ASensorManager_getInstance(); - if (sensor_manager_ != NULL) { - sensor_event_queue_ = ASensorManager_createEventQueue( - sensor_manager_, application_->looper, - LOOPER_ID_USER, NULL, &sensor_poll_source_); - - sensor_ = ASensorManager_getDefaultSensor(sensor_manager_, - ASENSOR_TYPE_ACCELEROMETER); - if (sensor_ != NULL) { - int32_t min_delay = ASensor_getMinDelay(sensor_); - if (ASensorEventQueue_enableSensor(sensor_event_queue_, sensor_) < 0 || - ASensorEventQueue_setEventRate(sensor_event_queue_, sensor_, - min_delay) < 0) { - LOGE("Error while activating sensor."); - DisableSensorEvents(); - return; - } - LOGI("Activating sensor:"); - LOGI("Name : %s", ASensor_getName(sensor_)); - LOGI("Vendor : %s", ASensor_getVendor(sensor_)); - LOGI("Resolution : %f", ASensor_getResolution(sensor_)); - LOGI("Min Delay : %d", min_delay); - } else { - LOGI("No sensor"); - } - } -} - -void EventLoop::DisableSensorEvents() { - if (sensor_ != NULL) { - if (ASensorEventQueue_disableSensor(sensor_event_queue_, sensor_) < 0) { - LOGE("Error while deactivating sensor."); - } - sensor_ = NULL; - } - if (sensor_event_queue_ != NULL) { - ASensorManager_destroyEventQueue(sensor_manager_, - sensor_event_queue_); - sensor_event_queue_ = NULL; - } - sensor_manager_ = NULL; -} - -void EventLoop::ProcessActivityEvent(int32_t command) { - switch (command) { - case APP_CMD_INIT_WINDOW: - if (lifecycle_handler_->Activate() != 0) { - quit_ = true; - } else { - hasSurface_ = true; - } - break; - case APP_CMD_CONFIG_CHANGED: - lifecycle_handler_->OnConfigurationChanged(); - break; - case APP_CMD_DESTROY: - hasFocus_ = false; - lifecycle_handler_->FreeAllResources(); - break; - case APP_CMD_GAINED_FOCUS: - hasFocus_ = true; - if (hasSurface_ && isResumed_ && hasFocus_) { - enabled_ = (lifecycle_handler_->Resume() == 0); - if (enabled_) { - EnableSensorEvents(); - } - } - break; - case APP_CMD_LOST_FOCUS: - hasFocus_ = false; - enabled_ = false; - DisableSensorEvents(); - lifecycle_handler_->Pause(); - break; - case APP_CMD_LOW_MEMORY: - lifecycle_handler_->OnLowMemory(); - break; - case APP_CMD_PAUSE: - isResumed_ = false; - enabled_ = false; - DisableSensorEvents(); - lifecycle_handler_->Pause(); - break; - case APP_CMD_RESUME: - isResumed_ = true; - break; - case APP_CMD_SAVE_STATE: - lifecycle_handler_->OnSaveState(&application_->savedState, - &application_->savedStateSize); - break; - case APP_CMD_START: - break; - case APP_CMD_STOP: - hasFocus_ = false; - lifecycle_handler_->Deactivate(); - break; - case APP_CMD_TERM_WINDOW: - hasFocus_ = false; - hasSurface_ = false; - enabled_ = false; - DisableSensorEvents(); - lifecycle_handler_->Pause(); - break; - default: - break; - } -} - -void EventLoop::ProcessSensorEvent() { - ASensorEvent event; - while (ASensorEventQueue_getEvents(sensor_event_queue_, &event, 1) > 0) { - switch (event.type) { - case ASENSOR_TYPE_ACCELEROMETER: - input_handler_->OnAccelerometerEvent(event.vector.x, - event.vector.y, event.vector.z); - break; - } - } -} - -bool EventLoop::OnTouchEvent(AInputEvent* event) { - int32_t type = AMotionEvent_getAction(event); - MotionEvent motion_event; - switch (type) { - case AMOTION_EVENT_ACTION_DOWN: - motion_event = kMotionDown; - break; - case AMOTION_EVENT_ACTION_UP: - motion_event = kMotionUp; - break; - case AMOTION_EVENT_ACTION_MOVE: - motion_event = kMotionMove; - break; - case AMOTION_EVENT_ACTION_CANCEL: - motion_event = kMotionCancel; - break; - case AMOTION_EVENT_ACTION_OUTSIDE: - motion_event = kMotionOutside; - break; - case AMOTION_EVENT_ACTION_POINTER_DOWN: - motion_event = kMotionPointerDown; - break; - case AMOTION_EVENT_ACTION_POINTER_UP: - motion_event = kMotionPointerUp; - break; - default: - return false; - } - // For now we just get the last coords. - float move_x = AMotionEvent_getX(event, 0); - float move_y = AMotionEvent_getY(event, 0); - int64_t when = AMotionEvent_getEventTime(event); - LOGI("Got motion event %d at %f, %f", type, move_x, move_y); - - if (input_handler_->OnMotionEvent(motion_event, when, move_x, move_y) != 0) { - return false; - } - return true; -} - -bool EventLoop::OnKeyEvent(AInputEvent* event) { - int32_t type = AKeyEvent_getAction(event); - KeyEvent key_event; - switch (type) { - case AKEY_EVENT_ACTION_DOWN: - key_event = kKeyDown; - break; - case AKEY_EVENT_ACTION_UP: - key_event = kKeyUp; - break; - case AKEY_EVENT_ACTION_MULTIPLE: - key_event = kKeyMultiple; - break; - default: - return false; - } - /* Get the key code of the key event. - * This is the physical key that was pressed, not the Unicode character. */ - int32_t key_code = AKeyEvent_getKeyCode(event); - /* Get the meta key state. */ - int32_t meta_state = AKeyEvent_getMetaState(event); - /* Get the repeat count of the event. - * For both key up an key down events, this is the number of times the key - * has repeated with the first down starting at 0 and counting up from - * there. For multiple key events, this is the number of down/up pairs - * that have occurred. */ - int32_t repeat = AKeyEvent_getRepeatCount(event); - - /* Get the time of the most recent key down event, in the - * java.lang.System.nanoTime() time base. If this is a down event, - * this will be the same as eventTime. - * Note that when chording keys, this value is the down time of the most - * recently pressed key, which may not be the same physical key of this - * event. */ - // TODO(gram): Use or remove this. - // int64_t key_down_time = AKeyEvent_getDownTime(event); - - /* Get the time this event occurred, in the - * java.lang.System.nanoTime() time base. */ - int64_t when = AKeyEvent_getEventTime(event); - bool isAltKeyDown = (meta_state & AMETA_ALT_ON) != 0; - bool isShiftKeyDown = (meta_state & AMETA_SHIFT_ON) != 0; - bool isCtrlKeyDown = key_code < 32; - - LOGI("Got key event %d %d", type, key_code); - - if (input_handler_->OnKeyEvent(key_event, when, key_code, - isAltKeyDown, isCtrlKeyDown, isShiftKeyDown, - repeat) != 0) { - return false; - } - return true; -} - -int32_t EventLoop::ProcessInputEvent(AInputEvent* event) { - int32_t event_type = AInputEvent_getType(event); - LOGI("Got input event type %d", event_type); - switch (event_type) { - case AINPUT_EVENT_TYPE_MOTION: - if (AInputEvent_getSource(event) == AINPUT_SOURCE_TOUCHSCREEN) { - return OnTouchEvent(event); - } - break; - case AINPUT_EVENT_TYPE_KEY: - return OnKeyEvent(event); - } - return 0; -} - -void EventLoop::ActivityCallback(android_app* application, int32_t command) { - EventLoop* event_loop = reinterpret_cast<EventLoop*>(application->userData); - event_loop->ProcessActivityEvent(command); -} - -int32_t EventLoop::InputCallback(android_app* application, - AInputEvent* event) { - EventLoop* event_loop = reinterpret_cast<EventLoop*>(application->userData); - return event_loop->ProcessInputEvent(event); -} - -void EventLoop::SensorCallback(android_app* application, - android_poll_source* source) { - EventLoop* event_loop = reinterpret_cast<EventLoop*>(application->userData); - event_loop->ProcessSensorEvent(); -} -
diff --git a/runtime/embedders/openglui/android/eventloop.h b/runtime/embedders/openglui/android/eventloop.h deleted file mode 100644 index 031bf69..0000000 --- a/runtime/embedders/openglui/android/eventloop.h +++ /dev/null
@@ -1,51 +0,0 @@ -// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#ifndef EMBEDDERS_OPENGLUI_ANDROID_EVENTLOOP_H_ -#define EMBEDDERS_OPENGLUI_ANDROID_EVENTLOOP_H_ - -#include <android_native_app_glue.h> -#include <android/sensor.h> -#include "embedders/openglui/common/events.h" -#include "embedders/openglui/common/input_handler.h" -#include "embedders/openglui/common/lifecycle_handler.h" - -class EventLoop { - public: - explicit EventLoop(android_app* application); - void Run(LifeCycleHandler* activity_handler, - InputHandler* input_handler); - - protected: - void EnableSensorEvents(); - void DisableSensorEvents(); - - void ProcessActivityEvent(int32_t command); - int32_t ProcessInputEvent(AInputEvent* event); - void ProcessSensorEvent(); - - bool OnTouchEvent(AInputEvent* event); - bool OnKeyEvent(AInputEvent* event); - - static void ActivityCallback(android_app* application, int32_t command); - static int32_t InputCallback(android_app* application, AInputEvent* event); - static void SensorCallback(android_app* application, - android_poll_source* source); - - private: - friend class Sensor; - - bool enabled_, quit_; - bool isResumed_, hasSurface_, hasFocus_; - android_app* application_; - LifeCycleHandler* lifecycle_handler_; - InputHandler* input_handler_; - const ASensor* sensor_; - ASensorManager* sensor_manager_; - ASensorEventQueue* sensor_event_queue_; - android_poll_source sensor_poll_source_; -}; - -#endif // EMBEDDERS_OPENGLUI_ANDROID_EVENTLOOP_H_ -
diff --git a/runtime/embedders/openglui/android/main.cc b/runtime/embedders/openglui/android/main.cc deleted file mode 100644 index c0c386b..0000000 --- a/runtime/embedders/openglui/android/main.cc +++ /dev/null
@@ -1,39 +0,0 @@ -// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#include "embedders/openglui/android/android_graphics_handler.h" -#include "embedders/openglui/android/android_input_handler.h" -#include "embedders/openglui/android/android_resource.h" -#include "embedders/openglui/android/android_sound_handler.h" -#include "embedders/openglui/android/eventloop.h" -#include "embedders/openglui/common/context.h" -#include "embedders/openglui/common/dart_host.h" -#include "embedders/openglui/common/vm_glue.h" - -android_app* application_ = NULL; - -Resource* MakePlatformResource(const char *path) { - return new AndroidResource(application_, path); -} - -void android_main(android_app* application) { - application_ = application; - app_dummy(); // Link in native_app_glue. - const char* resource_path = "/data/data/com.google.dartndk/app_dart"; - EventLoop eventLoop(application); - AndroidGraphicsHandler graphics_handler(application, resource_path); - VMGlue vm_glue(&graphics_handler, resource_path); - AndroidInputHandler input_handler(&vm_glue, &graphics_handler); - AndroidSoundHandler sound_handler(application); - Timer timer; - Context app_context; - app_context.graphics_handler = &graphics_handler; - app_context.input_handler = &input_handler; - app_context.sound_handler = &sound_handler; - app_context.timer = &timer; - app_context.vm_glue = &vm_glue; - DartHost host(&app_context); - eventLoop.Run(&host, &input_handler); -} -
diff --git a/runtime/embedders/openglui/android/support_android.cc b/runtime/embedders/openglui/android/support_android.cc deleted file mode 100644 index 6755f154..0000000 --- a/runtime/embedders/openglui/android/support_android.cc +++ /dev/null
@@ -1,15 +0,0 @@ -// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -// Provide atexit, not part of Android libc or linker. - -extern "C" int atexit(void (*function)(void)) { - // Return error code. - return 1; -} - -// Provide __dso_handle, not part of Android libc or linker. - -__attribute__((weak)) void *__dso_handle; -
diff --git a/runtime/embedders/openglui/build_skia.sh b/runtime/embedders/openglui/build_skia.sh deleted file mode 100755 index 42710a8..0000000 --- a/runtime/embedders/openglui/build_skia.sh +++ /dev/null
@@ -1,112 +0,0 @@ -#!/bin/bash - -function usage { - echo "usage: $0 [ --help ] [ --android ] [ --arm | --x86] [ --debug ] [--clean] [<Dart directory>]" - echo - echo "Sync up Skia and build" - echo - echo " --android: Build for Android" - echo " --x86 : Build for Intel" - echo " --arm : Cross-compile for ARM (implies --android)" - echo " --debug : Build a debug version" - echo -} - -DO_ANDROID=0 -TARGET_ARCH=x86 -CLEAN=0 -BUILD=Release -DART_DIR=../../.. - -while [ ! -z "$1" ] ; do - case $1 in - "-h"|"-?"|"-help"|"--help") - usage - exit 1 - ;; - "--android") - DO_ANDROID=1 - ;; - "--arm") - TARGET_ARCH=arm - DO_ANDROID=1 - ;; - "--x86") - TARGET_ARCH=x86 - ;; - "--clean") - CLEAN=1 - ;; - "--debug") - BUILD=Debug - ;; - "--release") - BUILD=Release - ;; - *) - if [ ! -d "$1" ] - then - echo "Unrecognized argument: $1" - usage - exit 1 - fi - DART_DIR="$1" - ;; - esac - shift -done - -mkdir -p "${DART_DIR}/third_party/skia" -pushd "${DART_DIR}/third_party/skia" - -if [ ${DO_ANDROID} != 0 ] ; then - echo "Building for Android ${TARGET_ARCH}" - curl http://skia.googlecode.com/svn/trunk/platform_tools/android/gclient.config -o .gclient - gclient sync - - export ANDROID_SDK_ROOT=`readlink -f ../android_tools/sdk` - export GSUTIL_LOCATION=`readlink -f ../gsutil` - - cd trunk - - echo "Using SDK ${ANDROID_SDK_ROOT}" - if [ ${CLEAN} != 0 ] ; then - ./platform_tools/android/bin/android_make -d $TARGET_ARCH -j clean - else - echo env -i BUILDTYPE=$BUILD ANDROID_SDK_ROOT="${ANDROID_SDK_ROOT}" PATH="${PATH}:${GSUTIL_LOCATION}" ../android/bin/android_make BUILDTYPE=$BUILD -d $TARGET_ARCH -j --debug=j - env -i BUILDTYPE=$BUILD ANDROID_SDK_ROOT="${ANDROID_SDK_ROOT}" PATH="${PATH}:${GSUTIL_LOCATION}" ./platform_tools/android/bin/android_make BUILDTYPE=$BUILD -d $TARGET_ARCH -j --debug=j - fi - -else - - echo "Building for desktop in `pwd`" - # Desktop build. Requires svn client and Python. - - # Note that on Linux these packages should be installed first: - # - # libfreetype6 - # libfreetype6-dev - # libpng12-0, libpng12-dev - # libglu1-mesa-dev - # mesa-common-dev - # freeglut3-dev - - SKIA_INSTALLDIR=`pwd` - svn checkout http://skia.googlecode.com/svn/trunk - cd trunk - if [ ${CLEAN} != 0 ] ; then - echo 'Cleaning' - make clean - else - # Dart sets BUILDTYPE to DebugX64 which breaks Skia build. - make BUILDTYPE=$BUILD - fi - cd .. - -fi - -popd -# TODO(gram) We should really propogate the make exit code here. -exit 0 - -
diff --git a/runtime/embedders/openglui/common/canvas_context.cc b/runtime/embedders/openglui/common/canvas_context.cc deleted file mode 100644 index 24c0f7df..0000000 --- a/runtime/embedders/openglui/common/canvas_context.cc +++ /dev/null
@@ -1,107 +0,0 @@ -// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#include "embedders/openglui/common/canvas_context.h" - -#include <ctype.h> -#include <string.h> -#include "core/SkStream.h" -#include "embedders/openglui/common/image_cache.h" -#include "embedders/openglui/common/support.h" - -// TODO(gram): this should be dynamic. -#define MAX_CONTEXTS 256 -CanvasContext* contexts[MAX_CONTEXTS] = { 0 }; - -CanvasContext* Context2D(int handle) { - if (handle < 0 || handle >= MAX_CONTEXTS) { - LOGE("Request for out-of-range handle %d", handle); - return NULL; - } - if (contexts[handle] == NULL) { - LOGE("Warning: request for context with handle %d returns NULL", handle); - } - return contexts[handle]; -} - -void FreeContexts() { - extern CanvasContext* display_context; - for (int i = 0; i < MAX_CONTEXTS; i++) { - delete contexts[i]; - contexts[i] = NULL; - } - display_context = NULL; -} - - -CanvasContext::CanvasContext(int handle, int16_t widthp, int16_t heightp) - : canvas_(NULL), - width_(widthp), - height_(heightp), - imageSmoothingEnabled_(true), - state_(NULL) { - if (handle >= MAX_CONTEXTS) { - LOGE("Max contexts exceeded"); - exit(-1); - } - if (handle == 0) { - canvas_ = graphics->CreateDisplayCanvas(); - } else { - canvas_ = graphics->CreateBitmapCanvas(widthp, heightp); - } - state_ = new CanvasState(canvas_); - contexts[handle] = this; - LOGI("Created context with handle %d", handle); -} - -CanvasContext::~CanvasContext() { - delete state_; - delete canvas_; -} - -void CanvasContext::Save() { - state_ = state_->Save(); -} - -void CanvasContext::Restore() { - CanvasState* popped_state = state_; - state_ = state_->Restore(); - if (state_ == NULL) { - LOGE("Popping last state!"); - state_ = popped_state; - } - if (state_ != popped_state) { - // Only delete if the pop was successful. - delete popped_state; - } -} - -void CanvasContext::DrawImage(const char* src_url, - int sx, int sy, - bool has_src_dimensions, int sw, int sh, - int dx, int dy, - bool has_dst_dimensions, int dw, int dh) { - const SkBitmap* bm = ImageCache::GetImage(src_url); - if (bm == NULL) return; - if (!has_src_dimensions) { - sw = bm->width(); - sh = bm->height(); - } - if (!has_dst_dimensions) { - dw = bm->width(); - dh = bm->height(); - } - state_->DrawImage(*bm, sx, sy, sw, sh, dx, dy, dw, dh); - isDirty_ = true; -} - -void CanvasContext::ClearRect(float left, float top, - float width, float height) { - SkPaint paint; - paint.setStyle(SkPaint::kFill_Style); - paint.setColor(0xFFFFFFFF); - canvas_->drawRectCoords(left, top, left + width, top + height, paint); - isDirty_ = true; -} -
diff --git a/runtime/embedders/openglui/common/canvas_context.h b/runtime/embedders/openglui/common/canvas_context.h deleted file mode 100644 index a45b574..0000000 --- a/runtime/embedders/openglui/common/canvas_context.h +++ /dev/null
@@ -1,324 +0,0 @@ -// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#ifndef EMBEDDERS_OPENGLUI_COMMON_CANVAS_CONTEXT_H_ -#define EMBEDDERS_OPENGLUI_COMMON_CANVAS_CONTEXT_H_ - -#include "embedders/openglui/common/canvas_state.h" -#include "embedders/openglui/common/graphics_handler.h" -#include "embedders/openglui/common/log.h" -#include "embedders/openglui/common/opengl.h" -#include "embedders/openglui/common/support.h" - -typedef struct ImageData { - int width; - int height; - GLubyte* pixels; - - ImageData(int wp, int hp, GLubyte* pp) - : width(wp), height(hp), pixels(pp) { - } - ImageData() - : width(0), height(0), pixels(NULL) { - } -} ImageData; - -class CanvasContext { - protected: - SkCanvas* canvas_; - int16_t width_, height_; - bool imageSmoothingEnabled_; - bool isDirty_; - CanvasState* state_; - - static inline float Radians2Degrees(float angle) { - return 180.0 * angle / M_PI; - } - - inline void NotImplemented(const char* method) { - LOGE("Method CanvasContext::%s is not yet implemented", method); - } - - public: - CanvasContext(int handle, int16_t width, int16_t height); - virtual ~CanvasContext(); - - inline bool isDirty() { - return isDirty_; - } - - inline void clearDirty() { - isDirty_ = false; - } - - inline void setGlobalAlpha(float alpha) { - state_->setGlobalAlpha(alpha); - } - - inline void setFillColor(const char* color) { - state_->setFillColor(color); - } - - inline void setStrokeColor(const char* color) { - state_->setStrokeColor(color); - } - - inline void setShadowBlur(float blur) { - state_->setShadowBlur(blur); - } - - inline void setShadowColor(const char* color) { - state_->setShadowColor(color); - } - - inline void setShadowOffsetX(float offset) { - state_->setShadowOffsetX(offset); - } - - inline void setShadowOffsetY(float offset) { - state_->setShadowOffsetY(offset); - } - - // For now, we don't allow resizing. - // TODO(gram): fix this or remove these. - inline int setWidth(int widthp) { - return width_; - } - - inline int setHeight(int heightp) { - return height_; - } - - inline bool imageSmoothingEnabled() { - return imageSmoothingEnabled_; - } - - inline void setImageSmoothingEnabled(bool enabled) { - // TODO(gram): We're not actually doing anything with this yet. - imageSmoothingEnabled_ = enabled; - } - - inline void setGlobalCompositeOperation(const char* op) { - state_->setGlobalCompositeOperation(op); - } - - void Save(); - void Restore(); - - inline void Rotate(float angle) { - canvas_->rotate(Radians2Degrees(angle)); - } - - inline void Translate(float x, float y) { - canvas_->translate(x, y); - } - - inline void Scale(float x, float y) { - canvas_->scale(x, y); - } - - inline void Transform(float a, float b, - float c, float d, - float e, float f) { - SkMatrix t; - // Our params are for a 3 x 2 matrix in column order: - // - // a c e - // b d f - // - // We need to turn this into a 3x3 matrix: - // - // a c e - // b d f - // 0 0 1 - // - // and pass the params in row order: - t.setAll(a, c, e, b, d, f, 0, 0, 1); - canvas_->concat(t); - } - - inline void setTransform(float a, float b, - float c, float d, - float e, float f) { - SkMatrix t; - t.setAll(a, c, e, b, d, f, 0, 0, 1); - canvas_->setMatrix(t); - } - - ImageData* GetImageData(float sx, float sy, float sw, float sh) { - NotImplemented("GetImageData"); - return NULL; - } - - void PutImageData(ImageData* imageData, float dx, float dy) { - NotImplemented("PutImageData"); - } - - void DrawImage(const char* src_url, - int sx, int sy, bool has_src_dimensions, int sw, int sh, - int dx, int dy, bool has_dst_dimensions, int dw, int dh); - - inline void Clear() { - canvas_->drawColor(0xFFFFFFFF); - isDirty_ = true; - } - - void ClearRect(float left, float top, float width, float height); - - inline void FillRect(float left, float top, float width, float height) { - // Does not affect the path. - state_->FillRect(left, top, width, height); - isDirty_ = true; - } - - inline void StrokeRect(float left, float top, float width, float height) { - // Does not affect the path. - state_->StrokeRect(left, top, width, height); - isDirty_ = true; - } - - inline void BeginPath() { - state_->BeginPath(); - } - - inline void Fill() { - state_->Fill(); - isDirty_ = true; - } - - inline void Stroke() { - state_->Stroke(); - isDirty_ = true; - } - - inline void ClosePath() { - state_->ClosePath(); - } - - inline void MoveTo(float x, float y) { - state_->MoveTo(x, y); - } - - inline void LineTo(float x, float y) { - state_->LineTo(x, y); - } - - inline void QuadraticCurveTo(float cpx, float cpy, float x, float y) { - state_->QuadraticCurveTo(cpx, cpy, x, y); - } - - inline void BezierCurveTo(float cp1x, float cp1y, float cp2x, float cp2y, - float x, float y) { - state_->BezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y); - } - - inline void ArcTo(float x1, float y1, float x2, float y2, float radius) { - state_->ArcTo(x1, y1, x2, y2, radius); - } - - inline void Rect(float x, float y, float w, float h) { - state_->Rect(x, y, w, h); - } - - inline void Arc(float x, float y, float radius, - float startAngle, float endAngle, - bool antiClockwise) { - state_->Arc(x, y, radius, startAngle, endAngle, antiClockwise); - } - - inline void setLineWidth(double w) { - state_->setLineWidth(w); - } - - inline void setLineCap(const char* lc) { - state_->setLineCap(lc); - } - - inline void setLineDash(float* dashes, int len) { - state_->setLineDash(dashes, len); - } - - inline void setLineDashOffset(float offset) { - state_->setLineDashOffset(offset); - } - - inline void setLineJoin(const char* lj) { - state_->setLineJoin(lj); - } - - inline void setMiterLimit(float limit) { - state_->setMiterLimit(limit); - } - - inline const char* setFont(const char* font) { - return state_->setFont(font); - } - - inline const char* setTextAlign(const char* align) { - return state_->setTextAlign(align); - } - - const char* setTextBaseline(const char* baseline) { - return state_->setTextBaseline(baseline); - } - - inline const char* setDirection(const char* direction) { - return state_->setTextDirection(direction); - } - - inline void FillText(const char* text, float x, float y, - float maxWidth = -1) { - state_->FillText(text, x, y, maxWidth); - isDirty_ = true; - } - - inline void StrokeText(const char* text, float x, float y, - float maxWidth = -1) { - state_->StrokeText(text, x, y, maxWidth); - isDirty_ = true; - } - - inline float MeasureText(const char *text) { - return state_->MeasureText(text); - } - - inline void Clip() { - state_->Clip(); - } - - inline void ResetClip() { - // TODO(gram): Check this. Is it affected by the transform? - canvas_->clipRect(SkRect::MakeLTRB(0, 0, width_, height_), - SkRegion::kReplace_Op); - } - - virtual void Flush() { - canvas_->flush(); - } - - inline void SetFillGradient(bool is_radial, double x0, double y0, double r0, - double x1, double y1, double r1, - int stops, float* positions, char** colors) { - state_->SetFillGradient(is_radial, x0, y0, r0, x1, y1, r1, - stops, positions, colors); - } - - inline void SetStrokeGradient(bool is_radial, double x0, double y0, double r0, - double x1, double y1, double r1, - int stops, float* positions, char** colors) { - state_->SetStrokeGradient(is_radial, x0, y0, r0, x1, y1, r1, - stops, positions, colors); - } - - inline const SkBitmap* GetBitmap() { - SkDevice* device = canvas_->getDevice(); - return &device->accessBitmap(false); - } -}; - -CanvasContext* Context2D(int handle); -void FreeContexts(); - -#endif // EMBEDDERS_OPENGLUI_COMMON_CANVAS_CONTEXT_H_ -
diff --git a/runtime/embedders/openglui/common/canvas_state.cc b/runtime/embedders/openglui/common/canvas_state.cc deleted file mode 100644 index 8d927c8..0000000 --- a/runtime/embedders/openglui/common/canvas_state.cc +++ /dev/null
@@ -1,411 +0,0 @@ -// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#include "embedders/openglui/common/canvas_state.h" - -#include <ctype.h> -#include <string.h> - -#include "embedders/openglui/common/support.h" - -// Float parser. Does not handle exponents. This is -// used to parse font sizes so it doesn't need to be full-blown. -float ParseFloat(const char* s, int& pos) { - int len = strlen(s); - float rtn = 0.0; - while (pos < len && s[pos] != '.' && !isdigit(s[pos])) { - ++pos; - } - while (pos < len && isdigit(s[pos])) { - rtn = rtn * 10.0 + s[pos] - '0'; - ++pos; - } - if (pos < len && s[pos] == '.') { - pos++; - float div = 1.0; - while (pos < len && isdigit(s[pos])) { - rtn = rtn * 10.0 + s[pos] - '0'; - ++pos; - div *= 10.0; - } - rtn /= div; - } - return rtn; -} - -int ParseInt(const char* s, int& pos) { - int len = strlen(s); - int rtn = 0; - while (pos < len && !isdigit(s[pos])) { - ++pos; - } - while (pos < len && isdigit(s[pos])) { - rtn = rtn * 10 + s[pos] - '0'; - ++pos; - } - return rtn; -} - -CanvasState* CanvasState::Restore() { - if (next_ != NULL) { - // If the state we are popping has a non-empty path, - // apply the state's transform to the path, then - // add the path to the previous state's path. - if (path_->countPoints() > 0) { - path_->transform(canvas_->getTotalMatrix()); - next_->path_->addPath(*path_); - } - canvas_->restore(); - return next_; - } - canvas_->restore(); - return next_; // TODO(gram): Should we assert/throw? -} - -void CanvasState::setLineCap(const char* lc) { - if (strcmp(lc, "round") == 0) { - paint_.setStrokeCap(SkPaint::kRound_Cap); - } else if (strcmp(lc, "square") == 0) { - paint_.setStrokeCap(SkPaint::kSquare_Cap); - } else { - paint_.setStrokeCap(SkPaint::kButt_Cap); - } -} - -void CanvasState::setLineJoin(const char* lj) { - if (strcmp(lj, "round") == 0) { - paint_.setStrokeJoin(SkPaint::kRound_Join); - } else if (strcmp(lj, "bevel") == 0) { - paint_.setStrokeJoin(SkPaint::kBevel_Join); - } else { - paint_.setStrokeJoin(SkPaint::kMiter_Join); - } -} - -const char* CanvasState::setFont(const char*name, float size) { - // Font names have the form "<modifier> <size> <family>". - // Modifiers are "normal", "italic", "bold". - // Sizes have magnitude and units; e.g. "10pt", "20px". - const char* rtn = name; - if (size < 0) { - int pos = 0; - // TODO(gram): need to handle these modifiers. - if (strncmp(name, "normal", 6) == 0) { - pos = 6; - } else if (strncmp(name, "italic", 6) == 0) { - pos = 6; - } else if (strncmp(name, "bold", 4) == 0) { - pos = 4; - } - size = ParseFloat(name, pos); - // Font size units: px, etc. For now just px. - // TODO(gram): Handle other units. - if (strncmp(name + pos, "px", 2) == 0) { - pos += 2; - } - int len = strlen(name); - while (pos < len && isspace(name[pos])) { - ++pos; - } - name = name + pos; - } - SkTypeface *pTypeface = SkTypeface::CreateFromName(name, SkTypeface::kNormal); - paint_.setTypeface(pTypeface); - paint_.setTextSize(size); - // TODO(gram): Must return a normalized font name incorporating size, so - // callers can set the Dart canvas font name to an appropriate value. - // Actually this may not be necessary in which case we can change this - // method to return void. - return rtn; -} - -const char* CanvasState::setTextAlign(const char* align) { - // TODO(gram): What about "start" and "end"? - // I don't see any an analogs in Skia. - if (strcmp(align, "left") == 0) { - paint_.setTextAlign(SkPaint::kLeft_Align); - } else if (strcmp(align, "right") == 0) { - paint_.setTextAlign(SkPaint::kRight_Align); - } else { - paint_.setTextAlign(SkPaint::kCenter_Align); - } - return align; -} - -const char* CanvasState::setTextBaseline(const char* baseline) { - // TODO(gram): Does skia support this? It doesn't seem like - // it. Right now we don't use the textBaseline value, but we - // may have to implement this ourselves, by adjusting the y - // values passed to StrokeText/FillText using the font metrics. - if (strcmp(baseline, "top") == 0) { - } else if (strcmp(baseline, "middle") == 0) { - } else if (strcmp(baseline, "bottom") == 0) { - } else if (strcmp(baseline, "hanging") == 0) { - } else if (strcmp(baseline, "alphabetic") == 0) { - } else if (strcmp(baseline, "ideographic") == 0) { - } - return baseline; -} - -const char* CanvasState::setTextDirection(const char* direction) { - // TODO(gram): Add support for this if Skia does. - return direction; -} - -void CanvasState::setMode(SkPaint::Style style, ColorRGBA color, - SkShader* shader) { - paint_.setStyle(style); - paint_.setColor(color.v); - paint_.setShader(shader); - uint8_t alpha = static_cast<uint8_t>( - globalAlpha_ * static_cast<float>(color.alpha())); - paint_.setAlpha(alpha); - bool drawShadow = (shadowOffsetX_ != 0 || - shadowOffsetY_ != 0 || - shadowBlur_ != 0) && - shadowColor_.alpha() > 0; - if (drawShadow) { - // TODO(gram): should we mult shadowColor by globalAlpha? - paint_.setLooper(new SkBlurDrawLooper(SkFloatToScalar(shadowBlur_), - SkFloatToScalar(shadowOffsetX_), - SkFloatToScalar(shadowOffsetY_), - shadowColor_.v))->unref(); - } else { - paint_.setLooper(NULL); - } -} - -void CanvasState::setGlobalCompositeOperation(const char* op) { - SkXfermode::Mode mode; - static const struct CompositOpToXfermodeMode { - const char* mCompositOp; - uint8_t m_xfermodeMode; - } gMapCompositOpsToXfermodeModes[] = { - { "clear", SkXfermode::kClear_Mode }, - { "copy", SkXfermode::kSrc_Mode }, - { "source-over", SkXfermode::kSrcOver_Mode }, - { "source-in", SkXfermode::kSrcIn_Mode }, - { "source-out", SkXfermode::kSrcOut_Mode }, - { "source-atop", SkXfermode::kSrcATop_Mode }, - { "destination-over", SkXfermode::kDstOver_Mode }, - { "destination-in", SkXfermode::kDstIn_Mode }, - { "destination-out", SkXfermode::kDstOut_Mode }, - { "destination-atop", SkXfermode::kDstATop_Mode }, - { "xor", SkXfermode::kXor_Mode }, - { "darker", SkXfermode::kDarken_Mode }, - { "lighter", SkXfermode::kPlus_Mode } - }; - for (unsigned i = 0; - i < SK_ARRAY_COUNT(gMapCompositOpsToXfermodeModes); - i++) { - if (strcmp(op, gMapCompositOpsToXfermodeModes[i].mCompositOp) == 0) { - mode = (SkXfermode::Mode)gMapCompositOpsToXfermodeModes[i].m_xfermodeMode; - paint_.setXfermodeMode(mode); - return; - } - } - LOGE("Unknown CompositeOperator %s\n", op); - paint_.setXfermodeMode(SkXfermode::kSrcOver_Mode); // fall-back -} - -void CanvasState::Arc(float x, float y, float radius, - float startAngle, float endAngle, - bool antiClockwise) { - SkRect rect; - rect.set(x - radius, y - radius, x + radius, y + radius); - bool doCircle = false; - - static float twoPi = 2 * M_PI; - - float sweep = endAngle - startAngle; - if (sweep >= twoPi || sweep <= -twoPi) { - doCircle = true; - } - - if (!antiClockwise && endAngle <= startAngle) { - endAngle += 2 * M_PI; - } else if (antiClockwise && startAngle <= endAngle) { - startAngle += 2 * M_PI; - } - sweep = endAngle - startAngle; - - startAngle = fmodf(startAngle, twoPi); - float sa = Radians2Degrees(startAngle); - float ea = Radians2Degrees(sweep); - path_->arcTo(rect, sa, ea, false); - if (doCircle) { - SkPath tmp; - tmp.addOval(rect); - tmp.addPath(*path_); - path_->swap(tmp); - } -} - -int hexDigit(char c) { - if (c >= '0' && c <= '9') return c - '0'; - if (c <= 'Z') return c - 'A' + 10; - return c - 'a' + 10; -} - -// Color parser. -// See http://www.w3.org/TR/CSS21/syndata.html#color-units. -// There is also another format: hsl(240,100%,100%) (and hsla) -// TODO(gram): We probably eventually want to use a table rather -// than a big if statement; see setGlobalCompositeOperation for -// an example. -ColorRGBA CanvasState::GetColor(const char* color) { - if (color[0] == '#') { - int r = 0, g = 0, b = 0; - if (strlen(color) == 7) { - r = hexDigit(color[1]) * 16 + hexDigit(color[2]); - g = hexDigit(color[3]) * 16 + hexDigit(color[4]); - b = hexDigit(color[5]) * 16 + hexDigit(color[6]); - } else if (strlen(color) == 4) { - r = hexDigit(color[1]) * 16 + hexDigit(color[1]); - g = hexDigit(color[2]) * 16 + hexDigit(color[2]); - b = hexDigit(color[3]) * 16 + hexDigit(color[3]); - } - return ColorRGBA(r, g, b); - } else if (strcmp(color, "maroon") == 0) { - return ColorRGBA(0x80, 0x00, 0x00); - } else if (strcmp(color, "red") == 0) { - return ColorRGBA(0xFF, 0x00, 0x00); - } else if (strcmp(color, "orange") == 0) { - return ColorRGBA(0xFF, 0xA5, 0x00); - } else if (strcmp(color, "yellow") == 0) { - return ColorRGBA(0xFF, 0xFF, 0x00); - } else if (strcmp(color, "olive") == 0) { - return ColorRGBA(0x80, 0x80, 0x00); - } else if (strcmp(color, "purple") == 0) { - return ColorRGBA(0x80, 0x00, 0x80); - } else if (strcmp(color, "fuschia") == 0) { - return ColorRGBA(0xFF, 0x00, 0xFF); - } else if (strcmp(color, "white") == 0) { - return ColorRGBA(0xFF, 0xFF, 0xFF); - } else if (strcmp(color, "lime") == 0) { - return ColorRGBA(0x00, 0xFF, 0x00); - } else if (strcmp(color, "green") == 0) { - return ColorRGBA(0x00, 0x80, 0x00); - } else if (strcmp(color, "navy") == 0) { - return ColorRGBA(0x00, 0x00, 0x80); - } else if (strcmp(color, "blue") == 0) { - return ColorRGBA(0x00, 0x00, 0xFF); - } else if (strcmp(color, "aqua") == 0) { - return ColorRGBA(0x00, 0xFF, 0xFF); - } else if (strcmp(color, "teal") == 0) { - return ColorRGBA(0x00, 0x80, 0x80); - } else if (strcmp(color, "silver") == 0) { - return ColorRGBA(0xC0, 0xC0, 0xC0); - } else if (strcmp(color, "gray") == 0) { - return ColorRGBA(0x80, 0x80, 0x80); - } else if (strncmp(color, "rgb(", 4) == 0) { - int pos = 4; - int r = ParseInt(color, pos); - ++pos; - int g = ParseInt(color, pos); - ++pos; - int b = ParseInt(color, pos); - return ColorRGBA(r, g, b); - } else if (strncmp(color, "rgba(", 5) == 0) { - int pos = 5; - int r = ParseInt(color, pos); - ++pos; - int g = ParseInt(color, pos); - ++pos; - int b = ParseInt(color, pos); - ++pos; - float a = ParseFloat(color, pos); - return ColorRGBA(r, g, b, static_cast<int>(a * 255.0)); - } - // Default to black. - return ColorRGBA(0x00, 0x00, 0x00); -} - -void CanvasState::DrawImage(const SkBitmap& bm, - int sx, int sy, int sw, int sh, - int dx, int dy, int dw, int dh) { - if (sw < 0) sw = bm.width(); - if (dw < 0) dw = bm.width(); - if (sh < 0) sh = bm.height(); - if (dh < 0) dh = bm.height(); - SkIRect src = SkIRect::MakeXYWH(sx, sy, sw, sh); - SkRect dst = SkRect::MakeXYWH(dx, dy, dw, dh); - LOGI("DrawImage(_,%d,%d,%d,%d,%d,%d,%d,%d)", sx, sy, sw, sh, dx, dy, dw, dh); - canvas_->drawBitmapRect(bm, &src, dst); -} - -void CanvasState::SetFillGradient(bool is_radial, - double x0, double y0, double r0, - double x1, double y1, double r1, - int stops, float* positions, char** colors) { - if (fillShader_ != NULL) { - fillShader_->unref(); - } - if (is_radial) { - fillShader_ = CreateRadialGradient(x0, y0, r0, x1, y1, r1, - stops, positions, colors); - } else { - fillShader_ = CreateLinearGradient(x0, y0, x1, y1, - stops, positions, colors); - } - fillShader_->validate(); -} - -void CanvasState::SetStrokeGradient(bool is_radial, - double x0, double y0, double r0, - double x1, double y1, double r1, - int stops, float* positions, char** colors) { - if (strokeShader_ != NULL) { - strokeShader_->unref(); - } - if (is_radial) { - strokeShader_ = CreateRadialGradient(x0, y0, r0, x1, y1, r1, - stops, positions, colors); - } else { - strokeShader_ = CreateLinearGradient(x0, y0, x1, y1, - stops, positions, colors); - } - strokeShader_->validate(); -} - -SkShader* CanvasState::CreateRadialGradient( - double x0, double y0, double r0, - double x1, double y1, double r1, - int stops, float* positions, char** colors) { - SkScalar* p = new SkScalar[stops]; - SkColor* c = new SkColor[stops]; - for (int i = 0; i < stops; i++) { - p[i] = positions[i]; - c[i] = GetColor(colors[i]).v; - } - LOGI("CreateRadialGradient(%f,%f,%f,%f,%f,%f,%d,[%f,%f],[%s,%s]", - x0, y0, r0, x1, y1, r1, stops, positions[0], positions[1], - colors[0], colors[1]); - SkShader* shader = SkGradientShader::CreateTwoPointRadial( - SkPoint::Make(x0, y0), r0, SkPoint::Make(x1, y1), r1, - c, p, stops, SkShader::kClamp_TileMode); - delete[] c; - delete[] p; - return shader; -} - -SkShader* CanvasState::CreateLinearGradient( - double x0, double y0, double x1, double y1, - int stops, float* positions, char** colors) { - SkScalar* p = new SkScalar[stops]; - SkColor* c = new SkColor[stops]; - for (int i = 0; i < stops; i++) { - p[i] = positions[i]; - c[i] = GetColor(colors[i]).v; - } - SkPoint pts[2]; - pts[0] = SkPoint::Make(x0, y0); - pts[1] = SkPoint::Make(x1, y1); - SkShader* shader = SkGradientShader::CreateLinear(pts, c, p, stops, - SkShader::kClamp_TileMode); - delete[] c; - delete[] p; - return shader; -} -
diff --git a/runtime/embedders/openglui/common/canvas_state.h b/runtime/embedders/openglui/common/canvas_state.h deleted file mode 100644 index fc0e095..0000000 --- a/runtime/embedders/openglui/common/canvas_state.h +++ /dev/null
@@ -1,312 +0,0 @@ -// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#ifndef EMBEDDERS_OPENGLUI_COMMON_CANVAS_STATE_H_ -#define EMBEDDERS_OPENGLUI_COMMON_CANVAS_STATE_H_ - -#include "embedders/openglui/common/graphics_handler.h" -#include "embedders/openglui/common/log.h" -#include "embedders/openglui/common/opengl.h" -#include "embedders/openglui/common/support.h" - -typedef struct CanvasState { - SkPaint paint_; - float globalAlpha_; - float miterLimit_; - ColorRGBA fillColor_; - ColorRGBA strokeColor_; - ColorRGBA shadowColor_; - float shadowBlur_; - float shadowOffsetX_; - float shadowOffsetY_; - float* lineDash_; - int lineDashCount_; - int lineDashOffset_; - SkShader* fillShader_; - SkShader* strokeShader_; - - SkPath* path_; - SkCanvas* canvas_; - CanvasState* next_; // For stack. - - CanvasState(SkCanvas* canvas) - : paint_(), - globalAlpha_(1.0), - miterLimit_(10), - fillColor_(ColorRGBA(255, 0, 0, 255)), - strokeColor_(fillColor_), - shadowColor_(ColorRGBA(0, 0, 0, 0)), - shadowBlur_(0.0), - shadowOffsetX_(0.0), - shadowOffsetY_(0.0), - lineDash_(NULL), - lineDashCount_(0), - lineDashOffset_(0), - fillShader_(NULL), - strokeShader_(NULL), - path_(new SkPath()), - canvas_(canvas), - next_(NULL) { - paint_.setStrokeCap(SkPaint::kButt_Cap); - paint_.setStrokeJoin(SkPaint::kMiter_Join); - paint_.setStrokeWidth(1); - paint_.setTextAlign(SkPaint::kLeft_Align); - paint_.setAntiAlias(true); - paint_.setStyle(SkPaint::kStroke_Style); - setFont("Helvetica", 10); - } - - CanvasState(const CanvasState& state) - : paint_(state.paint_), - globalAlpha_(state.globalAlpha_), - miterLimit_(state.miterLimit_), - fillColor_(state.fillColor_), - strokeColor_(state.strokeColor_), - shadowColor_(state.shadowColor_), - shadowBlur_(state.shadowBlur_), - shadowOffsetX_(state.shadowOffsetX_), - shadowOffsetY_(state.shadowOffsetY_), - lineDash_(NULL), - lineDashCount_(state.lineDashCount_), - lineDashOffset_(state.lineDashOffset_), - fillShader_(state.fillShader_), - strokeShader_(state.strokeShader_), - path_(new SkPath()), - canvas_(state.canvas_), - next_(NULL) { - setLineDash(state.lineDash_, lineDashCount_); - if (fillShader_ != NULL) fillShader_->ref(); - if (strokeShader_ != NULL) strokeShader_->ref(); - } - - ~CanvasState() { - if (fillShader_ != NULL) fillShader_->unref(); - if (strokeShader_ != NULL) strokeShader_->unref(); - delete path_; - delete[] lineDash_; - } - - static ColorRGBA GetColor(const char* color); - - inline CanvasState* Save() { - canvas_->save(); // For clip and transform. - CanvasState *new_state = new CanvasState(*this); - new_state->next_ = this; - // If the old state has a non-empty path, use its - // last point as the new states first point. - int np = path_->countPoints(); - if (np > 0) { - new_state->path_->moveTo(path_->getPoint(np-1)); - } - return new_state; - } - - CanvasState* Restore(); - - inline float Radians2Degrees(float angle) { - return 180.0 * angle / M_PI; - } - - inline void setGlobalAlpha(float alpha) { - globalAlpha_ = alpha; - } - - inline void setFillColor(const char* color) { - if (fillShader_ != NULL) { - fillShader_->unref(); - fillShader_ = NULL; - } - fillColor_ = GetColor(color); - } - - inline void setStrokeColor(const char* color) { - if (strokeShader_ != NULL) { - strokeShader_->unref(); - strokeShader_ = NULL; - } - strokeColor_ = GetColor(color); - } - - const char* setFont(const char*name, float size = -1); - void setLineCap(const char* lc); - void setLineJoin(const char* lj); - - inline void setMiterLimit(float limit) { - miterLimit_ = limit; - } - - const char* setTextAlign(const char* align); - const char* setTextBaseline(const char* baseline); - const char* setTextDirection(const char* direction); - - inline void FillText(const char* text, float x, float y, float maxWidth) { - setFillMode(); - canvas_->drawText(text, strlen(text), x, y, paint_); - } - - inline void StrokeText(const char* text, float x, float y, float maxWidth) { - setStrokeMode(); - canvas_->drawText(text, strlen(text), x, y, paint_); - } - - inline float MeasureText(const char *text) { - // TODO(gram): make sure this is not supposed to be affected - // by the canvas transform. - return paint_.measureText(text, strlen(text)); - } - - inline void setLineWidth(float w) { - paint_.setStrokeWidth(w); - } - - void setMode(SkPaint::Style style, ColorRGBA color, SkShader* shader); - - inline void setLineDashEffect() { - if (lineDashCount_ > 0) { - SkDashPathEffect* dashPathEffect = - new SkDashPathEffect(lineDash_, lineDashCount_, lineDashOffset_); - paint_.setPathEffect(dashPathEffect)->unref(); - } else { - paint_.setPathEffect(NULL); - } - } - - inline void setLineDash(float* dashes, int len) { - if (len == 0) { - lineDashCount_ = 0; - delete[] lineDash_; - lineDash_ = NULL; - } else { - lineDash_ = new float[lineDashCount_ = len]; - for (int i = 0; i < len; i++) { - lineDash_[i] = dashes[i]; - } - } - setLineDashEffect(); - } - - inline void setLineDashOffset(int offset) { - if (offset != lineDashOffset_) { - lineDashOffset_ = offset; - setLineDashEffect(); - } - } - - inline void setShadowColor(const char* color) { - shadowColor_ = GetColor(color); - } - - inline void setShadowBlur(float blur) { - shadowBlur_ = blur; - } - - inline void setShadowOffsetX(float ox) { - shadowOffsetX_ = ox; - } - - inline void setShadowOffsetY(float oy) { - shadowOffsetY_ = oy; - } - - inline void setFillMode() { - setMode(SkPaint::kFill_Style, fillColor_, fillShader_); - } - - inline void setStrokeMode() { - setMode(SkPaint::kStroke_Style, strokeColor_, strokeShader_); - } - - inline void FillRect(float left, float top, - float width, float height) { - // Does not affect the path. - setFillMode(); - canvas_->drawRectCoords(left, top, left + width, top + height, paint_); - } - - inline void StrokeRect(float left, float top, - float width, float height) { - // Does not affect the path. - setStrokeMode(); - canvas_->drawRectCoords(left, top, left + width, top + height, paint_); - } - - inline void BeginPath() { - path_->rewind(); - } - - inline void Fill() { - setFillMode(); - canvas_->drawPath(*path_, paint_); - } - - inline void Stroke() { - setStrokeMode(); - canvas_->drawPath(*path_, paint_); - } - - inline void ClosePath() { - path_->close(); - } - - inline void MoveTo(float x, float y) { - path_->moveTo(x, y); - } - - inline void LineTo(float x, float y) { - path_->lineTo(x, y); - } - - void Arc(float x, float y, float radius, float startAngle, float endAngle, - bool antiClockwise); - - inline void QuadraticCurveTo(float cpx, float cpy, float x, float y) { - path_->quadTo(cpx, cpy, x, y); - } - - inline void BezierCurveTo(float cp1x, float cp1y, float cp2x, float cp2y, - float x, float y) { - path_->cubicTo(cp1x, cp1y, cp2x, cp2y, x, y); - } - - inline void ArcTo(float x1, float y1, float x2, float y2, float radius) { - path_->arcTo(x1, y1, x2, y2, radius); - } - - inline void Rect(float x, float y, float w, float h) { - // TODO(gram): Should we draw this directly? If so, what happens with the - // path? - path_->addRect(x, y, x + w, y + h); - } - - void setGlobalCompositeOperation(const char* op); - - void DrawImage(const SkBitmap& bm, - int sx, int sy, int sw, int sh, - int dx, int dy, int dw, int dh); - - inline void Clip() { - canvas_->clipPath(*path_); - } - - void SetFillGradient(bool is_radial, double x0, double y0, double r0, - double x1, double y1, double r1, - int stops, float* positions, char** colors); - - void SetStrokeGradient(bool is_radial, double x0, double y0, double r0, - double x1, double y1, double r1, - int stops, float* positions, char** colors); - - private: - SkShader* CreateRadialGradient( - double x0, double y0, double r0, - double x1, double y1, double r1, - int stops, float* positions, char** colors); - - SkShader* CreateLinearGradient( - double x0, double y0, double x1, double y1, - int stops, float* positions, char** colors); -} CanvasState; - -#endif // EMBEDDERS_OPENGLUI_COMMON_CANVAS_STATE_H_ -
diff --git a/runtime/embedders/openglui/common/context.h b/runtime/embedders/openglui/common/context.h deleted file mode 100644 index 54148fc..0000000 --- a/runtime/embedders/openglui/common/context.h +++ /dev/null
@@ -1,23 +0,0 @@ -// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#ifndef EMBEDDERS_OPENGLUI_COMMON_CONTEXT_H_ -#define EMBEDDERS_OPENGLUI_COMMON_CONTEXT_H_ - -#include "embedders/openglui/common/graphics_handler.h" -#include "embedders/openglui/common/input_handler.h" -#include "embedders/openglui/common/sound_handler.h" -#include "embedders/openglui/common/timer.h" -#include "embedders/openglui/common/vm_glue.h" - -struct Context { - GraphicsHandler* graphics_handler; - InputHandler* input_handler; - SoundHandler* sound_handler; - Timer* timer; - VMGlue* vm_glue; -}; - -#endif // EMBEDDERS_OPENGLUI_COMMON_CONTEXT_H_ -
diff --git a/runtime/embedders/openglui/common/dart_host.cc b/runtime/embedders/openglui/common/dart_host.cc deleted file mode 100644 index dd2c1cd..0000000 --- a/runtime/embedders/openglui/common/dart_host.cc +++ /dev/null
@@ -1,117 +0,0 @@ -// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#include "embedders/openglui/common/dart_host.h" - -#include <math.h> -#include <unistd.h> - -#include "embedders/openglui/common/image_cache.h" -#include "embedders/openglui/common/log.h" - -DartHost::DartHost(Context *context) - : graphics_handler_(context->graphics_handler), - input_handler_(context->input_handler), - sound_handler_(context->sound_handler), - timer_(context->timer), - vm_glue_(context->vm_glue), - has_context_(false), - started_(false), - active_(false) { - ImageCache::Init(graphics_handler_->resource_path()); -} - -DartHost::~DartHost() { -} - -int32_t DartHost::OnStart() { - int result = vm_glue_->StartMainIsolate(); - if (result != 0) { - LOGE("startMainIsolate returned %d", result); - return -1; - } - started_ = true; - return 0; -} - -int32_t DartHost::Activate() { - if (!has_context_) { - if (graphics_handler_->Start() != 0) { - return -1; - } - if (sound_handler_->Start() != 0) { - graphics_handler_->Stop(); - return -1; - } - if (input_handler_->Start() != 0) { - sound_handler_->Stop(); - graphics_handler_->Stop(); - return -1; - } - int32_t rtn = vm_glue_->CallSetup(true); - timer_->Reset(); - has_context_ = true; - return rtn; - } - return 0; -} - -void DartHost::Deactivate() { - Pause(); - if (has_context_) { - vm_glue_->CallShutdown(); - input_handler_->Stop(); - sound_handler_->Stop(); - graphics_handler_->Stop(); - has_context_ = false; - } -} - -int32_t DartHost::OnStep() { - if (active_) { - timer_->Update(); - if (vm_glue_->CallUpdate() != 0 || - graphics_handler_->Update() != 0) { - return -1; - } - } - return 0; -} - -int32_t DartHost::Resume() { - if (!active_) { - if (Activate() == 0) { - sound_handler_->Resume(); - active_ = true; - } - } - return 0; -} - -void DartHost::Pause() { - if (active_) { - active_ = false; // This stops update() calls. - sound_handler_->Suspend(); - } -} - -void DartHost::FreeAllResources() { - if (started_) { - vm_glue_->FinishMainIsolate(); - started_ = false; - } -} - -void DartHost::OnSaveState(void** data, size_t* size) { - LOGI("Saving DartHost state"); -} - -void DartHost::OnConfigurationChanged() { - LOGI("DartHost config changed"); -} - -void DartHost::OnLowMemory() { - LOGI("DartHost low on memory"); -} -
diff --git a/runtime/embedders/openglui/common/dart_host.h b/runtime/embedders/openglui/common/dart_host.h deleted file mode 100644 index 9233aa2f..0000000 --- a/runtime/embedders/openglui/common/dart_host.h +++ /dev/null
@@ -1,47 +0,0 @@ -// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#ifndef EMBEDDERS_OPENGLUI_COMMON_DART_HOST_H_ -#define EMBEDDERS_OPENGLUI_COMMON_DART_HOST_H_ - -#include "embedders/openglui/common/context.h" -#include "embedders/openglui/common/graphics_handler.h" -#include "embedders/openglui/common/input_handler.h" -#include "embedders/openglui/common/lifecycle_handler.h" -#include "embedders/openglui/common/sound_handler.h" -#include "embedders/openglui/common/timer.h" -#include "embedders/openglui/common/vm_glue.h" -#include "include/dart_api.h" - -class DartHost : public LifeCycleHandler { - public: - explicit DartHost(Context* context); - virtual ~DartHost(); - - int32_t OnStart(); - void OnSaveState(void** data, size_t* size); - void OnConfigurationChanged(); - void OnLowMemory(); - int32_t Activate(); - void Deactivate(); - void Pause(); - int32_t Resume(); - void FreeAllResources(); - int32_t OnStep(); - - private: - void Clear(); - - GraphicsHandler* graphics_handler_; - InputHandler* input_handler_; - SoundHandler* sound_handler_; - Timer* timer_; - VMGlue* vm_glue_; - bool has_context_; - bool started_; - bool active_; -}; - -#endif // EMBEDDERS_OPENGLUI_COMMON_DART_HOST_H_ -
diff --git a/runtime/embedders/openglui/common/events.h b/runtime/embedders/openglui/common/events.h deleted file mode 100644 index 64c6951..0000000 --- a/runtime/embedders/openglui/common/events.h +++ /dev/null
@@ -1,39 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#ifndef EMBEDDERS_OPENGLUI_COMMON_EVENTS_H_ -#define EMBEDDERS_OPENGLUI_COMMON_EVENTS_H_ - -typedef enum { - kStart, - kStop, - kGainedFocus, - kLostFocus, - kPause, - kResume, - kSaveState, - kConfigChanged, - kInitWindow, - kTermWindow, - kDestroy -} LifecycleEvent; - -typedef enum { - kKeyDown, - kKeyUp, - kKeyMultiple -} KeyEvent; - -typedef enum { - kMotionDown, - kMotionUp, - kMotionMove, - kMotionCancel, - kMotionOutside, - kMotionPointerDown, - kMotionPointerUp -} MotionEvent; - -#endif // EMBEDDERS_OPENGLUI_COMMON_EVENTS_H_ -
diff --git a/runtime/embedders/openglui/common/extension.cc b/runtime/embedders/openglui/common/extension.cc deleted file mode 100644 index 6304c3b..0000000 --- a/runtime/embedders/openglui/common/extension.cc +++ /dev/null
@@ -1,1737 +0,0 @@ -// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#include "embedders/openglui/common/extension.h" - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include "embedders/openglui/common/canvas_context.h" -#include "embedders/openglui/common/image_cache.h" -#include "embedders/openglui/common/graphics_handler.h" -#include "embedders/openglui/common/log.h" -#include "embedders/openglui/common/opengl.h" -#include "include/dart_api.h" -#include "include/dart_native_api.h" - -Dart_Handle HandleError(Dart_Handle handle) { - if (Dart_IsError(handle)) Dart_PropagateError(handle); - return handle; -} - -void CheckGLError(const char *function) { - int error = glGetError(); - if (error != GL_NO_ERROR) { - if (error == GL_INVALID_ENUM) { - LOGE("%s: An unacceptable value is given for an enumerated argument.", - function); - } else if (error == GL_INVALID_VALUE) { - LOGE("%s: A numeric argument is out of range.", function); - } else if (error == GL_INVALID_OPERATION) { - LOGE("%s: The specified operation is not allowed in the current state.", - function); - } else if (error == GL_INVALID_FRAMEBUFFER_OPERATION) { - LOGE("%s: The framebuffer object is not complete.", function); - } else if (error == GL_OUT_OF_MEMORY) { - LOGE("%s: There is not enough memory left to execute the command.", - function); - } else { - LOGE("ERROR!: %s returns %d", function, error); - } - } -} - -const char* GetArgAsString(Dart_NativeArguments arguments, int idx) { - Dart_Handle handle = HandleError(Dart_GetNativeArgument(arguments, idx)); - uint8_t* str; - intptr_t length; - HandleError(Dart_StringLength(handle, &length)); - HandleError(Dart_StringToUTF8(handle, &str, &length)); - str[length] = 0; - return const_cast<const char*>(reinterpret_cast<char*>(str)); -} - -double GetArgAsDouble(Dart_NativeArguments arguments, int index) { - Dart_Handle handle = HandleError(Dart_GetNativeArgument(arguments, index)); - if (Dart_IsDouble(handle)) { - double v; - HandleError(Dart_DoubleValue(handle, &v)); - return v; - } - if (Dart_IsInteger(handle)) { - int64_t v; - HandleError(Dart_IntegerToInt64(handle, &v)); - return static_cast<double>(v); - } - LOGE("Argument at index %d has non-numeric type", index); - Dart_ThrowException(Dart_NewStringFromCString("Numeric argument expected.")); - return 0; -} - -int64_t GetArgAsInt(Dart_NativeArguments arguments, int index) { - Dart_Handle handle = HandleError(Dart_GetNativeArgument(arguments, index)); - if (Dart_IsDouble(handle)) { - double v; - HandleError(Dart_DoubleValue(handle, &v)); - return static_cast<int64_t>(v); - } - if (Dart_IsInteger(handle)) { - int64_t v; - HandleError(Dart_IntegerToInt64(handle, &v)); - return v; - } - LOGE("Argument at index %d has non-numeric type", index); - Dart_ThrowException(Dart_NewStringFromCString("Numeric argument expected.")); - return 0; -} - -bool GetArgAsBool(Dart_NativeArguments arguments, int index) { - Dart_Handle handle = HandleError(Dart_GetNativeArgument(arguments, index)); - if (Dart_IsBoolean(handle)) { - bool v; - HandleError(Dart_BooleanValue(handle, &v)); - return v; - } - LOGI("Argument at index %d has non-Boolean type", index); - Dart_ThrowException(Dart_NewStringFromCString("Boolean argument expected.")); - return false; -} - -int GetListLength(Dart_NativeArguments arguments, int index, - Dart_Handle& argHandle) { - argHandle = HandleError(Dart_GetNativeArgument(arguments, index)); - if (Dart_IsList(argHandle)) { - intptr_t len; - HandleError(Dart_ListLength(argHandle, &len)); - return len; - } - LOGI("Argument at index %d has non-List type", index); - Dart_ThrowException(Dart_NewStringFromCString("List argument expected.")); - return -1; -} - -GLint* GetArgsAsGLintList(Dart_NativeArguments arguments, int index, - int* len_out) { - Dart_Handle argHandle; - int len = GetListLength(arguments, index, argHandle); - if (len < 0) return NULL; - GLint* list = new GLint[len]; - for (int i = 0; i < len; i++) { - Dart_Handle vHandle = Dart_ListGetAt(argHandle, i); - int64_t v; - HandleError(Dart_IntegerToInt64(vHandle, &v)); - list[i] = v; - } - *len_out = len; - return list; -} - -GLfloat* GetArgsAsFloatList(Dart_NativeArguments arguments, int index, - int* len_out) { - Dart_Handle argHandle; - int len = GetListLength(arguments, index, argHandle); - if (len < 0) return NULL; - GLfloat* list = new GLfloat[len]; - for (int i = 0; i < len; i++) { - Dart_Handle vHandle = Dart_ListGetAt(argHandle, i); - double v; - HandleError(Dart_DoubleValue(vHandle, &v)); - list[i] = v; - } - *len_out = len; - return list; -} - -char** GetArgsAsStringList(Dart_NativeArguments arguments, int index, - int* len_out) { - Dart_Handle argHandle; - int len = GetListLength(arguments, index, argHandle); - if (len < 0) return NULL; - char** list = new char*[len]; - for (int i = 0; i < len; i++) { - Dart_Handle vHandle = Dart_ListGetAt(argHandle, i); - uint8_t* str; - intptr_t length; - HandleError(Dart_StringLength(vHandle, &length)); - HandleError(Dart_StringToUTF8(vHandle, &str, &length)); - str[length] = 0; - list[i] = reinterpret_cast<char*>(str); - } - *len_out = len; - return list; -} - -void SetBoolReturnValue(Dart_NativeArguments arguments, bool b) { - Dart_Handle result = HandleError(Dart_NewBoolean(b)); - Dart_SetReturnValue(arguments, result); -} - -void SetIntReturnValue(Dart_NativeArguments arguments, int v) { - Dart_Handle result = HandleError(Dart_NewInteger(v)); - Dart_SetReturnValue(arguments, result); -} - -void SetDoubleReturnValue(Dart_NativeArguments arguments, double v) { - Dart_Handle result = HandleError(Dart_NewDouble(v)); - Dart_SetReturnValue(arguments, result); -} - -void SetStringReturnValue(Dart_NativeArguments arguments, const char* s) { - Dart_Handle result = HandleError(Dart_NewStringFromCString(s)); - Dart_SetReturnValue(arguments, result); -} - -void Log(Dart_NativeArguments arguments) { - Dart_EnterScope(); - LOGI("%s", GetArgAsString(arguments, 0)); - Dart_ExitScope(); -} - -void LogError(Dart_NativeArguments arguments) { - Dart_EnterScope(); - LOGE("%s", GetArgAsString(arguments, 0)); - Dart_ExitScope(); -} - -void SystemRand(Dart_NativeArguments arguments) { - Dart_EnterScope(); - SetIntReturnValue(arguments, rand()); - Dart_ExitScope(); -} - -void SystemSrand(Dart_NativeArguments arguments) { - Dart_EnterScope(); - bool success = false; - Dart_Handle seed_object = HandleError(Dart_GetNativeArgument(arguments, 0)); - if (Dart_IsInteger(seed_object)) { - bool fits; - HandleError(Dart_IntegerFitsIntoInt64(seed_object, &fits)); - if (fits) { - int64_t seed; - HandleError(Dart_IntegerToInt64(seed_object, &seed)); - srand(static_cast<unsigned>(seed)); - success = true; - } - } - SetBoolReturnValue(arguments, success); - Dart_ExitScope(); -} - -void GetDeviceScreenWidth(Dart_NativeArguments arguments) { - LOGI("GetDeviceScreenWidth"); - Dart_EnterScope(); - SetIntReturnValue(arguments, graphics->width()); - Dart_ExitScope(); -} - -void GetDeviceScreenHeight(Dart_NativeArguments arguments) { - LOGI("GetDeviceScreenHeight"); - Dart_EnterScope(); - SetIntReturnValue(arguments, graphics->height()); - Dart_ExitScope(); -} - -void SwapBuffers(Dart_NativeArguments arguments) { - LOGI("SwapBuffers"); - Dart_EnterScope(); - GLSwapBuffers(); - CheckGLError("GLSwapBuffers"); - Dart_ExitScope(); -} - -void GLAttachShader(Dart_NativeArguments arguments) { - LOGI("GLAttachShader"); - Dart_EnterScope(); - - int64_t program = GetArgAsInt(arguments, 0); - int64_t shader = GetArgAsInt(arguments, 1); - - glAttachShader(program, shader); - CheckGLError("glAttachShader"); - Dart_ExitScope(); -} - -void GLBindBuffer(Dart_NativeArguments arguments) { - LOGI("GLBindBuffer"); - Dart_EnterScope(); - - int64_t target = GetArgAsInt(arguments, 0); - int64_t buffer = GetArgAsInt(arguments, 1); - - glBindBuffer(target, buffer); - CheckGLError("glBindBuffer"); - Dart_ExitScope(); -} - -void GLBufferData(Dart_NativeArguments arguments) { - LOGI("GLBufferData"); - Dart_EnterScope(); - - int64_t target = GetArgAsInt(arguments, 0); - - Dart_Handle dataHandle = HandleError(Dart_GetNativeArgument(arguments, 1)); - intptr_t size; - HandleError(Dart_ListLength(dataHandle, &size)); - - LOGI("Size: %d", static_cast<int>(size)); - - // TODO(vsm): No guarantee that this is a float! - float* data = new float[size]; - for (int i = 0; i < size; i++) { - Dart_Handle elemHandle = HandleError(Dart_ListGetAt(dataHandle, i)); - double value; - Dart_DoubleValue(elemHandle, &value); - data[i] = static_cast<float>(value); - LOGI("Value[%d]: %f", i, data[i]); - } - - Dart_Handle usageHandle = HandleError(Dart_GetNativeArgument(arguments, 2)); - int64_t usage; - HandleError(Dart_IntegerToInt64(usageHandle, &usage)); - - glBufferData(target, size * sizeof(data[0]), data, usage); - CheckGLError("glBufferData"); - delete[] data; - Dart_ExitScope(); -} - -void GLCompileShader(Dart_NativeArguments arguments) { - LOGI("GLCompileShader"); - Dart_EnterScope(); - int64_t shader = GetArgAsInt(arguments, 0); - glCompileShader(shader); - CheckGLError("glCompileShader"); - Dart_ExitScope(); -} - -void GLCreateBuffer(Dart_NativeArguments arguments) { - LOGI("GLCreateBuffer"); - Dart_EnterScope(); - GLuint buffer; - glGenBuffers(1, &buffer); - CheckGLError("glGenBuffers"); - SetIntReturnValue(arguments, buffer); - Dart_ExitScope(); -} - -void GLCreateProgram(Dart_NativeArguments arguments) { - LOGI("GLCreateProgram"); - Dart_EnterScope(); - int64_t program = glCreateProgram(); - CheckGLError("glCreateProgram"); - SetIntReturnValue(arguments, program); - Dart_ExitScope(); -} - -void GLCreateShader(Dart_NativeArguments arguments) { - LOGI("GLCreateShader"); - Dart_EnterScope(); - int64_t type = GetArgAsInt(arguments, 0); - int64_t shader = glCreateShader((GLenum)type); - CheckGLError("glCreateShader"); - SetIntReturnValue(arguments, shader); - Dart_ExitScope(); -} - -void GLDrawArrays(Dart_NativeArguments arguments) { - LOGI("GLDrawArrays"); - Dart_EnterScope(); - - int64_t mode = GetArgAsInt(arguments, 0); - int64_t first = GetArgAsInt(arguments, 1); - int64_t count = GetArgAsInt(arguments, 2); - - glDrawArrays(mode, first, count); - CheckGLError("glDrawArrays"); - Dart_ExitScope(); - LOGI("Done GLDrawArrays"); -} - -void GLEnableVertexAttribArray(Dart_NativeArguments arguments) { - LOGI("GLEnableVertexAttribArray"); - Dart_EnterScope(); - - int64_t location = GetArgAsInt(arguments, 0); - - glEnableVertexAttribArray(location); - CheckGLError("glEnableVertexAttribArray"); - Dart_ExitScope(); -} - -void GLGetAttribLocation(Dart_NativeArguments arguments) { - LOGI("GLGetAttribLocation"); - Dart_EnterScope(); - - int64_t program = GetArgAsInt(arguments, 0); - - Dart_Handle nameHandle = HandleError(Dart_GetNativeArgument(arguments, 1)); - intptr_t length; - HandleError(Dart_StringLength(nameHandle, &length)); - uint8_t* str; - HandleError(Dart_StringToUTF8(nameHandle, &str, &length)); - str[length] = 0; - - int64_t location = glGetAttribLocation(program, - const_cast<const GLchar*>(reinterpret_cast<GLchar*>(str))); - CheckGLError("glGetAttribLocation"); - SetIntReturnValue(arguments, location); - Dart_ExitScope(); -} - -void GLGetError(Dart_NativeArguments arguments) { - LOGI("GLGetError"); - Dart_EnterScope(); - SetIntReturnValue(arguments, glGetError()); - Dart_ExitScope(); -} - -void GLGetProgramParameter(Dart_NativeArguments arguments) { - LOGI("GLGetProgramParameter"); - Dart_EnterScope(); - - int64_t program = GetArgAsInt(arguments, 0); - int64_t param = GetArgAsInt(arguments, 1); - - GLint value = -1; - glGetProgramiv(program, param, &value); - CheckGLError("glGetProgramiv"); - - SetIntReturnValue(arguments, value); - Dart_ExitScope(); -} - -void GLGetShaderParameter(Dart_NativeArguments arguments) { - LOGI("GLGetShaderParameter"); - Dart_EnterScope(); - - int64_t shader = GetArgAsInt(arguments, 0); - int64_t param = GetArgAsInt(arguments, 1); - - GLint value = -1; - glGetShaderiv((GLuint)shader, (GLenum)param, &value); - CheckGLError("glGetShaderiv"); - - SetIntReturnValue(arguments, value); - Dart_ExitScope(); -} - -void GLGetShaderInfoLog(Dart_NativeArguments arguments) { - LOGI("GLGetShaderInfoLog"); - Dart_EnterScope(); - - int64_t shader = GetArgAsInt(arguments, 0); - - GLint infoLogLength = 0; - glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength); - GLchar* strInfoLog = new GLchar[infoLogLength + 1]; - glGetShaderInfoLog(shader, infoLogLength, NULL, strInfoLog); - strInfoLog[infoLogLength] = 0; - - SetStringReturnValue(arguments, strInfoLog); - Dart_ExitScope(); - delete[] strInfoLog; -} - -void GLGetProgramInfoLog(Dart_NativeArguments arguments) { - LOGI("GLGetProgramInfoLog"); - Dart_EnterScope(); - - int64_t program = GetArgAsInt(arguments, 0); - - GLint infoLogLength; - glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength); - - GLchar* strInfoLog = new GLchar[infoLogLength + 1]; - glGetProgramInfoLog(program, infoLogLength, NULL, strInfoLog); - strInfoLog[infoLogLength] = 0; - - SetStringReturnValue(arguments, strInfoLog); - Dart_ExitScope(); - delete[] strInfoLog; -} - -void GLGetUniformLocation(Dart_NativeArguments arguments) { - LOGI("GLGetUniformLocation"); - Dart_EnterScope(); - - int64_t program = GetArgAsInt(arguments, 0); - - - Dart_Handle nameHandle = HandleError(Dart_GetNativeArgument(arguments, 1)); - intptr_t length; - HandleError(Dart_StringLength(nameHandle, &length)); - uint8_t* str; - HandleError(Dart_StringToUTF8(nameHandle, &str, &length)); - str[length] = 0; - - int64_t location = glGetUniformLocation(program, - const_cast<const GLchar*>(reinterpret_cast<GLchar*>(str))); - CheckGLError("glGetUniformLocation"); - SetIntReturnValue(arguments, location); - Dart_ExitScope(); -} - -void GLLinkProgram(Dart_NativeArguments arguments) { - LOGI("GLLinkProgram"); - Dart_EnterScope(); - int64_t program = GetArgAsInt(arguments, 0); - glLinkProgram(program); - CheckGLError("glLinkProgram"); - Dart_ExitScope(); -} - -void GLShaderSource(Dart_NativeArguments arguments) { - LOGI("GLShaderSource"); - Dart_EnterScope(); - - int64_t shader = GetArgAsInt(arguments, 0); - - Dart_Handle sourceHandle = HandleError(Dart_GetNativeArgument(arguments, 1)); - intptr_t length[1]; - HandleError(Dart_StringLength(sourceHandle, length)); - LOGI("Source length is %d", static_cast<int>(length[0])); - uint8_t* str[1]; - HandleError(Dart_StringToUTF8(sourceHandle, &str[0], length)); - LOGI("Converted length is %d", static_cast<int>(length[0])); - str[0][*length] = 0; - - LOGI("Source: %s", - const_cast<const GLchar*>(reinterpret_cast<GLchar*>(str[0]))); - glShaderSource(shader, 1, - const_cast<const GLchar**>(reinterpret_cast<GLchar**>(str)), NULL); - CheckGLError("glShaderSource"); - Dart_ExitScope(); -} - -void GLUseProgram(Dart_NativeArguments arguments) { - LOGI("GLUseProgram"); - Dart_EnterScope(); - int64_t program = GetArgAsInt(arguments, 0); - glUseProgram(program); - CheckGLError("glUseProgram"); - Dart_ExitScope(); -} - -void GLUniform1i(Dart_NativeArguments arguments) { - LOGI("GLUniform1i"); - Dart_EnterScope(); - int64_t location = GetArgAsInt(arguments, 0); - int64_t v0 = GetArgAsInt(arguments, 1); - glUniform1i(location, v0); - CheckGLError("glUniform1i"); - Dart_ExitScope(); -} - -void GLUniform2i(Dart_NativeArguments arguments) { - LOGI("GLUniform2i"); - Dart_EnterScope(); - int64_t location = GetArgAsInt(arguments, 0); - int64_t v0 = GetArgAsInt(arguments, 1); - int64_t v1 = GetArgAsInt(arguments, 2); - glUniform2i(location, v0, v1); - CheckGLError("glUniform2i"); - Dart_ExitScope(); -} - -void GLUniform3i(Dart_NativeArguments arguments) { - LOGI("GLUniform3i"); - Dart_EnterScope(); - int64_t location = GetArgAsInt(arguments, 0); - int64_t v0 = GetArgAsInt(arguments, 1); - int64_t v1 = GetArgAsInt(arguments, 2); - int64_t v2 = GetArgAsInt(arguments, 3); - glUniform3i(location, v0, v1, v2); - CheckGLError("glUniform3i"); - Dart_ExitScope(); -} - -void GLUniform4i(Dart_NativeArguments arguments) { - LOGI("GLUniform4i"); - Dart_EnterScope(); - int64_t location = GetArgAsInt(arguments, 0); - int64_t v0 = GetArgAsInt(arguments, 1); - int64_t v1 = GetArgAsInt(arguments, 2); - int64_t v2 = GetArgAsInt(arguments, 3); - int64_t v3 = GetArgAsInt(arguments, 4); - glUniform4i(location, v0, v1, v2, v3); - CheckGLError("glUniform4i"); - Dart_ExitScope(); -} - -void GLUniform1f(Dart_NativeArguments arguments) { - LOGI("GLUniform1f"); - Dart_EnterScope(); - int64_t location = GetArgAsInt(arguments, 0); - double v0 = GetArgAsDouble(arguments, 1); - glUniform1f(location, v0); - CheckGLError("glUniform1f"); - Dart_ExitScope(); -} - -void GLUniform2f(Dart_NativeArguments arguments) { - LOGI("GLUniform2f"); - Dart_EnterScope(); - int64_t location = GetArgAsInt(arguments, 0); - double v0 = GetArgAsDouble(arguments, 1); - double v1 = GetArgAsDouble(arguments, 2); - glUniform2f(location, v0, v1); - CheckGLError("glUniform2f"); - Dart_ExitScope(); -} - -void GLUniform3f(Dart_NativeArguments arguments) { - LOGI("GLUniform3f"); - Dart_EnterScope(); - int64_t location = GetArgAsInt(arguments, 0); - double v0 = GetArgAsDouble(arguments, 1); - double v1 = GetArgAsDouble(arguments, 2); - double v2 = GetArgAsDouble(arguments, 3); - glUniform3f(location, v0, v1, v2); - CheckGLError("glUniform3f"); - Dart_ExitScope(); -} - -void GLUniform4f(Dart_NativeArguments arguments) { - LOGI("GLUniform4f"); - Dart_EnterScope(); - int64_t location = GetArgAsInt(arguments, 0); - double v0 = GetArgAsDouble(arguments, 1); - double v1 = GetArgAsDouble(arguments, 2); - double v2 = GetArgAsDouble(arguments, 3); - double v3 = GetArgAsDouble(arguments, 4); - glUniform4f(location, v0, v1, v2, v3); - CheckGLError("glUniform4f"); - Dart_ExitScope(); -} - -void GLUniform1iv(Dart_NativeArguments arguments) { - LOGI("GLUniform1iv"); - Dart_EnterScope(); - int64_t location = GetArgAsInt(arguments, 0); - int len; - GLint* list = GetArgsAsGLintList(arguments, 1, &len); - if (list != NULL) { - glUniform1iv(location, len, list); - delete [] list; - CheckGLError("glUniform1iv"); - } - Dart_ExitScope(); -} - -void GLUniform2iv(Dart_NativeArguments arguments) { - LOGI("GLUniform2iv"); - Dart_EnterScope(); - int64_t location = GetArgAsInt(arguments, 0); - int len; - GLint* list = GetArgsAsGLintList(arguments, 1, &len); - if (list != NULL) { - glUniform2iv(location, len / 2, list); - delete [] list; - CheckGLError("glUniform2iv"); - } - Dart_ExitScope(); -} - -void GLUniform3iv(Dart_NativeArguments arguments) { - LOGI("GLUniform3iv"); - Dart_EnterScope(); - int64_t location = GetArgAsInt(arguments, 0); - int len; - GLint* list = GetArgsAsGLintList(arguments, 1, &len); - if (list != NULL) { - glUniform3iv(location, len / 3, list); - delete [] list; - CheckGLError("glUniform3iv"); - } - Dart_ExitScope(); -} - -void GLUniform4iv(Dart_NativeArguments arguments) { - LOGI("GLUniform4iv"); - Dart_EnterScope(); - int64_t location = GetArgAsInt(arguments, 0); - int len; - GLint* list = GetArgsAsGLintList(arguments, 1, &len); - if (list != NULL) { - glUniform1iv(location, len / 4, list); - delete [] list; - CheckGLError("glUniform4iv"); - } - Dart_ExitScope(); -} - -void GLUniform1fv(Dart_NativeArguments arguments) { - LOGI("GLUniform1fv"); - Dart_EnterScope(); - int64_t location = GetArgAsInt(arguments, 0); - int len; - GLfloat* list = GetArgsAsFloatList(arguments, 1, &len); - if (list != NULL) { - glUniform1fv(location, len, list); - delete [] list; - CheckGLError("glUniform1fv"); - } - Dart_ExitScope(); -} - -void GLUniform2fv(Dart_NativeArguments arguments) { - LOGI("GLUniform2fv"); - Dart_EnterScope(); - int64_t location = GetArgAsInt(arguments, 0); - int len; - GLfloat* list = GetArgsAsFloatList(arguments, 1, &len); - if (list != NULL) { - glUniform2fv(location, len / 2, list); - delete [] list; - CheckGLError("glUniform2fv"); - } - Dart_ExitScope(); -} - -void GLUniform3fv(Dart_NativeArguments arguments) { - LOGI("GLUniform3fv"); - Dart_EnterScope(); - int64_t location = GetArgAsInt(arguments, 0); - int len; - GLfloat* list = GetArgsAsFloatList(arguments, 1, &len); - if (list != NULL) { - glUniform3fv(location, len / 3, list); - delete [] list; - CheckGLError("glUniform3fv"); - } - Dart_ExitScope(); -} - -void GLUniform4fv(Dart_NativeArguments arguments) { - LOGI("In GLUniform4fv"); - Dart_EnterScope(); - int64_t location = GetArgAsInt(arguments, 0); - int len; - GLfloat* list = GetArgsAsFloatList(arguments, 1, &len); - if (list != NULL) { - glUniform4fv(location, len / 4, list); - delete [] list; - CheckGLError("glUniform4fv"); - } - Dart_ExitScope(); -} - -void GLViewport(Dart_NativeArguments arguments) { - LOGI("GLViewport"); - Dart_EnterScope(); - int64_t x = GetArgAsInt(arguments, 0); - int64_t y = GetArgAsInt(arguments, 1); - int64_t width = GetArgAsInt(arguments, 2); - int64_t height = GetArgAsInt(arguments, 3); - glViewport(x, y, width, height); - CheckGLError("glViewPort"); - Dart_ExitScope(); -} - -void GLVertexAttribPointer(Dart_NativeArguments arguments) { - LOGI("GLVertexAttribPointer"); - Dart_EnterScope(); - int64_t index = GetArgAsInt(arguments, 0); - int64_t size = GetArgAsInt(arguments, 1); - int64_t type = GetArgAsInt(arguments, 2); - bool normalized = GetArgAsBool(arguments, 3); - int64_t stride = GetArgAsInt(arguments, 4); - - Dart_Handle pointerHandle = HandleError(Dart_GetNativeArgument(arguments, 5)); - int64_t pointerValue; - HandleError(Dart_IntegerToInt64(pointerHandle, &pointerValue)); - const void* pointer; - pointer = const_cast<const void*>(reinterpret_cast<void*>(pointerValue)); - - glVertexAttribPointer(index, size, type, normalized, stride, pointer); - CheckGLError("glVertexAttribPointer"); - Dart_ExitScope(); -} - -void GLClearColor(Dart_NativeArguments arguments) { - LOGI("GLClearColor"); - Dart_EnterScope(); - double red = GetArgAsDouble(arguments, 0); - double green = GetArgAsDouble(arguments, 1); - double blue = GetArgAsDouble(arguments, 2); - double alpha = GetArgAsDouble(arguments, 3); - glClearColor(red, green, blue, alpha); - CheckGLError("glClearColor"); - Dart_ExitScope(); -} - -void GLClearDepth(Dart_NativeArguments arguments) { - LOGI("GLClearDepth"); - Dart_EnterScope(); - double depth = GetArgAsDouble(arguments, 0); -#if defined(__ANDROID__) - glClearDepthf(depth); -#else - glClearDepth(depth); -#endif - CheckGLError("glClearDepth"); - Dart_ExitScope(); -} - -void GLClear(Dart_NativeArguments arguments) { - LOGI("GLClear"); - Dart_EnterScope(); - Dart_Handle maskHandle = HandleError(Dart_GetNativeArgument(arguments, 0)); - int64_t mask; - HandleError(Dart_IntegerToInt64(maskHandle, &mask)); - glClear(mask); - CheckGLError("glClear"); - Dart_ExitScope(); -} - -void ReturnGLIntConstant(Dart_NativeArguments arguments, int c) { - Dart_EnterScope(); - SetIntReturnValue(arguments, c); - Dart_ExitScope(); -} - -void GLArrayBuffer(Dart_NativeArguments arguments) { - ReturnGLIntConstant(arguments, GL_ARRAY_BUFFER); -} - -void GLColorBufferBit(Dart_NativeArguments arguments) { - ReturnGLIntConstant(arguments, GL_COLOR_BUFFER_BIT); -} - -void GLCompileStatus(Dart_NativeArguments arguments) { - ReturnGLIntConstant(arguments, GL_COMPILE_STATUS); -} - -void GLDeleteStatus(Dart_NativeArguments arguments) { - ReturnGLIntConstant(arguments, GL_DELETE_STATUS); -} - -void GLDepthBufferBit(Dart_NativeArguments arguments) { - ReturnGLIntConstant(arguments, GL_DEPTH_BUFFER_BIT); -} - -void GLFloat(Dart_NativeArguments arguments) { - ReturnGLIntConstant(arguments, GL_FLOAT); -} - -void GLFragmentShader(Dart_NativeArguments arguments) { - ReturnGLIntConstant(arguments, GL_FRAGMENT_SHADER); -} - -void GLLinkStatus(Dart_NativeArguments arguments) { - ReturnGLIntConstant(arguments, GL_LINK_STATUS); -} - -void GLStaticDraw(Dart_NativeArguments arguments) { - ReturnGLIntConstant(arguments, GL_STATIC_DRAW); -} - -void GLTriangleStrip(Dart_NativeArguments arguments) { - ReturnGLIntConstant(arguments, GL_TRIANGLE_STRIP); -} - -void GLTriangles(Dart_NativeArguments arguments) { - ReturnGLIntConstant(arguments, GL_TRIANGLES); -} - -void GLTrue(Dart_NativeArguments arguments) { - ReturnGLIntConstant(arguments, GL_TRUE); -} - -void GLValidateStatus(Dart_NativeArguments arguments) { - ReturnGLIntConstant(arguments, GL_VALIDATE_STATUS); -} - -void GLVertexShader(Dart_NativeArguments arguments) { - ReturnGLIntConstant(arguments, GL_VERTEX_SHADER); -} - -uint8_t* RandomArray(int seed, int length) { - if (length <= 0 || length > 10000000) return NULL; - uint8_t* values = reinterpret_cast<uint8_t*>(malloc(length)); - if (NULL == values) return NULL; - srand(seed); - for (int i = 0; i < length; ++i) { - values[i] = rand() % 256; - } - return values; -} - -void WrappedRandomArray(Dart_Port dest_port_id, - Dart_Port reply_port_id, - Dart_CObject* message) { - if (message->type == Dart_CObject_kArray && - 2 == message->value.as_array.length) { - // Use .as_array and .as_int32 to access the data in the Dart_CObject. - Dart_CObject* param0 = message->value.as_array.values[0]; - Dart_CObject* param1 = message->value.as_array.values[1]; - if (param0->type == Dart_CObject_kInt32 && - param1->type == Dart_CObject_kInt32) { - int length = param0->value.as_int32; - int seed = param1->value.as_int32; - - uint8_t* values = RandomArray(seed, length); - - if (values != NULL) { - Dart_CObject result; - result.type = Dart_CObject_kTypedData; - result.value.as_typed_data.type = Dart_TypedData_kUint8; - result.value.as_typed_data.values = values; - result.value.as_typed_data.length = length; - Dart_PostCObject(reply_port_id, &result); - free(values); - // It is OK that result is destroyed when function exits. - // Dart_PostCObject has copied its data. - return; - } - } - } - Dart_CObject result; - result.type = Dart_CObject_kNull; - Dart_PostCObject(reply_port_id, &result); -} - -void RandomArrayServicePort(Dart_NativeArguments arguments) { - Dart_EnterScope(); - Dart_SetReturnValue(arguments, Dart_Null()); - Dart_Port service_port = - Dart_NewNativePort("RandomArrayService", WrappedRandomArray, true); - if (service_port != ((Dart_Port)0)) { - Dart_Handle send_port = HandleError(Dart_NewSendPort(service_port)); - Dart_SetReturnValue(arguments, send_port); - } - Dart_ExitScope(); -} - -void PlayBackground(Dart_NativeArguments arguments) { - LOGI("PlayBackground"); - Dart_EnterScope(); - const char* what = GetArgAsString(arguments, 0); - int rtn = PlayBackgroundSound(what); - SetIntReturnValue(arguments, rtn); - Dart_ExitScope(); -} - -void StopBackground(Dart_NativeArguments arguments) { - LOGI("StopBackground"); - Dart_EnterScope(); - StopBackgroundSound(); - Dart_ExitScope(); -} - -void LoadSample(Dart_NativeArguments arguments) { - LOGI("LoadSample"); - Dart_EnterScope(); - const char* what = GetArgAsString(arguments, 0); - int rtn = LoadSoundSample(what); - SetIntReturnValue(arguments, rtn); - Dart_ExitScope(); -} - -void PlaySample(Dart_NativeArguments arguments) { - LOGI("PlaySample"); - Dart_EnterScope(); - const char* what = GetArgAsString(arguments, 0); - int rtn = PlaySoundSample(what); - SetIntReturnValue(arguments, rtn); - Dart_ExitScope(); -} - -// 2D Canvas. - -CanvasContext* display_context = NULL; - -void C2DCreateNativeContext(Dart_NativeArguments arguments) { - LOGI("In C2DCreateNativeContext"); - Dart_EnterScope(); - - int handle = GetArgAsInt(arguments, 0); - int width = GetArgAsInt(arguments, 1); - int height = GetArgAsInt(arguments, 2); - - CanvasContext* rtn = new CanvasContext(handle, width, height); - if (display_context == NULL) { - LOGI("Created display context"); - display_context = rtn; - } - Dart_ExitScope(); - LOGI("Out C2DCreateNativeContext"); -} - -void C2DSetWidth(Dart_NativeArguments arguments) { - LOGI("In C2DSetWidth"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - int width = GetArgAsInt(arguments, 1); - SetIntReturnValue(arguments, Context2D(handle)->setWidth(width)); - Dart_ExitScope(); - LOGI("Out C2DSetWidth"); -} - -void C2DSetHeight(Dart_NativeArguments arguments) { - LOGI("In C2DSetHeight"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - int height = GetArgAsInt(arguments, 1); - SetIntReturnValue(arguments, Context2D(handle)->setHeight(height)); - Dart_ExitScope(); - LOGI("Out C2DSetHeight"); -} - -void C2DSetGlobalAlpha(Dart_NativeArguments arguments) { - LOGI("In C2DSetGlobalAlpha"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - double alpha = GetArgAsDouble(arguments, 1); - alpha = MIN(1.0, MAX(alpha, 0.0)); - Context2D(handle)->setGlobalAlpha(alpha); - SetDoubleReturnValue(arguments, alpha); - Dart_ExitScope(); - LOGI("Out C2DSetGlobalAlpha"); -} - -void C2DSetFillStyle(Dart_NativeArguments arguments) { - LOGI("In C2DSetFillStyle"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - const char* color = GetArgAsString(arguments, 1); - Context2D(handle)->setFillColor(color); - Dart_ExitScope(); - LOGI("Out C2DSetFillStyle"); -} - -void C2DSetFont(Dart_NativeArguments arguments) { - LOGI("In C2DSetFont"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - const char* font = GetArgAsString(arguments, 1); - SetStringReturnValue(arguments, Context2D(handle)->setFont(font)); - Dart_ExitScope(); - LOGI("Out C2DSetFont"); -} - -void C2DSetGlobalCompositeOperation(Dart_NativeArguments arguments) { - LOGI("In C2DSetGlobalCompositeOperation"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - const char* op = GetArgAsString(arguments, 1); - Context2D(handle)->setGlobalCompositeOperation(op); - Dart_ExitScope(); - LOGI("Out C2DSetGlobalCompositeOperation"); -} - -void C2DSetLineCap(Dart_NativeArguments arguments) { - LOGI("In C2DSetLineCap"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - const char* lc = GetArgAsString(arguments, 1); - Context2D(handle)->setLineCap(lc); - Dart_ExitScope(); - LOGI("Out C2DSetLineCap"); -} - -void C2DSetLineJoin(Dart_NativeArguments arguments) { - LOGI("In C2DSetLineJoin"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - const char* lj = GetArgAsString(arguments, 1); - Context2D(handle)->setLineJoin(lj); - Dart_ExitScope(); - LOGI("Out C2DSetLineJoin"); -} - -void C2DSetLineWidth(Dart_NativeArguments arguments) { - LOGI("In C2DSetLineWidth"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - double w = GetArgAsDouble(arguments, 1); - Context2D(handle)->setLineWidth(w); - Dart_ExitScope(); - LOGI("Out C2DSetLineWidth"); -} - -void C2DSetMiterLimit(Dart_NativeArguments arguments) { - LOGI("In C2DSetMiterLimit"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - double w = GetArgAsDouble(arguments, 1); - Context2D(handle)->setMiterLimit(w); - Dart_ExitScope(); - LOGI("Out C2DSetMiterLimit"); -} - -void C2DSetShadowBlur(Dart_NativeArguments arguments) { - LOGI("In C2DSetShadowBlur"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - double blur = GetArgAsDouble(arguments, 1); - Context2D(handle)->setShadowBlur(blur); - Dart_ExitScope(); - LOGI("Out C2DSetShadowBlur"); -} - -void C2DSetShadowColor(Dart_NativeArguments arguments) { - LOGI("In C2DSetShadowColor"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - const char* color = GetArgAsString(arguments, 1); - Context2D(handle)->setShadowColor(color); - Dart_ExitScope(); - LOGI("Out C2DSetShadowColor"); -} - -void C2DSetShadowOffsetX(Dart_NativeArguments arguments) { - LOGI("In C2DSetShadowOffsetX"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - double offset = GetArgAsDouble(arguments, 1); - Context2D(handle)->setShadowOffsetX(offset); - Dart_ExitScope(); - LOGI("Out C2DSetShadowOffsetX"); -} - -void C2DSetShadowOffsetY(Dart_NativeArguments arguments) { - LOGI("In C2DSetShadowOffsetY"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - double offset = GetArgAsDouble(arguments, 1); - Context2D(handle)->setShadowOffsetY(offset); - Dart_ExitScope(); - LOGI("Out C2DSetShadowOffsetY"); -} - -void C2DSetStrokeStyle(Dart_NativeArguments arguments) { - LOGI("In C2DSetStrokeStyle"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - const char* color = GetArgAsString(arguments, 1); - Context2D(handle)->setStrokeColor(color); - Dart_ExitScope(); - LOGI("Out C2DSetStrokeStyle"); -} - -void C2DSetTextAlign(Dart_NativeArguments arguments) { - LOGI("In C2DSetTextAlign"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - const char* align = GetArgAsString(arguments, 1); - SetStringReturnValue(arguments, Context2D(handle)->setTextAlign(align)); - Dart_ExitScope(); - LOGI("Out C2DSetTextAlign"); -} - -void C2DSetTextBaseline(Dart_NativeArguments arguments) { - LOGI("In C2DSetTextBaseline"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - const char* baseline = GetArgAsString(arguments, 1); - SetStringReturnValue(arguments, Context2D(handle)->setTextBaseline(baseline)); - Dart_ExitScope(); - LOGI("Out C2DSetTextBaseline"); -} - -void C2DGetImageSmoothingEnabled(Dart_NativeArguments arguments) { - LOGI("In C2DGetImageSmoothingEnabled"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - SetDoubleReturnValue(arguments, Context2D(handle)->imageSmoothingEnabled()); - Dart_ExitScope(); - LOGI("Out C2DGetImageSmoothingEnabled"); -} - -void C2DArc(Dart_NativeArguments arguments) { - LOGI("In C2DArc"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - double x = GetArgAsDouble(arguments, 1); - double y = GetArgAsDouble(arguments, 2); - double r = GetArgAsDouble(arguments, 3); - double a1 = GetArgAsDouble(arguments, 4); - double a2 = GetArgAsDouble(arguments, 5); - bool anticlockwise = GetArgAsBool(arguments, 6); - Context2D(handle)->Arc(x, y, r, a1, a2, anticlockwise); - Dart_ExitScope(); - LOGI("Out C2DArc"); -} - -void C2DArcTo(Dart_NativeArguments arguments) { - LOGI("In C2DArcTo"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - double x1 = GetArgAsDouble(arguments, 1); - double y1 = GetArgAsDouble(arguments, 2); - double x2 = GetArgAsDouble(arguments, 3); - double y2 = GetArgAsDouble(arguments, 4); - double radius = GetArgAsDouble(arguments, 5); - Context2D(handle)->ArcTo(x1, y1, x2, y2, radius); - Dart_ExitScope(); - LOGI("Out C2DArcTo"); -} - -void C2DBeginPath(Dart_NativeArguments arguments) { - LOGI("In C2DBeginPath"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - Context2D(handle)->BeginPath(); - Dart_ExitScope(); - LOGI("Out C2DBeginPath"); -} - -void C2DBezierCurveTo(Dart_NativeArguments arguments) { - LOGI("In C2DBezierCurveTo"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - double cp1x = GetArgAsDouble(arguments, 1); - double cp1y = GetArgAsDouble(arguments, 2); - double cp2x = GetArgAsDouble(arguments, 3); - double cp2y = GetArgAsDouble(arguments, 4); - double x = GetArgAsDouble(arguments, 5); - double y = GetArgAsDouble(arguments, 6); - Context2D(handle)->BezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y); - Dart_ExitScope(); - LOGI("Out C2DBezierCurveTo"); -} - -void C2DClearRect(Dart_NativeArguments arguments) { - LOGI("In C2DClearRect"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - double left = GetArgAsDouble(arguments, 1); - double top = GetArgAsDouble(arguments, 2); - double width = GetArgAsDouble(arguments, 3); - double height = GetArgAsDouble(arguments, 4); - Context2D(handle)->ClearRect(left, top, width, height); - Dart_ExitScope(); - LOGI("Out C2DClearRect"); -} - -void C2DClip(Dart_NativeArguments arguments) { - LOGI("In C2DClip"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - Context2D(handle)->Clip(); - Dart_ExitScope(); - LOGI("Out C2DClip"); -} - -void C2DClosePath(Dart_NativeArguments arguments) { - LOGI("In C2DClosePath"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - Context2D(handle)->ClosePath(); - Dart_ExitScope(); - LOGI("Out C2DClosePath"); -} - -void C2DCreateImageDataFromDimensions(Dart_NativeArguments arguments) { - LOGI("In C2DCreateImageDataFromDimensions"); - Dart_EnterScope(); - // int handle = GetArgAsInt(arguments, 0); - // double sw = GetArgAsDouble(arguments, 1); - // double sh = GetArgAsDouble(arguments, 2); - // GLubyte* pixels = (GLubyte*)calloc(sw * sh * 4, sizeof(GLubyte)); - // ImageData* imageData = new ImageData(sw, sh, pixels); - // TODO(gram): How do we create a Dart ImageData object from this? - Dart_ExitScope(); - LOGI("Out C2DCreateImageDataFromDimensions"); -} - -void C2DDrawImage(Dart_NativeArguments arguments) { - LOGI("In C2DDrawImage"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - const char* src_url = GetArgAsString(arguments, 1); - int sx = GetArgAsInt(arguments, 2); - int sy = GetArgAsInt(arguments, 3); - bool has_src_dimensions = GetArgAsBool(arguments, 4); - int sw = GetArgAsInt(arguments, 5); - int sh = GetArgAsInt(arguments, 6); - int dx = GetArgAsInt(arguments, 7); - int dy = GetArgAsInt(arguments, 8); - bool has_dst_dimensions = GetArgAsBool(arguments, 9); - int dw = GetArgAsInt(arguments, 10); - int dh = GetArgAsInt(arguments, 11); - Context2D(handle)->DrawImage(src_url, - sx, sy, has_src_dimensions, sw, sh, - dx, dy, has_dst_dimensions, dw, dh); - Dart_ExitScope(); - LOGI("Out C2DDrawImage"); -} - -void C2DFill(Dart_NativeArguments arguments) { - LOGI("In C2DFill"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - Context2D(handle)->Fill(); - Dart_ExitScope(); - LOGI("Out C2DFill"); -} - -void C2DFillRect(Dart_NativeArguments arguments) { - LOGI("In C2DFillRect"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - double left = GetArgAsDouble(arguments, 1); - double top = GetArgAsDouble(arguments, 2); - double width = GetArgAsDouble(arguments, 3); - double height = GetArgAsDouble(arguments, 4); - Context2D(handle)->FillRect(left, top, width, height); - Dart_ExitScope(); - LOGI("Out C2DFillRect"); -} - -void C2DFillText(Dart_NativeArguments arguments) { - LOGI("In C2DFillText"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - const char* text = GetArgAsString(arguments, 1); - double x = GetArgAsDouble(arguments, 2); - double y = GetArgAsDouble(arguments, 3); - double maxWidth = GetArgAsDouble(arguments, 4); - Context2D(handle)->FillText(text, x, y, maxWidth); - Dart_ExitScope(); - LOGI("Out C2DFillText"); -} - -void C2DGetImageData(Dart_NativeArguments arguments) { - LOGI("In C2DGetImageData"); - Dart_EnterScope(); - // TODO(gram): Complete this. - // int handle = GetArgAsInt(arguments, 0); - // double sx = GetArgAsDouble(arguments, 1); - // double sy = GetArgAsDouble(arguments, 2); - // double sw = GetArgAsDouble(arguments, 3); - // double sh = GetArgAsDouble(arguments, 4); - // ... = Context2D(handle)->GetImageData(text, x, y, maxWidth); - Dart_ExitScope(); - LOGI("Out C2DGetImageData"); -} - -void C2DLineTo(Dart_NativeArguments arguments) { - LOGI("In C2DLineTo"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - double x = GetArgAsDouble(arguments, 1); - double y = GetArgAsDouble(arguments, 2); - Context2D(handle)->LineTo(x, y); - Dart_ExitScope(); - LOGI("Out C2DLineTo"); -} - -void C2DMeasureText(Dart_NativeArguments arguments) { - LOGI("In C2DMeasureText"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - const char* text = GetArgAsString(arguments, 1); - float width = Context2D(handle)->MeasureText(text); - SetDoubleReturnValue(arguments, width); - Dart_ExitScope(); - LOGI("Out C2DMeasureText"); -} - -void C2DMoveTo(Dart_NativeArguments arguments) { - LOGI("IN C2DMoveTo"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - double x = GetArgAsDouble(arguments, 1); - double y = GetArgAsDouble(arguments, 2); - Context2D(handle)->MoveTo(x, y); - Dart_ExitScope(); - LOGI("Out C2DMoveTo"); -} - -void C2DPutImageData(Dart_NativeArguments arguments) { - LOGI("IN C2DPutImageData"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - // Get object arguments 2 - // BindingImageData* imageData = GetArgAsObject(arguments, 1); - double dx = GetArgAsDouble(arguments, 2); - double dy = GetArgAsDouble(arguments, 3); - Context2D(handle)->PutImageData(NULL, dx, dy); - Dart_ExitScope(); - LOGI("Out C2DPutImageData"); -} - -void C2DQuadraticCurveTo(Dart_NativeArguments arguments) { - LOGI("In C2DQuadraticCurveTo"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - double cpx = GetArgAsDouble(arguments, 1); - double cpy = GetArgAsDouble(arguments, 2); - double x = GetArgAsDouble(arguments, 3); - double y = GetArgAsDouble(arguments, 4); - Context2D(handle)->QuadraticCurveTo(cpx, cpy, x, y); - Dart_ExitScope(); - LOGI("Out C2DQuadraticCurveTo"); -} - -void C2DRect(Dart_NativeArguments arguments) { - LOGI("In C2DRect"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - double x = GetArgAsDouble(arguments, 1); - double y = GetArgAsDouble(arguments, 2); - double w = GetArgAsDouble(arguments, 3); - double h = GetArgAsDouble(arguments, 4); - Context2D(handle)->Rect(x, y, w, h); - Dart_ExitScope(); - LOGI("Out C2DRect"); -} - -void C2DRestore(Dart_NativeArguments arguments) { - LOGI("In C2DRestore"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - CanvasContext* context = Context2D(handle); - context->Restore(); - Dart_ExitScope(); - LOGI("Out C2DRestore"); -} - -void C2DRotate(Dart_NativeArguments arguments) { - LOGI("In C2DRotate"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - double a = GetArgAsDouble(arguments, 1); - Context2D(handle)->Rotate(a); - Dart_ExitScope(); - LOGI("Out C2DRotate"); -} - -void C2DSave(Dart_NativeArguments arguments) { - LOGI("In C2DSave"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - Context2D(handle)->Save(); - Dart_ExitScope(); - LOGI("Out C2DSave"); -} - -void C2DScale(Dart_NativeArguments arguments) { - LOGI("In C2DScale"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - double sx = GetArgAsDouble(arguments, 1); - double sy = GetArgAsDouble(arguments, 2); - Context2D(handle)->Scale(sx, sy); - Dart_ExitScope(); - LOGI("Out C2DScale"); -} - -void C2DSetLineDash(Dart_NativeArguments arguments) { - LOGI("In C2DSetLineDash"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - int len; - float* dash = static_cast<float*>(GetArgsAsFloatList(arguments, 1, &len)); - if (dash != NULL) { - Context2D(handle)->setLineDash(dash, len); - delete[] dash; - } - Dart_ExitScope(); - LOGI("Out C2DSetLineDash"); -} - -void C2DSetLineDashOffset(Dart_NativeArguments arguments) { - LOGI("In C2DSetLineDashOffset"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - double offset = GetArgAsDouble(arguments, 1); - Context2D(handle)->setLineDashOffset(offset); - Dart_ExitScope(); - LOGI("Out C2DSetLineDashOffset"); -} - -void C2DSetTransform(Dart_NativeArguments arguments) { - LOGI("In C2DSetTransform"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - double m11 = GetArgAsDouble(arguments, 1); - double m12 = GetArgAsDouble(arguments, 2); - double m21 = GetArgAsDouble(arguments, 3); - double m22 = GetArgAsDouble(arguments, 4); - double dx = GetArgAsDouble(arguments, 5); - double dy = GetArgAsDouble(arguments, 6); - Context2D(handle)->setTransform(m11, m12, m21, m22, dx, dy); - Dart_ExitScope(); - LOGI("Out C2DSetTransform"); -} - -void C2DStroke(Dart_NativeArguments arguments) { - LOGI("In C2DStroke"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - Context2D(handle)->Stroke(); - Dart_ExitScope(); - LOGI("Out C2DStroke"); -} - -void C2DStrokeRect(Dart_NativeArguments arguments) { - LOGI("In C2DStrokeRect"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - double left = GetArgAsDouble(arguments, 1); - double top = GetArgAsDouble(arguments, 2); - double width = GetArgAsDouble(arguments, 3); - double height = GetArgAsDouble(arguments, 4); - Context2D(handle)->StrokeRect(left, top, width, height); - Dart_ExitScope(); - LOGI("Out C2DStrokeRect"); -} - -void C2DStrokeText(Dart_NativeArguments arguments) { - LOGI("In C2DStrokeText"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - const char* text = GetArgAsString(arguments, 1); - double x = GetArgAsDouble(arguments, 2); - double y = GetArgAsDouble(arguments, 3); - double maxWidth = GetArgAsDouble(arguments, 4); - Context2D(handle)->StrokeText(text, x, y, maxWidth); - Dart_ExitScope(); - LOGI("Out C2DStrokeText"); -} - -void C2DTransform(Dart_NativeArguments arguments) { - LOGI("In C2DTransform"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - double m11 = GetArgAsDouble(arguments, 1); - double m12 = GetArgAsDouble(arguments, 2); - double m21 = GetArgAsDouble(arguments, 3); - double m22 = GetArgAsDouble(arguments, 4); - double dx = GetArgAsDouble(arguments, 5); - double dy = GetArgAsDouble(arguments, 6); - Context2D(handle)->Transform(m11, m12, m21, m22, dx, dy); - Dart_ExitScope(); - LOGI("Out C2DTransform"); -} - -void C2DTranslate(Dart_NativeArguments arguments) { - LOGI("In C2DTranslate"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - double x = GetArgAsDouble(arguments, 1); - double y = GetArgAsDouble(arguments, 2); - Context2D(handle)->Translate(x, y); - Dart_ExitScope(); - LOGI("Out C2DTranslate"); -} - -void C2DSetFillGradient(Dart_NativeArguments arguments) { - LOGI("In C2DSetFillGradient"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - bool is_radial = GetArgAsBool(arguments, 1); - double x0 = GetArgAsDouble(arguments, 2); - double y0 = GetArgAsDouble(arguments, 3); - double r0 = GetArgAsDouble(arguments, 4); - double x1 = GetArgAsDouble(arguments, 5); - double y1 = GetArgAsDouble(arguments, 6); - double r1 = GetArgAsDouble(arguments, 7); - int num_positions, num_colors; - float* positions = GetArgsAsFloatList(arguments, 8, &num_positions); - char** colors = GetArgsAsStringList(arguments, 9, &num_colors); - Context2D(handle)->SetFillGradient(is_radial, x0, y0, r0, x1, y1, r1, - num_positions, positions, colors); - Dart_ExitScope(); - LOGI("Out C2DSetFillGradient"); -} - -void C2DSetStrokeGradient(Dart_NativeArguments arguments) { - LOGI("In C2DSetStrokeGradient"); - Dart_EnterScope(); - int handle = GetArgAsInt(arguments, 0); - bool is_radial = GetArgAsBool(arguments, 1); - double x0 = GetArgAsDouble(arguments, 2); - double y0 = GetArgAsDouble(arguments, 3); - double r0 = GetArgAsDouble(arguments, 4); - double x1 = GetArgAsDouble(arguments, 5); - double y1 = GetArgAsDouble(arguments, 6); - double r1 = GetArgAsDouble(arguments, 7); - int num_positions, num_colors; - float* positions = GetArgsAsFloatList(arguments, 8, &num_positions); - char** colors = GetArgsAsStringList(arguments, 9, &num_colors); - Context2D(handle)->SetStrokeGradient(is_radial, x0, y0, r0, x1, y1, r1, - num_positions, positions, colors); - Dart_ExitScope(); - LOGI("Out C2DSetStrokeGradient"); -} - -void C2DGetImageWidth(Dart_NativeArguments arguments) { - LOGI("In C2DGetImageWidth"); - Dart_EnterScope(); - const char* src_url = GetArgAsString(arguments, 0); - int w = ImageCache::GetWidth(src_url); - SetIntReturnValue(arguments, w); - Dart_ExitScope(); - LOGI("Out C2DGetImageWidth"); -} - -void C2DGetImageHeight(Dart_NativeArguments arguments) { - LOGI("In C2DGetImageHeight"); - Dart_EnterScope(); - const char* src_url = GetArgAsString(arguments, 0); - int h = ImageCache::GetHeight(src_url); - SetIntReturnValue(arguments, h); - Dart_ExitScope(); - LOGI("Out C2DGetImageHeight"); -} - -struct FunctionLookup { - const char* name; - Dart_NativeFunction function; -}; - -FunctionLookup function_list[] = { - {"Log", Log}, - {"LogError", LogError}, - {"SystemRand", SystemRand}, - {"SystemSrand", SystemSrand}, - {"SwapBuffers", SwapBuffers}, - {"GetDeviceScreenWidth", GetDeviceScreenWidth}, - {"GetDeviceScreenHeight", GetDeviceScreenHeight}, - {"GLAttachShader", GLAttachShader}, - {"GLBindBuffer", GLBindBuffer}, - {"GLBufferData", GLBufferData}, - {"GLClear", GLClear}, - {"GLClearColor", GLClearColor}, - {"GLClearDepth", GLClearDepth}, - {"GLCompileShader", GLCompileShader}, - {"GLCreateBuffer", GLCreateBuffer}, - {"GLCreateProgram", GLCreateProgram}, - {"GLCreateShader", GLCreateShader}, - {"GLDrawArrays", GLDrawArrays}, - {"GLEnableVertexAttribArray", GLEnableVertexAttribArray}, - {"GLGetAttribLocation", GLGetAttribLocation}, - {"GLGetError", GLGetError}, - {"GLGetProgramParameter", GLGetProgramParameter}, - {"GLGetShaderParameter", GLGetShaderParameter}, - {"GLGetUniformLocation", GLGetUniformLocation}, - {"GLLinkProgram", GLLinkProgram}, - {"GLShaderSource", GLShaderSource}, - {"GLUniform1f", GLUniform1f}, - {"GLUniform2f", GLUniform2f}, - {"GLUniform3f", GLUniform3f}, - {"GLUniform4f", GLUniform4f}, - {"GLUniform1i", GLUniform1i}, - {"GLUniform2i", GLUniform2i}, - {"GLUniform3i", GLUniform3i}, - {"GLUniform4i", GLUniform4i}, - {"GLUniform1fv", GLUniform1fv}, - {"GLUniform2fv", GLUniform2fv}, - {"GLUniform3fv", GLUniform3fv}, - {"GLUniform4fv", GLUniform4fv}, - {"GLUniform1iv", GLUniform1iv}, - {"GLUniform2iv", GLUniform2iv}, - {"GLUniform3iv", GLUniform3iv}, - {"GLUniform4iv", GLUniform4iv}, - {"GLUseProgram", GLUseProgram}, - {"GLVertexAttribPointer", GLVertexAttribPointer}, - {"GLViewport", GLViewport}, - {"GLArrayBuffer", GLArrayBuffer}, - {"GLColorBufferBit", GLColorBufferBit}, - {"GLCompileStatus", GLCompileStatus}, - {"GLDeleteStatus", GLDeleteStatus}, - {"GLDepthBufferBit", GLDepthBufferBit}, - {"GLFloat", GLFloat}, - {"GLFragmentShader", GLFragmentShader}, - {"GLLinkStatus", GLLinkStatus}, - {"GLTriangleStrip", GLTriangleStrip}, - {"GLTriangles", GLTriangles}, - {"GLTrue", GLTrue}, - {"GLStaticDraw", GLStaticDraw}, - {"GLValidateStatus", GLValidateStatus}, - {"GLVertexShader", GLVertexShader}, - {"GLGetShaderInfoLog", GLGetShaderInfoLog}, - {"GLGetProgramInfoLog", GLGetProgramInfoLog}, - {"RandomArray_ServicePort", RandomArrayServicePort}, - - // Audio support. - {"PlayBackground", PlayBackground}, - {"StopBackground", StopBackground}, - {"LoadSample", LoadSample}, - {"PlaySample", PlaySample}, - - // 2D Support - - { "C2DCreateNativeContext", C2DCreateNativeContext}, - - // Property getters/setters. - - { "C2DSetWidth", C2DSetWidth}, - { "C2DSetHeight", C2DSetHeight}, - { "C2DSetGlobalAlpha", C2DSetGlobalAlpha}, - { "C2DSetFillStyle", C2DSetFillStyle}, - { "C2DSetFont", C2DSetFont}, - { "C2DSetGlobalCompositeOperation", C2DSetGlobalCompositeOperation}, - { "C2DSetLineCap", C2DSetLineCap}, - { "C2DSetLineJoin", C2DSetLineJoin}, - { "C2DSetLineWidth", C2DSetLineWidth}, - { "C2DSetMiterLimit", C2DSetMiterLimit}, - { "C2DSetShadowBlur", C2DSetShadowBlur}, - { "C2DSetShadowColor", C2DSetShadowColor}, - { "C2DSetShadowOffsetX", C2DSetShadowOffsetX}, - { "C2DSetShadowOffsetY", C2DSetShadowOffsetY}, - { "C2DSetStrokeStyle", C2DSetStrokeStyle}, - { "C2DSetTextAlign", C2DSetTextAlign}, - { "C2DSetTextBaseline", C2DSetTextBaseline}, - { "C2DGetImageSmoothingEnabled", C2DGetImageSmoothingEnabled}, - - // Methods. - { "C2DArc", C2DArc}, - { "C2DArcTo", C2DArcTo}, - { "C2DBeginPath", C2DBeginPath}, - { "C2DBezierCurveTo", C2DBezierCurveTo}, - { "C2DClearRect", C2DClearRect}, - { "C2DClip", C2DClip}, - { "C2DClosePath", C2DClosePath}, - { "C2DCreateImageDataFromDimensions", C2DCreateImageDataFromDimensions}, - { "C2DDrawImage", C2DDrawImage}, - { "C2DFill", C2DFill}, - { "C2DFillRect", C2DFillRect}, - { "C2DFillText", C2DFillText}, - { "C2DGetImageData", C2DGetImageData}, - { "C2DLineTo", C2DLineTo}, - { "C2DMeasureText", C2DMeasureText}, - { "C2DMoveTo", C2DMoveTo}, - { "C2DPutImageData", C2DPutImageData}, - { "C2DQuadraticCurveTo", C2DQuadraticCurveTo}, - { "C2DRect", C2DRect}, - { "C2DRestore", C2DRestore}, - { "C2DRotate", C2DRotate}, - { "C2DSave", C2DSave}, - { "C2DScale", C2DScale}, - { "C2DSetLineDash", C2DSetLineDash}, - { "C2DSetLineDashOffset", C2DSetLineDashOffset}, - { "C2DSetTransform", C2DSetTransform}, - { "C2DStroke", C2DStroke}, - { "C2DStrokeRect", C2DStrokeRect}, - { "C2DStrokeText", C2DStrokeText}, - { "C2DTransform", C2DTransform}, - { "C2DTranslate", C2DTranslate}, - { "C2DSetFillGradient", C2DSetFillGradient}, - { "C2DSetStrokeGradient", C2DSetStrokeGradient}, - { "C2DGetImageWidth", C2DGetImageWidth}, - { "C2DGetImageHeight", C2DGetImageHeight}, - - {NULL, NULL}}; - -Dart_NativeFunction ResolveName(Dart_Handle name, int argc) { - if (!Dart_IsString(name)) return NULL; - Dart_NativeFunction result = NULL; - Dart_EnterScope(); - const char* cname; - HandleError(Dart_StringToCString(name, &cname)); - for (int i = 0; function_list[i].name != NULL; ++i) { - if (strcmp(function_list[i].name, cname) == 0) { - result = function_list[i].function; - break; - } - } - Dart_ExitScope(); - return result; -}
diff --git a/runtime/embedders/openglui/common/extension.h b/runtime/embedders/openglui/common/extension.h deleted file mode 100644 index a13413e..0000000 --- a/runtime/embedders/openglui/common/extension.h +++ /dev/null
@@ -1,20 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#ifndef EMBEDDERS_OPENGLUI_COMMON_EXTENSION_H_ -#define EMBEDDERS_OPENGLUI_COMMON_EXTENSION_H_ - -#include "include/dart_api.h" - -Dart_NativeFunction ResolveName(Dart_Handle name, int argc); - -extern int32_t PlayBackgroundSound(const char* path); -extern void StopBackgroundSound(); -extern int32_t LoadSoundSample(const char* path); -extern int32_t PlaySoundSample(const char* path); -extern int32_t Init2DGraphics(); - - -#endif // EMBEDDERS_OPENGLUI_COMMON_EXTENSION_H_ -
diff --git a/runtime/embedders/openglui/common/gl.dart b/runtime/embedders/openglui/common/gl.dart deleted file mode 100644 index c37c80b..0000000 --- a/runtime/embedders/openglui/common/gl.dart +++ /dev/null
@@ -1,1211 +0,0 @@ -// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -library android_extension; -import 'dart:async'; - -// A VERY simplified DOM. - -class BodyElement { - List _nodes; - get nodes => _nodes; - BodyElement() : _nodes = new List(); -} - -// The OpenGLUI "equivalent" of Window. - -typedef void RequestAnimationFrameCallback(num highResTime); - -class Window { - static int _nextId = 0; - List _callbacks; - List _arguments; - - Window._internal() : _callbacks = [], _arguments = []; - - int _scheduleCallback(callback, [argument]) { - _callbacks.add(callback); - _arguments.add(argument); - return _callbacks.length - 1; - } - - int requestAnimationFrame(RequestAnimationFrameCallback callback) { - return _scheduleCallback(callback, - (new DateTime.now()).millisecondsSinceEpoch); - } - - void cancelAnimationFrame(id) { - _callbacks[id] = null; - _arguments[id] = null; - } - - get animationFrame { - // TODO(gram) - return null; - } - - void _dispatch() { - // We clear out the callbacks map before calling any callbacks, - // as they may schedule new callbacks. - var oldcallbacks = _callbacks; - var oldarguments = _arguments; - _callbacks = []; - _arguments = []; - for (var i = 0; i < oldcallbacks.length; i++) { - if (oldcallbacks[i] != null) { - oldcallbacks[i](oldarguments[i]); - } - } - // We could loop around here to handle any callbacks - // scheduled in processing the prior ones, but then we - // need some other mechanism for trying to get requestAnimationFrame - // callbacks at 60fps. - } - - Map localStorage = {}; // TODO(gram) - Make this persistent. -} - -Window window = new Window._internal(); - -// The OpenGLUI "equivalent" of HtmlDocument. -class Document extends Node { - BodyElement _body; - get body => _body; - Document._internal() : _body = new BodyElement(); -} - -Document document = new Document._internal(); - -// TODO(gram): make private and call from within library context. -update_() { - log("in update"); - window._dispatch(); -} - -// Event handling. This is very kludgy for now, especially the -// bare-bones Stream stuff! - -typedef void EventListener(Event event); - -class EventTarget { - static Map<EventTarget, Map<String, List<EventListener>>> - _listeners = new Map(); - - static get listeners => _listeners; - - bool dispatchEvent(Event event) { - var rtn = false; - if (!_listeners.containsKey(this)) return false; - var listeners = _listeners[this]; - if (!listeners.containsKey(event.type)) return false; - var eventListeners = listeners[event.type]; - for (var eventListener in eventListeners) { - if (eventListener != null) { - eventListener(event); - rtn = true; - } - } - return rtn; - } - - void addListener(String eventType, EventListener handler) { - if (!_listeners.containsKey(this)) { - _listeners[this] = new Map(); - } - var listeners = _listeners[this]; - if (!listeners.containsKey(eventType)) { - listeners[eventType] = new List(); - } - var event_listeners = listeners[eventType]; - for (var i = 0; i < event_listeners.length; i++) { - if (event_listeners[i] == null) { - event_listeners[i] = handler; - return; - } - } - event_listeners.add(handler); - } - - void removeListener(String eventType, EventListener handler) { - if (_listeners.containsKey(this)) { - var listeners = _listeners[this]; - if (listeners.containsKey(eventType)) { - var event_listeners = listeners[eventType]; - for (var i = 0; i < event_listeners.length; i++) { - if (event_listeners[i] == handler) { - event_listeners[i] = null; - break; - } - } - } - } - } -} - -class Event { - final String type; - EventTarget target; - Event(String type) : this.type = type; - preventDefault() {} - stopPropagation() {} -} - -class KeyboardEvent extends Event { - final bool altKey; - final bool ctrlKey; - final bool shiftKey; - final int keyCode; - - KeyboardEvent(String type, int keycode, bool alt, bool ctrl, bool shift) - : super(type), - keyCode = keycode, - altKey = alt, - ctrlKey = ctrl, - shiftKey = shift { - } -} - -class MouseEvent extends Event { - final int screenX, screenY; - final int clientX, clientY; - - MouseEvent(String type, int x, int y) - : super(type), - screenX = x, - screenY = y, - clientX = x, - clientY = y { - } -} - -class _EventStreamSubscription<T extends Event> extends StreamSubscription<T> { - int _pauseCount = 0; - EventTarget _target; - final String _eventType; - var _onData; - - _EventStreamSubscription(this._target, this._eventType, this._onData) { - _tryResume(); - } - - void cancel() { - if (_canceled) { - throw new StateError("Subscription has been canceled."); - } - - _unlisten(); - // Clear out the target to indicate this is complete. - _target = null; - _onData = null; - } - - bool get _canceled => _target == null; - - void onData(void handleData(T event)) { - if (_canceled) { - throw new StateError("Subscription has been canceled."); - } - // Remove current event listener. - _unlisten(); - - _onData = handleData - _tryResume(); - } - - /// Has no effect. - void onError(void handleError(Object error)) {} - - /// Has no effect. - void onDone(void handleDone()) {} - - void pause([Future resumeSignal]) { - if (_canceled) { - throw new StateError("Subscription has been canceled."); - } - ++_pauseCount; - _unlisten(); - - if (resumeSignal != null) { - resumeSignal.whenComplete(resume); - } - } - - bool get _paused => _pauseCount > 0; - - void resume() { - if (_canceled) { - throw new StateError("Subscription has been canceled."); - } - if (!_paused) { - throw new StateError("Subscription is not paused."); - } - --_pauseCount; - _tryResume(); - } - - void _tryResume() { - if (_onData != null && !_paused) { - _target.addListener(_eventType, _onData); - } - } - - void _unlisten() { - if (_onData != null) { - _target.removeListener(_eventType, _onData); - } - } - - Future asFuture([var futureValue]) { - // We just need a future that will never succeed or fail. - Completer completer = new Completer(); - return completer.future; - } -} - -class _EventStream<T extends Event> extends Stream<T> { - final Object _target; - final String _eventType; - - _EventStream(this._target, this._eventType); - - // DOM events are inherently multi-subscribers. - Stream<T> asBroadcastStream() => this; - bool get isBroadcast => true; - - StreamSubscription<T> listen(void onData(T event), - { void onError(Object error), - void onDone(), - bool cancelOnError}) { - - return new _EventStreamSubscription<T>( - this._target, this._eventType, onData); - } -} - -class Node extends EventTarget { - Stream<KeyboardEvent> get onKeyDown => new _EventStream(this, 'keydown'); - Stream<KeyboardEvent> get onKeyUp => new _EventStream(this, 'keyup'); - Stream<MouseEvent> get onMouseDown => new _EventStream(this, 'mousedown'); - Stream<MouseEvent> get onMouseMove => new _EventStream(this, 'mousemove'); - Stream<MouseEvent> get onMouseUp => new _EventStream(this, 'mouseup'); -} - -// TODO(gram): If we support more than one on-screen canvas, we will -// need to filter dispatched mouse and key events by the target Node -// with more granularity; right now we just iterate through DOM nodes -// until we find one that handles the event. -_dispatchEvent(Event event) { - assert(document.body.nodes.length <= 1); - for (var target in document.body.nodes) { - event.target = target; - if (target.dispatchEvent(event)) { - return; - } - } - document.dispatchEvent(event); -} - -_dispatchKeyEvent(String type, int keyCode, bool alt, bool ctrl, bool shift) { - _dispatchEvent(new KeyboardEvent(type, keyCode, alt, ctrl, shift)); -} - -_dispatchMouseEvent(String type, double x, double y) { - _dispatchEvent(new MouseEvent(type, x.toInt(), y.toInt())); -} - -// These next few are called by vmglue.cc. -onKeyDown_(int when, int keyCode, bool alt, bool ctrl, bool shift, int repeat) - => _dispatchKeyEvent('keydown', keyCode, alt, ctrl, shift); - -onKeyUp_(int when, int keyCode, bool alt, bool ctrl, bool shift, int repeat) => - _dispatchKeyEvent('keyup', keyCode, alt, ctrl, shift); - -onMouseDown_(int when, double x, double y) => - _dispatchMouseEvent('mousedown', x, y); - -onMouseMove_(int when, double x, double y) => - _dispatchMouseEvent('mousemove', x, y); - -onMouseUp_(int when, double x, double y) => - _dispatchMouseEvent('mouseup', x, y); - -class CanvasElement extends Node { - int height; - int width; - - CanvasRenderingContext2D _context2d; - WebGLRenderingContext _context3d; - - // For use with drawImage, we want to support a src property - // like ImageElement, which maps to the context handle in native - // code. - get src => "context2d://${_context2d.handle}"; - - CanvasElement({int width, int height}) - : super() { - this.width = (width == null) ? getDeviceScreenWidth() : width; - this.height = (height == null) ? getDeviceScreenHeight() : height; - getContext('2d'); - } - - CanvasRenderingContext getContext(String contextId) { - if (contextId == "2d") { - if (_context2d == null) { - _context2d = new CanvasRenderingContext2D(this, width, height); - } - return _context2d; - } else if (contextId == "webgl" || - contextId == "experimental-webgl") { - if (_context3d == null) { - _context3d = new WebGLRenderingContext(this); - } - return _context3d; - } - } - - String toDataUrl(String type) { - // This needs to take the contents of the underlying - // canvas painted by the 2d context, give that a unique - // URL, and return that. The canvas element should be - // reuable afterwards without destroying the previously - // rendered data associated with this URL. - assert(_context2d != null); - var rtn = src; - _context2d = null; - return rtn; - } -} - -class CanvasRenderingContext { - final CanvasElement canvas; - - CanvasRenderingContext(this.canvas); -} - -class AudioElement { - double volume; - String _src; - get src => _src; - set src(String v) { - _src = v; - _loadSample(v); - } - - AudioElement([this._src]); - void play() { - _playSample(_src); - } -} - -// The simplest way to call native code: top-level functions. -int systemRand() native "SystemRand"; -void systemSrand(int seed) native "SystemSrand"; -void log(String what) native "Log"; - -int getDeviceScreenWidth() native "GetDeviceScreenWidth"; -int getDeviceScreenHeight() native "GetDeviceScreenHeight"; - -// EGL functions. -void glSwapBuffers() native "SwapBuffers"; - -// GL functions. -void glAttachShader(int program, int shader) native "GLAttachShader"; -void glBindBuffer(int target, int buffer) native "GLBindBuffer"; -void glBufferData(int target, List data, int usage) native "GLBufferData"; -void glClearColor(num r, num g, num b, num alpha) native "GLClearColor"; -void glClearDepth(num depth) native "GLClearDepth"; -void glClear(int mask) native "GLClear"; -void glCompileShader(int shader) native "GLCompileShader"; -int glCreateBuffer() native "GLCreateBuffer"; -int glCreateProgram() native "GLCreateProgram"; -int glCreateShader(int shaderType) native "GLCreateShader"; -void glDrawArrays(int mode, int first, int count) native "GLDrawArrays"; -void glEnableVertexAttribArray(int index) native "GLEnableVertexAttribArray"; -int glGetAttribLocation(int program, String name) native "GLGetAttribLocation"; -int glGetError() native "GLGetError"; -int glGetProgramParameter(int program, int param) - native "GLGetProgramParameter"; -int glGetShaderParameter(int shader, int param) native "GLGetShaderParameter"; -int glGetUniformLocation(int program, String name) - native "GLGetUniformLocation"; -void glLinkProgram(int program) native "GLLinkProgram"; -void glShaderSource(int shader, String source) native "GLShaderSource"; -void glUniform1f(int location, double v0) native "GLUniform1f"; -void glUniform2f(int location, double v0, double v1) native "GLUniform2f"; -void glUniform3f(int location, double v0, double v1, double v2) - native "GLUniform3f"; -void glUniform4f(int location, double v0, double v1, double v2, double v3) - native "GLUniform4f"; -void glUniform1i(int location, int v0) native "GLUniform1i"; -void glUniform2i(int location, int v0, int v1) native "GLUniform2i"; -void glUniform3i(int location, int v0, int v1, int v2) native "GLUniform3i"; -void glUniform4i(int location, int v0, int v1, int v2, int v3) - native "GLUniform4i"; -void glUniform1fv(int location, List values) native "GLUniform1fv"; -void glUniform2fv(int location, List values) native "GLUniform2fv"; -void glUniform3fv(int location, List values) native "GLUniform3fv"; -void glUniform4fv(int location, List values) native "GLUniform4fv"; -void glUniform1iv(int location, List values) native "GLUniform1iv"; -void glUniform2iv(int location, List values) native "GLUniform2iv"; -void glUniform3iv(int location, List values) native "GLUniform3iv"; -void glUniform4iv(int location, List values) native "GLUniform4iv"; -void glUseProgram(int program) native "GLUseProgram"; -void glVertexAttribPointer(int index, int size, int type, bool normalized, - int stride, int pointer) native "GLVertexAttribPointer"; -void glViewport(int x, int y, int width, int height) native "GLViewport"; - -int glArrayBuffer() native "GLArrayBuffer"; -int glColorBufferBit() native "GLColorBufferBit"; -int glCompileStatus() native "GLCompileStatus"; -int glDeleteStatus() native "GLDeleteStatus"; -int glDepthBufferBit() native "GLDepthBufferBit"; -int glFloat() native "GLFloat"; -int glFragmentShader() native "GLFragmentShader"; -int glLinkStatus() native "GLLinkStatus"; -int glStaticDraw() native "GLStaticDraw"; -int glTriangleStrip() native "GLTriangleStrip"; -int glTriangles() native "GLTriangles"; -int glTrue() native "GLTrue"; -int glValidateStatus() native "GLValidateStatus"; -int glVertexShader() native "GLVertexShader"; - -String glGetShaderInfoLog(int shader) native "GLGetShaderInfoLog"; -String glGetProgramInfoLog(int program) native "GLGetProgramInfoLog"; - -class WebGLRenderingContext extends CanvasRenderingContext { - WebGLRenderingContext(canvas) : super(canvas); - - static get ARRAY_BUFFER => glArrayBuffer(); - static get COLOR_BUFFER_BIT => glColorBufferBit(); - static get COMPILE_STATUS => glCompileStatus(); - static get DELETE_STATUS => glDeleteStatus(); - static get DEPTH_BUFFER_BIT => glDepthBufferBit(); - static get FLOAT => glFloat(); - static get FRAGMENT_SHADER => glFragmentShader(); - static get LINK_STATUS => glLinkStatus(); - static get STATIC_DRAW => glStaticDraw(); - static get TRUE => glTrue(); - static get TRIANGLE_STRIP => glTriangleStrip(); - static get TRIANGLES => glTriangles(); - static get VALIDATE_STATUS => glValidateStatus(); - static get VERTEX_SHADER => glVertexShader(); - - attachShader(program, shader) => glAttachShader(program, shader); - bindBuffer(target, buffer) => glBindBuffer(target, buffer); - bufferData(target, data, usage) => glBufferData(target, data, usage); - clearColor(r, g, b, alpha) => glClearColor(r, g, b, alpha); - clearDepth(depth) => glClearDepth(depth); - clear(mask) => glClear(mask); - compileShader(shader) => glCompileShader(shader); - createBuffer() => glCreateBuffer(); - createProgram() => glCreateProgram(); - createShader(shaderType) => glCreateShader(shaderType); - drawArrays(mode, first, count) => glDrawArrays(mode, first, count); - enableVertexAttribArray(index) => glEnableVertexAttribArray(index); - getAttribLocation(program, name) => glGetAttribLocation(program, name); - getError() => glGetError(); - getProgramParameter(program, name) { - var rtn = glGetProgramParameter(program, name); - if (name == DELETE_STATUS || - name == LINK_STATUS || - name == VALIDATE_STATUS) { - return (rtn == 0) ? false : true; - } - return rtn; - } - getShaderParameter(shader, name) { - var rtn = glGetShaderParameter(shader, name); - if (name == DELETE_STATUS || name == COMPILE_STATUS) { - return (rtn == 0) ? false : true; - } - return rtn; - } - getUniformLocation(program, name) => glGetUniformLocation(program, name); - linkProgram(program) => glLinkProgram(program); - shaderSource(shader, source) => glShaderSource(shader, source); - uniform1f(location, v0) => glUniform1f(location, v0); - uniform2f(location, v0, v1) => glUniform2f(location, v0, v1); - uniform3f(location, v0, v1, v2) => glUniform3f(location, v0, v1, v2); - uniform4f(location, v0, v1, v2, v3) => glUniform4f(location, v0, v1, v2, v3); - uniform1i(location, v0) => glUniform1i(location, v0); - uniform2i(location, v0, v1) => glUniform2i(location, v0, v1); - uniform3i(location, v0, v1, v2) => glUniform3i(location, v0, v1, v2); - uniform4i(location, v0, v1, v2, v3) => glUniform4i(location, v0, v1, v2, v3); - uniform1fv(location, values) => glUniform1fv(location, values); - uniform2fv(location, values) => glUniform2fv(location, values); - uniform3fv(location, values) => glUniform3fv(location, values); - uniform4fv(location, values) => glUniform4fv(location, values); - uniform1iv(location, values) => glUniform1iv(location, values); - uniform2iv(location, values) => glUniform2iv(location, values); - uniform3iv(location, values) => glUniform3iv(location, values); - uniform4iv(location, values) => glUniform4iv(location, values); - useProgram(program) => glUseProgram(program); - vertexAttribPointer(index, size, type, normalized, stride, pointer) => - glVertexAttribPointer(index, size, type, normalized, stride, pointer); - viewport(x, y, width, height) => glViewport(x, y, width, height); - getShaderInfoLog(shader) => glGetShaderInfoLog(shader); - getProgramInfoLog(program) => glGetProgramInfoLog(program); - - // TODO(vsm): Kill. - noSuchMethod(invocation) { - throw new Exception('Unimplemented ${invocation.memberName}'); - } -} - -//------------------------------------------------------------------ -// Simple audio support. - -void playBackground(String path) native "PlayBackground"; -void stopBackground() native "StopBackground"; - -//------------------------------------------------------------------- -// Set up print(). - -get _printClosure => (s) { - try { - log(s); - } catch (_) { - throw(s); - } -}; - -//------------------------------------------------------------------ -// Temp hack for compat with WebGL. - -class Float32Array extends List<double> { - Float32Array.fromList(List a) { - addAll(a); - } -} - -//------------------------------------------------------------------ -// 2D canvas support - -int _SetWidth(int handle, int width) - native "C2DSetWidth"; -int _SetHeight(int handle, int height) - native "C2DSetHeight"; - -double _SetGlobalAlpha(int handle, double globalAlpha) - native "C2DSetGlobalAlpha"; -void _SetFillStyle(int handle, fs) - native "C2DSetFillStyle"; -String _SetFont(int handle, String font) - native "C2DSetFont"; -void _SetGlobalCompositeOperation(int handle, String op) - native "C2DSetGlobalCompositeOperation"; -_SetLineCap(int handle, String lc) - native "C2DSetLineCap"; -_SetLineJoin(int handle, String lj) - native "C2DSetLineJoin"; -_SetLineWidth(int handle, double w) - native "C2DSetLineWidth"; -_SetMiterLimit(int handle, double limit) - native "C2DSetMiterLimit"; -_SetShadowBlur(int handle, double blur) - native "C2DSetShadowBlur"; -_SetShadowColor(int handle, String color) - native "C2DSetShadowColor"; -_SetShadowOffsetX(int handle, double offset) - native "C2DSetShadowOffsetX"; -_SetShadowOffsetY(int handle, double offset) - native "C2DSetShadowOffsetY"; -void _SetStrokeStyle(int handle, ss) - native "C2DSetStrokeStyle"; -String _SetTextAlign(int handle, String align) - native "C2DSetTextAlign"; -String _SetTextBaseline(int handle, String baseline) - native "C2DSetTextBaseline"; -_GetBackingStorePixelRatio(int handle) - native "C2DGetBackingStorePixelRatio"; -void _SetImageSmoothingEnabled(int handle, bool ise) - native "C2DSetImageSmoothingEnabled"; -void _SetLineDash(int handle, List v) - native "C2DSetLineDash"; -_SetLineDashOffset(int handle, int v) - native "C2DSetLineDashOffset"; -void _Arc(int handle, double x, double y, double radius, - double startAngle, double endAngle, [bool anticlockwise = false]) - native "C2DArc"; -void _ArcTo(int handle, double x1, double y1, - double x2, double y2, double radius) - native "C2DArcTo"; -void _ArcTo2(int handle, double x1, double y1, - double x2, double y2, double radiusX, - double radiusY, double rotation) - native "C2DArcTo2"; -void _BeginPath(int handle) - native "C2DBeginPath"; -void _BezierCurveTo(int handle, double cp1x, double cp1y, - double cp2x, double cp2y, double x, double y) - native "C2DBezierCurveTo"; -void _ClearRect(int handle, double x, double y, double w, double h) - native "C2DClearRect"; -void _Clip(int handle) - native "C2DClip"; -void _ClosePath(int handle) - native "C2DClosePath"; -ImageData _CreateImageDataFromDimensions(int handle, num w, num h) - native "C2DCreateImageDataFromDimensions"; -void _DrawImage(int handle, String src_url, - int sx, int sy, - bool has_src_dimensions, int sw, int sh, - int dx, int dy, - bool has_dst_dimensions, int dw, int dh) - native "C2DDrawImage"; -void _Fill(int handle) - native "C2DFill"; -void _FillRect(int handle, double x, double y, double w, double h) - native "C2DFillRect"; -void _FillText(int handle, String text, double x, double y, double maxWidth) - native "C2DFillText"; -ImageData _GetImageData(num sx, num sy, num sw, num sh) - native "C2DGetImageData"; -void _LineTo(int handle, double x, double y) - native "C2DLineTo"; -double _MeasureText(int handle, String text) - native "C2DMeasureText"; -void _MoveTo(int handle, double x, double y) - native "C2DMoveTo"; -void _PutImageData(int handle, ImageData imagedata, double dx, double dy) - native "C2DPutImageData"; -void _QuadraticCurveTo(int handle, double cpx, double cpy, - double x, double y) - native "C2DQuadraticCurveTo"; -void _Rect(int handle, double x, double y, double w, double h) - native "C2DRect"; -void _Restore(int handle) - native "C2DRestore"; -void _Rotate(int handle, double a) - native "C2DRotate"; -void _Save(int handle) - native "C2DSave"; -void _Scale(int handle, double sx, double sy) - native "C2DScale"; -void _SetTransform(int handle, double m11, double m12, - double m21, double m22, double dx, double dy) - native "C2DSetTransform"; -void _Stroke(int handle) - native "C2DStroke"; -void _StrokeRect(int handle, double x, double y, double w, double h) - native "C2DStrokeRect"; -void _StrokeText(int handle, String text, double x, double y, - double maxWidth) - native "C2DStrokeText"; -void _Transform(int handle, double m11, double m12, - double m21, double m22, double dx, double dy) - native "C2DTransform"; -void _Translate(int handle, double x, double y) - native "C2DTranslate"; - -void _CreateNativeContext(int handle, int width, int height) - native "C2DCreateNativeContext"; - -void _SetFillGradient(int handle, bool isRadial, - double x0, double y0, double r0, - double x1, double y1, double r1, - List<double> positions, List<String> colors) - native "C2DSetFillGradient"; - -void _SetStrokeGradient(int handle, bool isRadial, - double x0, double y0, double r0, - double x1, double y1, double r1, - List<double> positions, List<String> colors) - native "C2DSetStrokeGradient"; - -int _GetImageWidth(String url) - native "C2DGetImageWidth"; - -int _GetImageHeight(String url) - native "C2DGetImageHeight"; - -class CanvasGradient { - num _x0, _y0, _r0 = 0, _x1, _y1, _r1 = 0; - bool _isRadial; - List<double> _colorStopPositions = []; - List<String> _colorStopColors = []; - - void addColorStop(num offset, String color) { - _colorStopPositions.add(offset.toDouble()); - _colorStopColors.add(color); - } - - CanvasGradient.linear(this._x0, this._y0, this._x1, this._y1) - : _isRadial = false; - - CanvasGradient.radial(this._x0, this._y0, this._r0, - this._x1, this._y1, this._r1) - : _isRadial = true; - - void setAsFillStyle(_handle) { - _SetFillGradient(_handle, _isRadial, - _x0.toDouble(), _y0.toDouble(), _r0.toDouble(), - _x1.toDouble(), _y1.toDouble(), _r1.toDouble(), - _colorStopPositions, _colorStopColors); - } - - void setAsStrokeStyle(_handle) { - _SetStrokeGradient(_handle, _isRadial, - _x0.toDouble(), _y0.toDouble(), _r0.toDouble(), - _x1.toDouble(), _y1.toDouble(), _r1.toDouble(), - _colorStopPositions, _colorStopColors); - } -} - -class ImageElement extends Node { - Stream<Event> get onLoad => new _EventStream(this, 'load'); - - String _src; - int _width; - int _height; - - get src => _src; - - set src(String v) { - log("Set ImageElement src to $v"); - _src = v; - } - - // The onLoad handler may be set after the src, so - // we hook into that here... - void addListener(String eventType, EventListener handler) { - super.addListener(eventType, handler); - if (eventType == 'load') { - var e = new Event('load'); - e.target = this; - window._scheduleCallback(handler, e); - } - } - - get width => _width == null ? _width = _GetImageWidth(_src) : _width; - get height => _height == null ? _height = _GetImageHeight(_src) : _height; - set width(int widthp) => _width = widthp; - set height(int heightp) => _height = heightp; - - ImageElement({String srcp, int widthp, int heightp}) - : _src = srcp, - _width = widthp, - _height = heightp { - if (_src != null) { - if (_width == null) _width = _GetImageWidth(_src); - if (_height == null) _height = _GetImageHeight(_src); - } - } -} - -class ImageData { - final Uint8ClampedArray data; - final int height; - final int width; - ImageData(this.height, this.width, this.data); -} - -class TextMetrics { - final num width; - TextMetrics(this.width); -} - -void shutdown() { - CanvasRenderingContext2D.next_handle = 0; -} - -class Rect { - final num top, left, width, height; - const Rect(this.left, this.top, this.width, this.height); -} - -class CanvasRenderingContext2D extends CanvasRenderingContext { - // TODO(gram): We need to support multiple contexts, for cached content - // prerendered to an offscreen buffer. For this we will use handles, with - // handle 0 being the physical display. - static int next_handle = 0; - int _handle = 0; - get handle => _handle; - - int _width, _height; - set width(int w) { _width = SetWidth(_handle, w); } - get width => _width; - set height(int h) { _height = SetHeight(_handle, h); } - get height => _height; - - CanvasRenderingContext2D(canvas, width, height) : super(canvas) { - _width = width; - _height = height; - _CreateNativeContext(_handle = next_handle++, width, height); - } - - double _alpha = 1.0; - set globalAlpha(num a) { - _alpha = _SetGlobalAlpha(_handle, a.toDouble()); - } - get globalAlpha => _alpha; - - // TODO(gram): make sure we support compound assignments like: - // fillStyle = strokeStyle = "red" - var _fillStyle = "#000"; - set fillStyle(fs) { - _fillStyle = fs; - // TODO(gram): Support for CanvasPattern. - if (fs is CanvasGradient) { - fs.setAsFillStyle(_handle); - } else { - _SetFillStyle(_handle, fs); - } - } - get fillStyle => _fillStyle; - - String _font = "10px sans-serif"; - set font(String f) { _font = _SetFont(_handle, f); } - get font => _font; - - String _globalCompositeOperation = "source-over"; - set globalCompositeOperation(String o) => - _SetGlobalCompositeOperation(_handle, _globalCompositeOperation = o); - get globalCompositeOperation => _globalCompositeOperation; - - String _lineCap = "butt"; // "butt", "round", "square" - get lineCap => _lineCap; - set lineCap(String lc) => _SetLineCap(_handle, _lineCap = lc); - - int _lineDashOffset = 0; - get lineDashOffset => _lineDashOffset; - set lineDashOffset(num v) { - _lineDashOffset = v.toInt(); - _SetLineDashOffset(_handle, _lineDashOffset); - } - - String _lineJoin = "miter"; // "round", "bevel", "miter" - get lineJoin => _lineJoin; - set lineJoin(String lj) => _SetLineJoin(_handle, _lineJoin = lj); - - num _lineWidth = 1.0; - get lineWidth => _lineWidth; - set lineWidth(num w) { - _SetLineWidth(_handle, w.toDouble()); - _lineWidth = w; - } - - num _miterLimit = 10.0; // (default 10) - get miterLimit => _miterLimit; - set miterLimit(num limit) { - _SetMiterLimit(_handle, limit.toDouble()); - _miterLimit = limit; - } - - num _shadowBlur; - get shadowBlur => _shadowBlur; - set shadowBlur(num blur) { - _shadowBlur = blur; - _SetShadowBlur(_handle, blur.toDouble()); - } - - String _shadowColor; - get shadowColor => _shadowColor; - set shadowColor(String color) => - _SetShadowColor(_handle, _shadowColor = color); - - num _shadowOffsetX; - get shadowOffsetX => _shadowOffsetX; - set shadowOffsetX(num offset) { - _shadowOffsetX = offset; - _SetShadowOffsetX(_handle, offset.toDouble()); - } - - num _shadowOffsetY; - get shadowOffsetY => _shadowOffsetY; - set shadowOffsetY(num offset) { - _shadowOffsetY = offset; - _SetShadowOffsetY(_handle, offset.toDouble()); - } - - var _strokeStyle = "#000"; - get strokeStyle => _strokeStyle; - set strokeStyle(ss) { - _strokeStyle = ss; - // TODO(gram): Support for CanvasPattern. - if (ss is CanvasGradient) { - ss.setAsStrokeStyle(_handle); - } else { - _SetStrokeStyle(_handle, ss); - } - } - - String _textAlign = "start"; - get textAlign => _textAlign; - set textAlign(String a) { _textAlign = _SetTextAlign(_handle, a); } - - String _textBaseline = "alphabetic"; - get textBaseline => _textBaseline; - set textBaseline(String b) { _textBaseline = _SetTextBaseline(_handle, b); } - - get webkitBackingStorePixelRatio => _GetBackingStorePixelRatio(_handle); - - bool _webkitImageSmoothingEnabled; - get webkitImageSmoothingEnabled => _webkitImageSmoothingEnabled; - set webkitImageSmoothingEnabled(bool v) => - _SetImageSmoothingEnabled(_webkitImageSmoothingEnabled = v); - - get webkitLineDash => lineDash; - set webkitLineDash(List v) => lineDash = v; - - get webkitLineDashOffset => lineDashOffset; - set webkitLineDashOffset(num v) => lineDashOffset = v; - - // Methods - - void arc(num x, num y, num radius, num a1, num a2, bool anticlockwise) { - if (radius < 0) { - // throw IndexSizeError - } else { - _Arc(_handle, x.toDouble(), y.toDouble(), radius.toDouble(), - a1.toDouble(), a2.toDouble(), anticlockwise); - } - } - - // Note - looking at the Dart docs it seems Dart doesn't support - // the second form in the browser. - void arcTo(num x1, num y1, num x2, num y2, - num radiusX, [num radiusY, num rotation]) { - if (radiusY == null) { - _ArcTo(_handle, x1.toDouble(), y1.toDouble(), - x2.toDouble(), y2.toDouble(), radiusX.toDouble()); - } else { - _ArcTo2(_handle, x1.toDouble(), y1.toDouble(), - x2.toDouble(), y2.toDouble(), - radiusX.toDouble(), radiusY.toDouble(), - rotation.toDouble()); - } - } - - void beginPath() => _BeginPath(_handle); - - void bezierCurveTo(num cp1x, num cp1y, num cp2x, num cp2y, - num x, num y) => - _BezierCurveTo(_handle, cp1x.toDouble(), cp1y.toDouble(), - cp2x.toDouble(), cp2y.toDouble(), - x.toDouble(), y.toDouble()); - - void clearRect(num x, num y, num w, num h) => - _ClearRect(_handle, x.toDouble(), y.toDouble(), - w.toDouble(), h.toDouble()); - - void clip() => _Clip(_handle); - - void closePath() => _ClosePath(_handle); - - ImageData createImageData(var imagedata_OR_sw, [num sh = null]) { - if (sh == null) { - throw new Exception('Unimplemented createImageData(imagedata)'); - } else { - return _CreateImageDataFromDimensions(_handle, imagedata_OR_sw, sh); - } - } - - CanvasGradient createLinearGradient(num x0, num y0, num x1, num y1) { - return new CanvasGradient.linear(x0, y0, x1, y1); - } - - CanvasPattern createPattern(canvas_OR_image, String repetitionType) { - throw new Exception('Unimplemented createPattern'); - } - - CanvasGradient createRadialGradient(num x0, num y0, num r0, - num x1, num y1, num r1) { - return new CanvasGradient.radial(x0, y0, r0, x1, y1, r1); - } - - void _drawImage(element, num x1, num y1, - [num w1, num h1, num x2, num y2, num w2, num h2]) { - if (element == null || element.src == null || element.src.length == 0) { - throw "drawImage called with no valid src"; - } else { - log("drawImage ${element.src}"); - } - var w = (element.width == null) ? 0 : element.width; - var h = (element.height == null) ? 0 : element.height; - if (!?w1) { // drawImage(element, dx, dy) - _DrawImage(_handle, element.src, 0, 0, false, w, h, - x1.toInt(), y1.toInt(), false, 0, 0); - } else if (!?x2) { // drawImage(element, dx, dy, dw, dh) - _DrawImage(_handle, element.src, 0, 0, false, w, h, - x1.toInt(), y1.toInt(), true, w1.toInt(), h1.toInt()); - } else { // drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh) - _DrawImage(_handle, element.src, - x1.toInt(), y1.toInt(), true, w1.toInt(), h1.toInt(), - x2.toInt(), y2.toInt(), true, w2.toInt(), h2.toInt()); - } - } - - void drawImage(source, num destX, num destY) { - _drawImage(source, destX, destY); - } - - void drawImageScaled(source, - num destX, num destY, num destWidth, num destHeight) { - _drawImage(source, destX, destY, destWidth, destHeight); - } - - void drawImageScaledFromSource(source, - num sourceX, num sourceY, num sourceWidth, num sourceHeight, - num destX, num destY, num destWidth, num destHeight) { - _drawImage(source, sourceX, sourceY, sourceWidth, sourceHeight, - destX, destY, destWidth, destHeight); - } - - void drawImageToRect(source, Rect dest, {Rect sourceRect}) { - if (sourceRect == null) { - _drawImage(source, dest.left, dest.top, dest.width, dest.height); - } else { - _drawImage(source, - sourceRect.left, sourceRect.top, sourceRect.width, sourceRect.height, - dest.left, dest.top, dest.width, dest.height); - } - } - - void fill() => _Fill(_handle); - - void fillRect(num x, num y, num w, num h) => - _FillRect(_handle, x.toDouble(), y.toDouble(), - w.toDouble(), h.toDouble()); - - void fillText(String text, num x, num y, [num maxWidth = -1]) => - _FillText(_handle, text, x.toDouble(), y.toDouble(), - maxWidth.toDouble()); - - ImageData getImageData(num sx, num sy, num sw, num sh) => - _GetImageData(sx, sy, sw, sh); - - List<double> _lineDash = null; - List<num> getLineDash() { - if (_lineDash == null) return []; - return _lineDash; // TODO(gram): should we return a copy? - } - - bool isPointInPath(num x, num y) { - throw new Exception('Unimplemented isPointInPath'); - } - - void lineTo(num x, num y) { - _LineTo(_handle, x.toDouble(), y.toDouble()); - } - - TextMetrics measureText(String text) { - double w = _MeasureText(_handle, text); - return new TextMetrics(w); - } - - void moveTo(num x, num y) => - _MoveTo(_handle, x.toDouble(), y.toDouble()); - - void putImageData(ImageData imagedata, num dx, num dy, - [num dirtyX, num dirtyY, num dirtyWidth, num dirtyHeight]) { - if (dirtyX != null || dirtyY != null) { - throw new Exception('Unimplemented putImageData'); - } else { - _PutImageData(_handle, imagedata, dx, dy); - } - } - - void quadraticCurveTo(num cpx, num cpy, num x, num y) => - _QuadraticCurveTo(_handle, cpx.toDouble(), cpy.toDouble(), - x.toDouble(), y.toDouble()); - - void rect(num x, num y, num w, num h) => - _Rect(_handle, x.toDouble(), y.toDouble(), w.toDouble(), h.toDouble()); - - void restore() => _Restore(_handle); - - void rotate(num angle) => _Rotate(_handle, angle.toDouble()); - - void save() => _Save(_handle); - - void scale(num x, num y) => _Scale(_handle, x.toDouble(), y.toDouble()); - - void setFillColorHsl(int h, num s, num l, [num a = 1]) { - throw new Exception('Unimplemented setFillColorHsl'); - } - - void setFillColorRgb(int r, int g, int b, [num a = 1]) { - throw new Exception('Unimplemented setFillColorRgb'); - } - - void setLineDash(List<num> dash) { - var valid = true; - var new_dash; - if (dash.length % 2 == 1) { - new_dash = new List<double>(2 * dash.length); - for (int i = 0; i < dash.length; i++) { - double v = dash[i].toDouble(); - if (v < 0) { - valid = false; - break; - } - new_dash[i] = new_dash[i + dash.length] = v; - } - } else { - new_dash = new List<double>(dash.length); - for (int i = 0; i < dash.length; i++) { - double v = dash[i].toDouble(); - if (v < 0) { - valid = false; - break; - } - new_dash[i] = v; - } - } - if (valid) { - _SetLineDash(_handle, _lineDash = new_dash); - } - } - - void setStrokeColorHsl(int h, num s, num l, [num a = 1]) { - throw new Exception('Unimplemented setStrokeColorHsl'); - } - - void setStrokeColorRgb(int r, int g, int b, [num a = 1]) { - throw new Exception('Unimplemented setStrokeColorRgb'); - } - - void setTransform(num m11, num m12, num m21, num m22, num dx, num dy) => - _SetTransform(_handle, m11.toDouble(), m12.toDouble(), - m21.toDouble(), m22.toDouble(), - dx.toDouble(), dy.toDouble()); - - void stroke() => _Stroke(_handle); - - void strokeRect(num x, num y, num w, num h, [num lineWidth]) => - _StrokeRect(_handle, x.toDouble(), y.toDouble(), - w.toDouble(), h.toDouble()); - - void strokeText(String text, num x, num y, [num maxWidth = -1]) => - _StrokeText(_handle, text, x.toDouble(), y.toDouble(), - maxWidth.toDouble()); - - void transform(num m11, num m12, num m21, num m22, num dx, num dy) => - _Transform(_handle, m11.toDouble(), m12.toDouble(), - m21.toDouble(), m22.toDouble(), - dx.toDouble(), dy.toDouble()); - - void translate(num x, num y) => - _Translate(_handle, x.toDouble(), y.toDouble()); - - ImageData webkitGetImageDataHD(num sx, num sy, num sw, num sh) { - throw new Exception('Unimplemented webkitGetImageDataHD'); - } - - void webkitPutImageDataHD(ImageData imagedata, num dx, num dy, - [num dirtyX, num dirtyY, - num dirtyWidth, num dirtyHeight]) { - throw new Exception('Unimplemented webkitGetImageDataHD'); - } - - // TODO(vsm): Kill. - noSuchMethod(invocation) { - throw new Exception('Unimplemented/unknown ${invocation.memberName}'); - } -} - -var sfx_extension = 'raw'; -int _loadSample(String s) native "LoadSample"; -int _playSample(String s) native "PlaySample";
diff --git a/runtime/embedders/openglui/common/graphics_handler.cc b/runtime/embedders/openglui/common/graphics_handler.cc deleted file mode 100644 index 449facb..0000000 --- a/runtime/embedders/openglui/common/graphics_handler.cc +++ /dev/null
@@ -1,123 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#include "embedders/openglui/common/graphics_handler.h" -#include "embedders/openglui/common/canvas_context.h" -#include "embedders/openglui/common/log.h" - -extern void CheckGLError(const char *function); - -GraphicsHandler* graphics; -extern CanvasContext* display_context; - -GraphicsHandler::GraphicsHandler(const char* resource_path) - : resource_path_(resource_path), - ag(), - grcontext(NULL), - width_(0), - height_(0) { - graphics = this; - DecoderHack(0, NULL); -} - -void GraphicsHandler::DecoderHack(int x, SkStream* s) { - if (x) { // hack to keep the linker from throwing these out - extern SkImageDecoder* sk_libpng_dfactory(SkStream* s); - sk_libpng_dfactory(s); - - // TODO(gram): For some reason I get linker errors on these, even though - // they are defined in libskia_images. Figure out why... - /* - extern SkImageDecoder* sk_libjpeg_dfactory(SkStream* s); - extern SkImageDecoder* sk_libbmp_dfactory(SkStream* s); - extern SkImageDecoder* sk_libgif_dfactory(SkStream* s); - extern SkImageDecoder* sk_libico_dfactory(SkStream* s); - extern SkImageDecoder* sk_libwbmp_dfactory(SkStream* s); - sk_libjpeg_dfactory(s); - sk_libbmp_dfactory(s); - sk_libgif_dfactory(s); - sk_libico_dfactory(s); - sk_libwbmp_dfactory(s); - */ - } -} - -// Kludge to get around an issue with Android emulator, which returns -// NULL for the shader language version, causing Skia to blow up. -const GrGLubyte* myGLGetString(GLenum name) { - const GrGLubyte* str = glGetString(name); - if (NULL == str && GL_SHADING_LANGUAGE_VERSION == name) { - return reinterpret_cast<GrGLubyte*>( - const_cast<char*>("OpenGL ES GLSL ES 1.0")); - } else { - return str; - } -} - -int32_t GraphicsHandler::Start() { - GrGLInterface* fGL = const_cast<GrGLInterface*>(GrGLCreateNativeInterface()); - LOGI("Created native interface %s\n", fGL ? "succeeded" : "failed"); - fGL->fGetString = myGLGetString; - grcontext = GrContext::Create(kOpenGL_GrBackend, (GrBackendContext)fGL); - LOGI("Created GrContext %s\n", grcontext ? "succeeded" : "failed"); - return 0; -} - -void GraphicsHandler::Stop() { - LOGI("Releasing display context"); - FreeContexts(); - grcontext->unref(); - grcontext = NULL; -} - -SkCanvas* GraphicsHandler::CreateDisplayCanvas() { - GrBackendRenderTargetDesc desc; - desc.fWidth = width_; - desc.fHeight = height_; - desc.fConfig = kSkia8888_GrPixelConfig; - desc.fOrigin = kBottomLeft_GrSurfaceOrigin; - glGetIntegerv(GL_SAMPLES, &desc.fSampleCnt); - glGetIntegerv(GL_STENCIL_BITS, &desc.fStencilBits); - LOGI("Creating %dx%d display canvas, samples %d, stencil bits %d", - width_, height_, desc.fSampleCnt, desc.fStencilBits); - GrGLint buffer; - glGetIntegerv(GL_FRAMEBUFFER_BINDING, &buffer); - desc.fRenderTargetHandle = buffer; - GrRenderTarget* fGrRenderTarget = grcontext->wrapBackendRenderTarget(desc); - SkGpuDevice* device = new SkGpuDevice(grcontext, fGrRenderTarget); -// fGrRenderTarget->unref(); // TODO(gram): determine if we need this. - SkCanvas* canvas = new SkCanvas(device); - device->unref(); - return canvas; -} - -SkCanvas* GraphicsHandler::CreateBitmapCanvas(int width, int height) { - LOGI("Creating %dx%d bitmap canvas", width, height); - SkDevice* rasterDevice = - new SkDevice(SkBitmap::kARGB_8888_Config, width, height); - SkCanvas* canvas = new SkCanvas(rasterDevice); - rasterDevice->unref(); - return canvas; -} - -void GraphicsHandler::SetViewport(int left, int top, int width, int height) { - width_ = width; - height_ = height; - glViewport(left, top, width, height); - CheckGLError("glViewPort"); -} - -int32_t GraphicsHandler::Update() { - LOGI("In GraphicsHandler::Update, display_context dirty %s", - (display_context == NULL ? "NULL" : - (display_context->isDirty() ? "yes":"no"))); - if (display_context != NULL && display_context->isDirty()) { - LOGI("Flushing display context\n"); - display_context->Flush(); - SwapBuffers(); - display_context->clearDirty(); - } - return 0; -} -
diff --git a/runtime/embedders/openglui/common/graphics_handler.h b/runtime/embedders/openglui/common/graphics_handler.h deleted file mode 100644 index 77f57ec..0000000 --- a/runtime/embedders/openglui/common/graphics_handler.h +++ /dev/null
@@ -1,62 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#ifndef EMBEDDERS_OPENGLUI_COMMON_GRAPHICS_HANDLER_H_ -#define EMBEDDERS_OPENGLUI_COMMON_GRAPHICS_HANDLER_H_ - -#include "embedders/openglui/common/isized.h" -#include "embedders/openglui/common/opengl.h" -#include "embedders/openglui/common/support.h" -#include "embedders/openglui/common/timer.h" - -class GraphicsHandler : public ISized { - private: - void DecoderHack(int x, SkStream* s); - - public: - explicit GraphicsHandler(const char* resource_path); - - const int32_t& height() { - return height_; - } - - const int32_t& width() { - return width_; - } - - void ApplyOrtho(float maxX, float maxY) const; - void ApplyRotation(float degrees) const; - - virtual int32_t Start(); - virtual void Stop(); - - void SwapBuffers() { - GLSwapBuffers(); - } - - virtual int32_t Update(); - - void SetViewport(int left, int top, int width, int height); - - SkCanvas* CreateDisplayCanvas(); - SkCanvas* CreateBitmapCanvas(int width, int height); - - inline const char* resource_path() { - return resource_path_; - } - - virtual ~GraphicsHandler() { - } - - protected: - const char* resource_path_; - SkAutoGraphics ag; - GrContext* grcontext; - int32_t width_, height_; -}; - -extern GraphicsHandler* graphics; - -#endif // EMBEDDERS_OPENGLUI_COMMON_GRAPHICS_HANDLER_H_ -
diff --git a/runtime/embedders/openglui/common/image_cache.cc b/runtime/embedders/openglui/common/image_cache.cc deleted file mode 100644 index 957f7ea..0000000 --- a/runtime/embedders/openglui/common/image_cache.cc +++ /dev/null
@@ -1,95 +0,0 @@ -// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#include "embedders/openglui/common/image_cache.h" - -#include <ctype.h> -#include <string.h> -#include "core/SkStream.h" -#include "embedders/openglui/common/canvas_context.h" - -ImageCache* ImageCache::instance_ = NULL; - -extern CanvasContext* Context2D(int handle); - -ImageCache::ImageCache(const char* resource_path) - : images(), resource_path_(resource_path) { -} - -const SkBitmap* ImageCache::GetImage_(const char* src_url) { - if (strncmp(src_url, "context2d://", 12) == 0) { - int handle = atoi(src_url + 12); - CanvasContext* otherContext = Context2D(handle); - return otherContext->GetBitmap(); - } else if (images.find(src_url) == images.end()) { - SkBitmap* bm = Load(src_url); - if (bm != NULL) { - images[src_url] = bm; - } - return bm; - } else { - return images[src_url]; - } -} - -int ImageCache::GetWidth_(const char* src_url) { - const SkBitmap* image = GetImage(src_url); - if (image == NULL) return 0; - return image->width(); -} - -int ImageCache::GetHeight_(const char* src_url) { - const SkBitmap* image = GetImage(src_url); - if (image == NULL) return 0; - return image->height(); -} - -SkBitmap* ImageCache::Load(const char* src_url) { - SkBitmap *bm = NULL; - const char* filepath; - if (strncmp(src_url, "file://", 7) == 0) { - filepath = src_url + 7; - } else { - // TODO(gram): We need a way to remap URLs to local file names. - // For now I am just using the characters after the last '/'. - // Note also that if we want to support URLs and network fetches, - // then we introduce more complexity; this can't just be an URL. - int pos = strlen(src_url); - while (--pos >= 0 && src_url[pos] != '/'); - filepath = src_url + pos + 1; - } - char* path; - if (filepath[0] == '/') { - path = const_cast<char*>(filepath); - } else { - size_t len1 = strlen(resource_path_); - size_t len2 = strlen(filepath); - path = new char[len1 + 1 + len2 + 1]; - strncpy(path, resource_path_, len1+1); - strncat(path, "/", 1); - strncat(path, filepath, len2); - } - - SkFILEStream stream(path); - if (stream.isValid()) { - // We could use DecodeFile and pass the path, but by creating the - // SkStream here we can produce better error log messages. - bm = new SkBitmap(); - if (!SkImageDecoder::DecodeStream(&stream, bm)) { - LOGI("Image decode of %s failed", path); - return NULL; - } else { - LOGI("Decode image %s: width=%d,height=%d", - path, bm->width(), bm->height()); - } - } else { - LOGI("Path %s is invalid", path); - } - - if (path != filepath) { - delete[] path; - } - return bm; -} -
diff --git a/runtime/embedders/openglui/common/image_cache.h b/runtime/embedders/openglui/common/image_cache.h deleted file mode 100644 index 4aa22f8..0000000 --- a/runtime/embedders/openglui/common/image_cache.h +++ /dev/null
@@ -1,58 +0,0 @@ -// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#ifndef EMBEDDERS_OPENGLUI_COMMON_IMAGE_CACHE_H_ -#define EMBEDDERS_OPENGLUI_COMMON_IMAGE_CACHE_H_ - -#include <map> -#include <string> -#include "embedders/openglui/common/log.h" -#include "embedders/openglui/common/opengl.h" -#include "embedders/openglui/common/support.h" - -class ImageCache { - public: - static void Init(const char *resource_path) { - if (instance_ == NULL) { - instance_ = new ImageCache(resource_path); - } - } - - inline static const SkBitmap* GetImage(const char* src_url) { - if (instance_ == NULL) { - fprintf(stderr, "GetImage called with no instance_\n"); - return NULL; - } - return instance_->GetImage_(src_url); - } - - inline static int GetWidth(const char* src_url) { - if (instance_ == NULL) { - fprintf(stderr, "GetWidth called with no instance_\n"); - return NULL; - } - return instance_->GetWidth_(src_url); - } - - inline static int GetHeight(const char* src_url) { - if (instance_ == NULL) { - fprintf(stderr, "GetHeight called with no instance_\n"); - return NULL; - } - return instance_->GetHeight_(src_url); - } - - private: - explicit ImageCache(const char* resource_path); - SkBitmap* Load(const char* src_url); - const SkBitmap* GetImage_(const char* src_url); - int GetWidth_(const char* src_url); - int GetHeight_(const char* src_url); - - std::map<std::string, SkBitmap*> images; - const char* resource_path_; - static ImageCache* instance_; -}; - -#endif // EMBEDDERS_OPENGLUI_COMMON_IMAGE_CACHE_H_
diff --git a/runtime/embedders/openglui/common/input_handler.cc b/runtime/embedders/openglui/common/input_handler.cc deleted file mode 100644 index 7c4c3d2..0000000 --- a/runtime/embedders/openglui/common/input_handler.cc +++ /dev/null
@@ -1,76 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#include "embedders/openglui/common/input_handler.h" -#include "embedders/openglui/common/log.h" - -InputHandler::InputHandler(VMGlue* vm_glue) - : vm_glue_(vm_glue) { -} - -int InputHandler::OnMotionEvent(MotionEvent event, - int64_t when, - float x, - float y) { - const char *function = NULL; - // For now we just keep this simple. There are - // no click events or mouseover events. - switch (event) { - case kMotionDown: - function = "onMouseDown_"; - break; - case kMotionUp: - function = "onMouseUp_"; - break; - case kMotionMove: - function = "onMouseMove_"; - break; - case kMotionCancel: - break; - case kMotionOutside: - break; - case kMotionPointerDown: - break; - case kMotionPointerUp: - break; - default: - return -1; - } - if (function == NULL) { - return 0; - } else { - return vm_glue_->OnMotionEvent(function, when, x, y); - } -} - -int InputHandler::OnKeyEvent(KeyEvent event, - int64_t when, - int32_t key_code, - bool isAltKeyDown, - bool isCtrlKeyDown, - bool isShiftKeyDown, - int32_t repeat) { - const char *function = NULL; - switch (event) { - case kKeyDown: - function = "onKeyDown_"; - break; - case kKeyUp: - function = "onKeyUp_"; - break; - case kKeyMultiple: - return -1; // TODO(gram): handle this. - break; - default: - return -1; - } - return vm_glue_->OnKeyEvent(function, when, key_code, - isAltKeyDown, isCtrlKeyDown, isShiftKeyDown, - repeat); -} - -void InputHandler::OnAccelerometerEvent(float x, float y, float z) { - vm_glue_->OnAccelerometerEvent(x, y, z); -} -
diff --git a/runtime/embedders/openglui/common/input_handler.h b/runtime/embedders/openglui/common/input_handler.h deleted file mode 100644 index 06d6d0f..0000000 --- a/runtime/embedders/openglui/common/input_handler.h +++ /dev/null
@@ -1,30 +0,0 @@ -// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#ifndef EMBEDDERS_OPENGLUI_COMMON_INPUT_HANDLER_H_ -#define EMBEDDERS_OPENGLUI_COMMON_INPUT_HANDLER_H_ - -#include "embedders/openglui/common/events.h" -#include "embedders/openglui/common/vm_glue.h" - -class InputHandler { - public: - explicit InputHandler(VMGlue* vm_glue); - virtual int32_t Start() { return 0; } - virtual void Stop() { } - virtual int OnMotionEvent(MotionEvent event, int64_t when, - float move_x, float move_y); - virtual int OnKeyEvent(KeyEvent event, int64_t when, int32_t key_code, - bool isAltKeyDown, bool isCtrlKeyDown, - bool isShiftKeyDown, int32_t repeat); - virtual void OnAccelerometerEvent(float x, float y, float z); - - virtual ~InputHandler() {} - - protected: - VMGlue* vm_glue_; -}; - -#endif // EMBEDDERS_OPENGLUI_COMMON_INPUT_HANDLER_H_ -
diff --git a/runtime/embedders/openglui/common/isized.h b/runtime/embedders/openglui/common/isized.h deleted file mode 100644 index b84dde2..0000000 --- a/runtime/embedders/openglui/common/isized.h +++ /dev/null
@@ -1,21 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#ifndef EMBEDDERS_OPENGLUI_COMMON_ISIZED_H_ -#define EMBEDDERS_OPENGLUI_COMMON_ISIZED_H_ - -#include <stdint.h> - -// An interface for objects that have a size. VMGlue needs the window -// size when calling setup() (and eventually resize()) but it does not -// need to know anything else about the window, so we use this interface. -class ISized { - public: - virtual const int32_t& height() = 0; - virtual const int32_t& width() = 0; - virtual ~ISized() {} -}; - -#endif // EMBEDDERS_OPENGLUI_COMMON_ISIZED_H_ -
diff --git a/runtime/embedders/openglui/common/lifecycle_handler.h b/runtime/embedders/openglui/common/lifecycle_handler.h deleted file mode 100644 index cc1a659..0000000 --- a/runtime/embedders/openglui/common/lifecycle_handler.h +++ /dev/null
@@ -1,26 +0,0 @@ -// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#ifndef EMBEDDERS_OPENGLUI_COMMON_LIFECYCLE_HANDLER_H_ -#define EMBEDDERS_OPENGLUI_COMMON_LIFECYCLE_HANDLER_H_ - -class LifeCycleHandler { - public: - virtual int32_t OnStart() = 0; - virtual int32_t Activate() = 0; - virtual void Deactivate() = 0; - virtual int32_t OnStep() = 0; - virtual void Pause() {} - virtual int32_t Resume() { - return 0; - } - virtual void FreeAllResources() {} - virtual void OnSaveState(void** data, size_t* size) {} - virtual void OnConfigurationChanged() {} - virtual void OnLowMemory() {} - virtual ~LifeCycleHandler() {} -}; - -#endif // EMBEDDERS_OPENGLUI_COMMON_LIFECYCLE_HANDLER_H_ -
diff --git a/runtime/embedders/openglui/common/log.h b/runtime/embedders/openglui/common/log.h deleted file mode 100644 index d74e0f5..0000000 --- a/runtime/embedders/openglui/common/log.h +++ /dev/null
@@ -1,30 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#ifndef EMBEDDERS_OPENGLUI_COMMON_LOG_H_ -#define EMBEDDERS_OPENGLUI_COMMON_LOG_H_ - -#ifndef ANDROID -#include <stdio.h> -#define LOGI(...) do {\ - fprintf(stdout, __VA_ARGS__);\ - fprintf(stdout, "\n");\ - fflush(stdout);\ - } while (0) -#define LOGE(...) do { \ - fprintf(stderr, __VA_ARGS__);\ - fprintf(stderr, "\n");\ - fflush(stderr);\ - } while (0) -#else -#include "embedders/openglui/android/android_log.h" -#endif - -#ifndef DEBUG -#undef LOGI -#define LOGI(...) -#endif - -#endif // EMBEDDERS_OPENGLUI_COMMON_LOG_H_ -
diff --git a/runtime/embedders/openglui/common/opengl.h b/runtime/embedders/openglui/common/opengl.h deleted file mode 100644 index 3a41415..0000000 --- a/runtime/embedders/openglui/common/opengl.h +++ /dev/null
@@ -1,57 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -// A semi-generic header file that can be used to isolate platform differences -// for OpenGL headers. -#ifndef EMBEDDERS_OPENGLUI_COMMON_OPENGL_H_ -#define EMBEDDERS_OPENGLUI_COMMON_OPENGL_H_ - -#if defined(__APPLE__) -# ifdef GL_ES_VERSION_2_0 -# include <OpenGLES/ES2/gl.h> -# else -# include <Glut/glut.h> -# include <OpenGL/gl.h> -# endif -# define GLSwapBuffers() glutSwapBuffers() -#elif defined(_WIN32) || defined(_WIN64) -# include <GL/glew.h> -# include <GL/wglew.h> -# include <GLUT/glut.h> -# include <Windows.h> -# define GLSwapBuffers() glutSwapBuffers() -#elif defined(__ANDROID__) -# include <EGL/egl.h> -# include <GLES2/gl2.h> -# include <GLES2/gl2ext.h> -# define GLSwapBuffers() \ - do {\ - EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); \ - EGLSurface surface = eglGetCurrentSurface(EGL_DRAW); \ - eglSwapBuffers(display, surface); \ - } while (0); -#else // Linux. -# define GL_GLEXT_PROTOTYPES 1 -# include <GL/gl.h> -# include <GL/glext.h> -# include <GL/glut.h> -# define GLSwapBuffers() glutSwapBuffers() -#endif - -#include "core/SkCanvas.h" -#include "core/SkGraphics.h" -#include "core/SkPaint.h" -#include "core/SkTypeface.h" -#include "effects/SkBlurDrawLooper.h" -#include "effects/SkDashPathEffect.h" -#include "effects/SkGradientShader.h" -#include "gpu/SkGpuDevice.h" -#include "gpu/GrContext.h" -#include "gpu/GrRenderTarget.h" -#include "gpu/gl/GrGLInterface.h" -#include "gpu/gl/SkNativeGLContext.h" -#include "images/SkImageDecoder.h" - -#endif // EMBEDDERS_OPENGLUI_COMMON_OPENGL_H_ -
diff --git a/runtime/embedders/openglui/common/resource.h b/runtime/embedders/openglui/common/resource.h deleted file mode 100644 index dd07a68..0000000 --- a/runtime/embedders/openglui/common/resource.h +++ /dev/null
@@ -1,59 +0,0 @@ -// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#ifndef EMBEDDERS_OPENGLUI_COMMON_RESOURCE_H_ -#define EMBEDDERS_OPENGLUI_COMMON_RESOURCE_H_ - -#include <stdlib.h> -#include <string.h> - -class Resource { - public: - explicit Resource(const char* path) - : descriptor_(-1), - start_(0), - length_(-1) { - path_ = strdup(path); - } - - const char* path() { - return path_; - } - - virtual int32_t descriptor() { - return descriptor_; - } - - virtual off_t start() { - return start_; - } - - virtual off_t length() { - return length_; - } - - virtual int32_t Open() { - return -1; - } - - virtual void Close() { - } - - virtual int32_t Read(void* buffer, size_t count) { - return -1; - } - - virtual ~Resource() { - free(path_); - } - - protected: - char* path_; - int32_t descriptor_; - off_t start_; - off_t length_; -}; - -#endif // EMBEDDERS_OPENGLUI_COMMON_RESOURCE_H_ -
diff --git a/runtime/embedders/openglui/common/sample.h b/runtime/embedders/openglui/common/sample.h deleted file mode 100644 index 5fc4239..0000000 --- a/runtime/embedders/openglui/common/sample.h +++ /dev/null
@@ -1,63 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#ifndef EMBEDDERS_OPENGLUI_COMMON_SAMPLE_H_ -#define EMBEDDERS_OPENGLUI_COMMON_SAMPLE_H_ - -#include "embedders/openglui/common/resource.h" - -extern Resource* MakePlatformResource(const char *path); - -class Sample { - public: - explicit Sample(const char* path) - : buffer_(NULL), - length_(0) { - resource_ = MakePlatformResource(path); - } - - ~Sample() { - Unload(); - delete resource_; - } - - const char* path() { - return resource_->path(); - } - - uint8_t* buffer() { - return buffer_; - } - - off_t length() { - return length_; - } - - int32_t Load() { - int32_t rtn = -1; - if (resource_->Open() == 0) { - buffer_ = new uint8_t[length_ = resource_->length()]; - rtn = resource_->Read(buffer_, length_); - resource_->Close(); - } - return rtn; - } - - void Unload() { - if (buffer_ != NULL) { - delete[] buffer_; - buffer_ = NULL; - } - length_ = 0; - } - - private: - friend class SoundService; - Resource* resource_; - uint8_t* buffer_; - off_t length_; -}; - -#endif // EMBEDDERS_OPENGLUI_COMMON_SAMPLE_H_ -
diff --git a/runtime/embedders/openglui/common/sound_handler.cc b/runtime/embedders/openglui/common/sound_handler.cc deleted file mode 100644 index 8af2379..0000000 --- a/runtime/embedders/openglui/common/sound_handler.cc +++ /dev/null
@@ -1,58 +0,0 @@ -// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#include "embedders/openglui/common/sound_handler.h" - -#include <string.h> - -#include "embedders/openglui/common/log.h" - -// TODO(gram): Clean up this instance pointer; either make the class -// a proper singleton or provide a cleaner way for the static functions -// at the end to access it (those functions are the hooks into the Dart -// native extension). -SoundHandler* instance_ = NULL; - -SoundHandler::SoundHandler() - : samples_() { - instance_ = this; -} - -Sample* SoundHandler::GetSample(const char* path) { - for (samples_t::iterator sp = samples_.begin(); - sp != samples_.end(); - ++sp) { - Sample* sample = (*sp); - if (strcmp(sample->path(), path) == 0) { - LOGI("Returning cached sample %s", path); - return sample; - } - } - Sample* sample = new Sample(path); - if (sample->Load() != 0) { - LOGI("Failed to load sample %s", path); - delete sample; - return NULL; - } - samples_.push_back(sample); - LOGI("Adding sample %s to cache", path); - return sample; -} - -int32_t PlayBackgroundSound(const char* path) { - return instance_->PlayBackground(path); -} - -void StopBackgroundSound() { - instance_->StopBackground(); -} - -int32_t LoadSoundSample(const char* path) { - return instance_->LoadSample(path); -} - -int32_t PlaySoundSample(const char* path) { - return instance_->PlaySample(path); -} -
diff --git a/runtime/embedders/openglui/common/sound_handler.h b/runtime/embedders/openglui/common/sound_handler.h deleted file mode 100644 index 61090a7..0000000 --- a/runtime/embedders/openglui/common/sound_handler.h +++ /dev/null
@@ -1,66 +0,0 @@ -// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#ifndef EMBEDDERS_OPENGLUI_COMMON_SOUND_HANDLER_H_ -#define EMBEDDERS_OPENGLUI_COMMON_SOUND_HANDLER_H_ - -#include <stdint.h> -#include <vector> - -#include "embedders/openglui/common/sample.h" - -class SoundHandler { - public: - SoundHandler(); - - virtual ~SoundHandler() { - } - - virtual int32_t Start() { - return 0; - } - - virtual void Stop() { - } - - virtual int32_t Suspend() { - return 0; - } - - virtual int32_t Resume() { - return 0; - } - - virtual int32_t PlayBackground(const char* path) { - return 0; - } - - virtual void StopBackground() { - } - - // Optional, for preloading. - int32_t LoadSample(const char* path) { - return (GetSample(path) == NULL) ? -1 : 0; - } - - virtual int32_t PlaySample(const char* path) { - // Just do a load so we can get logging. - return (GetSample(path) == NULL) ? -1 : 0; - } - - protected: - typedef std::vector<Sample*> samples_t; - - Sample* GetSample(const char* path); - - samples_t samples_; -}; - -int32_t PlayBackgroundSound(const char* path); -void StopBackgroundSound(); -int32_t LoadSoundSample(const char* path); -int32_t PlaySoundSample(const char* path); - -#endif // EMBEDDERS_OPENGLUI_COMMON_SOUND_HANDLER_H_ -
diff --git a/runtime/embedders/openglui/common/support.h b/runtime/embedders/openglui/common/support.h deleted file mode 100644 index 143c9a9..0000000 --- a/runtime/embedders/openglui/common/support.h +++ /dev/null
@@ -1,37 +0,0 @@ -// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#ifndef EMBEDDERS_OPENGLUI_COMMON_SUPPORT_H_ -#define EMBEDDERS_OPENGLUI_COMMON_SUPPORT_H_ - -#include "embedders/openglui/common/opengl.h" - -#ifndef MAX -#define MAX(a, b) (((a) > (b)) ? (a) : (b)) -#endif -#ifndef MIN -#define MIN(a, b) (((a) < (b)) ? (a) : (b)) -#endif - -// Colors as used by canvas. -typedef struct ColorRGBA { - // We store Skia-compatible values. Skia uses - // the form AARRGGBB. - uint32_t v; - - inline ColorRGBA(char rp, char gp, char bp, char ap = 255) { - v = ((static_cast<uint32_t>(rp) & 0xFF) << 16) | - ((static_cast<uint32_t>(gp) & 0xFF) << 8) | - ((static_cast<uint32_t>(bp) & 0xFF) << 0) | - ((static_cast<uint32_t>(ap) & 0xFF) << 24); - } - inline ColorRGBA(uint32_t vp) - : v(vp) { - } - inline uint8_t alpha() { - return (v >> 24) & 0xFF; - } -} ColorRGBA; - -#endif // EMBEDDERS_OPENGLUI_COMMON_SUPPORT_H_
diff --git a/runtime/embedders/openglui/common/timer.cc b/runtime/embedders/openglui/common/timer.cc deleted file mode 100644 index 9a0e2af..0000000 --- a/runtime/embedders/openglui/common/timer.cc +++ /dev/null
@@ -1,66 +0,0 @@ -// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#include "embedders/openglui/common/timer.h" - -#define NANO (+1.0E-9) - -#ifdef __MACH__ -#include <mach/mach.h> -#include <mach/mach_time.h> -#include <sys/time.h> - -#define GIGA UINT64_C(1000000000) - -#define CLOCK_REALTIME 0 -#define CLOCK_MONOTONIC 1 - -double timebase = 0.0; -uint64_t timestart = 0; - -void clock_gettime(int type, timespec* t) { - if (!timestart) { - mach_timebase_info_data_t tb = { 0, 1 }; - mach_timebase_info(&tb); - timebase = tb.numer; - timebase /= tb.denom; - timestart = mach_absolute_time(); - } - if (type == CLOCK_MONOTONIC) { - double diff = (mach_absolute_time() - timestart) * timebase; - t->tv_sec = diff * NANO; - t->tv_nsec = diff - (t->tv_sec * GIGA); - } else { // type == CLOCK_REALTIME - struct timeval now; - gettimeofday(&now, NULL); - t->tv_sec = now.tv_sec; - t->tv_nsec = now.tv_usec * 1000; - } -} -#endif - -Timer::Timer() : elapsed_(0.0f), last_time_(0.0) { -} - -void Timer::Reset() { - elapsed_ = 0.0f; - last_time_ = Now(); -} - -void Timer::Update() { - double current = Now(); - elapsed_ = (current - last_time_); - last_time_ = current; -} - -double Timer::Now() { - timespec timeval; - clock_gettime(CLOCK_MONOTONIC, &timeval); - return timeval.tv_sec + (timeval.tv_nsec * NANO); -} - -float Timer::Elapsed() { - return elapsed_; -} -
diff --git a/runtime/embedders/openglui/common/timer.h b/runtime/embedders/openglui/common/timer.h deleted file mode 100644 index d2f3d67..0000000 --- a/runtime/embedders/openglui/common/timer.h +++ /dev/null
@@ -1,24 +0,0 @@ -// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#ifndef EMBEDDERS_OPENGLUI_COMMON_TIMER_H_ -#define EMBEDDERS_OPENGLUI_COMMON_TIMER_H_ - -#include <time.h> - -class Timer { - public: - Timer(); - void Reset(); - void Update(); - double Now(); - float Elapsed(); - - private: - float elapsed_; - double last_time_; -}; - -#endif // EMBEDDERS_OPENGLUI_COMMON_TIMER_H_ -
diff --git a/runtime/embedders/openglui/common/types.h b/runtime/embedders/openglui/common/types.h deleted file mode 100644 index 8acbe8c..0000000 --- a/runtime/embedders/openglui/common/types.h +++ /dev/null
@@ -1,24 +0,0 @@ -// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#ifndef EMBEDDERS_OPENGLUI_COMMON_TYPES_H_ -#define EMBEDDERS_OPENGLUI_COMMON_TYPES_H_ - -struct Location { - Location() : pos_x_(0), pos_y_(0) { - }; - void setPosition(float pos_x, float pos_y) { - pos_x_ = pos_x; - pos_y_ = pos_y; - } - void translate(float amount_x, float amount_y) { - pos_x_ += amount_x; - pos_y_ += amount_y; - } - - float pos_x_, pos_y_; -}; - -#endif // EMBEDDERS_OPENGLUI_COMMON_TYPES_H_ -
diff --git a/runtime/embedders/openglui/common/vm_glue.cc b/runtime/embedders/openglui/common/vm_glue.cc deleted file mode 100644 index 91a26db..0000000 --- a/runtime/embedders/openglui/common/vm_glue.cc +++ /dev/null
@@ -1,398 +0,0 @@ -// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#include <math.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/stat.h> -#include <unistd.h> - -#include "embedders/openglui/common/extension.h" -#include "embedders/openglui/common/log.h" -#include "embedders/openglui/common/vm_glue.h" -#include "include/dart_api.h" - -char* VMGlue::extension_script_ = NULL; -bool VMGlue::initialized_vm_ = false; - -// snapshot_buffer points to a snapshot if we link in a snapshot otherwise -// it is initialized to NULL. - -VMGlue::VMGlue(ISized* surface, - const char* script_path, - const char* extension_script, - const char* main_script, - int setup_flag) - : surface_(surface), - isolate_(NULL), - initialized_script_(false), - x_(0.0), - y_(0.0), - z_(0.0), - accelerometer_changed_(false), - setup_flag_(setup_flag) { - LOGI("Creating VMGlue"); - if (main_script == NULL) { - main_script = "main.dart"; - } - if (extension_script == NULL) { - extension_script = "gl.dart"; - } - size_t len = strlen(script_path) + strlen(main_script) + 2; - main_script_ = new char[len]; - snprintf(main_script_, len, "%s/%s", script_path, main_script); - len = strlen(script_path) + strlen(extension_script) + 2; - extension_script_ = new char[len]; - snprintf(extension_script_, len, "%s/%s", script_path, extension_script); -} - -Dart_Handle VMGlue::CheckError(Dart_Handle handle) { - if (Dart_IsError(handle)) { - LOGE("Unexpected Error Handle: %s", Dart_GetError(handle)); - Dart_PropagateError(handle); - } - return handle; -} - -#define CHECK_RESULT(result) \ - if (Dart_IsError(result)) { \ - *error = strdup(Dart_GetError(result)); \ - LOGE("%s", *error); \ - Dart_ExitScope(); \ - Dart_ShutdownIsolate(); \ - return false; \ - } - -Dart_Handle VMGlue::LibraryTagHandler(Dart_LibraryTag tag, - Dart_Handle library, - Dart_Handle urlHandle) { - const char* url; - Dart_StringToCString(urlHandle, &url); - if (tag == kCanonicalizeUrl) { - return urlHandle; - } - // TODO(vsm): Split this up into separate libraries for 3D, 2D, - // Touch, Audio, etc. All builtin libraries should be handled here - // (or moved into a snapshot). - if (strcmp(url, "gl.dart") == 0) { - Dart_Handle source = - VMGlue::LoadSourceFromFile(extension_script_); - Dart_Handle library = CheckError(Dart_LoadLibrary(urlHandle, source)); - CheckError(Dart_SetNativeResolver(library, ResolveName)); - return library; - } - LOGE("UNIMPLEMENTED: load library %s\n", url); - return NULL; -} - -// Returns true on success, false on failure. -Dart_Isolate VMGlue::CreateIsolateAndSetupHelper(const char* script_uri, - const char* main, - void* data, - char** error) { - LOGI("Creating isolate %s, %s", script_uri, main); - Dart_Isolate isolate = - Dart_CreateIsolate(script_uri, main, NULL, data, error); - if (isolate == NULL) { - LOGE("Couldn't create isolate: %s", *error); - return NULL; - } - - LOGI("Entering scope"); - Dart_EnterScope(); - - // Set up the library tag handler for this isolate. - LOGI("Setting up library tag handler"); - Dart_Handle result = CheckError(Dart_SetLibraryTagHandler(LibraryTagHandler)); - CHECK_RESULT(result); - - Dart_ExitScope(); - return isolate; -} - -Dart_Isolate VMGlue::CreateIsolateAndSetup(const char* script_uri, - const char* main, - void* data, char** error) { - return CreateIsolateAndSetupHelper(script_uri, - main, - data, - error); -} - -const char* VM_FLAGS[] = { - "--enable_type_checks", // TODO(gram): This should be an option! - // "--trace_isolates", - // "--trace_natives", - // "--trace_compiler", -}; - -static void* openFileCallback(const char* name, bool write) { - return fopen(name, write ? "w" : "r"); -} - -static void readFileCallback(const uint8_t** data, intptr_t* fileLength, - void* stream) { - if (!stream) { - *data = 0; - *fileLength = 0; - } else { - FILE* file = reinterpret_cast<FILE*>(stream); - - // Get the file size. - fseek(file, 0, SEEK_END); - *fileLength = ftell(file); - rewind(file); - - // Allocate data buffer. - *data = new uint8_t[*fileLength]; - *fileLength = fread(const_cast<uint8_t*>(*data), 1, *fileLength, file); - } -} - -static void writeFileCallback(const void* data, intptr_t length, void* file) { - fwrite(data, 1, length, reinterpret_cast<FILE*>(file)); -} - -static void closeFileCallback(void* file) { - fclose(reinterpret_cast<FILE*>(file)); -} - -int VMGlue::InitializeVM() { - // We need the next call to get Dart_Initialize not to bail early. - LOGI("Setting VM Options"); - Dart_SetVMFlags(sizeof(VM_FLAGS) / sizeof(VM_FLAGS[0]), VM_FLAGS); - - // Initialize the Dart VM, providing the callbacks to use for - // creating and shutting down isolates. - LOGI("Initializing Dart"); - if (!Dart_Initialize(CreateIsolateAndSetup, - 0, - 0, - 0, - openFileCallback, - readFileCallback, - writeFileCallback, - closeFileCallback)) { - LOGE("VM initialization failed\n"); - return -1; - } - initialized_vm_ = true; - - return 0; -} - -Dart_Handle VMGlue::LoadSourceFromFile(const char* url) { - FILE* file = fopen(url, "r"); - if (file == NULL) { - LOGE("Main script not found at: %s\n", url); - return NULL; - } - - struct stat sb; - int fd = fileno(file); - fstat(fd, &sb); - int length = sb.st_size; - LOGI("Entry file %s is %d bytes.\n", url, length); - - char* buffer = new char[length+1]; - if (read(fd, buffer, length) < 0) { - LOGE("Could not read script %s.\n", url); - return NULL; - } - buffer[length] = 0; - fclose(file); - - Dart_Handle contents = CheckError(Dart_NewStringFromCString(buffer)); - delete[] buffer; - return contents; -} - -int VMGlue::StartMainIsolate() { - if (!initialized_vm_) { - int rtn = InitializeVM(); - if (rtn != 0) return rtn; - } - - // Create an isolate and loads up the application script. - char* error = NULL; - if (!CreateIsolateAndSetup(main_script_, "main", NULL, &error)) { - LOGE("CreateIsolateAndSetup: %s\n", error); - free(error); - return -1; - } - LOGI("Created isolate"); - isolate_ = Dart_CurrentIsolate(); - Dart_EnterScope(); - - Dart_Handle url = CheckError(Dart_NewStringFromCString(main_script_)); - Dart_Handle source = LoadSourceFromFile(main_script_); - CheckError(Dart_LoadScript(url, source, 0, 0)); - - Dart_ExitScope(); - Dart_ExitIsolate(); - return 0; -} - -int VMGlue::CallSetup(bool force) { - // TODO(gram): See if we actually need this flag guard here, or if - // we can eliminate it along with the need for the force parameter. - if (!initialized_script_ || force) { - initialized_script_ = true; - LOGI("Invoking setup(null, %d,%d,%d)", - surface_->width(), surface_->height(), setup_flag_); - Dart_EnterIsolate(isolate_); - Dart_EnterScope(); - Dart_Handle args[4]; - args[0] = CheckError(Dart_Null()); - args[1] = CheckError(Dart_NewInteger(surface_->width())); - args[2] = CheckError(Dart_NewInteger(surface_->height())); - args[3] = CheckError(Dart_NewInteger(setup_flag_)); - int rtn = Invoke("setup", 4, args); - - if (rtn == 0) { - // Plug in the print handler. It would be nice if we could do this - // before calling setup, but the call to GetField blows up if we - // haven't run anything yet. - Dart_Handle library = CheckError(Dart_LookupLibrary( - Dart_NewStringFromCString("gl.dart"))); - Dart_Handle print = CheckError( - Dart_GetField(library, Dart_NewStringFromCString("_printClosure"))); - Dart_Handle corelib = CheckError(Dart_LookupLibrary( - Dart_NewStringFromCString("dart:core"))); - CheckError(Dart_SetField(corelib, - Dart_NewStringFromCString("_printClosure"), print)); - } - Dart_ExitScope(); - Dart_ExitIsolate(); - LOGI("Done setup"); - return rtn; - } - return 0; -} - -int VMGlue::CallUpdate() { - if (initialized_script_) { - // If the accelerometer has changed, first do that - // event. - Dart_EnterIsolate(isolate_); - if (accelerometer_changed_) { - Dart_Handle args[3]; - LOGI("Invoking onAccelerometer(%f,%f,%f)", x_, y_, z_); - Dart_EnterScope(); - args[0] = CheckError(Dart_NewDouble(x_)); - args[1] = CheckError(Dart_NewDouble(y_)); - args[2] = CheckError(Dart_NewDouble(z_)); - Invoke("onAccelerometer", 3, args, false); - Dart_ExitScope(); - accelerometer_changed_ = false; - } - Dart_EnterScope(); - int rtn = Invoke("update_", 0, 0); - Dart_ExitScope(); - Dart_ExitIsolate(); - LOGI("Invoke update_ returns %d", rtn); - return rtn; - } - return -1; -} - -int VMGlue::CallShutdown() { - if (initialized_script_) { - Dart_EnterIsolate(isolate_); - Dart_EnterScope(); - int rtn = Invoke("shutdown", 0, 0); - Dart_ExitScope(); - Dart_ExitIsolate(); - return rtn; - } - return -1; -} - -int VMGlue::OnMotionEvent(const char* pFunction, int64_t pWhen, - float pMoveX, float pMoveY) { - if (initialized_script_) { - LOGI("Invoking %s", pFunction); - Dart_EnterIsolate(isolate_); - Dart_EnterScope(); - Dart_Handle args[3]; - args[0] = CheckError(Dart_NewInteger(pWhen)); - args[1] = CheckError(Dart_NewDouble(pMoveX)); - args[2] = CheckError(Dart_NewDouble(pMoveY)); - int rtn = Invoke(pFunction, 3, args, false); - Dart_ExitScope(); - Dart_ExitIsolate(); - LOGI("Done %s", pFunction); - return rtn; - } - return -1; -} - -int VMGlue::OnKeyEvent(const char* function, int64_t when, int32_t key_code, - bool isAltKeyDown, bool isCtrlKeyDown, - bool isShiftKeyDown, int32_t repeat) { - if (initialized_script_) { - LOGI("Invoking %s(_,%d,...)", function, key_code); - Dart_EnterIsolate(isolate_); - Dart_EnterScope(); - Dart_Handle args[6]; - args[0] = CheckError(Dart_NewInteger(when)); - args[1] = CheckError(Dart_NewInteger(key_code)); - args[2] = CheckError(Dart_NewBoolean(isAltKeyDown)); - args[3] = CheckError(Dart_NewBoolean(isCtrlKeyDown)); - args[4] = CheckError(Dart_NewBoolean(isShiftKeyDown)); - args[5] = CheckError(Dart_NewInteger(repeat)); - int rtn = Invoke(function, 6, args, false); - Dart_ExitScope(); - Dart_ExitIsolate(); - LOGI("Done %s", function); - return rtn; - } - return -1; -} - -int VMGlue::Invoke(const char* function, - int argc, - Dart_Handle* args, - bool failIfNotDefined) { - // Lookup the library of the root script. - Dart_Handle library = Dart_RootLibrary(); - if (Dart_IsNull(library)) { - LOGE("Unable to find root library\n"); - return -1; - } - - Dart_Handle nameHandle = Dart_NewStringFromCString(function); - - Dart_Handle result = Dart_Invoke(library, nameHandle, argc, args); - - if (Dart_IsError(result)) { - const char* error = Dart_GetError(result); - LOGE("Invoke %s failed: %s", function, error); - if (failIfNotDefined) { - return -1; - } - } - - // TODO(vsm): I don't think we need this. - // Keep handling messages until the last active receive port is closed. - result = Dart_RunLoop(); - if (Dart_IsError(result)) { - LOGE("Dart_RunLoop: %s\n", Dart_GetError(result)); - return -1; - } - - return 0; -} - -void VMGlue::FinishMainIsolate() { - LOGI("Finish main isolate"); - Dart_EnterIsolate(isolate_); - // Shutdown the isolate. - Dart_ShutdownIsolate(); - isolate_ = NULL; - initialized_script_ = false; -} -
diff --git a/runtime/embedders/openglui/common/vm_glue.h b/runtime/embedders/openglui/common/vm_glue.h deleted file mode 100644 index 8f84377..0000000 --- a/runtime/embedders/openglui/common/vm_glue.h +++ /dev/null
@@ -1,78 +0,0 @@ -// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#ifndef EMBEDDERS_OPENGLUI_COMMON_VM_GLUE_H_ -#define EMBEDDERS_OPENGLUI_COMMON_VM_GLUE_H_ - -#include <stdlib.h> - -#include "embedders/openglui/common/events.h" -#include "embedders/openglui/common/isized.h" -#include "include/dart_api.h" - -class VMGlue { - public: - explicit VMGlue(ISized* surface, - const char* script_path, - const char* extension_script = NULL, - const char* main_script = NULL, - int setup_flag = 0); - ~VMGlue() { - delete[] main_script_; - delete[] extension_script_; - } - - int InitializeVM(); - int StartMainIsolate(); - int CallSetup(bool force = false); - int CallUpdate(); - int CallShutdown(); - int OnMotionEvent(const char* funtion, int64_t when, - float move_x, float move_y); - int OnKeyEvent(const char* funtion, int64_t when, int32_t key_code, - bool isAltKeyDown, bool isCtrlKeyDown, bool isShiftKeyDown, - int32_t repeat); - inline void OnAccelerometerEvent(float x, float y, float z) { - if (x != x_ || y != y_ || z != z_) { - x_ = x; - y_ = y; - z_ = z; - accelerometer_changed_ = true; - } - } - - void FinishMainIsolate(); - - private: - int Invoke(const char *function, int argc, Dart_Handle* args, - bool failIfNotDefined = true); - - static Dart_Handle CheckError(Dart_Handle); - - static Dart_Isolate CreateIsolateAndSetupHelper(const char* script_uri, - const char* main, - void* data, - char** error); - static Dart_Isolate CreateIsolateAndSetup(const char* script_uri, - const char* main, - void* data, char** error); - static Dart_Handle LibraryTagHandler(Dart_LibraryTag tag, - Dart_Handle library, - Dart_Handle urlHandle); - static Dart_Handle LoadSourceFromFile(const char* url); - static void ShutdownIsolate(void* callback_data); - - static bool initialized_vm_; - static char* extension_script_; - ISized* surface_; - Dart_Isolate isolate_; - bool initialized_script_; - char* main_script_; - float x_, y_, z_; // Last values from accelerometer. - bool accelerometer_changed_; - int setup_flag_; -}; - -#endif // EMBEDDERS_OPENGLUI_COMMON_VM_GLUE_H_ -
diff --git a/runtime/embedders/openglui/emulator/emulator_embedder.cc b/runtime/embedders/openglui/emulator/emulator_embedder.cc deleted file mode 100644 index de01870..0000000 --- a/runtime/embedders/openglui/emulator/emulator_embedder.cc +++ /dev/null
@@ -1,132 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#include "embedders/openglui/emulator/emulator_embedder.h" - -#include <string.h> -#include <sys/time.h> -#include <time.h> -#include "embedders/openglui/common/canvas_context.h" -#include "embedders/openglui/common/context.h" -#include "embedders/openglui/common/dart_host.h" -#include "embedders/openglui/common/events.h" -#include "embedders/openglui/common/input_handler.h" -#include "embedders/openglui/common/log.h" -#include "embedders/openglui/common/sound_handler.h" -#include "embedders/openglui/common/vm_glue.h" -#include "embedders/openglui/emulator/emulator_graphics_handler.h" -#include "embedders/openglui/emulator/emulator_resource.h" - -InputHandler* input_handler_ptr; -LifeCycleHandler* lifecycle_handler_ptr; - -struct timeval tvStart; -void tick(int data); - -Resource* MakePlatformResource(const char *path) { - return new EmulatorResource(path); -} - -void display() { - // Get number of msecs since last call. - struct timeval tvEnd; - gettimeofday(&tvEnd, NULL); - uint64_t now = (tvEnd.tv_usec + 1000000 * tvEnd.tv_sec); - - if (lifecycle_handler_ptr->OnStep() != 0) { - exit(-1); - } - // Schedule next call, trying to aim for 60fps. - uint64_t elapsed = now - (tvStart.tv_usec + 1000000 * tvStart.tv_sec); - int delay = 1000 / 60 - (elapsed / 1000); - if (delay < 0) delay = 0; - tvStart = tvEnd; - glutTimerFunc(delay, tick, 0); -} - -void tick(int data) { - display(); -} - -void reshape(int width, int height) { - glViewport(0, 0, width, height); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, width, 0, height, -1, 1); - glMatrixMode(GL_MODELVIEW); - glutPostRedisplay(); -} - -void keyboard(unsigned char key, int x, int y) { - input_handler_ptr->OnKeyEvent(kKeyDown, time(0), key, false, false, false, 0); - input_handler_ptr->OnKeyEvent(kKeyUp, time(0), key, false, false, false, 0); - if (key == 'Q') { - lifecycle_handler_ptr->Pause(); - lifecycle_handler_ptr->Deactivate(); - lifecycle_handler_ptr->FreeAllResources(); - exit(0); - } else if (key == 'S') { - LOGI("Simulating suspend"); - lifecycle_handler_ptr->Pause(); - lifecycle_handler_ptr->Deactivate(); - } else if (key == 'R') { - LOGI("Simulating resume"); - lifecycle_handler_ptr->Activate(); - lifecycle_handler_ptr->Resume(); - } else if (key == '+') { - LOGI("Simulating focus gain"); - lifecycle_handler_ptr->Resume(); - } else if (key == '-') { - LOGI("Simulating focus loss"); - lifecycle_handler_ptr->Pause(); - } -} - -void mouse(int button, int state, int x, int y) { - if (state == GLUT_UP) { - input_handler_ptr->OnMotionEvent(kMotionUp, time(0), x, y); - } else if (state == GLUT_DOWN) { - input_handler_ptr->OnMotionEvent(kMotionDown, time(0), x, y); - } -} - -void motion(int x, int y) { - input_handler_ptr->OnMotionEvent(kMotionMove, time(0), x, y); -} - -DART_EXPORT void emulator_main(int argc, char** argv, const char* script) { - EmulatorGraphicsHandler graphics_handler(argc, argv); - if (argc > 0) { - int i = argc - 1; - size_t len = strlen(argv[i]); - if (len > 5 && strcmp(".dart", argv[i] + len - 5) == 0) { - script = argv[i]; - } - } - VMGlue vm_glue(&graphics_handler, ".", "gl.dart", script, 1); - InputHandler input_handler(&vm_glue); - input_handler_ptr = &input_handler; - SoundHandler sound_handler; - Timer timer; - Context app_context; - app_context.graphics_handler = &graphics_handler; - app_context.input_handler = &input_handler; - app_context.sound_handler = &sound_handler; - app_context.timer = &timer; - app_context.vm_glue = &vm_glue; - DartHost host(&app_context); - lifecycle_handler_ptr = &host; - glutReshapeFunc(reshape); - glutDisplayFunc(display); - glutKeyboardFunc(keyboard); - glutMouseFunc(mouse); - glutMotionFunc(motion); - lifecycle_handler_ptr->OnStart(); - lifecycle_handler_ptr->Activate(); - lifecycle_handler_ptr->Resume(); - gettimeofday(&tvStart, NULL); - glutTimerFunc(1, tick, 0); - glutMainLoop(); -} -
diff --git a/runtime/embedders/openglui/emulator/emulator_embedder.h b/runtime/embedders/openglui/emulator/emulator_embedder.h deleted file mode 100644 index f0f0638..0000000 --- a/runtime/embedders/openglui/emulator/emulator_embedder.h +++ /dev/null
@@ -1,14 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#ifndef EMBEDDERS_OPENGLUI_EMULATOR_EMULATOR_EMBEDDER_H_ -#define EMBEDDERS_OPENGLUI_EMULATOR_EMULATOR_EMBEDDER_H_ - -#include "include/dart_api.h" - -DART_EXPORT void emulator_main(int argc, char** argv, - const char* script); - -#endif // EMBEDDERS_OPENGLUI_EMULATOR_EMULATOR_EMBEDDER_H_ -
diff --git a/runtime/embedders/openglui/emulator/emulator_graphics_handler.cc b/runtime/embedders/openglui/emulator/emulator_graphics_handler.cc deleted file mode 100644 index 606dc76..0000000 --- a/runtime/embedders/openglui/emulator/emulator_graphics_handler.cc +++ /dev/null
@@ -1,39 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#include "embedders/openglui/emulator/emulator_graphics_handler.h" - -#include <stdlib.h> -#include <string.h> - -EmulatorGraphicsHandler::EmulatorGraphicsHandler(int argc, - char** argv) - : GraphicsHandler(".") { - glutInit(&argc, argv); - width_ = 800; - height_ = 480; - for (int i = 1; i < argc; i++) { - if (argv[i][0] == '-') { - int next_arg = i + 1; - if (next_arg < argc && strcmp(argv[i], "-w") == 0) { - width_ = static_cast<size_t>(atoi(argv[i = next_arg])); - } else if (next_arg < argc && strcmp(argv[i], "-h") == 0) { - height_ = static_cast<size_t>(atoi(argv[i = next_arg])); - } - } - } - SetViewport(0, 0, width_, height_); - glutInitWindowSize(width_, height_); - glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH | GLUT_STENCIL); - glutCreateWindow("Dart"); -} - -int32_t EmulatorGraphicsHandler::Start() { - return GraphicsHandler::Start(); -} - -void EmulatorGraphicsHandler::Stop() { - GraphicsHandler::Stop(); -} -
diff --git a/runtime/embedders/openglui/emulator/emulator_graphics_handler.h b/runtime/embedders/openglui/emulator/emulator_graphics_handler.h deleted file mode 100644 index 4a29270..0000000 --- a/runtime/embedders/openglui/emulator/emulator_graphics_handler.h +++ /dev/null
@@ -1,19 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#ifndef EMBEDDERS_OPENGLUI_EMULATOR_EMULATOR_GRAPHICS_HANDLER_H_ -#define EMBEDDERS_OPENGLUI_EMULATOR_EMULATOR_GRAPHICS_HANDLER_H_ - -#include "embedders/openglui/common/graphics_handler.h" - -class EmulatorGraphicsHandler : public GraphicsHandler { - public: - EmulatorGraphicsHandler(int argc, char** argv); - - int32_t Start(); - void Stop(); -}; - -#endif // EMBEDDERS_OPENGLUI_EMULATOR_EMULATOR_GRAPHICS_HANDLER_H_ -
diff --git a/runtime/embedders/openglui/emulator/emulator_resource.h b/runtime/embedders/openglui/emulator/emulator_resource.h deleted file mode 100644 index fc54f8a..0000000 --- a/runtime/embedders/openglui/emulator/emulator_resource.h +++ /dev/null
@@ -1,64 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -#ifndef EMBEDDERS_OPENGLUI_EMULATOR_EMULATOR_RESOURCE_H_ -#define EMBEDDERS_OPENGLUI_EMULATOR_EMULATOR_RESOURCE_H_ - -#include <fcntl.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <unistd.h> - -#include "embedders/openglui/common/log.h" -#include "embedders/openglui/common/resource.h" - -class EmulatorResource : public Resource { - public: - explicit EmulatorResource(const char* path) - : Resource(path), - fd_(-1) { - } - - int32_t descriptor() { - if (fd_ < 0) { - Open(); - } - return fd_; - } - - off_t length() { - if (length_ < 0) { - length_ = lseek(fd_, 0, SEEK_END); - lseek(fd_, 0, SEEK_SET); - } - return length_; - } - - int32_t Open() { - fd_ = open(path_, 0); - if (fd_ >= 0) { - return 0; - } - LOGE("Could not open asset %s", path_); - return -1; - } - - void Close() { - if (fd_ >= 0) { - close(fd_); - fd_ = -1; - } - } - - int32_t Read(void* buffer, size_t count) { - size_t actual = read(fd_, buffer, count); - return (actual == count) ? 0 : -1; - } - - private: - int fd_; -}; - -#endif // EMBEDDERS_OPENGLUI_EMULATOR_EMULATOR_RESOURCE_H_ -
diff --git a/runtime/embedders/openglui/openglui_embedder.gypi b/runtime/embedders/openglui/openglui_embedder.gypi deleted file mode 100644 index 4b058cc..0000000 --- a/runtime/embedders/openglui/openglui_embedder.gypi +++ /dev/null
@@ -1,310 +0,0 @@ -# Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -# for details. All rights reserved. Use of this source code is governed by a -# BSD-style license that can be found in the LICENSE file. - -{ - # TODO(gram) : figure out how to make this be autoconfigured. - # I've tried a bunch of things with no success yet. - 'variables': { - 'skia_build_flag' : '--release', - 'skia_libs_location_android': '-Lthird_party/skia/trunk/out/config/android-x86/Release/obj.target/gyp', - 'skia_libs_location_desktop': '-Lthird_party/skia/trunk/out/Release', - }, - 'conditions': [ - ['OS=="android"', - { - 'targets': [ - { - # Dart shared library for Android. - 'target_name': 'android_embedder', - 'type': 'shared_library', - 'dependencies': [ - 'skia-android', - 'libdart_lib_withcore', - 'libdart_vm', - 'libjscre', - 'libdouble_conversion', - 'generate_version_cc_file#host', - ], - 'include_dirs': [ - '../..', - '../../../third_party/android_tools/ndk/sources/android/native_app_glue', - '../../../third_party/skia/trunk/include', - '../../../third_party/skia/trunk/include/config', - '../../../third_party/skia/trunk/include/core', - '../../../third_party/skia/trunk/include/gpu', - '../../../third_party/skia/trunk/include/lazy', - '../../../third_party/skia/trunk/include/utils', - ], - 'defines': [ - 'DART_SHARED_LIB', - '__ANDROID__', - 'SK_BUILD_FOR_ANDROID', - 'SK_BUILD_FOR_ANDROID_NDK', - ], - 'sources': [ - '../../include/dart_api.h', - '../../include/dart_debugger_api.h', - '../../vm/dart_api_impl.cc', - '../../vm/debugger_api_impl.cc', - '../../vm/version.h', - '../../../third_party/android_tools/ndk/sources/android/native_app_glue/android_native_app_glue.h', - '../../../third_party/android_tools/ndk/sources/android/native_app_glue/android_native_app_glue.c', - '../../../third_party/skia/trunk/src/core/SkPaintOptionsAndroid.cpp', - 'android/android_graphics_handler.cc', - 'android/android_graphics_handler.h', - 'android/android_input_handler.h', - 'android/android_resource.h', - 'android/android_sound_handler.cc', - 'android/android_sound_handler.h', - 'android/eventloop.cc', - 'android/eventloop.h', - 'android/log.h', - 'android/main.cc', - 'android/support_android.cc', - 'common/canvas_context.cc', - 'common/canvas_context.h', - 'common/canvas_state.cc', - 'common/canvas_state.h', - 'common/context.h', - 'common/dart_host.cc', - 'common/dart_host.h', - 'common/events.h', - 'common/extension.cc', - 'common/extension.h', - 'common/graphics_handler.cc', - 'common/graphics_handler.h', - 'common/image_cache.cc', - 'common/image_cache.h', - 'common/input_handler.cc', - 'common/input_handler.h', - 'common/isized.h', - 'common/life_cycle_handler.h', - 'common/log.h', - 'common/opengl.h', - 'common/resource.h', - 'common/sample.h', - 'common/sound_handler.cc', - 'common/sound_handler.h', - 'common/support.h', - 'common/timer.cc', - 'common/timer.h', - 'common/types.h', - 'common/vm_glue.cc', - 'common/vm_glue.h', - '<(version_cc_file)', - ], - 'link_settings': { - 'ldflags': [ - # The libraries we need should all be in - # Lthird_party/skia/trunk/out/config/android-x86/Debug but - # As I (gram) want to avoid patching the Skia gyp files to build - # real libraries we'll just point to the location of the 'thin' - # libraries used by the Skia build for now. - # TODO(gram): We need to support debug vs release modes. - '<(skia_libs_location_android)', - '-z', - 'muldefs', - ], - 'ldflags!': [ - '-Wl,--exclude-libs=ALL,-shared', - ], - 'libraries': [ - '-Wl,--start-group', - '-lexpat', - '-lfreetype', - '-lgif', - '-ljpeg', - '-lpng', - '-lwebp_dec', - '-lwebp_utils', - '-lwebp_dsp', - '-lwebp_enc', - '-lskia_core', - '-lskia_effects', - '-lskia_gr', - '-lskia_images', - '-lskia_opts', - '-lskia_pdf', - '-lskia_ports', - '-lskia_sfnt', - '-lskia_skgr', - '-lskia_utils', - '-lskia_views', - '-lskia_xml', - '-lzlib', - '-Wl,--end-group', - '-llog', - '-lc', - '-lz', - '-landroid', - '-lEGL', - '-lGLESv2', - '-lOpenSLES', - '-landroid', - ], - }, - }, - { - 'target_name': 'skia-android', - 'type': 'none', - 'actions': [ - { - 'action_name': 'build_skia', - 'inputs': [ - 'build_skia.sh' - ], - 'outputs': [ - 'dummy' # To force re-execution every time. - ], - # For now we drive the build from a shell - # script, to get us going. Eventually we will - # want to either fork Skia or incorporate its - # gclient settings into ours, and include its - # gyp files within ours, so that it gets built - # as part of our tree. - 'action': [ - 'embedders/openglui/build_skia.sh', - '--android', - '<(skia_build_flag)', - '..' - ], - 'message': 'Building Skia.' - } - ] - } - ], - }, - ], - ['OS=="mac" or OS=="linux"', - { - 'targets': [ - { - 'target_name': 'emulator_embedder', - 'type': 'static_library', - 'dependencies': [ - 'skia-desktop', - 'libdart_lib_withcore', - 'libdart_vm', - 'libjscre', - 'libdouble_conversion', - 'generate_version_cc_file', - ], - 'include_dirs': [ - '../..', - '/usr/X11/include', - '../../../third_party/skia/trunk/include', - '../../../third_party/skia/trunk/include/config', - '../../../third_party/skia/trunk/include/core', - '../../../third_party/skia/trunk/include/gpu', - '../../../third_party/skia/trunk/include/lazy', - '../../../third_party/skia/trunk/include/utils', - ], - 'defines': [ - 'DART_SHARED_LIB' - ], - 'sources': [ - '../../include/dart_api.h', - '../../include/dart_debugger_api.h', - '../../vm/dart_api_impl.cc', - '../../vm/debugger_api_impl.cc', - '../../vm/version.h', - 'common/canvas_context.cc', - 'common/canvas_context.h', - 'common/canvas_state.cc', - 'common/canvas_state.h', - 'common/context.h', - 'common/dart_host.cc', - 'common/dart_host.h', - 'common/events.h', - 'common/extension.cc', - 'common/extension.h', - 'common/graphics_handler.cc', - 'common/graphics_handler.h', - 'common/image_cache.cc', - 'common/image_cache.h', - 'common/input_handler.cc', - 'common/input_handler.h', - 'common/isized.h', - 'common/life_cycle_handler.h', - 'common/log.h', - 'common/opengl.h', - 'common/resource.h', - 'common/sample.h', - 'common/sound_handler.cc', - 'common/sound_handler.h', - 'common/support.h', - 'common/support.h', - 'common/timer.cc', - 'common/timer.h', - 'common/types.h', - 'common/vm_glue.cc', - 'common/vm_glue.h', - 'emulator/emulator_embedder.cc', - 'emulator/emulator_embedder.h', - 'emulator/emulator_graphics_handler.cc', - 'emulator/emulator_graphics_handler.h', - 'emulator/emulator_resource.h', - '<(version_cc_file)', - ], - 'link_settings': { - 'ldflags': [ - '-Wall', - '<(skia_libs_location_desktop)', - '-Wl,--start-group', - '-lskia_core', - '-lskia_effects', - '-lskia_gr', - '-lskia_images', - '-lskia_opts', - '-lskia_opts_ssse3', - '-lskia_ports', - '-lskia_sfnt', - '-lskia_skgr', - '-lskia_utils', - '-Wl,--end-group', - '-lfreetype', - ], - 'libraries': [ - '-lGL', - '-lglut', - '-lGLU', - '-lm', - '-lwebp' - ], - }, - 'conditions': [ - ['OS=="mac"', { - 'xcode_settings' : { - 'OTHER_LDFLAGS': [ '-framework OpenGL', '-framework GLUT', '-L /usr/X11/lib' ] - }, - }], - ] - }, - { - 'target_name': 'skia-desktop', - 'type': 'none', - 'actions': [ - { - 'action_name': 'build_skia', - 'inputs': [ - 'build_skia.sh' - ], - 'outputs': [ - 'dummy' # To force re-execution every time. - ], - 'action': [ - 'embedders/openglui/build_skia.sh', - '<(skia_build_flag)', - '..' - ], - 'message': 'Building Skia.' - } - ] - } - ], - }, - ], - ], -} -
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h index a09f212..9f4969e 100755 --- a/runtime/include/dart_api.h +++ b/runtime/include/dart_api.h
@@ -185,9 +185,13 @@ * can be used to store objects across scopes. Persistent handles have * the lifetime of the current isolate unless they are explicitly * deallocated (see Dart_DeletePersistentHandle). + * The type Dart_Handle represents a handle (both local and persistent). + * The type Dart_PersistentHandle is a Dart_Handle and it is used to + * document that a persistent handle is expected as a parameter to a call + * or the return value from a call is a persistent handle. */ typedef struct _Dart_Handle* Dart_Handle; -typedef struct _Dart_PersistentHandle* Dart_PersistentHandle; +typedef Dart_Handle Dart_PersistentHandle; typedef struct _Dart_WeakPersistentHandle* Dart_WeakPersistentHandle; typedef void (*Dart_WeakPersistentHandleFinalizer)( @@ -2241,9 +2245,9 @@ * \param url A url identifying the origin of the patch source * \param source A string of Dart patch source */ -DART_EXPORT Dart_Handle Dart_LoadPatch(Dart_Handle library, - Dart_Handle url, - Dart_Handle patch_source); +DART_EXPORT Dart_Handle Dart_LibraryLoadPatch(Dart_Handle library, + Dart_Handle url, + Dart_Handle patch_source); /*
diff --git a/runtime/lib/array.cc b/runtime/lib/array.cc index 7116f5b..c81aef2 100644 --- a/runtime/lib/array.cc +++ b/runtime/lib/array.cc
@@ -12,7 +12,7 @@ namespace dart { -DEFINE_NATIVE_ENTRY(ObjectArray_allocate, 2) { +DEFINE_NATIVE_ENTRY(List_allocate, 2) { const AbstractTypeArguments& type_arguments = AbstractTypeArguments::CheckedHandle(isolate, arguments->NativeArgAt(0)); const Instance& length = Instance::CheckedHandle( @@ -21,18 +21,14 @@ const String& error = String::Handle(String::NewFormatted( "Length must be an integer in the range [0..%" Pd "].", Array::kMaxElements)); - const Array& args = Array::Handle(Array::New(1)); - args.SetAt(0, error); - Exceptions::ThrowByType(Exceptions::kArgument, args); + Exceptions::ThrowArgumentError(error); } intptr_t len = Smi::Cast(length).Value(); if (len < 0 || len > Array::kMaxElements) { const String& error = String::Handle(String::NewFormatted( "Length (%" Pd ") must be an integer in the range [0..%" Pd "].", len, Array::kMaxElements)); - const Array& args = Array::Handle(Array::New(1)); - args.SetAt(0, error); - Exceptions::ThrowByType(Exceptions::kArgument, args); + Exceptions::ThrowArgumentError(error); } const Array& new_array = Array::Handle(Array::New(len)); new_array.SetTypeArguments(type_arguments); @@ -40,7 +36,7 @@ } -DEFINE_NATIVE_ENTRY(ObjectArray_getIndexed, 2) { +DEFINE_NATIVE_ENTRY(List_getIndexed, 2) { const Array& array = Array::CheckedHandle(arguments->NativeArgAt(0)); GET_NON_NULL_NATIVE_ARGUMENT(Smi, index, arguments->NativeArgAt(1)); if ((index.Value() < 0) || (index.Value() >= array.Length())) { @@ -52,7 +48,7 @@ } -DEFINE_NATIVE_ENTRY(ObjectArray_setIndexed, 3) { +DEFINE_NATIVE_ENTRY(List_setIndexed, 3) { const Array& array = Array::CheckedHandle(arguments->NativeArgAt(0)); GET_NON_NULL_NATIVE_ARGUMENT(Smi, index, arguments->NativeArgAt(1)); const Instance& value = Instance::CheckedHandle(arguments->NativeArgAt(2)); @@ -66,14 +62,14 @@ } -DEFINE_NATIVE_ENTRY(ObjectArray_getLength, 1) { +DEFINE_NATIVE_ENTRY(List_getLength, 1) { const Array& array = Array::CheckedHandle(arguments->NativeArgAt(0)); return Smi::New(array.Length()); } // ObjectArray src, int srcStart, int dstStart, int count. -DEFINE_NATIVE_ENTRY(ObjectArray_copyFromObjectArray, 5) { +DEFINE_NATIVE_ENTRY(List_copyFromObjectArray, 5) { const Array& dest = Array::CheckedHandle(arguments->NativeArgAt(0)); GET_NON_NULL_NATIVE_ARGUMENT(Array, source, arguments->NativeArgAt(1)); GET_NON_NULL_NATIVE_ARGUMENT(Smi, src_start, arguments->NativeArgAt(2));
diff --git a/runtime/lib/array.dart b/runtime/lib/array.dart index e16cbef..89ddce5 100644 --- a/runtime/lib/array.dart +++ b/runtime/lib/array.dart
@@ -4,26 +4,26 @@ // TODO(srdjan): Use shared array implementation. -class _ObjectArray<E> implements List<E> { - static final int _classId = (new _ObjectArray(0))._cid; +class _List<E> implements List<E> { + static final int _classId = (new _List(0))._cid; - factory _ObjectArray(length) native "ObjectArray_allocate"; + factory _List(length) native "List_allocate"; - E operator [](int index) native "ObjectArray_getIndexed"; + E operator [](int index) native "List_getIndexed"; - void operator []=(int index, E value) native "ObjectArray_setIndexed"; + void operator []=(int index, E value) native "List_setIndexed"; String toString() { return IterableMixinWorkaround.toStringIterable(this,'[' , ']'); } - int get length native "ObjectArray_getLength"; + int get length native "List_getLength"; - void _copyFromObjectArray(_ObjectArray src, + void _copyFromObjectArray(_List src, int srcStart, int dstStart, int count) - native "ObjectArray_copyFromObjectArray"; + native "List_copyFromObjectArray"; void insert(int index, E element) { throw new UnsupportedError( @@ -74,7 +74,7 @@ int length = end - start; if (length == 0) return; - if (iterable is _ObjectArray) { + if (iterable is _List) { _copyFromObjectArray(iterable, skipCount, start, length); } else { List otherList; @@ -110,7 +110,7 @@ if (end == null) end = this.length; int length = end - start; if (start == end) return []; - List list = new _GrowableObjectArray<E>.withCapacity(length); + List list = new _GrowableList<E>.withCapacity(length); list.length = length; Arrays.copy(this, start, list, 0, length); return list; @@ -270,29 +270,29 @@ } -// This is essentially the same class as _ObjectArray, but it does not +// This is essentially the same class as _List, but it does not // permit any modification of array elements from Dart code. We use // this class for arrays constructed from Dart array literals. // TODO(hausner): We should consider the trade-offs between two // classes (and inline cache misses) versus a field in the native // implementation (checks when modifying). We should keep watching // the inline cache misses. -class _ImmutableArray<E> implements List<E> { +class _ImmutableList<E> implements List<E> { static final int _classId = (const [])._cid; - factory _ImmutableArray._uninstantiable() { + factory _ImmutableList._uninstantiable() { throw new UnsupportedError( "ImmutableArray can only be allocated by the VM"); } - E operator [](int index) native "ObjectArray_getIndexed"; + E operator [](int index) native "List_getIndexed"; void operator []=(int index, E value) { throw new UnsupportedError( "Cannot modify an immutable array"); } - int get length native "ObjectArray_getLength"; + int get length native "List_getLength"; void insert(int index, E element) { throw new UnsupportedError( @@ -537,7 +537,7 @@ _FixedSizeArrayIterator(List array) : _array = array, _length = array.length, _position = -1 { - assert(array is _ObjectArray || array is _ImmutableArray); + assert(array is _List || array is _ImmutableList); } bool moveNext() {
diff --git a/runtime/lib/array_patch.dart b/runtime/lib/array_patch.dart index 386e8ac..cb9ca76 100644 --- a/runtime/lib/array_patch.dart +++ b/runtime/lib/array_patch.dart
@@ -13,17 +13,17 @@ patch class List<E> { /* patch */ factory List([int length = _GROWABLE_ARRAY_MARKER]) { if (identical(length, _GROWABLE_ARRAY_MARKER)) { - return new _GrowableObjectArray<E>(0); + return new _GrowableList<E>(0); } // All error handling on the length parameter is done at the implementation - // of new _ObjectArray. - return new _ObjectArray<E>(length); + // of new _List. + return new _List<E>(length); } /* patch */ factory List.filled(int length, E fill) { // All error handling on the length parameter is done at the implementation - // of new _ObjectArray. - var result = new _ObjectArray<E>(length); + // of new _List. + var result = new _List<E>(length); if (fill != null) { for (int i = 0; i < length; i++) { result[i] = fill; @@ -36,9 +36,9 @@ // [elements] contains elements that are already type checked. factory List._fromLiteral(List elements) { if (elements.isEmpty) { - return new _GrowableObjectArray<E>(0); + return new _GrowableList<E>(0); } - var result = new _GrowableObjectArray<E>.withData(elements); + var result = new _GrowableList<E>.withData(elements); result._setLength(elements.length); return result; }
diff --git a/runtime/lib/date.cc b/runtime/lib/date.cc index 154f1fe..f1b0298 100644 --- a/runtime/lib/date.cc +++ b/runtime/lib/date.cc
@@ -20,9 +20,7 @@ Integer, dart_seconds, arguments->NativeArgAt(0)); int64_t seconds = dart_seconds.AsInt64Value(); if (seconds < 0 || seconds > kMaxAllowedSeconds) { - const Array& args = Array::Handle(Array::New(1)); - args.SetAt(0, dart_seconds); - Exceptions::ThrowByType(Exceptions::kArgument, args); + Exceptions::ThrowArgumentError(dart_seconds); } const char* name = OS::GetTimeZoneName(seconds); return String::New(name); @@ -34,9 +32,7 @@ Integer, dart_seconds, arguments->NativeArgAt(0)); int64_t seconds = dart_seconds.AsInt64Value(); if (seconds < 0 || seconds > kMaxAllowedSeconds) { - const Array& args = Array::Handle(Array::New(1)); - args.SetAt(0, dart_seconds); - Exceptions::ThrowByType(Exceptions::kArgument, args); + Exceptions::ThrowArgumentError(dart_seconds); } int offset = OS::GetTimeZoneOffsetInSeconds(seconds); return Integer::New(offset);
diff --git a/runtime/lib/double.cc b/runtime/lib/double.cc index b37c526..1cadbdb 100644 --- a/runtime/lib/double.cc +++ b/runtime/lib/double.cc
@@ -219,10 +219,8 @@ && kLowerBoundary < d && d < kUpperBoundary) { return DoubleToStringAsFixed(d, static_cast<int>(fraction_digits_value)); } else { - const Array& args = Array::Handle(Array::New(1)); - args.SetAt(0, String::Handle( + Exceptions::ThrowArgumentError(String::Handle( String::New("Illegal arguments to double.toStringAsFixed"))); - Exceptions::ThrowByType(Exceptions::kArgument, args); return Object::null(); } } @@ -237,10 +235,8 @@ return DoubleToStringAsExponential( d, static_cast<int>(fraction_digits_value)); } else { - const Array& args = Array::Handle(Array::New(1)); - args.SetAt(0, String::Handle( + Exceptions::ThrowArgumentError(String::Handle( String::New("Illegal arguments to double.toStringAsExponential"))); - Exceptions::ThrowByType(Exceptions::kArgument, args); return Object::null(); } } @@ -254,10 +250,8 @@ if (1 <= precision_value && precision_value <= 21) { return DoubleToStringAsPrecision(d, static_cast<int>(precision_value)); } else { - const Array& args = Array::Handle(Array::New(1)); - args.SetAt(0, String::Handle( + Exceptions::ThrowArgumentError(String::Handle( String::New("Illegal arguments to double.toStringAsPrecision"))); - Exceptions::ThrowByType(Exceptions::kArgument, args); return Object::null(); } }
diff --git a/runtime/lib/function.cc b/runtime/lib/function.cc index 8c41892..82e6df1 100644 --- a/runtime/lib/function.cc +++ b/runtime/lib/function.cc
@@ -33,6 +33,7 @@ isolate, arguments->NativeArgAt(0)); ASSERT(receiver.IsClosure()); GET_NATIVE_ARGUMENT(Instance, other, arguments->NativeArgAt(1)); + ASSERT(!other.IsNull()); if (receiver.raw() == other.raw()) return Bool::True().raw(); if (other.IsClosure()) { const Function& func_a = Function::Handle(Closure::function(receiver));
diff --git a/runtime/lib/growable_array.cc b/runtime/lib/growable_array.cc index a080325..34f60a0 100644 --- a/runtime/lib/growable_array.cc +++ b/runtime/lib/growable_array.cc
@@ -12,7 +12,7 @@ namespace dart { -DEFINE_NATIVE_ENTRY(GrowableObjectArray_allocate, 2) { +DEFINE_NATIVE_ENTRY(GrowableList_allocate, 2) { const AbstractTypeArguments& type_arguments = AbstractTypeArguments::CheckedHandle(arguments->NativeArgAt(0)); GET_NON_NULL_NATIVE_ARGUMENT(Array, data, arguments->NativeArgAt(1)); @@ -29,7 +29,7 @@ } -DEFINE_NATIVE_ENTRY(GrowableObjectArray_getIndexed, 2) { +DEFINE_NATIVE_ENTRY(GrowableList_getIndexed, 2) { const GrowableObjectArray& array = GrowableObjectArray::CheckedHandle(arguments->NativeArgAt(0)); GET_NON_NULL_NATIVE_ARGUMENT(Smi, index, arguments->NativeArgAt(1)); @@ -43,7 +43,7 @@ } -DEFINE_NATIVE_ENTRY(GrowableObjectArray_setIndexed, 3) { +DEFINE_NATIVE_ENTRY(GrowableList_setIndexed, 3) { const GrowableObjectArray& array = GrowableObjectArray::CheckedHandle(arguments->NativeArgAt(0)); GET_NON_NULL_NATIVE_ARGUMENT(Smi, index, arguments->NativeArgAt(1)); @@ -58,21 +58,21 @@ } -DEFINE_NATIVE_ENTRY(GrowableObjectArray_getLength, 1) { +DEFINE_NATIVE_ENTRY(GrowableList_getLength, 1) { const GrowableObjectArray& array = GrowableObjectArray::CheckedHandle(arguments->NativeArgAt(0)); return Smi::New(array.Length()); } -DEFINE_NATIVE_ENTRY(GrowableObjectArray_getCapacity, 1) { +DEFINE_NATIVE_ENTRY(GrowableList_getCapacity, 1) { const GrowableObjectArray& array = GrowableObjectArray::CheckedHandle(arguments->NativeArgAt(0)); return Smi::New(array.Capacity()); } -DEFINE_NATIVE_ENTRY(GrowableObjectArray_setLength, 2) { +DEFINE_NATIVE_ENTRY(GrowableList_setLength, 2) { const GrowableObjectArray& array = GrowableObjectArray::CheckedHandle(arguments->NativeArgAt(0)); GET_NON_NULL_NATIVE_ARGUMENT(Smi, length, arguments->NativeArgAt(1)); @@ -82,7 +82,7 @@ } -DEFINE_NATIVE_ENTRY(GrowableObjectArray_setData, 2) { +DEFINE_NATIVE_ENTRY(GrowableList_setData, 2) { const GrowableObjectArray& array = GrowableObjectArray::CheckedHandle(arguments->NativeArgAt(0)); GET_NON_NULL_NATIVE_ARGUMENT(Array, data, arguments->NativeArgAt(1));
diff --git a/runtime/lib/growable_array.dart b/runtime/lib/growable_array.dart index 812a71a..b1f1ccb 100644 --- a/runtime/lib/growable_array.dart +++ b/runtime/lib/growable_array.dart
@@ -2,8 +2,8 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -class _GrowableObjectArray<T> implements List<T> { - static final int _classId = (new _GrowableObjectArray(0))._cid; +class _GrowableList<T> implements List<T> { + static final int _classId = (new _GrowableList(0))._cid; void insert(int index, T element) { if (index < 0 || index > length) { @@ -117,38 +117,38 @@ if (end == null) end = length; int length = end - start; if (start == end) return <T>[]; - List list = new _GrowableObjectArray<T>.withCapacity(length); + List list = new _GrowableList<T>.withCapacity(length); list.length = length; Arrays.copy(this, start, list, 0, length); return list; } - factory _GrowableObjectArray(int length) { - var data = new _ObjectArray((length == 0) ? 4 : length); - var result = new _GrowableObjectArray<T>.withData(data); + factory _GrowableList(int length) { + var data = new _List((length == 0) ? 4 : length); + var result = new _GrowableList<T>.withData(data); if (length > 0) { result._setLength(length); } return result; } - factory _GrowableObjectArray.withCapacity(int capacity) { - var data = new _ObjectArray((capacity == 0)? 4 : capacity); - return new _GrowableObjectArray<T>.withData(data); + factory _GrowableList.withCapacity(int capacity) { + var data = new _List((capacity == 0)? 4 : capacity); + return new _GrowableList<T>.withData(data); } - factory _GrowableObjectArray.from(Iterable<T> other) { - List<T> result = new _GrowableObjectArray<T>(); + factory _GrowableList.from(Iterable<T> other) { + List<T> result = new _GrowableList<T>(); result.addAll(other); return result; } - factory _GrowableObjectArray.withData(_ObjectArray data) - native "GrowableObjectArray_allocate"; + factory _GrowableList.withData(_List data) + native "GrowableList_allocate"; - int get length native "GrowableObjectArray_getLength"; + int get length native "GrowableList_getLength"; - int get _capacity native "GrowableObjectArray_getCapacity"; + int get _capacity native "GrowableList_getCapacity"; void set length(int new_length) { if (new_length > _capacity) { @@ -161,13 +161,13 @@ _setLength(new_length); } - void _setLength(int new_length) native "GrowableObjectArray_setLength"; + void _setLength(int new_length) native "GrowableList_setLength"; - void _setData(_ObjectArray array) native "GrowableObjectArray_setData"; + void _setData(_List array) native "GrowableList_setData"; - T operator [](int index) native "GrowableObjectArray_getIndexed"; + T operator [](int index) native "GrowableList_getIndexed"; - void operator []=(int index, T value) native "GrowableObjectArray_setIndexed"; + void operator []=(int index, T value) native "GrowableList_setIndexed"; // The length of this growable array. It is always less than or equal to the // length of the object array, which itself is always greater than 0, so that @@ -221,7 +221,7 @@ } void _grow(int new_length) { - var new_data = new _ObjectArray(new_length); + var new_data = new _List(new_length); for (int i = 0; i < length; i++) { new_data[i] = this[i]; }
diff --git a/runtime/lib/immutable_map.dart b/runtime/lib/immutable_map.dart index 65db0c9..475051f 100644 --- a/runtime/lib/immutable_map.dart +++ b/runtime/lib/immutable_map.dart
@@ -4,9 +4,9 @@ // Immutable map class for compiler generated map literals. class ImmutableMap<K, V> implements Map<K, V> { - final _ImmutableArray _kvPairs; + final _ImmutableList _kvPairs; - const ImmutableMap._create(_ImmutableArray keyValuePairs) + const ImmutableMap._create(_ImmutableList keyValuePairs) : _kvPairs = keyValuePairs;
diff --git a/runtime/lib/integers.cc b/runtime/lib/integers.cc index 84dc9d6..dedb88d 100644 --- a/runtime/lib/integers.cc +++ b/runtime/lib/integers.cc
@@ -232,9 +232,7 @@ const Smi& amount, const bool silent = false) { if (amount.Value() < 0) { - const Array& args = Array::Handle(Array::New(1)); - args.SetAt(0, amount); - Exceptions::ThrowByType(Exceptions::kArgument, args); + Exceptions::ThrowArgumentError(amount); } if (value.IsSmi()) { const Smi& smi_value = Smi::Cast(value);
diff --git a/runtime/lib/integers.dart b/runtime/lib/integers.dart index cec9518..50a3ab0 100644 --- a/runtime/lib/integers.dart +++ b/runtime/lib/integers.dart
@@ -187,31 +187,53 @@ return this.toDouble().toStringAsPrecision(precision); } + static const _digits = "0123456789abcdefghijklmnopqrstuvwxyz"; + String toRadixString(int radix) { - final table = const ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", - "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", - "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", - "u", "v", "w", "x", "y", "z"]; if (radix is! int || radix < 2 || radix > 36) { throw new ArgumentError(radix); } + if (radix & (radix - 1) == 0) { + return _toPow2String(this, radix); + } + if (radix == 10) return this.toString(); final bool isNegative = this < 0; int value = isNegative ? -this : this; List temp = new List(); - while (value > 0) { + do { int digit = value % radix; value ~/= radix; - temp.add(digit); + temp.add(_digits.codeUnitAt(digit)); + } while (value > 0); + if (isNegative) temp.add(0x2d); // '-'. + + _OneByteString string = _OneByteString._allocate(temp.length); + for (int i = 0, j = temp.length; j > 0; i++) { + string._setAt(i, temp[--j]); } - if (temp.isEmpty) { - return "0"; + return string; + } + + static String _toPow2String(value, radix) { + if (value == 0) return "0"; + assert(radix & (radix - 1) == 0); + var negative = value < 0; + var bitsPerDigit = radix.bitLength - 1; + var length = 0; + if (negative) { + value = -value; + length = 1; } - StringBuffer buffer = new StringBuffer(); - if (isNegative) buffer.write("-"); - for (int i = temp.length - 1; i >= 0; i--) { - buffer.write(table[temp[i]]); - } - return buffer.toString(); + // Integer division, rounding up, to find number of _digits. + length += (value.bitLength + bitsPerDigit - 1) ~/ bitsPerDigit; + _OneByteString string = _OneByteString._allocate(length); + string._setAt(0, 0x2d); // '-'. Is overwritten if not negative. + var mask = radix - 1; + do { + string._setAt(--length, _digits.codeUnitAt(value & mask)); + value >>= bitsPerDigit; + } while (value > 0); + return string; } _leftShiftWithMask32(count, mask) native "Integer_leftShiftWithMask32";
diff --git a/runtime/lib/isolate.cc b/runtime/lib/isolate.cc index 8880d2306..9cfcddf 100644 --- a/runtime/lib/isolate.cc +++ b/runtime/lib/isolate.cc
@@ -114,13 +114,6 @@ } -static void ThrowIllegalArgException(const String& message) { - const Array& args = Array::Handle(Array::New(1)); - args.SetAt(0, message); - Exceptions::ThrowByType(Exceptions::kArgument, args); -} - - static void ThrowIsolateSpawnException(const String& message) { const Array& args = Array::Handle(Array::New(1)); args.SetAt(0, message); @@ -239,7 +232,7 @@ const String& msg = String::Handle(String::New( "spawnFunction expects to be passed a closure to a top-level static " "function")); - ThrowIllegalArgException(msg); + Exceptions::ThrowArgumentError(msg); } GET_NATIVE_ARGUMENT(Instance, callback, arguments->NativeArgAt(1)); @@ -258,7 +251,7 @@ const String& msg = String::Handle(String::New( "spawnFunction expects to be passed either a unhandled exception " "callback to a top-level static function, or null")); - ThrowIllegalArgException(msg); + Exceptions::ThrowArgumentError(msg); } #if defined(DEBUG)
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc index 8e71843..754aa5f 100644 --- a/runtime/lib/mirrors.cc +++ b/runtime/lib/mirrors.cc
@@ -742,9 +742,7 @@ const Class& cls = Class::Handle(type.type_class()); ASSERT(!cls.IsNull()); if (cls.IsDynamicClass() || cls.IsVoidClass()) { - const Array& args = Array::Handle(Array::New(1)); - args.SetAt(0, type); - Exceptions::ThrowByType(Exceptions::kArgument, args); + Exceptions::ThrowArgumentError(type); UNREACHABLE(); } const Type& stripped_type = Type::Handle(cls.RareType()); @@ -1410,11 +1408,31 @@ UNREACHABLE(); } + ASSERT(!type.IsNull()); + AbstractTypeArguments& type_arguments = + AbstractTypeArguments::Handle(type.arguments()); + Class& redirected_klass = Class::Handle(klass.raw()); Function& redirected_constructor = Function::Handle(lookup_constructor.raw()); if (lookup_constructor.IsRedirectingFactory()) { ClassFinalizer::ResolveRedirectingFactory(klass, lookup_constructor); - Type& type = Type::Handle(lookup_constructor.RedirectionType()); + Type& redirect_type = Type::Handle(lookup_constructor.RedirectionType()); + + if (!redirect_type.IsInstantiated()) { + // The type arguments of the redirection type are instantiated from the + // type arguments of the type reflected by the class mirror. + Error& malformed_error = Error::Handle(); + redirect_type ^= redirect_type.InstantiateFrom(type_arguments, + &malformed_error); + if (!malformed_error.IsNull()) { + ThrowInvokeError(malformed_error); + UNREACHABLE(); + } + } + + type = redirect_type.raw(); + type_arguments = redirect_type.arguments(); + redirected_constructor = lookup_constructor.RedirectionTarget(); ASSERT(!redirected_constructor.IsNull()); redirected_klass = type.type_class(); @@ -1451,10 +1469,6 @@ UNREACHABLE(); } - ASSERT(!type.IsNull()); - const AbstractTypeArguments& type_arguments = - AbstractTypeArguments::Handle(type.arguments()); - Instance& new_object = Instance::Handle(); if (redirected_constructor.IsConstructor()) { // Constructors get the uninitialized object and a constructor phase. Note
diff --git a/runtime/lib/string.cc b/runtime/lib/string.cc index 0127c15..bab0aba 100644 --- a/runtime/lib/string.cc +++ b/runtime/lib/string.cc
@@ -15,9 +15,7 @@ DEFINE_NATIVE_ENTRY(StringBase_createFromCodePoints, 1) { GET_NON_NULL_NATIVE_ARGUMENT(Instance, list, arguments->NativeArgAt(0)); if (!list.IsGrowableObjectArray() && !list.IsArray()) { - const Array& args = Array::Handle(Array::New(1)); - args.SetAt(0, list); - Exceptions::ThrowByType(Exceptions::kArgument, args); + Exceptions::ThrowArgumentError(list); } Array& a = Array::Handle(); @@ -37,13 +35,11 @@ bool is_one_byte_string = true; intptr_t utf16_len = array_len; int32_t* utf32_array = zone->Alloc<int32_t>(array_len); - Object& index_object = Object::Handle(isolate); + Instance& index_object = Instance::Handle(isolate); for (intptr_t i = 0; i < array_len; i++) { - index_object = a.At(i); + index_object ^= a.At(i); if (!index_object.IsSmi()) { - const Array& args = Array::Handle(Array::New(1)); - args.SetAt(0, index_object); - Exceptions::ThrowByType(Exceptions::kArgument, args); + Exceptions::ThrowArgumentError(index_object); } intptr_t value = Smi::Cast(index_object).Value(); if (Utf::IsOutOfRange(value)) { @@ -214,20 +210,39 @@ } -DEFINE_NATIVE_ENTRY(Strings_concatAll, 1) { - GET_NON_NULL_NATIVE_ARGUMENT(Array, strings, arguments->NativeArgAt(0)); - ASSERT(!strings.IsNull()); +DEFINE_NATIVE_ENTRY(Strings_concatAll, 3) { + GET_NON_NULL_NATIVE_ARGUMENT(Instance, argument, arguments->NativeArgAt(0)); + GET_NON_NULL_NATIVE_ARGUMENT(Smi, start, arguments->NativeArgAt(1)); + GET_NON_NULL_NATIVE_ARGUMENT(Smi, end, arguments->NativeArgAt(2)); + const intptr_t start_ix = start.Value(); + const intptr_t end_ix = end.Value(); + if (start_ix < 0) { + Exceptions::ThrowArgumentError(start); + } + Array& strings = Array::Handle(); + intptr_t length = -1; + if (argument.IsArray()) { + strings ^= argument.raw(); + length = strings.Length(); + } else if (argument.IsGrowableObjectArray()) { + const GrowableObjectArray& g_array = GrowableObjectArray::Cast(argument); + strings = g_array.data(); + length = g_array.Length(); + } else { + Exceptions::ThrowArgumentError(argument); + } + if (end_ix > length) { + Exceptions::ThrowArgumentError(end); + } +#if defined(DEBUG) // Check that the array contains strings. Instance& elem = Instance::Handle(); - for (intptr_t i = 0; i < strings.Length(); i++) { + for (intptr_t i = start_ix; i < end_ix; i++) { elem ^= strings.At(i); - if (!elem.IsString()) { - const Array& args = Array::Handle(Array::New(1)); - args.SetAt(0, elem); - Exceptions::ThrowByType(Exceptions::kArgument, args); - } + ASSERT(elem.IsString()); } - return String::ConcatAll(strings); +#endif + return String::ConcatAllRange(strings, start_ix, end_ix, Heap::kNew); }
diff --git a/runtime/lib/string_buffer_patch.dart b/runtime/lib/string_buffer_patch.dart index 9a22647..72ec095 100644 --- a/runtime/lib/string_buffer_patch.dart +++ b/runtime/lib/string_buffer_patch.dart
@@ -11,7 +11,7 @@ * When strings are written to the string buffer, we add them to a * list of string parts. */ - List _parts = null; + List<String> _parts = null; /** * Total number of code units in the string parts. Does not include @@ -28,11 +28,10 @@ */ int _partsCompactionIndex = 0; int _partsCodeUnitsSinceCompaction = 0; - _ObjectArray _partsCompactionArray = null; /** * The buffer is used to build up a string from code units. It is - * used when writing short strings or individul char codes to the + * used when writing short strings or individual char codes to the * buffer. The buffer is allocated on demand. */ Uint16List _buffer = null; @@ -101,15 +100,9 @@ /** Returns the contents of buffer as a string. */ /* patch */ String toString() { _consumeBuffer(); - if (_partsCodeUnits == 0) return ""; - - // TODO(kasperl): It would be nice if concatAllNative would - // allow me to pass in a grownable array directly, but for - // now we have to copy the contents to a non-growable array. - int length = _parts.length; - _ObjectArray array = new _ObjectArray(length); - for (int i = 0; i < length; i++) array[i] = _parts[i]; - return _StringBase._concatAllNative(array); + return (_partsCodeUnits == 0) ? + "" : + _StringBase._concatAllNative(_parts, 0, _parts.length); } /** Ensures that the buffer has enough capacity to add n code units. */ @@ -160,18 +153,13 @@ */ void _compact() { if (_partsCodeUnitsSinceCompaction < _PARTS_TO_COMPACT_SIZE_LIMIT) { - if (_partsCompactionArray == null) { - _partsCompactionArray = new _ObjectArray(_PARTS_TO_COMPACT); - } - for (int i = 0; i < _PARTS_TO_COMPACT; i++) { - _partsCompactionArray[i] = _parts[i + _partsCompactionIndex]; - } - String compacted = _StringBase._concatAllNative(_partsCompactionArray); + String compacted = _StringBase._concatAllNative( + _parts, + _partsCompactionIndex, // Start + _partsCompactionIndex + _PARTS_TO_COMPACT // End + ); _parts.length = _parts.length - _PARTS_TO_COMPACT; _parts.add(compacted); - for (int i = 0; i < _PARTS_TO_COMPACT; i++) { - _partsCompactionArray[i] = null; - } } _partsCodeUnitsSinceCompaction = 0; _partsCompactionIndex = _parts.length;
diff --git a/runtime/lib/string_patch.dart b/runtime/lib/string_patch.dart index e4f959e..d3285b2 100644 --- a/runtime/lib/string_patch.dart +++ b/runtime/lib/string_patch.dart
@@ -30,9 +30,9 @@ if (charCodes != null) { // TODO(srdjan): Also skip copying of typed arrays. final ccid = charCodes._cid; - if ((ccid != _ObjectArray._classId) && - (ccid != _GrowableObjectArray._classId) && - (ccid != _ImmutableArray._classId)) { + if ((ccid != _List._classId) && + (ccid != _GrowableList._classId) && + (ccid != _ImmutableList._classId)) { charCodes = new List<int>.from(charCodes, growable: false); } @@ -395,9 +395,9 @@ * Convert all objects in [values] to strings and concat them * into a result string. */ - static String _interpolate(List values) { + static String _interpolate(List<String> values) { final int numValues = values.length; - _ObjectArray stringList = new List(numValues); + _List stringList = new List<String>(numValues); bool isOneByteString = true; int totalLength = 0; for (int i = 0; i < numValues; i++) { @@ -406,13 +406,16 @@ totalLength += s.length; } else { isOneByteString = false; + if (s is! String) { + throw new ArgumentError(s); + } } stringList[i] = s; } if (isOneByteString) { return _OneByteString._concatAll(stringList, totalLength); } - return _concatAllNative(stringList); + return _concatAllNative(stringList, 0, stringList.length); } Iterable<Match> allMatches(String str) { @@ -497,8 +500,9 @@ String toLowerCase() native "String_toLowerCase"; - // Call this method if not all list elements are OneByteString-s. - static String _concatAllNative(_ObjectArray<String> strings) + // Call this method if not all list elements are known to be OneByteString(s). + // 'strings' must be an _List or _GrowableList. + static String _concatAllNative(List<String> strings, int start, int end) native "Strings_concatAll"; } @@ -531,11 +535,11 @@ } // All element of 'strings' must be OneByteStrings. - static _concatAll(_ObjectArray<String> strings, int totalLength) { + static _concatAll(_List<String> strings, int totalLength) { // TODO(srdjan): Improve code below and raise or eliminate the limit. if (totalLength > 128) { // Native is quicker. - return _StringBase._concatAllNative(strings); + return _StringBase._concatAllNative(strings, 0, strings.length); } var res = _OneByteString._allocate(totalLength); final stringsLength = strings.length;
diff --git a/runtime/lib/typed_data.cc b/runtime/lib/typed_data.cc index 6690085..ff4d00b 100644 --- a/runtime/lib/typed_data.cc +++ b/runtime/lib/typed_data.cc
@@ -38,9 +38,7 @@ const String& error = String::Handle(String::NewFormatted( "Length (%" Pd ") of object must be in range [0..%" Pd "]", len, max)); - const Array& args = Array::Handle(Array::New(1)); - args.SetAt(0, error); - Exceptions::ThrowByType(Exceptions::kArgument, args); + Exceptions::ThrowArgumentError(error); } } @@ -63,9 +61,7 @@ } const String& error = String::Handle(String::NewFormatted( "Expected a TypedData object but found %s", instance.ToCString())); - const Array& args = Array::Handle(Array::New(1)); - args.SetAt(0, error); - Exceptions::ThrowByType(Exceptions::kArgument, args); + Exceptions::ThrowArgumentError(error); return Integer::null(); } @@ -107,9 +103,7 @@ if (length.Value() < 0) { const String& error = String::Handle(String::NewFormatted( "length (%" Pd ") must be non-negative", length.Value())); - const Array& args = Array::Handle(Array::New(1)); - args.SetAt(0, error); - Exceptions::ThrowByType(Exceptions::kArgument, args); + Exceptions::ThrowArgumentError(error); } if (dst.IsTypedData()) { if (src.IsTypedData()) { @@ -193,9 +187,7 @@ } \ const String& error = String::Handle(String::NewFormatted( \ "Expected a TypedData object but found %s", instance.ToCString())); \ - const Array& args = Array::Handle(Array::New(1)); \ - args.SetAt(0, error); \ - Exceptions::ThrowByType(Exceptions::kArgument, args); \ + Exceptions::ThrowArgumentError(error); \ return object::null(); \ } \ @@ -218,9 +210,7 @@ } else { \ const String& error = String::Handle(String::NewFormatted( \ "Expected a TypedData object but found %s", instance.ToCString())); \ - const Array& args = Array::Handle(Array::New(1)); \ - args.SetAt(0, error); \ - Exceptions::ThrowByType(Exceptions::kArgument, args); \ + Exceptions::ThrowArgumentError(error); \ } \ return Object::null(); \ } @@ -242,9 +232,7 @@ } else { \ const String& error = String::Handle(String::NewFormatted( \ "Expected a TypedData object but found %s", instance.ToCString())); \ - const Array& args = Array::Handle(Array::New(1)); \ - args.SetAt(0, error); \ - Exceptions::ThrowByType(Exceptions::kArgument, args); \ + Exceptions::ThrowArgumentError(error); \ } \ return Integer::NewFromUint64(value); \ } \ @@ -277,9 +265,7 @@ } else { \ const String& error = String::Handle(String::NewFormatted( \ "Expected a TypedData object but found %s", instance.ToCString())); \ - const Array& args = Array::Handle(Array::New(1)); \ - args.SetAt(0, error); \ - Exceptions::ThrowByType(Exceptions::kArgument, args); \ + Exceptions::ThrowArgumentError(error); \ } \ return Object::null(); \ }
diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status index 744aa61..445dd40 100644 --- a/runtime/tests/vm/vm.status +++ b/runtime/tests/vm/vm.status
@@ -66,3 +66,6 @@ [ $compiler == dart2analyzer ] # has compilation error, as designed dart/isolate_mirror_local_test: fail + +[ $compiler == none && $runtime == dartium ] +dart/isolate_mirror_local_test: Fail # Issue 13719: Please triage this failure.
diff --git a/runtime/vm/assembler_x64.cc b/runtime/vm/assembler_x64.cc index f7b0ea3..cc93724 100644 --- a/runtime/vm/assembler_x64.cc +++ b/runtime/vm/assembler_x64.cc
@@ -204,6 +204,16 @@ } +void Assembler::PushImmediate(const Immediate& imm, Register pp) { + if (CanLoadImmediateFromPool(imm, pp)) { + LoadImmediate(TMP, imm, pp); + pushq(TMP); + } else { + pushq(imm); + } +} + + void Assembler::popq(Register reg) { AssemblerBuffer::EnsureCapacity ensured(&buffer_); EmitRegisterREX(reg, REX_NONE); @@ -813,7 +823,8 @@ uint32_t d; } float_not_constant = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; - movq(TMP, Immediate(reinterpret_cast<intptr_t>(&float_not_constant))); + LoadImmediate( + TMP, Immediate(reinterpret_cast<intptr_t>(&float_not_constant)), PP); xorps(dst, Address(TMP, 0)); } @@ -826,7 +837,8 @@ uint32_t d; } float_negate_constant = { 0x80000000, 0x80000000, 0x80000000, 0x80000000 }; - movq(TMP, Immediate(reinterpret_cast<intptr_t>(&float_negate_constant))); + LoadImmediate( + TMP, Immediate(reinterpret_cast<intptr_t>(&float_negate_constant)), PP); xorps(dst, Address(TMP, 0)); } @@ -839,7 +851,8 @@ uint32_t d; } float_absolute_constant = { 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF }; - movq(TMP, Immediate(reinterpret_cast<intptr_t>(&float_absolute_constant))); + LoadImmediate( + TMP, Immediate(reinterpret_cast<intptr_t>(&float_absolute_constant)), PP); andps(dst, Address(TMP, 0)); } @@ -852,7 +865,8 @@ uint32_t d; } float_zerow_constant = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000 }; - movq(TMP, Immediate(reinterpret_cast<intptr_t>(&float_zerow_constant))); + LoadImmediate( + TMP, Immediate(reinterpret_cast<intptr_t>(&float_zerow_constant)), PP); andps(dst, Address(TMP, 0)); } @@ -1342,6 +1356,28 @@ } +void Assembler::CompareImmediate(Register reg, const Immediate& imm, + Register pp) { + if (CanLoadImmediateFromPool(imm, pp)) { + LoadImmediate(TMP, imm, pp); + cmpq(reg, TMP); + } else { + cmpq(reg, imm); + } +} + + +void Assembler::CompareImmediate(const Address& address, const Immediate& imm, + Register pp) { + if (CanLoadImmediateFromPool(imm, pp)) { + LoadImmediate(TMP, imm, pp); + cmpq(address, TMP); + } else { + cmpq(address, imm); + } +} + + void Assembler::testl(Register reg1, Register reg2) { AssemblerBuffer::EnsureCapacity ensured(&buffer_); Operand operand(reg2); @@ -1492,6 +1528,17 @@ } +void Assembler::AndImmediate(Register dst, const Immediate& imm, Register pp) { + if (CanLoadImmediateFromPool(imm, pp)) { + ASSERT(dst != TMP); + LoadImmediate(TMP, imm, pp); + andq(dst, TMP); + } else { + andq(dst, imm); + } +} + + void Assembler::orq(Register dst, Register src) { AssemblerBuffer::EnsureCapacity ensured(&buffer_); Operand operand(src); @@ -1521,6 +1568,17 @@ } +void Assembler::OrImmediate(Register dst, const Immediate& imm, Register pp) { + if (CanLoadImmediateFromPool(imm, pp)) { + ASSERT(dst != TMP); + LoadImmediate(TMP, imm, pp); + orq(dst, TMP); + } else { + orq(dst, imm); + } +} + + void Assembler::xorq(Register dst, Register src) { AssemblerBuffer::EnsureCapacity ensured(&buffer_); Operand operand(src); @@ -1558,6 +1616,17 @@ } +void Assembler::XorImmediate(Register dst, const Immediate& imm, Register pp) { + if (CanLoadImmediateFromPool(imm, pp)) { + ASSERT(dst != TMP); + LoadImmediate(TMP, imm, pp); + xorq(dst, TMP); + } else { + xorq(dst, imm); + } +} + + void Assembler::addl(Register dst, Register src) { AssemblerBuffer::EnsureCapacity ensured(&buffer_); Operand operand(src); @@ -1602,9 +1671,14 @@ void Assembler::addq(const Address& address, const Immediate& imm) { - // TODO(srdjan): Implement shorter version for imm32. - movq(TMP, imm); - addq(address, TMP); + if (imm.is_int32()) { + AssemblerBuffer::EnsureCapacity ensured(&buffer_); + EmitOperandREX(0, address, REX_W); + EmitComplex(0, Operand(address), imm); + } else { + movq(TMP, imm); + addq(address, TMP); + } } @@ -1708,6 +1782,17 @@ } +void Assembler::MulImmediate(Register reg, const Immediate& imm, Register pp) { + if (CanLoadImmediateFromPool(imm, pp)) { + ASSERT(reg != TMP); + LoadImmediate(TMP, imm, pp); + imulq(reg, TMP); + } else { + imulq(reg, imm); + } +} + + void Assembler::imulq(Register dst, const Address& address) { AssemblerBuffer::EnsureCapacity ensured(&buffer_); EmitOperandREX(dst, address, REX_W); @@ -1746,6 +1831,26 @@ } +void Assembler::subq(const Address& address, Register reg) { + AssemblerBuffer::EnsureCapacity ensured(&buffer_); + EmitOperandREX(reg, address, REX_W); + EmitUint8(0x29); + EmitOperand(reg & 7, address); +} + + +void Assembler::subq(const Address& address, const Immediate& imm) { + if (imm.is_int32()) { + AssemblerBuffer::EnsureCapacity ensured(&buffer_); + EmitOperandREX(0, address, REX_W); + EmitComplex(5, Operand(address), imm); + } else { + movq(TMP, imm); + subq(address, TMP); + } +} + + void Assembler::shll(Register reg, const Immediate& imm) { EmitGenericShift(false, 4, reg, imm); } @@ -2138,20 +2243,64 @@ } -void Assembler::AddImmediate(Register reg, const Immediate& imm) { +void Assembler::AddImmediate(Register reg, const Immediate& imm, Register pp) { int64_t value = imm.value(); if (value > 0) { if (value == 1) { incq(reg); } else if (value != 0) { - addq(reg, imm); + if (CanLoadImmediateFromPool(imm, pp)) { + ASSERT(reg != TMP); + LoadImmediate(TMP, imm, pp); + addq(reg, TMP); + } else { + addq(reg, imm); + } } } else if (value < 0) { value = -value; if (value == 1) { decq(reg); } else if (value != 0) { - subq(reg, Immediate(value)); + const Immediate& s = Immediate(value); + if (CanLoadImmediateFromPool(s, pp)) { + ASSERT(reg != TMP); + LoadImmediate(TMP, s, pp); + subq(reg, TMP); + } else { + subq(reg, Immediate(value)); + } + } + } +} + + +void Assembler::AddImmediate(const Address& address, const Immediate& imm, + Register pp) { + int64_t value = imm.value(); + if (value > 0) { + if (value == 1) { + incq(address); + } else if (value != 0) { + if (CanLoadImmediateFromPool(imm, pp)) { + LoadImmediate(TMP, imm, pp); + addq(address, TMP); + } else { + addq(address, imm); + } + } + } else if (value < 0) { + value = -value; + if (value == 1) { + decq(address); + } else if (value != 0) { + const Immediate& s = Immediate(value); + if (CanLoadImmediateFromPool(s, pp)) { + LoadImmediate(TMP, s, pp); + subq(address, TMP); + } else { + subq(address, s); + } } } } @@ -2261,38 +2410,86 @@ ASSERT((Isolate::Current() == Dart::vm_isolate()) || object.IsSmi() || object.InVMHeap()); - movq(dst, Immediate(reinterpret_cast<int64_t>(object.raw()))); + LoadImmediate(dst, Immediate(reinterpret_cast<int64_t>(object.raw())), pp); } } -void Assembler::StoreObject(const Address& dst, const Object& object) { +void Assembler::StoreObject(const Address& dst, const Object& object, + Register pp) { if (CanLoadFromObjectPool(object)) { - LoadObject(TMP, object, PP); + LoadObject(TMP, object, pp); movq(dst, TMP); } else { - movq(dst, Immediate(reinterpret_cast<int64_t>(object.raw()))); + LoadImmediate(dst, Immediate(reinterpret_cast<int64_t>(object.raw())), pp); } } -void Assembler::PushObject(const Object& object) { +void Assembler::PushObject(const Object& object, Register pp) { if (CanLoadFromObjectPool(object)) { - LoadObject(TMP, object, PP); + LoadObject(TMP, object, pp); pushq(TMP); } else { - pushq(Immediate(reinterpret_cast<int64_t>(object.raw()))); + PushImmediate(Immediate(reinterpret_cast<int64_t>(object.raw())), pp); } } -void Assembler::CompareObject(Register reg, const Object& object) { +void Assembler::CompareObject(Register reg, const Object& object, Register pp) { if (CanLoadFromObjectPool(object)) { ASSERT(reg != TMP); - LoadObject(TMP, object, PP); + LoadObject(TMP, object, pp); cmpq(reg, TMP); } else { - cmpq(reg, Immediate(reinterpret_cast<int64_t>(object.raw()))); + CompareImmediate( + reg, Immediate(reinterpret_cast<int64_t>(object.raw())), pp); + } +} + + +intptr_t Assembler::FindImmediate(int64_t imm) { + ASSERT(Isolate::Current() != Dart::vm_isolate()); + ASSERT(!object_pool_.IsNull()); + const Smi& smi = Smi::Handle(reinterpret_cast<RawSmi*>(imm)); + return FindObject(smi, kNotPatchable); +} + + +bool Assembler::CanLoadImmediateFromPool(const Immediate& imm, Register pp) { + return !imm.is_int32() && + (pp != kNoRegister) && + (Isolate::Current() != Dart::vm_isolate()); +} + + +void Assembler::LoadImmediate(Register reg, const Immediate& imm, Register pp) { + if (CanLoadImmediateFromPool(imm, pp)) { + // It's a 64-bit constant and we're not in the VM isolate, so load from + // object pool. + int64_t val = imm.value(); + // Save the bits that must be masked-off for the SmiTag + int64_t val_smi_tag = val & kSmiTagMask; + val &= ~kSmiTagMask; // Mask off the tag bits. + const int32_t offset = Array::element_offset(FindImmediate(val)); + LoadWordFromPoolOffset(reg, pp, offset - kHeapObjectTag); + if (val_smi_tag != 0) { + // Add back the tag bits. + orq(reg, Immediate(val_smi_tag)); + } + } else { + movq(reg, imm); + } +} + + +void Assembler::LoadImmediate(const Address& dst, const Immediate& imm, + Register pp) { + if (CanLoadImmediateFromPool(imm, pp)) { + LoadImmediate(TMP, imm, pp); + movq(dst, TMP); + } else { + movq(dst, imm); } } @@ -2383,7 +2580,8 @@ uint64_t b; } double_negate_constant = {0x8000000000000000LL, 0x8000000000000000LL}; - movq(TMP, Immediate(reinterpret_cast<intptr_t>(&double_negate_constant))); + LoadImmediate( + TMP, Immediate(reinterpret_cast<intptr_t>(&double_negate_constant)), PP); xorpd(d, Address(TMP, 0)); } @@ -2394,7 +2592,8 @@ uint64_t b; } double_abs_constant = {0x7FFFFFFFFFFFFFFFLL, 0x7FFFFFFFFFFFFFFFLL}; - movq(TMP, Immediate(reinterpret_cast<intptr_t>(&double_abs_constant))); + LoadImmediate(TMP, + Immediate(reinterpret_cast<intptr_t>(&double_abs_constant)), PP); andpd(reg, Address(TMP, 0)); } @@ -2404,7 +2603,7 @@ if (FLAG_print_stop_message) { pushq(TMP); // Preserve TMP register. pushq(RDI); // Preserve RDI register. - movq(RDI, Immediate(message_address)); + LoadImmediate(RDI, Immediate(message_address), PP); call(&StubCode::PrintStopMessageLabel()); popq(RDI); // Restore RDI register. popq(TMP); // Restore TMP register. @@ -2477,7 +2676,9 @@ void Assembler::ReserveAlignedFrameSpace(intptr_t frame_space) { // Reserve space for arguments and align frame before entering // the C++ world. - AddImmediate(RSP, Immediate(-frame_space)); + if (frame_space != 0) { + subq(RSP, Immediate(frame_space)); + } if (OS::ActivationFrameAlignment() > 1) { andq(RSP, Immediate(~(OS::ActivationFrameAlignment() - 1))); } @@ -2667,29 +2868,31 @@ void Assembler::TryAllocate(const Class& cls, Label* failure, bool near_jump, - Register instance_reg) { + Register instance_reg, + Register pp) { ASSERT(failure != NULL); if (FLAG_inline_alloc) { Heap* heap = Isolate::Current()->heap(); const intptr_t instance_size = cls.instance_size(); - movq(TMP, Immediate(heap->TopAddress())); + LoadImmediate(TMP, Immediate(heap->TopAddress()), pp); movq(instance_reg, Address(TMP, 0)); - addq(instance_reg, Immediate(instance_size)); + AddImmediate(instance_reg, Immediate(instance_size), pp); // instance_reg: potential next object start. - movq(TMP, Immediate(heap->EndAddress())); + LoadImmediate(TMP, Immediate(heap->EndAddress()), pp); cmpq(instance_reg, Address(TMP, 0)); j(ABOVE_EQUAL, failure, near_jump); // Successfully allocated the object, now update top to point to // next object start and store the class in the class field of object. - movq(TMP, Immediate(heap->TopAddress())); + LoadImmediate(TMP, Immediate(heap->TopAddress()), pp); movq(Address(TMP, 0), instance_reg); ASSERT(instance_size >= kHeapObjectTag); - subq(instance_reg, Immediate(instance_size - kHeapObjectTag)); + AddImmediate(instance_reg, Immediate(kHeapObjectTag - instance_size), pp); uword tags = 0; tags = RawObject::SizeTag::update(instance_size, tags); ASSERT(cls.id() != kIllegalCid); tags = RawObject::ClassIdTag::update(cls.id(), tags); - movq(FieldAddress(instance_reg, Object::tags_offset()), Immediate(tags)); + LoadImmediate(FieldAddress(instance_reg, Object::tags_offset()), + Immediate(tags), pp); } else { jmp(failure); }
diff --git a/runtime/vm/assembler_x64.h b/runtime/vm/assembler_x64.h index 4aa070c..5f17299 100644 --- a/runtime/vm/assembler_x64.h +++ b/runtime/vm/assembler_x64.h
@@ -356,6 +356,7 @@ void pushq(Register reg); void pushq(const Address& address); void pushq(const Immediate& imm); + void PushImmediate(const Immediate& imm, Register pp); void popq(Register reg); void popq(const Address& address); @@ -489,6 +490,10 @@ void cmpq(Register reg0, Register reg1); void cmpq(Register reg, const Address& address); + void CompareImmediate(Register reg, const Immediate& imm, Register pp); + void CompareImmediate(const Address& address, const Immediate& imm, + Register pp); + void testl(Register reg1, Register reg2); void testl(Register reg, const Immediate& imm); @@ -506,15 +511,18 @@ void andq(Register dst, Register src); void andq(Register dst, const Address& address); void andq(Register dst, const Immediate& imm); + void AndImmediate(Register dst, const Immediate& imm, Register pp); void orq(Register dst, Register src); void orq(Register dst, const Address& address); void orq(Register dst, const Immediate& imm); + void OrImmediate(Register dst, const Immediate& imm, Register pp); void xorq(Register dst, Register src); void xorq(Register dst, const Address& address); void xorq(const Address& dst, Register src); void xorq(Register dst, const Immediate& imm); + void XorImmediate(Register dst, const Immediate& imm, Register pp); void addl(Register dst, Register src); void addl(const Address& address, const Immediate& imm); @@ -541,10 +549,13 @@ void imulq(Register dst, Register src); void imulq(Register dst, const Address& address); void imulq(Register dst, const Immediate& imm); + void MulImmediate(Register reg, const Immediate& imm, Register pp); void subq(Register dst, Register src); void subq(Register reg, const Immediate& imm); void subq(Register reg, const Address& address); + void subq(const Address& address, Register reg); + void subq(const Address& address, const Immediate& imm); void shll(Register reg, const Immediate& imm); void shll(Register operand, Register shifter); @@ -657,7 +668,8 @@ void MoveRegister(Register to, Register from); void PopRegister(Register r); - void AddImmediate(Register reg, const Immediate& imm); + void AddImmediate(Register reg, const Immediate& imm, Register pp); + void AddImmediate(const Address& address, const Immediate& imm, Register pp); void Drop(intptr_t stack_elements); @@ -666,15 +678,18 @@ kNotPatchable, }; + bool CanLoadImmediateFromPool(const Immediate& imm, Register pp); + void LoadImmediate(Register reg, const Immediate& imm, Register pp); + void LoadImmediate(const Address& dst, const Immediate& imm, Register pp); void LoadObject(Register dst, const Object& obj, Register pp); void JmpPatchable(const ExternalLabel* label, Register pp); void Jmp(const ExternalLabel* label, Register pp); void J(Condition condition, const ExternalLabel* label, Register pp); void CallPatchable(const ExternalLabel* label); void Call(const ExternalLabel* label, Register pp); - void StoreObject(const Address& dst, const Object& obj); - void PushObject(const Object& object); - void CompareObject(Register reg, const Object& object); + void StoreObject(const Address& dst, const Object& obj, Register pp); + void PushObject(const Object& object, Register pp); + void CompareObject(Register reg, const Object& object, Register pp); void LoadDoubleConstant(XmmRegister dst, double value); // Destroys value. @@ -812,10 +827,13 @@ // calls. Jump to 'failure' if the instance cannot be allocated here. // Allocated instance is returned in 'instance_reg'. // Only the tags field of the object is initialized. + // Loads large immediates from the object pool with pool pointer in PP if it + // is not kNoRegister void TryAllocate(const Class& cls, Label* failure, bool near_jump, - Register instance_reg); + Register instance_reg, + Register pp); // Debugging and bringup support. void Stop(const char* message); @@ -901,6 +919,7 @@ intptr_t FindObject(const Object& obj, Patchability patchable); intptr_t FindExternalLabel(const ExternalLabel* label, Patchability patchable); + intptr_t FindImmediate(int64_t imm); void LoadExternalLabel(Register dst, const ExternalLabel* label, Patchability patchable,
diff --git a/runtime/vm/assembler_x64_test.cc b/runtime/vm/assembler_x64_test.cc index 2d148cd..fd68d8e 100644 --- a/runtime/vm/assembler_x64_test.cc +++ b/runtime/vm/assembler_x64_test.cc
@@ -1292,14 +1292,14 @@ ExternalLabel call2("LeafReturnArgument", reinterpret_cast<uword>(LeafReturnArgument)); int space = ComputeStackSpaceReservation(0, 8); - __ AddImmediate(RSP, Immediate(-space)); + __ subq(RSP, Immediate(space)); __ call(&call1); - __ AddImmediate(RSP, Immediate(space)); + __ addq(RSP, Immediate(space)); space = ComputeStackSpaceReservation(0, 8); - __ AddImmediate(RSP, Immediate(-space)); + __ subq(RSP, Immediate(space)); __ movl(RDI, RAX); __ call(&call2); - __ AddImmediate(RSP, Immediate(space)); + __ addq(RSP, Immediate(space)); __ ret(); } @@ -1314,9 +1314,9 @@ ExternalLabel call1("LeafReturn42", reinterpret_cast<uword>(LeafReturn42)); Label L; int space = ComputeStackSpaceReservation(0, 8); - __ AddImmediate(RSP, Immediate(-space)); + __ subq(RSP, Immediate(space)); __ call(&L); - __ AddImmediate(RSP, Immediate(space)); + __ addq(RSP, Immediate(space)); __ ret(); __ Bind(&L); __ jmp(&call1); @@ -1625,11 +1625,13 @@ ASSEMBLER_TEST_GENERATE(PackedNegate, assembler) { + __ EnterDartFrame(0); __ movl(RAX, Immediate(bit_cast<int32_t, float>(12.3f))); __ movd(XMM0, RAX); __ shufps(XMM0, XMM0, Immediate(0x0)); __ negateps(XMM0); __ shufps(XMM0, XMM0, Immediate(0xAA)); // Copy third lane into all 4 lanes. + __ LeaveFrameWithPP(); __ ret(); } @@ -1642,11 +1644,13 @@ ASSEMBLER_TEST_GENERATE(PackedAbsolute, assembler) { + __ EnterDartFrame(0); __ movl(RAX, Immediate(bit_cast<int32_t, float>(-15.3f))); __ movd(XMM0, RAX); __ shufps(XMM0, XMM0, Immediate(0x0)); __ absps(XMM0); __ shufps(XMM0, XMM0, Immediate(0xAA)); // Copy third lane into all 4 lanes. + __ LeaveFrameWithPP(); __ ret(); } @@ -1659,9 +1663,11 @@ ASSEMBLER_TEST_GENERATE(PackedSetWZero, assembler) { + __ EnterDartFrame(0); __ set1ps(XMM0, RAX, Immediate(bit_cast<int32_t, float>(12.3f))); __ zerowps(XMM0); __ shufps(XMM0, XMM0, Immediate(0xFF)); // Copy the W lane which is now 0.0. + __ LeaveFrameWithPP(); __ ret(); } @@ -1778,13 +1784,15 @@ uint32_t d; } constant1 = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; - __ movq(RAX, Immediate(reinterpret_cast<intptr_t>(&constant1))); + __ EnterDartFrame(0); + __ LoadImmediate(RAX, Immediate(reinterpret_cast<intptr_t>(&constant1)), PP); __ movups(XMM9, Address(RAX, 0)); __ notps(XMM9); __ movaps(XMM0, XMM9); __ pushq(RAX); __ movss(Address(RSP, 0), XMM0); __ popq(RAX); + __ LeaveFrameWithPP(); __ ret(); } @@ -2183,24 +2191,24 @@ Label fail; __ EnterDartFrame(0); __ LoadObject(RAX, obj, PP); - __ CompareObject(RAX, obj); + __ CompareObject(RAX, obj, PP); __ j(NOT_EQUAL, &fail); __ LoadObject(RCX, obj, PP); - __ CompareObject(RCX, obj); + __ CompareObject(RCX, obj, PP); __ j(NOT_EQUAL, &fail); const Smi& smi = Smi::ZoneHandle(Smi::New(15)); __ LoadObject(RCX, smi, PP); - __ CompareObject(RCX, smi); + __ CompareObject(RCX, smi, PP); __ j(NOT_EQUAL, &fail); __ pushq(RAX); - __ StoreObject(Address(RSP, 0), obj); + __ StoreObject(Address(RSP, 0), obj, PP); __ popq(RCX); - __ CompareObject(RCX, obj); + __ CompareObject(RCX, obj, PP); __ j(NOT_EQUAL, &fail); __ pushq(RAX); - __ StoreObject(Address(RSP, 0), smi); + __ StoreObject(Address(RSP, 0), smi, PP); __ popq(RCX); - __ CompareObject(RCX, smi); + __ CompareObject(RCX, smi, PP); __ j(NOT_EQUAL, &fail); __ movl(RAX, Immediate(1)); // OK __ LeaveFrameWithPP(); @@ -2539,7 +2547,9 @@ ASSEMBLER_TEST_GENERATE(DoubleAbs, assembler) { + __ EnterDartFrame(0); __ DoubleAbs(XMM0); + __ LeaveFrameWithPP(); __ ret(); }
diff --git a/runtime/vm/ast.cc b/runtime/vm/ast.cc index 2c911eb..ded8a96 100644 --- a/runtime/vm/ast.cc +++ b/runtime/vm/ast.cc
@@ -376,6 +376,25 @@ } +bool ConditionalExprNode::IsPotentiallyConst() const { + return this->condition()->IsPotentiallyConst() && + this->true_expr()->IsPotentiallyConst() && + this->false_expr()->IsPotentiallyConst(); +} + + +const Instance* ConditionalExprNode::EvalConstExpr() const { + const Instance* cond = this->condition()->EvalConstExpr(); + if ((cond != NULL) && + cond->IsBool() && + (this->true_expr()->EvalConstExpr() != NULL) && + (this->false_expr()->EvalConstExpr() != NULL)) { + return cond; + } + return NULL; +} + + bool ClosureNode::IsPotentiallyConst() const { if (function().IsImplicitStaticClosureFunction()) { return true;
diff --git a/runtime/vm/ast.h b/runtime/vm/ast.h index 2f7af98..c294eeb 100644 --- a/runtime/vm/ast.h +++ b/runtime/vm/ast.h
@@ -699,6 +699,9 @@ false_expr_ = false_expr; } + virtual bool IsPotentiallyConst() const; + virtual const Instance* EvalConstExpr() const; + virtual void VisitChildren(AstNodeVisitor* visitor) const { condition()->Visit(visitor); true_expr()->Visit(visitor);
diff --git a/runtime/vm/block_scheduler.cc b/runtime/vm/block_scheduler.cc index 2594e8a..27d2a9e 100644 --- a/runtime/vm/block_scheduler.cc +++ b/runtime/vm/block_scheduler.cc
@@ -5,6 +5,7 @@ #include "vm/block_scheduler.h" #include "vm/allocation.h" +#include "vm/code_patcher.h" #include "vm/flow_graph.h" namespace dart { @@ -14,25 +15,9 @@ intptr_t deopt_id) { ASSERT(deopt_id != Isolate::kNoDeoptId); - // Intrinsified functions do not have edge counts, so give all edges equal - // weights. - if (unoptimized_code.pointer_offsets_length() == 0) return 1; - uword pc = unoptimized_code.GetPcForDeoptId(deopt_id, PcDescriptors::kDeopt); Array& array = Array::Handle(); - // Pointer offsets are sorted in decreasing order. Find the first one - // after the deopt id's pc. - // TODO(kmillikin): Use a more reliable way to find the counter. - for (intptr_t j = unoptimized_code.pointer_offsets_length() - 1; - j >= 0; - --j) { - uword addr = - unoptimized_code.GetPointerOffsetAt(j) + unoptimized_code.EntryPoint(); - if (addr > pc) { - array ^= *reinterpret_cast<RawObject**>(addr); - break; - } - } + array ^= CodePatcher::GetEdgeCounterAt(pc, unoptimized_code); ASSERT(!array.IsNull()); return Smi::Value(Smi::RawCast(array.At(0))); } @@ -208,7 +193,7 @@ for (intptr_t i = block_count - 1; i >= 0; --i) { if (chains[i]->first->block == flow_graph()->postorder()[i]) { for (Link* link = chains[i]->first; link != NULL; link = link->next) { - flow_graph()->codegen_block_order(true)->Add(link->block); + flow_graph()->CodegenBlockOrder(true)->Add(link->block); } } }
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h index f4b947c..48844b2 100644 --- a/runtime/vm/bootstrap_natives.h +++ b/runtime/vm/bootstrap_natives.h
@@ -82,11 +82,11 @@ V(JSSyntaxRegExp_getIsCaseSensitive, 1) \ V(JSSyntaxRegExp_getGroupCount, 1) \ V(JSSyntaxRegExp_ExecuteMatch, 3) \ - V(ObjectArray_allocate, 2) \ - V(ObjectArray_getIndexed, 2) \ - V(ObjectArray_setIndexed, 3) \ - V(ObjectArray_getLength, 1) \ - V(ObjectArray_copyFromObjectArray, 5) \ + V(List_allocate, 2) \ + V(List_getIndexed, 2) \ + V(List_setIndexed, 3) \ + V(List_getLength, 1) \ + V(List_copyFromObjectArray, 5) \ V(StringBase_createFromCodePoints, 1) \ V(StringBase_substringUnchecked, 3) \ V(StringBuffer_createStringFromUint16Array, 3) \ @@ -101,7 +101,7 @@ V(String_concat, 2) \ V(String_toLowerCase, 1) \ V(String_toUpperCase, 1) \ - V(Strings_concatAll, 1) \ + V(Strings_concatAll, 3) \ V(Math_sqrt, 1) \ V(Math_sin, 1) \ V(Math_cos, 1) \ @@ -292,13 +292,13 @@ V(ParameterMirror_type, 2) \ V(TypedefMirror_referent, 1) \ V(VariableMirror_type, 1) \ - V(GrowableObjectArray_allocate, 2) \ - V(GrowableObjectArray_getIndexed, 2) \ - V(GrowableObjectArray_setIndexed, 3) \ - V(GrowableObjectArray_getLength, 1) \ - V(GrowableObjectArray_getCapacity, 1) \ - V(GrowableObjectArray_setLength, 2) \ - V(GrowableObjectArray_setData, 2) \ + V(GrowableList_allocate, 2) \ + V(GrowableList_getIndexed, 2) \ + V(GrowableList_setIndexed, 3) \ + V(GrowableList_getLength, 1) \ + V(GrowableList_getCapacity, 1) \ + V(GrowableList_setLength, 2) \ + V(GrowableList_setData, 2) \ V(WeakProperty_new, 2) \ V(WeakProperty_getKey, 1) \ V(WeakProperty_getValue, 1) \
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc index dff2717..b5c6103 100644 --- a/runtime/vm/class_finalizer.cc +++ b/runtime/vm/class_finalizer.cc
@@ -337,7 +337,7 @@ // Replace the type with a malformed type and compile a throw when called. type = NewFinalizedMalformedType( Error::Handle(), // No previous error. - cls, + Script::Handle(cls.script()), factory.token_pos(), "factory may not redirect to 'dynamic'"); factory.SetRedirectionType(type); @@ -364,7 +364,7 @@ // Replace the type with a malformed type and compile a throw when called. type = NewFinalizedMalformedType( Error::Handle(), // No previous error. - cls, + Script::Handle(target_class.script()), factory.token_pos(), "class '%s' has no constructor or factory named '%s'", target_class_name.ToCString(), @@ -378,8 +378,9 @@ // Verify that the target is compatible with the redirecting factory. Error& error = Error::Handle(); if (!target.HasCompatibleParametersWith(factory, &error)) { + const Script& script = Script::Handle(target_class.script()); type = NewFinalizedMalformedType( - error, target_class, target.token_pos(), + error, script, target.token_pos(), "constructor '%s' has incompatible parameters with " "redirecting factory '%s'", String::Handle(target.name()).ToCString(), @@ -428,7 +429,8 @@ if (malformed_error.IsNull()) { target_type ^= FinalizeType(cls, target_type, kCanonicalize); } else { - FinalizeMalformedType(malformed_error, cls, target_type, + const Script& script = Script::Handle(target_class.script()); + FinalizeMalformedType(malformed_error, script, target_type, "cannot resolve redirecting factory"); target_target = Function::null(); } @@ -471,7 +473,7 @@ // The type class could not be resolved. The type is malformed. FinalizeMalformedType( Error::Handle(), // No previous error. - cls, + Script::Handle(cls.script()), parameterized_type, "cannot resolve class '%s' from '%s'", String::Handle(unresolved_class.Name()).ToCString(), @@ -908,7 +910,7 @@ parameterized_type.UserVisibleName()); const Type& malformed_bound = Type::Handle( NewFinalizedMalformedType(bound_error, - cls, + Script::Handle(cls.script()), parameterized_type.token_pos(), "type '%s' has an out of bound type argument", parameterized_type_name.ToCString())); @@ -2460,12 +2462,11 @@ // Either report an error or mark the type as malformed. void ClassFinalizer::ReportMalformedType(const Error& prev_error, - const Class& cls, + const Script& script, const Type& type, const char* format, va_list args) { LanguageError& error = LanguageError::Handle(); - const Script& script = Script::Handle(cls.script()); if (prev_error.IsNull()) { error ^= Parser::FormatError( script, type.token_pos(), "Error", format, args); @@ -2493,7 +2494,7 @@ RawType* ClassFinalizer::NewFinalizedMalformedType(const Error& prev_error, - const Class& cls, + const Script& script, intptr_t type_pos, const char* format, ...) { va_list args; @@ -2504,7 +2505,7 @@ type_pos)); const Type& type = Type::Handle( Type::New(unresolved_class, TypeArguments::Handle(), type_pos)); - ReportMalformedType(prev_error, cls, type, format, args); + ReportMalformedType(prev_error, script, type, format, args); va_end(args); ASSERT(type.IsMalformed()); ASSERT(type.IsFinalized()); @@ -2513,12 +2514,12 @@ void ClassFinalizer::FinalizeMalformedType(const Error& prev_error, - const Class& cls, + const Script& script, const Type& type, const char* format, ...) { va_list args; va_start(args, format); - ReportMalformedType(prev_error, cls, type, format, args); + ReportMalformedType(prev_error, script, type, format, args); va_end(args); }
diff --git a/runtime/vm/class_finalizer.h b/runtime/vm/class_finalizer.h index e2689d0..cc94684 100644 --- a/runtime/vm/class_finalizer.h +++ b/runtime/vm/class_finalizer.h
@@ -52,7 +52,7 @@ // If not null, prepend prev_error to the error message built from the format // string and its arguments. static RawType* NewFinalizedMalformedType(const Error& prev_error, - const Class& cls, + const Script& script, intptr_t type_pos, const char* format, ...) PRINTF_ATTRIBUTE(4, 5); @@ -62,7 +62,7 @@ // If not null, prepend prev_error to the error message built from the format // string and its arguments. static void FinalizeMalformedType(const Error& prev_error, - const Class& cls, + const Script& script, const Type& type, const char* format, ...) PRINTF_ATTRIBUTE(4, 5); @@ -145,7 +145,7 @@ static void CollectInterfaces(const Class& cls, const GrowableObjectArray& interfaces); static void ReportMalformedType(const Error& prev_error, - const Class& cls, + const Script& script, const Type& type, const char* format, va_list args);
diff --git a/runtime/vm/code_generator.cc b/runtime/vm/code_generator.cc index 9bfd2a5..162e702 100644 --- a/runtime/vm/code_generator.cc +++ b/runtime/vm/code_generator.cc
@@ -1494,8 +1494,9 @@ } -// Copy saved registers into the isolate buffer. -static void CopySavedRegisters(uword saved_registers_address) { +static void CopySavedRegisters(uword saved_registers_address, + fpu_register_t** fpu_registers, + intptr_t** cpu_registers) { ASSERT(sizeof(fpu_register_t) == kFpuRegisterSize); fpu_register_t* fpu_registers_copy = new fpu_register_t[kNumberOfFpuRegisters]; @@ -1505,7 +1506,7 @@ *reinterpret_cast<fpu_register_t*>(saved_registers_address); saved_registers_address += kFpuRegisterSize; } - Isolate::Current()->set_deopt_fpu_registers_copy(fpu_registers_copy); + *fpu_registers = fpu_registers_copy; ASSERT(sizeof(intptr_t) == kWordSize); intptr_t* cpu_registers_copy = new intptr_t[kNumberOfCpuRegisters]; @@ -1515,14 +1516,16 @@ *reinterpret_cast<intptr_t*>(saved_registers_address); saved_registers_address += kWordSize; } - Isolate::Current()->set_deopt_cpu_registers_copy(cpu_registers_copy); + *cpu_registers = cpu_registers_copy; } -// Copy optimized frame into the isolate buffer. -// The first incoming argument is stored at the last entry in the -// copied frame buffer. -static void CopyFrame(const Code& optimized_code, const StackFrame& frame) { +// Copy optimized frame. The first incoming argument is stored at the +// last entry in the copied frame buffer. +static void CopyFrame(const Code& optimized_code, + const StackFrame& frame, + intptr_t** frame_start, + intptr_t* frame_size) { const Function& function = Function::Handle(optimized_code.function()); // Do not copy incoming arguments if there are optional arguments (they // are copied into local space at method entry). @@ -1545,7 +1548,8 @@ for (intptr_t i = 0; i < frame_copy_size; i++) { frame_copy[i] = *(start + i); } - Isolate::Current()->SetDeoptFrameCopy(frame_copy, frame_copy_size); + *frame_start = frame_copy; + *frame_size = frame_copy_size; } @@ -1562,7 +1566,6 @@ + (kNumberOfCpuRegisters * kWordSize) + (kNumberOfFpuRegisters * kFpuRegisterSize) - ((kFirstLocalSlotFromFp + 1) * kWordSize); - CopySavedRegisters(saved_registers_address); // Get optimized code and frame that need to be deoptimized. DartFrameIterator iterator(last_fp); @@ -1576,9 +1579,28 @@ optimized_code.GetDeoptInfoAtPc(caller_frame->pc(), &deopt_reason)); ASSERT(!deopt_info.IsNull()); - CopyFrame(optimized_code, *caller_frame); + // Create the DeoptContext for this deoptimization. Store in isolate. + const Function& function = Function::Handle(optimized_code.function()); + const intptr_t num_args = + function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); + DeoptContext* deopt_context = new DeoptContext( + Array::Handle(optimized_code.object_table()), + num_args, + static_cast<DeoptReasonId>(deopt_reason)); + isolate->set_deopt_context(deopt_context); + + // Copy the saved registers and the source frame. + fpu_register_t* fpu_registers; + intptr_t* cpu_registers; + intptr_t* frame_start; + intptr_t frame_size; + CopySavedRegisters(saved_registers_address, &fpu_registers, &cpu_registers); + CopyFrame(optimized_code, *caller_frame, &frame_start, &frame_size); + deopt_context->SetSourceArgs(frame_start, frame_size, + fpu_registers, cpu_registers, + true); // true = source frame is a copy. + if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { - Function& function = Function::Handle(optimized_code.function()); OS::PrintErr( "Deoptimizing (reason %" Pd " '%s') at pc %#" Px " '%s' (count %d)\n", deopt_reason, @@ -1591,9 +1613,6 @@ // Compute the stack size of the unoptimized frame. For functions with // optional arguments the deoptimization info does not describe the // incoming arguments. - const Function& function = Function::Handle(optimized_code.function()); - const intptr_t num_args = - function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); const intptr_t unoptimized_stack_size = + deopt_info.FrameSize() - kDartFrameFixedSize @@ -1605,10 +1624,10 @@ END_LEAF_RUNTIME_ENTRY -static void DeoptimizeWithDeoptInfo(const Code& code, +static void DeoptimizeWithDeoptInfo(DeoptContext* deopt_context, + const Code& code, const DeoptInfo& deopt_info, - const StackFrame& caller_frame, - intptr_t deopt_reason) { + const StackFrame& caller_frame) { const intptr_t len = deopt_info.TranslationLength(); GrowableArray<DeoptInstr*> deopt_instructions(len); const Array& deopt_table = Array::Handle(code.deopt_info_array()); @@ -1626,11 +1645,9 @@ + 1 // For fp. + kParamEndSlotFromFp + num_args; - DeoptimizationContext deopt_context(start, - to_frame_size, - Array::Handle(code.object_table()), - num_args, - static_cast<DeoptReasonId>(deopt_reason)); + + deopt_context->SetDestArgs(start, to_frame_size); + const intptr_t frame_size = deopt_info.FrameSize(); // All kMaterializeObject instructions are emitted before the instructions @@ -1642,15 +1659,15 @@ // frame. They will be used during materialization and removed from the stack // right before control switches to the unoptimized code. const intptr_t num_materializations = len - frame_size; - Isolate::Current()->PrepareForDeferredMaterialization(num_materializations); + deopt_context->PrepareForDeferredMaterialization(num_materializations); for (intptr_t from_index = 0, to_index = kDartFrameFixedSize; from_index < num_materializations; from_index++) { const intptr_t field_count = DeoptInstr::GetFieldCount(deopt_instructions[from_index]); - intptr_t* args = deopt_context.GetToFrameAddressAt(to_index); + intptr_t* args = deopt_context->GetDestFrameAddressAt(to_index); DeferredObject* obj = new DeferredObject(field_count, args); - Isolate::Current()->SetDeferredObjectAt(from_index, obj); + deopt_context->SetDeferredObjectAt(from_index, obj); to_index += obj->ArgumentCount(); } @@ -1658,8 +1675,8 @@ for (intptr_t to_index = frame_size - 1, from_index = len - 1; to_index >= 0; to_index--, from_index--) { - intptr_t* to_addr = deopt_context.GetToFrameAddressAt(to_index); - deopt_instructions[from_index]->Execute(&deopt_context, to_addr); + intptr_t* to_addr = deopt_context->GetDestFrameAddressAt(to_index); + deopt_instructions[from_index]->Execute(deopt_context, to_addr); } if (FLAG_trace_deoptimization_verbose) { @@ -1691,26 +1708,16 @@ ASSERT(!optimized_code.IsNull() && optimized_code.is_optimized()); ASSERT(!unoptimized_code.IsNull() && !unoptimized_code.is_optimized()); - intptr_t* frame_copy = isolate->deopt_frame_copy(); - intptr_t* cpu_registers_copy = isolate->deopt_cpu_registers_copy(); - fpu_register_t* fpu_registers_copy = isolate->deopt_fpu_registers_copy(); - intptr_t deopt_reason = kDeoptUnknown; const DeoptInfo& deopt_info = DeoptInfo::Handle( optimized_code.GetDeoptInfoAtPc(caller_frame->pc(), &deopt_reason)); ASSERT(!deopt_info.IsNull()); - DeoptimizeWithDeoptInfo(optimized_code, + DeoptContext* deopt_context = isolate->deopt_context(); + DeoptimizeWithDeoptInfo(deopt_context, + optimized_code, deopt_info, - *caller_frame, - deopt_reason); - - isolate->SetDeoptFrameCopy(NULL, 0); - isolate->set_deopt_cpu_registers_copy(NULL); - isolate->set_deopt_fpu_registers_copy(NULL); - delete[] frame_copy; - delete[] cpu_registers_copy; - delete[] fpu_registers_copy; + *caller_frame); } END_LEAF_RUNTIME_ENTRY @@ -1721,25 +1728,15 @@ // under return address to keep them discoverable by GC that can occur during // materialization phase. DEFINE_RUNTIME_ENTRY(DeoptimizeMaterialize, 0) { - // First materialize all unboxed "primitive" values (doubles, mints, simd) - // then materialize objects. The order is important: objects might be - // referencing boxes allocated on the first step. At the same time - // objects can't be referencing other deferred objects because storing - // an object into a field is always conservatively treated as escaping by - // allocation sinking and load forwarding. - isolate->MaterializeDeferredBoxes(); - isolate->MaterializeDeferredObjects(); + DeoptContext* deopt_context = isolate->deopt_context(); - // Compute total number of artificial arguments used during deoptimization. - intptr_t deopt_arguments = 0; - for (intptr_t i = 0; i < isolate->DeferredObjectsCount(); i++) { - deopt_arguments += isolate->GetDeferredObject(i)->ArgumentCount(); - } - Isolate::Current()->DeleteDeferredObjects(); + intptr_t deopt_arg_count = deopt_context->MaterializeDeferredObjects(); + isolate->set_deopt_context(NULL); + delete deopt_context; // Return value tells deoptimization stub to remove the given number of bytes // from the stack. - arguments.SetReturn(Smi::Handle(Smi::New(deopt_arguments * kWordSize))); + arguments.SetReturn(Smi::Handle(Smi::New(deopt_arg_count * kWordSize))); // Since this is the only step where GC can occur during deoptimization, // use it to report the source line where deoptimization occured. @@ -1756,7 +1753,7 @@ String& line_string = String::Handle(script.GetLine(line)); OS::PrintErr(" Function: %s\n", top_function.ToFullyQualifiedCString()); OS::PrintErr(" Line %" Pd ": '%s'\n", line, line_string.ToCString()); - OS::PrintErr(" Deopt args: %" Pd "\n", deopt_arguments); + OS::PrintErr(" Deopt args: %" Pd "\n", deopt_arg_count); } }
diff --git a/runtime/vm/code_patcher.h b/runtime/vm/code_patcher.h index fea3ba4..9294e0e 100644 --- a/runtime/vm/code_patcher.h +++ b/runtime/vm/code_patcher.h
@@ -19,6 +19,7 @@ class RawArray; class RawFunction; class RawICData; +class RawObject; class String; class CodePatcher : public AllStatic { @@ -70,6 +71,8 @@ static intptr_t InstanceCallSizeInBytes(); static void InsertCallAt(uword start, uword target); + + static RawObject* GetEdgeCounterAt(uword pc, const Code& code); }; } // namespace dart
diff --git a/runtime/vm/code_patcher_arm.cc b/runtime/vm/code_patcher_arm.cc index 105d3a1..759bf54 100644 --- a/runtime/vm/code_patcher_arm.cc +++ b/runtime/vm/code_patcher_arm.cc
@@ -84,6 +84,47 @@ return ic_data.GetTargetAt(0); } + +// This class pattern matches on a load from the object pool. Loading on +// ARM is complicated because it can take four possible different forms. We +// match backwards from the end of the sequence so we can reuse the code for +// matching object pool loads at calls. +class EdgeCounter : public ValueObject { + public: + EdgeCounter(uword pc, const Code& code) + : end_(pc - kAdjust), object_pool_(Array::Handle(code.ObjectPool())) { + // An IsValid predicate is complicated and duplicates the code in the + // decoding function. Instead we rely on decoding the pattern which + // will assert partial validity. + } + + RawObject* edge_counter() const { + Register ignored; + intptr_t index; + InstructionPattern::DecodeLoadWordFromPool(end_, &ignored, &index); + ASSERT(ignored == R0); + return object_pool_.At(index); + } + + private: + // The object pool load is followed by the fixed-size edge counter + // incrementing code: + // ldr ip, [r0, #+11] + // adds ip, ip, #2 + // str ip, [r0, #+11] + static const intptr_t kAdjust = 3 * Instr::kInstrSize; + + uword end_; + const Array& object_pool_; +}; + + +RawObject* CodePatcher::GetEdgeCounterAt(uword pc, const Code& code) { + ASSERT(code.ContainsInstructionAt(pc)); + EdgeCounter counter(pc, code); + return counter.edge_counter(); +} + } // namespace dart #endif // defined TARGET_ARCH_ARM
diff --git a/runtime/vm/code_patcher_ia32.cc b/runtime/vm/code_patcher_ia32.cc index 9cccd56..8143d69 100644 --- a/runtime/vm/code_patcher_ia32.cc +++ b/runtime/vm/code_patcher_ia32.cc
@@ -149,7 +149,7 @@ }; -// The expected pattern of a dart closure call: +// The expected pattern of a Dart closure call: // mov EDX, arguments_descriptor_array // call target_address // <- return address @@ -259,6 +259,39 @@ return InstanceCall::kNumInstructions * InstanceCall::kInstructionSize; } + +// The expected code pattern of an edge counter in unoptimized code: +// b8 imm32 mov EAX, immediate +class EdgeCounter : public ValueObject { + public: + EdgeCounter(uword pc, const Code& ignored) : end_(pc - kAdjust) { + ASSERT(IsValid(end_)); + } + + static bool IsValid(uword end) { + return (*reinterpret_cast<uint8_t*>(end - 5) == 0xb8); + } + + RawObject* edge_counter() const { + return *reinterpret_cast<RawObject**>(end_ - 4); + } + + private: + // The edge counter load is followed by the fixed-size edge counter + // incrementing code: + // 83 40 0b 02 add [eax+0xb],0x2 + static const intptr_t kAdjust = 4; + + uword end_; +}; + + +RawObject* CodePatcher::GetEdgeCounterAt(uword pc, const Code& code) { + ASSERT(code.ContainsInstructionAt(pc)); + EdgeCounter counter(pc, code); + return counter.edge_counter(); +} + } // namespace dart #endif // defined TARGET_ARCH_IA32
diff --git a/runtime/vm/code_patcher_mips.cc b/runtime/vm/code_patcher_mips.cc index f25b460..7a84596 100644 --- a/runtime/vm/code_patcher_mips.cc +++ b/runtime/vm/code_patcher_mips.cc
@@ -84,6 +84,47 @@ return ic_data.GetTargetAt(0); } + +// This class pattern matches on a load from the object pool. Loading on +// MIPS is complicated because it can take four possible different forms. +// We match backwards from the end of the sequence so we can reuse the code +// for matching object pool loads at calls. +class EdgeCounter : public ValueObject { + public: + EdgeCounter(uword pc, const Code& code) + : end_(pc - kAdjust), object_pool_(Array::Handle(code.ObjectPool())) { + // An IsValid predicate is complicated and duplicates the code in the + // decoding function. Instead we rely on decoding the pattern which + // will assert partial validity. + } + + RawObject* edge_counter() const { + Register ignored; + intptr_t index; + InstructionPattern::DecodeLoadWordFromPool(end_, &ignored, &index); + ASSERT(ignored == T0); + return object_pool_.At(index); + } + + private: + // The object pool load is followed by the fixed-size edge counter + // incrementing code: + // lw r9, 11(r8) + // addiu r9, r9, 2 + // sw r9, 11(r8) + static const intptr_t kAdjust = 3 * Instr::kInstrSize; + + uword end_; + const Array& object_pool_; +}; + + +RawObject* CodePatcher::GetEdgeCounterAt(uword pc, const Code& code) { + ASSERT(code.ContainsInstructionAt(pc)); + EdgeCounter counter(pc, code); + return counter.edge_counter(); +} + } // namespace dart #endif // defined TARGET_ARCH_MIPS
diff --git a/runtime/vm/code_patcher_x64.cc b/runtime/vm/code_patcher_x64.cc index 5782527c..0de7bd6 100644 --- a/runtime/vm/code_patcher_x64.cc +++ b/runtime/vm/code_patcher_x64.cc
@@ -142,7 +142,7 @@ }; -// The expected code pattern of a dart closure call: +// The expected code pattern of a Dart closure call: // 00: 49 ba imm64 mov R10, immediate 2 ; 10 bytes // 10: 4d 8b 9f imm32 mov R11, [PP + off] // 17: 41 ff d3 call R11 ; 3 bytes @@ -248,6 +248,42 @@ return ic_data.GetTargetAt(0); } + +// The expected code pattern of an edge counter in unoptimized code: +// 49 8b 87 imm32 mov RAX, [PP + offset] +class EdgeCounter : public ValueObject { + public: + EdgeCounter(uword pc, const Code& code) + : end_(pc - kAdjust), object_pool_(Array::Handle(code.ObjectPool())) { + ASSERT(IsValid(end_)); + } + + static bool IsValid(uword end) { + uint8_t* bytes = reinterpret_cast<uint8_t*>(end - 7); + return (bytes[0] == 0x49) && (bytes[1] == 0x8b) && (bytes[2] == 0x87); + } + + RawObject* edge_counter() const { + return object_pool_.At(InstructionPattern::IndexFromPPLoad(end_ - 4)); + } + + private: + // The edge counter load is followed by the fixed-size edge counter + // incrementing code: + // 48 83 40 17 02 addq [rax+0x17],0x2 + static const intptr_t kAdjust = 5; + + uword end_; + const Array& object_pool_; +}; + + +RawObject* CodePatcher::GetEdgeCounterAt(uword pc, const Code& code) { + ASSERT(code.ContainsInstructionAt(pc)); + EdgeCounter counter(pc, code); + return counter.edge_counter(); +} + } // namespace dart #endif // defined TARGET_ARCH_X64
diff --git a/runtime/vm/compiler.cc b/runtime/vm/compiler.cc index d9f1a53..5a9ff9d 100644 --- a/runtime/vm/compiler.cc +++ b/runtime/vm/compiler.cc
@@ -307,7 +307,9 @@ } BlockScheduler block_scheduler(flow_graph); - if (optimized && FLAG_reorder_basic_blocks) { + const bool reorder_blocks = + FlowGraph::ShouldReorderBlocks(function, optimized); + if (reorder_blocks) { block_scheduler.AssignEdgeWeights(); } @@ -508,7 +510,7 @@ // Perform register allocation on the SSA graph. FlowGraphAllocator allocator(*flow_graph); allocator.AllocateRegisters(); - if (FLAG_reorder_basic_blocks) block_scheduler.ReorderBlocks(); + if (reorder_blocks) block_scheduler.ReorderBlocks(); if (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized) { FlowGraphPrinter::PrintGraph("After Optimizations", flow_graph); @@ -739,8 +741,8 @@ TIMERSCOPE(time_compilation); Timer per_compile_timer(FLAG_trace_compiler, "Compilation time"); per_compile_timer.Start(); - ParsedFunction* parsed_function = new ParsedFunction( - Function::ZoneHandle(function.raw())); + ParsedFunction* parsed_function = + new ParsedFunction(Function::ZoneHandle(function.raw())); if (FLAG_trace_compiler) { OS::Print("Compiling %s%sfunction: '%s' @ token %" Pd ", size %" Pd "\n", (osr_id == Isolate::kNoDeoptId ? "" : "osr "),
diff --git a/runtime/vm/coverage.cc b/runtime/vm/coverage.cc index 5d284d2..56733f4 100644 --- a/runtime/vm/coverage.cc +++ b/runtime/vm/coverage.cc
@@ -6,6 +6,7 @@ #include "include/dart_api.h" +#include "vm/compiler.h" #include "vm/isolate.h" #include "vm/json_stream.h" #include "vm/object.h" @@ -16,64 +17,105 @@ DEFINE_FLAG(charp, coverage_dir, NULL, "Enable writing coverage data into specified directory."); + +void CodeCoverage::CompileAndAdd(const Function& function, + const JSONArray& hits_arr) { + if (!function.HasCode()) { + if (Compiler::CompileFunction(function) != Error::null()) { + return; + } + } + ASSERT(function.HasCode()); + + Isolate* isolate = Isolate::Current(); + // Print the hit counts for all IC datas. + const Script& script = Script::Handle(function.script()); + const Code& code = Code::Handle(function.unoptimized_code()); + const Array& ic_array = Array::Handle(code.ExtractTypeFeedbackArray()); + const PcDescriptors& descriptors = PcDescriptors::Handle( + code.pc_descriptors()); + ICData& ic_data = ICData::Handle(); + + for (int j = 0; j < descriptors.Length(); j++) { + HANDLESCOPE(isolate); + PcDescriptors::Kind kind = descriptors.DescriptorKind(j); + // Only IC based calls have counting. + if ((kind == PcDescriptors::kIcCall) || + (kind == PcDescriptors::kUnoptStaticCall)) { + intptr_t deopt_id = descriptors.DeoptId(j); + ic_data ^= ic_array.At(deopt_id); + if (!ic_data.IsNull()) { + intptr_t token_pos = descriptors.TokenPos(j); + intptr_t line = -1; + script.GetTokenLocation(token_pos, &line, NULL); + hits_arr.AddValue(line); + hits_arr.AddValue(ic_data.AggregateCount()); + } + } + } +} + + void CodeCoverage::PrintClass(const Class& cls, const JSONArray& jsarr) { - const Array& functions = Array::Handle(cls.functions()); + Isolate* isolate = Isolate::Current(); + Array& functions = Array::Handle(cls.functions()); ASSERT(!functions.IsNull()); Function& function = Function::Handle(); - Code& code = Code::Handle(); Script& script = Script::Handle(); + String& saved_url = String::Handle(); String& url = String::Handle(); - String& name = String::Handle(); - PcDescriptors& descriptors = PcDescriptors::Handle(); - Array& ic_array = Array::Handle(); - ICData& ic_data = ICData::Handle(); - for (int i = 0; i < functions.Length(); i++) { - function ^= functions.At(i); + int i = 0; + while (i < functions.Length()) { + HANDLESCOPE(isolate); + function ^= functions.At(i); JSONObject jsobj(&jsarr); script = function.script(); - url = script.url(); - name = function.QualifiedUserVisibleName(); - jsobj.AddProperty("source", url.ToCString()); - jsobj.AddProperty("function", name.ToCString()); + saved_url = script.url(); + jsobj.AddProperty("source", saved_url.ToCString()); + JSONArray hits_arr(&jsobj, "hits"); - JSONArray jsarr(&jsobj, "hits"); - - if (function.HasCode()) { - // Print the hit counts for all IC datas. - code = function.unoptimized_code(); - ic_array = code.ExtractTypeFeedbackArray(); - descriptors = code.pc_descriptors(); - - for (int j = 0; j < descriptors.Length(); j++) { - PcDescriptors::Kind kind = descriptors.DescriptorKind(j); - // Only IC based calls have counting. - if ((kind == PcDescriptors::kIcCall) || - (kind == PcDescriptors::kUnoptStaticCall)) { - intptr_t deopt_id = descriptors.DeoptId(j); - ic_data ^= ic_array.At(deopt_id); - if (!ic_data.IsNull()) { - intptr_t token_pos = descriptors.TokenPos(j); - intptr_t line = -1; - intptr_t col = -1; - script.GetTokenLocation(token_pos, &line, &col); - JSONObject ic_info(&jsarr); - ic_info.AddProperty("line", line); - ic_info.AddProperty("col", col); - ic_info.AddProperty("count", ic_data.AggregateCount()); - } - } + // We stay within this loop while we are seeing functions from the same + // source URI. + while (i < functions.Length()) { + function ^= functions.At(i); + script = function.script(); + url = script.url(); + if (!url.Equals(saved_url)) { + break; } - } else { - // The function has no code so it was never executed and thus we add one - // zero count hit at the first token index. - intptr_t line = -1; - intptr_t col = -1; - script.GetTokenLocation(function.token_pos(), &line, &col); - JSONObject func_info(&jsarr); - func_info.AddProperty("line", line); - func_info.AddProperty("col", col); - func_info.AddProperty("count", static_cast<intptr_t>(0)); + CompileAndAdd(function, hits_arr); + i++; + } + } + + GrowableObjectArray& closures = + GrowableObjectArray::Handle(cls.closures()); + if (!closures.IsNull()) { + i = 0; + // We need to keep rechecking the length of the closures array, as handling + // a closure potentially adds new entries to the end. + while (i < closures.Length()) { + HANDLESCOPE(isolate); + function ^= closures.At(i); + JSONObject jsobj(&jsarr); + script = function.script(); + saved_url = script.url(); + jsobj.AddProperty("source", saved_url.ToCString()); + JSONArray hits_arr(&jsobj, "hits"); + + // We stay within this loop while we are seeing functions from the same + // source URI. + while (i < closures.Length()) { + function ^= closures.At(i); + script = function.script(); + url = script.url(); + if (!url.Equals(saved_url)) { + break; + } + CompileAndAdd(function, hits_arr); + i++; + } } } } @@ -103,7 +145,7 @@ ClassDictionaryIterator it(lib, ClassDictionaryIterator::kIteratePrivate); while (it.HasNext()) { cls = it.GetNextClass(); - if (cls.is_finalized()) { + if (cls.EnsureIsFinalized(isolate) == Error::null()) { // Only classes that have been finalized do have a meaningful list of // functions. PrintClass(cls, jsarr);
diff --git a/runtime/vm/coverage.h b/runtime/vm/coverage.h index ef7ee82..0c17bda 100644 --- a/runtime/vm/coverage.h +++ b/runtime/vm/coverage.h
@@ -14,6 +14,7 @@ // Forward declarations. class Class; +class Function; class Isolate; class JSONArray; @@ -23,6 +24,8 @@ private: static void PrintClass(const Class& cls, const JSONArray& arr); + static void CompileAndAdd(const Function& function, + const JSONArray& hits_arr); }; } // namespace dart
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc index 7a6bc66..680476e 100644 --- a/runtime/vm/dart_api_impl.cc +++ b/runtime/vm/dart_api_impl.cc
@@ -2834,12 +2834,14 @@ } // Get the class to instantiate. - const Type& type_obj = Api::UnwrapTypeHandle(isolate, type); - if (type_obj.IsNull()) { + Object& unchecked_type = Object::Handle(Api::UnwrapHandle(type)); + if (unchecked_type.IsNull() || !unchecked_type.IsType()) { RETURN_TYPE_ERROR(isolate, type, Type); } + Type& type_obj = Type::Handle(); + type_obj ^= unchecked_type.raw(); Class& cls = Class::Handle(isolate, type_obj.type_class()); - const AbstractTypeArguments& type_arguments = + AbstractTypeArguments& type_arguments = AbstractTypeArguments::Handle(isolate, type_obj.arguments()); const String& base_constructor_name = String::Handle(isolate, cls.Name()); @@ -2877,13 +2879,28 @@ Instance& new_object = Instance::Handle(isolate); if (constructor.IsRedirectingFactory()) { ClassFinalizer::ResolveRedirectingFactory(cls, constructor); - const Type& type = Type::Handle(constructor.RedirectionType()); + Type& redirect_type = Type::Handle(constructor.RedirectionType()); constructor = constructor.RedirectionTarget(); if (constructor.IsNull()) { - ASSERT(type.IsMalformed()); - return Api::NewHandle(isolate, type.malformed_error()); + ASSERT(redirect_type.IsMalformed()); + return Api::NewHandle(isolate, redirect_type.malformed_error()); } - cls = type.type_class(); + + if (!redirect_type.IsInstantiated()) { + // The type arguments of the redirection type are instantiated from the + // type arguments of the type argument. + Error& malformed_error = Error::Handle(); + redirect_type ^= redirect_type.InstantiateFrom(type_arguments, + &malformed_error); + if (!malformed_error.IsNull()) { + return Api::NewHandle(isolate, malformed_error.raw()); + } + } + + type_obj = redirect_type.raw(); + type_arguments = redirect_type.arguments(); + + cls = type_obj.type_class(); } if (constructor.IsConstructor()) { // Create the new object. @@ -3613,7 +3630,7 @@ CHECK_ISOLATE(isolate); ReusableObjectHandleScope reused_obj_handle(isolate); Object& obj = reused_obj_handle.Handle(); - obj = arguments->NativeArgAt(0); + obj = arguments->NativeArg0(); intptr_t cid = obj.GetClassId(); if (cid <= kNumPredefinedCids) { if (cid == kNullCid) { @@ -4208,9 +4225,9 @@ } -DART_EXPORT Dart_Handle Dart_LoadPatch(Dart_Handle library, - Dart_Handle url, - Dart_Handle patch_source) { +DART_EXPORT Dart_Handle Dart_LibraryLoadPatch(Dart_Handle library, + Dart_Handle url, + Dart_Handle patch_source) { TIMERSCOPE(time_script_loading); Isolate* isolate = Isolate::Current(); DARTSCOPE(isolate);
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc index e5fce0d..aa860ea 100644 --- a/runtime/vm/dart_api_impl_test.cc +++ b/runtime/vm/dart_api_impl_test.cc
@@ -2711,19 +2711,6 @@ } -#define CHECK_CLASS(handle, name) \ - { \ - Dart_Handle tmp = (handle); \ - EXPECT_VALID(tmp); \ - EXPECT(Dart_IsClass(tmp)); \ - Dart_Handle intf_name = Dart_TypeName(tmp); \ - EXPECT_VALID(intf_name); \ - const char* intf_name_cstr = ""; \ - EXPECT_VALID(Dart_StringToCString(intf_name, &intf_name_cstr)); \ - EXPECT_STREQ((name), intf_name_cstr); \ - } - - TEST_CASE(TypeGetNonParamtericTypes) { const char* kScriptChars = "class MyClass0 {\n" @@ -5258,7 +5245,7 @@ url = NewString("patch_url"); source = NewString(kPatchChars); - result = Dart_LoadPatch(lib, url, source); + result = Dart_LibraryLoadPatch(lib, url, source); EXPECT_VALID(result); result = Dart_Invoke(lib, NewString("foo"), 0, NULL);
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc index 66930ed..c085f5c 100644 --- a/runtime/vm/debugger.cc +++ b/runtime/vm/debugger.cc
@@ -1595,6 +1595,9 @@ if (!IsDebuggable(func)) { return; } + if (frame->TokenPos() == Scanner::kDummyTokenIndex) { + return; + } if (FLAG_verbose_debug) { OS::Print(">>> single step break at %s:%" Pd " (func %s token %" Pd ")\n",
diff --git a/runtime/vm/debugger_api_impl.cc b/runtime/vm/debugger_api_impl.cc index 130decd..3ffff4a 100644 --- a/runtime/vm/debugger_api_impl.cc +++ b/runtime/vm/debugger_api_impl.cc
@@ -507,6 +507,7 @@ CURRENT_FUNC); } UNWRAP_AND_CHECK_PARAM(String, expr, expr_in); + // Type extends Instance, must check first. if (target.IsType()) { const Class& cls = Class::Handle(isolate, Type::Cast(target).type_class()); return Api::NewHandle(isolate, cls.Evaluate(expr)); @@ -514,6 +515,8 @@ return Api::NewHandle(isolate, Instance::Cast(target).Evaluate(expr)); } else if (target.IsLibrary()) { return Api::NewHandle(isolate, Library::Cast(target).Evaluate(expr)); + } else if (target.IsClass()) { + return Api::NewHandle(isolate, Class::Cast(target).Evaluate(expr)); } return Api::NewError("%s: unsupported target type", CURRENT_FUNC); }
diff --git a/runtime/vm/debugger_api_impl_test.cc b/runtime/vm/debugger_api_impl_test.cc index d73e812..5bd2084 100644 --- a/runtime/vm/debugger_api_impl_test.cc +++ b/runtime/vm/debugger_api_impl_test.cc
@@ -1583,14 +1583,16 @@ EXPECT(Dart_IsNumber(len)); EXPECT_EQ(3, ToInt64(len)); - Dart_Handle point_class = Dart_GetClass(script_lib, NewString("Point")); - EXPECT_VALID(point_class); - Dart_Handle elem = Dart_EvaluateExpr(point_class, NewString("m['\"']")); + Dart_Handle point_type = + Dart_GetType(script_lib, NewString("Point"), 0, NULL); + EXPECT_VALID(point_type); + EXPECT(Dart_IsType(point_type)); + Dart_Handle elem = Dart_EvaluateExpr(point_type, NewString("m['\"']")); EXPECT_VALID(elem); EXPECT(Dart_IsString(elem)); EXPECT_STREQ("quote", ToCString(elem)); - elem = Dart_EvaluateExpr(point_class, NewString("m[\"\\t\"]")); + elem = Dart_EvaluateExpr(point_type, NewString("m[\"\\t\"]")); EXPECT_VALID(elem); EXPECT(Dart_IsString(elem)); EXPECT_STREQ("tab", ToCString(elem)); @@ -1617,6 +1619,10 @@ EXPECT_VALID(len); EXPECT(Dart_IsNumber(len)); EXPECT_EQ(6, ToInt64(len)); + + Dart_Handle error = + Dart_EvaluateExpr(script_lib, NewString("new NonexistingType()")); + EXPECT(Dart_IsError(error)); }
diff --git a/runtime/vm/deferred_objects.cc b/runtime/vm/deferred_objects.cc new file mode 100644 index 0000000..76f5be7 --- /dev/null +++ b/runtime/vm/deferred_objects.cc
@@ -0,0 +1,127 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +#include "vm/deferred_objects.h" + +#include "vm/deopt_instructions.h" +#include "vm/flags.h" +#include "vm/object.h" + +namespace dart { + +DECLARE_FLAG(bool, trace_deoptimization_verbose); + + +void DeferredDouble::Materialize() { + RawDouble** double_slot = reinterpret_cast<RawDouble**>(slot()); + *double_slot = Double::New(value()); + + if (FLAG_trace_deoptimization_verbose) { + OS::PrintErr("materializing double at %" Px ": %g\n", + reinterpret_cast<uword>(slot()), value()); + } +} + + +void DeferredMint::Materialize() { + RawMint** mint_slot = reinterpret_cast<RawMint**>(slot()); + ASSERT(!Smi::IsValid64(value())); + Mint& mint = Mint::Handle(); + mint ^= Integer::New(value()); + *mint_slot = mint.raw(); + + if (FLAG_trace_deoptimization_verbose) { + OS::PrintErr("materializing mint at %" Px ": %" Pd64 "\n", + reinterpret_cast<uword>(slot()), value()); + } +} + + +void DeferredFloat32x4::Materialize() { + RawFloat32x4** float32x4_slot = reinterpret_cast<RawFloat32x4**>(slot()); + RawFloat32x4* raw_float32x4 = Float32x4::New(value()); + *float32x4_slot = raw_float32x4; + + if (FLAG_trace_deoptimization_verbose) { + float x = raw_float32x4->x(); + float y = raw_float32x4->y(); + float z = raw_float32x4->z(); + float w = raw_float32x4->w(); + OS::PrintErr("materializing Float32x4 at %" Px ": %g,%g,%g,%g\n", + reinterpret_cast<uword>(slot()), x, y, z, w); + } +} + + +void DeferredUint32x4::Materialize() { + RawUint32x4** uint32x4_slot = reinterpret_cast<RawUint32x4**>(slot()); + RawUint32x4* raw_uint32x4 = Uint32x4::New(value()); + *uint32x4_slot = raw_uint32x4; + + if (FLAG_trace_deoptimization_verbose) { + uint32_t x = raw_uint32x4->x(); + uint32_t y = raw_uint32x4->y(); + uint32_t z = raw_uint32x4->z(); + uint32_t w = raw_uint32x4->w(); + OS::PrintErr("materializing Uint32x4 at %" Px ": %x,%x,%x,%x\n", + reinterpret_cast<uword>(slot()), x, y, z, w); + } +} + + +void DeferredObjectRef::Materialize() { + // TODO(turnidge): Consider passing the deopt_context to materialize + // instead of accessing it through the current isolate. It would + // make it easier to test deferred object materialization in a unit + // test eventually. + DeferredObject* obj = + Isolate::Current()->deopt_context()->GetDeferredObject(index()); + *slot() = obj->object(); + if (FLAG_trace_deoptimization_verbose) { + OS::PrintErr("writing instance ref at %" Px ": %s\n", + reinterpret_cast<uword>(slot()), + Instance::Handle(obj->object()).ToCString()); + } +} + + +RawInstance* DeferredObject::object() { + if (object_ == NULL) { + Materialize(); + } + return object_->raw(); +} + + +void DeferredObject::Materialize() { + Class& cls = Class::Handle(); + cls ^= GetClass(); + + if (FLAG_trace_deoptimization_verbose) { + OS::PrintErr("materializing instance of %s (%" Px ", %" Pd " fields)\n", + cls.ToCString(), + reinterpret_cast<uword>(args_), + field_count_); + } + + const Instance& obj = Instance::ZoneHandle(Instance::New(cls)); + + Field& field = Field::Handle(); + Object& value = Object::Handle(); + for (intptr_t i = 0; i < field_count_; i++) { + field ^= GetField(i); + value = GetValue(i); + obj.SetField(field, value); + + if (FLAG_trace_deoptimization_verbose) { + OS::PrintErr(" %s <- %s\n", + String::Handle(field.name()).ToCString(), + value.ToCString()); + } + } + + object_ = &obj; +} + +} // namespace dart
diff --git a/runtime/vm/deferred_objects.h b/runtime/vm/deferred_objects.h new file mode 100644 index 0000000..7e2c3c9 --- /dev/null +++ b/runtime/vm/deferred_objects.h
@@ -0,0 +1,187 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +#ifndef VM_DEFERRED_OBJECTS_H_ +#define VM_DEFERRED_OBJECTS_H_ + +#include "platform/globals.h" + +namespace dart { + +// Forward declarations. +class Instance; +class RawInstance; +class RawObject; + +// Used by the deoptimization infrastructure to defer allocation of +// unboxed objects until frame is fully rewritten and GC is safe. +// Describes a stack slot that should be populated with a reference to +// the materialized object. +class DeferredSlot { + public: + DeferredSlot(RawInstance** slot, DeferredSlot* next) + : slot_(slot), next_(next) { } + virtual ~DeferredSlot() { } + + RawInstance** slot() const { return slot_; } + DeferredSlot* next() const { return next_; } + + virtual void Materialize() = 0; + + private: + RawInstance** const slot_; + DeferredSlot* const next_; + + DISALLOW_COPY_AND_ASSIGN(DeferredSlot); +}; + + +class DeferredDouble : public DeferredSlot { + public: + DeferredDouble(double value, RawInstance** slot, DeferredSlot* next) + : DeferredSlot(slot, next), value_(value) { } + + virtual void Materialize(); + + double value() const { return value_; } + + private: + const double value_; + + DISALLOW_COPY_AND_ASSIGN(DeferredDouble); +}; + + +class DeferredMint : public DeferredSlot { + public: + DeferredMint(int64_t value, RawInstance** slot, DeferredSlot* next) + : DeferredSlot(slot, next), value_(value) { } + + virtual void Materialize(); + + int64_t value() const { return value_; } + + private: + const int64_t value_; + + DISALLOW_COPY_AND_ASSIGN(DeferredMint); +}; + + +class DeferredFloat32x4 : public DeferredSlot { + public: + DeferredFloat32x4(simd128_value_t value, RawInstance** slot, + DeferredSlot* next) + : DeferredSlot(slot, next), value_(value) { } + + virtual void Materialize(); + + simd128_value_t value() const { return value_; } + + private: + const simd128_value_t value_; + + DISALLOW_COPY_AND_ASSIGN(DeferredFloat32x4); +}; + + +class DeferredUint32x4 : public DeferredSlot { + public: + DeferredUint32x4(simd128_value_t value, RawInstance** slot, + DeferredSlot* next) + : DeferredSlot(slot, next), value_(value) { } + + virtual void Materialize(); + + simd128_value_t value() const { return value_; } + + private: + const simd128_value_t value_; + + DISALLOW_COPY_AND_ASSIGN(DeferredUint32x4); +}; + + +// Describes a slot that contains a reference to an object that had its +// allocation removed by AllocationSinking pass. +// Object itself is described and materialized by DeferredObject. +class DeferredObjectRef : public DeferredSlot { + public: + DeferredObjectRef(intptr_t index, RawInstance** slot, DeferredSlot* next) + : DeferredSlot(slot, next), index_(index) { } + + virtual void Materialize(); + + intptr_t index() const { return index_; } + + private: + const intptr_t index_; + + DISALLOW_COPY_AND_ASSIGN(DeferredObjectRef); +}; + + +// Describes an object which allocation was removed by AllocationSinking pass. +// Arguments for materialization are stored as a part of expression stack +// for the bottommost deoptimized frame so that GC could discover them. +// They will be removed from the stack at the very end of deoptimization. +class DeferredObject { + public: + DeferredObject(intptr_t field_count, intptr_t* args) + : field_count_(field_count), + args_(reinterpret_cast<RawObject**>(args)), + object_(NULL) { } + + intptr_t ArgumentCount() const { + return kFieldsStartIndex + kFieldEntrySize * field_count_; + } + + RawInstance* object(); + + private: + enum { + kClassIndex = 0, + kFieldsStartIndex = kClassIndex + 1 + }; + + enum { + kFieldIndex = 0, + kValueIndex, + kFieldEntrySize, + }; + + // Materializes the object. Returns amount of values that were consumed + // and should be removed from the expression stack at the very end of + // deoptimization. + void Materialize(); + + RawObject* GetClass() const { + return args_[kClassIndex]; + } + + RawObject* GetField(intptr_t index) const { + return args_[kFieldsStartIndex + kFieldEntrySize * index + kFieldIndex]; + } + + RawObject* GetValue(intptr_t index) const { + return args_[kFieldsStartIndex + kFieldEntrySize * index + kValueIndex]; + } + + // Amount of fields that have to be initialized. + const intptr_t field_count_; + + // Pointer to the first materialization argument on the stack. + // The first argument is Class of the instance to materialize followed by + // Field, value pairs. + RawObject** args_; + + // Object materialized from this description. + const Instance* object_; + + DISALLOW_COPY_AND_ASSIGN(DeferredObject); +}; + +} // namespace dart + +#endif // VM_DEFERRED_OBJECTS_H_
diff --git a/runtime/vm/deopt_instructions.cc b/runtime/vm/deopt_instructions.cc index adca206..f7a7c53 100644 --- a/runtime/vm/deopt_instructions.cc +++ b/runtime/vm/deopt_instructions.cc
@@ -18,71 +18,158 @@ DECLARE_FLAG(bool, trace_deoptimization); DECLARE_FLAG(bool, trace_deoptimization_verbose); -DeoptimizationContext::DeoptimizationContext(intptr_t* to_frame_start, - intptr_t to_frame_size, - const Array& object_table, - intptr_t num_args, - DeoptReasonId deopt_reason) - : object_table_(object_table), - to_frame_(to_frame_start), - to_frame_size_(to_frame_size), - from_frame_(NULL), - from_frame_size_(0), - registers_copy_(NULL), - fpu_registers_copy_(NULL), +DeoptContext::DeoptContext(const Array& object_table, + intptr_t num_args, + DeoptReasonId deopt_reason) + : object_table_(object_table.raw()), + dest_frame_(NULL), + dest_frame_size_(0), + source_frame_is_copy_(false), + source_frame_(NULL), + source_frame_size_(0), + cpu_registers_(NULL), + fpu_registers_(NULL), num_args_(num_args), deopt_reason_(deopt_reason), - isolate_(Isolate::Current()) { - from_frame_ = isolate_->deopt_frame_copy(); - from_frame_size_ = isolate_->deopt_frame_copy_size(); - registers_copy_ = isolate_->deopt_cpu_registers_copy(); - fpu_registers_copy_ = isolate_->deopt_fpu_registers_copy(); - // The deoptimized frame is filled starting just below the sp of its caller - // down to kDartFrameFixedSize words below its own sp. - // The chain of frame pointers is recreated from the fp of the caller. - caller_fp_ = GetFromFp(); + isolate_(Isolate::Current()), + deferred_boxes_(NULL), + deferred_object_refs_(NULL), + deferred_objects_count_(0), + deferred_objects_(NULL) { } -intptr_t DeoptimizationContext::GetFromFp() const { - return from_frame_[from_frame_size_ - 1 - num_args_ - kParamEndSlotFromFp]; +DeoptContext::~DeoptContext() { + // Delete memory for source frame and registers. + if (source_frame_is_copy_) { + delete[] source_frame_; + } + source_frame_ = NULL; + delete[] fpu_registers_; + delete[] cpu_registers_; + fpu_registers_ = NULL; + cpu_registers_ = NULL; + + // Delete all deferred objects. + for (intptr_t i = 0; i < deferred_objects_count_; i++) { + delete deferred_objects_[i]; + } + delete[] deferred_objects_; + deferred_objects_ = NULL; + deferred_objects_count_ = 0; } -intptr_t DeoptimizationContext::GetFromPp() const { - return from_frame_[from_frame_size_ - 1 - num_args_ - kParamEndSlotFromFp + - StackFrame::SavedCallerPpSlotFromFp()]; +void DeoptContext::SetSourceArgs(intptr_t* frame_start, + intptr_t frame_size, + fpu_register_t* fpu_registers, + intptr_t* cpu_registers, + bool source_frame_is_copy) { + ASSERT(frame_start != NULL); + ASSERT(frame_size >= 0); + ASSERT(source_frame_ == NULL); + ASSERT(cpu_registers_ == NULL && fpu_registers_ == NULL); + source_frame_ = frame_start; + source_frame_size_ = frame_size; + caller_fp_ = GetSourceFp(); + cpu_registers_ = cpu_registers; + fpu_registers_ = fpu_registers; + source_frame_is_copy_ = source_frame_is_copy; } -intptr_t DeoptimizationContext::GetFromPc() const { - return from_frame_[from_frame_size_ - num_args_ + kSavedPcSlotFromSp]; +void DeoptContext::SetDestArgs(intptr_t* frame_start, + intptr_t frame_size) { + ASSERT(frame_start != NULL); + ASSERT(frame_size >= 0); + ASSERT(dest_frame_ == NULL); + dest_frame_ = frame_start; + dest_frame_size_ = frame_size; } -intptr_t DeoptimizationContext::GetCallerFp() const { +void DeoptContext::VisitObjectPointers(ObjectPointerVisitor* visitor) { + visitor->VisitPointer(reinterpret_cast<RawObject**>(&object_table_)); +} + + +intptr_t DeoptContext::GetSourceFp() const { + return source_frame_[source_frame_size_ - 1 - num_args_ - + kParamEndSlotFromFp]; +} + + +intptr_t DeoptContext::GetSourcePp() const { + return source_frame_[source_frame_size_ - 1 - num_args_ - + kParamEndSlotFromFp + + StackFrame::SavedCallerPpSlotFromFp()]; +} + + +intptr_t DeoptContext::GetSourcePc() const { + return source_frame_[source_frame_size_ - num_args_ + kSavedPcSlotFromSp]; +} + + +intptr_t DeoptContext::GetCallerFp() const { return caller_fp_; } -void DeoptimizationContext::SetCallerFp(intptr_t caller_fp) { +void DeoptContext::SetCallerFp(intptr_t caller_fp) { caller_fp_ = caller_fp; } +static void FillDeferredSlots(DeferredSlot** slot_list) { + DeferredSlot* slot = *slot_list; + *slot_list = NULL; + + while (slot != NULL) { + DeferredSlot* current = slot; + slot = slot->next(); + + current->Materialize(); + + delete current; + } +} + + +// Materializes all deferred objects. Returns the total number of +// artificial arguments used during deoptimization. +intptr_t DeoptContext::MaterializeDeferredObjects() { + // First materialize all unboxed "primitive" values (doubles, mints, simd) + // then materialize objects. The order is important: objects might be + // referencing boxes allocated on the first step. At the same time + // objects can't be referencing other deferred objects because storing + // an object into a field is always conservatively treated as escaping by + // allocation sinking and load forwarding. + FillDeferredSlots(&deferred_boxes_); + FillDeferredSlots(&deferred_object_refs_); + + // Compute total number of artificial arguments used during deoptimization. + intptr_t deopt_arguments = 0; + for (intptr_t i = 0; i < DeferredObjectsCount(); i++) { + deopt_arguments += GetDeferredObject(i)->ArgumentCount(); + } + return deopt_arguments; +} + + // Deoptimization instruction moving value from optimized frame at -// 'from_index' to specified slots in the unoptimized frame. -// 'from_index' represents the slot index of the frame (0 being first argument) -// and accounts for saved return address, frame pointer, pool pointer and pc -// marker. +// 'source_index' to specified slots in the unoptimized frame. +// 'source_index' represents the slot index of the frame (0 being +// first argument) and accounts for saved return address, frame +// pointer, pool pointer and pc marker. class DeoptStackSlotInstr : public DeoptInstr { public: - explicit DeoptStackSlotInstr(intptr_t from_index) - : stack_slot_index_(from_index) { + explicit DeoptStackSlotInstr(intptr_t source_index) + : stack_slot_index_(source_index) { ASSERT(stack_slot_index_ >= 0); } - virtual intptr_t from_index() const { return stack_slot_index_; } + virtual intptr_t source_index() const { return stack_slot_index_; } virtual DeoptInstr::Kind kind() const { return kStackSlot; } virtual const char* ToCString() const { @@ -90,11 +177,12 @@ "s%" Pd "", stack_slot_index_); } - void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { - intptr_t from_index = - deopt_context->from_frame_size() - stack_slot_index_ - 1; - intptr_t* from_addr = deopt_context->GetFromFrameAddressAt(from_index); - *to_addr = *from_addr; + void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { + intptr_t source_index = + deopt_context->source_frame_size() - stack_slot_index_ - 1; + intptr_t* source_addr = + deopt_context->GetSourceFrameAddressAt(source_index); + *dest_addr = *source_addr; } private: @@ -106,12 +194,12 @@ class DeoptDoubleStackSlotInstr : public DeoptInstr { public: - explicit DeoptDoubleStackSlotInstr(intptr_t from_index) - : stack_slot_index_(from_index) { + explicit DeoptDoubleStackSlotInstr(intptr_t source_index) + : stack_slot_index_(source_index) { ASSERT(stack_slot_index_ >= 0); } - virtual intptr_t from_index() const { return stack_slot_index_; } + virtual intptr_t source_index() const { return stack_slot_index_; } virtual DeoptInstr::Kind kind() const { return kDoubleStackSlot; } virtual const char* ToCString() const { @@ -119,14 +207,14 @@ "ds%" Pd "", stack_slot_index_); } - void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { - intptr_t from_index = - deopt_context->from_frame_size() - stack_slot_index_ - 1; - double* from_addr = reinterpret_cast<double*>( - deopt_context->GetFromFrameAddressAt(from_index)); - *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); - Isolate::Current()->DeferDoubleMaterialization( - *from_addr, reinterpret_cast<RawDouble**>(to_addr)); + void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { + intptr_t source_index = + deopt_context->source_frame_size() - stack_slot_index_ - 1; + double* source_addr = reinterpret_cast<double*>( + deopt_context->GetSourceFrameAddressAt(source_index)); + *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); + deopt_context->DeferDoubleMaterialization( + *source_addr, reinterpret_cast<RawDouble**>(dest_addr)); } private: @@ -138,12 +226,12 @@ class DeoptInt64StackSlotInstr : public DeoptInstr { public: - explicit DeoptInt64StackSlotInstr(intptr_t from_index) - : stack_slot_index_(from_index) { + explicit DeoptInt64StackSlotInstr(intptr_t source_index) + : stack_slot_index_(source_index) { ASSERT(stack_slot_index_ >= 0); } - virtual intptr_t from_index() const { return stack_slot_index_; } + virtual intptr_t source_index() const { return stack_slot_index_; } virtual DeoptInstr::Kind kind() const { return kInt64StackSlot; } virtual const char* ToCString() const { @@ -151,18 +239,18 @@ "ms%" Pd "", stack_slot_index_); } - void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { - intptr_t from_index = - deopt_context->from_frame_size() - stack_slot_index_ - 1; - int64_t* from_addr = reinterpret_cast<int64_t*>( - deopt_context->GetFromFrameAddressAt(from_index)); - *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); - if (Smi::IsValid64(*from_addr)) { - *to_addr = reinterpret_cast<intptr_t>( - Smi::New(static_cast<intptr_t>(*from_addr))); + void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { + intptr_t source_index = + deopt_context->source_frame_size() - stack_slot_index_ - 1; + int64_t* source_addr = reinterpret_cast<int64_t*>( + deopt_context->GetSourceFrameAddressAt(source_index)); + *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); + if (Smi::IsValid64(*source_addr)) { + *dest_addr = reinterpret_cast<intptr_t>( + Smi::New(static_cast<intptr_t>(*source_addr))); } else { - Isolate::Current()->DeferMintMaterialization( - *from_addr, reinterpret_cast<RawMint**>(to_addr)); + deopt_context->DeferMintMaterialization( + *source_addr, reinterpret_cast<RawMint**>(dest_addr)); } } @@ -175,12 +263,12 @@ class DeoptFloat32x4StackSlotInstr : public DeoptInstr { public: - explicit DeoptFloat32x4StackSlotInstr(intptr_t from_index) - : stack_slot_index_(from_index) { + explicit DeoptFloat32x4StackSlotInstr(intptr_t source_index) + : stack_slot_index_(source_index) { ASSERT(stack_slot_index_ >= 0); } - virtual intptr_t from_index() const { return stack_slot_index_; } + virtual intptr_t source_index() const { return stack_slot_index_; } virtual DeoptInstr::Kind kind() const { return kFloat32x4StackSlot; } virtual const char* ToCString() const { @@ -188,14 +276,14 @@ "f32x4s%" Pd "", stack_slot_index_); } - void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { - intptr_t from_index = - deopt_context->from_frame_size() - stack_slot_index_ - 1; - simd128_value_t* from_addr = reinterpret_cast<simd128_value_t*>( - deopt_context->GetFromFrameAddressAt(from_index)); - *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); - Isolate::Current()->DeferFloat32x4Materialization( - *from_addr, reinterpret_cast<RawFloat32x4**>(to_addr)); + void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { + intptr_t source_index = + deopt_context->source_frame_size() - stack_slot_index_ - 1; + simd128_value_t* source_addr = reinterpret_cast<simd128_value_t*>( + deopt_context->GetSourceFrameAddressAt(source_index)); + *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); + deopt_context->DeferFloat32x4Materialization( + *source_addr, reinterpret_cast<RawFloat32x4**>(dest_addr)); } private: @@ -207,12 +295,12 @@ class DeoptUint32x4StackSlotInstr : public DeoptInstr { public: - explicit DeoptUint32x4StackSlotInstr(intptr_t from_index) - : stack_slot_index_(from_index) { + explicit DeoptUint32x4StackSlotInstr(intptr_t source_index) + : stack_slot_index_(source_index) { ASSERT(stack_slot_index_ >= 0); } - virtual intptr_t from_index() const { return stack_slot_index_; } + virtual intptr_t source_index() const { return stack_slot_index_; } virtual DeoptInstr::Kind kind() const { return kUint32x4StackSlot; } virtual const char* ToCString() const { @@ -220,14 +308,14 @@ "ui32x4s%" Pd "", stack_slot_index_); } - void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { - intptr_t from_index = - deopt_context->from_frame_size() - stack_slot_index_ - 1; - simd128_value_t* from_addr = reinterpret_cast<simd128_value_t*>( - deopt_context->GetFromFrameAddressAt(from_index)); - *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); - Isolate::Current()->DeferUint32x4Materialization( - *from_addr, reinterpret_cast<RawUint32x4**>(to_addr)); + void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { + intptr_t source_index = + deopt_context->source_frame_size() - stack_slot_index_ - 1; + simd128_value_t* source_addr = reinterpret_cast<simd128_value_t*>( + deopt_context->GetSourceFrameAddressAt(source_index)); + *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); + deopt_context->DeferUint32x4Materialization( + *source_addr, reinterpret_cast<RawUint32x4**>(dest_addr)); } private: @@ -247,12 +335,12 @@ ASSERT(deopt_id >= 0); } - explicit DeoptRetAddressInstr(intptr_t from_index) - : object_table_index_(ObjectTableIndex::decode(from_index)), - deopt_id_(DeoptId::decode(from_index)) { + explicit DeoptRetAddressInstr(intptr_t source_index) + : object_table_index_(ObjectTableIndex::decode(source_index)), + deopt_id_(DeoptId::decode(source_index)) { } - virtual intptr_t from_index() const { + virtual intptr_t source_index() const { return ObjectTableIndex::encode(object_table_index_) | DeoptId::encode(deopt_id_); } @@ -264,7 +352,7 @@ "ret oti:%" Pd "(%" Pd ")", object_table_index_, deopt_id_); } - void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { + void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { Function& function = Function::Handle(deopt_context->isolate()); function ^= deopt_context->ObjectAt(object_table_index_); const Code& code = @@ -273,7 +361,7 @@ uword continue_at_pc = code.GetPcForDeoptId(deopt_id_, PcDescriptors::kDeopt); ASSERT(continue_at_pc != 0); - *to_addr = continue_at_pc; + *dest_addr = continue_at_pc; uword pc = code.GetPcForDeoptId(deopt_id_, PcDescriptors::kIcCall); if (pc != 0) { @@ -310,7 +398,7 @@ ASSERT(object_table_index >= 0); } - virtual intptr_t from_index() const { return object_table_index_; } + virtual intptr_t source_index() const { return object_table_index_; } virtual DeoptInstr::Kind kind() const { return kConstant; } virtual const char* ToCString() const { @@ -318,10 +406,10 @@ "const oti:%" Pd "", object_table_index_); } - void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { + void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { const Object& obj = Object::Handle( deopt_context->isolate(), deopt_context->ObjectAt(object_table_index_)); - *reinterpret_cast<RawObject**>(to_addr) = obj.raw(); + *reinterpret_cast<RawObject**>(dest_addr) = obj.raw(); } private: @@ -337,15 +425,15 @@ explicit DeoptRegisterInstr(intptr_t reg_as_int) : reg_(static_cast<Register>(reg_as_int)) {} - virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); } + virtual intptr_t source_index() const { return static_cast<intptr_t>(reg_); } virtual DeoptInstr::Kind kind() const { return kRegister; } virtual const char* ToCString() const { return Assembler::RegisterName(reg_); } - void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { - *to_addr = deopt_context->RegisterValue(reg_); + void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { + *dest_addr = deopt_context->RegisterValue(reg_); } private: @@ -361,18 +449,18 @@ explicit DeoptFpuRegisterInstr(intptr_t reg_as_int) : reg_(static_cast<FpuRegister>(reg_as_int)) {} - virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); } + virtual intptr_t source_index() const { return static_cast<intptr_t>(reg_); } virtual DeoptInstr::Kind kind() const { return kFpuRegister; } virtual const char* ToCString() const { return Assembler::FpuRegisterName(reg_); } - void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { + void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { double value = deopt_context->FpuRegisterValue(reg_); - *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); - Isolate::Current()->DeferDoubleMaterialization( - value, reinterpret_cast<RawDouble**>(to_addr)); + *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); + deopt_context->DeferDoubleMaterialization( + value, reinterpret_cast<RawDouble**>(dest_addr)); } private: @@ -387,7 +475,7 @@ explicit DeoptInt64FpuRegisterInstr(intptr_t reg_as_int) : reg_(static_cast<FpuRegister>(reg_as_int)) {} - virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); } + virtual intptr_t source_index() const { return static_cast<intptr_t>(reg_); } virtual DeoptInstr::Kind kind() const { return kInt64FpuRegister; } virtual const char* ToCString() const { @@ -395,15 +483,15 @@ "%s(m)", Assembler::FpuRegisterName(reg_)); } - void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { + void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { int64_t value = deopt_context->FpuRegisterValueAsInt64(reg_); - *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); + *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); if (Smi::IsValid64(value)) { - *to_addr = reinterpret_cast<intptr_t>( + *dest_addr = reinterpret_cast<intptr_t>( Smi::New(static_cast<intptr_t>(value))); } else { - Isolate::Current()->DeferMintMaterialization( - value, reinterpret_cast<RawMint**>(to_addr)); + deopt_context->DeferMintMaterialization( + value, reinterpret_cast<RawMint**>(dest_addr)); } } @@ -420,7 +508,7 @@ explicit DeoptFloat32x4FpuRegisterInstr(intptr_t reg_as_int) : reg_(static_cast<FpuRegister>(reg_as_int)) {} - virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); } + virtual intptr_t source_index() const { return static_cast<intptr_t>(reg_); } virtual DeoptInstr::Kind kind() const { return kFloat32x4FpuRegister; } virtual const char* ToCString() const { @@ -428,11 +516,11 @@ "%s(f32x4)", Assembler::FpuRegisterName(reg_)); } - void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { + void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { simd128_value_t value = deopt_context->FpuRegisterValueAsSimd128(reg_); - *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); - Isolate::Current()->DeferFloat32x4Materialization( - value, reinterpret_cast<RawFloat32x4**>(to_addr)); + *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); + deopt_context->DeferFloat32x4Materialization( + value, reinterpret_cast<RawFloat32x4**>(dest_addr)); } private: @@ -448,7 +536,7 @@ explicit DeoptUint32x4FpuRegisterInstr(intptr_t reg_as_int) : reg_(static_cast<FpuRegister>(reg_as_int)) {} - virtual intptr_t from_index() const { return static_cast<intptr_t>(reg_); } + virtual intptr_t source_index() const { return static_cast<intptr_t>(reg_); } virtual DeoptInstr::Kind kind() const { return kUint32x4FpuRegister; } virtual const char* ToCString() const { @@ -456,11 +544,11 @@ "%s(f32x4)", Assembler::FpuRegisterName(reg_)); } - void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { + void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { simd128_value_t value = deopt_context->FpuRegisterValueAsSimd128(reg_); - *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); - Isolate::Current()->DeferUint32x4Materialization( - value, reinterpret_cast<RawUint32x4**>(to_addr)); + *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); + deopt_context->DeferUint32x4Materialization( + value, reinterpret_cast<RawUint32x4**>(dest_addr)); } private: @@ -479,7 +567,7 @@ ASSERT(object_table_index >= 0); } - virtual intptr_t from_index() const { return object_table_index_; } + virtual intptr_t source_index() const { return object_table_index_; } virtual DeoptInstr::Kind kind() const { return kPcMarker; } virtual const char* ToCString() const { @@ -487,12 +575,12 @@ "pcmark oti:%" Pd "", object_table_index_); } - void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { + void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { Function& function = Function::Handle(deopt_context->isolate()); function ^= deopt_context->ObjectAt(object_table_index_); if (function.IsNull()) { // Callee's PC marker is not used (pc of Deoptimize stub). Set to 0. - *to_addr = 0; + *dest_addr = 0; return; } const Code& code = @@ -500,7 +588,7 @@ ASSERT(!code.IsNull()); const intptr_t pc_marker = code.EntryPoint() + Assembler::kEntryPointToPcMarkerOffset; - *to_addr = pc_marker; + *dest_addr = pc_marker; // Increment the deoptimization counter. This effectively increments each // function occurring in the optimized frame. function.set_deoptimization_counter(function.deoptimization_counter() + 1); @@ -531,7 +619,7 @@ ASSERT(object_table_index >= 0); } - virtual intptr_t from_index() const { return object_table_index_; } + virtual intptr_t source_index() const { return object_table_index_; } virtual DeoptInstr::Kind kind() const { return kPp; } virtual const char* ToCString() const { @@ -539,14 +627,14 @@ "pp oti:%" Pd "", object_table_index_); } - void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { + void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { Function& function = Function::Handle(deopt_context->isolate()); function ^= deopt_context->ObjectAt(object_table_index_); const Code& code = Code::Handle(deopt_context->isolate(), function.unoptimized_code()); ASSERT(!code.IsNull()); const intptr_t pp = reinterpret_cast<intptr_t>(code.ObjectPool()); - *to_addr = pp; + *dest_addr = pp; } private: @@ -561,17 +649,17 @@ public: DeoptCallerFpInstr() {} - virtual intptr_t from_index() const { return 0; } + virtual intptr_t source_index() const { return 0; } virtual DeoptInstr::Kind kind() const { return kCallerFp; } virtual const char* ToCString() const { return "callerfp"; } - void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { - *to_addr = deopt_context->GetCallerFp(); + void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { + *dest_addr = deopt_context->GetCallerFp(); deopt_context->SetCallerFp(reinterpret_cast<intptr_t>( - to_addr - (kSavedCallerFpSlotFromFp * kWordSize))); + dest_addr - (kSavedCallerFpSlotFromFp * kWordSize))); } private: @@ -584,15 +672,15 @@ public: DeoptCallerPpInstr() {} - virtual intptr_t from_index() const { return 0; } + virtual intptr_t source_index() const { return 0; } virtual DeoptInstr::Kind kind() const { return kCallerPp; } virtual const char* ToCString() const { return "callerpp"; } - void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { - *to_addr = deopt_context->GetFromPp(); + void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { + *dest_addr = deopt_context->GetSourcePp(); } private: @@ -606,15 +694,15 @@ public: DeoptCallerPcInstr() {} - virtual intptr_t from_index() const { return 0; } + virtual intptr_t source_index() const { return 0; } virtual DeoptInstr::Kind kind() const { return kCallerPc; } virtual const char* ToCString() const { return "callerpc"; } - void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { - *to_addr = deopt_context->GetFromPc(); + void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { + *dest_addr = deopt_context->GetSourcePc(); } private: @@ -634,12 +722,12 @@ ASSERT(suffix_length >= 0); } - explicit DeoptSuffixInstr(intptr_t from_index) - : info_number_(InfoNumber::decode(from_index)), - suffix_length_(SuffixLength::decode(from_index)) { + explicit DeoptSuffixInstr(intptr_t source_index) + : info_number_(InfoNumber::decode(source_index)), + suffix_length_(SuffixLength::decode(source_index)) { } - virtual intptr_t from_index() const { + virtual intptr_t source_index() const { return InfoNumber::encode(info_number_) | SuffixLength::encode(suffix_length_); } @@ -650,7 +738,7 @@ "suffix %" Pd ":%" Pd, info_number_, suffix_length_); } - void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { + void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { // The deoptimization info is uncompressed by translating away suffixes // before executing the instructions. UNREACHABLE(); @@ -681,7 +769,7 @@ ASSERT(index >= 0); } - virtual intptr_t from_index() const { return index_; } + virtual intptr_t source_index() const { return index_; } virtual DeoptInstr::Kind kind() const { return kMaterializedObjectRef; } virtual const char* ToCString() const { @@ -689,10 +777,10 @@ "mat ref #%" Pd "", index_); } - void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { - *reinterpret_cast<RawSmi**>(to_addr) = Smi::New(0); - Isolate::Current()->DeferMaterializedObjectRef( - index_, to_addr); + void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { + *reinterpret_cast<RawSmi**>(dest_addr) = Smi::New(0); + deopt_context->DeferMaterializedObjectRef( + index_, dest_addr); } private: @@ -712,7 +800,7 @@ ASSERT(field_count >= 0); } - virtual intptr_t from_index() const { return field_count_; } + virtual intptr_t source_index() const { return field_count_; } virtual DeoptInstr::Kind kind() const { return kMaterializeObject; } virtual const char* ToCString() const { @@ -720,7 +808,7 @@ "mat obj len:%" Pd "", field_count_); } - void Execute(DeoptimizationContext* deopt_context, intptr_t* to_addr) { + void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) { // This instructions are executed manually by the DeoptimizeWithDeoptInfo. UNREACHABLE(); } @@ -732,9 +820,10 @@ }; -intptr_t DeoptInstr::DecodeSuffix(intptr_t from_index, intptr_t* info_number) { - *info_number = DeoptSuffixInstr::InfoNumber::decode(from_index); - return DeoptSuffixInstr::SuffixLength::decode(from_index); +intptr_t DeoptInstr::DecodeSuffix(intptr_t source_index, + intptr_t* info_number) { + *info_number = DeoptSuffixInstr::InfoNumber::decode(source_index); + return DeoptSuffixInstr::SuffixLength::decode(source_index); } @@ -759,34 +848,35 @@ } -DeoptInstr* DeoptInstr::Create(intptr_t kind_as_int, intptr_t from_index) { +DeoptInstr* DeoptInstr::Create(intptr_t kind_as_int, intptr_t source_index) { Kind kind = static_cast<Kind>(kind_as_int); switch (kind) { - case kStackSlot: return new DeoptStackSlotInstr(from_index); - case kDoubleStackSlot: return new DeoptDoubleStackSlotInstr(from_index); - case kInt64StackSlot: return new DeoptInt64StackSlotInstr(from_index); + case kStackSlot: return new DeoptStackSlotInstr(source_index); + case kDoubleStackSlot: return new DeoptDoubleStackSlotInstr(source_index); + case kInt64StackSlot: return new DeoptInt64StackSlotInstr(source_index); case kFloat32x4StackSlot: - return new DeoptFloat32x4StackSlotInstr(from_index); + return new DeoptFloat32x4StackSlotInstr(source_index); case kUint32x4StackSlot: - return new DeoptUint32x4StackSlotInstr(from_index); - case kRetAddress: return new DeoptRetAddressInstr(from_index); - case kConstant: return new DeoptConstantInstr(from_index); - case kRegister: return new DeoptRegisterInstr(from_index); - case kFpuRegister: return new DeoptFpuRegisterInstr(from_index); - case kInt64FpuRegister: return new DeoptInt64FpuRegisterInstr(from_index); + return new DeoptUint32x4StackSlotInstr(source_index); + case kRetAddress: return new DeoptRetAddressInstr(source_index); + case kConstant: return new DeoptConstantInstr(source_index); + case kRegister: return new DeoptRegisterInstr(source_index); + case kFpuRegister: return new DeoptFpuRegisterInstr(source_index); + case kInt64FpuRegister: return new DeoptInt64FpuRegisterInstr(source_index); case kFloat32x4FpuRegister: - return new DeoptFloat32x4FpuRegisterInstr(from_index); + return new DeoptFloat32x4FpuRegisterInstr(source_index); case kUint32x4FpuRegister: - return new DeoptUint32x4FpuRegisterInstr(from_index); - case kPcMarker: return new DeoptPcMarkerInstr(from_index); - case kPp: return new DeoptPpInstr(from_index); + return new DeoptUint32x4FpuRegisterInstr(source_index); + case kPcMarker: return new DeoptPcMarkerInstr(source_index); + case kPp: return new DeoptPpInstr(source_index); case kCallerFp: return new DeoptCallerFpInstr(); case kCallerPp: return new DeoptCallerPpInstr(); case kCallerPc: return new DeoptCallerPcInstr(); - case kSuffix: return new DeoptSuffixInstr(from_index); + case kSuffix: return new DeoptSuffixInstr(source_index); case kMaterializedObjectRef: - return new DeoptMaterializedObjectRefInstr(from_index); - case kMaterializeObject: return new DeoptMaterializeObjectInstr(from_index); + return new DeoptMaterializedObjectRefInstr(source_index); + case kMaterializeObject: + return new DeoptMaterializeObjectInstr(source_index); } UNREACHABLE(); return NULL; @@ -850,16 +940,17 @@ } -intptr_t DeoptInfoBuilder::CalculateStackIndex(const Location& from_loc) const { - return from_loc.stack_index() < 0 ? - from_loc.stack_index() + num_args_ : - from_loc.stack_index() + num_args_ + kDartFrameFixedSize; +intptr_t DeoptInfoBuilder::CalculateStackIndex( + const Location& source_loc) const { + return source_loc.stack_index() < 0 ? + source_loc.stack_index() + num_args_ : + source_loc.stack_index() + num_args_ + kDartFrameFixedSize; } void DeoptInfoBuilder::AddReturnAddress(const Function& function, intptr_t deopt_id, - intptr_t to_index) { + intptr_t dest_index) { // Check that deopt_id exists. // TODO(vegorov): verify after deoptimization targets as well. #ifdef DEBUG @@ -868,68 +959,68 @@ (code.GetPcForDeoptId(deopt_id, PcDescriptors::kDeopt) != 0)); #endif const intptr_t object_table_index = FindOrAddObjectInTable(function); - ASSERT(to_index == FrameSize()); + ASSERT(dest_index == FrameSize()); instructions_.Add(new DeoptRetAddressInstr(object_table_index, deopt_id)); } void DeoptInfoBuilder::AddPcMarker(const Function& function, - intptr_t to_index) { + intptr_t dest_index) { intptr_t object_table_index = FindOrAddObjectInTable(function); - ASSERT(to_index == FrameSize()); + ASSERT(dest_index == FrameSize()); instructions_.Add(new DeoptPcMarkerInstr(object_table_index)); } -void DeoptInfoBuilder::AddPp(const Function& function, intptr_t to_index) { +void DeoptInfoBuilder::AddPp(const Function& function, intptr_t dest_index) { intptr_t object_table_index = FindOrAddObjectInTable(function); - ASSERT(to_index == FrameSize()); + ASSERT(dest_index == FrameSize()); instructions_.Add(new DeoptPpInstr(object_table_index)); } void DeoptInfoBuilder::AddCopy(Value* value, - const Location& from_loc, - const intptr_t to_index) { + const Location& source_loc, + const intptr_t dest_index) { DeoptInstr* deopt_instr = NULL; - if (from_loc.IsConstant()) { - intptr_t object_table_index = FindOrAddObjectInTable(from_loc.constant()); + if (source_loc.IsConstant()) { + intptr_t object_table_index = FindOrAddObjectInTable(source_loc.constant()); deopt_instr = new DeoptConstantInstr(object_table_index); - } else if (from_loc.IsRegister()) { + } else if (source_loc.IsRegister()) { ASSERT(value->definition()->representation() == kTagged); - deopt_instr = new DeoptRegisterInstr(from_loc.reg()); - } else if (from_loc.IsFpuRegister()) { + deopt_instr = new DeoptRegisterInstr(source_loc.reg()); + } else if (source_loc.IsFpuRegister()) { if (value->definition()->representation() == kUnboxedDouble) { - deopt_instr = new DeoptFpuRegisterInstr(from_loc.fpu_reg()); + deopt_instr = new DeoptFpuRegisterInstr(source_loc.fpu_reg()); } else if (value->definition()->representation() == kUnboxedMint) { - deopt_instr = new DeoptInt64FpuRegisterInstr(from_loc.fpu_reg()); + deopt_instr = new DeoptInt64FpuRegisterInstr(source_loc.fpu_reg()); } else if (value->definition()->representation() == kUnboxedFloat32x4) { - deopt_instr = new DeoptFloat32x4FpuRegisterInstr(from_loc.fpu_reg()); + deopt_instr = new DeoptFloat32x4FpuRegisterInstr(source_loc.fpu_reg()); } else { ASSERT(value->definition()->representation() == kUnboxedUint32x4); - deopt_instr = new DeoptUint32x4FpuRegisterInstr(from_loc.fpu_reg()); + deopt_instr = new DeoptUint32x4FpuRegisterInstr(source_loc.fpu_reg()); } - } else if (from_loc.IsStackSlot()) { + } else if (source_loc.IsStackSlot()) { ASSERT(value->definition()->representation() == kTagged); - intptr_t from_index = CalculateStackIndex(from_loc); - deopt_instr = new DeoptStackSlotInstr(from_index); - } else if (from_loc.IsDoubleStackSlot()) { - intptr_t from_index = CalculateStackIndex(from_loc); + intptr_t source_index = CalculateStackIndex(source_loc); + deopt_instr = new DeoptStackSlotInstr(source_index); + } else if (source_loc.IsDoubleStackSlot()) { + intptr_t source_index = CalculateStackIndex(source_loc); if (value->definition()->representation() == kUnboxedDouble) { - deopt_instr = new DeoptDoubleStackSlotInstr(from_index); + deopt_instr = new DeoptDoubleStackSlotInstr(source_index); } else { ASSERT(value->definition()->representation() == kUnboxedMint); - deopt_instr = new DeoptInt64StackSlotInstr(from_index); + deopt_instr = new DeoptInt64StackSlotInstr(source_index); } - } else if (from_loc.IsQuadStackSlot()) { - intptr_t from_index = CalculateStackIndex(from_loc); + } else if (source_loc.IsQuadStackSlot()) { + intptr_t source_index = CalculateStackIndex(source_loc); if (value->definition()->representation() == kUnboxedFloat32x4) { - deopt_instr = new DeoptFloat32x4StackSlotInstr(from_index); + deopt_instr = new DeoptFloat32x4StackSlotInstr(source_index); } else { ASSERT(value->definition()->representation() == kUnboxedUint32x4); - deopt_instr = new DeoptUint32x4StackSlotInstr(from_index); + deopt_instr = new DeoptUint32x4StackSlotInstr(source_index); } - } else if (from_loc.IsInvalid() && + } else if (source_loc.IsInvalid() && value->definition()->IsMaterializeObject()) { const intptr_t index = FindMaterialization( value->definition()->AsMaterializeObject()); @@ -938,32 +1029,32 @@ } else { UNREACHABLE(); } - ASSERT(to_index == FrameSize()); + ASSERT(dest_index == FrameSize()); ASSERT(deopt_instr != NULL); instructions_.Add(deopt_instr); } -void DeoptInfoBuilder::AddCallerFp(intptr_t to_index) { - ASSERT(to_index == FrameSize()); +void DeoptInfoBuilder::AddCallerFp(intptr_t dest_index) { + ASSERT(dest_index == FrameSize()); instructions_.Add(new DeoptCallerFpInstr()); } -void DeoptInfoBuilder::AddCallerPp(intptr_t to_index) { - ASSERT(to_index == FrameSize()); +void DeoptInfoBuilder::AddCallerPp(intptr_t dest_index) { + ASSERT(dest_index == FrameSize()); instructions_.Add(new DeoptCallerPpInstr()); } -void DeoptInfoBuilder::AddCallerPc(intptr_t to_index) { - ASSERT(to_index == FrameSize()); +void DeoptInfoBuilder::AddCallerPc(intptr_t dest_index) { + ASSERT(dest_index == FrameSize()); instructions_.Add(new DeoptCallerPcInstr()); } -void DeoptInfoBuilder::AddConstant(const Object& obj, intptr_t to_index) { - ASSERT(to_index == FrameSize()); +void DeoptInfoBuilder::AddConstant(const Object& obj, intptr_t dest_index) { + ASSERT(dest_index == FrameSize()); intptr_t object_table_index = FindOrAddObjectInTable(obj); instructions_.Add(new DeoptConstantInstr(object_table_index)); } @@ -990,20 +1081,21 @@ } -intptr_t DeoptInfoBuilder::EmitMaterializationArguments(intptr_t to_index) { - ASSERT(to_index == kDartFrameFixedSize); +intptr_t DeoptInfoBuilder::EmitMaterializationArguments(intptr_t dest_index) { + ASSERT(dest_index == kDartFrameFixedSize); for (intptr_t i = 0; i < materializations_.length(); i++) { MaterializeObjectInstr* mat = materializations_[i]; - AddConstant(mat->cls(), to_index++); // Class of the instance to allocate. + // Class of the instance to allocate. + AddConstant(mat->cls(), dest_index++); for (intptr_t i = 0; i < mat->InputCount(); i++) { if (!mat->InputAt(i)->BindsToConstantNull()) { // Emit field-value pair. - AddConstant(mat->FieldAt(i), to_index++); - AddCopy(mat->InputAt(i), mat->LocationAt(i), to_index++); + AddConstant(mat->FieldAt(i), dest_index++); + AddCopy(mat->InputAt(i), mat->LocationAt(i), dest_index++); } } } - return to_index; + return dest_index; } @@ -1049,7 +1141,7 @@ intptr_t write_count = (suffix_length > 1) ? length - 1 : length; for (intptr_t i = 0; i < write_count; ++i) { DeoptInstr* instr = instructions_[i]; - deopt_info.SetAt(i, instr->kind(), instr->from_index()); + deopt_info.SetAt(i, instr->kind(), instr->source_index()); TrieNode* child = node; node = new TrieNode(instr, current_info_number_); node->AddChild(child); @@ -1059,7 +1151,7 @@ suffix->AddChild(node); DeoptInstr* instr = new DeoptSuffixInstr(suffix->info_number(), suffix_length); - deopt_info.SetAt(length - 1, instr->kind(), instr->from_index()); + deopt_info.SetAt(length - 1, instr->kind(), instr->source_index()); } else { trie_root_->AddChild(node); }
diff --git a/runtime/vm/deopt_instructions.h b/runtime/vm/deopt_instructions.h index 564b744..420ce10 100644 --- a/runtime/vm/deopt_instructions.h +++ b/runtime/vm/deopt_instructions.h
@@ -8,6 +8,7 @@ #include "vm/allocation.h" #include "vm/assembler.h" #include "vm/code_generator.h" +#include "vm/deferred_objects.h" #include "vm/growable_array.h" #include "vm/object.h" @@ -18,75 +19,167 @@ class MaterializeObjectInstr; // Holds all data relevant for execution of deoptimization instructions. -class DeoptimizationContext : public ValueObject { +class DeoptContext { public: - // 'to_frame_start' points to the fixed size portion of the frame under sp. // 'num_args' is 0 if there are no arguments or if there are optional // arguments. - DeoptimizationContext(intptr_t* to_frame_start, - intptr_t to_frame_size, - const Array& object_table, - intptr_t num_args, - DeoptReasonId deopt_reason); + DeoptContext(const Array& object_table, + intptr_t num_args, + DeoptReasonId deopt_reason); - intptr_t* GetFromFrameAddressAt(intptr_t index) const { - ASSERT((0 <= index) && (index < from_frame_size_)); - return &from_frame_[index]; + virtual ~DeoptContext(); + + // Sets the sources (frame and registers) for this deoptimization. + // + // if 'frame_is_copy' is true, DeoptContext will delete the frame + // when it is done. + void SetSourceArgs(intptr_t* frame_start, + intptr_t frame_size, + fpu_register_t* fpu_registers, + intptr_t* cpu_registers, + bool frame_is_copy); + + // Sets the destination fraem for this deoptimization. + // + // 'frame_start' oints to the fixed size portion of the frame under + // sp. + // + // DeoptContext does not claim ownership of the frame memory. + void SetDestArgs(intptr_t* frame_start, intptr_t frame_size); + + intptr_t* GetSourceFrameAddressAt(intptr_t index) const { + ASSERT(source_frame_ != NULL); + ASSERT((0 <= index) && (index < source_frame_size_)); + return &source_frame_[index]; } - intptr_t* GetToFrameAddressAt(intptr_t index) const { - ASSERT((0 <= index) && (index < to_frame_size_)); - return &to_frame_[index]; + intptr_t* GetDestFrameAddressAt(intptr_t index) const { + ASSERT(dest_frame_ != NULL); + ASSERT((0 <= index) && (index < dest_frame_size_)); + return &dest_frame_[index]; } - intptr_t GetFromFp() const; - intptr_t GetFromPp() const; - intptr_t GetFromPc() const; + intptr_t GetSourceFp() const; + intptr_t GetSourcePp() const; + intptr_t GetSourcePc() const; intptr_t GetCallerFp() const; void SetCallerFp(intptr_t callers_fp); RawObject* ObjectAt(intptr_t index) const { - return object_table_.At(index); + const Array& object_table = Array::Handle(object_table_); + return object_table.At(index); } intptr_t RegisterValue(Register reg) const { - return registers_copy_[reg]; + return cpu_registers_[reg]; } double FpuRegisterValue(FpuRegister reg) const { - return *reinterpret_cast<double*>(&fpu_registers_copy_[reg]); + return *reinterpret_cast<double*>(&fpu_registers_[reg]); } int64_t FpuRegisterValueAsInt64(FpuRegister reg) const { - return *reinterpret_cast<int64_t*>(&fpu_registers_copy_[reg]); + return *reinterpret_cast<int64_t*>(&fpu_registers_[reg]); } simd128_value_t FpuRegisterValueAsSimd128(FpuRegister reg) const { - const float* address = reinterpret_cast<float*>(&fpu_registers_copy_[reg]); + const float* address = reinterpret_cast<float*>(&fpu_registers_[reg]); return simd128_value_t().readFrom(address); } Isolate* isolate() const { return isolate_; } - intptr_t from_frame_size() const { return from_frame_size_; } + intptr_t source_frame_size() const { return source_frame_size_; } DeoptReasonId deopt_reason() const { return deopt_reason_; } + void VisitObjectPointers(ObjectPointerVisitor* visitor); + + void PrepareForDeferredMaterialization(intptr_t count) { + if (count > 0) { + deferred_objects_ = new DeferredObject*[count]; + deferred_objects_count_ = count; + } + } + + DeferredObject* GetDeferredObject(intptr_t idx) const { + return deferred_objects_[idx]; + } + + // Sets the materialized value for some deferred object. + // + // Claims ownership of the memory for 'object'. + void SetDeferredObjectAt(intptr_t idx, DeferredObject* object) { + deferred_objects_[idx] = object; + } + + intptr_t DeferredObjectsCount() const { + return deferred_objects_count_; + } + + void DeferMaterializedObjectRef(intptr_t idx, intptr_t* slot) { + deferred_object_refs_ = new DeferredObjectRef( + idx, + reinterpret_cast<RawInstance**>(slot), + deferred_object_refs_); + } + + void DeferDoubleMaterialization(double value, RawDouble** slot) { + deferred_boxes_ = new DeferredDouble( + value, + reinterpret_cast<RawInstance**>(slot), + deferred_boxes_); + } + + void DeferMintMaterialization(int64_t value, RawMint** slot) { + deferred_boxes_ = new DeferredMint( + value, + reinterpret_cast<RawInstance**>(slot), + deferred_boxes_); + } + + void DeferFloat32x4Materialization(simd128_value_t value, + RawFloat32x4** slot) { + deferred_boxes_ = new DeferredFloat32x4( + value, + reinterpret_cast<RawInstance**>(slot), + deferred_boxes_); + } + + void DeferUint32x4Materialization(simd128_value_t value, + RawUint32x4** slot) { + deferred_boxes_ = new DeferredUint32x4( + value, + reinterpret_cast<RawInstance**>(slot), + deferred_boxes_); + } + + // Materializes all deferred objects. Returns the total number of + // artificial arguments used during deoptimization. + intptr_t MaterializeDeferredObjects(); + private: - const Array& object_table_; - intptr_t* to_frame_; - const intptr_t to_frame_size_; - intptr_t* from_frame_; - intptr_t from_frame_size_; - intptr_t* registers_copy_; - fpu_register_t* fpu_registers_copy_; + RawArray* object_table_; + intptr_t* dest_frame_; + intptr_t dest_frame_size_; + bool source_frame_is_copy_; + intptr_t* source_frame_; + intptr_t source_frame_size_; + intptr_t* cpu_registers_; + fpu_register_t* fpu_registers_; const intptr_t num_args_; const DeoptReasonId deopt_reason_; intptr_t caller_fp_; Isolate* isolate_; - DISALLOW_COPY_AND_ASSIGN(DeoptimizationContext); + DeferredSlot* deferred_boxes_; + DeferredSlot* deferred_object_refs_; + + intptr_t deferred_objects_count_; + DeferredObject** deferred_objects_; + + DISALLOW_COPY_AND_ASSIGN(DeoptContext); }; @@ -119,25 +212,24 @@ kMaterializeObject }; - static DeoptInstr* Create(intptr_t kind_as_int, intptr_t from_index); + static DeoptInstr* Create(intptr_t kind_as_int, intptr_t source_index); DeoptInstr() {} virtual ~DeoptInstr() {} virtual const char* ToCString() const = 0; - virtual void Execute(DeoptimizationContext* deopt_context, - intptr_t* to_addr) = 0; + virtual void Execute(DeoptContext* deopt_context, intptr_t* dest_addr) = 0; virtual DeoptInstr::Kind kind() const = 0; bool Equals(const DeoptInstr& other) const { - return (kind() == other.kind()) && (from_index() == other.from_index()); + return (kind() == other.kind()) && (source_index() == other.source_index()); } // Decode the payload of a suffix command. Return the suffix length and // set the output parameter info_number to the index of the shared suffix. - static intptr_t DecodeSuffix(intptr_t from_index, intptr_t* info_number); + static intptr_t DecodeSuffix(intptr_t source_index, intptr_t* info_number); // Get the function and return address which is encoded in this // kRetAfterAddress deopt instruction. @@ -149,13 +241,13 @@ // materialized by kMaterializeObject instruction. static intptr_t GetFieldCount(DeoptInstr* instr) { ASSERT(instr->kind() == DeoptInstr::kMaterializeObject); - return instr->from_index(); + return instr->source_index(); } protected: friend class DeoptInfoBuilder; - virtual intptr_t from_index() const = 0; + virtual intptr_t source_index() const = 0; private: DISALLOW_COPY_AND_ASSIGN(DeoptInstr); @@ -178,15 +270,15 @@ // Return address before instruction. void AddReturnAddress(const Function& function, intptr_t deopt_id, - intptr_t to_index); + intptr_t dest_index); // Copy from optimized frame to unoptimized. - void AddCopy(Value* value, const Location& from_loc, intptr_t to_index); - void AddPcMarker(const Function& function, intptr_t to_index); - void AddPp(const Function& function, intptr_t to_index); - void AddCallerFp(intptr_t to_index); - void AddCallerPp(intptr_t to_index); - void AddCallerPc(intptr_t to_index); + void AddCopy(Value* value, const Location& source_loc, intptr_t dest_index); + void AddPcMarker(const Function& function, intptr_t dest_index); + void AddPp(const Function& function, intptr_t dest_index); + void AddCallerFp(intptr_t dest_index); + void AddCallerPp(intptr_t dest_index); + void AddCallerPc(intptr_t dest_index); // Add object to be materialized. Emit kMaterializeObject instruction. void AddMaterialization(MaterializeObjectInstr* mat); @@ -200,7 +292,7 @@ // At deoptimization they will be removed by the stub at the very end: // after they were used to materialize objects. // Returns the index of the next stack slot. Used for verification. - intptr_t EmitMaterializationArguments(intptr_t to_index); + intptr_t EmitMaterializationArguments(intptr_t dest_index); RawDeoptInfo* CreateDeoptInfo(const Array& deopt_table); @@ -216,13 +308,13 @@ intptr_t FindOrAddObjectInTable(const Object& obj) const; intptr_t FindMaterialization(MaterializeObjectInstr* mat) const; - intptr_t CalculateStackIndex(const Location& from_loc) const; + intptr_t CalculateStackIndex(const Location& source_loc) const; intptr_t FrameSize() const { return instructions_.length() - frame_start_; } - void AddConstant(const Object& obj, intptr_t to_index); + void AddConstant(const Object& obj, intptr_t dest_index); GrowableArray<DeoptInstr*> instructions_; const GrowableObjectArray& object_table_;
diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc index 04cf4f5..5365419 100644 --- a/runtime/vm/exceptions.cc +++ b/runtime/vm/exceptions.cc
@@ -609,6 +609,13 @@ } +void Exceptions::ThrowArgumentError(const Instance& arg) { + const Array& args = Array::Handle(Array::New(1)); + args.SetAt(0, arg); + Exceptions::ThrowByType(Exceptions::kArgument, args); +} + + RawObject* Exceptions::Create(ExceptionType type, const Array& arguments) { Library& library = Library::Handle(); const String* class_name = NULL;
diff --git a/runtime/vm/exceptions.h b/runtime/vm/exceptions.h index 79f7e3a..46d8120 100644 --- a/runtime/vm/exceptions.h +++ b/runtime/vm/exceptions.h
@@ -65,6 +65,7 @@ static void ThrowByType(ExceptionType type, const Array& arguments); static void ThrowOOM(); static void ThrowStackOverflow(); + static void ThrowArgumentError(const Instance& arg); // Returns a RawInstance if the exception is successfully created, // otherwise returns a RawError.
diff --git a/runtime/vm/flow_graph.cc b/runtime/vm/flow_graph.cc index 0f6dce3..b39671b 100644 --- a/runtime/vm/flow_graph.cc +++ b/runtime/vm/flow_graph.cc
@@ -60,9 +60,15 @@ } -GrowableArray<BlockEntryInstr*>* FlowGraph::codegen_block_order( +bool FlowGraph::ShouldReorderBlocks(const Function& function, + bool is_optimized) { + return is_optimized && FLAG_reorder_basic_blocks && !function.is_intrinsic(); +} + + +GrowableArray<BlockEntryInstr*>* FlowGraph::CodegenBlockOrder( bool is_optimized) { - return (is_optimized && FLAG_reorder_basic_blocks) + return ShouldReorderBlocks(parsed_function().function(), is_optimized) ? &optimized_block_order_ : &reverse_postorder_; }
diff --git a/runtime/vm/flow_graph.h b/runtime/vm/flow_graph.h index db384d0..517a9eb 100644 --- a/runtime/vm/flow_graph.h +++ b/runtime/vm/flow_graph.h
@@ -82,7 +82,8 @@ const GrowableArray<BlockEntryInstr*>& reverse_postorder() const { return reverse_postorder_; } - GrowableArray<BlockEntryInstr*>* codegen_block_order(bool is_optimized); + static bool ShouldReorderBlocks(const Function& function, bool is_optimized); + GrowableArray<BlockEntryInstr*>* CodegenBlockOrder(bool is_optimized); // Iterators. BlockIterator reverse_postorder_iterator() const {
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc index ec2b202..69199f0 100644 --- a/runtime/vm/flow_graph_builder.cc +++ b/runtime/vm/flow_graph_builder.cc
@@ -2151,18 +2151,6 @@ } -void EffectGraphVisitor::TranslateArgumentList( - const ArgumentListNode& node, - ZoneGrowableArray<Value*>* values) { - for (intptr_t i = 0; i < node.length(); ++i) { - ValueGraphVisitor for_argument(owner(), temp_index()); - node.NodeAt(i)->Visit(&for_argument); - Append(for_argument); - values->Add(for_argument.value()); - } -} - - void EffectGraphVisitor::BuildPushArguments( const ArgumentListNode& node, ZoneGrowableArray<PushArgumentInstr*>* values) {
diff --git a/runtime/vm/flow_graph_builder.h b/runtime/vm/flow_graph_builder.h index 5013f3e..d022409 100644 --- a/runtime/vm/flow_graph_builder.h +++ b/runtime/vm/flow_graph_builder.h
@@ -20,9 +20,9 @@ // (factory-name-symbol, result-cid, fingerprint). // TODO(srdjan): Store the values in the snapshot instead. #define RECOGNIZED_LIST_FACTORY_LIST(V) \ - V(ObjectArrayFactory, kArrayCid, 1558200848) \ - V(GrowableObjectArrayWithData, kGrowableObjectArrayCid, 619965861) \ - V(GrowableObjectArrayFactory, kGrowableObjectArrayCid, 1180134731) \ + V(_ListFactory, kArrayCid, 1436567945) \ + V(_GrowableListWithData, kGrowableObjectArrayCid, 461305701) \ + V(_GrowableListFactory, kGrowableObjectArrayCid, 910639199) \ V(_Int8ArrayFactory, kTypedDataInt8ArrayCid, 810750844) \ V(_Uint8ArrayFactory, kTypedDataUint8ArrayCid, 1246070930) \ V(_Uint8ClampedArrayFactory, kTypedDataUint8ClampedArrayCid, 1882603960) \ @@ -278,8 +278,6 @@ void HandleStoreLocal(StoreLocalNode* node, bool result_is_needed); // Helpers for translating parts of the AST. - void TranslateArgumentList(const ArgumentListNode& node, - ZoneGrowableArray<Value*>* values); void BuildPushArguments(const ArgumentListNode& node, ZoneGrowableArray<PushArgumentInstr*>* values);
diff --git a/runtime/vm/flow_graph_compiler.cc b/runtime/vm/flow_graph_compiler.cc index 42df32d..2914711 100644 --- a/runtime/vm/flow_graph_compiler.cc +++ b/runtime/vm/flow_graph_compiler.cc
@@ -69,7 +69,7 @@ : assembler_(assembler), parsed_function_(flow_graph->parsed_function()), flow_graph_(*flow_graph), - block_order_(*flow_graph->codegen_block_order(is_optimizing)), + block_order_(*flow_graph->CodegenBlockOrder(is_optimizing)), current_block_(NULL), exception_handlers_list_(NULL), pc_descriptors_list_(NULL), @@ -225,6 +225,31 @@ } +void FlowGraphCompiler::EmitInstructionPrologue(Instruction* instr) { + if (!is_optimizing()) { + if (FLAG_enable_type_checks && instr->IsAssertAssignable()) { + AssertAssignableInstr* assert = instr->AsAssertAssignable(); + AddCurrentDescriptor(PcDescriptors::kDeopt, + assert->deopt_id(), + assert->token_pos()); + } else if (instr->IsGuardField() || + (instr->CanBecomeDeoptimizationTarget() && !instr->IsGoto())) { + // GuardField and instructions that can be deoptimization targets need + // to record their deopt id. GotoInstr records its own so that it can + // control the placement. + AddCurrentDescriptor(PcDescriptors::kDeopt, + instr->deopt_id(), + Scanner::kDummyTokenIndex); + } + AllocateRegistersLocally(instr); + } else if (instr->MayThrow() && + (CurrentTryIndex() != CatchClauseNode::kInvalidTryIndex)) { + // Optimized try-block: Sync locals to fixed stack locations. + EmitTrySync(instr, CurrentTryIndex()); + } +} + + void FlowGraphCompiler::VisitBlocks() { CompactBlocks();
diff --git a/runtime/vm/flow_graph_compiler.h b/runtime/vm/flow_graph_compiler.h index f53ad0f..00f31ec 100644 --- a/runtime/vm/flow_graph_compiler.h +++ b/runtime/vm/flow_graph_compiler.h
@@ -340,6 +340,8 @@ void EmitComment(Instruction* instr); + void EmitEdgeCounter(); + void EmitOptimizedInstanceCall(ExternalLabel* target_label, const ICData& ic_data, intptr_t argument_count,
diff --git a/runtime/vm/flow_graph_compiler_arm.cc b/runtime/vm/flow_graph_compiler_arm.cc index 7353b27..fded60a 100644 --- a/runtime/vm/flow_graph_compiler_arm.cc +++ b/runtime/vm/flow_graph_compiler_arm.cc
@@ -720,28 +720,6 @@ } -void FlowGraphCompiler::EmitInstructionPrologue(Instruction* instr) { - if (!is_optimizing()) { - if (FLAG_enable_type_checks && instr->IsAssertAssignable()) { - AssertAssignableInstr* assert = instr->AsAssertAssignable(); - AddCurrentDescriptor(PcDescriptors::kDeopt, - assert->deopt_id(), - assert->token_pos()); - } else if (instr->IsGuardField() || - instr->CanBecomeDeoptimizationTarget()) { - AddCurrentDescriptor(PcDescriptors::kDeopt, - instr->deopt_id(), - Scanner::kDummyTokenIndex); - } - AllocateRegistersLocally(instr); - } else if (instr->MayThrow() && - (CurrentTryIndex() != CatchClauseNode::kInvalidTryIndex)) { - // Optimized try-block: Sync locals to fixed stack locations. - EmitTrySync(instr, CurrentTryIndex()); - } -} - - void FlowGraphCompiler::EmitTrySyncMove(intptr_t dest_offset, Location loc, bool* push_emitted) { @@ -1275,6 +1253,22 @@ } +void FlowGraphCompiler::EmitEdgeCounter() { + // We do not check for overflow when incrementing the edge counter. The + // function should normally be optimized long before the counter can + // overflow; and though we do not reset the counters when we optimize or + // deoptimize, there is a bound on the number of + // optimization/deoptimization cycles we will attempt. + const Array& counter = Array::ZoneHandle(Array::New(1, Heap::kOld)); + counter.SetAt(0, Smi::Handle(Smi::New(0))); + __ Comment("Edge counter"); + __ LoadObject(R0, counter); + __ ldr(IP, FieldAddress(R0, Array::element_offset(0))); + __ adds(IP, IP, ShifterOperand(Smi::RawValue(1))); + __ str(IP, FieldAddress(R0, Array::element_offset(0))); +} + + void FlowGraphCompiler::EmitOptimizedInstanceCall( ExternalLabel* target_label, const ICData& ic_data, @@ -1457,9 +1451,11 @@ __ Push(reg); __ PushObject(obj); if (is_optimizing()) { - __ BranchLink(&StubCode::OptimizedIdenticalWithNumberCheckLabel()); + __ BranchLinkPatchable( + &StubCode::OptimizedIdenticalWithNumberCheckLabel()); } else { - __ BranchLink(&StubCode::UnoptimizedIdenticalWithNumberCheckLabel()); + __ BranchLinkPatchable( + &StubCode::UnoptimizedIdenticalWithNumberCheckLabel()); } AddCurrentDescriptor(PcDescriptors::kRuntimeCall, Isolate::kNoDeoptId, @@ -1481,9 +1477,11 @@ __ Push(left); __ Push(right); if (is_optimizing()) { - __ BranchLink(&StubCode::OptimizedIdenticalWithNumberCheckLabel()); + __ BranchLinkPatchable( + &StubCode::OptimizedIdenticalWithNumberCheckLabel()); } else { - __ BranchLink(&StubCode::UnoptimizedIdenticalWithNumberCheckLabel()); + __ BranchLinkPatchable( + &StubCode::UnoptimizedIdenticalWithNumberCheckLabel()); } AddCurrentDescriptor(PcDescriptors::kRuntimeCall, Isolate::kNoDeoptId,
diff --git a/runtime/vm/flow_graph_compiler_ia32.cc b/runtime/vm/flow_graph_compiler_ia32.cc index 2ea07d5..cfcde17 100644 --- a/runtime/vm/flow_graph_compiler_ia32.cc +++ b/runtime/vm/flow_graph_compiler_ia32.cc
@@ -742,28 +742,6 @@ } -void FlowGraphCompiler::EmitInstructionPrologue(Instruction* instr) { - if (!is_optimizing()) { - if (FLAG_enable_type_checks && instr->IsAssertAssignable()) { - AssertAssignableInstr* assert = instr->AsAssertAssignable(); - AddCurrentDescriptor(PcDescriptors::kDeopt, - assert->deopt_id(), - assert->token_pos()); - } else if (instr->IsGuardField() || - instr->CanBecomeDeoptimizationTarget()) { - AddCurrentDescriptor(PcDescriptors::kDeopt, - instr->deopt_id(), - Scanner::kDummyTokenIndex); - } - AllocateRegistersLocally(instr); - } else if (instr->MayThrow() && - (CurrentTryIndex() != CatchClauseNode::kInvalidTryIndex)) { - // Optimized try-block: Sync locals to fixed stack locations. - EmitTrySync(instr, CurrentTryIndex()); - } -} - - void FlowGraphCompiler::EmitTrySyncMove(intptr_t dest_offset, Location loc, bool* push_emitted) { @@ -1323,6 +1301,21 @@ } +void FlowGraphCompiler::EmitEdgeCounter() { + // We do not check for overflow when incrementing the edge counter. The + // function should normally be optimized long before the counter can + // overflow; and though we do not reset the counters when we optimize or + // deoptimize, there is a bound on the number of + // optimization/deoptimization cycles we will attempt. + const Array& counter = Array::ZoneHandle(Array::New(1, Heap::kOld)); + counter.SetAt(0, Smi::Handle(Smi::New(0))); + __ Comment("Edge counter"); + __ LoadObject(EAX, counter); + __ addl(FieldAddress(EAX, Array::element_offset(0)), + Immediate(Smi::RawValue(1))); +} + + void FlowGraphCompiler::EmitOptimizedInstanceCall( ExternalLabel* target_label, const ICData& ic_data,
diff --git a/runtime/vm/flow_graph_compiler_mips.cc b/runtime/vm/flow_graph_compiler_mips.cc index 03b0a9a..e18577e 100644 --- a/runtime/vm/flow_graph_compiler_mips.cc +++ b/runtime/vm/flow_graph_compiler_mips.cc
@@ -744,28 +744,6 @@ } -void FlowGraphCompiler::EmitInstructionPrologue(Instruction* instr) { - if (!is_optimizing()) { - if (FLAG_enable_type_checks && instr->IsAssertAssignable()) { - AssertAssignableInstr* assert = instr->AsAssertAssignable(); - AddCurrentDescriptor(PcDescriptors::kDeopt, - assert->deopt_id(), - assert->token_pos()); - } else if (instr->IsGuardField() || - instr->CanBecomeDeoptimizationTarget()) { - AddCurrentDescriptor(PcDescriptors::kDeopt, - instr->deopt_id(), - Scanner::kDummyTokenIndex); - } - AllocateRegistersLocally(instr); - } else if (instr->MayThrow() && - (CurrentTryIndex() != CatchClauseNode::kInvalidTryIndex)) { - // Optimized try-block: Sync locals to fixed stack locations. - EmitTrySync(instr, CurrentTryIndex()); - } -} - - void FlowGraphCompiler::EmitTrySyncMove(intptr_t dest_offset, Location loc, bool* push_emitted) { @@ -1319,6 +1297,22 @@ } +void FlowGraphCompiler::EmitEdgeCounter() { + // We do not check for overflow when incrementing the edge counter. The + // function should normally be optimized long before the counter can + // overflow; and though we do not reset the counters when we optimize or + // deoptimize, there is a bound on the number of + // optimization/deoptimization cycles we will attempt. + const Array& counter = Array::ZoneHandle(Array::New(1, Heap::kOld)); + counter.SetAt(0, Smi::Handle(Smi::New(0))); + __ Comment("Edge counter"); + __ LoadObject(T0, counter); + __ lw(T1, FieldAddress(T0, Array::element_offset(0))); + __ AddImmediate(T1, T1, Smi::RawValue(1)); + __ sw(T1, FieldAddress(T0, Array::element_offset(0))); +} + + void FlowGraphCompiler::EmitOptimizedInstanceCall( ExternalLabel* target_label, const ICData& ic_data, @@ -1508,9 +1502,11 @@ __ LoadObject(TMP1, obj); __ sw(TMP1, Address(SP, 0 * kWordSize)); if (is_optimizing()) { - __ BranchLink(&StubCode::OptimizedIdenticalWithNumberCheckLabel()); + __ BranchLinkPatchable( + &StubCode::OptimizedIdenticalWithNumberCheckLabel()); } else { - __ BranchLink(&StubCode::UnoptimizedIdenticalWithNumberCheckLabel()); + __ BranchLinkPatchable( + &StubCode::UnoptimizedIdenticalWithNumberCheckLabel()); } AddCurrentDescriptor(PcDescriptors::kRuntimeCall, Isolate::kNoDeoptId, @@ -1535,9 +1531,11 @@ __ sw(left, Address(SP, 1 * kWordSize)); __ sw(right, Address(SP, 0 * kWordSize)); if (is_optimizing()) { - __ BranchLink(&StubCode::OptimizedIdenticalWithNumberCheckLabel()); + __ BranchLinkPatchable( + &StubCode::OptimizedIdenticalWithNumberCheckLabel()); } else { - __ BranchLink(&StubCode::UnoptimizedIdenticalWithNumberCheckLabel()); + __ BranchLinkPatchable( + &StubCode::UnoptimizedIdenticalWithNumberCheckLabel()); } AddCurrentDescriptor(PcDescriptors::kRuntimeCall, Isolate::kNoDeoptId,
diff --git a/runtime/vm/flow_graph_compiler_x64.cc b/runtime/vm/flow_graph_compiler_x64.cc index d3c4095..3078762 100644 --- a/runtime/vm/flow_graph_compiler_x64.cc +++ b/runtime/vm/flow_graph_compiler_x64.cc
@@ -163,9 +163,9 @@ Label* is_true, Label* is_false) { Label fall_through; - __ CompareObject(bool_register, Object::null_object()); + __ CompareObject(bool_register, Object::null_object(), PP); __ j(EQUAL, &fall_through, Assembler::kNearJump); - __ CompareObject(bool_register, Bool::True()); + __ CompareObject(bool_register, Bool::True(), PP); __ j(EQUAL, is_true); __ jmp(is_false); __ Bind(&fall_through); @@ -187,11 +187,11 @@ __ pushq(instance_reg); // Instance. if (test_kind == kTestTypeOneArg) { ASSERT(type_arguments_reg == kNoRegister); - __ PushObject(Object::null_object()); + __ PushObject(Object::null_object(), PP); __ Call(&StubCode::Subtype1TestCacheLabel(), PP); } else if (test_kind == kTestTypeTwoArgs) { ASSERT(type_arguments_reg == kNoRegister); - __ PushObject(Object::null_object()); + __ PushObject(Object::null_object(), PP); __ Call(&StubCode::Subtype2TestCacheLabel(), PP); } else if (test_kind == kTestTypeThreeArgs) { __ pushq(type_arguments_reg); @@ -342,7 +342,7 @@ // Check if instance is a closure. __ LoadClassById(R13, kClassIdReg); __ movq(R13, FieldAddress(R13, Class::signature_function_offset())); - __ CompareObject(R13, Object::null_object()); + __ CompareObject(R13, Object::null_object(), PP); __ j(NOT_EQUAL, is_instance_lbl); } // Custom checking for numbers (Smi, Mint, Bigint and Double). @@ -380,7 +380,7 @@ // Check immediate superclass equality. __ movq(R13, FieldAddress(R10, Class::super_type_offset())); __ movq(R13, FieldAddress(R13, Type::type_class_offset())); - __ CompareObject(R13, type_class); + __ CompareObject(R13, type_class, PP); __ j(EQUAL, is_instance_lbl); const Register kTypeArgumentsReg = kNoRegister; @@ -411,7 +411,7 @@ __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments. // RDX: instantiator type arguments. // Check if type argument is dynamic. - __ CompareObject(RDX, Object::null_object()); + __ CompareObject(RDX, Object::null_object(), PP); __ j(EQUAL, is_instance_lbl); // Can handle only type arguments that are instances of TypeArguments. // (runtime checks canonicalize type arguments). @@ -422,21 +422,21 @@ FieldAddress(RDX, TypeArguments::type_at_offset(type_param.index()))); // RDI: Concrete type of type. // Check if type argument is dynamic. - __ CompareObject(RDI, Type::ZoneHandle(Type::DynamicType())); + __ CompareObject(RDI, Type::ZoneHandle(Type::DynamicType()), PP); __ j(EQUAL, is_instance_lbl); - __ CompareObject(RDI, Object::null_object()); + __ CompareObject(RDI, Object::null_object(), PP); __ j(EQUAL, is_instance_lbl); const Type& object_type = Type::ZoneHandle(Type::ObjectType()); - __ CompareObject(RDI, object_type); + __ CompareObject(RDI, object_type, PP); __ j(EQUAL, is_instance_lbl); // For Smi check quickly against int and num interfaces. Label not_smi; __ testq(RAX, Immediate(kSmiTagMask)); // Value is Smi? __ j(NOT_ZERO, ¬_smi, Assembler::kNearJump); - __ CompareObject(RDI, Type::ZoneHandle(Type::IntType())); + __ CompareObject(RDI, Type::ZoneHandle(Type::IntType()), PP); __ j(EQUAL, is_instance_lbl); - __ CompareObject(RDI, Type::ZoneHandle(Type::Number())); + __ CompareObject(RDI, Type::ZoneHandle(Type::Number()), PP); __ j(EQUAL, is_instance_lbl); // Smi must be handled in runtime. __ jmp(&fall_through); @@ -577,7 +577,7 @@ // We can only inline this null check if the type is instantiated at compile // time, since an uninstantiated type at compile time could be Object or // dynamic at run time. - __ CompareObject(RAX, Object::null_object()); + __ CompareObject(RAX, Object::null_object(), PP); __ j(EQUAL, &is_not_instance); } @@ -592,9 +592,9 @@ // Generate runtime call. __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments. __ movq(RCX, Address(RSP, kWordSize)); // Get instantiator. - __ PushObject(Object::ZoneHandle()); // Make room for the result. + __ PushObject(Object::ZoneHandle(), PP); // Make room for the result. __ pushq(RAX); // Push the instance. - __ PushObject(type); // Push the type. + __ PushObject(type, PP); // Push the type. __ pushq(RCX); // TODO(srdjan): Pass instantiator instead of null. __ pushq(RDX); // Instantiator type arguments. __ LoadObject(RAX, test_cache, PP); @@ -657,13 +657,13 @@ __ pushq(RDX); // Store instantiator type arguments. // A null object is always assignable and is returned as result. Label is_assignable, runtime_call; - __ CompareObject(RAX, Object::null_object()); + __ CompareObject(RAX, Object::null_object(), PP); __ j(EQUAL, &is_assignable); if (!FLAG_eliminate_type_checks || dst_type.IsMalformed()) { // If type checks are not eliminated during the graph building then // a transition sentinel can be seen here. - __ CompareObject(RAX, Object::transition_sentinel()); + __ CompareObject(RAX, Object::transition_sentinel(), PP); __ j(EQUAL, &is_assignable); } @@ -678,10 +678,10 @@ } const String& error_message = String::ZoneHandle( Symbols::New(error.ToErrorCString())); - __ PushObject(Object::ZoneHandle()); // Make room for the result. + __ PushObject(Object::ZoneHandle(), PP); // Make room for the result. __ pushq(RAX); // Push the source object. - __ PushObject(dst_name); // Push the name of the destination. - __ PushObject(error_message); + __ PushObject(dst_name, PP); // Push the name of the destination. + __ PushObject(error_message, PP); GenerateCallRuntime(token_pos, deopt_id, kMalformedTypeErrorRuntimeEntry, @@ -704,12 +704,12 @@ __ Bind(&runtime_call); __ movq(RDX, Address(RSP, 0)); // Get instantiator type arguments. __ movq(RCX, Address(RSP, kWordSize)); // Get instantiator. - __ PushObject(Object::ZoneHandle()); // Make room for the result. + __ PushObject(Object::ZoneHandle(), PP); // Make room for the result. __ pushq(RAX); // Push the source object. - __ PushObject(dst_type); // Push the type of the destination. + __ PushObject(dst_type, PP); // Push the type of the destination. __ pushq(RCX); // Instantiator. __ pushq(RDX); // Instantiator type arguments. - __ PushObject(dst_name); // Push the name of the destination. + __ PushObject(dst_name, PP); // Push the name of the destination. __ LoadObject(RAX, test_cache, PP); __ pushq(RAX); GenerateCallRuntime(token_pos, deopt_id, kTypeCheckRuntimeEntry, 6, locs); @@ -724,28 +724,6 @@ } -void FlowGraphCompiler::EmitInstructionPrologue(Instruction* instr) { - if (!is_optimizing()) { - if (FLAG_enable_type_checks && instr->IsAssertAssignable()) { - AssertAssignableInstr* assert = instr->AsAssertAssignable(); - AddCurrentDescriptor(PcDescriptors::kDeopt, - assert->deopt_id(), - assert->token_pos()); - } else if (instr->IsGuardField() || - instr->CanBecomeDeoptimizationTarget()) { - AddCurrentDescriptor(PcDescriptors::kDeopt, - instr->deopt_id(), - Scanner::kDummyTokenIndex); - } - AllocateRegistersLocally(instr); - } else if (instr->MayThrow() && - (CurrentTryIndex() != CatchClauseNode::kInvalidTryIndex)) { - // Optimized try-block: Sync locals to fixed stack locations. - EmitTrySync(instr, CurrentTryIndex()); - } -} - - void FlowGraphCompiler::EmitTrySyncMove(intptr_t dest_offset, Location loc, bool* push_emitted) { @@ -844,10 +822,10 @@ FieldAddress(R10, ArgumentsDescriptor::positional_count_offset())); // Check that min_num_pos_args <= num_pos_args. Label wrong_num_arguments; - __ cmpq(RCX, Immediate(Smi::RawValue(min_num_pos_args))); + __ CompareImmediate(RCX, Immediate(Smi::RawValue(min_num_pos_args)), PP); __ j(LESS, &wrong_num_arguments); // Check that num_pos_args <= max_num_pos_args. - __ cmpq(RCX, Immediate(Smi::RawValue(max_num_pos_args))); + __ CompareImmediate(RCX, Immediate(Smi::RawValue(max_num_pos_args)), PP); __ j(GREATER, &wrong_num_arguments); // Copy positional arguments. @@ -929,14 +907,15 @@ // Load RAX with the name of the argument. __ movq(RAX, Address(RDI, ArgumentsDescriptor::name_offset())); ASSERT(opt_param[i]->name().IsSymbol()); - __ CompareObject(RAX, opt_param[i]->name()); + __ CompareObject(RAX, opt_param[i]->name(), PP); __ j(NOT_EQUAL, &load_default_value, Assembler::kNearJump); // Load RAX with passed-in argument at provided arg_pos, i.e. at // fp[kParamEndSlotFromFp + num_args - arg_pos]. __ movq(RAX, Address(RDI, ArgumentsDescriptor::position_offset())); // RAX is arg_pos as Smi. // Point to next named entry. - __ addq(RDI, Immediate(ArgumentsDescriptor::named_entry_size())); + __ AddImmediate( + RDI, Immediate(ArgumentsDescriptor::named_entry_size()), PP); __ negq(RAX); Address argument_addr(RBX, RAX, TIMES_4, 0); // RAX is a negative Smi. __ movq(RAX, argument_addr); @@ -976,7 +955,7 @@ // arguments have been passed, where k is param_pos, the position of this // optional parameter in the formal parameter list. const int param_pos = num_fixed_params + i; - __ cmpq(RCX, Immediate(param_pos)); + __ CompareImmediate(RCX, Immediate(param_pos), PP); __ j(GREATER, &next_parameter, Assembler::kNearJump); // Load RAX with default argument. const Object& value = Object::ZoneHandle( @@ -1101,12 +1080,16 @@ if (is_optimizing()) { // Reoptimization of an optimized function is triggered by counting in // IC stubs, but not at the entry of the function. - __ cmpq(FieldAddress(function_reg, Function::usage_counter_offset()), - Immediate(FLAG_reoptimization_counter_threshold)); + __ CompareImmediate( + FieldAddress(function_reg, Function::usage_counter_offset()), + Immediate(FLAG_reoptimization_counter_threshold), + new_pp); } else { __ incq(FieldAddress(function_reg, Function::usage_counter_offset())); - __ cmpq(FieldAddress(function_reg, Function::usage_counter_offset()), - Immediate(FLAG_optimization_counter_threshold)); + __ CompareImmediate( + FieldAddress(function_reg, Function::usage_counter_offset()), + Immediate(FLAG_optimization_counter_threshold), + new_pp); } ASSERT(function_reg == RDI); __ J(GREATER_EQUAL, &StubCode::OptimizeFunctionLabel(), R13); @@ -1181,7 +1164,7 @@ // Check that exactly num_fixed arguments are passed in. Label correct_num_arguments, wrong_num_arguments; __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset())); - __ cmpq(RAX, Immediate(Smi::RawValue(num_fixed_params))); + __ CompareImmediate(RAX, Immediate(Smi::RawValue(num_fixed_params)), PP); __ j(NOT_EQUAL, &wrong_num_arguments, Assembler::kNearJump); __ cmpq(RAX, FieldAddress(R10, @@ -1353,6 +1336,21 @@ } +void FlowGraphCompiler::EmitEdgeCounter() { + // We do not check for overflow when incrementing the edge counter. The + // function should normally be optimized long before the counter can + // overflow; and though we do not reset the counters when we optimize or + // deoptimize, there is a bound on the number of + // optimization/deoptimization cycles we will attempt. + const Array& counter = Array::ZoneHandle(Array::New(1, Heap::kOld)); + counter.SetAt(0, Smi::Handle(Smi::New(0))); + __ Comment("Edge counter"); + __ LoadObject(RAX, counter, PP); + __ AddImmediate(FieldAddress(RAX, Array::element_offset(0)), + Immediate(Smi::RawValue(1)), PP); +} + + void FlowGraphCompiler::EmitOptimizedInstanceCall( ExternalLabel* target_label, const ICData& ic_data, @@ -1410,7 +1408,7 @@ __ movq(RAX, Address(RSP, (argument_count - 1) * kWordSize)); __ testq(RAX, Immediate(kSmiTagMask)); __ j(NOT_ZERO, ¬_smi, Assembler::kNearJump); - __ movq(RAX, Immediate(Smi::RawValue(kSmiCid))); + __ LoadImmediate(RAX, Immediate(Smi::RawValue(kSmiCid)), PP); __ jmp(&load_cache); __ Bind(¬_smi); @@ -1430,7 +1428,7 @@ __ jmp(&loop); __ Bind(&update); - __ addq(RCX, Immediate(Smi::RawValue(1))); + __ AddImmediate(RCX, Immediate(Smi::RawValue(1)), PP); __ Bind(&loop); __ andq(RCX, RBX); const intptr_t base = Array::data_offset(); @@ -1453,7 +1451,8 @@ __ movq(RAX, FieldAddress(RAX, Code::instructions_offset())); __ LoadObject(RBX, ic_data, PP); __ LoadObject(R10, arguments_descriptor, PP); - __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); + __ AddImmediate( + RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag), PP); __ call(RAX); AddCurrentDescriptor(PcDescriptors::kOther, Isolate::kNoDeoptId, token_pos); RecordSafepoint(locs); @@ -1500,7 +1499,7 @@ if (needs_number_check) { __ pushq(reg); - __ PushObject(obj); + __ PushObject(obj, PP); if (is_optimizing()) { __ CallPatchable(&StubCode::OptimizedIdenticalWithNumberCheckLabel()); } else { @@ -1514,7 +1513,7 @@ return; } - __ CompareObject(reg, obj); + __ CompareObject(reg, obj, PP); } @@ -1547,7 +1546,7 @@ // TODO(vegorov): consider saving only caller save (volatile) registers. const intptr_t xmm_regs_count = locs->live_registers()->fpu_regs_count(); if (xmm_regs_count > 0) { - __ subq(RSP, Immediate(xmm_regs_count * kFpuRegisterSize)); + __ AddImmediate(RSP, Immediate(-xmm_regs_count * kFpuRegisterSize), PP); // Store XMM registers with the lowest register number at the lowest // address. intptr_t offset = 0; @@ -1594,7 +1593,7 @@ } } ASSERT(offset == (xmm_regs_count * kFpuRegisterSize)); - __ addq(RSP, Immediate(offset)); + __ AddImmediate(RSP, Immediate(offset), PP); } } @@ -1890,7 +1889,7 @@ void ParallelMoveResolver::StoreObject(const Address& dst, const Object& obj) { - __ StoreObject(dst, obj); + __ StoreObject(dst, obj, PP); } @@ -1926,14 +1925,14 @@ void ParallelMoveResolver::SpillFpuScratch(FpuRegister reg) { - __ subq(RSP, Immediate(kFpuRegisterSize)); + __ AddImmediate(RSP, Immediate(-kFpuRegisterSize), PP); __ movups(Address(RSP, 0), reg); } void ParallelMoveResolver::RestoreFpuScratch(FpuRegister reg) { __ movups(reg, Address(RSP, 0)); - __ addq(RSP, Immediate(kFpuRegisterSize)); + __ AddImmediate(RSP, Immediate(kFpuRegisterSize), PP); }
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc index 7da716a..b9f6bd4 100644 --- a/runtime/vm/flow_graph_optimizer.cc +++ b/runtime/vm/flow_graph_optimizer.cc
@@ -692,8 +692,6 @@ const ICData& ic_data = ICData::Handle(call->ic_data()->AsUnaryClassChecks()); - if (ic_data.NumberOfChecks() == 0) return kIllegalCid; - // TODO(vegorov): Add multiple receiver type support. if (ic_data.NumberOfChecks() != 1) return kIllegalCid; ASSERT(ic_data.HasOneTarget()); @@ -1069,9 +1067,13 @@ case MethodRecognizer::kExternalUint8ClampedArrayGetIndexed: case MethodRecognizer::kInt16ArrayGetIndexed: case MethodRecognizer::kUint16ArrayGetIndexed: + return TryInlineGetIndexed(kind, call, ic_data, entry, last); + case MethodRecognizer::kFloat32x4ArrayGetIndexed: + if (!ShouldInlineSimd()) return false; + return TryInlineGetIndexed(kind, call, ic_data, entry, last); case MethodRecognizer::kInt32ArrayGetIndexed: case MethodRecognizer::kUint32ArrayGetIndexed: - case MethodRecognizer::kFloat32x4ArrayGetIndexed: + if (!CanUnboxInt32()) return false; return TryInlineGetIndexed(kind, call, ic_data, entry, last); default: return false; @@ -1176,44 +1178,22 @@ bool FlowGraphOptimizer::TryReplaceWithLoadIndexed(InstanceCallInstr* call) { - const intptr_t class_id = ReceiverClassId(call); - switch (class_id) { - case kArrayCid: - case kImmutableArrayCid: - case kGrowableObjectArrayCid: - case kTypedDataFloat32ArrayCid: - case kTypedDataFloat64ArrayCid: - case kTypedDataInt8ArrayCid: - case kTypedDataUint8ArrayCid: - case kTypedDataUint8ClampedArrayCid: - case kExternalTypedDataUint8ArrayCid: - case kExternalTypedDataUint8ClampedArrayCid: - case kTypedDataInt16ArrayCid: - case kTypedDataUint16ArrayCid: - break; - case kTypedDataFloat32x4ArrayCid: - if (!ShouldInlineSimd()) { - return false; - } - break; - case kTypedDataInt32ArrayCid: - case kTypedDataUint32ArrayCid: - if (!CanUnboxInt32()) return false; - break; - default: - return false; - } + // Check for monomorphic IC data. + if (!call->HasICData()) return false; + const ICData& ic_data = ICData::Handle(call->ic_data()->AsUnaryClassChecks()); + if (ic_data.NumberOfChecks() != 1) return false; + ASSERT(ic_data.HasOneTarget()); - const Function& target = - Function::Handle(call->ic_data()->GetTargetAt(0)); + const Function& target = Function::Handle(ic_data.GetTargetAt(0)); TargetEntryInstr* entry; Definition* last; - ASSERT(class_id == MethodKindToCid(MethodRecognizer::RecognizeKind(target))); - bool success = TryInlineRecognizedMethod(target, - call, - *call->ic_data(), - &entry, &last); - ASSERT(success); + if (!TryInlineRecognizedMethod(target, + call, + *call->ic_data(), + &entry, &last)) { + return false; + } + // Insert receiver class check. AddReceiverCheck(call); // Remove the original push arguments. @@ -4168,7 +4148,7 @@ switch (instr->tag()) { case Instruction::kLoadField: { LoadFieldInstr* load_field = instr->AsLoadField(); - instance_ = load_field->instance()->definition(); + instance_ = OriginalDefinition(load_field->instance()->definition()); if (load_field->field() != NULL) { kind_ = kField; field_ = load_field->field(); @@ -4184,7 +4164,8 @@ StoreInstanceFieldInstr* store_instance_field = instr->AsStoreInstanceField(); kind_ = kField; - instance_ = store_instance_field->instance()->definition(); + instance_ = + OriginalDefinition(store_instance_field->instance()->definition()); field_ = &store_instance_field->field(); break; } @@ -4192,7 +4173,7 @@ case Instruction::kStoreVMField: { StoreVMFieldInstr* store_vm_field = instr->AsStoreVMField(); kind_ = kVMField; - instance_ = store_vm_field->dest()->definition(); + instance_ = OriginalDefinition(store_vm_field->dest()->definition()); offset_in_bytes_ = store_vm_field->offset_in_bytes(); break; } @@ -4211,7 +4192,7 @@ case Instruction::kLoadIndexed: { LoadIndexedInstr* load_indexed = instr->AsLoadIndexed(); kind_ = kIndexed; - instance_ = load_indexed->array()->definition(); + instance_ = OriginalDefinition(load_indexed->array()->definition()); index_ = load_indexed->index()->definition(); *is_load = true; break; @@ -4220,7 +4201,7 @@ case Instruction::kStoreIndexed: { StoreIndexedInstr* store_indexed = instr->AsStoreIndexed(); kind_ = kIndexed; - instance_ = store_indexed->array()->definition(); + instance_ = OriginalDefinition(store_indexed->array()->definition()); index_ = store_indexed->index()->definition(); break; } @@ -4251,7 +4232,7 @@ void set_instance(Definition* def) { ASSERT((kind_ == kField) || (kind_ == kVMField) || (kind_ == kIndexed)); - instance_ = def; + instance_ = OriginalDefinition(def); } const Field& field() const { @@ -4322,6 +4303,13 @@ static Place* Wrap(const Place& place); private: + static Definition* OriginalDefinition(Definition* defn) { + while (defn->IsRedefinition()) { + defn = defn->AsRedefinition()->value()->definition(); + } + return defn; + } + bool SameField(Place* other) const { return (kind_ == kField) ? (field().raw() == other->field().raw()) : (offset_in_bytes_ == other->offset_in_bytes_); @@ -6048,6 +6036,80 @@ void ConstantPropagator::VisitStaticCall(StaticCallInstr* instr) { SetValue(instr, non_constant_); + return; + // TODO(srdjan): Enable code below once issues resolved. + if (IsNonConstant(instr->constant_value())) { + // Do not bother with costly analysis if we already know that the + // instruction is not a constant. + SetValue(instr, non_constant_); + return; + } + MethodRecognizer::Kind recognized_kind = + MethodRecognizer::RecognizeKind(instr->function()); + if (recognized_kind == MethodRecognizer::kStringBaseInterpolate) { + // static String _interpolate(List values) + // + // Code for calling interpolate is generated by the compiler: + // v2 <- CreateArray(v0) + // StoreIndexed(v2, v3, v4) -- v3:constant index, v4: value. + // .. + // PushArgument(v2) + // v8 <- StaticCall(_interpolate, v2) + // Detect that all values are constant, interpolate at compile + // time. + ASSERT(instr->ArgumentCount() == 1); + CreateArrayInstr* create_array = instr->ArgumentAt(0)->AsCreateArray(); + ASSERT(create_array != NULL); + // Check if the string interpolation has only constant inputs. + for (Value::Iterator it(create_array->input_use_list()); + !it.Done(); + it.Advance()) { + Instruction* curr = it.Current()->instruction(); + StoreIndexedInstr* store = curr->AsStoreIndexed(); + // 'store' is NULL fir PushArgument instruction: skip it. + if ((store != NULL) && + (IsNonConstant(store->value()->definition()->constant_value()))) { + SetValue(instr, non_constant_); + return; + } + } + // Interpolate string at compile time. + const Array& value_arr = + Array::Handle(Array::New(create_array->num_elements())); + // Build the array of literal values to interpolate, abort if a value is + // not literal. + for (Value::Iterator it(create_array->input_use_list()); + !it.Done(); + it.Advance()) { + Instruction* curr = it.Current()->instruction(); + StoreIndexedInstr* store = curr->AsStoreIndexed(); + if (store == NULL) { + ASSERT(curr == instr->PushArgumentAt(0)); + } else { + Value* index_value = store->index(); + ASSERT(index_value->BindsToConstant() && index_value->IsSmiValue()); + const intptr_t ix = Smi::Cast(index_value->BoundConstant()).Value(); + ASSERT(IsConstant(store->value()->definition()->constant_value())); + value_arr.SetAt(ix, store->value()->definition()->constant_value()); + } + } + // Build argument array to pass to the interpolation function. + const Array& interpolate_arg = Array::Handle(Array::New(1)); + interpolate_arg.SetAt(0, value_arr); + // Call interpolation function. + String& concatenated = String::ZoneHandle(); + concatenated ^= + DartEntry::InvokeFunction(instr->function(), interpolate_arg); + if (concatenated.IsUnhandledException()) { + SetValue(instr, non_constant_); + return; + } + + concatenated = Symbols::New(concatenated); + SetValue(instr, concatenated); + } else { + SetValue(instr, non_constant_); + } } @@ -6300,6 +6362,16 @@ void ConstantPropagator::VisitLoadClassId(LoadClassIdInstr* instr) { + intptr_t cid = instr->object()->Type()->ToCid(); + if (cid != kDynamicCid) { + SetValue(instr, Smi::ZoneHandle(Smi::New(cid))); + return; + } + const Object& object = instr->object()->definition()->constant_value(); + if (IsConstant(object)) { + SetValue(instr, Smi::ZoneHandle(Smi::New(object.GetClassId()))); + return; + } SetValue(instr, non_constant_); } @@ -6870,6 +6942,27 @@ } +// Code for calling interpolate is generated by the compiler: +// v2 <- CreateArray(v0) +// StoreIndexed(v2, v3, v4) -- v3:constant index, v4: value. +// .. +// PushArgument(v2) +// v8 <- StaticCall(_interpolate, v2) +// Remove the inputs. +void ConstantPropagator::RemoveInterpolationInputs( + const StaticCallInstr& call) { + ASSERT(call.ArgumentCount() == 1); + CreateArrayInstr* create_array = call.ArgumentAt(0)->AsCreateArray(); + ASSERT(create_array != NULL); + for (Value* use = create_array->input_use_list(); + use != NULL; + use = create_array->input_use_list()) { + use->instruction()->RemoveFromGraph(); + } + create_array->RemoveFromGraph(); +} + + void ConstantPropagator::Transform() { if (FLAG_trace_constant_propagation) { OS::Print("\n==== Before constant propagation ====\n"); @@ -6977,6 +7070,13 @@ ConstantInstr* constant = graph_->GetConstant(defn->constant_value()); defn->ReplaceUsesWith(constant); i.RemoveCurrentFromGraph(); + if (defn->IsStaticCall()) { + MethodRecognizer::Kind recognized_kind = + MethodRecognizer::RecognizeKind(defn->AsStaticCall()->function()); + if (recognized_kind == MethodRecognizer::kStringBaseInterpolate) { + RemoveInterpolationInputs(*defn->AsStaticCall()); + } + } } }
diff --git a/runtime/vm/flow_graph_optimizer.h b/runtime/vm/flow_graph_optimizer.h index 8c9f6fe..1879186 100644 --- a/runtime/vm/flow_graph_optimizer.h +++ b/runtime/vm/flow_graph_optimizer.h
@@ -282,6 +282,8 @@ const Value& left, const Value& right); + void RemoveInterpolationInputs(const StaticCallInstr& call); + virtual void VisitBlocks() { UNREACHABLE(); } #define DECLARE_VISIT(type) virtual void Visit##type(type##Instr* instr);
diff --git a/runtime/vm/il_printer.cc b/runtime/vm/il_printer.cc index 5c442da..80817b5 100644 --- a/runtime/vm/il_printer.cc +++ b/runtime/vm/il_printer.cc
@@ -650,7 +650,8 @@ void Float32x4ComparisonInstr::PrintOperandsTo(BufferFormatter* f) const { - f->Print("Float32x4 Comparison %d", op_kind()); + f->Print("Float32x4 Comparison %s, ", + MethodRecognizer::KindToCString(op_kind())); left()->PrintTo(f); f->Print(", "); right()->PrintTo(f);
diff --git a/runtime/vm/instructions_arm.cc b/runtime/vm/instructions_arm.cc index 4ae5936..9cc0d58 100644 --- a/runtime/vm/instructions_arm.cc +++ b/runtime/vm/instructions_arm.cc
@@ -13,88 +13,99 @@ namespace dart { CallPattern::CallPattern(uword pc, const Code& code) - : end_(reinterpret_cast<uword*>(pc)), + : object_pool_(Array::Handle(code.ObjectPool())), + end_(pc), + args_desc_load_end_(0), + ic_data_load_end_(0), target_address_pool_index_(-1), - args_desc_load_end_(-1), args_desc_(Array::Handle()), - ic_data_load_end_(-1), - ic_data_(ICData::Handle()), - object_pool_(Array::Handle(code.ObjectPool())) { + ic_data_(ICData::Handle()) { ASSERT(code.ContainsInstructionAt(pc)); - ASSERT(Back(1) == 0xe12fff3e); // Last instruction: blx lr + // Last instruction: blx lr. + ASSERT(*(reinterpret_cast<uword*>(end_) - 1) == 0xe12fff3e); + Register reg; ic_data_load_end_ = - DecodeLoadWordFromPool(1, ®, &target_address_pool_index_); + InstructionPattern::DecodeLoadWordFromPool(end_ - Instr::kInstrSize, + ®, + &target_address_pool_index_); ASSERT(reg == LR); } -uword CallPattern::Back(int n) const { - ASSERT(n > 0); - return *(end_ - n); -} - - -// Decodes a load sequence ending at end. Returns the register being loaded and -// the loaded object. -// Returns the location of the load sequence, counting the number of -// instructions back from the end of the call pattern. -int CallPattern::DecodeLoadObject(int end, Register* reg, Object* obj) { - ASSERT(end > 0); - uword instr = Back(end + 1); - if ((instr & 0xfff00000) == 0xe5900000) { // ldr reg, [reg, #+offset] - int index = 0; - end = DecodeLoadWordFromPool(end, reg, &index); - *obj = object_pool_.At(index); +// Decodes a load sequence ending at 'end' (the last instruction of the load +// sequence is the instruction before the one at end). Returns a pointer to +// the first instruction in the sequence. Returns the register being loaded +// and the loaded object in the output parameters 'reg' and 'obj' +// respectively. +uword InstructionPattern::DecodeLoadObject(uword end, + const Array& object_pool, + Register* reg, + Object* obj) { + uword start = 0; + Instr* instr = Instr::At(end - Instr::kInstrSize); + if ((instr->InstructionBits() & 0xfff00000) == 0xe5900000) { + // ldr reg, [reg, #+offset] + intptr_t index = 0; + start = DecodeLoadWordFromPool(end, reg, &index); + *obj = object_pool.At(index); } else { - int value = 0; - end = DecodeLoadWordImmediate(end, reg, &value); + intptr_t value = 0; + start = DecodeLoadWordImmediate(end, reg, &value); *obj = reinterpret_cast<RawObject*>(value); } - return end; + return start; } -// Decodes a load sequence ending at end. Returns the register being loaded and -// the loaded immediate value. -// Returns the location of the load sequence, counting the number of -// instructions back from the end of the call pattern. -int CallPattern::DecodeLoadWordImmediate(int end, Register* reg, int* value) { - ASSERT(end > 0); - uword instr = Back(++end); - int imm = 0; +// Decodes a load sequence ending at 'end' (the last instruction of the load +// sequence is the instruction before the one at end). Returns a pointer to +// the first instruction in the sequence. Returns the register being loaded +// and the loaded immediate value in the output parameters 'reg' and 'value' +// respectively. +uword InstructionPattern::DecodeLoadWordImmediate(uword end, + Register* reg, + intptr_t* value) { + uword start = end - Instr::kInstrSize; + int32_t instr = Instr::At(start)->InstructionBits(); + intptr_t imm = 0; if ((instr & 0xfff00000) == 0xe3400000) { // movt reg, #imm_hi imm |= (instr & 0xf0000) << 12; imm |= (instr & 0xfff) << 16; - instr = Back(++end); + start -= Instr::kInstrSize; + instr = Instr::At(start)->InstructionBits(); } ASSERT((instr & 0xfff00000) == 0xe3000000); // movw reg, #imm_lo imm |= (instr & 0xf0000) >> 4; imm |= instr & 0xfff; *reg = static_cast<Register>((instr & 0xf000) >> 12); *value = imm; - return end; + return start; } -// Decodes a load sequence ending at end. Returns the register being loaded and -// the index in the pool being read from. -// Returns the location of the load sequence, counting the number of -// instructions back from the end of the call pattern. -int CallPattern::DecodeLoadWordFromPool(int end, Register* reg, int* index) { - ASSERT(end > 0); - uword instr = Back(++end); - int offset = 0; +// Decodes a load sequence ending at 'end' (the last instruction of the load +// sequence is the instruction before the one at end). Returns a pointer to +// the first instruction in the sequence. Returns the register being loaded +// and the index in the pool being read from in the output parameters 'reg' +// and 'index' respectively. +uword InstructionPattern::DecodeLoadWordFromPool(uword end, + Register* reg, + intptr_t* index) { + uword start = end - Instr::kInstrSize; + int32_t instr = Instr::At(start)->InstructionBits(); + intptr_t offset = 0; if ((instr & 0xffff0000) == 0xe59a0000) { // ldr reg, [pp, #+offset] offset = instr & 0xfff; *reg = static_cast<Register>((instr & 0xf000) >> 12); } else { ASSERT((instr & 0xfff00000) == 0xe5900000); // ldr reg, [reg, #+offset] offset = instr & 0xfff; - instr = Back(++end); + start -= Instr::kInstrSize; + instr = Instr::At(start)->InstructionBits(); if ((instr & 0xffff0000) == 0xe28a0000) { // add reg, pp, shifter_op - const int rot = (instr & 0xf00) >> 7; - const int imm8 = instr & 0xff; + const intptr_t rot = (instr & 0xf00) >> 7; + const intptr_t imm8 = instr & 0xff; offset += (imm8 >> rot) | (imm8 << (32 - rot)); *reg = static_cast<Register>((instr & 0xf000) >> 12); } else { @@ -104,15 +115,19 @@ } offset += kHeapObjectTag; ASSERT(Utils::IsAligned(offset, 4)); - *index = (offset - Array::data_offset())/4; - return end; + *index = (offset - Array::data_offset()) / 4; + return start; } RawICData* CallPattern::IcData() { if (ic_data_.IsNull()) { Register reg; - args_desc_load_end_ = DecodeLoadObject(ic_data_load_end_, ®, &ic_data_); + args_desc_load_end_ = + InstructionPattern::DecodeLoadObject(ic_data_load_end_, + object_pool_, + ®, + &ic_data_); ASSERT(reg == R5); } return ic_data_.raw(); @@ -123,7 +138,10 @@ if (args_desc_.IsNull()) { IcData(); // Loading of the ic_data must be decoded first, if not already. Register reg; - DecodeLoadObject(args_desc_load_end_, ®, &args_desc_); + InstructionPattern::DecodeLoadObject(args_desc_load_end_, + object_pool_, + ®, + &args_desc_); ASSERT(reg == R4); } return args_desc_.raw(); @@ -198,4 +216,3 @@ } // namespace dart #endif // defined TARGET_ARCH_ARM -
diff --git a/runtime/vm/instructions_arm.h b/runtime/vm/instructions_arm.h index 59cb259..05235d1 100644 --- a/runtime/vm/instructions_arm.h +++ b/runtime/vm/instructions_arm.h
@@ -15,6 +15,38 @@ namespace dart { +class InstructionPattern : public AllStatic { + public: + // Decodes a load sequence ending at 'end' (the last instruction of the + // load sequence is the instruction before the one at end). Returns the + // address of the first instruction in the sequence. Returns the register + // being loaded and the loaded object in the output parameters 'reg' and + // 'obj' respectively. + static uword DecodeLoadObject(uword end, + const Array& object_pool, + Register* reg, + Object* obj); + + // Decodes a load sequence ending at 'end' (the last instruction of the + // load sequence is the instruction before the one at end). Returns the + // address of the first instruction in the sequence. Returns the register + // being loaded and the loaded immediate value in the output parameters + // 'reg' and 'value' respectively. + static uword DecodeLoadWordImmediate(uword end, + Register* reg, + intptr_t* value); + + // Decodes a load sequence ending at 'end' (the last instruction of the + // load sequence is the instruction before the one at end). Returns the + // address of the first instruction in the sequence. Returns the register + // being loaded and the index in the pool being read from in the output + // parameters 'reg' and 'index' respectively. + static uword DecodeLoadWordFromPool(uword end, + Register* reg, + intptr_t* index); +}; + + class CallPattern : public ValueObject { public: CallPattern(uword pc, const Code& code); @@ -32,18 +64,16 @@ static void InsertAt(uword pc, uword target_address); private: - uword Back(int n) const; - int DecodeLoadObject(int end, Register* reg, Object* obj); - int DecodeLoadWordImmediate(int end, Register* reg, int* value); - int DecodeLoadWordFromPool(int end, Register* reg, int* index); - const uword* end_; - int target_address_pool_index_; - int args_desc_load_end_; - Array& args_desc_; - int ic_data_load_end_; - ICData& ic_data_; const Array& object_pool_; + uword end_; + uword args_desc_load_end_; + uword ic_data_load_end_; + + intptr_t target_address_pool_index_; + Array& args_desc_; + ICData& ic_data_; + DISALLOW_COPY_AND_ASSIGN(CallPattern); }; @@ -71,4 +101,3 @@ } // namespace dart #endif // VM_INSTRUCTIONS_ARM_H_ -
diff --git a/runtime/vm/instructions_mips.cc b/runtime/vm/instructions_mips.cc index 7215ec0..ae6fbf2 100644 --- a/runtime/vm/instructions_mips.cc +++ b/runtime/vm/instructions_mips.cc
@@ -13,82 +13,88 @@ namespace dart { CallPattern::CallPattern(uword pc, const Code& code) - : end_(reinterpret_cast<uword*>(pc)), + : object_pool_(Array::Handle(code.ObjectPool())), + end_(pc), + args_desc_load_end_(0), + ic_data_load_end_(0), target_address_pool_index_(-1), - args_desc_load_end_(-1), args_desc_(Array::Handle()), - ic_data_load_end_(-1), - ic_data_(ICData::Handle()), - object_pool_(Array::Handle(code.ObjectPool())) { + ic_data_(ICData::Handle()) { ASSERT(code.ContainsInstructionAt(pc)); - ASSERT(Back(2) == 0x0020f809); // Last instruction: jalr RA, TMP(=R1) + // Last instruction: jalr RA, TMP(=R1). + ASSERT(*(reinterpret_cast<uword*>(end_) - 2) == 0x0020f809); Register reg; - // First end is 0 so that we begin from the delay slot of the jalr. + // The end of the pattern is the instruction after the delay slot of the jalr. ic_data_load_end_ = - DecodeLoadWordFromPool(2, ®, &target_address_pool_index_); + InstructionPattern::DecodeLoadWordFromPool(end_ - (2 * Instr::kInstrSize), + ®, + &target_address_pool_index_); ASSERT(reg == TMP); } -uword CallPattern::Back(int n) const { - ASSERT(n > 0); - return *(end_ - n); -} - - -// Decodes a load sequence ending at end. Returns the register being loaded and -// the loaded object. -// Returns the location of the load sequence, counting the number of -// instructions back from the end of the call pattern. -int CallPattern::DecodeLoadObject(int end, Register* reg, Object* obj) { - ASSERT(end > 0); - uword i = Back(end + 1); - Instr* instr = Instr::At(reinterpret_cast<uword>(&i)); +// Decodes a load sequence ending at 'end' (the last instruction of the load +// sequence is the instruction before the one at end). Returns a pointer to +// the first instruction in the sequence. Returns the register being loaded +// and the loaded object in the output parameters 'reg' and 'obj' +// respectively. +uword InstructionPattern::DecodeLoadObject(uword end, + const Array& object_pool, + Register* reg, + Object* obj) { + uword start = 0; + Instr* instr = Instr::At(end - Instr::kInstrSize); if (instr->OpcodeField() == LW) { - int index = 0; - end = DecodeLoadWordFromPool(end, reg, &index); - *obj = object_pool_.At(index); + intptr_t index = 0; + start = DecodeLoadWordFromPool(end, reg, &index); + *obj = object_pool.At(index); } else { - int value = 0; - end = DecodeLoadWordImmediate(end, reg, &value); + intptr_t value = 0; + start = DecodeLoadWordImmediate(end, reg, &value); *obj = reinterpret_cast<RawObject*>(value); } - return end; + return start; } -// Decodes a load sequence ending at end. Returns the register being loaded and -// the loaded immediate value. -// Returns the location of the load sequence, counting the number of -// instructions back from the end of the call pattern. -int CallPattern::DecodeLoadWordImmediate(int end, Register* reg, int* value) { - ASSERT(end > 0); - int imm = 0; - uword i = Back(++end); - Instr* instr = Instr::At(reinterpret_cast<uword>(&i)); +// Decodes a load sequence ending at 'end' (the last instruction of the load +// sequence is the instruction before the one at end). Returns a pointer to +// the first instruction in the sequence. Returns the register being loaded +// and the loaded immediate value in the output parameters 'reg' and 'value' +// respectively. +uword InstructionPattern::DecodeLoadWordImmediate(uword end, + Register* reg, + intptr_t* value) { + // The pattern is a fixed size, but match backwards for uniformity with + // DecodeLoadWordFromPool. + uword start = end - Instr::kInstrSize; + Instr* instr = Instr::At(start); + intptr_t imm = 0; ASSERT(instr->OpcodeField() == ORI); imm = instr->UImmField(); *reg = instr->RtField(); - i = Back(++end); - instr = Instr::At(reinterpret_cast<uword>(&i)); + start -= Instr::kInstrSize; + instr = Instr::At(start); ASSERT(instr->OpcodeField() == LUI); ASSERT(instr->RtField() == *reg); imm |= (instr->UImmField() << 16); *value = imm; - return end; + return start; } -// Decodes a load sequence ending at end. Returns the register being loaded and -// the index in the pool being read from. -// Returns the location of the load sequence, counting the number of -// instructions back from the end of the call pattern. -int CallPattern::DecodeLoadWordFromPool(int end, Register* reg, int* index) { - ASSERT(end > 0); - uword i = Back(++end); - Instr* instr = Instr::At(reinterpret_cast<uword>(&i)); - int offset = 0; +// Decodes a load sequence ending at 'end' (the last instruction of the load +// sequence is the instruction before the one at end). Returns a pointer to +// the first instruction in the sequence. Returns the register being loaded +// and the index in the pool being read from in the output parameters 'reg' +// and 'index' respectively. +uword InstructionPattern::DecodeLoadWordFromPool(uword end, + Register* reg, + intptr_t* index) { + uword start = end - Instr::kInstrSize; + Instr* instr = Instr::At(start); + intptr_t offset = 0; if ((instr->OpcodeField() == LW) && (instr->RsField() == PP)) { offset = instr->SImmField(); *reg = instr->RtField(); @@ -97,16 +103,16 @@ offset = instr->SImmField(); *reg = instr->RtField(); - i = Back(++end); - instr = Instr::At(reinterpret_cast<uword>(&i)); + start -= Instr::kInstrSize; + instr = Instr::At(start); ASSERT(instr->OpcodeField() == SPECIAL); ASSERT(instr->FunctionField() == ADDU); ASSERT(instr->RdField() == *reg); ASSERT(instr->RsField() == *reg); ASSERT(instr->RtField() == PP); - i = Back(++end); - instr = Instr::At(reinterpret_cast<uword>(&i)); + start -= Instr::kInstrSize; + instr = Instr::At(start); ASSERT(instr->OpcodeField() == LUI); ASSERT(instr->RtField() == *reg); // Offset is signed, so add the upper 16 bits. @@ -114,15 +120,19 @@ } offset += kHeapObjectTag; ASSERT(Utils::IsAligned(offset, 4)); - *index = (offset - Array::data_offset())/4; - return end; + *index = (offset - Array::data_offset()) / 4; + return start; } RawICData* CallPattern::IcData() { if (ic_data_.IsNull()) { Register reg; - args_desc_load_end_ = DecodeLoadObject(ic_data_load_end_, ®, &ic_data_); + args_desc_load_end_ = + InstructionPattern::DecodeLoadObject(ic_data_load_end_, + object_pool_, + ®, + &ic_data_); ASSERT(reg == S5); } return ic_data_.raw(); @@ -133,7 +143,10 @@ if (args_desc_.IsNull()) { IcData(); // Loading of the ic_data must be decoded first, if not already. Register reg; - DecodeLoadObject(args_desc_load_end_, ®, &args_desc_); + InstructionPattern::DecodeLoadObject(args_desc_load_end_, + object_pool_, + ®, + &args_desc_); ASSERT(reg == S4); } return args_desc_.raw(); @@ -217,4 +230,3 @@ } // namespace dart #endif // defined TARGET_ARCH_MIPS -
diff --git a/runtime/vm/instructions_mips.h b/runtime/vm/instructions_mips.h index 7cecc70..b4864b7 100644 --- a/runtime/vm/instructions_mips.h +++ b/runtime/vm/instructions_mips.h
@@ -15,6 +15,38 @@ namespace dart { +class InstructionPattern : public AllStatic { + public: + // Decodes a load sequence ending at 'end' (the last instruction of the + // load sequence is the instruction before the one at end). Returns the + // address of the first instruction in the sequence. Returns the register + // being loaded and the loaded object in the output parameters 'reg' and + // 'obj' respectively. + static uword DecodeLoadObject(uword end, + const Array& object_pool, + Register* reg, + Object* obj); + + // Decodes a load sequence ending at 'end' (the last instruction of the + // load sequence is the instruction before the one at end). Returns the + // address of the first instruction in the sequence. Returns the register + // being loaded and the loaded immediate value in the output parameters + // 'reg' and 'value' respectively. + static uword DecodeLoadWordImmediate(uword end, + Register* reg, + intptr_t* value); + + // Decodes a load sequence ending at 'end' (the last instruction of the + // load sequence is the instruction before the one at end). Returns the + // address of the first instruction in the sequence. Returns the register + // being loaded and the index in the pool being read from in the output + // parameters 'reg' and 'index' respectively. + static uword DecodeLoadWordFromPool(uword end, + Register* reg, + intptr_t* index); +}; + + class CallPattern : public ValueObject { public: CallPattern(uword pc, const Code& code); @@ -32,18 +64,16 @@ static void InsertAt(uword pc, uword target_address); private: - uword Back(int n) const; - int DecodeLoadObject(int end, Register* reg, Object* obj); - int DecodeLoadWordImmediate(int end, Register* reg, int* value); - int DecodeLoadWordFromPool(int end, Register* reg, int* index); - const uword* end_; - int target_address_pool_index_; - int args_desc_load_end_; - Array& args_desc_; - int ic_data_load_end_; - ICData& ic_data_; const Array& object_pool_; + uword end_; + uword args_desc_load_end_; + uword ic_data_load_end_; + + intptr_t target_address_pool_index_; + Array& args_desc_; + ICData& ic_data_; + DISALLOW_COPY_AND_ASSIGN(CallPattern); }; @@ -72,4 +102,3 @@ } // namespace dart #endif // VM_INSTRUCTIONS_MIPS_H_ -
diff --git a/runtime/vm/instructions_x64.cc b/runtime/vm/instructions_x64.cc index 0f788073..7b0b4ae 100644 --- a/runtime/vm/instructions_x64.cc +++ b/runtime/vm/instructions_x64.cc
@@ -13,7 +13,7 @@ intptr_t InstructionPattern::IndexFromPPLoad(uword start) { int32_t offset = *reinterpret_cast<int32_t*>(start); - offset += kHeapObjectTag; + offset += kHeapObjectTag; return (offset - Array::data_offset()) / kWordSize; }
diff --git a/runtime/vm/intermediate_language.cc b/runtime/vm/intermediate_language.cc index 147ea56..50c4930 100644 --- a/runtime/vm/intermediate_language.cc +++ b/runtime/vm/intermediate_language.cc
@@ -362,12 +362,12 @@ MethodRecognizer::Kind MethodRecognizer::RecognizeKind( const Function& function) { - const Class& function_class = Class::Handle(function.Owner()); - const Library& lib = Library::Handle(function_class.library()); - if (!IsRecognizedLibrary(lib)) { + if (!function.is_recognized()) { return kUnknown; } + const Class& function_class = Class::Handle(function.Owner()); + const Library& lib = Library::Handle(function_class.library()); const String& function_name = String::Handle(function.name()); const String& class_name = String::Handle(function_class.Name()); @@ -379,6 +379,7 @@ } RECOGNIZED_LIST(RECOGNIZE_FUNCTION) #undef RECOGNIZE_FUNCTION + UNREACHABLE(); return kUnknown; } @@ -414,7 +415,25 @@ } +void MethodRecognizer::InitializeState() { + GrowableArray<Library*> libs(3); + libs.Add(&Library::ZoneHandle(Library::CoreLibrary())); + libs.Add(&Library::ZoneHandle(Library::MathLibrary())); + libs.Add(&Library::ZoneHandle(Library::TypedDataLibrary())); + Function& func = Function::Handle(); + +#define SET_IS_RECOGNIZED(class_name, function_name, dest, fp) \ + func = Library::GetFunction(libs, #class_name, #function_name); \ + ASSERT(!func.IsNull()); \ + func.set_is_recognized(true); \ + + RECOGNIZED_LIST(SET_IS_RECOGNIZED); + +#undef SET_IS_RECOGNIZED +} + // ==== Support for visiting flow graphs. + #define DEFINE_ACCEPT(ShortName) \ void ShortName##Instr::Accept(FlowGraphVisitor* visitor) { \ visitor->Visit##ShortName(this); \ @@ -1645,6 +1664,12 @@ LocationSummary* TargetEntryInstr::MakeLocationSummary() const { + // FlowGraphCompiler::EmitInstructionPrologue is not called for block + // entry instructions, so this function is unused. If it becomes + // reachable, note that the deoptimization descriptor in unoptimized code + // comes after the point of local register allocation due to pattern + // matching the edge counter code backwards (as a code reuse convenience + // on some platforms). UNREACHABLE(); return NULL; }
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h index 766fcaa..35ca39c 100644 --- a/runtime/vm/intermediate_language.h +++ b/runtime/vm/intermediate_language.h
@@ -41,8 +41,8 @@ V(::, identical, ObjectIdentical, 496869842) \ V(Object, Object., ObjectConstructor, 1058585294) \ V(Object, get:_cid, ObjectCid, 1498721510) \ - V(_ObjectArray, get:length, ObjectArrayLength, 259382695) \ - V(_ImmutableArray, get:length, ImmutableArrayLength, 1342001998) \ + V(_List, get:length, ObjectArrayLength, 215153395) \ + V(_ImmutableList, get:length, ImmutableArrayLength, 578733070) \ V(_TypedList, get:length, TypedDataLength, 26616328) \ V(_TypedList, _getInt8, ByteArrayBaseGetInt8, 272598802) \ V(_TypedList, _getUint8, ByteArrayBaseGetUint8, 831354841) \ @@ -62,14 +62,15 @@ V(_TypedList, _setFloat32, ByteArrayBaseSetFloat32, 1457395244) \ V(_TypedList, _setFloat64, ByteArrayBaseSetFloat64, 49127618) \ V(_TypedList, _setFloat32x4, ByteArrayBaseSetFloat32x4, 1261559935) \ - V(_GrowableObjectArray, get:length, GrowableArrayLength, 1160417196) \ - V(_GrowableObjectArray, get:_capacity, GrowableArrayCapacity, 1509841570) \ - V(_GrowableObjectArray, _setData, GrowableArraySetData, 1574432374) \ - V(_GrowableObjectArray, _setLength, GrowableArraySetLength, 1112774552) \ + V(_GrowableList, get:length, GrowableArrayLength, 1654225242) \ + V(_GrowableList, get:_capacity, GrowableArrayCapacity, 817090003) \ + V(_GrowableList, _setData, GrowableArraySetData, 1375509957) \ + V(_GrowableList, _setLength, GrowableArraySetLength, 1227678442) \ V(_StringBase, get:length, StringBaseLength, 1483520063) \ V(_StringBase, get:isEmpty, StringBaseIsEmpty, 879849436) \ V(_StringBase, codeUnitAt, StringBaseCodeUnitAt, 1958436584) \ V(_StringBase, [], StringBaseCharAt, 990046076) \ + V(_StringBase, _interpolate, StringBaseInterpolate, 908021574) \ V(_OneByteString, _setAt, OneByteStringSetAt, 308408714) \ V(_IntegerImplementation, toDouble, IntegerToDouble, 2011998508) \ V(_IntegerImplementation, _leftShiftWithMask32, IntegerLeftShiftWithMask32, \ @@ -134,9 +135,9 @@ V(_Uint32x4, withFlagY, Uint32x4WithFlagY, 830610988) \ V(_Uint32x4, withFlagZ, Uint32x4WithFlagZ, 1714792414) \ V(_Uint32x4, withFlagW, Uint32x4WithFlagW, 1516924162) \ - V(_ObjectArray, [], ObjectArrayGetIndexed, 544020319) \ - V(_ImmutableArray, [], ImmutableArrayGetIndexed, 1345387065) \ - V(_GrowableObjectArray, [], GrowableArrayGetIndexed, 951312767) \ + V(_List, [], ObjectArrayGetIndexed, 1079829188) \ + V(_ImmutableList, [], ImmutableArrayGetIndexed, 25983597) \ + V(_GrowableList, [], GrowableArrayGetIndexed, 1686777561) \ V(_Float32Array, [], Float32ArrayGetIndexed, 1225286513) \ V(_Float64Array, [], Float64ArrayGetIndexed, 871118335) \ V(_Int8Array, [], Int8ArrayGetIndexed, 199925538) \ @@ -154,14 +155,14 @@ // A list of core function that should always be inlined. #define INLINE_WHITE_LIST(V) \ - V(_ObjectArray, get:length, ObjectArrayLength, 259382695) \ - V(_ImmutableArray, get:length, ImmutableArrayLength, 1342001998) \ + V(_List, get:length, ObjectArrayLength, 215153395) \ + V(_ImmutableList, get:length, ImmutableArrayLength, 578733070) \ V(_TypedList, get:length, TypedDataLength, 26616328) \ - V(_GrowableObjectArray, get:length, GrowableArrayLength, 1160417196) \ + V(_GrowableList, get:length, GrowableArrayLength, 1654225242) \ V(_StringBase, get:length, StringBaseLength, 1483520063) \ V(ListIterator, moveNext, ListIteratorMoveNext, 90930587) \ - V(_GrowableObjectArray, get:iterator, GrowableArrayIterator, 2129691657) \ - V(_GrowableObjectArray, forEach, GrowableArrayForEach, 1669274418) + V(_GrowableList, get:iterator, GrowableArrayIterator, 1305127405) \ + V(_GrowableList, forEach, GrowableArrayForEach, 1675430533) // Class that recognizes the name and owner of a function and returns the @@ -179,6 +180,7 @@ static Kind RecognizeKind(const Function& function); static bool AlwaysInline(const Function& function); static const char* KindToCString(Kind kind); + static void InitializeState(); };
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc index 00df26b..35b43d9 100644 --- a/runtime/vm/intermediate_language_arm.cc +++ b/runtime/vm/intermediate_language_arm.cc
@@ -361,14 +361,6 @@ const Array& kNoArgumentNames = Object::null_array(); const int kNumArgumentsChecked = 2; - Label check_identity; - __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null())); - __ ldm(IA, SP, (1 << R0) | (1 << R1)); - __ cmp(R1, ShifterOperand(IP)); - __ b(&check_identity, EQ); - __ cmp(R0, ShifterOperand(IP)); - __ b(&check_identity, EQ); - ICData& equality_ic_data = ICData::ZoneHandle(); if (compiler->is_optimizing() && FLAG_propagate_ic_data) { ASSERT(!original_ic_data.IsNull()); @@ -395,42 +387,12 @@ kNoArgumentNames, locs, equality_ic_data); - Label check_ne; - __ b(&check_ne); - - __ Bind(&check_identity); - Label equality_done; - if (compiler->is_optimizing()) { - // No need to update IC data. - __ PopList((1 << R0) | (1 << R1)); - __ cmp(R0, ShifterOperand(R1)); - __ LoadObject(R0, Bool::Get(kind != Token::kEQ), NE); - __ LoadObject(R0, Bool::Get(kind == Token::kEQ), EQ); - if (kind == Token::kNE) { - // Skip not-equal result conversion. - __ b(&equality_done); - } - } else { - // Call stub, load IC data in register. The stub will update ICData if - // necessary. - Register ic_data_reg = locs->temp(0).reg(); - ASSERT(ic_data_reg == R5); // Stub depends on it. - __ LoadObject(ic_data_reg, equality_ic_data); - // Pass left in R1 and right in R0. - compiler->GenerateCall(token_pos, - &StubCode::EqualityWithNullArgLabel(), - PcDescriptors::kRuntimeCall, - locs); - __ Drop(2); - } - __ Bind(&check_ne); if (kind == Token::kNE) { // Negate the condition: true label returns false and vice versa. __ CompareObject(R0, Bool::True()); __ LoadObject(R0, Bool::True(), NE); __ LoadObject(R0, Bool::False(), EQ); } - __ Bind(&equality_done); } @@ -612,35 +574,11 @@ ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); Register left = locs->in(0).reg(); Register right = locs->in(1).reg(); - Label done, identity_compare, non_null_compare; - __ LoadImmediate(IP, reinterpret_cast<intptr_t>(Object::null())); - __ cmp(right, ShifterOperand(IP)); - __ b(&identity_compare, EQ); - __ cmp(left, ShifterOperand(IP)); - __ b(&non_null_compare, NE); - // Comparison with NULL is "===". - __ Bind(&identity_compare); - __ cmp(left, ShifterOperand(right)); - Condition cond = TokenKindToSmiCondition(kind); - if (branch != NULL) { - branch->EmitBranchOnCondition(compiler, cond); - } else { - Register result = locs->out().reg(); - Label load_true; - __ b(&load_true, cond); - __ LoadObject(result, Bool::False()); - __ b(&done); - __ Bind(&load_true); - __ LoadObject(result, Bool::True()); - } - __ b(&done); - __ Bind(&non_null_compare); // Receiver is not null. ASSERT(left == R1); ASSERT(right == R0); __ PushList((1 << R0) | (1 << R1)); EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, deopt_id, token_pos); - __ Bind(&done); } @@ -4444,18 +4382,14 @@ void TargetEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { __ Bind(compiler->GetJumpLabel(this)); if (!compiler->is_optimizing()) { + compiler->EmitEdgeCounter(); + // Add an edge counter. + // On ARM the deoptimization descriptor points after the edge counter + // code so that we can reuse the same pattern matching code as at call + // sites, which matches backwards from the end of the pattern. compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, deopt_id_, Scanner::kDummyTokenIndex); - // Add an edge counter. - const Array& counter = Array::ZoneHandle(Array::New(1, Heap::kOld)); - counter.SetAt(0, Smi::Handle(Smi::New(0))); - __ Comment("Edge counter"); - __ LoadObject(R0, counter); - __ ldr(IP, FieldAddress(R0, Array::element_offset(0))); - __ adds(IP, IP, ShifterOperand(Smi::RawValue(1))); - __ LoadImmediate(IP, Smi::RawValue(Smi::kMaxValue), VS); // If overflow. - __ str(IP, FieldAddress(R0, Array::element_offset(0))); } if (HasParallelMove()) { compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); @@ -4469,6 +4403,17 @@ void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { + if (!compiler->is_optimizing()) { + compiler->EmitEdgeCounter(); + // Add a deoptimization descriptor for deoptimizing instructions that + // may be inserted before this instruction. On ARM this descriptor + // points after the edge counter code so that we can reuse the same + // pattern matching code as at call sites, which matches backwards from + // the end of the pattern. + compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, + GetDeoptId(), + Scanner::kDummyTokenIndex); + } if (HasParallelMove()) { compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); }
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc index 279051c..bbbbe97 100644 --- a/runtime/vm/intermediate_language_ia32.cc +++ b/runtime/vm/intermediate_language_ia32.cc
@@ -310,14 +310,6 @@ const Array& kNoArgumentNames = Object::null_array(); const int kNumArgumentsChecked = 2; - const Immediate& raw_null = - Immediate(reinterpret_cast<intptr_t>(Object::null())); - Label check_identity; - __ cmpl(Address(ESP, 0 * kWordSize), raw_null); - __ j(EQUAL, &check_identity); - __ cmpl(Address(ESP, 1 * kWordSize), raw_null); - __ j(EQUAL, &check_identity); - ICData& equality_ic_data = ICData::ZoneHandle(); if (compiler->is_optimizing() && FLAG_propagate_ic_data) { ASSERT(!original_ic_data.IsNull()); @@ -344,39 +336,6 @@ kNoArgumentNames, locs, equality_ic_data); - Label check_ne; - __ jmp(&check_ne); - - __ Bind(&check_identity); - Label equality_done; - if (compiler->is_optimizing()) { - // No need to update IC data. - Label is_true; - __ popl(EAX); - __ popl(EDX); - __ cmpl(EAX, EDX); - __ j(EQUAL, &is_true); - __ LoadObject(EAX, Bool::Get(kind != Token::kEQ)); - __ jmp(&equality_done); - __ Bind(&is_true); - __ LoadObject(EAX, Bool::Get(kind == Token::kEQ)); - if (kind == Token::kNE) { - // Skip not-equal result conversion. - __ jmp(&equality_done); - } - } else { - // Call stub, load IC data in register. The stub will update ICData if - // necessary. - Register ic_data_reg = locs->temp(0).reg(); - ASSERT(ic_data_reg == ECX); // Stub depends on it. - __ LoadObject(ic_data_reg, equality_ic_data); - compiler->GenerateCall(token_pos, - &StubCode::EqualityWithNullArgLabel(), - PcDescriptors::kRuntimeCall, - locs); - __ Drop(2); - } - __ Bind(&check_ne); if (kind == Token::kNE) { Label true_label, done; // Negate the condition: true label returns false and vice versa. @@ -388,7 +347,6 @@ __ LoadObject(EAX, Bool::False()); __ Bind(&done); } - __ Bind(&equality_done); } @@ -562,35 +520,10 @@ ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); Register left = locs->in(0).reg(); Register right = locs->in(1).reg(); - const Immediate& raw_null = - Immediate(reinterpret_cast<intptr_t>(Object::null())); - Label done, identity_compare, non_null_compare; - __ cmpl(right, raw_null); - __ j(EQUAL, &identity_compare, Assembler::kNearJump); - __ cmpl(left, raw_null); - __ j(NOT_EQUAL, &non_null_compare, Assembler::kNearJump); - // Comparison with NULL is "===". - __ Bind(&identity_compare); - __ cmpl(left, right); - Condition cond = TokenKindToSmiCondition(kind); - if (branch != NULL) { - branch->EmitBranchOnCondition(compiler, cond); - } else { - Register result = locs->out().reg(); - Label load_true; - __ j(cond, &load_true, Assembler::kNearJump); - __ LoadObject(result, Bool::False()); - __ jmp(&done); - __ Bind(&load_true); - __ LoadObject(result, Bool::True()); - } - __ jmp(&done); - __ Bind(&non_null_compare); // Receiver is not null. __ pushl(left); __ pushl(right); EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, deopt_id, token_pos); - __ Bind(&done); } @@ -1827,7 +1760,7 @@ __ movl(value_cid_reg, FieldAddress(value_reg, TypedData::length_offset())); } - __ cmpl(value_cid_reg, Immediate(field_length)); + __ cmpl(value_cid_reg, Immediate(Smi::RawValue(field_length))); if (ok_is_fall_through) { __ j(NOT_EQUAL, fail); } @@ -4780,21 +4713,13 @@ void TargetEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { __ Bind(compiler->GetJumpLabel(this)); if (!compiler->is_optimizing()) { + compiler->EmitEdgeCounter(); + // The deoptimization descriptor points after the edge counter code for + // uniformity with ARM and MIPS, where we can reuse pattern matching + // code that matches backwards from the end of the pattern. compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, deopt_id_, Scanner::kDummyTokenIndex); - // Add an edge counter. - const Array& counter = Array::ZoneHandle(Array::New(1, Heap::kOld)); - counter.SetAt(0, Smi::Handle(Smi::New(0))); - Label done; - __ Comment("Edge counter"); - __ LoadObject(EAX, counter); - __ addl(FieldAddress(EAX, Array::element_offset(0)), - Immediate(Smi::RawValue(1))); - __ j(NO_OVERFLOW, &done); - __ movl(FieldAddress(EAX, Array::element_offset(0)), - Immediate(Smi::RawValue(Smi::kMaxValue))); - __ Bind(&done); } if (HasParallelMove()) { compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); @@ -4809,23 +4734,15 @@ void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { if (!compiler->is_optimizing()) { - // Add deoptimization descriptor for deoptimizing instructions that may - // be inserted before this instruction. + compiler->EmitEdgeCounter(); + // Add a deoptimization descriptor for deoptimizing instructions that + // may be inserted before this instruction. This descriptor points + // after the edge counter for uniformity with ARM and MIPS, where we can + // reuse pattern matching that matches backwards from the end of the + // pattern. compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, GetDeoptId(), - 0); // No token position. - // Add an edge counter. - const Array& counter = Array::ZoneHandle(Array::New(1, Heap::kOld)); - counter.SetAt(0, Smi::Handle(Smi::New(0))); - Label done; - __ Comment("Edge counter"); - __ LoadObject(EAX, counter); - __ addl(FieldAddress(EAX, Array::element_offset(0)), - Immediate(Smi::RawValue(1))); - __ j(NO_OVERFLOW, &done); - __ movl(FieldAddress(EAX, Array::element_offset(0)), - Immediate(Smi::RawValue(Smi::kMaxValue))); - __ Bind(&done); + Scanner::kDummyTokenIndex); } if (HasParallelMove()) { compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
diff --git a/runtime/vm/intermediate_language_mips.cc b/runtime/vm/intermediate_language_mips.cc index a1d5b18..4456f6e 100644 --- a/runtime/vm/intermediate_language_mips.cc +++ b/runtime/vm/intermediate_language_mips.cc
@@ -356,12 +356,6 @@ __ TraceSimMsg("EmitEqualityAsInstanceCall"); __ Comment("EmitEqualityAsInstanceCall"); - Label check_identity; - __ lw(A1, Address(SP, 1 * kWordSize)); - __ lw(A0, Address(SP, 0 * kWordSize)); - __ LoadImmediate(CMPRES1, reinterpret_cast<int32_t>(Object::null())); - __ beq(A1, CMPRES1, &check_identity); - __ beq(A0, CMPRES1, &check_identity); ICData& equality_ic_data = ICData::ZoneHandle(); if (compiler->is_optimizing() && FLAG_propagate_ic_data) { @@ -389,40 +383,6 @@ kNoArgumentNames, locs, equality_ic_data); - Label check_ne; - __ b(&check_ne); - - __ Bind(&check_identity); - Label equality_done; - if (compiler->is_optimizing()) { - // No need to update IC data. - Label is_true; - __ lw(A1, Address(SP, 1 * kWordSize)); - __ lw(A0, Address(SP, 0 * kWordSize)); - __ addiu(SP, SP, Immediate(2 * kWordSize)); - __ beq(A1, A0, &is_true); - __ LoadObject(V0, Bool::Get(kind != Token::kEQ)); - __ b(&equality_done); - __ Bind(&is_true); - __ LoadObject(V0, Bool::Get(kind == Token::kEQ)); - if (kind == Token::kNE) { - // Skip not-equal result conversion. - __ b(&equality_done); - } - } else { - // Call stub, load IC data in register. The stub will update ICData if - // necessary. - Register ic_data_reg = locs->temp(0).reg(); - ASSERT(ic_data_reg == T0); // Stub depends on it. - __ LoadObject(ic_data_reg, equality_ic_data); - // Pass left in A1 and right in A0. - compiler->GenerateCall(token_pos, - &StubCode::EqualityWithNullArgLabel(), - PcDescriptors::kRuntimeCall, - locs); - __ Drop(2); - } - __ Bind(&check_ne); if (kind == Token::kNE) { Label true_label, done; // Negate the condition: true label returns false and vice versa. @@ -433,7 +393,6 @@ __ LoadObject(V0, Bool::False()); __ Bind(&done); } - __ Bind(&equality_done); } @@ -649,31 +608,8 @@ ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); Register left = locs->in(0).reg(); Register right = locs->in(1).reg(); - Label done, identity_compare, non_null_compare; __ TraceSimMsg("EmitGenericEqualityCompare"); __ Comment("EmitGenericEqualityCompare"); - __ LoadImmediate(CMPRES1, reinterpret_cast<int32_t>(Object::null())); - __ beq(right, CMPRES1, &identity_compare); - __ bne(left, CMPRES1, &non_null_compare); - - // Comparison with NULL is "===". - __ Bind(&identity_compare); - Condition cond = TokenKindToSmiCondition(kind); - __ slt(CMPRES1, left, right); - __ slt(CMPRES2, right, left); - if (branch != NULL) { - branch->EmitBranchOnCondition(compiler, cond); - } else { - Register result = locs->out().reg(); - Label load_true; - EmitBranchAfterCompare(compiler, cond, &load_true); - __ LoadObject(result, Bool::False()); - __ b(&done); - __ Bind(&load_true); - __ LoadObject(result, Bool::True()); - } - __ b(&done); - __ Bind(&non_null_compare); // Receiver is not null. ASSERT(left == A1); ASSERT(right == A0); __ addiu(SP, SP, Immediate(-2 * kWordSize)); @@ -681,7 +617,6 @@ __ sw(A0, Address(SP, 0 * kWordSize)); EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, deopt_id, token_pos); - __ Bind(&done); } @@ -3838,22 +3773,13 @@ void TargetEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { __ Bind(compiler->GetJumpLabel(this)); if (!compiler->is_optimizing()) { + compiler->EmitEdgeCounter(); + // On MIPS the deoptimization descriptor points after the edge counter + // code so that we can reuse the same pattern matching code as at call + // sites, which matches backwards from the end of the pattern. compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, deopt_id_, Scanner::kDummyTokenIndex); - // Add an edge counter. - const Array& counter = Array::ZoneHandle(Array::New(1, Heap::kOld)); - counter.SetAt(0, Smi::Handle(Smi::New(0))); - Label done; - __ Comment("Edge counter"); - __ LoadObject(T0, counter); - __ lw(T1, FieldAddress(T0, Array::element_offset(0))); - __ AddImmediateDetectOverflow(T1, T1, Smi::RawValue(1), CMPRES, T2); - __ bgez(CMPRES, &done); - __ delay_slot()->sw(T1, FieldAddress(T0, Array::element_offset(0))); - __ LoadImmediate(TMP1, Smi::RawValue(Smi::kMaxValue)); - __ sw(TMP1, FieldAddress(T0, Array::element_offset(0))); // If overflow. - __ Bind(&done); } if (HasParallelMove()) { compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); @@ -3868,6 +3794,17 @@ void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { __ TraceSimMsg("GotoInstr"); + if (!compiler->is_optimizing()) { + compiler->EmitEdgeCounter(); + // Add a deoptimization descriptor for deoptimizing instructions that + // may be inserted before this instruction. On MIPS this descriptor + // points after the edge counter code so that we can reuse the same + // pattern matching code as at call sites, which matches backwards from + // the end of the pattern. + compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, + GetDeoptId(), + Scanner::kDummyTokenIndex); + } if (HasParallelMove()) { compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); }
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc index 096ff06..4b5562b 100644 --- a/runtime/vm/intermediate_language_x64.cc +++ b/runtime/vm/intermediate_language_x64.cc
@@ -52,7 +52,7 @@ if (value.IsRegister()) { __ pushq(value.reg()); } else if (value.IsConstant()) { - __ PushObject(value.constant()); + __ PushObject(value.constant(), PP); } else { ASSERT(value.IsStackSlot()); __ pushq(value.ToStackSlotAddress()); @@ -90,7 +90,7 @@ ASSERT(fp_sp_dist <= 0); __ movq(RDI, RSP); __ subq(RDI, RBP); - __ cmpq(RDI, Immediate(fp_sp_dist)); + __ CompareImmediate(RDI, Immediate(fp_sp_dist), PP); __ j(EQUAL, &done, Assembler::kNearJump); __ int3(); __ Bind(&done); @@ -196,9 +196,9 @@ if ((kind_ == Token::kNE_STRICT) || (kind_ == Token::kNE)) { result = !result; } - __ movq(locs()->out().reg(), + __ LoadImmediate(locs()->out().reg(), Immediate(reinterpret_cast<int64_t>( - Smi::New(result ? if_true_ : if_false_)))); + Smi::New(result ? if_true_ : if_false_))), PP); return; } @@ -212,9 +212,9 @@ // TODO(vegorov): reuse code from the other comparison instructions instead of // generating it inline here. if (left.IsConstant()) { - __ CompareObject(right.reg(), left.constant()); + __ CompareObject(right.reg(), left.constant(), PP); } else if (right.IsConstant()) { - __ CompareObject(left.reg(), right.constant()); + __ CompareObject(left.reg(), right.constant(), PP); } else { __ cmpq(left.reg(), right.reg()); } @@ -251,11 +251,11 @@ Utils::ShiftForPowerOfTwo(Utils::Maximum(true_value, false_value)); __ shlq(RDX, Immediate(shift + kSmiTagSize)); } else { - __ subq(RDX, Immediate(1)); - __ andq(RDX, Immediate( - Smi::RawValue(true_value) - Smi::RawValue(false_value))); + __ AddImmediate(RDX, Immediate(-1), PP); + __ AndImmediate(RDX, + Immediate(Smi::RawValue(true_value) - Smi::RawValue(false_value)), PP); if (false_value != 0) { - __ addq(RDX, Immediate(Smi::RawValue(false_value))); + __ AddImmediate(RDX, Immediate(Smi::RawValue(false_value)), PP); } } } @@ -341,9 +341,9 @@ // Call the runtime if the object is not bool::true or bool::false. ASSERT(locs->always_calls()); Label done; - __ CompareObject(reg, Bool::True()); + __ CompareObject(reg, Bool::True(), PP); __ j(EQUAL, &done, Assembler::kNearJump); - __ CompareObject(reg, Bool::False()); + __ CompareObject(reg, Bool::False(), PP); __ j(EQUAL, &done, Assembler::kNearJump); __ pushq(reg); // Push the source object. @@ -453,13 +453,6 @@ const Array& kNoArgumentNames = Object::null_array(); const int kNumArgumentsChecked = 2; - Label check_identity; - __ LoadObject(TMP, Object::null_object(), PP); - __ cmpq(Address(RSP, 0 * kWordSize), TMP); - __ j(EQUAL, &check_identity); - __ cmpq(Address(RSP, 1 * kWordSize), TMP); - __ j(EQUAL, &check_identity); - ICData& equality_ic_data = ICData::ZoneHandle(original_ic_data.raw()); if (compiler->is_optimizing() && FLAG_propagate_ic_data) { ASSERT(!original_ic_data.IsNull()); @@ -486,43 +479,10 @@ kNoArgumentNames, locs, equality_ic_data); - Label check_ne; - __ jmp(&check_ne); - - __ Bind(&check_identity); - Label equality_done; - if (compiler->is_optimizing()) { - // No need to update IC data. - Label is_true; - __ popq(RAX); - __ popq(RDX); - __ cmpq(RAX, RDX); - __ j(EQUAL, &is_true); - __ LoadObject(RAX, Bool::Get(kind != Token::kEQ), PP); - __ jmp(&equality_done); - __ Bind(&is_true); - __ LoadObject(RAX, Bool::Get(kind == Token::kEQ), PP); - if (kind == Token::kNE) { - // Skip not-equal result conversion. - __ jmp(&equality_done); - } - } else { - // Call stub, load IC data in register. The stub will update ICData if - // necessary. - Register ic_data_reg = locs->temp(0).reg(); - ASSERT(ic_data_reg == RBX); // Stub depends on it. - __ LoadObject(ic_data_reg, equality_ic_data, PP); - compiler->GenerateCall(token_pos, - &StubCode::EqualityWithNullArgLabel(), - PcDescriptors::kRuntimeCall, - locs); - __ Drop(2); - } - __ Bind(&check_ne); if (kind == Token::kNE) { Label true_label, done; // Negate the condition: true label returns false and vice versa. - __ CompareObject(RAX, Bool::True()); + __ CompareObject(RAX, Bool::True(), PP); __ j(EQUAL, &true_label, Assembler::kNearJump); __ LoadObject(RAX, Bool::True(), PP); __ jmp(&done, Assembler::kNearJump); @@ -530,7 +490,6 @@ __ LoadObject(RAX, Bool::False(), PP); __ Bind(&done); } - __ Bind(&equality_done); } @@ -540,7 +499,7 @@ Label* value_is_smi = NULL) { Label done; if (value_is_smi == NULL) { - __ movq(value_cid_reg, Immediate(kSmiCid)); + __ LoadImmediate(value_cid_reg, Immediate(kSmiCid), PP); } __ testq(value_reg, Immediate(kSmiTagMask)); if (value_is_smi == NULL) { @@ -579,7 +538,7 @@ // Assert that the Smi is at position 0, if at all. ASSERT((ic_data.GetReceiverClassIdAt(i) != kSmiCid) || (i == 0)); Label next_test; - __ cmpq(temp, Immediate(ic_data.GetReceiverClassIdAt(i))); + __ CompareImmediate(temp, Immediate(ic_data.GetReceiverClassIdAt(i)), PP); if (i < len - 1) { __ j(NOT_EQUAL, &next_test); } else { @@ -614,7 +573,7 @@ if (branch == NULL) { if (kind == Token::kNE) { Label false_label; - __ CompareObject(RAX, Bool::True()); + __ CompareObject(RAX, Bool::True(), PP); __ j(EQUAL, &false_label, Assembler::kNearJump); __ LoadObject(RAX, Bool::True(), PP); __ jmp(&done); @@ -625,7 +584,7 @@ if (branch->is_checked()) { EmitAssertBoolean(RAX, token_pos, deopt_id, locs, compiler); } - __ CompareObject(RAX, Bool::True()); + __ CompareObject(RAX, Bool::True(), PP); branch->EmitBranchOnCondition(compiler, cond); } } @@ -655,16 +614,16 @@ // 'left' is not Smi. Label identity_compare; - __ CompareObject(right, Object::null_object()); + __ CompareObject(right, Object::null_object(), PP); __ j(EQUAL, &identity_compare); - __ CompareObject(left, Object::null_object()); + __ CompareObject(left, Object::null_object(), PP); __ j(EQUAL, &identity_compare); __ LoadClassId(temp, left); const ICData& ic_data = ICData::Handle(orig_ic_data.AsUnaryClassChecks()); const intptr_t len = ic_data.NumberOfChecks(); for (intptr_t i = 0; i < len; i++) { - __ cmpq(temp, Immediate(ic_data.GetReceiverClassIdAt(i))); + __ CompareImmediate(temp, Immediate(ic_data.GetReceiverClassIdAt(i)), PP); if (i == (len - 1)) { __ j(NOT_EQUAL, deopt); } else { @@ -704,34 +663,10 @@ ASSERT(!ic_data.IsNull() && (ic_data.NumberOfChecks() > 0)); Register left = locs->in(0).reg(); Register right = locs->in(1).reg(); - - Label done, identity_compare, non_null_compare; - __ CompareObject(right, Object::null_object()); - __ j(EQUAL, &identity_compare, Assembler::kNearJump); - __ CompareObject(left, Object::null_object()); - __ j(NOT_EQUAL, &non_null_compare, Assembler::kNearJump); - // Comparison with NULL is "===". - __ Bind(&identity_compare); - __ cmpq(left, right); - Condition cond = TokenKindToSmiCondition(kind); - if (branch != NULL) { - branch->EmitBranchOnCondition(compiler, cond); - } else { - Register result = locs->out().reg(); - Label load_true; - __ j(cond, &load_true, Assembler::kNearJump); - __ LoadObject(result, Bool::False(), PP); - __ jmp(&done); - __ Bind(&load_true); - __ LoadObject(result, Bool::True(), PP); - } - __ jmp(&done); - __ Bind(&non_null_compare); // Receiver is not null. __ pushq(left); __ pushq(right); EmitEqualityAsPolymorphicCall(compiler, ic_data, locs, branch, kind, deopt_id, token_pos); - __ Bind(&done); } @@ -765,10 +700,10 @@ Condition true_condition = TokenKindToSmiCondition(kind); if (left.IsConstant()) { - __ CompareObject(right.reg(), left.constant()); + __ CompareObject(right.reg(), left.constant(), PP); true_condition = FlipCondition(true_condition); } else if (right.IsConstant()) { - __ CompareObject(left.reg(), right.constant()); + __ CompareObject(left.reg(), right.constant(), PP); } else if (right.IsStackSlot()) { __ cmpq(left.reg(), right.ToStackSlotAddress()); } else { @@ -897,7 +832,7 @@ EmitAssertBoolean(RAX, token_pos(), deopt_id(), locs(), compiler); } Condition branch_condition = (kind() == Token::kNE) ? NOT_EQUAL : EQUAL; - __ CompareObject(RAX, Bool::True()); + __ CompareObject(RAX, Bool::True(), PP); branch->EmitBranchOnCondition(compiler, branch_condition); } @@ -968,7 +903,7 @@ Register result = locs()->out().reg(); // Push the result place holder initialized to NULL. - __ PushObject(Object::ZoneHandle()); + __ PushObject(Object::ZoneHandle(), PP); // Pass a pointer to the first argument in RAX. if (!function().HasOptionalParameters()) { __ leaq(RAX, Address(RBP, (kParamEndSlotFromFp + @@ -977,8 +912,10 @@ __ leaq(RAX, Address(RBP, kFirstLocalSlotFromFp * kWordSize)); } - __ movq(RBX, Immediate(reinterpret_cast<uword>(native_c_function()))); - __ movq(R10, Immediate(NativeArguments::ComputeArgcTag(function()))); + __ LoadImmediate( + RBX, Immediate(reinterpret_cast<uword>(native_c_function())), PP); + __ LoadImmediate( + R10, Immediate(NativeArguments::ComputeArgcTag(function())), PP); const ExternalLabel* stub_entry = (is_bootstrap_native()) ? &StubCode::CallBootstrapCFunctionLabel() : &StubCode::CallNativeCFunctionLabel(); @@ -1014,8 +951,8 @@ void StringFromCharCodeInstr::EmitNativeCode(FlowGraphCompiler* compiler) { Register char_code = locs()->in(0).reg(); Register result = locs()->out().reg(); - __ movq(result, - Immediate(reinterpret_cast<uword>(Symbols::PredefinedAddress()))); + __ LoadImmediate(result, + Immediate(reinterpret_cast<uword>(Symbols::PredefinedAddress())), PP); __ movq(result, Address(result, char_code, TIMES_HALF_WORD_SIZE, // Char code is a smi. @@ -1052,7 +989,7 @@ Label load, done; __ testq(object, Immediate(kSmiTagMask)); __ j(NOT_ZERO, &load, Assembler::kNearJump); - __ movq(result, Immediate(Smi::RawValue(kSmiCid))); + __ LoadImmediate(result, Immediate(Smi::RawValue(kSmiCid)), PP); __ jmp(&done); __ Bind(&load); __ LoadClassId(result, object); @@ -1360,7 +1297,7 @@ __ StoreIntoObject(array, element_address, value); } else if (locs()->in(2).IsConstant()) { const Object& constant = locs()->in(2).constant(); - __ StoreObject(element_address, constant); + __ StoreObject(element_address, constant, PP); } else { Register value = locs()->in(2).reg(); __ StoreIntoObjectNoBarrier(array, element_address, value); @@ -1397,14 +1334,14 @@ ASSERT(locs()->in(2).reg() == RAX); Label store_value, store_0xff; __ SmiUntag(RAX); - __ cmpq(RAX, Immediate(0xFF)); + __ CompareImmediate(RAX, Immediate(0xFF), PP); __ j(BELOW_EQUAL, &store_value, Assembler::kNearJump); // Clamp to 0x0 or 0xFF respectively. __ j(GREATER, &store_0xff); __ xorq(RAX, RAX); __ jmp(&store_value, Assembler::kNearJump); __ Bind(&store_0xff); - __ movq(RAX, Immediate(0xFF)); + __ LoadImmediate(RAX, Immediate(0xFF), PP); __ Bind(&store_value); __ movb(element_address, RAX); } @@ -1538,13 +1475,15 @@ __ pushq(value_cid_reg); __ movq(value_cid_reg, FieldAddress(value_reg, Array::length_offset())); - __ cmpq(value_cid_reg, Immediate(Smi::RawValue(field_length))); + __ CompareImmediate( + value_cid_reg, Immediate(Smi::RawValue(field_length)), PP); __ popq(value_cid_reg); } else if (RawObject::IsTypedDataClassId(field_cid)) { __ pushq(value_cid_reg); __ movq(value_cid_reg, FieldAddress(value_reg, TypedData::length_offset())); - __ cmpq(value_cid_reg, Immediate(Smi::RawValue(field_length))); + __ CompareImmediate( + value_cid_reg, Immediate(Smi::RawValue(field_length)), PP); __ popq(value_cid_reg); } else { ASSERT(field_cid == kIllegalCid); @@ -1558,15 +1497,18 @@ // If length is negative the length guard is either disabled or // has not been initialized, either way it is safe to skip the // length check. - __ cmpq(field_length_operand, Immediate(Smi::RawValue(0))); + __ CompareImmediate( + field_length_operand, Immediate(Smi::RawValue(0)), PP); __ j(LESS, &skip_length_check); - __ cmpq(value_cid_reg, Immediate(kNullCid)); + __ CompareImmediate(value_cid_reg, Immediate(kNullCid), PP); __ j(EQUAL, &no_fixed_length, Assembler::kNearJump); // Check for typed data array. - __ cmpq(value_cid_reg, Immediate(kTypedDataFloat32x4ArrayCid)); + __ CompareImmediate( + value_cid_reg, Immediate(kTypedDataFloat32x4ArrayCid), PP); // Not a typed array or a regular array. __ j(GREATER, &no_fixed_length, Assembler::kNearJump); - __ cmpq(value_cid_reg, Immediate(kTypedDataInt8ArrayCid)); + __ CompareImmediate( + value_cid_reg, Immediate(kTypedDataInt8ArrayCid), PP); // Could still be a regular array. __ j(LESS, &check_array, Assembler::kNearJump); __ pushq(value_cid_reg); @@ -1577,9 +1519,9 @@ __ jmp(&length_compared, Assembler::kNearJump); // Check for regular array. __ Bind(&check_array); - __ cmpq(value_cid_reg, Immediate(kImmutableArrayCid)); + __ CompareImmediate(value_cid_reg, Immediate(kImmutableArrayCid), PP); __ j(GREATER, &no_fixed_length, Assembler::kNearJump); - __ cmpq(value_cid_reg, Immediate(kArrayCid)); + __ CompareImmediate(value_cid_reg, Immediate(kArrayCid), PP); __ j(LESS, &no_fixed_length, Assembler::kNearJump); __ pushq(value_cid_reg); __ movq(value_cid_reg, @@ -1596,21 +1538,22 @@ __ Bind(&skip_length_check); __ cmpq(value_cid_reg, field_nullability_operand); } else if (value_cid == kNullCid) { - __ cmpq(field_nullability_operand, Immediate(value_cid)); + __ CompareImmediate(field_nullability_operand, Immediate(value_cid), PP); } else { Label skip_length_check; - __ cmpq(field_cid_operand, Immediate(value_cid)); + __ CompareImmediate(field_cid_operand, Immediate(value_cid), PP); // If not equal, skip over length check. __ j(NOT_EQUAL, &skip_length_check); // Insert length check. if (field_has_length) { ASSERT(value_cid_reg != kNoRegister); if ((value_cid == kArrayCid) || (value_cid == kImmutableArrayCid)) { - __ cmpq(FieldAddress(value_reg, Array::length_offset()), - Immediate(Smi::RawValue(field_length))); + __ CompareImmediate(FieldAddress(value_reg, Array::length_offset()), + Immediate(Smi::RawValue(field_length)), PP); } else if (RawObject::IsTypedDataClassId(value_cid)) { - __ cmpq(FieldAddress(value_reg, TypedData::length_offset()), - Immediate(Smi::RawValue(field_length))); + __ CompareImmediate( + FieldAddress(value_reg, TypedData::length_offset()), + Immediate(Smi::RawValue(field_length)), PP); } else if (field_cid != kIllegalCid) { ASSERT(field_cid != value_cid); ASSERT(field_length >= 0); @@ -1629,7 +1572,7 @@ } __ j(EQUAL, &ok); - __ cmpq(field_cid_operand, Immediate(kIllegalCid)); + __ CompareImmediate(field_cid_operand, Immediate(kIllegalCid), PP); __ j(NOT_EQUAL, fail); if (value_cid == kDynamicCid) { @@ -1637,13 +1580,15 @@ __ movq(field_nullability_operand, value_cid_reg); if (field_has_length) { Label check_array, length_set, no_fixed_length; - __ cmpq(value_cid_reg, Immediate(kNullCid)); + __ CompareImmediate(value_cid_reg, Immediate(kNullCid), PP); __ j(EQUAL, &no_fixed_length, Assembler::kNearJump); // Check for typed data array. - __ cmpq(value_cid_reg, Immediate(kTypedDataFloat32x4ArrayCid)); + __ CompareImmediate(value_cid_reg, + Immediate(kTypedDataFloat32x4ArrayCid), PP); // Not a typed array or a regular array. __ j(GREATER, &no_fixed_length); - __ cmpq(value_cid_reg, Immediate(kTypedDataInt8ArrayCid)); + __ CompareImmediate( + value_cid_reg, Immediate(kTypedDataInt8ArrayCid), PP); // Could still be a regular array. __ j(LESS, &check_array, Assembler::kNearJump); // Destroy value_cid_reg (safe because we are finished with it). @@ -1654,9 +1599,9 @@ __ jmp(&length_set); // Check for regular array. __ Bind(&check_array); - __ cmpq(value_cid_reg, Immediate(kImmutableArrayCid)); + __ CompareImmediate(value_cid_reg, Immediate(kImmutableArrayCid), PP); __ j(GREATER, &no_fixed_length, Assembler::kNearJump); - __ cmpq(value_cid_reg, Immediate(kArrayCid)); + __ CompareImmediate(value_cid_reg, Immediate(kArrayCid), PP); __ j(LESS, &no_fixed_length, Assembler::kNearJump); // Destroy value_cid_reg (safe because we are finished with it). __ movq(value_cid_reg, @@ -1665,14 +1610,14 @@ // Updated field length from regular array. __ jmp(&length_set, Assembler::kNearJump); __ Bind(&no_fixed_length); - __ movq(field_length_operand, - Immediate(Smi::RawValue(Field::kNoFixedLength))); + __ LoadImmediate(field_length_operand, + Immediate(Smi::RawValue(Field::kNoFixedLength)), PP); __ Bind(&length_set); } } else { ASSERT(field_reg != kNoRegister); - __ movq(field_cid_operand, Immediate(value_cid)); - __ movq(field_nullability_operand, Immediate(value_cid)); + __ LoadImmediate(field_cid_operand, Immediate(value_cid), PP); + __ LoadImmediate(field_nullability_operand, Immediate(value_cid), PP); if (field_has_length) { ASSERT(value_cid_reg != kNoRegister); if ((value_cid == kArrayCid) || (value_cid == kImmutableArrayCid)) { @@ -1686,8 +1631,8 @@ FieldAddress(value_reg, TypedData::length_offset())); __ movq(field_length_operand, value_cid_reg); } else { - __ movq(field_length_operand, - Immediate(Smi::RawValue(Field::kNoFixedLength))); + __ LoadImmediate(field_length_operand, + Immediate(Smi::RawValue(Field::kNoFixedLength)), PP); } } } @@ -1706,7 +1651,7 @@ if (field_cid != kSmiCid) { __ j(ZERO, fail); __ LoadClassId(value_cid_reg, value_reg); - __ cmpq(value_cid_reg, Immediate(field_cid)); + __ CompareImmediate(value_cid_reg, Immediate(field_cid), PP); } if (field_has_length) { @@ -1732,7 +1677,7 @@ if (field().is_nullable() && (field_cid != kNullCid)) { __ j(EQUAL, &ok); - __ CompareObject(value_reg, Object::null_object()); + __ CompareObject(value_reg, Object::null_object(), PP); } if (ok_is_fall_through) { @@ -1757,7 +1702,8 @@ __ movq(value_cid_reg, FieldAddress(value_reg, TypedData::length_offset())); } - __ cmpq(value_cid_reg, Immediate(Smi::RawValue(field_length))); + __ CompareImmediate( + value_cid_reg, Immediate(Smi::RawValue(field_length)), PP); if (ok_is_fall_through) { __ j(NOT_EQUAL, fail); } @@ -1773,8 +1719,8 @@ ASSERT(!compiler->is_optimizing()); __ Bind(fail); - __ cmpq(FieldAddress(field_reg, Field::guarded_cid_offset()), - Immediate(kDynamicCid)); + __ CompareImmediate(FieldAddress(field_reg, Field::guarded_cid_offset()), + Immediate(kDynamicCid), PP); __ j(EQUAL, &ok); __ pushq(field_reg); @@ -1811,7 +1757,7 @@ } else { if (locs()->in(1).IsConstant()) { __ StoreObject(FieldAddress(instance_reg, field().Offset()), - locs()->in(1).constant()); + locs()->in(1).constant(), PP); } else { Register value_reg = locs()->in(1).reg(); __ StoreIntoObjectNoBarrier(instance_reg, @@ -1909,7 +1855,7 @@ void CreateArrayInstr::EmitNativeCode(FlowGraphCompiler* compiler) { // Allocate the array. R10 = length, RBX = element type. ASSERT(locs()->in(0).reg() == RBX); - __ movq(R10, Immediate(Smi::RawValue(num_elements()))); + __ LoadImmediate(R10, Immediate(Smi::RawValue(num_elements())), PP); compiler->GenerateCall(token_pos(), &StubCode::AllocateArrayLabel(), PcDescriptors::kOther, @@ -1970,8 +1916,8 @@ // 'instantiator_reg' is the instantiator AbstractTypeArguments object // (or null). // A runtime call to instantiate the type is required. - __ PushObject(Object::ZoneHandle()); // Make room for the result. - __ PushObject(type()); + __ PushObject(Object::ZoneHandle(), PP); // Make room for the result. + __ PushObject(type(), PP); __ pushq(instantiator_reg); // Push instantiator type arguments. compiler->GenerateCallRuntime(token_pos(), deopt_id(), @@ -2011,13 +1957,13 @@ Label type_arguments_instantiated; const intptr_t len = type_arguments().Length(); if (type_arguments().IsRawInstantiatedRaw(len)) { - __ CompareObject(instantiator_reg, Object::null_object()); + __ CompareObject(instantiator_reg, Object::null_object(), PP); __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); } // Instantiate non-null type arguments. // A runtime call to instantiate the type arguments is required. - __ PushObject(Object::ZoneHandle()); // Make room for the result. - __ PushObject(type_arguments()); + __ PushObject(Object::ZoneHandle(), PP); // Make room for the result. + __ PushObject(type_arguments(), PP); __ pushq(instantiator_reg); // Push instantiator type arguments. compiler->GenerateCallRuntime(token_pos(), deopt_id(), @@ -2060,7 +2006,7 @@ Label type_arguments_instantiated; ASSERT(type_arguments().IsRawInstantiatedRaw(type_arguments().Length())); - __ CompareObject(instantiator_reg, Object::null_object()); + __ CompareObject(instantiator_reg, Object::null_object(), PP); __ j(EQUAL, &type_arguments_instantiated, Assembler::kNearJump); // Instantiate non-null type arguments. // In the non-factory case, we rely on the allocation stub to @@ -2102,12 +2048,12 @@ ASSERT(type_arguments().IsRawInstantiatedRaw(type_arguments().Length())); Label instantiator_not_null; - __ CompareObject(instantiator_reg, Object::null_object()); + __ CompareObject(instantiator_reg, Object::null_object(), PP); __ j(NOT_EQUAL, &instantiator_not_null, Assembler::kNearJump); // Null was used in VisitExtractConstructorTypeArguments as the // instantiated type arguments, no proper instantiator needed. - __ movq(instantiator_reg, - Immediate(Smi::RawValue(StubCode::kNoInstantiator))); + __ LoadImmediate(instantiator_reg, + Immediate(Smi::RawValue(StubCode::kNoInstantiator)), PP); __ Bind(&instantiator_not_null); // instantiator_reg: instantiator or kNoInstantiator. } @@ -2128,7 +2074,7 @@ ASSERT(locs()->temp(0).reg() == R10); ASSERT(locs()->out().reg() == RAX); - __ movq(R10, Immediate(num_context_variables())); + __ LoadImmediate(R10, Immediate(num_context_variables()), PP); const ExternalLabel label("alloc_context", StubCode::AllocateContextEntryPoint()); compiler->GenerateCall(token_pos(), @@ -2153,7 +2099,7 @@ Register context_value = locs()->in(0).reg(); Register result = locs()->out().reg(); - __ PushObject(Object::ZoneHandle()); // Make room for the result. + __ PushObject(Object::ZoneHandle(), PP); // Make room for the result. __ pushq(context_value); compiler->GenerateCallRuntime(token_pos(), deopt_id(), @@ -2255,7 +2201,8 @@ Register temp = locs()->temp(0).reg(); // Generate stack overflow check. - __ movq(temp, Immediate(Isolate::Current()->stack_limit_address())); + __ LoadImmediate( + temp, Immediate(Isolate::Current()->stack_limit_address()), PP); __ cmpq(RSP, Address(temp, 0)); __ j(BELOW_EQUAL, slow_path->entry_label()); if (compiler->CanOSRFunction() && in_loop()) { @@ -2265,8 +2212,8 @@ __ LoadObject(temp, compiler->parsed_function().function(), PP); intptr_t threshold = FLAG_optimization_counter_threshold * (loop_depth() + 1); - __ cmpq(FieldAddress(temp, Function::usage_counter_offset()), - Immediate(threshold)); + __ CompareImmediate(FieldAddress(temp, Function::usage_counter_offset()), + Immediate(threshold), PP); __ j(GREATER_EQUAL, slow_path->entry_label()); } __ Bind(slow_path->exit_label()); @@ -2279,9 +2226,9 @@ Register result) { if (!range->IsWithin(-0x20000000000000LL, 0x20000000000000LL)) { ASSERT(overflow != NULL); - __ cmpq(result, Immediate(-0x20000000000000LL)); + __ CompareImmediate(result, Immediate(-0x20000000000000LL), PP); __ j(LESS, overflow); - __ cmpq(result, Immediate(0x20000000000000LL)); + __ CompareImmediate(result, Immediate(0x20000000000000LL), PP); __ j(GREATER, overflow); } } @@ -2342,7 +2289,7 @@ if (obj.IsSmi()) { const intptr_t left_int = Smi::Cast(obj).Value(); if (left_int == 0) { - __ cmpq(right, Immediate(0)); + __ CompareImmediate(right, Immediate(0), PP); __ j(NEGATIVE, deopt); return; } @@ -2351,8 +2298,8 @@ (right_range == NULL) || !right_range->IsWithin(0, max_right - 1); if (right_needs_check) { - __ cmpq(right, - Immediate(reinterpret_cast<int64_t>(Smi::New(max_right)))); + __ CompareImmediate(right, + Immediate(reinterpret_cast<int64_t>(Smi::New(max_right))), PP); __ j(ABOVE_EQUAL, deopt); } __ SmiUntag(right); @@ -2374,12 +2321,12 @@ !right_range->IsWithin(0, RangeBoundary::kPlusInfinity); if (right_may_be_negative) { ASSERT(shift_left->CanDeoptimize()); - __ cmpq(right, Immediate(0)); + __ CompareImmediate(right, Immediate(0), PP); __ j(NEGATIVE, deopt); } Label done, is_not_zero; - __ cmpq(right, - Immediate(reinterpret_cast<int64_t>(Smi::New(Smi::kBits)))); + __ CompareImmediate(right, + Immediate(reinterpret_cast<int64_t>(Smi::New(Smi::kBits))), PP); __ j(BELOW, &is_not_zero, Assembler::kNearJump); __ xorq(left, left); __ jmp(&done, Assembler::kNearJump); @@ -2394,8 +2341,8 @@ } else { if (right_needs_check) { ASSERT(shift_left->CanDeoptimize()); - __ cmpq(right, - Immediate(reinterpret_cast<int64_t>(Smi::New(Smi::kBits)))); + __ CompareImmediate(right, + Immediate(reinterpret_cast<int64_t>(Smi::New(Smi::kBits))), PP); __ j(ABOVE_EQUAL, deopt); } // Left is not a constant. @@ -2518,12 +2465,12 @@ reinterpret_cast<int64_t>(constant.raw()); switch (op_kind()) { case Token::kADD: { - __ addq(left, Immediate(imm)); + __ AddImmediate(left, Immediate(imm), PP); if (deopt != NULL) __ j(OVERFLOW, deopt); break; } case Token::kSUB: { - __ subq(left, Immediate(imm)); + __ AddImmediate(left, Immediate(-imm), PP); if (deopt != NULL) __ j(OVERFLOW, deopt); break; } @@ -2533,7 +2480,7 @@ if (value == 2) { __ shlq(left, Immediate(1)); } else { - __ imulq(left, Immediate(value)); + __ MulImmediate(left, Immediate(value), PP); } if (deopt != NULL) __ j(OVERFLOW, deopt); break; @@ -2546,7 +2493,7 @@ } else if (value == -1) { // Check the corner case of dividing the 'MIN_SMI' with -1, in which // case we cannot negate the result. - __ cmpq(left, Immediate(0x8000000000000000)); + __ CompareImmediate(left, Immediate(0x8000000000000000), PP); __ j(EQUAL, deopt); __ negq(left); break; @@ -2572,17 +2519,17 @@ } case Token::kBIT_AND: { // No overflow check. - __ andq(left, Immediate(imm)); + __ AndImmediate(left, Immediate(imm), PP); break; } case Token::kBIT_OR: { // No overflow check. - __ orq(left, Immediate(imm)); + __ OrImmediate(left, Immediate(imm), PP); break; } case Token::kBIT_XOR: { // No overflow check. - __ xorq(left, Immediate(imm)); + __ XorImmediate(left, Immediate(imm), PP); break; } @@ -2738,7 +2685,7 @@ __ idivq(right); // RAX: quotient, RDX: remainder. // Check the corner case of dividing the 'MIN_SMI' with -1, in which // case we cannot tag the result. - __ cmpq(result, Immediate(0x4000000000000000)); + __ CompareImmediate(result, Immediate(0x4000000000000000), PP); __ j(EQUAL, deopt); __ Bind(&done); __ SmiTag(result); @@ -2746,7 +2693,7 @@ } case Token::kSHR: { if (CanDeoptimize()) { - __ cmpq(right, Immediate(0)); + __ CompareImmediate(right, Immediate(0), PP); __ j(LESS, deopt); } __ SmiUntag(right); @@ -2755,10 +2702,10 @@ Range* right_range = this->right()->definition()->range(); if ((right_range == NULL) || !right_range->IsWithin(RangeBoundary::kMinusInfinity, kCountLimit)) { - __ cmpq(right, Immediate(kCountLimit)); + __ CompareImmediate(right, Immediate(kCountLimit), PP); Label count_ok; __ j(LESS, &count_ok, Assembler::kNearJump); - __ movq(right, Immediate(kCountLimit)); + __ LoadImmediate(right, Immediate(kCountLimit), PP); __ Bind(&count_ok); } ASSERT(right == RCX); // Count must be in RCX @@ -2886,7 +2833,8 @@ __ TryAllocate(compiler->double_class(), slow_path->entry_label(), Assembler::kFarJump, - out_reg); + out_reg, + PP); __ Bind(slow_path->exit_label()); __ movsd(FieldAddress(out_reg, Double::value_offset()), value); } @@ -2988,7 +2936,8 @@ __ TryAllocate(compiler->float32x4_class(), slow_path->entry_label(), Assembler::kFarJump, - out_reg); + out_reg, + PP); __ Bind(slow_path->exit_label()); __ movups(FieldAddress(out_reg, Float32x4::value_offset()), value); } @@ -3073,7 +3022,8 @@ __ TryAllocate(compiler->uint32x4_class(), slow_path->entry_label(), Assembler::kFarJump, - out_reg); + out_reg, + PP); __ Bind(slow_path->exit_label()); __ movups(FieldAddress(out_reg, Uint32x4::value_offset()), value); } @@ -3243,7 +3193,7 @@ XmmRegister v2 = locs()->in(2).fpu_reg(); XmmRegister v3 = locs()->in(3).fpu_reg(); ASSERT(v0 == locs()->out().fpu_reg()); - __ subq(RSP, Immediate(16)); + __ AddImmediate(RSP, Immediate(-16), PP); __ cvtsd2ss(v0, v0); __ movss(Address(RSP, 0), v0); __ movsd(v0, v1); @@ -3256,7 +3206,7 @@ __ cvtsd2ss(v0, v0); __ movss(Address(RSP, 12), v0); __ movups(v0, Address(RSP, 0)); - __ addq(RSP, Immediate(16)); + __ AddImmediate(RSP, Immediate(16), PP); } @@ -3501,47 +3451,47 @@ switch (op_kind()) { case MethodRecognizer::kFloat32x4WithX: __ cvtsd2ss(replacement, replacement); - __ subq(RSP, Immediate(16)); + __ AddImmediate(RSP, Immediate(-16), PP); // Move value to stack. __ movups(Address(RSP, 0), value); // Write over X value. __ movss(Address(RSP, 0), replacement); // Move updated value into output register. __ movups(replacement, Address(RSP, 0)); - __ addq(RSP, Immediate(16)); + __ AddImmediate(RSP, Immediate(16), PP); break; case MethodRecognizer::kFloat32x4WithY: __ cvtsd2ss(replacement, replacement); - __ subq(RSP, Immediate(16)); + __ AddImmediate(RSP, Immediate(-16), PP); // Move value to stack. __ movups(Address(RSP, 0), value); // Write over Y value. __ movss(Address(RSP, 4), replacement); // Move updated value into output register. __ movups(replacement, Address(RSP, 0)); - __ addq(RSP, Immediate(16)); + __ AddImmediate(RSP, Immediate(16), PP); break; case MethodRecognizer::kFloat32x4WithZ: __ cvtsd2ss(replacement, replacement); - __ subq(RSP, Immediate(16)); + __ AddImmediate(RSP, Immediate(-16), PP); // Move value to stack. __ movups(Address(RSP, 0), value); // Write over Z value. __ movss(Address(RSP, 8), replacement); // Move updated value into output register. __ movups(replacement, Address(RSP, 0)); - __ addq(RSP, Immediate(16)); + __ AddImmediate(RSP, Immediate(16), PP); break; case MethodRecognizer::kFloat32x4WithW: __ cvtsd2ss(replacement, replacement); - __ subq(RSP, Immediate(16)); + __ AddImmediate(RSP, Immediate(-16), PP); // Move value to stack. __ movups(Address(RSP, 0), value); // Write over W value. __ movss(Address(RSP, 12), replacement); // Move updated value into output register. __ movups(replacement, Address(RSP, 0)); - __ addq(RSP, Immediate(16)); + __ AddImmediate(RSP, Immediate(16), PP); break; default: UNREACHABLE(); } @@ -3629,46 +3579,46 @@ Label y_false, y_done; Label z_false, z_done; Label w_false, w_done; - __ subq(RSP, Immediate(16)); + __ AddImmediate(RSP, Immediate(-16), PP); - __ CompareObject(v0, Bool::True()); + __ CompareObject(v0, Bool::True(), PP); __ j(NOT_EQUAL, &x_false); - __ movq(temp, Immediate(0xFFFFFFFF)); + __ LoadImmediate(temp, Immediate(0xFFFFFFFF), PP); __ jmp(&x_done); __ Bind(&x_false); - __ movq(temp, Immediate(0x0)); + __ LoadImmediate(temp, Immediate(0x0), PP); __ Bind(&x_done); __ movl(Address(RSP, 0), temp); - __ CompareObject(v1, Bool::True()); + __ CompareObject(v1, Bool::True(), PP); __ j(NOT_EQUAL, &y_false); - __ movq(temp, Immediate(0xFFFFFFFF)); + __ LoadImmediate(temp, Immediate(0xFFFFFFFF), PP); __ jmp(&y_done); __ Bind(&y_false); - __ movq(temp, Immediate(0x0)); + __ LoadImmediate(temp, Immediate(0x0), PP); __ Bind(&y_done); __ movl(Address(RSP, 4), temp); - __ CompareObject(v2, Bool::True()); + __ CompareObject(v2, Bool::True(), PP); __ j(NOT_EQUAL, &z_false); - __ movq(temp, Immediate(0xFFFFFFFF)); + __ LoadImmediate(temp, Immediate(0xFFFFFFFF), PP); __ jmp(&z_done); __ Bind(&z_false); - __ movq(temp, Immediate(0x0)); + __ LoadImmediate(temp, Immediate(0x0), PP); __ Bind(&z_done); __ movl(Address(RSP, 8), temp); - __ CompareObject(v3, Bool::True()); + __ CompareObject(v3, Bool::True(), PP); __ j(NOT_EQUAL, &w_false); - __ movq(temp, Immediate(0xFFFFFFFF)); + __ LoadImmediate(temp, Immediate(0xFFFFFFFF), PP); __ jmp(&w_done); __ Bind(&w_false); - __ movq(temp, Immediate(0x0)); + __ LoadImmediate(temp, Immediate(0x0), PP); __ Bind(&w_done); __ movl(Address(RSP, 12), temp); __ movups(result, Address(RSP, 0)); - __ addq(RSP, Immediate(16)); + __ AddImmediate(RSP, Immediate(16), PP); } @@ -3688,7 +3638,7 @@ Register result = locs()->out().reg(); Label done; Label non_zero; - __ subq(RSP, Immediate(16)); + __ AddImmediate(RSP, Immediate(-16), PP); // Move value to stack. __ movups(Address(RSP, 0), value); switch (op_kind()) { @@ -3706,7 +3656,7 @@ break; default: UNREACHABLE(); } - __ addq(RSP, Immediate(16)); + __ AddImmediate(RSP, Immediate(16), PP); __ testl(result, result); __ j(NOT_ZERO, &non_zero, Assembler::kNearJump); __ LoadObject(result, Bool::False(), PP); @@ -3769,43 +3719,43 @@ Register flag = locs()->in(1).reg(); Register temp = locs()->temp(0).reg(); ASSERT(mask == locs()->out().fpu_reg()); - __ subq(RSP, Immediate(16)); + __ AddImmediate(RSP, Immediate(-16), PP); // Copy mask to stack. __ movups(Address(RSP, 0), mask); Label falsePath, exitPath; - __ CompareObject(flag, Bool::True()); + __ CompareObject(flag, Bool::True(), PP); __ j(NOT_EQUAL, &falsePath); switch (op_kind()) { case MethodRecognizer::kUint32x4WithFlagX: - __ movq(temp, Immediate(0xFFFFFFFF)); + __ LoadImmediate(temp, Immediate(0xFFFFFFFF), PP); __ movl(Address(RSP, 0), temp); __ jmp(&exitPath); __ Bind(&falsePath); - __ movq(temp, Immediate(0x0)); + __ LoadImmediate(temp, Immediate(0x0), PP); __ movl(Address(RSP, 0), temp); break; case MethodRecognizer::kUint32x4WithFlagY: - __ movq(temp, Immediate(0xFFFFFFFF)); + __ LoadImmediate(temp, Immediate(0xFFFFFFFF), PP); __ movl(Address(RSP, 4), temp); __ jmp(&exitPath); __ Bind(&falsePath); - __ movq(temp, Immediate(0x0)); + __ LoadImmediate(temp, Immediate(0x0), PP); __ movl(Address(RSP, 4), temp); break; case MethodRecognizer::kUint32x4WithFlagZ: - __ movq(temp, Immediate(0xFFFFFFFF)); + __ LoadImmediate(temp, Immediate(0xFFFFFFFF), PP); __ movl(Address(RSP, 8), temp); __ jmp(&exitPath); __ Bind(&falsePath); - __ movq(temp, Immediate(0x0)); + __ LoadImmediate(temp, Immediate(0x0), PP); __ movl(Address(RSP, 8), temp); break; case MethodRecognizer::kUint32x4WithFlagW: - __ movq(temp, Immediate(0xFFFFFFFF)); + __ LoadImmediate(temp, Immediate(0xFFFFFFFF), PP); __ movl(Address(RSP, 12), temp); __ jmp(&exitPath); __ Bind(&falsePath); - __ movq(temp, Immediate(0x0)); + __ LoadImmediate(temp, Immediate(0x0), PP); __ movl(Address(RSP, 12), temp); break; default: UNREACHABLE(); @@ -3813,7 +3763,7 @@ __ Bind(&exitPath); // Copy mask back to register. __ movups(mask, Address(RSP, 0)); - __ addq(RSP, Immediate(16)); + __ AddImmediate(RSP, Immediate(16), PP); } @@ -3936,7 +3886,8 @@ } case Token::kBIT_NOT: __ notq(value); - __ andq(value, Immediate(~kSmiTagMask)); // Remove inverted smi-tag. + // Remove inverted smi-tag. + __ AndImmediate(value, Immediate(~kSmiTagMask), PP); break; default: UNREACHABLE(); @@ -4011,7 +3962,7 @@ __ Bind(&returns_nan); static double kNaN = NAN; - __ movq(temp, Immediate(reinterpret_cast<intptr_t>(&kNaN))); + __ LoadImmediate(temp, Immediate(reinterpret_cast<intptr_t>(&kNaN)), PP); __ movsd(result, Address(temp, 0)); __ jmp(&done, Assembler::kNearJump); @@ -4337,7 +4288,7 @@ Label* deopt = compiler->AddDeoptStub(deopt_id(), kDeoptCheckClass); __ CompareObject(locs()->in(0).reg(), - Object::null_object()); + Object::null_object(), PP); __ j(EQUAL, deopt); return; } @@ -4434,12 +4385,14 @@ if (index_loc.IsConstant()) { Register length = length_loc.reg(); const Smi& index = Smi::Cast(index_loc.constant()); - __ cmpq(length, Immediate(reinterpret_cast<int64_t>(index.raw()))); + __ CompareImmediate( + length, Immediate(reinterpret_cast<int64_t>(index.raw())), PP); __ j(BELOW_EQUAL, deopt); } else if (length_loc.IsConstant()) { const Smi& length = Smi::Cast(length_loc.constant()); Register index = index_loc.reg(); - __ cmpq(index, Immediate(reinterpret_cast<int64_t>(length.raw()))); + __ CompareImmediate( + index, Immediate(reinterpret_cast<int64_t>(length.raw())), PP); __ j(ABOVE_EQUAL, deopt); } else { Register length = length_loc.reg(); @@ -4546,21 +4499,13 @@ void TargetEntryInstr::EmitNativeCode(FlowGraphCompiler* compiler) { __ Bind(compiler->GetJumpLabel(this)); if (!compiler->is_optimizing()) { + compiler->EmitEdgeCounter(); + // The deoptimization descriptor points after the edge counter code for + // uniformity with ARM and MIPS, where we can reuse pattern matching + // code that matches backwards from the end of the pattern. compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, deopt_id_, Scanner::kDummyTokenIndex); - // Add an edge counter. - const Array& counter = Array::ZoneHandle(Array::New(1, Heap::kOld)); - counter.SetAt(0, Smi::Handle(Smi::New(0))); - Label done; - __ Comment("Edge counter"); - __ LoadObject(RAX, counter, PP); - __ addq(FieldAddress(RAX, Array::element_offset(0)), - Immediate(Smi::RawValue(1))); - __ j(NO_OVERFLOW, &done); - __ movq(FieldAddress(RAX, Array::element_offset(0)), - Immediate(Smi::RawValue(Smi::kMaxValue))); - __ Bind(&done); } if (HasParallelMove()) { compiler->parallel_move_resolver()->EmitNativeCode(parallel_move()); @@ -4575,23 +4520,15 @@ void GotoInstr::EmitNativeCode(FlowGraphCompiler* compiler) { if (!compiler->is_optimizing()) { - // Add deoptimization descriptor for deoptimizing instructions that may - // be inserted before this instruction. + compiler->EmitEdgeCounter(); + // Add a deoptimization descriptor for deoptimizing instructions that + // may be inserted before this instruction. This descriptor points + // after the edge counter for uniformity with ARM and MIPS, where we can + // reuse pattern matching that matches backwards from the end of the + // pattern. compiler->AddCurrentDescriptor(PcDescriptors::kDeopt, GetDeoptId(), - 0); // No token position. - // Add an edge counter. - const Array& counter = Array::ZoneHandle(Array::New(1, Heap::kOld)); - counter.SetAt(0, Smi::Handle(Smi::New(0))); - Label done; - __ Comment("Edge counter"); - __ LoadObject(RAX, counter, PP); - __ addq(FieldAddress(RAX, Array::element_offset(0)), - Immediate(Smi::RawValue(1))); - __ j(NO_OVERFLOW, &done); - __ movq(FieldAddress(RAX, Array::element_offset(0)), - Immediate(Smi::RawValue(Smi::kMaxValue))); - __ Bind(&done); + Scanner::kDummyTokenIndex); } if (HasParallelMove()) { compiler->parallel_move_resolver()->EmitNativeCode(parallel_move());
diff --git a/runtime/vm/intrinsifier.cc b/runtime/vm/intrinsifier.cc index e7edd62..fa3992b 100644 --- a/runtime/vm/intrinsifier.cc +++ b/runtime/vm/intrinsifier.cc
@@ -69,7 +69,7 @@ // the class matches and the rest of the method name starting with // the dot matches, we have found a match. // We do not store the entire factory constructor name with the class - // (e.g: _GrowableObjectArray.withData) because the actual function name + // (e.g: _GrowableList.withData) because the actual function name // that we see here includes the private key. if (test_function_name[0] == '.') { function_name = strstr(function_name, ".");
diff --git a/runtime/vm/intrinsifier.h b/runtime/vm/intrinsifier.h index de6d92e..e5d4dd2 100644 --- a/runtime/vm/intrinsifier.h +++ b/runtime/vm/intrinsifier.h
@@ -31,20 +31,20 @@ V(_Double, get:isNegative, Double_getIsNegative, 1711391869) \ V(_Double, _mulFromInteger, Double_mulFromInteger, 1238321808) \ V(_Double, .fromInteger, Double_fromInteger, 82414734) \ - V(_ObjectArray, ., ObjectArray_Allocate, 1558200848) \ - V(_ObjectArray, get:length, Array_getLength, 259382695) \ - V(_ObjectArray, [], Array_getIndexed, 544020319) \ - V(_ObjectArray, []=, Array_setIndexed, 304306010) \ - V(_GrowableObjectArray, .withData, GrowableArray_Allocate, 619965861) \ - V(_GrowableObjectArray, get:length, GrowableArray_getLength, 1160417196) \ - V(_GrowableObjectArray, get:_capacity, GrowableArray_getCapacity, 1509841570)\ - V(_GrowableObjectArray, [], GrowableArray_getIndexed, 951312767) \ - V(_GrowableObjectArray, []=, GrowableArray_setIndexed, 1366856519) \ - V(_GrowableObjectArray, _setLength, GrowableArray_setLength, 1112774552) \ - V(_GrowableObjectArray, _setData, GrowableArray_setData, 1574432374) \ - V(_GrowableObjectArray, add, GrowableArray_add, 635801182) \ - V(_ImmutableArray, [], ImmutableArray_getIndexed, 1345387065) \ - V(_ImmutableArray, get:length, ImmutableArray_getLength, 1342001998) \ + V(_List, ., List_Allocate, 1436567945) \ + V(_List, get:length, Array_getLength, 215153395) \ + V(_List, [], Array_getIndexed, 1079829188) \ + V(_List, []=, Array_setIndexed, 748954698) \ + V(_GrowableList, .withData, GrowableList_Allocate, 461305701) \ + V(_GrowableList, get:length, GrowableList_getLength, 1654225242) \ + V(_GrowableList, get:_capacity, GrowableList_getCapacity, 817090003) \ + V(_GrowableList, [], GrowableList_getIndexed, 1686777561) \ + V(_GrowableList, []=, GrowableList_setIndexed, 327404102) \ + V(_GrowableList, _setLength, GrowableList_setLength, 1227678442) \ + V(_GrowableList, _setData, GrowableList_setData, 1375509957) \ + V(_GrowableList, add, GrowableList_add, 996912766) \ + V(_ImmutableList, [], ImmutableList_getIndexed, 25983597) \ + V(_ImmutableList, get:length, ImmutableList_getLength, 578733070) \ V(Object, ==, Object_equal, 936042315) \ V(_StringBase, get:hashCode, String_getHashCode, 654543028) \ V(_StringBase, get:isEmpty, String_getIsEmpty, 879849436) \
diff --git a/runtime/vm/intrinsifier_arm.cc b/runtime/vm/intrinsifier_arm.cc index 734b889..8770677 100644 --- a/runtime/vm/intrinsifier_arm.cc +++ b/runtime/vm/intrinsifier_arm.cc
@@ -20,7 +20,7 @@ #define __ assembler-> -void Intrinsifier::ObjectArray_Allocate(Assembler* assembler) { +void Intrinsifier::List_Allocate(Assembler* assembler) { const intptr_t kTypeArgumentsOffset = 1 * kWordSize; const intptr_t kArrayLengthOffset = 0 * kWordSize; Label fall_through; @@ -133,7 +133,7 @@ } -void Intrinsifier::ImmutableArray_getLength(Assembler* assembler) { +void Intrinsifier::ImmutableList_getLength(Assembler* assembler) { return Array_getLength(assembler); } @@ -160,7 +160,7 @@ } -void Intrinsifier::ImmutableArray_getIndexed(Assembler* assembler) { +void Intrinsifier::ImmutableList_getIndexed(Assembler* assembler) { return Array_getIndexed(assembler); } @@ -168,7 +168,7 @@ static intptr_t ComputeObjectArrayTypeArgumentsOffset() { const Library& core_lib = Library::Handle(Library::CoreLibrary()); const Class& cls = Class::Handle( - core_lib.LookupClassAllowPrivate(Symbols::ObjectArray())); + core_lib.LookupClassAllowPrivate(Symbols::_List())); ASSERT(!cls.IsNull()); ASSERT(cls.HasTypeArguments()); ASSERT(cls.NumTypeArguments() == 1); @@ -247,7 +247,7 @@ // Allocate a GrowableObjectArray using the backing array specified. // On stack: type argument (+1), data (+0). -void Intrinsifier::GrowableArray_Allocate(Assembler* assembler) { +void Intrinsifier::GrowableList_Allocate(Assembler* assembler) { // The newly allocated object is returned in R0. const intptr_t kTypeArgumentsOffset = 1 * kWordSize; const intptr_t kArrayOffset = 0 * kWordSize; @@ -313,14 +313,14 @@ } -void Intrinsifier::GrowableArray_getLength(Assembler* assembler) { +void Intrinsifier::GrowableList_getLength(Assembler* assembler) { __ ldr(R0, Address(SP, 0 * kWordSize)); __ ldr(R0, FieldAddress(R0, GrowableObjectArray::length_offset())); __ Ret(); } -void Intrinsifier::GrowableArray_getCapacity(Assembler* assembler) { +void Intrinsifier::GrowableList_getCapacity(Assembler* assembler) { __ ldr(R0, Address(SP, 0 * kWordSize)); __ ldr(R0, FieldAddress(R0, GrowableObjectArray::data_offset())); __ ldr(R0, FieldAddress(R0, Array::length_offset())); @@ -328,7 +328,7 @@ } -void Intrinsifier::GrowableArray_getIndexed(Assembler* assembler) { +void Intrinsifier::GrowableList_getIndexed(Assembler* assembler) { Label fall_through; __ ldr(R0, Address(SP, + 0 * kWordSize)); // Index @@ -353,7 +353,7 @@ // Set value into growable object array at specified index. // On stack: growable array (+2), index (+1), value (+0). -void Intrinsifier::GrowableArray_setIndexed(Assembler* assembler) { +void Intrinsifier::GrowableList_setIndexed(Assembler* assembler) { if (FLAG_enable_type_checks) { return; } @@ -383,7 +383,7 @@ // Set length of growable object array. The length cannot // be greater than the length of the data container. // On stack: growable array (+1), length (+0). -void Intrinsifier::GrowableArray_setLength(Assembler* assembler) { +void Intrinsifier::GrowableList_setLength(Assembler* assembler) { __ ldr(R0, Address(SP, 1 * kWordSize)); // Growable array. __ ldr(R1, Address(SP, 0 * kWordSize)); // Length value. __ tst(R1, ShifterOperand(kSmiTagMask)); // Check for Smi. @@ -395,7 +395,7 @@ // Set data of growable object array. // On stack: growable array (+1), data (+0). -void Intrinsifier::GrowableArray_setData(Assembler* assembler) { +void Intrinsifier::GrowableList_setData(Assembler* assembler) { if (FLAG_enable_type_checks) { return; } @@ -418,7 +418,7 @@ // Add an element to growable array if it doesn't need to grow, otherwise // call into regular code. // On stack: growable array (+1), value (+0). -void Intrinsifier::GrowableArray_add(Assembler* assembler) { +void Intrinsifier::GrowableList_add(Assembler* assembler) { // In checked mode we need to type-check the incoming argument. if (FLAG_enable_type_checks) return; Label fall_through;
diff --git a/runtime/vm/intrinsifier_ia32.cc b/runtime/vm/intrinsifier_ia32.cc index 64758e6..f9634c8 100644 --- a/runtime/vm/intrinsifier_ia32.cc +++ b/runtime/vm/intrinsifier_ia32.cc
@@ -28,7 +28,7 @@ #define __ assembler-> -void Intrinsifier::ObjectArray_Allocate(Assembler* assembler) { +void Intrinsifier::List_Allocate(Assembler* assembler) { // This snippet of inlined code uses the following registers: // EAX, EBX, EDI // and the newly allocated object is returned in EAX. @@ -142,7 +142,7 @@ } -void Intrinsifier::ImmutableArray_getLength(Assembler* assembler) { +void Intrinsifier::ImmutableList_getLength(Assembler* assembler) { return Array_getLength(assembler); } @@ -165,7 +165,7 @@ } -void Intrinsifier::ImmutableArray_getIndexed(Assembler* assembler) { +void Intrinsifier::ImmutableList_getIndexed(Assembler* assembler) { return Array_getIndexed(assembler); } @@ -173,7 +173,7 @@ static intptr_t ComputeObjectArrayTypeArgumentsOffset() { const Library& core_lib = Library::Handle(Library::CoreLibrary()); const Class& cls = Class::Handle( - core_lib.LookupClassAllowPrivate(Symbols::ObjectArray())); + core_lib.LookupClassAllowPrivate(Symbols::_List())); ASSERT(!cls.IsNull()); ASSERT(cls.HasTypeArguments()); ASSERT(cls.NumTypeArguments() == 1); @@ -245,7 +245,7 @@ // Allocate a GrowableObjectArray using the backing array specified. // On stack: type argument (+2), data (+1), return-address (+0). -void Intrinsifier::GrowableArray_Allocate(Assembler* assembler) { +void Intrinsifier::GrowableList_Allocate(Assembler* assembler) { // This snippet of inlined code uses the following registers: // EAX, EBX // and the newly allocated object is returned in EAX. @@ -312,7 +312,7 @@ // Get length of growable object array. // On stack: growable array (+1), return-address (+0). -void Intrinsifier::GrowableArray_getLength(Assembler* assembler) { +void Intrinsifier::GrowableList_getLength(Assembler* assembler) { __ movl(EAX, Address(ESP, + 1 * kWordSize)); __ movl(EAX, FieldAddress(EAX, GrowableObjectArray::length_offset())); __ ret(); @@ -321,7 +321,7 @@ // Get capacity of growable object array. // On stack: growable array (+1), return-address (+0). -void Intrinsifier::GrowableArray_getCapacity(Assembler* assembler) { +void Intrinsifier::GrowableList_getCapacity(Assembler* assembler) { __ movl(EAX, Address(ESP, + 1 * kWordSize)); __ movl(EAX, FieldAddress(EAX, GrowableObjectArray::data_offset())); __ movl(EAX, FieldAddress(EAX, Array::length_offset())); @@ -331,7 +331,7 @@ // Access growable object array at specified index. // On stack: growable array (+2), index (+1), return-address (+0). -void Intrinsifier::GrowableArray_getIndexed(Assembler* assembler) { +void Intrinsifier::GrowableList_getIndexed(Assembler* assembler) { Label fall_through; __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Index. __ movl(EAX, Address(ESP, + 2 * kWordSize)); // GrowableArray. @@ -353,7 +353,7 @@ // Set value into growable object array at specified index. // On stack: growable array (+3), index (+2), value (+1), return-address (+0). -void Intrinsifier::GrowableArray_setIndexed(Assembler* assembler) { +void Intrinsifier::GrowableList_setIndexed(Assembler* assembler) { if (FLAG_enable_type_checks) { return; } @@ -381,7 +381,7 @@ // Set length of growable object array. The length cannot // be greater than the length of the data container. // On stack: growable array (+2), length (+1), return-address (+0). -void Intrinsifier::GrowableArray_setLength(Assembler* assembler) { +void Intrinsifier::GrowableList_setLength(Assembler* assembler) { Label fall_through; __ movl(EAX, Address(ESP, + 2 * kWordSize)); // Growable array. __ movl(EBX, Address(ESP, + 1 * kWordSize)); // Length value. @@ -395,7 +395,7 @@ // Set data of growable object array. // On stack: growable array (+2), data (+1), return-address (+0). -void Intrinsifier::GrowableArray_setData(Assembler* assembler) { +void Intrinsifier::GrowableList_setData(Assembler* assembler) { if (FLAG_enable_type_checks) { return; } @@ -418,7 +418,7 @@ // Add an element to growable array if it doesn't need to grow, otherwise // call into regular code. // On stack: growable array (+2), value (+1), return-address (+0). -void Intrinsifier::GrowableArray_add(Assembler* assembler) { +void Intrinsifier::GrowableList_add(Assembler* assembler) { // In checked mode we need to type-check the incoming argument. if (FLAG_enable_type_checks) return;
diff --git a/runtime/vm/intrinsifier_mips.cc b/runtime/vm/intrinsifier_mips.cc index de39ced8..3a12f24 100644 --- a/runtime/vm/intrinsifier_mips.cc +++ b/runtime/vm/intrinsifier_mips.cc
@@ -20,7 +20,7 @@ #define __ assembler-> -void Intrinsifier::ObjectArray_Allocate(Assembler* assembler) { +void Intrinsifier::List_Allocate(Assembler* assembler) { const intptr_t kTypeArgumentsOffset = 1 * kWordSize; const intptr_t kArrayLengthOffset = 0 * kWordSize; Label fall_through; @@ -140,7 +140,7 @@ } -void Intrinsifier::ImmutableArray_getLength(Assembler* assembler) { +void Intrinsifier::ImmutableList_getLength(Assembler* assembler) { return Array_getLength(assembler); } @@ -168,7 +168,7 @@ } -void Intrinsifier::ImmutableArray_getIndexed(Assembler* assembler) { +void Intrinsifier::ImmutableList_getIndexed(Assembler* assembler) { return Array_getIndexed(assembler); } @@ -176,7 +176,7 @@ static intptr_t ComputeObjectArrayTypeArgumentsOffset() { const Library& core_lib = Library::Handle(Library::CoreLibrary()); const Class& cls = Class::Handle( - core_lib.LookupClassAllowPrivate(Symbols::ObjectArray())); + core_lib.LookupClassAllowPrivate(Symbols::_List())); ASSERT(!cls.IsNull()); ASSERT(cls.HasTypeArguments()); ASSERT(cls.NumTypeArguments() == 1); @@ -252,7 +252,7 @@ // Allocate a GrowableObjectArray using the backing array specified. // On stack: type argument (+1), data (+0). -void Intrinsifier::GrowableArray_Allocate(Assembler* assembler) { +void Intrinsifier::GrowableList_Allocate(Assembler* assembler) { // The newly allocated object is returned in V0. const intptr_t kTypeArgumentsOffset = 1 * kWordSize; const intptr_t kArrayOffset = 0 * kWordSize; @@ -317,7 +317,7 @@ } -void Intrinsifier::GrowableArray_getLength(Assembler* assembler) { +void Intrinsifier::GrowableList_getLength(Assembler* assembler) { __ lw(V0, Address(SP, 0 * kWordSize)); __ Ret(); __ delay_slot()->lw(V0, @@ -325,7 +325,7 @@ } -void Intrinsifier::GrowableArray_getCapacity(Assembler* assembler) { +void Intrinsifier::GrowableList_getCapacity(Assembler* assembler) { __ lw(V0, Address(SP, 0 * kWordSize)); __ lw(V0, FieldAddress(V0, GrowableObjectArray::data_offset())); __ Ret(); @@ -333,7 +333,7 @@ } -void Intrinsifier::GrowableArray_getIndexed(Assembler* assembler) { +void Intrinsifier::GrowableList_getIndexed(Assembler* assembler) { Label fall_through; __ lw(T0, Address(SP, 0 * kWordSize)); // Index @@ -360,7 +360,7 @@ // Set value into growable object array at specified index. // On stack: growable array (+2), index (+1), value (+0). -void Intrinsifier::GrowableArray_setIndexed(Assembler* assembler) { +void Intrinsifier::GrowableList_setIndexed(Assembler* assembler) { if (FLAG_enable_type_checks) { return; } @@ -390,7 +390,7 @@ // Set length of growable object array. The length cannot // be greater than the length of the data container. // On stack: growable array (+1), length (+0). -void Intrinsifier::GrowableArray_setLength(Assembler* assembler) { +void Intrinsifier::GrowableList_setLength(Assembler* assembler) { Label fall_through; __ lw(T1, Address(SP, 0 * kWordSize)); // Length value. __ andi(CMPRES, T1, Immediate(kSmiTagMask)); @@ -405,7 +405,7 @@ // Set data of growable object array. // On stack: growable array (+1), data (+0). -void Intrinsifier::GrowableArray_setData(Assembler* assembler) { +void Intrinsifier::GrowableList_setData(Assembler* assembler) { if (FLAG_enable_type_checks) { return; } @@ -428,7 +428,7 @@ // Add an element to growable array if it doesn't need to grow, otherwise // call into regular code. // On stack: growable array (+1), value (+0). -void Intrinsifier::GrowableArray_add(Assembler* assembler) { +void Intrinsifier::GrowableList_add(Assembler* assembler) { // In checked mode we need to type-check the incoming argument. if (FLAG_enable_type_checks) return; Label fall_through;
diff --git a/runtime/vm/intrinsifier_x64.cc b/runtime/vm/intrinsifier_x64.cc index 83180be..e976fd5 100644 --- a/runtime/vm/intrinsifier_x64.cc +++ b/runtime/vm/intrinsifier_x64.cc
@@ -27,7 +27,7 @@ #define __ assembler-> -void Intrinsifier::ObjectArray_Allocate(Assembler* assembler) { +void Intrinsifier::List_Allocate(Assembler* assembler) { // This snippet of inlined code uses the following registers: // RAX, RCX, RDI, R13 // and the newly allocated object is returned in RAX. @@ -141,7 +141,7 @@ } -void Intrinsifier::ImmutableArray_getLength(Assembler* assembler) { +void Intrinsifier::ImmutableList_getLength(Assembler* assembler) { return Array_getLength(assembler); } @@ -164,7 +164,7 @@ } -void Intrinsifier::ImmutableArray_getIndexed(Assembler* assembler) { +void Intrinsifier::ImmutableList_getIndexed(Assembler* assembler) { return Array_getIndexed(assembler); } @@ -197,7 +197,7 @@ // Allocate a GrowableObjectArray using the backing array specified. // On stack: type argument (+2), data (+1), return-address (+0). -void Intrinsifier::GrowableArray_Allocate(Assembler* assembler) { +void Intrinsifier::GrowableList_Allocate(Assembler* assembler) { // This snippet of inlined code uses the following registers: // RAX, RCX, R13 // and the newly allocated object is returned in RAX. @@ -267,14 +267,14 @@ // Get length of growable object array. // On stack: growable array (+1), return-address (+0). -void Intrinsifier::GrowableArray_getLength(Assembler* assembler) { +void Intrinsifier::GrowableList_getLength(Assembler* assembler) { __ movq(RAX, Address(RSP, + 1 * kWordSize)); __ movq(RAX, FieldAddress(RAX, GrowableObjectArray::length_offset())); __ ret(); } -void Intrinsifier::GrowableArray_getCapacity(Assembler* assembler) { +void Intrinsifier::GrowableList_getCapacity(Assembler* assembler) { __ movq(RAX, Address(RSP, + 1 * kWordSize)); __ movq(RAX, FieldAddress(RAX, GrowableObjectArray::data_offset())); __ movq(RAX, FieldAddress(RAX, Array::length_offset())); @@ -284,7 +284,7 @@ // Access growable object array at specified index. // On stack: growable array (+2), index (+1), return-address (+0). -void Intrinsifier::GrowableArray_getIndexed(Assembler* assembler) { +void Intrinsifier::GrowableList_getIndexed(Assembler* assembler) { Label fall_through; __ movq(RCX, Address(RSP, + 1 * kWordSize)); // Index. __ movq(RAX, Address(RSP, + 2 * kWordSize)); // GrowableArray. @@ -306,7 +306,7 @@ // Set value into growable object array at specified index. // On stack: growable array (+3), index (+2), value (+1), return-address (+0). -void Intrinsifier::GrowableArray_setIndexed(Assembler* assembler) { +void Intrinsifier::GrowableList_setIndexed(Assembler* assembler) { if (FLAG_enable_type_checks) { return; } @@ -334,7 +334,7 @@ // Set length of growable object array. The length cannot // be greater than the length of the data container. // On stack: growable array (+2), length (+1), return-address (+0). -void Intrinsifier::GrowableArray_setLength(Assembler* assembler) { +void Intrinsifier::GrowableList_setLength(Assembler* assembler) { Label fall_through; __ movq(RAX, Address(RSP, + 2 * kWordSize)); // Growable array. __ movq(RCX, Address(RSP, + 1 * kWordSize)); // Length value. @@ -348,7 +348,7 @@ // Set data of growable object array. // On stack: growable array (+2), data (+1), return-address (+0). -void Intrinsifier::GrowableArray_setData(Assembler* assembler) { +void Intrinsifier::GrowableList_setData(Assembler* assembler) { if (FLAG_enable_type_checks) { return; } @@ -370,7 +370,7 @@ // Add an element to growable array if it doesn't need to grow, otherwise // call into regular code. // On stack: growable array (+2), value (+1), return-address (+0). -void Intrinsifier::GrowableArray_add(Assembler* assembler) { +void Intrinsifier::GrowableList_add(Assembler* assembler) { // In checked mode we need to check the incoming argument. if (FLAG_enable_type_checks) return; Label fall_through; @@ -1101,7 +1101,8 @@ __ TryAllocate(double_class, &fall_through, Assembler::kNearJump, - RAX); // Result register. + RAX, // Result register. + kNoRegister); // Pool pointer might not be loaded. __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0); __ ret(); __ Bind(&fall_through); @@ -1145,7 +1146,8 @@ __ TryAllocate(double_class, &fall_through, Assembler::kNearJump, - RAX); // Result register. + RAX, // Result register. + kNoRegister); // Pool pointer might not be loaded. __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0); __ ret(); __ Bind(&fall_through); @@ -1166,7 +1168,8 @@ __ TryAllocate(double_class, &fall_through, Assembler::kNearJump, - RAX); // Result register. + RAX, // Result register. + kNoRegister); // Pool pointer might not be loaded. __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0); __ ret(); __ Bind(&fall_through); @@ -1236,7 +1239,8 @@ __ TryAllocate(double_class, &alloc_failed, Assembler::kNearJump, - RAX); // Result register. + RAX, // Result register. + kNoRegister); // Pool pointer might not be loaded. __ fstpl(FieldAddress(RAX, Double::value_offset())); __ ret(); @@ -1283,7 +1287,8 @@ __ TryAllocate(double_class, &fall_through, Assembler::kNearJump, - RAX); // Result register. + RAX, // Result register. + kNoRegister); // Pool pointer might not be loaded. __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0); __ ret(); __ Bind(&is_smi);
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc index 5d12dc6..0e6ad03 100644 --- a/runtime/vm/isolate.cc +++ b/runtime/vm/isolate.cc
@@ -14,6 +14,7 @@ #include "vm/dart_api_state.h" #include "vm/dart_entry.h" #include "vm/debugger.h" +#include "vm/deopt_instructions.h" #include "vm/heap.h" #include "vm/heap_histogram.h" #include "vm/message_handler.h" @@ -38,7 +39,6 @@ "Track function usage and report."); DEFINE_FLAG(bool, trace_isolates, false, "Trace isolate creation and shut down."); -DECLARE_FLAG(bool, trace_deoptimization_verbose); void Isolate::RegisterClass(const Class& cls) { @@ -270,113 +270,6 @@ #endif -void DeferredDouble::Materialize() { - RawDouble** double_slot = reinterpret_cast<RawDouble**>(slot()); - *double_slot = Double::New(value()); - - if (FLAG_trace_deoptimization_verbose) { - OS::PrintErr("materializing double at %" Px ": %g\n", - reinterpret_cast<uword>(slot()), value()); - } -} - - -void DeferredMint::Materialize() { - RawMint** mint_slot = reinterpret_cast<RawMint**>(slot()); - ASSERT(!Smi::IsValid64(value())); - Mint& mint = Mint::Handle(); - mint ^= Integer::New(value()); - *mint_slot = mint.raw(); - - if (FLAG_trace_deoptimization_verbose) { - OS::PrintErr("materializing mint at %" Px ": %" Pd64 "\n", - reinterpret_cast<uword>(slot()), value()); - } -} - - -void DeferredFloat32x4::Materialize() { - RawFloat32x4** float32x4_slot = reinterpret_cast<RawFloat32x4**>(slot()); - RawFloat32x4* raw_float32x4 = Float32x4::New(value()); - *float32x4_slot = raw_float32x4; - - if (FLAG_trace_deoptimization_verbose) { - float x = raw_float32x4->x(); - float y = raw_float32x4->y(); - float z = raw_float32x4->z(); - float w = raw_float32x4->w(); - OS::PrintErr("materializing Float32x4 at %" Px ": %g,%g,%g,%g\n", - reinterpret_cast<uword>(slot()), x, y, z, w); - } -} - - -void DeferredUint32x4::Materialize() { - RawUint32x4** uint32x4_slot = reinterpret_cast<RawUint32x4**>(slot()); - RawUint32x4* raw_uint32x4 = Uint32x4::New(value()); - *uint32x4_slot = raw_uint32x4; - - if (FLAG_trace_deoptimization_verbose) { - uint32_t x = raw_uint32x4->x(); - uint32_t y = raw_uint32x4->y(); - uint32_t z = raw_uint32x4->z(); - uint32_t w = raw_uint32x4->w(); - OS::PrintErr("materializing Uint32x4 at %" Px ": %x,%x,%x,%x\n", - reinterpret_cast<uword>(slot()), x, y, z, w); - } -} - - -void DeferredObjectRef::Materialize() { - DeferredObject* obj = Isolate::Current()->GetDeferredObject(index()); - *slot() = obj->object(); - if (FLAG_trace_deoptimization_verbose) { - OS::PrintErr("writing instance ref at %" Px ": %s\n", - reinterpret_cast<uword>(slot()), - Instance::Handle(obj->object()).ToCString()); - } -} - - -RawInstance* DeferredObject::object() { - if (object_ == NULL) { - Materialize(); - } - return object_->raw(); -} - - -void DeferredObject::Materialize() { - Class& cls = Class::Handle(); - cls ^= GetClass(); - - if (FLAG_trace_deoptimization_verbose) { - OS::PrintErr("materializing instance of %s (%" Px ", %" Pd " fields)\n", - cls.ToCString(), - reinterpret_cast<uword>(args_), - field_count_); - } - - const Instance& obj = Instance::ZoneHandle(Instance::New(cls)); - - Field& field = Field::Handle(); - Object& value = Object::Handle(); - for (intptr_t i = 0; i < field_count_; i++) { - field ^= GetField(i); - value = GetValue(i); - obj.SetField(field, value); - - if (FLAG_trace_deoptimization_verbose) { - OS::PrintErr(" %s <- %s\n", - String::Handle(field.name()).ToCString(), - value.ToCString()); - } - } - - object_ = &obj; -} - - #define REUSABLE_HANDLE_INITIALIZERS(object) \ object##_handle_(NULL), @@ -409,14 +302,7 @@ gc_prologue_callbacks_(), gc_epilogue_callbacks_(), defer_finalization_count_(0), - deopt_cpu_registers_copy_(NULL), - deopt_fpu_registers_copy_(NULL), - deopt_frame_copy_(NULL), - deopt_frame_copy_size_(0), - deferred_boxes_(NULL), - deferred_object_refs_(NULL), - deferred_objects_count_(0), - deferred_objects_(NULL), + deopt_context_(NULL), stacktrace_(NULL), stack_frame_index_(-1), object_histogram_(NULL), @@ -444,6 +330,7 @@ mutex_ = NULL; // Fail fast if interrupts are scheduled on a dead isolate. delete message_handler_; message_handler_ = NULL; // Fail fast if we send messages to a dead isolate. + ASSERT(deopt_context_ == NULL); // No deopt in progress when isolate deleted. delete object_histogram_; } @@ -864,6 +751,11 @@ // Visit objects in the debugger. debugger()->VisitObjectPointers(visitor); + + // Visit objects that are being used for deoptimization. + if (deopt_context() != NULL) { + deopt_context()->VisitObjectPointers(visitor); + } } @@ -1079,31 +971,6 @@ } -static void FillDeferredSlots(DeferredSlot** slot_list) { - DeferredSlot* slot = *slot_list; - *slot_list = NULL; - - while (slot != NULL) { - DeferredSlot* current = slot; - slot = slot->next(); - - current->Materialize(); - - delete current; - } -} - - -void Isolate::MaterializeDeferredBoxes() { - FillDeferredSlots(&deferred_boxes_); -} - - -void Isolate::MaterializeDeferredObjects() { - FillDeferredSlots(&deferred_object_refs_); -} - - static char* GetRootScriptUri(Isolate* isolate) { const Library& library = Library::Handle(isolate->object_store()->root_library());
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h index 7a71eb4..128f7e2 100644 --- a/runtime/vm/isolate.h +++ b/runtime/vm/isolate.h
@@ -25,6 +25,7 @@ class Class; class CodeIndexTable; class Debugger; +class DeoptContext; class Field; class Function; class HandleScope; @@ -58,174 +59,6 @@ class ObjectIdRing; -// Used by the deoptimization infrastructure to defer allocation of unboxed -// objects until frame is fully rewritten and GC is safe. -// Describes a stack slot that should be populated with a reference to the -// materialized object. -class DeferredSlot { - public: - DeferredSlot(RawInstance** slot, DeferredSlot* next) - : slot_(slot), next_(next) { } - virtual ~DeferredSlot() { } - - RawInstance** slot() const { return slot_; } - DeferredSlot* next() const { return next_; } - - virtual void Materialize() = 0; - - private: - RawInstance** const slot_; - DeferredSlot* const next_; - - DISALLOW_COPY_AND_ASSIGN(DeferredSlot); -}; - - -class DeferredDouble : public DeferredSlot { - public: - DeferredDouble(double value, RawInstance** slot, DeferredSlot* next) - : DeferredSlot(slot, next), value_(value) { } - - virtual void Materialize(); - - double value() const { return value_; } - - private: - const double value_; - - DISALLOW_COPY_AND_ASSIGN(DeferredDouble); -}; - - -class DeferredMint : public DeferredSlot { - public: - DeferredMint(int64_t value, RawInstance** slot, DeferredSlot* next) - : DeferredSlot(slot, next), value_(value) { } - - virtual void Materialize(); - - int64_t value() const { return value_; } - - private: - const int64_t value_; - - DISALLOW_COPY_AND_ASSIGN(DeferredMint); -}; - - -class DeferredFloat32x4 : public DeferredSlot { - public: - DeferredFloat32x4(simd128_value_t value, RawInstance** slot, - DeferredSlot* next) - : DeferredSlot(slot, next), value_(value) { } - - virtual void Materialize(); - - simd128_value_t value() const { return value_; } - - private: - const simd128_value_t value_; - - DISALLOW_COPY_AND_ASSIGN(DeferredFloat32x4); -}; - - -class DeferredUint32x4 : public DeferredSlot { - public: - DeferredUint32x4(simd128_value_t value, RawInstance** slot, - DeferredSlot* next) - : DeferredSlot(slot, next), value_(value) { } - - virtual void Materialize(); - - simd128_value_t value() const { return value_; } - - private: - const simd128_value_t value_; - - DISALLOW_COPY_AND_ASSIGN(DeferredUint32x4); -}; - - -// Describes a slot that contains a reference to an object that had its -// allocation removed by AllocationSinking pass. -// Object itself is described and materialized by DeferredObject. -class DeferredObjectRef : public DeferredSlot { - public: - DeferredObjectRef(intptr_t index, RawInstance** slot, DeferredSlot* next) - : DeferredSlot(slot, next), index_(index) { } - - virtual void Materialize(); - - intptr_t index() const { return index_; } - - private: - const intptr_t index_; - - DISALLOW_COPY_AND_ASSIGN(DeferredObjectRef); -}; - - -// Describes an object which allocation was removed by AllocationSinking pass. -// Arguments for materialization are stored as a part of expression stack -// for the bottommost deoptimized frame so that GC could discover them. -// They will be removed from the stack at the very end of deoptimization. -class DeferredObject { - public: - DeferredObject(intptr_t field_count, intptr_t* args) - : field_count_(field_count), - args_(reinterpret_cast<RawObject**>(args)), - object_(NULL) { } - - intptr_t ArgumentCount() const { - return kFieldsStartIndex + kFieldEntrySize * field_count_; - } - - RawInstance* object(); - - private: - enum { - kClassIndex = 0, - kFieldsStartIndex = kClassIndex + 1 - }; - - enum { - kFieldIndex = 0, - kValueIndex, - kFieldEntrySize, - }; - - // Materializes the object. Returns amount of values that were consumed - // and should be removed from the expression stack at the very end of - // deoptimization. - void Materialize(); - - RawObject* GetClass() const { - return args_[kClassIndex]; - } - - RawObject* GetField(intptr_t index) const { - return args_[kFieldsStartIndex + kFieldEntrySize * index + kFieldIndex]; - } - - RawObject* GetValue(intptr_t index) const { - return args_[kFieldsStartIndex + kFieldEntrySize * index + kValueIndex]; - } - - // Amount of fields that have to be initialized. - const intptr_t field_count_; - - // Pointer to the first materialization argument on the stack. - // The first argument is Class of the instance to materialize followed by - // Field, value pairs. - RawObject** args_; - - // Object materialized from this description. - const Instance* object_; - - DISALLOW_COPY_AND_ASSIGN(DeferredObject); -}; - #define REUSABLE_HANDLE_LIST(V) \ V(Object) \ V(Array) \ @@ -503,29 +336,6 @@ return file_close_callback_; } - intptr_t* deopt_cpu_registers_copy() const { - return deopt_cpu_registers_copy_; - } - void set_deopt_cpu_registers_copy(intptr_t* value) { - ASSERT((value == NULL) || (deopt_cpu_registers_copy_ == NULL)); - deopt_cpu_registers_copy_ = value; - } - fpu_register_t* deopt_fpu_registers_copy() const { - return deopt_fpu_registers_copy_; - } - void set_deopt_fpu_registers_copy(fpu_register_t* value) { - ASSERT((value == NULL) || (deopt_fpu_registers_copy_ == NULL)); - deopt_fpu_registers_copy_ = value; - } - intptr_t* deopt_frame_copy() const { return deopt_frame_copy_; } - void SetDeoptFrameCopy(intptr_t* value, intptr_t size) { - ASSERT((value == NULL) || (size > 0)); - ASSERT((value == NULL) || (deopt_frame_copy_ == NULL)); - deopt_frame_copy_ = value; - deopt_frame_copy_size_ = size; - } - intptr_t deopt_frame_copy_size() const { return deopt_frame_copy_size_; } - void set_object_id_ring(ObjectIdRing* ring) { object_id_ring_ = ring; } @@ -533,79 +343,12 @@ return object_id_ring_; } - void PrepareForDeferredMaterialization(intptr_t count) { - if (count > 0) { - deferred_objects_ = new DeferredObject*[count]; - deferred_objects_count_ = count; - } + DeoptContext* deopt_context() const { return deopt_context_; } + void set_deopt_context(DeoptContext* value) { + ASSERT(value == NULL || deopt_context_ == NULL); + deopt_context_ = value; } - void DeleteDeferredObjects() { - for (intptr_t i = 0; i < deferred_objects_count_; i++) { - delete deferred_objects_[i]; - } - delete[] deferred_objects_; - deferred_objects_ = NULL; - deferred_objects_count_ = 0; - } - - DeferredObject* GetDeferredObject(intptr_t idx) const { - return deferred_objects_[idx]; - } - - void SetDeferredObjectAt(intptr_t idx, DeferredObject* object) { - deferred_objects_[idx] = object; - } - - intptr_t DeferredObjectsCount() const { - return deferred_objects_count_; - } - - void DeferMaterializedObjectRef(intptr_t idx, intptr_t* slot) { - deferred_object_refs_ = new DeferredObjectRef( - idx, - reinterpret_cast<RawInstance**>(slot), - deferred_object_refs_); - } - - void DeferDoubleMaterialization(double value, RawDouble** slot) { - deferred_boxes_ = new DeferredDouble( - value, - reinterpret_cast<RawInstance**>(slot), - deferred_boxes_); - } - - void DeferMintMaterialization(int64_t value, RawMint** slot) { - deferred_boxes_ = new DeferredMint( - value, - reinterpret_cast<RawInstance**>(slot), - deferred_boxes_); - } - - void DeferFloat32x4Materialization(simd128_value_t value, - RawFloat32x4** slot) { - deferred_boxes_ = new DeferredFloat32x4( - value, - reinterpret_cast<RawInstance**>(slot), - deferred_boxes_); - } - - void DeferUint32x4Materialization(simd128_value_t value, - RawUint32x4** slot) { - deferred_boxes_ = new DeferredUint32x4( - value, - reinterpret_cast<RawInstance**>(slot), - deferred_boxes_); - } - - // Populate all deferred slots that contain boxes for double, mint, simd - // values. - void MaterializeDeferredBoxes(); - - // Populate all slots containing references to objects which allocations - // were eliminated by AllocationSinking pass. - void MaterializeDeferredObjects(); - static char* GetStatus(const char* request); intptr_t BlockClassFinalization() { @@ -668,17 +411,7 @@ GcPrologueCallbacks gc_prologue_callbacks_; GcEpilogueCallbacks gc_epilogue_callbacks_; intptr_t defer_finalization_count_; - - // Deoptimization support. - intptr_t* deopt_cpu_registers_copy_; - fpu_register_t* deopt_fpu_registers_copy_; - intptr_t* deopt_frame_copy_; - intptr_t deopt_frame_copy_size_; - DeferredSlot* deferred_boxes_; - DeferredSlot* deferred_object_refs_; - - intptr_t deferred_objects_count_; - DeferredObject** deferred_objects_; + DeoptContext* deopt_context_; // Status support. char* stacktrace_;
diff --git a/runtime/vm/native_arguments.h b/runtime/vm/native_arguments.h index 20335cc..72a4833 100644 --- a/runtime/vm/native_arguments.h +++ b/runtime/vm/native_arguments.h
@@ -87,46 +87,34 @@ Isolate* isolate() const { return isolate_; } int ArgCount() const { return ArgcBits::decode(argc_tag_); } - // Returns true if the arguments are those of an instance function call. - bool ToInstanceFunction() const { - return InstanceFunctionBit::decode(argc_tag_); - } - - // Returns true if the arguments are those of a closure function call. - bool ToClosureFunction() const { - return ClosureFunctionBit::decode(argc_tag_); - } - RawObject* ArgAt(int index) const { ASSERT((index >= 0) && (index < ArgCount())); return (*argv_)[-index]; } - int NumHiddenArgs() const { - // For static closure functions, the closure at index 0 is hidden. - // In the instance closure function case, the receiver is accessed from - // the context and the closure at index 0 is hidden, so the apparent - // argument count remains unchanged. - if (ToClosureFunction() && !ToInstanceFunction()) { - return 1; - } - return 0; + int NativeArgCount() const { + int function_bits = FunctionBits::decode(argc_tag_); + return ArgCount() - NumHiddenArgs(function_bits); } - int NativeArgCount() const { - return ArgCount() - NumHiddenArgs(); + RawObject* NativeArg0() const { + int function_bits = FunctionBits::decode(argc_tag_); + if (function_bits == (kClosureFunctionBit | kInstanceFunctionBit)) { + // Retrieve the receiver from the context. + const Context& context = Context::Handle(isolate_->top_context()); + return context.At(0); + } + return ArgAt(NumHiddenArgs(function_bits)); } RawObject* NativeArgAt(int index) const { ASSERT((index >= 0) && (index < NativeArgCount())); - if ((index == 0) && ToClosureFunction() && ToInstanceFunction()) { - // Retrieve the receiver from the context. - const Context& context = Context::Handle(isolate_->top_context()); - return context.At(0); - } else { - const int actual_index = index + NumHiddenArgs(); - return ArgAt(actual_index); + if (index == 0) { + return NativeArg0(); } + int function_bits = FunctionBits::decode(argc_tag_); + const int actual_index = index + NumHiddenArgs(function_bits); + return ArgAt(actual_index); } void SetReturn(const Object& value) const { @@ -162,21 +150,29 @@ ASSERT(function.is_native()); ASSERT(!function.IsConstructor()); // Not supported. int tag = ArgcBits::encode(function.NumParameters()); - tag = InstanceFunctionBit::update(!function.is_static(), tag); - tag = ClosureFunctionBit::update(function.IsClosureFunction(), tag); - return tag; + int function_bits = 0; + if (!function.is_static()) { + function_bits |= kInstanceFunctionBit; + } + if (function.IsClosureFunction()) { + function_bits |= kClosureFunctionBit; + } + return FunctionBits::update(function_bits, tag); } private: + enum { + kInstanceFunctionBit = 1, + kClosureFunctionBit = 2, + }; enum ArgcTagBits { kArgcBit = 0, kArgcSize = 24, - kInstanceFunctionBit = 24, - kClosureFunctionBit = 25, + kFunctionBit = 24, + kFunctionSize = 2, }; class ArgcBits : public BitField<int, kArgcBit, kArgcSize> {}; - class InstanceFunctionBit : public BitField<bool, kInstanceFunctionBit, 1> {}; - class ClosureFunctionBit : public BitField<bool, kClosureFunctionBit, 1> {}; + class FunctionBits : public BitField<int, kFunctionBit, kFunctionSize> {}; friend class Api; friend class BootstrapNatives; friend class Simulator; @@ -189,6 +185,27 @@ *retval_ = value; } + // Returns true if the arguments are those of an instance function call. + bool ToInstanceFunction() const { + return (FunctionBits::decode(argc_tag_) & kInstanceFunctionBit); + } + + // Returns true if the arguments are those of a closure function call. + bool ToClosureFunction() const { + return (FunctionBits::decode(argc_tag_) & kClosureFunctionBit); + } + + int NumHiddenArgs(int function_bits) const { + // For static closure functions, the closure at index 0 is hidden. + // In the instance closure function case, the receiver is accessed from + // the context and the closure at index 0 is hidden, so the apparent + // argument count remains unchanged. + if (function_bits == kClosureFunctionBit) { + return 1; + } + return 0; + } + Isolate* isolate_; // Current isolate pointer. int argc_tag_; // Encodes argument count and invoked native call type. RawObject*(*argv_)[]; // Pointer to an array of arguments to runtime call.
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc index 421ff4a..e25cbe9 100644 --- a/runtime/vm/object.cc +++ b/runtime/vm/object.cc
@@ -154,7 +154,7 @@ V(CoreLibrary, Object, _noSuchMethod) \ V(CoreLibrary, Object, _as) \ V(CoreLibrary, Object, _instanceOf) \ - V(CoreLibrary, _ObjectArray, _ObjectArray.) \ + V(CoreLibrary, _List, _List.) \ V(CoreLibrary, AssertionError, _throwNew) \ V(CoreLibrary, TypeError, _throwNew) \ V(CoreLibrary, FallThroughError, _throwNew) \ @@ -696,7 +696,7 @@ // Set up names for object array and one byte string class which are // pre-allocated in the vm isolate also. cls = Dart::vm_isolate()->object_store()->array_class(); - cls.set_name(Symbols::ObjectArray()); + cls.set_name(Symbols::_List()); cls = Dart::vm_isolate()->object_store()->one_byte_string_class(); cls.set_name(Symbols::OneByteString()); } @@ -876,7 +876,7 @@ // remaining classes and register them by name in the dictionaries. String& name = String::Handle(); cls = object_store->array_class(); // Was allocated above. - RegisterPrivateClass(cls, Symbols::ObjectArray(), core_lib); + RegisterPrivateClass(cls, Symbols::_List(), core_lib); pending_classes.Add(cls); // We cannot use NewNonParameterizedType(cls), because Array is parameterized. type ^= Type::New(Object::Handle(cls.raw()), @@ -887,7 +887,7 @@ object_store->set_array_type(type); cls = object_store->growable_object_array_class(); // Was allocated above. - RegisterPrivateClass(cls, Symbols::GrowableObjectArray(), core_lib); + RegisterPrivateClass(cls, Symbols::_GrowableList(), core_lib); pending_classes.Add(cls); cls = Class::New<Array>(kImmutableArrayCid); @@ -895,7 +895,7 @@ cls.set_type_arguments_field_offset(Array::type_arguments_offset()); ASSERT(object_store->immutable_array_class() != object_store->array_class()); cls.set_is_prefinalized(); - RegisterPrivateClass(cls, Symbols::ImmutableArray(), core_lib); + RegisterPrivateClass(cls, Symbols::_ImmutableList(), core_lib); pending_classes.Add(cls); cls = object_store->one_byte_string_class(); // Was allocated above. @@ -1175,9 +1175,12 @@ ClassFinalizer::VerifyBootstrapClasses(); MarkInvisibleFunctions(); - // Set up the intrinsic state of all functions (core, math and scalar list). + // Set up the intrinsic state of all functions (core, math and typed data). Intrinsifier::InitializeState(); + // Set up recognized state of all functions (core, math and typed data). + MethodRecognizer::InitializeState(); + return Error::null(); } @@ -4165,6 +4168,11 @@ } +void Function::set_is_recognized(bool value) const { + set_kind_tag(RecognizedBit::update(value, raw_ptr()->kind_tag_)); +} + + void Function::set_is_static(bool value) const { set_kind_tag(StaticBit::update(value, raw_ptr()->kind_tag_)); } @@ -4738,6 +4746,7 @@ result.set_is_external(is_external); result.set_is_visible(true); // Will be computed later. result.set_is_intrinsic(false); + result.set_is_recognized(false); result.set_owner(owner); result.set_token_pos(token_pos); result.set_end_token_pos(token_pos); @@ -6173,7 +6182,7 @@ } static const int kInitialTokenCount = 32; - static const intptr_t kTableSize = 128; + static const intptr_t kTableSize = 1024; uint8_t* buffer_; WriteStream stream_; @@ -8027,10 +8036,10 @@ -// Return Function::null() if function does not exist in lib. -static RawFunction* GetFunction(const GrowableArray<Library*>& libs, - const char* class_name, - const char* function_name) { +// Return Function::null() if function does not exist in libs. +RawFunction* Library::GetFunction(const GrowableArray<Library*>& libs, + const char* class_name, + const char* function_name) { Function& func = Function::Handle(); String& class_str = String::Handle(); String& func_str = String::Handle(); @@ -9833,7 +9842,6 @@ Array::Handle(arguments_descriptor()), deopt_id(), kNumArgsTested)); - result.set_deopt_reason(deopt_reason()); const intptr_t len = NumberOfChecks(); for (intptr_t i = 0; i < len; i++) { const intptr_t class_id = GetClassIdAt(i, arg_nr); @@ -9859,7 +9867,7 @@ } } // Copy deoptimization reason. - result.set_deopt_reason(this->deopt_reason()); + result.set_deopt_reason(deopt_reason()); return result.raw(); } @@ -13315,8 +13323,18 @@ if (str.IsOneByteString()) { return OneByteString::EscapeSpecialCharacters(str); } - ASSERT(str.IsTwoByteString()); - return TwoByteString::EscapeSpecialCharacters(str); + if (str.IsTwoByteString()) { + return TwoByteString::EscapeSpecialCharacters(str); + } + if (str.IsExternalOneByteString()) { + return ExternalOneByteString::EscapeSpecialCharacters(str); + } + ASSERT(str.IsExternalTwoByteString()); + // If EscapeSpecialCharacters is frequently called on external two byte + // strings, we should implement it directly on ExternalTwoByteString rather + // than first converting to a TwoByteString. + return TwoByteString::EscapeSpecialCharacters( + String::Handle(TwoByteString::New(str, Heap::kNew))); } @@ -13358,14 +13376,24 @@ RawString* String::ConcatAll(const Array& strings, Heap::Space space) { + return ConcatAllRange(strings, 0, strings.Length(), space); +} + + +RawString* String::ConcatAllRange(const Array& strings, + intptr_t start, + intptr_t end, + Heap::Space space) { ASSERT(!strings.IsNull()); + ASSERT(start >= 0); + ASSERT(end <= strings.Length()); intptr_t result_len = 0; - intptr_t strings_len = strings.Length(); String& str = String::Handle(); intptr_t char_size = kOneByteChar; - for (intptr_t i = 0; i < strings_len; i++) { + // Compute 'char_size' and 'result_len'. + for (intptr_t i = start; i < end; i++) { str ^= strings.At(i); - intptr_t str_len = str.Length(); + const intptr_t str_len = str.Length(); if ((kMaxElements - result_len) < str_len) { Isolate* isolate = Isolate::Current(); const Instance& exception = @@ -13377,10 +13405,10 @@ char_size = Utils::Maximum(char_size, str.CharSize()); } if (char_size == kOneByteChar) { - return OneByteString::ConcatAll(strings, result_len, space); + return OneByteString::ConcatAll(strings, start, end, result_len, space); } ASSERT(char_size == kTwoByteChar); - return TwoByteString::ConcatAll(strings, result_len, space); + return TwoByteString::ConcatAll(strings, start, end, result_len, space); } @@ -13721,7 +13749,6 @@ intptr_t len = str.Length(); if (len > 0) { intptr_t num_escapes = 0; - intptr_t index = 0; for (intptr_t i = 0; i < len; i++) { if (IsSpecialCharacter(*CharAddr(str, i))) { num_escapes += 1; @@ -13729,6 +13756,7 @@ } const String& dststr = String::Handle( OneByteString::New(len + num_escapes, Heap::kNew)); + intptr_t index = 0; for (intptr_t i = 0; i < len; i++) { if (IsSpecialCharacter(*CharAddr(str, i))) { *(CharAddr(dststr, index)) = '\\'; @@ -13741,7 +13769,36 @@ } return OneByteString::raw(dststr); } - return OneByteString::null(); + return OneByteString::raw(Symbols::Empty()); +} + +RawOneByteString* ExternalOneByteString::EscapeSpecialCharacters( + const String& str) { + intptr_t len = str.Length(); + if (len > 0) { + intptr_t num_escapes = 0; + for (intptr_t i = 0; i < len; i++) { + if (IsSpecialCharacter(*CharAddr(str, i))) { + num_escapes += 1; + } + } + const String& dststr = String::Handle( + OneByteString::New(len + num_escapes, Heap::kNew)); + intptr_t index = 0; + for (intptr_t i = 0; i < len; i++) { + if (IsSpecialCharacter(*CharAddr(str, i))) { + *(OneByteString::CharAddr(dststr, index)) = '\\'; + *(OneByteString::CharAddr(dststr, index + 1)) = + SpecialCharacter(*CharAddr(str, i)); + index += 2; + } else { + *(OneByteString::CharAddr(dststr, index)) = *CharAddr(str, i); + index += 1; + } + } + return OneByteString::raw(dststr); + } + return OneByteString::raw(Symbols::Empty()); } @@ -13842,15 +13899,19 @@ RawOneByteString* OneByteString::ConcatAll(const Array& strings, + intptr_t start, + intptr_t end, intptr_t len, Heap::Space space) { + ASSERT(!strings.IsNull()); + ASSERT(start >= 0); + ASSERT(end <= strings.Length()); const String& result = String::Handle(OneByteString::New(len, space)); String& str = String::Handle(); - intptr_t strings_len = strings.Length(); intptr_t pos = 0; - for (intptr_t i = 0; i < strings_len; i++) { + for (intptr_t i = start; i < end; i++) { str ^= strings.At(i); - intptr_t str_len = str.Length(); + const intptr_t str_len = str.Length(); String::Copy(result, pos, str, 0, str_len); ASSERT((kMaxElements - pos) >= str_len); pos += str_len; @@ -13918,7 +13979,6 @@ intptr_t len = str.Length(); if (len > 0) { intptr_t num_escapes = 0; - intptr_t index = 0; for (intptr_t i = 0; i < len; i++) { if (IsSpecialCharacter(*CharAddr(str, i))) { num_escapes += 1; @@ -13926,6 +13986,7 @@ } const String& dststr = String::Handle( TwoByteString::New(len + num_escapes, Heap::kNew)); + intptr_t index = 0; for (intptr_t i = 0; i < len; i++) { if (IsSpecialCharacter(*CharAddr(str, i))) { *(CharAddr(dststr, index)) = '\\'; @@ -13938,7 +13999,7 @@ } return TwoByteString::raw(dststr); } - return TwoByteString::null(); + return TwoByteString::New(0, Heap::kNew); } @@ -14024,15 +14085,19 @@ RawTwoByteString* TwoByteString::ConcatAll(const Array& strings, + intptr_t start, + intptr_t end, intptr_t len, Heap::Space space) { + ASSERT(!strings.IsNull()); + ASSERT(start >= 0); + ASSERT(end <= strings.Length()); const String& result = String::Handle(TwoByteString::New(len, space)); String& str = String::Handle(); - intptr_t strings_len = strings.Length(); intptr_t pos = 0; - for (intptr_t i = 0; i < strings_len; i++) { + for (intptr_t i = start; i < end; i++) { str ^= strings.At(i); - intptr_t str_len = str.Length(); + const intptr_t str_len = str.Length(); String::Copy(result, pos, str, 0, str_len); ASSERT((kMaxElements - pos) >= str_len); pos += str_len; @@ -14255,10 +14320,10 @@ const char* Array::ToCString() const { if (IsNull()) { - return IsImmutable() ? "ImmutableArray NULL" : "Array NULL"; + return IsImmutable() ? "_ImmutableList NULL" : "_List NULL"; } - const char* format = !IsImmutable() ? "Array len:%" Pd "" : - "Immutable Array len:%" Pd ""; + const char* format = IsImmutable() ? + "_ImmutableList len:%" Pd : "_List len:%" Pd; intptr_t len = OS::SNPrint(NULL, 0, format, Length()) + 1; char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); OS::SNPrint(chars, len, format, Length()); @@ -14466,9 +14531,9 @@ const char* GrowableObjectArray::ToCString() const { if (IsNull()) { - return "GrowableObjectArray NULL"; + return "_GrowableList NULL"; } - const char* format = "GrowableObjectArray len:%" Pd ""; + const char* format = "_GrowableList len:%" Pd ""; intptr_t len = OS::SNPrint(NULL, 0, format, Length()) + 1; char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); OS::SNPrint(chars, len, format, Length());
diff --git a/runtime/vm/object.h b/runtime/vm/object.h index 2caf67d..30ce9f7 100644 --- a/runtime/vm/object.h +++ b/runtime/vm/object.h
@@ -858,6 +858,9 @@ void SetFunctions(const Array& value) const; void AddFunction(const Function& function) const; + RawGrowableObjectArray* closures() const { + return raw_ptr()->closure_functions_; + } void AddClosureFunction(const Function& function) const; RawFunction* LookupClosureFunction(intptr_t token_pos) const; @@ -1691,6 +1694,11 @@ } void set_is_intrinsic(bool value) const; + bool is_recognized() const { + return RecognizedBit::decode(raw_ptr()->kind_tag_); + } + void set_is_recognized(bool value) const; + bool HasOptimizedCode() const; // Returns true if the argument counts are valid for calling this function. @@ -1849,7 +1857,8 @@ kExternalBit = 7, kVisibleBit = 8, kIntrinsicBit = 9, - kKindTagBit = 10, + kRecognizedBit = 10, + kKindTagBit = 11, kKindTagSize = 4, }; class StaticBit : public BitField<bool, kStaticBit, 1> {}; @@ -1862,6 +1871,7 @@ class ExternalBit : public BitField<bool, kExternalBit, 1> {}; class VisibleBit : public BitField<bool, kVisibleBit, 1> {}; class IntrinsicBit : public BitField<bool, kIntrinsicBit, 1> {}; + class RecognizedBit : public BitField<bool, kRecognizedBit, 1> {}; class KindBits : public BitField<RawFunction::Kind, kKindTagBit, kKindTagSize> {}; // NOLINT @@ -2510,6 +2520,11 @@ static bool IsPrivate(const String& name); + // Return Function::null() if function does not exist in libs. + static RawFunction* GetFunction(const GrowableArray<Library*>& libs, + const char* class_name, + const char* function_name); + private: static const int kInitialImportsCapacity = 4; static const int kImportsCapacityIncrement = 8; @@ -4778,6 +4793,11 @@ Heap::Space space = Heap::kNew); static RawString* ConcatAll(const Array& strings, Heap::Space space = Heap::kNew); + // Concat all strings in 'strings' from 'start' to 'end' (excluding). + static RawString* ConcatAllRange(const Array& strings, + intptr_t start, + intptr_t end, + Heap::Space space = Heap::kNew); static RawString* SubString(const String& str, intptr_t begin_index, @@ -4898,6 +4918,8 @@ const String& str2, Heap::Space space); static RawOneByteString* ConcatAll(const Array& strings, + intptr_t start, + intptr_t end, intptr_t len, Heap::Space space); @@ -4947,6 +4969,7 @@ friend class Class; friend class String; + friend class ExternalOneByteString; friend class SnapshotReader; }; @@ -4993,6 +5016,8 @@ const String& str2, Heap::Space space); static RawTwoByteString* ConcatAll(const Array& strings, + intptr_t start, + intptr_t end, intptr_t len, Heap::Space space); @@ -5068,6 +5093,8 @@ return reinterpret_cast<RawExternalOneByteString*>(Object::null()); } + static RawOneByteString* EscapeSpecialCharacters(const String& str); + static const ClassId kClassId = kExternalOneByteStringCid; private:
diff --git a/runtime/vm/object_test.cc b/runtime/vm/object_test.cc index 78a3d0c..cba6d44 100644 --- a/runtime/vm/object_test.cc +++ b/runtime/vm/object_test.cc
@@ -1529,6 +1529,100 @@ } +TEST_CASE(EscapeSpecialCharactersOneByteString) { + uint8_t characters[] = + { 'a', '\n', '\f', '\b', '\t', '\v', '\r', '\\', '$', 'z' }; + intptr_t len = ARRAY_SIZE(characters); + + const String& str = + String::Handle( + OneByteString::New(characters, len, Heap::kNew)); + EXPECT(str.IsOneByteString()); + EXPECT_EQ(str.Length(), len); + EXPECT(str.Equals("a\n\f\b\t\v\r\\$z")); + const String& escaped_str = + String::Handle(String::EscapeSpecialCharacters(str)); + EXPECT(escaped_str.Equals("a\\n\\f\\b\\t\\v\\r\\\\\\$z")); + + const String& escaped_empty_str = + String::Handle(String::EscapeSpecialCharacters(Symbols::Empty())); + EXPECT_EQ(escaped_empty_str.Length(), 0); +} + + +TEST_CASE(EscapeSpecialCharactersExternalOneByteString) { + uint8_t characters[] = + { 'a', '\n', '\f', '\b', '\t', '\v', '\r', '\\', '$', 'z' }; + intptr_t len = ARRAY_SIZE(characters); + + const String& str = + String::Handle( + ExternalOneByteString::New(characters, len, NULL, NULL, Heap::kNew)); + EXPECT(!str.IsOneByteString()); + EXPECT(str.IsExternalOneByteString()); + EXPECT_EQ(str.Length(), len); + EXPECT(str.Equals("a\n\f\b\t\v\r\\$z")); + const String& escaped_str = + String::Handle(String::EscapeSpecialCharacters(str)); + EXPECT(escaped_str.Equals("a\\n\\f\\b\\t\\v\\r\\\\\\$z")); + + const String& empty_str = + String::Handle( + ExternalOneByteString::New(characters, 0, NULL, NULL, Heap::kNew)); + const String& escaped_empty_str = + String::Handle(String::EscapeSpecialCharacters(empty_str)); + EXPECT_EQ(empty_str.Length(), 0); + EXPECT_EQ(escaped_empty_str.Length(), 0); +} + +TEST_CASE(EscapeSpecialCharactersTwoByteString) { + uint16_t characters[] = + { 'a', '\n', '\f', '\b', '\t', '\v', '\r', '\\', '$', 'z' }; + intptr_t len = ARRAY_SIZE(characters); + + const String& str = + String::Handle(TwoByteString::New(characters, len, Heap::kNew)); + EXPECT(str.IsTwoByteString()); + EXPECT_EQ(str.Length(), len); + EXPECT(str.Equals("a\n\f\b\t\v\r\\$z")); + const String& escaped_str = + String::Handle(String::EscapeSpecialCharacters(str)); + EXPECT(escaped_str.Equals("a\\n\\f\\b\\t\\v\\r\\\\\\$z")); + + const String& empty_str = + String::Handle(TwoByteString::New(static_cast<intptr_t>(0), Heap::kNew)); + const String& escaped_empty_str = + String::Handle(String::EscapeSpecialCharacters(empty_str)); + EXPECT_EQ(empty_str.Length(), 0); + EXPECT_EQ(escaped_empty_str.Length(), 0); +} + + +TEST_CASE(EscapeSpecialCharactersExternalTwoByteString) { + uint16_t characters[] = + { 'a', '\n', '\f', '\b', '\t', '\v', '\r', '\\', '$', 'z' }; + intptr_t len = ARRAY_SIZE(characters); + + const String& str = + String::Handle( + ExternalTwoByteString::New(characters, len, NULL, NULL, Heap::kNew)); + EXPECT(str.IsExternalTwoByteString()); + EXPECT_EQ(str.Length(), len); + EXPECT(str.Equals("a\n\f\b\t\v\r\\$z")); + const String& escaped_str = + String::Handle(String::EscapeSpecialCharacters(str)); + EXPECT(escaped_str.Equals("a\\n\\f\\b\\t\\v\\r\\\\\\$z")); + + const String& empty_str = + String::Handle( + ExternalTwoByteString::New(characters, 0, NULL, NULL, Heap::kNew)); + const String& escaped_empty_str = + String::Handle(String::EscapeSpecialCharacters(empty_str)); + EXPECT_EQ(empty_str.Length(), 0); + EXPECT_EQ(escaped_empty_str.Length(), 0); +} + + TEST_CASE(ExternalTwoByteString) { uint16_t characters[] = { 0x1E6B, 0x1E85, 0x1E53 }; intptr_t len = ARRAY_SIZE(characters);
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc index 11ce280..22ec97e 100644 --- a/runtime/vm/parser.cc +++ b/runtime/vm/parser.cc
@@ -308,7 +308,7 @@ } -void Parser::SetScript(const Script & script, intptr_t token_pos) { +void Parser::SetScript(const Script& script, intptr_t token_pos) { script_ = script.raw(); tokens_iterator_.SetStream(TokenStream::Handle(script.tokens()), token_pos); token_kind_ = Token::kILLEGAL; @@ -1019,7 +1019,7 @@ if (field.is_const()) { // This getter will only be called once at compile time. if (expr->EvalConstExpr() == NULL) { - ErrorMsg(expr_pos, "initializer must be a compile-time constant"); + ErrorMsg(expr_pos, "initializer is not a valid compile-time constant"); } ReturnNode* return_node = new ReturnNode(ident_pos, expr); current_block_->statements->Add(return_node); @@ -1923,55 +1923,7 @@ op_arguments = BuildNoSuchMethodArguments( operator_pos, operator_function_name, *op_arguments); } - if (super_operator.name() == Symbols::EqualOperator().raw()) { - // Expand super.== call to match correct == semantics into: - // Let t1 = left, t2 = right { - // (t1 === null || t2 === null) ? t1 === t2 - // : static_call(super.==, t1, t2) - // } - // Normal == calls are not expanded at the AST level to produce - // more compact code and enable more optimization opportunities. - ASSERT(!is_no_such_method); // == is always found. - EnsureExpressionTemp(); // Needed for ConditionalExprNode. - LetNode* result = new LetNode(operator_pos); - AstNode* left = - new LoadLocalNode(operator_pos, - result->AddInitializer(op_arguments->NodeAt(0))); - AstNode* right = - new LoadLocalNode(operator_pos, - result->AddInitializer(op_arguments->NodeAt(1))); - LiteralNode* null_operand = - new LiteralNode(operator_pos, Instance::ZoneHandle()); - ComparisonNode* is_left_null = new ComparisonNode(operator_pos, - Token::kEQ_STRICT, - left, - null_operand); - ComparisonNode* is_right_null = new ComparisonNode(operator_pos, - Token::kEQ_STRICT, - right, - null_operand); - BinaryOpNode* null_check = new BinaryOpNode(operator_pos, - Token::kOR, - is_left_null, - is_right_null); - ArgumentListNode* new_arguments = new ArgumentListNode(operator_pos); - new_arguments->Add(left); - new_arguments->Add(right); - StaticCallNode* call = new StaticCallNode(operator_pos, - super_operator, - new_arguments); - ComparisonNode* strict_eq = new ComparisonNode(operator_pos, - Token::kEQ_STRICT, - left, - right); - result->AddNode(new ConditionalExprNode(operator_pos, - null_check, - strict_eq, - call)); - super_op = result; - } else { - super_op = new StaticCallNode(operator_pos, super_operator, op_arguments); - } + super_op = new StaticCallNode(operator_pos, super_operator, op_arguments); if (negate_result) { super_op = new UnaryOpNode(operator_pos, Token::kNOT, super_op); } @@ -2879,17 +2831,35 @@ intptr_t end_token_pos = 0; if (CurrentToken() == Token::kLBRACE) { ConsumeToken(); + if (String::Handle(func.name()).Equals(Symbols::EqualOperator())) { + const Class& owner = Class::Handle(func.Owner()); + if (!owner.IsObjectClass()) { + AddEqualityNullCheck(); + } + } ParseStatementSequence(); end_token_pos = TokenPos(); ExpectToken(Token::kRBRACE); } else if (CurrentToken() == Token::kARROW) { ConsumeToken(); + if (String::Handle(func.name()).Equals(Symbols::EqualOperator())) { + const Class& owner = Class::Handle(func.Owner()); + if (!owner.IsObjectClass()) { + AddEqualityNullCheck(); + } + } const intptr_t expr_pos = TokenPos(); AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades); ASSERT(expr != NULL); current_block_->statements->Add(new ReturnNode(expr_pos, expr)); end_token_pos = TokenPos(); } else if (IsLiteral("native")) { + if (String::Handle(func.name()).Equals(Symbols::EqualOperator())) { + const Class& owner = Class::Handle(func.Owner()); + if (!owner.IsObjectClass()) { + AddEqualityNullCheck(); + } + } ParseNativeFunctionBlock(¶ms, func); end_token_pos = TokenPos(); ExpectSemicolon(); @@ -2924,6 +2894,31 @@ } +void Parser::AddEqualityNullCheck() { + const intptr_t token_pos = Scanner::kDummyTokenIndex; + AstNode* argument = + new LoadLocalNode(token_pos, + current_block_->scope->parent()->VariableAt(1)); + LiteralNode* null_operand = + new LiteralNode(token_pos, Instance::ZoneHandle()); + ComparisonNode* check_arg = new ComparisonNode(token_pos, + Token::kEQ_STRICT, + argument, + null_operand); + ComparisonNode* result = new ComparisonNode(token_pos, + Token::kEQ_STRICT, + LoadReceiver(token_pos), + null_operand); + SequenceNode* arg_is_null = new SequenceNode(token_pos, NULL); + arg_is_null->Add(new ReturnNode(token_pos, result)); + IfNode* if_arg_null = new IfNode(token_pos, + check_arg, + arg_is_null, + NULL); + current_block_->statements->Add(if_arg_null); +} + + void Parser::SkipIf(Token::Kind token) { if (CurrentToken() == token) { ConsumeToken(); @@ -3123,7 +3118,7 @@ // Replace the type with a malformed type and compile a throw when called. redirection_type = ClassFinalizer::NewFinalizedMalformedType( Error::Handle(), // No previous error. - current_class(), + script_, type_pos, "factory '%s' may not redirect to type parameter '%s'", method->name->ToCString(), @@ -6047,8 +6042,20 @@ } +// Return true if the type class of the given value implements the +// == operator. +static bool ImplementsEqualOperator(const Instance& value) { + Class& cls = Class::Handle(value.clazz()); + const Function& equal_op = Function::Handle( + Resolver::ResolveDynamicAnyArgs(cls, Symbols::EqualOperator())); + ASSERT(!equal_op.IsNull()); + cls = equal_op.Owner(); + return !cls.IsObjectClass(); +} + + // Check that all case expressions are of the same type, either int, String, -// double or any other class that does not override the == operator. +// or any other class that does not override the == operator. // The expressions are compile-time constants and are thus in the form // of a LiteralNode. void Parser::CheckCaseExpressions(const GrowableArray<LiteralNode*>& values) { @@ -6072,23 +6079,21 @@ } continue; } - if (first_value.IsDouble()) { - if (!val.IsDouble()) { - ErrorMsg(val_pos, "expected case expression of type double"); - } - continue; + if (val.IsDouble()) { + ErrorMsg(val_pos, "case expression may not be of type double"); } if (val.clazz() != first_value.clazz()) { ErrorMsg(val_pos, "all case expressions must be of same type"); } - Class& cls = Class::Handle(val.clazz()); - const Function& equal_op = Function::Handle( - Resolver::ResolveDynamicAnyArgs(cls, Symbols::EqualOperator())); - ASSERT(!equal_op.IsNull()); - cls = equal_op.Owner(); - if (!cls.IsObjectClass()) { - ErrorMsg(val_pos, - "type class of case expression must not implement operator =="); + if (i == 0) { + // The value is of some type other than int, String or double. + // Check that the type class does not override the == operator. + // Check this only in the first loop iteration since all values + // are of the same type, which we check above. + if (ImplementsEqualOperator(val)) { + ErrorMsg(val_pos, + "type class of case expression must not implement operator =="); + } } } } @@ -7652,7 +7657,7 @@ return expr; } if (expr->EvalConstExpr() == NULL) { - ErrorMsg(expr_pos, "expression must be a compile-time constant"); + ErrorMsg(expr_pos, "expression is not a valid compile-time constant"); } return new LiteralNode(expr_pos, EvaluateConstExpr(expr)); } @@ -7822,7 +7827,7 @@ ConsumeToken(); const intptr_t right_expr_pos = TokenPos(); if (require_compiletime_const && (assignment_op != Token::kASSIGN)) { - ErrorMsg(right_expr_pos, "expression must be a compile-time constant"); + ErrorMsg(right_expr_pos, "expression is not a valid compile-time constant"); } AstNode* right_expr = ParseExpr(require_compiletime_const, consume_cascades); if (assignment_op != Token::kASSIGN) { @@ -8530,7 +8535,7 @@ FLAG_error_on_bad_type) { *type = ClassFinalizer::NewFinalizedMalformedType( Error::Handle(), // No previous error. - scope_class, + script_, type->token_pos(), "type parameter '%s' cannot be referenced " "from static member", @@ -8548,7 +8553,7 @@ FLAG_error_on_bad_type) { *type = ClassFinalizer::NewFinalizedMalformedType( Error::Handle(), // No previous error. - scope_class, + script_, type_parameter.token_pos(), "type parameter '%s' cannot be parameterized", String::Handle(type_parameter.name()).ToCString()); @@ -8586,7 +8591,7 @@ FLAG_error_on_bad_type) { ClassFinalizer::FinalizeMalformedType( Error::Handle(), // No previous error. - scope_class, + script_, parameterized_type, "type '%s' is not loaded", String::Handle(parameterized_type.UserVisibleName()).ToCString()); @@ -9181,7 +9186,7 @@ if (finalization == ClassFinalizer::kCanonicalizeWellFormed) { return ClassFinalizer::NewFinalizedMalformedType( Error::Handle(), // No previous error. - current_class(), + script_, type_name.ident_pos, "using '%s' in this context is invalid", type_name.ident->ToCString()); @@ -9502,6 +9507,18 @@ key_type, Symbols::ListLiteralElement()); } + if (is_const) { + ASSERT(key->IsLiteralNode()); + const Instance& key_value = key->AsLiteralNode()->literal(); + if (key_value.IsDouble()) { + ErrorMsg(key_pos, "key value must not be of type double"); + } + if (!key_value.IsInteger() && + !key_value.IsString() && + ImplementsEqualOperator(key_value)) { + ErrorMsg(key_pos, "key value must not implement operator =="); + } + } ExpectToken(Token::kCOLON); const intptr_t value_pos = TokenPos(); AstNode* value = ParseExpr(is_const, kConsumeCascades); @@ -9744,7 +9761,7 @@ // Replace the type with a malformed type. type = ClassFinalizer::NewFinalizedMalformedType( Error::Handle(), // No previous error. - current_class(), + script_, type_pos, "%s'%s' cannot be instantiated", type.IsTypeParameter() ? "type parameter " : "", @@ -9756,7 +9773,7 @@ // Replace the type with a malformed type. type = ClassFinalizer::NewFinalizedMalformedType( bound_error, - current_class(), + script_, type_pos, "malbounded type '%s' cannot be instantiated", String::Handle(type.UserVisibleName()).ToCString()); @@ -9821,7 +9838,7 @@ if (is_const) { type = ClassFinalizer::NewFinalizedMalformedType( Error::Handle(), // No previous error. - current_class(), + script_, call_pos, "class '%s' has no constructor or factory named '%s'", String::Handle(type_class.Name()).ToCString(), @@ -9947,7 +9964,7 @@ &malformed_error)) { type_bound = ClassFinalizer::NewFinalizedMalformedType( malformed_error, - current_class(), + script_, new_pos, "const factory result is not an instance of '%s'", String::Handle(type_bound.UserVisibleName()).ToCString());
diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h index 4abfda0..16b9322 100644 --- a/runtime/vm/parser.h +++ b/runtime/vm/parser.h
@@ -662,6 +662,8 @@ const Function& constructor, ArgumentListNode* arguments); + void AddEqualityNullCheck(); + RawInstance* TryCanonicalize(const Instance& instance, intptr_t token_pos); Isolate* isolate() const { return isolate_; }
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h index 32f5d83..3ccbe98 100644 --- a/runtime/vm/raw_object.h +++ b/runtime/vm/raw_object.h
@@ -628,7 +628,7 @@ int16_t num_fixed_parameters_; int16_t num_optional_parameters_; // > 0: positional; < 0: named. int16_t deoptimization_counter_; - uint16_t kind_tag_; + uint16_t kind_tag_; // See Function::KindTagBits. uint16_t optimized_instruction_count_; uint16_t optimized_call_site_count_; };
diff --git a/runtime/vm/stub_code.h b/runtime/vm/stub_code.h index 3e185ee..a8351cd 100644 --- a/runtime/vm/stub_code.h +++ b/runtime/vm/stub_code.h
@@ -67,7 +67,6 @@ V(TwoArgsUnoptimizedStaticCall) \ V(OptimizeFunction) \ V(BreakpointDynamic) \ - V(EqualityWithNullArg) \ // class StubEntry is used to describe stub methods generated in dart to // abstract out common code executed from generated dart code.
diff --git a/runtime/vm/stub_code_arm.cc b/runtime/vm/stub_code_arm.cc index 596af42..0c35d5b 100644 --- a/runtime/vm/stub_code_arm.cc +++ b/runtime/vm/stub_code_arm.cc
@@ -1758,7 +1758,15 @@ void StubCode::GenerateBreakpointRuntimeStub(Assembler* assembler) { - __ Unimplemented("BreakpointRuntime stub"); + __ Comment("BreakpointRuntime stub"); + __ EnterStubFrame(); + __ LoadImmediate(R0, reinterpret_cast<intptr_t>(Object::null())); + // Preserve arguments descriptor and make room for result. + __ PushList((1 << R0) | (1 << R4) | (1 << R5)); + __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); + __ PopList((1 << R0) | (1 << R4) | (1 << R5)); + __ LeaveStubFrame(); + __ bx(R0); } @@ -1958,92 +1966,6 @@ } -// Implements equality operator when one of the arguments is null -// (identity check) and updates ICData if necessary. -// LR: return address. -// R1: left argument. -// R0: right argument. -// R5: ICData. -// R0: result. -// TODO(srdjan): Move to VM stubs once Boolean objects become VM objects. -void StubCode::GenerateEqualityWithNullArgStub(Assembler* assembler) { - __ EnterStubFrame(); - static const intptr_t kNumArgsTested = 2; -#if defined(DEBUG) - { Label ok; - __ ldr(IP, FieldAddress(R5, ICData::num_args_tested_offset())); - __ cmp(IP, ShifterOperand(kNumArgsTested)); - __ b(&ok, EQ); - __ Stop("Incorrect ICData for equality"); - __ Bind(&ok); - } -#endif // DEBUG - // Check IC data, update if needed. - // R5: IC data object (preserved). - __ ldr(R6, FieldAddress(R5, ICData::ic_data_offset())); - // R6: ic_data_array with check entries: classes and target functions. - __ AddImmediate(R6, Array::data_offset() - kHeapObjectTag); - // R6: points directly to the first ic data array element. - - Label get_class_id_as_smi, no_match, loop, found; - __ Bind(&loop); - // Check left. - __ mov(R2, ShifterOperand(R1)); - __ bl(&get_class_id_as_smi); - __ ldr(R3, Address(R6, 0 * kWordSize)); - __ cmp(R2, ShifterOperand(R3)); // Class id match? - __ b(&no_match, NE); - // Check right. - __ mov(R2, ShifterOperand(R0)); - __ bl(&get_class_id_as_smi); - __ ldr(R3, Address(R6, 1 * kWordSize)); - __ cmp(R2, ShifterOperand(R3)); // Class id match? - __ b(&found, EQ); - __ Bind(&no_match); - // Next check group. - __ AddImmediate(R6, kWordSize * ICData::TestEntryLengthFor(kNumArgsTested)); - __ CompareImmediate(R3, Smi::RawValue(kIllegalCid)); // Done? - __ b(&loop, NE); - Label update_ic_data; - __ b(&update_ic_data); - - __ Bind(&found); - const intptr_t count_offset = - ICData::CountIndexFor(kNumArgsTested) * kWordSize; - __ ldr(IP, Address(R6, count_offset)); - __ adds(IP, IP, ShifterOperand(Smi::RawValue(1))); - __ LoadImmediate(IP, Smi::RawValue(Smi::kMaxValue), VS); // If overflow. - __ str(IP, Address(R6, count_offset)); - - Label compute_result; - __ Bind(&compute_result); - __ cmp(R0, ShifterOperand(R1)); - __ LoadObject(R0, Bool::False(), NE); - __ LoadObject(R0, Bool::True(), EQ); - __ LeaveStubFrame(); - __ Ret(); - - __ Bind(&get_class_id_as_smi); - // Test if Smi -> load Smi class for comparison. - __ tst(R2, ShifterOperand(kSmiTagMask)); - __ mov(R2, ShifterOperand(Smi::RawValue(kSmiCid)), EQ); - __ bx(LR, EQ); - __ LoadClassId(R2, R2); - __ SmiTag(R2); - __ bx(LR); - - __ Bind(&update_ic_data); - // R5: ICData - __ PushList((1 << R0) | (1 << R1)); - __ PushObject(Symbols::EqualOperator()); // Target's name. - __ Push(R5); // ICData - __ CallRuntime(kUpdateICDataTwoArgsRuntimeEntry, 4); // Clobbers R4, R5. - __ Drop(2); - __ PopList((1 << R0) | (1 << R1)); - __ b(&compute_result); -} - - // Calls to the runtime to optimize the given function. // R6: function to be reoptimized. // R4: argument descriptor (preserved).
diff --git a/runtime/vm/stub_code_ia32.cc b/runtime/vm/stub_code_ia32.cc index f2ba2ea..4df92d7 100644 --- a/runtime/vm/stub_code_ia32.cc +++ b/runtime/vm/stub_code_ia32.cc
@@ -1796,7 +1796,7 @@ } -// EDX, EXC: May contain arguments to runtime stub. +// EDX, ECX: May contain arguments to runtime stub. void StubCode::GenerateBreakpointRuntimeStub(Assembler* assembler) { __ EnterStubFrame(); // Save runtime args. @@ -2032,105 +2032,6 @@ } -// Implements equality operator when one of the arguments is null -// (identity check) and updates ICData if necessary. -// TOS + 0: return address -// TOS + 1: right argument -// TOS + 2: left argument -// ECX: ICData. -// EAX: result. -// TODO(srdjan): Move to VM stubs once Boolean objects become VM objects. -void StubCode::GenerateEqualityWithNullArgStub(Assembler* assembler) { - static const intptr_t kNumArgsTested = 2; -#if defined(DEBUG) - { Label ok; - __ movl(EAX, FieldAddress(ECX, ICData::num_args_tested_offset())); - __ cmpl(EAX, Immediate(kNumArgsTested)); - __ j(EQUAL, &ok, Assembler::kNearJump); - __ Stop("Incorrect ICData for equality"); - __ Bind(&ok); - } -#endif // DEBUG - // Check IC data, update if needed. - // ECX: IC data object (preserved). - __ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset())); - // EBX: ic_data_array with check entries: classes and target functions. - __ leal(EBX, FieldAddress(EBX, Array::data_offset())); - // EBX: points directly to the first ic data array element. - - Label get_class_id_as_smi, no_match, loop, compute_result, found; - __ Bind(&loop); - // Check left. - __ movl(EAX, Address(ESP, 2 * kWordSize)); - __ call(&get_class_id_as_smi); - __ movl(EDI, Address(EBX, 0 * kWordSize)); - __ cmpl(EAX, EDI); // Class id match? - __ j(NOT_EQUAL, &no_match, Assembler::kNearJump); - // Check right. - __ movl(EAX, Address(ESP, 1 * kWordSize)); - __ call(&get_class_id_as_smi); - __ movl(EDI, Address(EBX, 1 * kWordSize)); - __ cmpl(EAX, EDI); // Class id match? - __ j(EQUAL, &found, Assembler::kNearJump); - __ Bind(&no_match); - // Next check group. - __ addl(EBX, Immediate( - kWordSize * ICData::TestEntryLengthFor(kNumArgsTested))); - __ cmpl(EDI, Immediate(Smi::RawValue(kIllegalCid))); // Done? - __ j(NOT_EQUAL, &loop, Assembler::kNearJump); - Label update_ic_data; - __ jmp(&update_ic_data); - - __ Bind(&found); - const intptr_t count_offset = - ICData::CountIndexFor(kNumArgsTested) * kWordSize; - __ addl(Address(EBX, count_offset), Immediate(Smi::RawValue(1))); - __ j(NO_OVERFLOW, &compute_result); - __ movl(Address(EBX, count_offset), - Immediate(Smi::RawValue(Smi::kMaxValue))); - - __ Bind(&compute_result); - Label true_label; - __ movl(EAX, Address(ESP, 1 * kWordSize)); - __ cmpl(EAX, Address(ESP, 2 * kWordSize)); - __ j(EQUAL, &true_label, Assembler::kNearJump); - __ LoadObject(EAX, Bool::False()); - __ ret(); - __ Bind(&true_label); - __ LoadObject(EAX, Bool::True()); - __ ret(); - - __ Bind(&get_class_id_as_smi); - Label not_smi; - // Test if Smi -> load Smi class for comparison. - __ testl(EAX, Immediate(kSmiTagMask)); - __ j(NOT_ZERO, ¬_smi, Assembler::kNearJump); - __ movl(EAX, Immediate(Smi::RawValue(kSmiCid))); - __ ret(); - - __ Bind(¬_smi); - __ LoadClassId(EAX, EAX); - __ SmiTag(EAX); - __ ret(); - - __ Bind(&update_ic_data); - - // ECX: ICData - __ movl(EAX, Address(ESP, 1 * kWordSize)); - __ movl(EDI, Address(ESP, 2 * kWordSize)); - __ EnterStubFrame(); - __ pushl(EDI); // arg 0 - __ pushl(EAX); // arg 1 - __ PushObject(Symbols::EqualOperator()); // Target's name. - __ pushl(ECX); // ICData - __ CallRuntime(kUpdateICDataTwoArgsRuntimeEntry, 4); - __ Drop(4); - __ LeaveFrame(); - - __ jmp(&compute_result, Assembler::kNearJump); -} - - // Calls to the runtime to optimize the given function. // EDI: function to be reoptimized. // EDX: argument descriptor (preserved).
diff --git a/runtime/vm/stub_code_mips.cc b/runtime/vm/stub_code_mips.cc index 83990b8..0928f0a 100644 --- a/runtime/vm/stub_code_mips.cc +++ b/runtime/vm/stub_code_mips.cc
@@ -2000,7 +2000,22 @@ void StubCode::GenerateBreakpointRuntimeStub(Assembler* assembler) { - __ Unimplemented("BreakpointRuntime stub"); + __ Comment("BreakpointRuntime stub"); + __ EnterStubFrame(); + __ addiu(SP, SP, Immediate(-3 * kWordSize)); + __ sw(S5, Address(SP, 2 * kWordSize)); + __ sw(S4, Address(SP, 1 * kWordSize)); + __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null())); + __ sw(TMP, Address(SP, 0 * kWordSize)); + + __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0); + + __ lw(S5, Address(SP, 2 * kWordSize)); + __ lw(S4, Address(SP, 1 * kWordSize)); + __ lw(T0, Address(SP, 0 * kWordSize)); + __ addiu(SP, SP, Immediate(3 * kWordSize)); + __ LeaveStubFrame(); + __ jr(T0); } @@ -2217,110 +2232,6 @@ } -// Implements equality operator when one of the arguments is null -// (identity check) and updates ICData if necessary. -// RA: return address. -// A1: left argument. -// A0: right argument. -// T0: ICData. -// V0: result. -// TODO(srdjan): Move to VM stubs once Boolean objects become VM objects. -void StubCode::GenerateEqualityWithNullArgStub(Assembler* assembler) { - __ TraceSimMsg("EqualityWithNullArgStub"); - __ Comment("EqualityWithNullArgStub"); - __ EnterStubFrame(); - static const intptr_t kNumArgsTested = 2; -#if defined(DEBUG) - { Label ok; - __ lw(CMPRES1, FieldAddress(T0, ICData::num_args_tested_offset())); - __ BranchEqual(CMPRES1, kNumArgsTested, &ok); - __ Stop("Incorrect ICData for equality"); - __ Bind(&ok); - } -#endif // DEBUG - // Check IC data, update if needed. - // T0: IC data object (preserved). - __ lw(T6, FieldAddress(T0, ICData::ic_data_offset())); - // T6: ic_data_array with check entries: classes and target functions. - __ AddImmediate(T6, Array::data_offset() - kHeapObjectTag); - // T6: points directly to the first ic data array element. - - Label get_class_id_as_smi, no_match, loop, found; - __ Bind(&loop); - // Check left. - __ bal(&get_class_id_as_smi); - __ delay_slot()->mov(T2, A1); - __ lw(T3, Address(T6, 0 * kWordSize)); - __ bne(T2, T3, &no_match); // Class id match? - - // Check right. - __ bal(&get_class_id_as_smi); - __ delay_slot()->mov(T2, A0); - __ lw(T3, Address(T6, 1 * kWordSize)); - __ beq(T2, T3, &found); // Class id match? - __ Bind(&no_match); - // Next check group. - intptr_t entry_bytes = kWordSize * ICData::TestEntryLengthFor(kNumArgsTested); - if (Utils::IsInt(kImmBits, entry_bytes)) { - __ BranchNotEqual(T3, Smi::RawValue(kIllegalCid), &loop); // Done? - __ delay_slot()->addiu(T6, T6, Immediate(entry_bytes)); - } else { - __ AddImmediate(T6, entry_bytes); - __ BranchNotEqual(T3, Smi::RawValue(kIllegalCid), &loop); // Done? - } - - Label update_ic_data; - __ b(&update_ic_data); - - __ Bind(&found); - const intptr_t count_offset = - ICData::CountIndexFor(kNumArgsTested) * kWordSize; - Label no_overflow; - __ lw(T1, Address(T6, count_offset)); - __ AddImmediateDetectOverflow(T1, T1, Smi::RawValue(1), CMPRES, T5); - __ bgez(CMPRES, &no_overflow); - __ delay_slot()->sw(T1, Address(T6, count_offset)); - __ LoadImmediate(TMP1, Smi::RawValue(Smi::kMaxValue)); - __ sw(TMP1, Address(T6, count_offset)); // If overflow. - __ Bind(&no_overflow); - - Label compute_result; - __ Bind(&compute_result); - __ LoadObject(T4, Bool::True()); - __ LoadObject(T5, Bool::False()); - __ subu(CMPRES, A0, A1); - __ movz(V0, T4, CMPRES); - __ movn(V0, T5, CMPRES); - __ LeaveStubFrameAndReturn(); - - __ Bind(&get_class_id_as_smi); - // Test if Smi -> load Smi class for comparison. - Label not_smi; - __ andi(CMPRES, T2, Immediate(kSmiTagMask)); - __ bne(CMPRES, ZR, ¬_smi); - __ jr(RA); - __ delay_slot()->addiu(T2, ZR, Immediate(Smi::RawValue(kSmiCid))); - __ Bind(¬_smi); - __ LoadClassId(T2, T2); - __ jr(RA); - __ delay_slot()->SmiTag(T2); - - __ Bind(&update_ic_data); - // T0: ICData - __ addiu(SP, SP, Immediate(-4 * kWordSize)); - __ sw(A1, Address(SP, 3 * kWordSize)); - __ sw(A0, Address(SP, 2 * kWordSize)); - __ LoadObject(TMP1, Symbols::EqualOperator()); // Target's name. - __ sw(TMP1, Address(SP, 1 * kWordSize)); - __ sw(T0, Address(SP, 0 * kWordSize)); // ICData. - __ CallRuntime(kUpdateICDataTwoArgsRuntimeEntry, 4); - __ lw(A0, Address(SP, 2 * kWordSize)); - __ lw(A1, Address(SP, 3 * kWordSize)); - __ b(&compute_result); - __ delay_slot()->addiu(SP, SP, Immediate(4 * kWordSize)); -} - - // Calls to the runtime to optimize the given function. // T0: function to be reoptimized. // S4: argument descriptor (preserved).
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc index 7d47618..d2d304f 100644 --- a/runtime/vm/stub_code_x64.cc +++ b/runtime/vm/stub_code_x64.cc
@@ -60,7 +60,7 @@ __ movq(CTX, RAX); // Reserve space for arguments and align frame before entering C++ world. - __ AddImmediate(RSP, Immediate(-sizeof(NativeArguments))); + __ subq(RSP, Immediate(sizeof(NativeArguments))); if (OS::ActivationFrameAlignment() > 1) { __ andq(RSP, Immediate(~(OS::ActivationFrameAlignment() - 1))); } @@ -149,7 +149,7 @@ // Reserve space for the native arguments structure passed on the stack (the // outgoing pointer parameter to the native arguments structure is passed in // RDI) and align frame before entering the C++ world. - __ AddImmediate(RSP, Immediate(-sizeof(NativeArguments))); + __ subq(RSP, Immediate(sizeof(NativeArguments))); if (OS::ActivationFrameAlignment() > 1) { __ andq(RSP, Immediate(~(OS::ActivationFrameAlignment() - 1))); } @@ -217,7 +217,7 @@ // Reserve space for the native arguments structure passed on the stack (the // outgoing pointer parameter to the native arguments structure is passed in // RDI) and align frame before entering the C++ world. - __ AddImmediate(RSP, Immediate(-sizeof(NativeArguments))); + __ subq(RSP, Immediate(sizeof(NativeArguments))); if (OS::ActivationFrameAlignment() > 1) { __ andq(RSP, Immediate(~(OS::ActivationFrameAlignment() - 1))); } @@ -255,7 +255,7 @@ __ EnterStubFrame(); __ pushq(R10); // Preserve arguments descriptor array. // Setup space on stack for return value. - __ PushObject(Object::null_object()); + __ PushObject(Object::null_object(), PP); __ CallRuntime(kPatchStaticCallRuntimeEntry, 0); __ popq(RAX); // Get Code object result. __ popq(R10); // Restore arguments descriptor array. @@ -275,7 +275,7 @@ __ EnterStubFrame(); __ pushq(R10); // Preserve arguments descriptor array. // Setup space on stack for return value. - __ PushObject(Object::null_object()); + __ PushObject(Object::null_object(), PP); __ CallRuntime(kFixCallersTargetRuntimeEntry, 0); __ popq(RAX); // Get Code object. __ popq(R10); // Restore arguments descriptor array. @@ -308,8 +308,8 @@ __ Bind(&loop); __ movq(RAX, Address(R12, 0)); __ movq(Address(RBX, 0), RAX); - __ AddImmediate(RBX, Immediate(kWordSize)); - __ AddImmediate(R12, Immediate(-kWordSize)); + __ addq(RBX, Immediate(kWordSize)); + __ subq(R12, Immediate(kWordSize)); __ Bind(&loop_condition); __ decq(R10); __ j(POSITIVE, &loop, Assembler::kNearJump); @@ -324,7 +324,7 @@ // when trying to resolve the call. void StubCode::GenerateInstanceFunctionLookupStub(Assembler* assembler) { __ EnterStubFrameWithPP(); - __ PushObject(Object::null_object()); // Space for the return value. + __ PushObject(Object::null_object(), PP); // Space for the return value. // Push the receiver as an argument. Load the smi-tagged argument // count into R13 to index the receiver in the stack. There are @@ -504,7 +504,7 @@ __ pushq(R10); // Space for the result of the runtime call. - __ PushObject(Object::null_object()); + __ PushObject(Object::null_object(), PP); __ pushq(RAX); // Receiver. __ pushq(RBX); // IC data. __ pushq(R10); // Arguments descriptor. @@ -519,7 +519,7 @@ __ LeaveFrameWithPP(); Label lookup; - __ CompareObject(RAX, Object::null_object()); + __ CompareObject(RAX, Object::null_object(), PP); __ j(EQUAL, &lookup, Assembler::kNearJump); __ addq(RAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); __ jmp(RAX); @@ -650,7 +650,7 @@ // calling into the runtime. __ EnterStubFrame(); // Setup space on stack for return value. - __ PushObject(Object::null_object()); + __ PushObject(Object::null_object(), PP); __ pushq(R10); // Array length as Smi. __ pushq(RBX); // Element type. __ CallRuntime(kAllocateArrayRuntimeEntry, 2); @@ -1228,7 +1228,7 @@ // Create a stub frame. __ EnterStubFrameWithPP(); __ pushq(R12); // Setup space on stack for return value. - __ PushObject(cls); // Push class of object to be allocated. + __ PushObject(cls, PP); // Push class of object to be allocated. if (is_cls_parameterized) { __ pushq(RAX); // Push type arguments of object to be allocated. __ pushq(RDX); // Push type arguments of instantiator. @@ -1364,7 +1364,7 @@ } __ pushq(R12); // Setup space on stack for the return value. - __ PushObject(func); + __ PushObject(func, PP); if (is_implicit_instance_closure) { __ pushq(RAX); // Receiver. } @@ -2003,104 +2003,6 @@ } -// Implements equality operator when one of the arguments is null -// (identity check) and updates ICData if necessary. -// TOS + 0: return address -// TOS + 1: right argument -// TOS + 2: left argument -// RBX: ICData. -// RAX: result. -// TODO(srdjan): Move to VM stubs once Boolean objects become VM objects. -void StubCode::GenerateEqualityWithNullArgStub(Assembler* assembler) { - static const intptr_t kNumArgsTested = 2; -#if defined(DEBUG) - { Label ok; - __ movq(RCX, FieldAddress(RBX, ICData::num_args_tested_offset())); - __ cmpq(RCX, Immediate(kNumArgsTested)); - __ j(EQUAL, &ok, Assembler::kNearJump); - __ Stop("Incorrect ICData for equality"); - __ Bind(&ok); - } -#endif // DEBUG - // Check IC data, update if needed. - // RBX: IC data object (preserved). - __ movq(R12, FieldAddress(RBX, ICData::ic_data_offset())); - // R12: ic_data_array with check entries: classes and target functions. - __ leaq(R12, FieldAddress(R12, Array::data_offset())); - // R12: points directly to the first ic data array element. - - Label get_class_id_as_smi, no_match, loop, compute_result, found; - __ Bind(&loop); - // Check left. - __ movq(RAX, Address(RSP, 2 * kWordSize)); - __ call(&get_class_id_as_smi); - __ movq(R13, Address(R12, 0 * kWordSize)); - __ cmpq(RAX, R13); // Class id match? - __ j(NOT_EQUAL, &no_match, Assembler::kNearJump); - // Check right. - __ movq(RAX, Address(RSP, 1 * kWordSize)); - __ call(&get_class_id_as_smi); - __ movq(R13, Address(R12, 1 * kWordSize)); - __ cmpq(RAX, R13); // Class id match? - __ j(EQUAL, &found, Assembler::kNearJump); - __ Bind(&no_match); - // Next check group. - __ addq(R12, Immediate( - kWordSize * ICData::TestEntryLengthFor(kNumArgsTested))); - __ cmpq(R13, Immediate(Smi::RawValue(kIllegalCid))); // Done? - __ j(NOT_EQUAL, &loop, Assembler::kNearJump); - Label update_ic_data; - __ jmp(&update_ic_data); - - __ Bind(&found); - const intptr_t count_offset = - ICData::CountIndexFor(kNumArgsTested) * kWordSize; - __ addq(Address(R12, count_offset), Immediate(Smi::RawValue(1))); - __ j(NO_OVERFLOW, &compute_result); - __ movq(Address(R12, count_offset), - Immediate(Smi::RawValue(Smi::kMaxValue))); - - __ Bind(&compute_result); - Label true_label; - __ movq(RAX, Address(RSP, 1 * kWordSize)); - __ cmpq(RAX, Address(RSP, 2 * kWordSize)); - __ j(EQUAL, &true_label, Assembler::kNearJump); - __ LoadObject(RAX, Bool::False(), PP); - __ ret(); - __ Bind(&true_label); - __ LoadObject(RAX, Bool::True(), PP); - __ ret(); - - __ Bind(&get_class_id_as_smi); - Label not_smi; - // Test if Smi -> load Smi class for comparison. - __ testq(RAX, Immediate(kSmiTagMask)); - __ j(NOT_ZERO, ¬_smi, Assembler::kNearJump); - __ movq(RAX, Immediate(Smi::RawValue(kSmiCid))); - __ ret(); - - __ Bind(¬_smi); - __ LoadClassId(RAX, RAX); - __ SmiTag(RAX); - __ ret(); - - __ Bind(&update_ic_data); - - // RBX: ICData - __ movq(RAX, Address(RSP, 1 * kWordSize)); - __ movq(R13, Address(RSP, 2 * kWordSize)); - __ EnterStubFrame(); - __ pushq(R13); // arg 0 - __ pushq(RAX); // arg 1 - __ PushObject(Symbols::EqualOperator()); // Target's name. - __ pushq(RBX); // ICData - __ CallRuntime(kUpdateICDataTwoArgsRuntimeEntry, 4); - __ Drop(4); - __ LeaveFrame(); - - __ jmp(&compute_result, Assembler::kNearJump); -} - // Calls to the runtime to optimize the given function. // RDI: function to be reoptimized. // R10: argument descriptor (preserved).
diff --git a/runtime/vm/stub_code_x64_test.cc b/runtime/vm/stub_code_x64_test.cc index 3efc152..cc0e3fb 100644 --- a/runtime/vm/stub_code_x64_test.cc +++ b/runtime/vm/stub_code_x64_test.cc
@@ -47,12 +47,12 @@ ASSERT(context.isolate() == Isolate::Current()); __ EnterStubFrameWithPP(); __ LoadObject(CTX, context, PP); - __ PushObject(result); // Push Null object for return value. - __ PushObject(smi1); // Push argument 1 smi1. - __ PushObject(smi2); // Push argument 2 smi2. + __ PushObject(result, PP); // Push Null object for return value. + __ PushObject(smi1, PP); // Push argument 1 smi1. + __ PushObject(smi2, PP); // Push argument 2 smi2. ASSERT(kTestSmiSubRuntimeEntry.argument_count() == argc); __ CallRuntime(kTestSmiSubRuntimeEntry, argc); // Call SmiSub runtime func. - __ AddImmediate(RSP, Immediate(argc * kWordSize)); + __ AddImmediate(RSP, Immediate(argc * kWordSize), PP); __ popq(RAX); // Pop return value from return slot. __ LeaveFrameWithPP(); __ ret();
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h index 987eb45..723263c 100644 --- a/runtime/vm/symbols.h +++ b/runtime/vm/symbols.h
@@ -116,12 +116,12 @@ V(_Bigint, "_Bigint") \ V(_Double, "_Double") \ V(Bool, "bool") \ - V(ObjectArray, "_ObjectArray") \ - V(ObjectArrayFactory, "_ObjectArray.") \ - V(GrowableObjectArray, "_GrowableObjectArray") \ - V(GrowableObjectArrayFactory, "_GrowableObjectArray.") \ - V(GrowableObjectArrayWithData, "_GrowableObjectArray.withData") \ - V(ImmutableArray, "_ImmutableArray") \ + V(_List, "_List") \ + V(_ListFactory, "_List.") \ + V(_GrowableList, "_GrowableList") \ + V(_GrowableListFactory, "_GrowableList.") \ + V(_GrowableListWithData, "_GrowableList.withData") \ + V(_ImmutableList, "_ImmutableList") \ V(OneByteString, "_OneByteString") \ V(TwoByteString, "_TwoByteString") \ V(ExternalOneByteString, "_ExternalOneByteString") \
diff --git a/runtime/vm/vm_sources.gypi b/runtime/vm/vm_sources.gypi index edcd75d..921078b 100644 --- a/runtime/vm/vm_sources.gypi +++ b/runtime/vm/vm_sources.gypi
@@ -116,6 +116,8 @@ 'debuginfo.h', 'debuginfo_android.cc', 'debuginfo_linux.cc', + 'deferred_objects.cc', + 'deferred_objects.h', 'deopt_instructions.cc', 'deopt_instructions.h', 'disassembler.cc',
diff --git a/sdk/lib/_internal/compiler/implementation/common.dart b/sdk/lib/_internal/compiler/implementation/common.dart new file mode 100644 index 0000000..3c069ca --- /dev/null +++ b/sdk/lib/_internal/compiler/implementation/common.dart
@@ -0,0 +1,52 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +library dart2js.common; + +export 'dart2jslib.dart' show + CompilerTask, + Compiler, + Constant, + ConstantHandler, + InterceptorConstant, + MessageKind, + NullConstant, + Selector, + SourceString, + TreeElements, + TypeConstant, + invariant; + +export 'dart_types.dart' show + DartType, + FunctionType, + InterfaceType, + TypeVariableType, + Types; + +export 'elements/elements.dart' show + ClassElement, + ClosureFieldElement, + Element, + Elements, + FunctionElement, + FunctionSignature, + LibraryElement, + MetadataAnnotation, + MixinApplicationElement, + TypedefElement, + VariableElement; + +export 'tree/tree.dart' show + Node; + +export 'types/types.dart' show + TypeMask; + +export 'universe/universe.dart' show + SelectorKind; + +export 'util/util.dart' show + Link, + SpannableAssertionFailure;
diff --git a/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart b/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart index 48bc9f4..8ae51fa 100644 --- a/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart +++ b/sdk/lib/_internal/compiler/implementation/compile_time_constants.dart
@@ -29,12 +29,6 @@ /** Caches the statics where the initial value cannot be eagerly compiled. */ final Set<VariableElement> lazyStatics; - /** Caches the createRuntimeType function if registered. */ - Element createRuntimeTypeFunction = null; - - /** Caches the setRuntimeTypeInfo function if registered. */ - Element setRuntimeTypeInfoFunction = null; - ConstantHandler(Compiler compiler, this.constantSystem, { bool this.isMetadata: false }) : initialVariableValues = new Map<VariableElement, dynamic>(), @@ -45,90 +39,12 @@ String get name => 'ConstantHandler'; - void registerCompileTimeConstant(Constant constant, TreeElements elements) { - registerInstantiatedType(constant.computeType(compiler), elements); - if (constant.isFunction()) { - FunctionConstant function = constant; - registerGetOfStaticFunction(function.element); - } else if (constant.isInterceptor()) { - // An interceptor constant references the class's prototype chain. - InterceptorConstant interceptor = constant; - registerInstantiatedType(interceptor.dispatchedType, elements); - } + void addCompileTimeConstantForEmission(Constant constant) { compiledConstants.add(constant); } - void registerInstantiatedType(DartType type, TreeElements elements) { - if (isMetadata) { - compiler.backend.registerMetadataInstantiatedType(type, elements); - return; - } - compiler.enqueuer.codegen.registerInstantiatedType(type, elements); - if (type is InterfaceType && - !type.isRaw && - compiler.backend.classNeedsRti(type.element)) { - registerSetRuntimeTypeInfoFunction(); - } - } - - void registerStaticUse(Element element) { - if (isMetadata) { - compiler.backend.registerMetadataStaticUse(element); - return; - } - compiler.analyzeElement(element.declaration); - compiler.enqueuer.codegen.registerStaticUse(element); - } - - void registerGetOfStaticFunction(FunctionElement element) { - if (isMetadata) { - compiler.backend.registerMetadataGetOfStaticFunction(element); - return; - } - compiler.analyzeElement(element.declaration); - compiler.enqueuer.codegen.registerGetOfStaticFunction(element); - } - - void registerStringInstance(TreeElements elements) { - registerInstantiatedType(compiler.stringClass.rawType, elements); - } - - void registerSetRuntimeTypeInfoFunction() { - if (setRuntimeTypeInfoFunction != null) return; - SourceString helperName = const SourceString('setRuntimeTypeInfo'); - setRuntimeTypeInfoFunction = compiler.findHelper(helperName); - registerStaticUse(setRuntimeTypeInfoFunction); - } - - void registerCreateRuntimeTypeFunction() { - if (createRuntimeTypeFunction != null) return; - SourceString helperName = const SourceString('createRuntimeType'); - createRuntimeTypeFunction = compiler.findHelper(helperName); - registerStaticUse(createRuntimeTypeFunction); - } - - /** - * Compiles the initial value of the given field and stores it in an internal - * map. Returns the initial value (a constant) if it can be computed - * statically. Returns [:null:] if the variable must be initialized lazily. - * - * [work] must contain a [VariableElement] refering to a global or - * static field. - */ - Constant compileWorkItem(CodegenWorkItem work) { - return measure(() { - assert(work.element.kind == ElementKind.FIELD - || work.element.kind == ElementKind.PARAMETER - || work.element.kind == ElementKind.FIELD_PARAMETER); - VariableElement element = work.element; - // Shortcut if it has already been compiled. - Constant result = initialVariableValues[element]; - if (result != null) return result; - if (lazyStatics.contains(element)) return null; - result = compileVariableWithDefinitions(element, work.resolutionTree); - assert(pendingVariables.isEmpty); - return result; - }); + Constant getConstantForVariable(VariableElement element) { + return initialVariableValues[element]; } /** @@ -175,9 +91,6 @@ TreeElements definitions, {bool isConst: false}) { return measure(() { - // Initializers for parameters must be const. - isConst = isConst || element.modifiers.isConst() - || !Elements.isStaticOrTopLevel(element); if (!isConst && lazyStatics.contains(element)) return null; Node node = element.parseNode(compiler); @@ -235,23 +148,17 @@ {bool isConst: false}) { return measure(() { assert(node != null); + Constant constant = definitions.getConstant(node); + if (constant != null) { + return constant; + } CompileTimeConstantEvaluator evaluator = new CompileTimeConstantEvaluator( this, definitions, compiler, isConst: isConst); - return evaluator.evaluate(node); - }); - } - - /** Attempts to compile a constant expression. Returns null if not possible */ - Constant tryCompileNodeWithDefinitions(Node node, TreeElements definitions) { - return measure(() { - assert(node != null); - try { - TryCompileTimeConstantEvaluator evaluator = - new TryCompileTimeConstantEvaluator(this, definitions, compiler); - return evaluator.evaluate(node); - } on CompileTimeConstantError catch (exn) { - return null; + constant = evaluator.evaluate(node); + if (constant != null) { + definitions.setConstant(node, constant); } + return constant; }); } @@ -358,17 +265,14 @@ } Constant visitLiteralBool(LiteralBool node) { - handler.registerInstantiatedType(compiler.boolClass.rawType, elements); return constantSystem.createBool(node.value); } Constant visitLiteralDouble(LiteralDouble node) { - handler.registerInstantiatedType(compiler.doubleClass.rawType, elements); return constantSystem.createDouble(node.value); } Constant visitLiteralInt(LiteralInt node) { - handler.registerInstantiatedType(compiler.intClass.rawType, elements); return constantSystem.createInt(node.value); } @@ -383,10 +287,7 @@ arguments.add(evaluateConstant(link.head)); } DartType type = elements.getType(node); - handler.registerInstantiatedType(type, elements); - Constant constant = new ListConstant(type, arguments); - handler.registerCompileTimeConstant(constant, elements); - return constant; + return new ListConstant(type, arguments); } Constant visitLiteralMap(LiteralMap node) { @@ -422,13 +323,15 @@ bool hasProtoKey = (protoValue != null); List<Constant> values = map.values.toList(); InterfaceType sourceType = elements.getType(node); - Link<DartType> arguments = - new Link<DartType>.fromList([compiler.stringClass.rawType]); - DartType keysType = new InterfaceType(compiler.listClass, arguments); - ListConstant keysList = new ListConstant(keysType, keys); - if (onlyStringKeys) { - handler.registerCompileTimeConstant(keysList, elements); + DartType keysType; + if (sourceType.treatAsRaw) { + keysType = compiler.listClass.rawType; + } else { + Link<DartType> arguments = + new Link<DartType>.fromList([sourceType.typeArguments.head]); + keysType = new InterfaceType(compiler.listClass, arguments); } + ListConstant keysList = new ListConstant(keysType, keys); SourceString className = onlyStringKeys ? (hasProtoKey ? MapConstant.DART_PROTO_CLASS : MapConstant.DART_STRING_CLASS) @@ -436,12 +339,13 @@ ClassElement classElement = compiler.jsHelperLibrary.find(className); classElement.ensureResolved(compiler); Link<DartType> typeArgument = sourceType.typeArguments; - InterfaceType type = new InterfaceType(classElement, typeArgument); - handler.registerInstantiatedType(type, elements); - Constant constant = - new MapConstant(type, keysList, values, protoValue, onlyStringKeys); - handler.registerCompileTimeConstant(constant, elements); - return constant; + InterfaceType type; + if (sourceType.treatAsRaw) { + type = classElement.rawType; + } else { + type = new InterfaceType(classElement, typeArgument); + } + return new MapConstant(type, keysList, values, protoValue, onlyStringKeys); } Constant visitLiteralNull(LiteralNull node) { @@ -449,7 +353,6 @@ } Constant visitLiteralString(LiteralString node) { - handler.registerStringInstance(elements); return constantSystem.createString(node.dartString, node); } @@ -457,7 +360,6 @@ StringConstant left = evaluate(node.first); StringConstant right = evaluate(node.second); if (left == null || right == null) return null; - handler.registerStringInstance(elements); return constantSystem.createString( new DartString.concat(left.value, right.value), node); } @@ -485,12 +387,10 @@ if (partString == null) return null; accumulator = new DartString.concat(accumulator, partString.value); }; - handler.registerStringInstance(elements); return constantSystem.createString(accumulator, node); } Constant visitLiteralSymbol(LiteralSymbol node) { - handler.registerStringInstance(elements); InterfaceType type = compiler.symbolClass.computeType(compiler); List<Constant> createArguments(_) { return [constantSystem.createString( @@ -502,17 +402,9 @@ Constant makeTypeConstant(Element element) { DartType elementType = element.computeType(compiler).asRaw(); - compiler.backend.registerTypeLiteral( - element, compiler.enqueuer.codegen, elements); DartType constantType = compiler.backend.typeImplementation.computeType(compiler); - Constant constant = new TypeConstant(elementType, constantType); - // If we use a type literal in a constant, the compile time - // constant emitter will generate a call to the createRuntimeType - // helper so we register a use of that. - handler.registerCreateRuntimeTypeFunction(); - handler.registerCompileTimeConstant(constant, elements); - return constant; + return new TypeConstant(elementType, constantType); } // TODO(floitsch): provide better error-messages. @@ -520,9 +412,7 @@ Element element = elements[send]; if (send.isPropertyAccess) { if (Elements.isStaticOrTopLevelFunction(element)) { - Constant constant = new FunctionConstant(element); - handler.registerCompileTimeConstant(constant, elements); - return constant; + return new FunctionConstant(element); } else if (Elements.isStaticOrTopLevelField(element)) { Constant result; if (element.modifiers.isConst()) { @@ -532,6 +422,7 @@ } if (result != null) return result; } else if (Elements.isClass(element) || Elements.isTypedef(element)) { + assert(elements.isTypeLiteral(send)); return makeTypeConstant(element); } else if (send.receiver != null) { // Fall through to error handling. @@ -550,7 +441,10 @@ Constant result = constantSystem.identity.fold(left, right); if (result != null) return result; } else if (Elements.isClass(element) || Elements.isTypedef(element)) { - return makeTypeConstant(element); + // The node itself is not a constant but we register the selector (the + // identifier that refers to the class/typedef) as a constant. + Constant typeConstant = makeTypeConstant(element); + elements.setConstant(send.selector, typeConstant); } return signalNotCompileTimeConstant(send); } else if (send.isPrefix) { @@ -668,6 +562,25 @@ return signalNotCompileTimeConstant(send); } + Constant visitConditional(Conditional node) { + Constant condition = evaluate(node.condition); + if (condition == null) { + return null; + } else if (!condition.isBool()) { + DartType conditionType = condition.computeType(compiler); + if (isEvaluatingConstant) { + compiler.reportFatalError( + node.condition, MessageKind.NOT_ASSIGNABLE.error, + {'fromType': conditionType, 'toType': compiler.boolClass.rawType}); + } + return null; + } + Constant thenExpression = evaluate(node.thenExpression); + Constant elseExpression = evaluate(node.elseExpression); + BoolConstant boolCondition = condition; + return boolCondition.value ? thenExpression : elseExpression; + } + Constant visitSendSet(SendSet node) { return signalNotCompileTimeConstant(node); } @@ -744,10 +657,7 @@ evaluator.evaluateConstructorFieldValues(arguments); List<Constant> jsNewArguments = evaluator.buildJsNewArguments(classElement); - handler.registerInstantiatedType(type, elements); - Constant constant = new ConstructedConstant(type, jsNewArguments); - handler.registerCompileTimeConstant(constant, elements); - return constant; + return new ConstructedConstant(type, jsNewArguments); } Constant visitParenthesizedExpression(ParenthesizedExpression node) {
diff --git a/sdk/lib/_internal/compiler/implementation/compiler.dart b/sdk/lib/_internal/compiler/implementation/compiler.dart index 04c0df0..6f673a3 100644 --- a/sdk/lib/_internal/compiler/implementation/compiler.dart +++ b/sdk/lib/_internal/compiler/implementation/compiler.dart
@@ -123,6 +123,13 @@ bool classNeedsRti(ClassElement cls); bool methodNeedsRti(FunctionElement function); + + /// Called during codegen when [constant] has been used. + void registerCompileTimeConstant(Constant constant, TreeElements elements) {} + + /// Called during post-processing when [constant] has been evaluated. + void registerMetadataConstant(Constant constant, TreeElements elements) {} + /// Called during resolution to notify to the backend that a class is /// being instantiated. void registerInstantiatedClass(ClassElement cls, @@ -257,10 +264,6 @@ return new Future.value(); } - void registerMetadataInstantiatedType(DartType type, TreeElements elements) {} - void registerMetadataStaticUse(Element element) {} - void registerMetadataGetOfStaticFunction(FunctionElement element) {} - /// Called by [MirrorUsageAnalyzerTask] after it has merged all @MirrorsUsed /// annotations. The arguments corresponds to the unions of the corresponding /// fields of the annotations. @@ -529,11 +532,9 @@ ti.TypesTask typesTask; Backend backend; ConstantHandler constantHandler; - ConstantHandler metadataHandler; EnqueueTask enqueuer; DeferredLoadTask deferredLoadTask; MirrorUsageAnalyzerTask mirrorUsageAnalyzerTask; - ContainerTracer containerTracer; String buildId; static const SourceString MAIN = const SourceString('main'); @@ -639,15 +640,12 @@ closureToClassMapper = new closureMapping.ClosureTask(this, closureNamer), checker = new TypeCheckerTask(this), typesTask = new ti.TypesTask(this), - containerTracer = new ContainerTracer(this), constantHandler = new ConstantHandler(this, backend.constantSystem), deferredLoadTask = new DeferredLoadTask(this), mirrorUsageAnalyzerTask = new MirrorUsageAnalyzerTask(this), enqueuer = new EnqueueTask(this)]; tasks.addAll(backend.tasks); - metadataHandler = new ConstantHandler( - this, backend.constantSystem, isMetadata: true); } Universe get resolverWorld => enqueuer.resolution.universe;
diff --git a/sdk/lib/_internal/compiler/implementation/constants.dart b/sdk/lib/_internal/compiler/implementation/constants.dart index bca6524..a8ac524 100644 --- a/sdk/lib/_internal/compiler/implementation/constants.dart +++ b/sdk/lib/_internal/compiler/implementation/constants.dart
@@ -45,6 +45,7 @@ bool isNaN() => false; bool isMinusZero() => false; + // TODO(johnniwinther): Replace with a 'type' getter. DartType computeType(Compiler compiler); List<Constant> getDependencies(); @@ -295,6 +296,10 @@ int get length => value.length; accept(ConstantVisitor visitor) => visitor.visitString(this); + + String toString() { + return 'StringConstant(${Error.safeToString(value.slowToString())})'; + } } abstract class ObjectConstant extends Constant { @@ -323,6 +328,8 @@ List<Constant> getDependencies() => const <Constant>[]; accept(ConstantVisitor visitor) => visitor.visitType(this); + + String toString() => 'TypeConstant(${Error.safeToString(representedType)})'; } class ListConstant extends ObjectConstant { @@ -362,6 +369,17 @@ int get length => entries.length; accept(ConstantVisitor visitor) => visitor.visitList(this); + + String toString() { + StringBuffer sb = new StringBuffer(); + sb.write('ListConstant(['); + for (int i = 0 ; i < entries.length ; i++) { + if (i > 0) sb.write(','); + sb.write(Error.safeToString(entries[i])); + } + sb.write('])'); + return sb.toString(); + } } class MapConstant extends ObjectConstant { @@ -437,6 +455,19 @@ int get length => keys.length; accept(ConstantVisitor visitor) => visitor.visitMap(this); + + String toString() { + StringBuffer sb = new StringBuffer(); + sb.write('MapConstant({'); + for (int i = 0 ; i < keys.entries.length ; i++) { + if (i > 0) sb.write(','); + sb.write(Error.safeToString(keys.entries[i])); + sb.write(':'); + sb.write(Error.safeToString(values[i])); + } + sb.write('})'); + return sb.toString(); + } } class InterceptorConstant extends Constant { @@ -460,6 +491,10 @@ accept(ConstantVisitor visitor) => visitor.visitInterceptor(this); DartType computeType(Compiler compiler) => compiler.types.dynamicType; + + String toString() { + return 'InterceptorConstant(${Error.safeToString(dispatchedType)})'; + } } class ConstructedConstant extends ObjectConstant { @@ -510,4 +545,21 @@ }, includeSuperAndInjectedMembers: true); return result; } + + String toString() { + StringBuffer sb = new StringBuffer(); + sb.write('ConstructedConstant('); + sb.write(type); + sb.write('('); + int i = 0; + fieldElements.forEach((Element field, Constant value) { + if (i > 0) sb.write(','); + sb.write(Error.safeToString(field.name.slowToString())); + sb.write('='); + sb.write(Error.safeToString(value)); + i++; + }); + sb.write('))'); + return sb.toString(); + } }
diff --git a/sdk/lib/_internal/compiler/implementation/dart2jslib.dart b/sdk/lib/_internal/compiler/implementation/dart2jslib.dart index 47febfa..7d825c0 100644 --- a/sdk/lib/_internal/compiler/implementation/dart2jslib.dart +++ b/sdk/lib/_internal/compiler/implementation/dart2jslib.dart
@@ -32,7 +32,6 @@ import 'source_file.dart' show SourceFile; import 'js/js.dart' as js; import 'deferred_load.dart' show DeferredLoadTask; -import 'inferrer/container_tracer.dart' show ContainerTracer; import 'mirrors_used.dart' show MirrorUsageAnalyzerTask; export 'resolution/resolution.dart' show TreeElements, TreeElementMapping;
diff --git a/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart b/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart index 6dea904..bbf3c20 100644 --- a/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart +++ b/sdk/lib/_internal/compiler/implementation/dart_backend/backend.dart
@@ -619,7 +619,7 @@ } } -compareBy(f) => (x, y) => f(x).compareTo(f(y)); +Comparator compareBy(f) => (x, y) => f(x).compareTo(f(y)); List sorted(Iterable l, comparison) { final result = new List.from(l);
diff --git a/sdk/lib/_internal/compiler/implementation/dart_backend/renamer.dart b/sdk/lib/_internal/compiler/implementation/dart_backend/renamer.dart index f842ac3..bcaa080 100644 --- a/sdk/lib/_internal/compiler/implementation/dart_backend/renamer.dart +++ b/sdk/lib/_internal/compiler/implementation/dart_backend/renamer.dart
@@ -4,7 +4,7 @@ part of dart_backend; -Function get _compareNodes => +Comparator get _compareNodes => compareBy((n) => n.getBeginToken().charOffset); typedef String _Renamer(Renamable renamable); @@ -90,7 +90,7 @@ StringBuffer result = new StringBuffer(renameElement(type.element)); if (type is InterfaceType) { InterfaceType interfaceType = type; - if (!interfaceType.isRaw) { + if (!interfaceType.treatAsRaw) { result.write('<'); Link<DartType> argumentsLink = interfaceType.typeArguments; result.write(renameType(argumentsLink.head, renameElement)); @@ -306,53 +306,54 @@ } } -/** Always tries to return original identifier name unless it is forbidden. */ -String conservativeGenerator( - String originalName, bool isForbidden(String name)) { - String newName = originalName; - while (isForbidden(newName)) { - newName = 'p_$newName'; +/** + * Generates mini ID based on index. + * In other words, it converts index to visual representation + * as if digits are given characters. + */ +String generateMiniId(int index) { + const String firstCharAlphabet = + r'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; + const String otherCharsAlphabet = + r'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_$'; + // It's like converting index in decimal to [chars] radix. + if (index < firstCharAlphabet.length) return firstCharAlphabet[index]; + StringBuffer resultBuilder = new StringBuffer(); + resultBuilder.writeCharCode( + firstCharAlphabet.codeUnitAt(index % firstCharAlphabet.length)); + index ~/= firstCharAlphabet.length; + int length = otherCharsAlphabet.length; + while (index >= length) { + resultBuilder.writeCharCode(otherCharsAlphabet.codeUnitAt(index % length)); + index ~/= length; } - return newName; + resultBuilder.write(otherCharsAlphabet[index]); + return resultBuilder.toString(); } + +/** Always tries to return original identifier name unless it is forbidden. */ +String conservativeGenerator(String name, bool isForbidden(String name)) { + String result = name; + int index = 0; + while (isForbidden(result)) { + result = '${generateMiniId(index++)}_$name'; + } + return result; +} + + /** Always tries to generate the most compact identifier. */ class MinifyingGenerator { - static const String firstCharAlphabet = - r'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; - static const String otherCharsAlphabet = - r'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_$'; - int nextIdIndex; + int index = 0; - MinifyingGenerator() : nextIdIndex = 0; + MinifyingGenerator(); String generate(bool isForbidden(String name)) { - String newName; + String result; do { - newName = getNextId(); - } while(isForbidden(newName)); - return newName; + result = generateMiniId(index++); + } while (isForbidden(result)); + return result; } - - /** - * Generates next mini ID with current index and alphabet. - * Advances current index. - * In other words, it converts index to visual representation - * as if digits are given characters. - */ - String getNextId() { - // It's like converting index in decimal to [chars] radix. - int index = nextIdIndex++; - StringBuffer resultBuilder = new StringBuffer(); - if (index < firstCharAlphabet.length) return firstCharAlphabet[index]; - resultBuilder.write(firstCharAlphabet[index % firstCharAlphabet.length]); - index ~/= firstCharAlphabet.length; - int length = otherCharsAlphabet.length; - while (index >= length) { - resultBuilder.write(otherCharsAlphabet[index % length]); - index ~/= length; - } - resultBuilder.write(otherCharsAlphabet[index]); - return resultBuilder.toString(); - } -} +} \ No newline at end of file
diff --git a/sdk/lib/_internal/compiler/implementation/dart_types.dart b/sdk/lib/_internal/compiler/implementation/dart_types.dart index f301f9b..f70517e 100644 --- a/sdk/lib/_internal/compiler/implementation/dart_types.dart +++ b/sdk/lib/_internal/compiler/implementation/dart_types.dart
@@ -93,6 +93,9 @@ /// Returns the raw version of this type. DartType asRaw() => this; + /// Is [: true :] if this type has no non-dynamic type arguments. + bool get treatAsRaw => isRaw; + /// Is [: true :] if this type should be treated as the dynamic type. bool get treatAsDynamic => false; @@ -424,6 +427,14 @@ bool get isRaw => typeArguments.isEmpty || identical(this, element.rawType); GenericType asRaw() => element.rawType; + + bool get treatAsRaw { + if (isRaw) return true; + for (Link<DartType> link = typeArguments; !link.isEmpty; link = link.tail) { + if (!link.head.treatAsDynamic) return false; + } + return true; + } } class InterfaceType extends GenericType {
diff --git a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart b/sdk/lib/_internal/compiler/implementation/elements/modelx.dart index 42ef97c..394d4e4 100644 --- a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart +++ b/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
@@ -1574,6 +1574,7 @@ bool get isUnnamedMixinApplication => false; + // TODO(johnniwinther): Add [thisType] getter similar to [rawType]. InterfaceType computeType(Compiler compiler) { if (thisType == null) { if (origin == null) {
diff --git a/sdk/lib/_internal/compiler/implementation/enqueue.dart b/sdk/lib/_internal/compiler/implementation/enqueue.dart index d1ee2cc..e489fb1 100644 --- a/sdk/lib/_internal/compiler/implementation/enqueue.dart +++ b/sdk/lib/_internal/compiler/implementation/enqueue.dart
@@ -4,6 +4,8 @@ part of dart2js; +typedef ItemCompilationContext ItemCompilationContextCreator(); + class EnqueueTask extends CompilerTask { final ResolutionEnqueuer resolution; final CodegenEnqueuer codegen; @@ -71,7 +73,7 @@ abstract class Enqueuer { final String name; final Compiler compiler; // TODO(ahe): Remove this dependency. - final Function itemCompilationContextCreator; + final ItemCompilationContextCreator itemCompilationContextCreator; final Map<String, Link<Element>> instanceMembersByName = new Map<String, Link<Element>>(); final Map<String, Link<Element>> instanceFunctionsByName @@ -85,9 +87,7 @@ bool hasEnqueuedEverything = false; - Enqueuer(this.name, this.compiler, - ItemCompilationContext itemCompilationContextCreator()) - : this.itemCompilationContextCreator = itemCompilationContextCreator; + Enqueuer(this.name, this.compiler, this.itemCompilationContextCreator); Queue<WorkItem> get queue; @@ -104,7 +104,6 @@ */ void addToWorkList(Element element) { assert(invariant(element, element.isDeclaration)); - if (element.isForeign(compiler)) return; internalAddToWorkList(element); } @@ -614,7 +613,7 @@ if (getCachedElements(element) != null) return; if (queueIsClosed) { throw new SpannableAssertionFailure(element, - "Resolution work list is closed."); + "Resolution work list is closed. Trying to add $element."); } compiler.world.registerUsedElement(element); @@ -681,11 +680,14 @@ * The action is performed as part of the post-processing immediately after * the resolution queue has been closed. As a consequence, [action] must not * add elements to the resolution queue. + * + * The queue is processed in FIFO order. */ void addPostProcessAction(Element element, PostProcessAction action) { if (queueIsClosed) { throw new SpannableAssertionFailure(element, - "Resolution work list is closed."); + "Resolution work list is closed. " + "Trying to add post process action for $element"); } postQueue.add(new PostProcessTask(element, action)); } @@ -720,13 +722,16 @@ member.isAbstract(compiler) || generatedCode.containsKey(member); void internalAddToWorkList(Element element) { + // Don't generate code for foreign elements. + if (element.isForeign(compiler)) return; + // Codegen inlines field initializers, so it does not need to add // individual fields in the work list. if (element.isField() && element.isInstanceMember()) return; if (queueIsClosed) { throw new SpannableAssertionFailure(element, - "Codegen work list is closed."); + "Codegen work list is closed. Trying to add $element"); } CodegenWorkItem workItem = new CodegenWorkItem( element, itemCompilationContextCreator());
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/container_tracer.dart b/sdk/lib/_internal/compiler/implementation/inferrer/container_tracer.dart index d491aa4..2325cd9 100644 --- a/sdk/lib/_internal/compiler/implementation/inferrer/container_tracer.dart +++ b/sdk/lib/_internal/compiler/implementation/inferrer/container_tracer.dart
@@ -2,17 +2,7 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -library container_tracer; - -import '../dart2jslib.dart' hide Selector, TypedSelector; -import '../elements/elements.dart'; -import '../tree/tree.dart'; -import '../universe/universe.dart'; -import '../util/util.dart' show Link; -import 'simple_types_inferrer.dart' - show InferrerEngine, InferrerVisitor, LocalsHandler, TypeMaskSystem; -import '../types/types.dart'; -import 'inferrer_visitor.dart'; +part of type_graph_inferrer; /** * A set of selector names that [List] implements, that we know do not @@ -136,672 +126,154 @@ bool _VERBOSE = false; -class InferrerEngineForContainerTracer - implements MinimalInferrerEngine<TypeMask> { +class ContainerTracerVisitor implements TypeInformationVisitor { + final ContainerTypeInformation container; + final TypeGraphInferrerEngine inferrer; final Compiler compiler; - InferrerEngineForContainerTracer(this.compiler); + // The set of [TypeInformation] where the traced container could + // flow in, and operations done on them. + final Set<TypeInformation> allUsers = new Set<TypeInformation>(); - TypeMask typeOfElement(Element element) { - return compiler.typesTask.getGuaranteedTypeOfElement(element); - } + // The list of found assignments to the container. + final List<TypeInformation> assignments = <TypeInformation>[]; - TypeMask returnTypeOfElement(Element element) { - return compiler.typesTask.getGuaranteedReturnTypeOfElement(element); - } - - TypeMask returnTypeOfSelector(Selector selector) { - return compiler.typesTask.getGuaranteedTypeOfSelector(selector); - } - - TypeMask typeOfNode(Node node) { - return compiler.typesTask.getGuaranteedTypeOfNode(null, node); - } - - Iterable<Element> getCallersOf(Element element) { - return compiler.typesTask.typesInferrer.getCallersOf(element); - } - - void recordTypeOfNonFinalField(Node node, - Element field, - TypeMask type) {} -} - -/** - * Global analysis phase that traces container instantiations in order to - * find their element type. - */ -class ContainerTracer extends CompilerTask { - ContainerTracer(Compiler compiler) : super(compiler); - - String get name => 'List tracer'; - - bool analyze() { - measure(() { - if (compiler.disableTypeInference) return; - TypesInferrer inferrer = compiler.typesTask.typesInferrer; - InferrerEngineForContainerTracer engine = - new InferrerEngineForContainerTracer(compiler); - - // Walk over all created [ContainerTypeMask]. - inferrer.containerTypes.forEach((ContainerTypeMask mask) { - // The element type has already been set for const containers. - if (mask.elementType != null) return; - new TracerForConcreteContainer(mask, this, compiler, engine).run(); - }); - }); - } -} - -/** - * A tracer for a specific container. - */ -class TracerForConcreteContainer { - final Compiler compiler; - final ContainerTracer tracer; - final InferrerEngineForContainerTracer inferrer; - final ContainerTypeMask mask; - - final Node analyzedNode; - final Element startElement; - - final List<Element> workList = <Element>[]; - - /** - * A set of elements where this list might escape. - */ - final Set<Element> escapingElements = new Set<Element>(); - - /** - * A set of selectors that both use and update the list, for example - * [: list[0]++; :] or [: list[0] |= 42; :]. - */ - final Set<Selector> constraints = new Set<Selector>(); - - /** - * A cache of setters that were already seen. Caching these - * selectors avoid the filtering done in [addSettersToAnalysis]. - */ - final Set<Selector> seenSetterSelectors = new Set<Selector>(); - - static const int MAX_ANALYSIS_COUNT = 11; - - TypeMask potentialType; - int potentialLength; - bool isLengthTrackingDisabled = false; + bool enableLengthTracking = true; bool continueAnalyzing = true; - TracerForConcreteContainer(ContainerTypeMask mask, - this.tracer, - this.compiler, - this.inferrer) - : analyzedNode = mask.allocationNode, - startElement = mask.allocationElement, - this.mask = mask; + static const int MAX_ANALYSIS_COUNT = 11; + final Set<Element> analyzedElements = new Set<Element>(); + + ContainerTracerVisitor(this.container, inferrer) + : this.inferrer = inferrer, this.compiler = inferrer.compiler; void run() { - int analysisCount = 0; - workList.add(startElement); + // Add the assignments found at allocation site. + assignments.addAll(container.elementType.assignments); + + // Collect the [TypeInformation] where the container can flow in, + // as well as the operations done on all these [TypeInformation]s. + List<TypeInformation> workList = <TypeInformation>[]; + allUsers.add(container); + workList.add(container); while (!workList.isEmpty) { - if (workList.length + analysisCount > MAX_ANALYSIS_COUNT) { + TypeInformation user = workList.removeLast(); + user.users.forEach((TypeInformation info) { + if (allUsers.contains(info)) return; + allUsers.add(info); + analyzedElements.add(info.owner); + if (info.reachedBy(user, inferrer)) { + workList.add(info); + } + }); + if (analyzedElements.length > MAX_ANALYSIS_COUNT) { bailout('Too many users'); break; } - Element currentElement = workList.removeLast().implementation; - new ContainerTracerVisitor(currentElement, this).run(); - if (!continueAnalyzing) break; - analysisCount++; } - if (!continueAnalyzing) { - if (mask.forwardTo == compiler.typesTask.fixedListType) { - mask.length = potentialLength; + if (continueAnalyzing) { + for (TypeInformation info in allUsers) { + info.accept(this); + if (!continueAnalyzing) break; } - mask.elementType = compiler.typesTask.dynamicType; - return; } - // [potentialType] can be null if we did not find any instruction - // that adds elements to the list. - if (potentialType == null) { - if (_VERBOSE) { - print('Found empty type for $analyzedNode $startElement'); - } - mask.elementType = new TypeMask.nonNullEmpty(); - return; + ContainerTypeMask mask = container.type; + if (!enableLengthTracking + && (mask.forwardTo != compiler.typesTask.fixedListType)) { + mask.length = null; } - // Walk over the found constraints and update the type according - // to the selectors of these constraints. - for (Selector constraint in constraints) { - assert(constraint.isOperator()); - constraint = new TypedSelector(potentialType, constraint); - potentialType = potentialType.union( - inferrer.returnTypeOfSelector(constraint), compiler); - } + TypeMask result = continueAnalyzing + ? inferrer.types.computeTypeMask(assignments) + : inferrer.types.dynamicType.type; + + mask.elementType = result; if (_VERBOSE) { - print('$potentialType and $potentialLength ' - 'for $analyzedNode $startElement'); - } - mask.elementType = potentialType; - mask.length = potentialLength; - } - - void disableLengthTracking() { - if (mask.forwardTo == compiler.typesTask.fixedListType) { - // Bogus update to a fixed list. - return; - } - isLengthTrackingDisabled = true; - potentialLength = null; - } - - void setPotentialLength(int value) { - if (isLengthTrackingDisabled) return; - potentialLength = value; - } - - void unionPotentialTypeWith(TypeMask newType) { - assert(newType != null); - potentialType = potentialType == null - ? newType - : newType.union(potentialType, compiler); - if (potentialType == compiler.typesTask.dynamicType) { - bailout('Moved to dynamic'); + print('$result and ${mask.length} ' + 'for ${mask.allocationNode} ${mask.allocationElement}'); } } - void addEscapingElement(element) { - element = element.implementation; - if (escapingElements.contains(element)) return; - escapingElements.add(element); - if (element.isField() || element.isGetter() || element.isFunction()) { - for (Element e in inferrer.getCallersOf(element)) { - addElementToAnalysis(e); - } - } else if (element.isParameter()) { - addElementToAnalysis(element.enclosingElement); - } else if (element.isFieldParameter()) { - addEscapingElement(element.fieldElement); - } - } - - void addSettersToAnalysis(Selector selector) { - assert(selector.isSetter()); - if (seenSetterSelectors.contains(selector)) return; - seenSetterSelectors.add(selector); - for (var e in compiler.world.allFunctions.filter(selector)) { - e = e.implementation; - if (e.isField()) { - addEscapingElement(e); - } else { - FunctionSignature signature = e.computeSignature(compiler); - signature.forEachRequiredParameter((Element e) { - addEscapingElement(e); - }); - } - } - } - - void addElementToAnalysis(Element element) { - workList.add(element); - } - - TypeMask bailout(String reason) { + void bailout(String reason) { if (_VERBOSE) { - print('Bailout on $analyzedNode $startElement because of $reason'); + ContainerTypeMask mask = container.type; + print('Bailing out on ${mask.allocationNode} ${mask.allocationElement} ' + 'because: $reason'); } continueAnalyzing = false; - return compiler.typesTask.dynamicType; + enableLengthTracking = false; } - bool couldBeTheList(resolved) { - if (resolved is Selector) { - return escapingElements.any((e) { - return e.isInstanceMember() && resolved.applies(e, compiler); - }); - } else if (resolved is Node) { - return analyzedNode == resolved; - } else { - assert(resolved is Element); - return escapingElements.contains(resolved); + visitNarrowTypeInformation(NarrowTypeInformation info) {} + visitPhiElementTypeInformation(PhiElementTypeInformation info) {} + visitElementInContainerTypeInformation( + ElementInContainerTypeInformation info) {} + visitContainerTypeInformation(ContainerTypeInformation info) {} + visitConcreteTypeInformation(ConcreteTypeInformation info) {} + + visitClosureCallSiteTypeInformation(ClosureCallSiteTypeInformation info) { + bailout('Passed to a closure'); + } + + visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info) { + analyzedElements.add(info.caller); + Element called = info.calledElement; + if (called.isForeign(compiler) && called.name == const SourceString('JS')) { + bailout('Used in JS ${info.call}'); } } - void recordConstraint(Selector selector) { - constraints.add(selector); - } -} - -class ContainerTracerVisitor - extends InferrerVisitor<TypeMask, InferrerEngineForContainerTracer> { - final Element analyzedElement; - final TracerForConcreteContainer tracer; - final bool visitingClosure; - - ContainerTracerVisitor(element, tracer, [LocalsHandler<TypeMask> locals]) - : super(element, tracer.inferrer, new TypeMaskSystem(tracer.compiler), - tracer.compiler, locals), - this.analyzedElement = element, - this.tracer = tracer, - visitingClosure = locals != null; - - bool escaping = false; - bool visitingInitializers = false; - - void run() { - compiler.withCurrentElement(analyzedElement, () { - visit(analyzedElement.parseNode(compiler)); - }); - } - - /** - * Executes [f] and returns whether it triggered the list to escape. - */ - bool visitAndCatchEscaping(Function f) { - bool oldEscaping = escaping; - escaping = false; - f(); - bool foundEscaping = escaping; - escaping = oldEscaping; - return foundEscaping; - } - - /** - * Visits the [arguments] of [callee], and records the parameters - * that could hold the container as escaping. - * - * Returns whether the container escaped. - */ - bool visitArguments(Link<Node> arguments, /* Element or Selector */ callee) { - List<int> indices = []; - int index = 0; - for (Node node in arguments) { - if (visitAndCatchEscaping(() { visit(node); })) { - indices.add(index); - } - index++; - } - if (!indices.isEmpty) { - Iterable<Element> callees; - if (callee is Element) { - // No need to go further, we know the call will throw. - if (callee.isErroneous()) return false; - callees = [callee]; - } else { - assert(callee is Selector); - callees = compiler.world.allFunctions.filter(callee); - } - for (var e in callees) { - e = e.implementation; - if (e.isField()) { - tracer.bailout('Passed to a closure'); - break; - } - FunctionSignature signature = e.computeSignature(compiler); - index = 0; - int parameterIndex = 0; - signature.forEachRequiredParameter((Element parameter) { - if (index < indices.length && indices[index] == parameterIndex) { - tracer.addEscapingElement(parameter); - index++; - } - parameterIndex++; - }); - if (index != indices.length) { - tracer.bailout('Used in a named parameter or closure'); - } - } - return true; - } else { - return false; - } - } - - TypeMask visitFunctionExpression(FunctionExpression node) { - FunctionElement function = elements[node]; - if (function != analyzedElement) { - // Visiting a closure. - LocalsHandler closureLocals = new LocalsHandler<TypeMask>.from( - locals, node, useOtherTryBlock: false); - new ContainerTracerVisitor(function, tracer, closureLocals).run(); - return types.functionType; - } else { - // Visiting [analyzedElement]. - FunctionSignature signature = function.computeSignature(compiler); - signature.forEachParameter((element) { - locals.update(element, inferrer.typeOfElement(element), node); - }); - visitingInitializers = true; - visit(node.initializers); - visitingInitializers = false; - visit(node.body); - return null; - } - } - - TypeMask visitLiteralList(LiteralList node) { - if (node.isConst()) { - return inferrer.typeOfNode(node); - } - if (tracer.couldBeTheList(node)) { - escaping = true; - int length = 0; - for (Node element in node.elements.nodes) { - tracer.unionPotentialTypeWith(visit(element)); - length++; - } - tracer.setPotentialLength(length); - } else { - node.visitChildren(this); - } - return types.growableListType; - } - - TypeMask visitSendSet(SendSet node) { - bool isReceiver = visitAndCatchEscaping(() { - visit(node.receiver); - }); - return handleSendSet(node, isReceiver); - } - - TypeMask handleSendSet(SendSet node, bool isReceiver) { - TypeMask rhsType; - TypeMask indexType; - - Selector getterSelector = - elements.getGetterSelectorInComplexSendSet(node); - Selector operatorSelector = - elements.getOperatorSelectorInComplexSendSet(node); - Selector setterSelector = elements.getSelector(node); - - String op = node.assignmentOperator.source.stringValue; - bool isIncrementOrDecrement = op == '++' || op == '--'; - bool isIndexEscaping = false; - bool isValueEscaping = false; - if (isIncrementOrDecrement) { - rhsType = types.intType; - if (node.isIndex) { - isIndexEscaping = visitAndCatchEscaping(() { - indexType = visit(node.arguments.head); - }); - } - } else if (node.isIndex) { - isIndexEscaping = visitAndCatchEscaping(() { - indexType = visit(node.arguments.head); - }); - isValueEscaping = visitAndCatchEscaping(() { - rhsType = visit(node.arguments.tail.head); - }); - } else { - isValueEscaping = visitAndCatchEscaping(() { - rhsType = visit(node.arguments.head); - }); - } - - Element element = elements[node]; - - if (node.isIndex) { - if (isReceiver) { - if (op == '=') { - tracer.unionPotentialTypeWith(rhsType); - } else { - tracer.recordConstraint(operatorSelector); - } - } else if (isIndexEscaping || isValueEscaping) { - // If the index or value is escaping, iterate over all - // potential targets, and mark their parameter as escaping. - for (var e in compiler.world.allFunctions.filter(setterSelector)) { - e = e.implementation; - FunctionSignature signature = e.computeSignature(compiler); - int index = 0; - signature.forEachRequiredParameter((Element parameter) { - if (index == 0 && isIndexEscaping) { - tracer.addEscapingElement(parameter); - } - if (index == 1 && isValueEscaping) { - tracer.addEscapingElement(parameter); - } - index++; - }); - } - } - } else if (isReceiver) { - if (setterSelector.name == const SourceString('length')) { - tracer.disableLengthTracking(); - tracer.unionPotentialTypeWith(compiler.typesTask.nullType); - } - } else if (isValueEscaping) { - if (element != null - && element.isField() - && setterSelector == null - && !visitingInitializers) { - // Initializer at declaration of a field. - assert(analyzedElement.isField()); - tracer.addEscapingElement(analyzedElement); - } else if (element != null - && (!element.isInstanceMember() || visitingInitializers)) { - // A local, a static element, or a field in an initializer. - tracer.addEscapingElement(element); - } else { - tracer.addSettersToAnalysis(setterSelector); - } - } - - TypeMask result; - if (node.isPostfix) { - // We don't check if [getterSelector] could be the container because - // a list++ will always throw. - result = inferrer.returnTypeOfSelector(getterSelector); - } else if (op != '=') { - // We don't check if [getterSelector] could be the container because - // a list += 42 will always throw. - result = inferrer.returnTypeOfSelector(operatorSelector); - } else { - if (isValueEscaping) { - escaping = true; - } - result = rhsType; - } - - if (Elements.isLocal(element)) { - locals.update(element, result, node); - } - - return result; - } - - TypeMask visitSuperSend(Send node) { - Element element = elements[node]; - if (!node.isPropertyAccess) { - visitArguments(node.arguments, element); - } - - if (tracer.couldBeTheList(element)) { - escaping = true; - } - - if (element.isField()) { - return inferrer.typeOfElement(element); - } else if (element.isFunction()) { - return inferrer.returnTypeOfElement(element); - } else { - return types.dynamicType; - } - } - - TypeMask visitStaticSend(Send node) { - Element element = elements[node]; - - if (Elements.isGrowableListConstructorCall(element, node, compiler)) { - visitArguments(node.arguments, element); - if (tracer.couldBeTheList(node)) { - escaping = true; - } - return inferrer.typeOfNode(node); - } else if (Elements.isFixedListConstructorCall(element, node, compiler)) { - visitArguments(node.arguments, element); - if (tracer.couldBeTheList(node)) { - tracer.unionPotentialTypeWith(types.nullType); - escaping = true; - LiteralInt length = node.arguments.head.asLiteralInt(); - if (length != null) { - tracer.setPotentialLength(length.value); - } - } - return inferrer.typeOfNode(node); - } else if (Elements.isFilledListConstructorCall(element, node, compiler)) { - if (tracer.couldBeTheList(node)) { - escaping = true; - visit(node.arguments.head); - TypeMask fillWithType = visit(node.arguments.tail.head); - tracer.unionPotentialTypeWith(fillWithType); - LiteralInt length = node.arguments.head.asLiteralInt(); - if (length != null) { - tracer.setPotentialLength(length.value); - } - } else { - visitArguments(node.arguments, element); - } - return inferrer.typeOfNode(node); - } - - bool isEscaping = visitArguments(node.arguments, element); - - if (element.isForeign(compiler)) { - if (isEscaping) return tracer.bailout('Used in a JS'); - } - - if (tracer.couldBeTheList(element)) { - escaping = true; - } - - if (element.isFunction() || element.isConstructor()) { - return inferrer.returnTypeOfElement(element); - } else { - // Closure call or unresolved. - return types.dynamicType; - } - } - - TypeMask visitGetterSend(Send node) { - Element element = elements[node]; - Selector selector = elements.getSelector(node); - if (Elements.isStaticOrTopLevelField(element)) { - if (tracer.couldBeTheList(element)) { - escaping = true; - } - return inferrer.typeOfElement(element); - } else if (Elements.isInstanceSend(node, elements)) { - return visitDynamicSend(node); - } else if (Elements.isStaticOrTopLevelFunction(element)) { - return types.functionType; - } else if (Elements.isErroneousElement(element)) { - return types.dynamicType; - } else if (Elements.isLocal(element)) { - if (tracer.couldBeTheList(element)) { - escaping = true; - } - return locals.use(element); - } else { - node.visitChildren(this); - return types.dynamicType; - } - } - - TypeMask visitClosureSend(Send node) { - assert(node.receiver == null); - visit(node.selector); - bool isEscaping = - visitArguments(node.arguments, elements.getSelector(node)); - - if (isEscaping) return tracer.bailout('Passed to a closure'); - return types.dynamicType; - } - - TypeMask visitDynamicSend(Send node) { - bool isReceiver = visitAndCatchEscaping(() { - visit(node.receiver); - }); - return handleDynamicSend(node, isReceiver); - } - - TypeMask handleDynamicSend(Send node, bool isReceiver) { - Selector selector = elements.getSelector(node); + visitDynamicCallSiteTypeInformation(DynamicCallSiteTypeInformation info) { + Selector selector = info.selector; String selectorName = selector.name.slowToString(); - if (isReceiver && !okSelectorsSet.contains(selectorName)) { - if (selector.isCall() - && (selectorName == 'add' || selectorName == 'insert')) { - TypeMask argumentType; - if (node.arguments.isEmpty - || (selectorName == 'insert' && node.arguments.tail.isEmpty)) { - return tracer.bailout('Invalid "add" or "insert" call on a list'); - } - bool isEscaping = visitAndCatchEscaping(() { - argumentType = visit(node.arguments.head); - if (selectorName == 'insert') { - argumentType = visit(node.arguments.tail.head); + if (allUsers.contains(info.receiver)) { + if (!okSelectorsSet.contains(selectorName)) { + if (selector.isCall()) { + int positionalLength = info.arguments.positional.length; + if (selectorName == 'add') { + if (positionalLength == 1) { + assignments.add(info.arguments.positional[0]); + } + } else if (selectorName == 'insert') { + if (positionalLength == 2) { + assignments.add(info.arguments.positional[1]); + } + } else { + bailout('Used in a not-ok selector'); + return; } - }); - if (isEscaping) { - return tracer.bailout('List containing itself'); + } else if (selector.isIndexSet()) { + assignments.add(info.arguments.positional[1]); + } else if (!selector.isIndex()) { + bailout('Used in a not-ok selector'); + return; } - tracer.unionPotentialTypeWith(argumentType); - } else { - return tracer.bailout('Send with the node as receiver $node'); } - } else if (!node.isPropertyAccess) { - visitArguments(node.arguments, selector); + if (!doNotChangeLengthSelectorsSet.contains(selectorName)) { + enableLengthTracking = false; + } + if (selectorName == 'length' && selector.isSetter()) { + enableLengthTracking = false; + assignments.add(inferrer.types.nullType); + } + } else if (selector.isCall() + && !info.targets.every((element) => element.isFunction())) { + bailout('Passed to a closure'); + return; } - if (isReceiver && !doNotChangeLengthSelectorsSet.contains(selectorName)) { - tracer.disableLengthTracking(); - } - if (tracer.couldBeTheList(selector)) { - escaping = true; - } - return inferrer.returnTypeOfSelector(selector); } - TypeMask visitReturn(Return node) { - if (node.expression == null) { - return types.nullType; - } - - TypeMask type; - bool isEscaping = visitAndCatchEscaping(() { - type = visit(node.expression); - }); - - if (isEscaping) { - if (visitingClosure) { - tracer.bailout('Return from closure'); - } else { - tracer.addEscapingElement(analyzedElement); - } - } - return type; + bool isClosure(Element element) { + if (!element.isFunction()) return false; + Element outermost = element.getOutermostEnclosingMemberOrTopLevel(); + return outermost.declaration != element.declaration; } - TypeMask visitForIn(ForIn node) { - visit(node.expression); - Selector iteratorSelector = elements.getIteratorSelector(node); - Selector currentSelector = elements.getCurrentSelector(node); - - TypeMask iteratorType = inferrer.returnTypeOfSelector(iteratorSelector); - TypeMask currentType = inferrer.returnTypeOfSelector(currentSelector); - - // We nullify the type in case there is no element in the - // iterable. - currentType = currentType.nullable(); - - Node identifier = node.declaredIdentifier; - Element element = elements[identifier]; - if (Elements.isLocal(element)) { - locals.update(element, currentType, node); + visitElementTypeInformation(ElementTypeInformation info) { + if (isClosure(info.element)) { + bailout('Returned from a closure'); } - - return handleLoop(node, () { - visit(node.body); - }); } }
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/inferrer_visitor.dart b/sdk/lib/_internal/compiler/implementation/inferrer/inferrer_visitor.dart index bc58690..2a9d49b 100644 --- a/sdk/lib/_internal/compiler/implementation/inferrer/inferrer_visitor.dart +++ b/sdk/lib/_internal/compiler/implementation/inferrer/inferrer_visitor.dart
@@ -31,10 +31,11 @@ T get stringType; T get typeType; - T nonNullSubtype(DartType type); - T nonNullSubclass(DartType type); - T nonNullExact(DartType type); + T nonNullSubtype(ClassElement type); + T nonNullSubclass(ClassElement type); + T nonNullExact(ClassElement type); T nonNullEmpty(); + bool isNull(T type); Selector newTypedSelector(T receiver, Selector selector); T allocateContainer(T type, @@ -680,7 +681,7 @@ // TODO(kasperl): We should be able to tell that the type of a literal // symbol is always a non-null exact symbol implementation -- not just // any non-null subtype of the symbol interface. - return types.nonNullSubtype(compiler.symbolClass.rawType); + return types.nonNullSubtype(compiler.symbolClass); } T visitTypeReferenceSend(Send node) { @@ -701,11 +702,11 @@ if (_thisType != null) return _thisType; ClassElement cls = outermostElement.getEnclosingClass(); if (compiler.world.isUsedAsMixin(cls)) { - return _thisType = types.nonNullSubtype(cls.rawType); + return _thisType = types.nonNullSubtype(cls); } else if (compiler.world.hasAnySubclass(cls)) { - return _thisType = types.nonNullSubclass(cls.rawType); + return _thisType = types.nonNullSubclass(cls); } else { - return _thisType = types.nonNullExact(cls.rawType); + return _thisType = types.nonNullExact(cls); } } @@ -713,7 +714,7 @@ T get superType { if (_superType != null) return _superType; return _superType = types.nonNullExact( - outermostElement.getEnclosingClass().superclass.rawType); + outermostElement.getEnclosingClass().superclass); } T visitIdentifier(Identifier node) { @@ -730,20 +731,54 @@ isChecks.add(node); } + void potentiallyAddNullCheck(Send node, Node receiver) { + if (!accumulateIsChecks) return; + if (!Elements.isLocal(elements[receiver])) return; + isChecks.add(node); + } + void updateIsChecks(List<Node> tests, {bool usePositive}) { - if (tests == null) return; - for (Send node in tests) { - if (node.isIsNotCheck) { - if (usePositive) continue; - } else { - if (!usePositive) continue; - } - DartType type = elements.getType(node.typeAnnotationFromIsCheckOrCast); - Element element = elements[node.receiver]; + void narrow(Element element, DartType type, Node node) { T existing = locals.use(element); T newType = types.narrowType(existing, type, isNullable: false); locals.update(element, newType, node); } + + if (tests == null) return; + for (Send node in tests) { + if (node.isTypeTest) { + if (node.isIsNotCheck) { + if (usePositive) continue; + } else { + if (!usePositive) continue; + } + DartType type = elements.getType(node.typeAnnotationFromIsCheckOrCast); + narrow(elements[node.receiver], type, node); + } else { + Element receiverElement = elements[node.receiver]; + Element argumentElement = elements[node.arguments.first]; + String operator = node.selector.asOperator().source.stringValue; + if ((operator == '==' && usePositive) + || (operator == '!=' && !usePositive)) { + // Type the elements as null. + if (Elements.isLocal(receiverElement)) { + locals.update(receiverElement, types.nullType, node); + } + if (Elements.isLocal(argumentElement)) { + locals.update(argumentElement, types.nullType, node); + } + } else { + // Narrow the elements to a non-null type. + DartType objectType = compiler.objectClass.rawType; + if (Elements.isLocal(receiverElement)) { + narrow(receiverElement, objectType, node); + } + if (Elements.isLocal(argumentElement)) { + narrow(argumentElement, objectType, node); + } + } + } + } } T visitOperatorSend(Send node) { @@ -979,7 +1014,7 @@ DartType type = elements.getType(node.type); T mask = type == null || type.treatAsDynamic ? types.dynamicType - : types.nonNullSubtype(type.asRaw()); + : types.nonNullSubtype(type.element); locals.update(elements[exception], mask, node); } Node trace = node.trace;
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/simple_types_inferrer.dart b/sdk/lib/_internal/compiler/implementation/inferrer/simple_types_inferrer.dart index 6cdbd1f..932eb33 100644 --- a/sdk/lib/_internal/compiler/implementation/inferrer/simple_types_inferrer.dart +++ b/sdk/lib/_internal/compiler/implementation/inferrer/simple_types_inferrer.dart
@@ -44,7 +44,7 @@ return type; } else { assert(annotation.kind == TypeKind.INTERFACE); - otherType = new TypeMask.nonNullSubtype(annotation); + otherType = new TypeMask.nonNullSubtype(annotation.element); } if (isNullable) otherType = otherType.nullable(); if (type == null) return otherType; @@ -85,10 +85,14 @@ TypeMask get constMapType => compiler.typesTask.constMapType; TypeMask get stringType => compiler.typesTask.stringType; TypeMask get typeType => compiler.typesTask.typeType; + bool isNull(TypeMask mask) => mask.isEmpty && mask.isNullable; - TypeMask nonNullSubtype(DartType type) => new TypeMask.nonNullSubtype(type); - TypeMask nonNullSubclass(DartType type) => new TypeMask.nonNullSubclass(type); - TypeMask nonNullExact(DartType type) => new TypeMask.nonNullExact(type); + TypeMask nonNullSubtype(ClassElement type) + => new TypeMask.nonNullSubtype(type.declaration); + TypeMask nonNullSubclass(ClassElement type) + => new TypeMask.nonNullSubclass(type.declaration); + TypeMask nonNullExact(ClassElement type) + => new TypeMask.nonNullExact(type.declaration); TypeMask nonNullEmpty() => new TypeMask.nonNullEmpty(); TypeMask allocateContainer(TypeMask type, @@ -296,7 +300,7 @@ for (var type in typesReturned) { T mappedType; if (type == native.SpecialType.JsObject) { - mappedType = types.nonNullExact(compiler.objectClass.rawType); + mappedType = types.nonNullExact(compiler.objectClass); } else if (type.element == compiler.stringClass) { mappedType = types.stringType; } else if (type.element == compiler.intClass) { @@ -314,15 +318,15 @@ } else if (type.isDynamic) { return types.dynamicType; } else if (!compiler.world.hasAnySubtype(type.element)) { - mappedType = types.nonNullExact(type.element.rawType); + mappedType = types.nonNullExact(type.element); } else { ClassElement element = type.element; Set<ClassElement> subtypes = compiler.world.subtypesOf(element); Set<ClassElement> subclasses = compiler.world.subclassesOf(element); if (subclasses != null && subtypes.length == subclasses.length) { - mappedType = types.nonNullSubclass(element.rawType); + mappedType = types.nonNullSubclass(element); } else { - mappedType = types.nonNullSubtype(element.rawType); + mappedType = types.nonNullSubtype(element); } } returnType = types.computeLUB(returnType, mappedType); @@ -474,7 +478,7 @@ } }); } - returnType = types.nonNullExact(cls.rawType); + returnType = types.nonNullExact(cls); } else { signature.forEachParameter((element) { locals.update(element, inferrer.typeOfElement(element), node); @@ -535,38 +539,31 @@ } T visitLiteralList(LiteralList node) { - if (node.isConst()) { - // We only set the type once. We don't need to re-visit the children - // when re-analyzing the node. - return inferrer.concreteTypes.putIfAbsent(node, () { - T elementType; - int length = 0; - for (Node element in node.elements.nodes) { - T type = visit(element); - elementType = elementType == null - ? types.allocatePhi(null, null, type) - : types.addPhiInput(null, elementType, type); - length++; - } + // We only set the type once. We don't need to re-visit the children + // when re-analyzing the node. + return inferrer.concreteTypes.putIfAbsent(node, () { + T elementType; + int length = 0; + for (Node element in node.elements.nodes) { + T type = visit(element); elementType = elementType == null - ? types.nonNullEmpty() - : types.simplifyPhi(null, null, elementType); - return types.allocateContainer( - types.constListType, - node, - outermostElement, - elementType, - length); - }); - } else { - node.visitChildren(this); - return inferrer.concreteTypes.putIfAbsent(node, () { - return types.allocateContainer( - types.growableListType, - node, - outermostElement); - }); - } + ? types.allocatePhi(null, null, type) + : types.addPhiInput(null, elementType, type); + length++; + } + elementType = elementType == null + ? types.nonNullEmpty() + : types.simplifyPhi(null, null, elementType); + T containerType = node.isConst() + ? types.constListType + : types.growableListType; + return types.allocateContainer( + containerType, + node, + outermostElement, + elementType, + length); + }); } bool isThisOrSuper(Node node) => node.isThis() || node.isSuper(); @@ -823,12 +820,31 @@ if (Elements.isGrowableListConstructorCall(element, node, compiler)) { return inferrer.concreteTypes.putIfAbsent( node, () => types.allocateContainer( - types.growableListType, node, outermostElement)); + types.growableListType, node, outermostElement, + types.nonNullEmpty(), 0)); } else if (Elements.isFixedListConstructorCall(element, node, compiler) || Elements.isFilledListConstructorCall(element, node, compiler)) { + + int initialLength; + T elementType; + if (Elements.isFixedListConstructorCall(element, node, compiler)) { + LiteralInt length = node.arguments.head.asLiteralInt(); + if (length != null) { + initialLength = length.value; + } + elementType = types.nullType; + } else { + LiteralInt length = node.arguments.head.asLiteralInt(); + if (length != null) { + initialLength = length.value; + } + elementType = arguments.positional[1]; + } + return inferrer.concreteTypes.putIfAbsent( node, () => types.allocateContainer( - types.fixedListType, node, outermostElement)); + types.fixedListType, node, outermostElement, + elementType, initialLength)); } else if (element.isFunction() || element.isConstructor()) { return returnType; } else { @@ -983,6 +999,16 @@ ArgumentsTypes arguments = node.isPropertyAccess ? null : analyzeArguments(node.arguments); + if (selector.name == const SourceString('==') + || selector.name == const SourceString('!=')) { + if (types.isNull(receiverType)) { + potentiallyAddNullCheck(node, node.arguments.head); + return types.boolType; + } else if (types.isNull(arguments.positional[0])) { + potentiallyAddNullCheck(node, node.receiver); + return types.boolType; + } + } return handleDynamicSend(node, selector, receiverType, arguments); }
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_inferrer.dart b/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_inferrer.dart index fc8e211..2eb6270 100644 --- a/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_inferrer.dart +++ b/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_inferrer.dart
@@ -7,7 +7,7 @@ import 'dart:collection' show Queue, LinkedHashSet, IterableBase, HashMap; import '../dart_types.dart' show DartType, InterfaceType, TypeKind; import '../elements/elements.dart'; -import '../tree/tree.dart' show Node; +import '../tree/tree.dart' show LiteralList, Node; import '../types/types.dart' show TypeMask, ContainerTypeMask, TypesInferrer; import '../universe/universe.dart' show Selector, TypedSelector, SideEffects; import '../dart2jslib.dart' show Compiler, SourceString, TreeElementMapping; @@ -18,27 +18,28 @@ import '../dart2jslib.dart' show invariant; part 'type_graph_nodes.dart'; +part 'container_tracer.dart'; /** * A set of selector names that [List] implements, that we know return * their element type. */ -Set<String> returnsElementTypeSet = new Set<String>.from( - const <String>[ - 'first', - 'last', - 'single', - 'singleWhere', - 'elementAt', - '[]', - 'removeAt', - 'removeLast' +Set<Selector> returnsElementTypeSet = new Set<Selector>.from( + <Selector>[ + new Selector.getter(const SourceString('first'), null), + new Selector.getter(const SourceString('last'), null), + new Selector.getter(const SourceString('single'), null), + new Selector.call(const SourceString('singleWhere'), null, 1), + new Selector.call(const SourceString('elementAt'), null, 1), + new Selector.index(), + new Selector.call(const SourceString('removeAt'), null, 1), + new Selector.call(const SourceString('removeLast'), null, 0) ]); bool returnsElementType(Selector selector) { return (selector.mask != null) && selector.mask.isContainer - && returnsElementTypeSet.contains(selector.name.slowToString()); + && returnsElementTypeSet.contains(selector.asUntyped); } class TypeInformationSystem extends TypeSystem<TypeInformation> { @@ -203,7 +204,7 @@ return type; } else { assert(annotation.kind == TypeKind.INTERFACE); - otherType = new TypeMask.nonNullSubtype(annotation); + otherType = new TypeMask.nonNullSubtype(annotation.element); } if (isNullable) otherType = otherType.nullable(); if (type.type.isExact) { @@ -228,28 +229,36 @@ }); } - TypeInformation nonNullSubtype(DartType type) { - return getConcreteTypeFor(new TypeMask.nonNullSubtype(type)); + TypeInformation nonNullSubtype(ClassElement type) { + return getConcreteTypeFor(new TypeMask.nonNullSubtype(type.declaration)); } - TypeInformation nonNullSubclass(DartType type) { - return getConcreteTypeFor(new TypeMask.nonNullSubclass(type)); + TypeInformation nonNullSubclass(ClassElement type) { + return getConcreteTypeFor(new TypeMask.nonNullSubclass(type.declaration)); } - TypeInformation nonNullExact(DartType type) { - return getConcreteTypeFor(new TypeMask.nonNullExact(type)); + TypeInformation nonNullExact(ClassElement type) { + return getConcreteTypeFor(new TypeMask.nonNullExact(type.declaration)); } TypeInformation nonNullEmpty() { return nonNullEmptyType; } + bool isNull(TypeInformation type) { + return type == nullType; + } + TypeInformation allocateContainer(TypeInformation type, Node node, Element enclosing, [TypeInformation elementType, int length]) { ContainerTypeMask mask = new ContainerTypeMask(type.type, node, enclosing); - mask.elementType = elementType == null ? null : elementType.type; + // Set the element type now for const lists, so that the inferrer + // can use it. + mask.elementType = (type.type == compiler.typesTask.constListType) + ? elementType.type + : null; mask.length = length; TypeInformation element = new ElementInContainerTypeInformation(elementType, mask); @@ -388,7 +397,7 @@ compiler.log('Added $addedInGraph elements in inferencing graph.'); compiler.progress.reset(); } - // Force the creation of the [ElementTypeInformation] to ensure it is + // Force the creation of the [ElementTypeInformation] to ensure it is // in the graph. types.getInferredTypeOf(element); @@ -460,6 +469,7 @@ } processLoopInformation(); + types.allocatedContainers.values.forEach(analyzeContainer); } void processLoopInformation() { @@ -498,6 +508,11 @@ } } + void analyzeContainer(ContainerTypeInformation info) { + if (info.elementType.isInConstContainer) return; + new ContainerTracerVisitor(info, this).run(); + } + void buildWorkQueue() { workQueue.addAll(types.typeInformations.values); workQueue.addAll(types.allocatedTypes); @@ -506,7 +521,7 @@ /** * Update the assignments to parameters in the graph. [remove] tells - * wheter assignments must be added or removed. If [init] is true, + * wheter assignments must be added or removed. If [init] is false, * parameters are added to the work queue. */ void updateParameterAssignments(TypeInformation caller,
diff --git a/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart b/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart index fc7bfb5..539db8a 100644 --- a/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart +++ b/sdk/lib/_internal/compiler/implementation/inferrer/type_graph_nodes.dart
@@ -48,7 +48,7 @@ TypeInformation([users, assignments]) : users = (users == null) ? new Set<TypeInformation>() : users, assignments = (assignments == null) ? <TypeInformation>[] : assignments; - + void addUser(TypeInformation user) { assert(!user.isConcrete); @@ -61,10 +61,14 @@ } void addAssignment(TypeInformation assignment) { - if (abandonInferencing) return; // Cheap one-level cycle detection. if (assignment == this) return; - assignments.add(assignment); + if (!abandonInferencing) { + assignments.add(assignment); + } + // Even if we abandon inferencing on this [TypeInformation] we + // need to collect the users, so that phases that track where + // elements flow in still work. assignment.addUser(this); } @@ -92,6 +96,17 @@ assignments = const <TypeInformation>[]; users = const <TypeInformation>[]; } + + bool reachedBy(TypeInformation info, TypeGraphInferrerEngine inferrer) { + return true; + } + + accept(TypeInformationVisitor visitor); + + /// The [Element] where this [TypeInformation] was created. May be + /// for some [TypeInformation] nodes, where we do not need to store + /// the information. + Element get owner => null; } /** @@ -157,7 +172,7 @@ * - Native functions and fields: because native methods contain no Dart * code, and native fields do not have Dart assignments, we just * trust their type annotation. - * + * */ class ElementTypeInformation extends TypeInformation { final Element element; @@ -227,7 +242,7 @@ InterfaceType rawType = element.computeType(inferrer.compiler).asRaw(); return rawType.treatAsDynamic ? inferrer.types.dynamicType.type - : new TypeMask.subtype(rawType); + : new TypeMask.subtype(rawType.element); } else { assert(element.isFunction() || element.isGetter() @@ -268,6 +283,12 @@ } String toString() => 'Element $element $type'; + + accept(TypeInformationVisitor visitor) { + return visitor.visitElementTypeInformation(this); + } + + Element get owner => element.getOutermostEnclosingMemberOrTopLevel(); } /** @@ -301,6 +322,8 @@ /// Return an iterable over the targets of this call. Iterable<Element> get callees; + + Element get owner => caller; } class StaticCallSiteTypeInformation extends CallSiteTypeInformation { @@ -344,6 +367,14 @@ } Iterable<Element> get callees => [calledElement.implementation]; + + bool reachedBy(TypeInformation info, TypeGraphInferrerEngine inferrer) { + return info == inferrer.types.getInferredTypeOf(calledElement); + } + + accept(TypeInformationVisitor visitor) { + return visitor.visitStaticCallSiteTypeInformation(this); + } } class DynamicCallSiteTypeInformation extends CallSiteTypeInformation { @@ -454,7 +485,7 @@ inferrer.updateParameterAssignments( this, element, arguments, typedSelector, remove: false); } - + if (returnsElementType(typedSelector)) { // Find the [ElementInContainerTypeInformation] node and tell // that this node is a user of it. Later, when the element @@ -506,7 +537,17 @@ super.giveUp(inferrer); } - String toString() => 'Call site $call ${receiver.type} $type'; + bool reachedBy(TypeInformation info, TypeGraphInferrerEngine inferrer) { + return targets + .map((element) => inferrer.types.getInferredTypeOf(element)) + .any((other) => other == info); + } + + String toString() => 'Call site $call on ${receiver.type} $type'; + + accept(TypeInformationVisitor visitor) { + return visitor.visitDynamicCallSiteTypeInformation(this); + } } class ClosureCallSiteTypeInformation extends CallSiteTypeInformation { @@ -529,10 +570,14 @@ } Iterable<Element> get callees { - throw new UnsupportedError("Cannot compute callees of a closure."); + throw new UnsupportedError("Cannot compute callees of a closure call."); } String toString() => 'Closure call $call on $closure'; + + accept(TypeInformationVisitor visitor) { + return visitor.visitClosureCallSiteTypeInformation(this); + } } /** @@ -569,6 +614,10 @@ } String toString() => 'Type $type'; + + accept(TypeInformationVisitor visitor) { + return visitor.visitConcreteTypeInformation(this); + } } /** @@ -602,23 +651,28 @@ } String toString() => 'Narrow ${assignments.first} to $typeAnnotation $type'; + + accept(TypeInformationVisitor visitor) { + return visitor.visitNarrowTypeInformation(this); + } } /** - * A [ContainerTypeInformation] is a [ConcreteTypeInformation] created + * A [ContainerTypeInformation] is a [TypeInformation] created * for each `List` instantiations. */ -class ContainerTypeInformation extends ConcreteTypeInformation { - final TypeInformation elementType; +class ContainerTypeInformation extends TypeInformation { + final ElementInContainerTypeInformation elementType; - ContainerTypeInformation(containerType, this.elementType) - : super(containerType); - - void addUser(TypeInformation user) { - elementType.addUser(user); + ContainerTypeInformation(containerType, this.elementType) { + type = containerType; } String toString() => 'Container type $type'; + + accept(TypeInformationVisitor visitor) { + return visitor.visitContainerTypeInformation(this); + } } /** @@ -629,17 +683,27 @@ final ContainerTypeMask container; ElementInContainerTypeInformation(elementType, this.container) { - // [elementType] is not null for const lists. if (elementType != null) addAssignment(elementType); } + bool get isInConstContainer { + LiteralList literal = container.allocationNode.asLiteralList(); + return (literal != null) && literal.isConst(); + } + TypeMask refine(TypeGraphInferrerEngine inferrer) { - if (assignments.isEmpty) return inferrer.types.dynamicType.type; + if (!isInConstContainer) { + return inferrer.types.dynamicType.type; + } return container.elementType = inferrer.types.computeTypeMask(assignments); } String toString() => 'Element in container $type'; + + accept(TypeInformationVisitor visitor) { + return visitor.visitElementInContainerTypeInformation(this); + } } /** @@ -658,4 +722,21 @@ } String toString() => 'Phi $element $type'; + + accept(TypeInformationVisitor visitor) { + return visitor.visitPhiElementTypeInformation(this); + } +} + +abstract class TypeInformationVisitor<T> { + T visitNarrowTypeInformation(NarrowTypeInformation info); + T visitPhiElementTypeInformation(PhiElementTypeInformation info); + T visitElementInContainerTypeInformation( + ElementInContainerTypeInformation info); + T visitContainerTypeInformation(ContainerTypeInformation info); + T visitConcreteTypeInformation(ConcreteTypeInformation info); + T visitClosureCallSiteTypeInformation(ClosureCallSiteTypeInformation info); + T visitStaticCallSiteTypeInformation(StaticCallSiteTypeInformation info); + T visitDynamicCallSiteTypeInformation(DynamicCallSiteTypeInformation info); + T visitElementTypeInformation(ElementTypeInformation info); }
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart index b2cd1d9..754e5aa 100644 --- a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart +++ b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
@@ -319,17 +319,9 @@ /// True if there isn't sufficient @MirrorsUsed data. bool hasInsufficientMirrorsUsed = false; - /// List of instantiated types from metadata. If metadata must be preserved, - /// these types must registered. - final List<Dependency> metadataInstantiatedTypes = <Dependency>[]; - - /// List of elements used from metadata. If metadata must be preserved, - /// these elements must be compiled. - final List<Element> metadataStaticUse = <Element>[]; - - /// List of tear-off functions referenced from metadata. If metadata must be - /// preserved, these elements must be compiled. - final List<FunctionElement> metadataGetOfStaticFunction = <FunctionElement>[]; + /// List of constants from metadata. If metadata must be preserved, + /// these constants must be registered. + final List<Dependency> metadataConstants = <Dependency>[]; /// List of symbols that the user has requested for reflection. final Set<String> symbolsUsed = new Set<String>(); @@ -660,17 +652,17 @@ validateInterceptorImplementsAllObjectMethods(jsInterceptorClass); stringType = new HBoundedType( - new TypeMask.nonNullExact(jsStringClass.rawType)); + new TypeMask.nonNullExact(jsStringClass)); indexablePrimitiveType = new HBoundedType( - new TypeMask.nonNullSubtype(jsIndexableClass.rawType)); + new TypeMask.nonNullSubtype(jsIndexableClass)); readableArrayType = new HBoundedType( - new TypeMask.nonNullSubclass(jsArrayClass.rawType)); + new TypeMask.nonNullSubclass(jsArrayClass)); mutableArrayType = new HBoundedType( - new TypeMask.nonNullSubclass(jsMutableArrayClass.rawType)); + new TypeMask.nonNullSubclass(jsMutableArrayClass)); fixedArrayType = new HBoundedType( - new TypeMask.nonNullExact(jsFixedArrayClass.rawType)); + new TypeMask.nonNullExact(jsFixedArrayClass)); extendableArrayType = new HBoundedType( - new TypeMask.nonNullExact(jsExtendableArrayClass.rawType)); + new TypeMask.nonNullExact(jsExtendableArrayClass)); } void validateInterceptorImplementsAllObjectMethods( @@ -745,6 +737,56 @@ } } + Constant registerCompileTimeConstant(Constant constant, + TreeElements elements) { + registerCompileTimeConstantInternal(constant, elements); + for (Constant dependency in constant.getDependencies()) { + registerCompileTimeConstant(dependency, elements); + } + } + + void registerCompileTimeConstantInternal(Constant constant, + TreeElements elements) { + DartType type = constant.computeType(compiler); + registerInstantiatedConstantType(type, elements); + + if (constant.isFunction()) { + FunctionConstant function = constant; + compiler.enqueuer.codegen.registerGetOfStaticFunction(function.element); + } else if (constant.isInterceptor()) { + // An interceptor constant references the class's prototype chain. + InterceptorConstant interceptor = constant; + registerInstantiatedConstantType(interceptor.dispatchedType, elements); + } else if (constant.isType()) { + TypeConstant typeConstant = constant; + registerTypeLiteral(typeConstant.representedType.element, + compiler.enqueuer.codegen, elements); + } + } + + void registerInstantiatedConstantType(DartType type, TreeElements elements) { + Enqueuer enqueuer = compiler.enqueuer.codegen; + enqueuer.registerInstantiatedType(type, elements); + if (type is InterfaceType && !type.treatAsRaw && + classNeedsRti(type.element)) { + enqueuer.registerStaticUse(getSetRuntimeTypeInfo()); + } + if (type.element == typeImplementation) { + // If we use a type literal in a constant, the compile time + // constant emitter will generate a call to the createRuntimeType + // helper so we register a use of that. + enqueuer.registerStaticUse(getCreateRuntimeType()); + } + } + + void registerMetadataConstant(Constant constant, TreeElements elements) { + if (mustRetainMetadata) { + registerCompileTimeConstant(constant, elements); + } else { + metadataConstants.add(new Dependency(constant, elements)); + } + } + void registerInstantiatedClass(ClassElement cls, Enqueuer enqueuer, TreeElements elements) { @@ -990,7 +1032,7 @@ } } bool isTypeVariable = type.kind == TypeKind.TYPE_VARIABLE; - if (!type.isRaw || type.containsTypeVariables) { + if (!type.treatAsRaw || type.containsTypeVariables) { enqueueInResolution(getSetRuntimeTypeInfo(), elements); enqueueInResolution(getGetRuntimeTypeInfo(), elements); enqueueInResolution(getGetRuntimeTypeArgument(), elements); @@ -1187,8 +1229,12 @@ return; } if (kind.category == ElementCategory.VARIABLE) { - Constant initialValue = compiler.constantHandler.compileWorkItem(work); + Constant initialValue = + compiler.constantHandler.getConstantForVariable(element); if (initialValue != null) { + registerCompileTimeConstant(initialValue, work.resolutionTree); + compiler.constantHandler.addCompileTimeConstantForEmission( + initialValue); return; } else { // If the constant-handler was not able to produce a result we have to @@ -1372,7 +1418,7 @@ : 'stringSuperTypeCheck'; } } else if ((element == compiler.listClass || element == jsArrayClass) && - type.isRaw) { + type.treatAsRaw) { if (nativeCheckOnly) return null; return typeCast ? 'listTypeCast' @@ -1396,7 +1442,7 @@ ? 'interceptedTypeCast' : 'interceptedTypeCheck'; } else { - if (type.kind == TypeKind.INTERFACE && !type.isRaw) { + if (type.kind == TypeKind.INTERFACE && !type.treatAsRaw) { return typeCast ? 'subtypeCast' : 'assertSubtype'; @@ -1612,8 +1658,9 @@ if (mustRetainMetadata) hasRetainedMetadata = true; if (mustRetainMetadata && isNeededForReflection(element)) { for (MetadataAnnotation metadata in element.metadata) { - metadata.ensureResolved(compiler) - .value.accept(new ConstantCopier(compiler.constantHandler)); + metadata.ensureResolved(compiler); + compiler.constantHandler.addCompileTimeConstantForEmission( + metadata.value); } return true; } @@ -1633,30 +1680,6 @@ return new Future.value(); } - void registerMetadataInstantiatedType(DartType type, TreeElements elements) { - if (mustRetainMetadata) { - compiler.constantHandler.registerInstantiatedType(type, elements); - } else { - metadataInstantiatedTypes.add(new Dependency(type, elements)); - } - } - - void registerMetadataStaticUse(Element element) { - if (mustRetainMetadata) { - compiler.constantHandler.registerStaticUse(element); - } else { - metadataStaticUse.add(element); - } - } - - void registerMetadataGetOfStaticFunction(FunctionElement element) { - if (mustRetainMetadata) { - compiler.constantHandler.registerGetOfStaticFunction(element); - } else { - metadataGetOfStaticFunction.add(element); - } - } - void registerMirrorUsage(Set<String> symbols, Set<Element> targets, Set<Element> metaTargets) { @@ -1777,28 +1800,21 @@ compiler.log('Retaining metadata.'); compiler.libraries.values.forEach(retainMetadataOf); - for (Dependency dependency in metadataInstantiatedTypes) { - registerMetadataInstantiatedType(dependency.type, dependency.user); + for (Dependency dependency in metadataConstants) { + registerCompileTimeConstant( + dependency.constant, dependency.user); } - metadataInstantiatedTypes.clear(); - for (Element e in metadataStaticUse) { - registerMetadataStaticUse(e); - } - metadataStaticUse.clear(); - for (Element e in metadataGetOfStaticFunction) { - registerMetadataGetOfStaticFunction(e); - } - metadataGetOfStaticFunction.clear(); + metadataConstants.clear(); } } } -/// Records that [type] is used by [user.element]. +/// Records that [constant] is used by [user.element]. class Dependency { - final DartType type; + final Constant constant; final TreeElements user; - const Dependency(this.type, this.user); + const Dependency(this.constant, this.user); } /// Used to copy metadata to the the actual constant handler.
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/constant_emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/constant_emitter.dart index 16ffce5..bd5c8aab 100644 --- a/sdk/lib/_internal/compiler/implementation/js_backend/constant_emitter.dart +++ b/sdk/lib/_internal/compiler/implementation/js_backend/constant_emitter.dart
@@ -332,7 +332,7 @@ jsAst.Expression maybeAddTypeArguments(InterfaceType type, jsAst.Expression value) { if (type is InterfaceType && - !type.isRaw && + !type.treatAsRaw && backend.classNeedsRti(type.element)) { InterfaceType interface = type; RuntimeTypes rti = backend.rti;
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/js_backend.dart b/sdk/lib/_internal/compiler/implementation/js_backend/js_backend.dart index bee8ea9..b7cf4f2 100644 --- a/sdk/lib/_internal/compiler/implementation/js_backend/js_backend.dart +++ b/sdk/lib/_internal/compiler/implementation/js_backend/js_backend.dart
@@ -11,6 +11,7 @@ import '../../compiler.dart' as api; import '../elements/elements.dart'; import '../elements/modelx.dart' show FunctionElementX; +import '../js_emitter/js_emitter.dart' show Emitter, CodeEmitterTask, ClassBuilder; // TODO(ahe): There seems to be a bug in the VM, so we have to hide "js". import '../dart2jslib.dart' hide Selector, TypedSelector, js; @@ -31,7 +32,6 @@ part 'backend.dart'; part 'constant_emitter.dart'; part 'constant_system_javascript.dart'; -part 'emitter.dart'; part 'minify_namer.dart'; part 'namer.dart'; part 'native_emitter.dart';
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart b/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart index 141cd89..f11ac3b 100644 --- a/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart +++ b/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
@@ -352,21 +352,16 @@ ? library : shortPrivateNameOwners.putIfAbsent(nameString, () => library); - // If a private name could clash with a mangled private name we don't - // use the short name. For example a private name "_lib3_foo" would - // clash with "_foo" from "lib3". - if (owner == library && - !nameString.startsWith('_$LIBRARY_PREFIX') && - !shouldMinify) { + if (owner == library && !shouldMinify && !nameString.contains('\$')) { + // Since the name doesn't contain $ it doesn't clash with any + // of the private names that have the library name as the prefix. return nameString; + } else { + // Make sure to return a private name that starts with _ so it + // cannot clash with any public names. + String libraryName = getNameOfLibrary(library); + return '_$libraryName\$$nameString'; } - - // If a library name does not start with the [LIBRARY_PREFIX] then our - // assumptions about clashing with mangled private members do not hold. - String libraryName = getNameOfLibrary(library); - assert(shouldMinify || libraryName.startsWith(LIBRARY_PREFIX)); - // TODO(erikcorry): Fix this with other manglings to avoid clashes. - return '_lib$libraryName\$$nameString'; } String instanceMethodName(FunctionElement element) { @@ -563,8 +558,6 @@ return new SourceString("${name.slowToString()}_$id"); } - static const String LIBRARY_PREFIX = "lib"; - /** * Returns a preferred JS-id for the given top-level or static element. * The returned id is guaranteed to be a valid JS-id. @@ -589,7 +582,16 @@ name = element.name.slowToString().replaceAll('+', '_'); } } else if (element.isLibrary()) { - name = LIBRARY_PREFIX; + LibraryElement library = element; + name = library.getLibraryOrScriptName(); + if (name.contains('.')) { + // For libraries that have a library tag, we use the last part + // of the fully qualified name as their base name. For all other + // libraries, we use the first part of their filename. + name = library.hasLibraryName() + ? name.substring(name.lastIndexOf('.') + 1) + : name.substring(0, name.indexOf('.')); + } } else { name = element.name.slowToString(); } @@ -777,9 +779,6 @@ kind == ElementKind.TYPEDEF || kind == ElementKind.LIBRARY) { bool fixedName = false; - if (kind == ElementKind.CLASS) { - ClassElement classElement = element; - } if (Elements.isInstanceField(element)) { fixedName = element.hasFixedBackendName(); } @@ -803,10 +802,14 @@ String getNameOfField(VariableElement field) => getNameX(field); + // TODO(ahe): Remove this method. Use get getNameOfMember instead. String getNameOfInstanceMember(Element member) => getNameX(member); + String getNameOfMember(Element member) => getNameX(member); + String getNameOfGlobalField(VariableElement field) => getNameX(field); + // TODO(ahe): Remove this method. Use get getNameOfMember instead. String getNameOfGlobalFunction(FunctionElement element) => getNameX(element); /// Returns true if [element] is stored on CURRENT_ISOLATE ('$'). We intend
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart index 1153082..1f83c5f 100644 --- a/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart +++ b/sdk/lib/_internal/compiler/implementation/js_backend/native_emitter.dart
@@ -35,7 +35,7 @@ Compiler get compiler => emitter.compiler; JavaScriptBackend get backend => compiler.backend; - String get _ => emitter._; + String get _ => emitter.space; String get n => emitter.n; String get N => emitter.N; @@ -325,7 +325,9 @@ } ClassBuilder generateNativeClass(ClassElement classElement) { - assert(!classElement.hasBackendMembers); + // TODO(sra): Issue #13731- this is commented out as part of custom element + // constructor work. + //assert(!classElement.hasBackendMembers); nativeClasses.add(classElement); ClassElement superclass = classElement.superclass;
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart b/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart index 6a52399..fbb9da7 100644 --- a/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart +++ b/sdk/lib/_internal/compiler/implementation/js_backend/runtime_types.dart
@@ -162,7 +162,7 @@ compiler.resolverWorld.isChecks.forEach((DartType type) { if (type.kind == TypeKind.INTERFACE) { InterfaceType itf = type; - if (!itf.isRaw) { + if (!itf.treatAsRaw) { potentiallyAddForRti(itf.element); } } else { @@ -559,7 +559,7 @@ static bool hasTypeArguments(DartType type) { if (type is InterfaceType) { InterfaceType interfaceType = type; - return !interfaceType.isRaw; + return !interfaceType.treatAsRaw; } return false; } @@ -613,7 +613,7 @@ visitInterfaceType(InterfaceType type, _) { jsAst.Expression name = getJavaScriptClassName(type.element); - return type.isRaw ? name : visitList(type.typeArguments, head: name); + return type.treatAsRaw ? name : visitList(type.typeArguments, head: name); } jsAst.Expression visitList(Link<DartType> types, {jsAst.Expression head}) {
diff --git a/sdk/lib/_internal/compiler/implementation/js_emitter/class_builder.dart b/sdk/lib/_internal/compiler/implementation/js_emitter/class_builder.dart new file mode 100644 index 0000000..626de96 --- /dev/null +++ b/sdk/lib/_internal/compiler/implementation/js_emitter/class_builder.dart
@@ -0,0 +1,35 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart2js.js_emitter; + +/** + * A data structure for collecting fragments of a class definition. + */ +class ClassBuilder { + final List<jsAst.Property> properties = <jsAst.Property>[]; + + /// Set to true by user if class is indistinguishable from its superclass. + bool isTrivial = false; + + // Has the same signature as [DefineStubFunction]. + void addProperty(String name, jsAst.Expression value) { + properties.add(new jsAst.Property(js.string(name), value)); + } + + jsAst.Expression toObjectInitializer() { + return new jsAst.ObjectInitializer(properties); + } + + /// This method is temporary. Do not use it unless you're working on + /// transforming code to build jsAst.Nodes. + void writeOn_DO_NOT_USE(CodeBuffer buffer, + Compiler compiler, + String separatedBy) { + for (jsAst.Property property in properties) { + if (!buffer.isEmpty) buffer.write(separatedBy); + buffer.write(jsAst.prettyPrint(property, compiler)); + } + } +}
diff --git a/sdk/lib/_internal/compiler/implementation/js_emitter/closure_invocation_element.dart b/sdk/lib/_internal/compiler/implementation/js_emitter/closure_invocation_element.dart new file mode 100644 index 0000000..bd52fe2 --- /dev/null +++ b/sdk/lib/_internal/compiler/implementation/js_emitter/closure_invocation_element.dart
@@ -0,0 +1,25 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart2js.js_emitter; + +/** + * A function element that represents a closure call. The signature is copied + * from the given element. + */ +class ClosureInvocationElement extends FunctionElementX { + ClosureInvocationElement(SourceString name, + FunctionElement other) + : super.from(name, other, other.enclosingElement), + methodElement = other; + + isInstanceMember() => true; + + Element getOutermostEnclosingMemberOrTopLevel() => methodElement; + + /** + * The [member] this invocation refers to. + */ + Element methodElement; +}
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart b/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart similarity index 77% rename from sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart rename to sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart index a284cbe..dae8663 100644 --- a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart +++ b/sdk/lib/_internal/compiler/implementation/js_emitter/code_emitter_task.dart
@@ -2,86 +2,7 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -part of js_backend; - -/// Enables debugging of fast/slow objects using V8-specific primitives. -const DEBUG_FAST_OBJECTS = false; - -/** - * A function element that represents a closure call. The signature is copied - * from the given element. - */ -class ClosureInvocationElement extends FunctionElementX { - ClosureInvocationElement(SourceString name, - FunctionElement other) - : super.from(name, other, other.enclosingElement), - methodElement = other; - - isInstanceMember() => true; - - Element getOutermostEnclosingMemberOrTopLevel() => methodElement; - - /** - * The [member] this invocation refers to. - */ - Element methodElement; -} - -/** - * A convenient type alias for some functions that emit keyed values. - */ -typedef void DefineStubFunction(String invocationName, jsAst.Expression value); - -/** - * [member] is a field (instance, static, or top level). - * - * [name] is the field name that the [Namer] has picked for this field's - * storage, that is, the JavaScript property name. - * - * [accessorName] is the name of the accessor. For instance fields this is - * mostly the same as [name] except when [member] is shadowing a field in its - * superclass. For other fields, they are rarely the same. - * - * [needsGetter] and [needsSetter] represent if a getter or a setter - * respectively is needed. There are many factors in this, for example, if the - * accessor can be inlined. - * - * [needsCheckedSetter] indicates that a checked getter is needed, and in this - * case, [needsSetter] is always false. [needsCheckedSetter] is only true when - * type assertions are enabled (checked mode). - */ -typedef void AcceptField(VariableElement member, - String name, - String accessorName, - bool needsGetter, - bool needsSetter, - bool needsCheckedSetter); - -/** - * A data structure for collecting fragments of a class definition. - */ -class ClassBuilder { - final List<jsAst.Property> properties = <jsAst.Property>[]; - - /// Set to true by user if class is indistinguishable from its superclass. - bool isTrivial = false; - - // Has the same signature as [DefineStubFunction]. - void addProperty(String name, jsAst.Expression value) { - properties.add(new jsAst.Property(js.string(name), value)); - } - - jsAst.Expression toObjectInitializer() { - return new jsAst.ObjectInitializer(properties); - } -} - -// Function signatures used in the generation of runtime type information. -typedef void FunctionTypeSignatureEmitter(Element method, - FunctionType methodType); -// TODO(johnniwinther): Clean up terminology for rti in the emitter. -typedef void FunctionTypeTestEmitter(FunctionType functionType); -typedef void SubstitutionEmitter(Element element, {bool emitNull}); +part of dart2js.js_emitter; /** * Generates the code for all used classes in the program. Static fields (even @@ -90,6 +11,7 @@ * The code for the containing (used) methods must exist in the [:universe:]. */ class CodeEmitterTask extends CompilerTask { + final ContainerBuilder containerBuilder = new ContainerBuilder(); bool needsDefineClass = false; bool needsMixinSupport = false; bool needsLazyInitializer = false; @@ -124,29 +46,14 @@ // TODO(ngeoffray): remove this field. Set<ClassElement> instantiatedClasses; - final List<jsAst.Expression> boundClosures = <jsAst.Expression>[]; - JavaScriptBackend get backend => compiler.backend; - String get _ => compiler.enableMinification ? "" : " "; + String get _ => space; + String get space => compiler.enableMinification ? "" : " "; String get n => compiler.enableMinification ? "" : "\n"; String get N => compiler.enableMinification ? "\n" : ";\n"; /** - * A cache of closures that are used to closurize instance methods. - * A closure is dynamically bound to the instance used when - * closurized. - */ - final Map<int, String> boundClosureCache; - - /** - * A cache of closures that are used to closurize instance methods - * of interceptors. These closures are dynamically bound to the - * interceptor instance, and the actual receiver of the method. - */ - final Map<int, String> interceptorClosureCache; - - /** * Raw ClassElement symbols occuring in is-checks and type assertions. If the * program contains parameterized checks `x is Set<int>` and * `x is Set<String>` then the ClassElement `Set` will occur once in @@ -219,11 +126,10 @@ CodeEmitterTask(Compiler compiler, Namer namer, this.generateSourceMap) : mainBuffer = new CodeBuffer(), this.namer = namer, - boundClosureCache = new Map<int, String>(), - interceptorClosureCache = new Map<int, String>(), constantEmitter = new ConstantEmitter(compiler, namer), super(compiler) { nativeEmitter = new NativeEmitter(this); + containerBuilder.task = this; } void addComment(String comment, CodeBuffer buffer) { @@ -983,241 +889,6 @@ buffer.write("$isolate = $finishIsolateConstructorName($isolate)$N"); } - /** - * Generate stubs to handle invocation of methods with optional - * arguments. - * - * A method like [: foo([x]) :] may be invoked by the following - * calls: [: foo(), foo(1), foo(x: 1) :]. See the sources of this - * function for detailed examples. - */ - void addParameterStub(FunctionElement member, - Selector selector, - DefineStubFunction defineStub, - Set<String> alreadyGenerated) { - FunctionSignature parameters = member.computeSignature(compiler); - int positionalArgumentCount = selector.positionalArgumentCount; - if (positionalArgumentCount == parameters.parameterCount) { - assert(selector.namedArgumentCount == 0); - return; - } - if (parameters.optionalParametersAreNamed - && selector.namedArgumentCount == parameters.optionalParameterCount) { - // If the selector has the same number of named arguments as the element, - // we don't need to add a stub. The call site will hit the method - // directly. - return; - } - ConstantHandler handler = compiler.constantHandler; - List<SourceString> names = selector.getOrderedNamedArguments(); - - String invocationName = namer.invocationName(selector); - if (alreadyGenerated.contains(invocationName)) return; - alreadyGenerated.add(invocationName); - - bool isInterceptedMethod = backend.isInterceptedMethod(member); - - // If the method is intercepted, we need to also pass the actual receiver. - int extraArgumentCount = isInterceptedMethod ? 1 : 0; - // Use '$receiver' to avoid clashes with other parameter names. Using - // '$receiver' works because [:namer.safeName:] used for getting parameter - // names never returns a name beginning with a single '$'. - String receiverArgumentName = r'$receiver'; - - // The parameters that this stub takes. - List<jsAst.Parameter> parametersBuffer = - new List<jsAst.Parameter>(selector.argumentCount + extraArgumentCount); - // The arguments that will be passed to the real method. - List<jsAst.Expression> argumentsBuffer = - new List<jsAst.Expression>( - parameters.parameterCount + extraArgumentCount); - - int count = 0; - if (isInterceptedMethod) { - count++; - parametersBuffer[0] = new jsAst.Parameter(receiverArgumentName); - argumentsBuffer[0] = js(receiverArgumentName); - interceptorInvocationNames.add(invocationName); - } - - int optionalParameterStart = positionalArgumentCount + extraArgumentCount; - // Includes extra receiver argument when using interceptor convention - int indexOfLastOptionalArgumentInParameters = optionalParameterStart - 1; - - TreeElements elements = - compiler.enqueuer.resolution.getCachedElements(member); - - parameters.orderedForEachParameter((Element element) { - String jsName = backend.namer.safeName(element.name.slowToString()); - assert(jsName != receiverArgumentName); - if (count < optionalParameterStart) { - parametersBuffer[count] = new jsAst.Parameter(jsName); - argumentsBuffer[count] = js(jsName); - } else { - int index = names.indexOf(element.name); - if (index != -1) { - indexOfLastOptionalArgumentInParameters = count; - // The order of the named arguments is not the same as the - // one in the real method (which is in Dart source order). - argumentsBuffer[count] = js(jsName); - parametersBuffer[optionalParameterStart + index] = - new jsAst.Parameter(jsName); - } else { - Constant value = handler.initialVariableValues[element]; - if (value == null) { - argumentsBuffer[count] = constantReference(new NullConstant()); - } else { - if (!value.isNull()) { - // If the value is the null constant, we should not pass it - // down to the native method. - indexOfLastOptionalArgumentInParameters = count; - } - argumentsBuffer[count] = constantReference(value); - } - } - } - count++; - }); - - List body; - if (member.hasFixedBackendName()) { - body = nativeEmitter.generateParameterStubStatements( - member, isInterceptedMethod, invocationName, - parametersBuffer, argumentsBuffer, - indexOfLastOptionalArgumentInParameters); - } else { - body = [js.return_( - js('this')[namer.getNameOfInstanceMember(member)](argumentsBuffer))]; - } - - jsAst.Fun function = js.fun(parametersBuffer, body); - - defineStub(invocationName, function); - - String reflectionName = getReflectionName(selector, invocationName); - if (reflectionName != null) { - var reflectable = - js(backend.isAccessibleByReflection(member) ? '1' : '0'); - defineStub('+$reflectionName', reflectable); - } - } - - void addParameterStubs(FunctionElement member, - DefineStubFunction defineStub) { - // We fill the lists depending on the selector. For example, - // take method foo: - // foo(a, b, {c, d}); - // - // We may have multiple ways of calling foo: - // (1) foo(1, 2); - // (2) foo(1, 2, c: 3); - // (3) foo(1, 2, d: 4); - // (4) foo(1, 2, c: 3, d: 4); - // (5) foo(1, 2, d: 4, c: 3); - // - // What we generate at the call sites are: - // (1) foo$2(1, 2); - // (2) foo$3$c(1, 2, 3); - // (3) foo$3$d(1, 2, 4); - // (4) foo$4$c$d(1, 2, 3, 4); - // (5) foo$4$c$d(1, 2, 3, 4); - // - // The stubs we generate are (expressed in Dart): - // (1) foo$2(a, b) => foo$4$c$d(a, b, null, null) - // (2) foo$3$c(a, b, c) => foo$4$c$d(a, b, c, null); - // (3) foo$3$d(a, b, d) => foo$4$c$d(a, b, null, d); - // (4) No stub generated, call is direct. - // (5) No stub generated, call is direct. - - // Keep a cache of which stubs have already been generated, to - // avoid duplicates. Note that even if selectors are - // canonicalized, we would still need this cache: a typed selector - // on A and a typed selector on B could yield the same stub. - Set<String> generatedStubNames = new Set<String>(); - bool isClosureInvocation = - member.name == namer.closureInvocationSelectorName; - if (backend.isNeededForReflection(member) || - (compiler.enabledFunctionApply && isClosureInvocation)) { - // If [Function.apply] is called, we pessimistically compile all - // possible stubs for this closure. - FunctionSignature signature = member.computeSignature(compiler); - Set<Selector> selectors = signature.optionalParametersAreNamed - ? computeSeenNamedSelectors(member) - : computeOptionalSelectors(signature, member); - for (Selector selector in selectors) { - addParameterStub(member, selector, defineStub, generatedStubNames); - } - if (signature.optionalParametersAreNamed && isClosureInvocation) { - addCatchAllParameterStub(member, signature, defineStub); - } - } else { - Set<Selector> selectors = compiler.codegenWorld.invokedNames[member.name]; - if (selectors == null) return; - for (Selector selector in selectors) { - if (!selector.applies(member, compiler)) continue; - addParameterStub(member, selector, defineStub, generatedStubNames); - } - } - } - - Set<Selector> computeSeenNamedSelectors(FunctionElement element) { - Set<Selector> selectors = compiler.codegenWorld.invokedNames[element.name]; - Set<Selector> result = new Set<Selector>(); - if (selectors == null) return result; - for (Selector selector in selectors) { - if (!selector.applies(element, compiler)) continue; - result.add(selector); - } - return result; - } - - void addCatchAllParameterStub(FunctionElement member, - FunctionSignature signature, - DefineStubFunction defineStub) { - // See Primities.applyFunction in js_helper.dart for details. - List<jsAst.Property> properties = <jsAst.Property>[]; - for (Element element in signature.orderedOptionalParameters) { - String jsName = backend.namer.safeName(element.name.slowToString()); - Constant value = compiler.constantHandler.initialVariableValues[element]; - jsAst.Expression reference = null; - if (value == null) { - reference = new jsAst.LiteralNull(); - } else { - reference = constantReference(value); - } - properties.add(new jsAst.Property(js.string(jsName), reference)); - } - defineStub( - backend.namer.callCatchAllName, - js.fun([], js.return_(new jsAst.ObjectInitializer(properties)))); - } - - /** - * Compute the set of possible selectors in the presence of optional - * non-named parameters. - */ - Set<Selector> computeOptionalSelectors(FunctionSignature signature, - FunctionElement element) { - Set<Selector> selectors = new Set<Selector>(); - // Add the selector that does not have any optional argument. - selectors.add(new Selector(SelectorKind.CALL, - element.name, - element.getLibrary(), - signature.requiredParameterCount, - <SourceString>[])); - - // For each optional parameter, we increment the number of passed - // argument. - for (int i = 1; i <= signature.optionalParameterCount; i++) { - selectors.add(new Selector(SelectorKind.CALL, - element.name, - element.getLibrary(), - signature.requiredParameterCount + i, - <SourceString>[])); - } - return selectors; - } - bool fieldNeedsGetter(VariableElement field) { assert(field.isField()); if (fieldAccessNeverThrows(field)) return false; @@ -1240,55 +911,6 @@ return field is ClosureFieldElement; } - /** - * Documentation wanted -- johnniwinther - * - * Invariant: [member] must be a declaration element. - */ - void addInstanceMember(Element member, ClassBuilder builder) { - assert(invariant(member, member.isDeclaration)); - // TODO(floitsch): we don't need to deal with members of - // uninstantiated classes, that have been overwritten by subclasses. - - if (member.isFunction() - || member.isGenerativeConstructorBody() - || member.isAccessor()) { - if (member.isAbstract(compiler)) return; - jsAst.Expression code = backend.generatedCode[member]; - if (code == null) return; - String name = namer.getNameOfInstanceMember(member); - if (backend.isInterceptedMethod(member)) { - interceptorInvocationNames.add(name); - } - code = extendWithMetadata(member, code); - builder.addProperty(name, code); - String reflectionName = getReflectionName(member, name); - if (reflectionName != null) { - var reflectable = - js(backend.isAccessibleByReflection(member) ? '1' : '0'); - builder.addProperty('+$reflectionName', reflectable); - jsAst.Node defaultValues = reifyDefaultArguments(member); - if (defaultValues != null) { - String unmangledName = member.name.slowToString(); - builder.addProperty('*$unmangledName', defaultValues); - } - } - code = backend.generatedBailoutCode[member]; - if (code != null) { - builder.addProperty(namer.getBailoutName(member), code); - } - FunctionElement function = member; - FunctionSignature parameters = function.computeSignature(compiler); - if (!parameters.optionalParameters.isEmpty) { - addParameterStubs(function, builder.addProperty); - } - } else if (!member.isField()) { - compiler.internalError('unexpected kind: "${member.kind}"', - element: member); - } - emitExtraAccessors(member, builder); - } - /// Returns the "reflection name" of an [Element] or [Selector]. /// The reflection name of a getter 'foo' is 'foo'. /// The reflection name of a setter 'foo' is 'foo='. @@ -1411,7 +1033,7 @@ void visitMember(ClassElement enclosing, Element member) { assert(invariant(classElement, member.isDeclaration)); if (member.isInstanceMember()) { - addInstanceMember(member, builder); + containerBuilder.addMember(member, builder); } } @@ -2367,18 +1989,6 @@ } } - void emitStaticFunction(CodeBuffer buffer, - String name, - jsAst.Expression functionExpression) { - // TODO(ahe): This method (emitStaticFunction) should return a - // jsAst.Expression. - if (!buffer.isEmpty) { - buffer.write(',$n$n'); - } - buffer.write('$name:$_'); - buffer.write(jsAst.prettyPrint(functionExpression, compiler)); - } - void emitStaticFunctions(CodeBuffer eagerBuffer) { bool isStaticFunction(Element element) => !element.isInstanceMember() && !element.isField(); @@ -2391,27 +2001,11 @@ .toSet(); for (Element element in Elements.sortedByPosition(elements)) { - CodeBuffer buffer = bufferForElement(element, eagerBuffer); - jsAst.Expression code = backend.generatedCode[element]; - String name = namer.getNameOfGlobalFunction(element); - code = extendWithMetadata(element, code); - emitStaticFunction(buffer, name, code); - String reflectionName = getReflectionName(element, name); - if (reflectionName != null) { - var reflectable = backend.isAccessibleByReflection(element) ? 1 : 0; - buffer.write(',$n$n"+$reflectionName":${_}$reflectable'); - jsAst.Node defaultValues = reifyDefaultArguments(element); - if (defaultValues != null) { - String unmangledName = element.name.slowToString(); - buffer.write(',$n$n"*$unmangledName":${_}'); - buffer.write(jsAst.prettyPrint(defaultValues, compiler)); - } - } - jsAst.Expression bailoutCode = backend.generatedBailoutCode[element]; - if (bailoutCode != null) { - pendingElementsWithBailouts.remove(element); - emitStaticFunction(buffer, namer.getBailoutName(element), bailoutCode); - } + pendingElementsWithBailouts.remove(element); + ClassBuilder builder = new ClassBuilder(); + containerBuilder.addMember(element, builder); + builder.writeOn_DO_NOT_USE( + bufferForElement(element, eagerBuffer), compiler, ',$n$n'); } if (!pendingElementsWithBailouts.isEmpty) { @@ -2420,355 +2014,11 @@ // Is it possible the primary function was inlined but the bailout was not? for (Element element in Elements.sortedByPosition(pendingElementsWithBailouts)) { - CodeBuffer buffer = bufferForElement(element, eagerBuffer); jsAst.Expression bailoutCode = backend.generatedBailoutCode[element]; - emitStaticFunction(buffer, namer.getBailoutName(element), bailoutCode); - } - } - - final Map<Element, Element> staticGetters = new Map<Element, Element>(); - - void emitStaticFunctionGetters(CodeBuffer eagerBuffer) { - addComment('Static function getters', mainBuffer); - for (FunctionElement element in - Elements.sortedByPosition(staticGetters.keys)) { - Element closure = staticGetters[element]; - CodeBuffer buffer = isDeferred(element) ? deferredConstants : eagerBuffer; - String closureClass = namer.isolateAccess(closure); - String name = namer.getStaticClosureName(element); - - String closureName = namer.getStaticClosureName(element); - jsAst.Node assignment = js( - 'init.globalFunctions["$closureName"] =' - ' ${namer.globalObjectFor(element)}.$name =' - ' new $closureClass(#, "$closureName")', - namer.elementAccess(element)); - buffer.write(jsAst.prettyPrint(assignment, compiler)); - buffer.write('$N'); - } - } - - void emitStaticFunctionClosures() { - Set<FunctionElement> functionsNeedingGetter = - compiler.codegenWorld.staticFunctionsNeedingGetter; - for (FunctionElement element in - Elements.sortedByPosition(functionsNeedingGetter)) { - String superName = namer.getNameOfClass(compiler.closureClass); - String name = 'Closure\$${element.name.slowToString()}'; - assert(instantiatedClasses.contains(compiler.closureClass)); - - ClassElement closureClassElement = new ClosureClassElement( - null, new SourceString(name), compiler, element, - element.getCompilationUnit()); - // Now add the methods on the closure class. The instance method does not - // have the correct name. Since [addParameterStubs] use the name to create - // its stubs we simply create a fake element with the correct name. - // Note: the callElement will not have any enclosingElement. - FunctionElement callElement = - new ClosureInvocationElement(namer.closureInvocationSelectorName, - element); - - String invocationName = namer.instanceMethodName(callElement); - String mangledName = namer.getNameOfClass(closureClassElement); - - // Define the constructor with a name so that Object.toString can - // find the class name of the closure class. - ClassBuilder closureBuilder = new ClassBuilder(); - // If a static function is used as a closure we need to add its name - // in case it is used in spawnFunction. - String methodName = namer.STATIC_CLOSURE_NAME_NAME; - emitClosureClassHeader( - mangledName, superName, <String>[invocationName, methodName], - closureBuilder); - - addParameterStubs(callElement, closureBuilder.addProperty); - - // TODO(ngeoffray): Cache common base classes for closures, bound - // closures, and static closures that have common type checks. - boundClosures.add( - js('$classesCollector.$mangledName = #', - js('[${namer.globalObjectFor(closureClassElement)}, #]', - closureBuilder.toObjectInitializer()))); - - staticGetters[element] = closureClassElement; - - void emitFunctionTypeSignature(Element method, FunctionType methodType) { - RuntimeTypes rti = backend.rti; - // [:() => null:] is dummy encoding of [this] which is never needed for - // the encoding of the type of the static [method]. - jsAst.Expression encoding = - rti.getSignatureEncoding(methodType, js('null')); - String operatorSignature = namer.operatorSignature(); - // TODO(johnniwinther): Make MiniJsParser support function expressions. - closureBuilder.addProperty(operatorSignature, encoding); - } - - void emitIsFunctionTypeTest(FunctionType functionType) { - String operator = namer.operatorIsType(functionType); - closureBuilder.addProperty(operator, js('true')); - } - - FunctionType methodType = element.computeType(compiler); - Map<FunctionType, bool> functionTypeChecks = - getFunctionTypeChecksOn(methodType); - generateFunctionTypeTests(element, methodType, functionTypeChecks, - emitFunctionTypeSignature, emitIsFunctionTypeTest); - } - } - - void emitClosureClassHeader(String mangledName, - String superName, - List<String> fieldNames, - ClassBuilder builder) { - builder.addProperty('', - js.string("$superName;${fieldNames.join(',')}")); - - List<String> fields = fieldNames; - String constructorName = mangledName; - precompiledFunction.add(new jsAst.FunctionDeclaration( - new jsAst.VariableDeclaration(constructorName), - js.fun(fields, fields.map( - (name) => js('this.$name = $name')).toList()))); - precompiledFunction.addAll([ - js('$constructorName.builtin\$cls = "$constructorName"'), - js('\$desc=\$collectedClasses.$constructorName'), - js.if_('\$desc instanceof Array', js('\$desc = \$desc[1]')), - js('$constructorName.prototype = \$desc'), - ]); - - precompiledConstructorNames.add(js(constructorName)); - } - - /** - * Documentation wanted -- johnniwinther - * - * Invariant: [member] must be a declaration element. - */ - void emitDynamicFunctionGetter(FunctionElement member, - DefineStubFunction defineStub) { - assert(invariant(member, member.isDeclaration)); - assert(instantiatedClasses.contains(compiler.boundClosureClass)); - // For every method that has the same name as a property-get we create a - // getter that returns a bound closure. Say we have a class 'A' with method - // 'foo' and somewhere in the code there is a dynamic property get of - // 'foo'. Then we generate the following code (in pseudo Dart/JavaScript): - // - // class A { - // foo(x, y, z) { ... } // Original function. - // get foo { return new BoundClosure499(this, "foo"); } - // } - // class BoundClosure499 extends BoundClosure { - // BoundClosure499(this.self, this.name); - // $call3(x, y, z) { return self[name](x, y, z); } - // } - - // TODO(floitsch): share the closure classes with other classes - // if they share methods with the same signature. Currently we do this only - // if there are no optional parameters. Closures with optional parameters - // are more difficult to canonicalize because they would need to have the - // same default values. - - bool hasOptionalParameters = member.optionalParameterCount(compiler) != 0; - int parameterCount = member.parameterCount(compiler); - - Map<int, String> cache; - // Intercepted methods take an extra parameter, which is the - // receiver of the call. - bool inInterceptor = backend.isInterceptedMethod(member); - if (inInterceptor) { - cache = interceptorClosureCache; - } else { - cache = boundClosureCache; - } - List<String> fieldNames = <String>[]; - compiler.boundClosureClass.forEachInstanceField((_, Element field) { - fieldNames.add(namer.getNameOfInstanceMember(field)); - }); - - DartType memberType = member.computeType(compiler); - Map<FunctionType, bool> functionTypeChecks = - getFunctionTypeChecksOn(memberType); - bool hasFunctionTypeChecks = !functionTypeChecks.isEmpty; - - bool canBeShared = !hasOptionalParameters && !hasFunctionTypeChecks; - - ClassElement classElement = member.getEnclosingClass(); - String closureClass = canBeShared ? cache[parameterCount] : null; - if (closureClass == null) { - // Either the class was not cached yet, or there are optional parameters. - // Create a new closure class. - String name; - if (canBeShared) { - if (inInterceptor) { - name = 'BoundClosure\$i${parameterCount}'; - } else { - name = 'BoundClosure\$${parameterCount}'; - } - } else { - name = 'Bound_${member.name.slowToString()}' - '_${member.enclosingElement.name.slowToString()}'; - } - - ClassElement closureClassElement = new ClosureClassElement( - null, new SourceString(name), compiler, member, - member.getCompilationUnit()); - String mangledName = namer.getNameOfClass(closureClassElement); - String superName = namer.getNameOfClass(closureClassElement.superclass); - - // Define the constructor with a name so that Object.toString can - // find the class name of the closure class. - ClassBuilder boundClosureBuilder = new ClassBuilder(); - emitClosureClassHeader( - mangledName, superName, fieldNames, boundClosureBuilder); - // Now add the methods on the closure class. The instance method does not - // have the correct name. Since [addParameterStubs] use the name to create - // its stubs we simply create a fake element with the correct name. - // Note: the callElement will not have any enclosingElement. - FunctionElement callElement = - new ClosureInvocationElement(namer.closureInvocationSelectorName, - member); - - String invocationName = namer.instanceMethodName(callElement); - - List<String> parameters = <String>[]; - List<jsAst.Expression> arguments = <jsAst.Expression>[]; - arguments.add(js('this')[fieldNames[0]]); - if (inInterceptor) { - arguments.add(js('this')[fieldNames[2]]); - } - for (int i = 0; i < parameterCount; i++) { - String name = 'p$i'; - parameters.add(name); - arguments.add(js(name)); - } - - jsAst.Expression fun = js.fun( - parameters, - js.return_( - js('this')[fieldNames[1]]['call'](arguments))); - boundClosureBuilder.addProperty(invocationName, fun); - - addParameterStubs(callElement, boundClosureBuilder.addProperty); - - void emitFunctionTypeSignature(Element method, FunctionType methodType) { - jsAst.Expression encoding = backend.rti.getSignatureEncoding( - methodType, js('this')[fieldNames[0]]); - String operatorSignature = namer.operatorSignature(); - boundClosureBuilder.addProperty(operatorSignature, encoding); - } - - void emitIsFunctionTypeTest(FunctionType functionType) { - String operator = namer.operatorIsType(functionType); - boundClosureBuilder.addProperty(operator, - new jsAst.LiteralBool(true)); - } - - generateFunctionTypeTests(member, memberType, functionTypeChecks, - emitFunctionTypeSignature, emitIsFunctionTypeTest); - - boundClosures.add( - js('$classesCollector.$mangledName = #', - js('[${namer.globalObjectFor(closureClassElement)}, #]', - boundClosureBuilder.toObjectInitializer()))); - - closureClass = namer.isolateAccess(closureClassElement); - - // Cache it. - if (canBeShared) { - cache[parameterCount] = closureClass; - } - } - - // And finally the getter. - String getterName = namer.getterName(member); - String targetName = namer.instanceMethodName(member); - - List<String> parameters = <String>[]; - List<jsAst.Expression> arguments = <jsAst.Expression>[]; - arguments.add(js('this')); - jsAst.PropertyAccess method = - backend.namer.elementAccess(classElement)['prototype'][targetName]; - - arguments.add(method); - if (inInterceptor) { - String receiverArg = fieldNames[2]; - parameters.add(receiverArg); - arguments.add(js(receiverArg)); - } else { - // Put null in the intercepted receiver field. - arguments.add(new jsAst.LiteralNull()); - } - arguments.add(js.string(targetName)); - - jsAst.Expression getterFunction = js.fun( - parameters, js.return_(js(closureClass).newWith(arguments))); - - defineStub(getterName, getterFunction); - } - - /** - * Documentation wanted -- johnniwinther - * - * Invariant: [member] must be a declaration element. - */ - void emitCallStubForGetter(Element member, - Set<Selector> selectors, - DefineStubFunction defineStub) { - assert(invariant(member, member.isDeclaration)); - LibraryElement memberLibrary = member.getLibrary(); - // If the method is intercepted, the stub gets the - // receiver explicitely and we need to pass it to the getter call. - bool isInterceptedMethod = backend.isInterceptedMethod(member); - - const String receiverArgumentName = r'$receiver'; - - jsAst.Expression buildGetter() { - if (member.isGetter()) { - String getterName = namer.getterName(member); - return js('this')[getterName]( - isInterceptedMethod - ? <jsAst.Expression>[js(receiverArgumentName)] - : <jsAst.Expression>[]); - } else { - String fieldName = member.hasFixedBackendName() - ? member.fixedBackendName() - : namer.instanceFieldName(member); - return js('this')[fieldName]; - } - } - - // Two selectors may match but differ only in type. To avoid generating - // identical stubs for each we track untyped selectors which already have - // stubs. - Set<Selector> generatedSelectors = new Set<Selector>(); - for (Selector selector in selectors) { - if (selector.applies(member, compiler)) { - selector = selector.asUntyped; - if (generatedSelectors.contains(selector)) continue; - generatedSelectors.add(selector); - - String invocationName = namer.invocationName(selector); - Selector callSelector = new Selector.callClosureFrom(selector); - String closureCallName = namer.invocationName(callSelector); - - List<jsAst.Parameter> parameters = <jsAst.Parameter>[]; - List<jsAst.Expression> arguments = <jsAst.Expression>[]; - if (isInterceptedMethod) { - parameters.add(new jsAst.Parameter(receiverArgumentName)); - } - - for (int i = 0; i < selector.argumentCount; i++) { - String name = 'arg$i'; - parameters.add(new jsAst.Parameter(name)); - arguments.add(js(name)); - } - - jsAst.Fun function = js.fun( - parameters, - js.return_(buildGetter()[closureCallName](arguments))); - - defineStub(invocationName, function); - } + new ClassBuilder() + ..addProperty(namer.getBailoutName(element), bailoutCode) + ..writeOn_DO_NOT_USE( + bufferForElement(element, eagerBuffer), compiler, ',$n$n'); } } @@ -2887,25 +2137,6 @@ '''); } - /** - * Documentation wanted -- johnniwinther - * - * Invariant: [member] must be a declaration element. - */ - void emitExtraAccessors(Element member, ClassBuilder builder) { - assert(invariant(member, member.isDeclaration)); - if (member.isGetter() || member.isField()) { - Set<Selector> selectors = compiler.codegenWorld.invokedNames[member.name]; - if (selectors != null && !selectors.isEmpty) { - emitCallStubForGetter(member, selectors, builder.addProperty); - } - } else if (member.isFunction()) { - if (compiler.codegenWorld.hasInvokedGetter(member, compiler)) { - emitDynamicFunctionGetter(member, builder.addProperty); - } - } - } - // Identify the noSuchMethod handlers that are so simple that we can // generate them programatically. bool isTrivialNsmHandler( @@ -2948,7 +2179,7 @@ for (Selector selector in selectors) { TypeMask mask = selector.mask; if (mask == null) { - mask = new TypeMask.subclass(compiler.objectClass.rawType); + mask = new TypeMask.subclass(compiler.objectClass); } if (!mask.needsNoSuchMethodHandling(selector, compiler)) continue; @@ -3760,33 +2991,6 @@ }); } - jsAst.Fun extendWithMetadata(FunctionElement element, jsAst.Fun code) { - if (!backend.retainMetadataOf(element)) return code; - return compiler.withCurrentElement(element, () { - List<int> metadata = <int>[]; - FunctionSignature signature = element.functionSignature; - if (element.isConstructor()) { - metadata.add(reifyType(element.getEnclosingClass().thisType)); - } else { - metadata.add(reifyType(signature.returnType)); - } - signature.forEachParameter((Element parameter) { - metadata - ..add(reifyName(parameter.name)) - ..add(reifyType(parameter.computeType(compiler))); - }); - Link link = element.metadata; - // TODO(ahe): Why is metadata sometimes null? - if (link != null) { - for (; !link.isEmpty; link = link.tail) { - metadata.add(reifyMetadata(link.head)); - } - } - code.body.statements.add(js.string(metadata.join(',')).toStatement()); - return code; - }); - } - void emitMetadata(CodeBuffer buffer) { var literals = backend.typedefTypeLiterals.toList(); Elements.sortedByPosition(literals); @@ -3890,11 +3094,11 @@ } // As a side-effect, emitting classes will produce "bound closures" in - // [boundClosures]. The bound closures are JS AST nodes that add + // [methodClosures]. The bound closures are JS AST nodes that add // properties to $$ [classesCollector]. The bound closures are not // emitted until we have emitted all other classes (native or not). - // Might create boundClosures. + // Might create methodClosures. if (!regularClasses.isEmpty) { for (ClassElement element in regularClasses) { generateClass(element, bufferForElement(element, mainBuffer)); @@ -3902,7 +3106,7 @@ } // Emit native classes on [nativeBuffer]. - // Might create boundClosures. + // Might create methodClosures. final CodeBuffer nativeBuffer = new CodeBuffer(); if (!nativeClasses.isEmpty) { addComment('Native classes', nativeBuffer); @@ -3912,23 +3116,25 @@ nativeEmitter.finishGenerateNativeClasses(); nativeEmitter.assembleCode(nativeBuffer); - // Might create boundClosures. + // Might create methodClosures. if (!deferredClasses.isEmpty) { for (ClassElement element in deferredClasses) { generateClass(element, bufferForElement(element, mainBuffer)); } } - emitStaticFunctionClosures(); + containerBuilder.emitStaticFunctionClosures(); - addComment('Bound closures', mainBuffer); - // Now that we have emitted all classes, we know all the bound + addComment('Method closures', mainBuffer); + // Now that we have emitted all classes, we know all the method // closures that will be needed. - for (jsAst.Node node in boundClosures) { + containerBuilder.methodClosures.forEach((String code, Element closure) { // TODO(ahe): Some of these can be deferred. - mainBuffer.add(jsAst.prettyPrint(node, compiler)); + String mangledName = namer.getNameOfClass(closure); + mainBuffer.add('$classesCollector.$mangledName$_=$_' + '[${namer.globalObjectFor(closure)},$_$code]'); mainBuffer.add("$N$n"); - } + }); // After this assignment we will produce invalid JavaScript code if we use // the classesCollector variable. @@ -3995,7 +3201,7 @@ } } mainBuffer - ..write(getReflectionDataParser()) + ..write(getReflectionDataParser(classesCollector, namer)) ..write('([$n'); List<Element> sortedElements = @@ -4065,7 +3271,7 @@ classesCollector = oldClassesCollector; } - emitStaticFunctionGetters(mainBuffer); + containerBuilder.emitStaticFunctionGetters(mainBuffer); emitRuntimeTypeSupport(mainBuffer); emitGetInterceptorMethods(mainBuffer); @@ -4238,7 +3444,7 @@ '$_${namer.isolateName}.prototype$N$n' // The classesCollector object ($$). '$classesCollector$_=$_{};$n') - ..write(getReflectionDataParser()) + ..write(getReflectionDataParser(classesCollector, namer)) ..write('([$n') ..addBuffer(deferredLibraries) ..write('])$N'); @@ -4296,139 +3502,4 @@ bool get areAnyElementsDeferred { return compiler.deferredLoadTask.areAnyElementsDeferred; } - - // TODO(ahe): Remove this when deferred loading is fully implemented. - void warnNotImplemented(Element element, String message) { - compiler.reportMessage(compiler.spanFromSpannable(element), - MessageKind.GENERIC.error({'text': message}), - api.Diagnostic.WARNING); - } - - // TODO(ahe): This code should be integrated in finishClasses. - String getReflectionDataParser() { - String metadataField = '"${namer.metadataField}"'; - String reflectableField = namer.reflectableField; - String defaultValuesField = namer.defaultValuesField; - String methodsWithOptionalArgumentsField = - namer.methodsWithOptionalArgumentsField; - return ''' -(function (reflectionData) { -''' -// [map] returns an object literal that V8 shouldn't try to optimize with a -// hidden class. This prevents a potential performance problem where V8 tries -// to build a hidden class for an object used as a hashMap. -''' - function map(x){x={x:x};delete x.x;return x} - if (!init.libraries) init.libraries = []; - if (!init.mangledNames) init.mangledNames = map(); - if (!init.mangledGlobalNames) init.mangledGlobalNames = map(); - if (!init.statics) init.statics = map(); - if (!init.interfaces) init.interfaces = map(); - if (!init.globalFunctions) init.globalFunctions = map(); - var libraries = init.libraries; - var mangledNames = init.mangledNames; - var mangledGlobalNames = init.mangledGlobalNames; - var hasOwnProperty = Object.prototype.hasOwnProperty; - var length = reflectionData.length; - for (var i = 0; i < length; i++) { - var data = reflectionData[i]; -''' -// [data] contains these elements: -// 0. The library name (not unique). -// 1. The library URI (unique). -// 2. A function returning the metadata associated with this library. -// 3. The global object to use for this library. -// 4. An object literal listing the members of the library. -// 5. This element is optional and if present it is true and signals that this -// library is the root library (see dart:mirrors IsolateMirror.rootLibrary). -// -// The entries of [data] are built in [assembleProgram] above. -''' - var name = data[0]; - var uri = data[1]; - var metadata = data[2]; - var globalObject = data[3]; - var descriptor = data[4]; - var isRoot = !!data[5]; - var fields = descriptor && descriptor[""]; - var classes = []; - var functions = []; - function processStatics(descriptor) { - for (var property in descriptor) { - if (!hasOwnProperty.call(descriptor, property)) continue; - if (property === "") continue; - var element = descriptor[property]; - var firstChar = property.substring(0, 1); - var previousProperty; - if (firstChar === "+") { - mangledGlobalNames[previousProperty] = property.substring(1); - if (descriptor[property] == 1) ''' // Break long line. -'''descriptor[previousProperty].$reflectableField = 1; - if (element && element.length) ''' // Break long line. -'''init.interfaces[previousProperty] = element; - } else if (firstChar === "@") { - property = property.substring(1); - ${namer.CURRENT_ISOLATE}[property][$metadataField] = element; - } else if (firstChar === "*") { - globalObject[previousProperty].$defaultValuesField = element; - var optionalMethods = descriptor.$methodsWithOptionalArgumentsField; - if (!optionalMethods) { - descriptor.$methodsWithOptionalArgumentsField = optionalMethods = {} - } - optionalMethods[property] = previousProperty; - } else if (typeof element === "function") { - globalObject[previousProperty = property] = element; - functions.push(property); - init.globalFunctions[property] = element; - } else { - previousProperty = property; - var newDesc = {}; - var previousProp; - for (var prop in element) { - if (!hasOwnProperty.call(element, prop)) continue; - firstChar = prop.substring(0, 1); - if (prop === "static") { - processStatics(init.statics[property] = element[prop]); - } else if (firstChar === "+") { - mangledNames[previousProp] = prop.substring(1); - if (element[prop] == 1) ''' // Break long line. -'''element[previousProp].$reflectableField = 1; - } else if (firstChar === "@" && prop !== "@") { - newDesc[prop.substring(1)][$metadataField] = element[prop]; - } else if (firstChar === "*") { - newDesc[previousProp].$defaultValuesField = element[prop]; - var optionalMethods = newDesc.$methodsWithOptionalArgumentsField; - if (!optionalMethods) { - newDesc.$methodsWithOptionalArgumentsField = optionalMethods={} - } - optionalMethods[prop] = previousProp; - } else { - newDesc[previousProp = prop] = element[prop]; - } - } - $classesCollector[property] = [globalObject, newDesc]; - classes.push(property); - } - } - } - processStatics(descriptor); - libraries.push([name, uri, classes, functions, metadata, fields, isRoot, - globalObject]); - } -})'''; - } } - -const String GENERATED_BY = """ -// Generated by dart2js, the Dart to JavaScript compiler. -"""; - -const String HOOKS_API_USAGE = """ -// The code supports the following hooks: -// dartPrint(message) - if this function is defined it is called -// instead of the Dart [print] method. -// dartMainRunner(main) - if this function is defined, the Dart [main] -// method will not be invoked directly. -// Instead, a closure that will invoke [main] is -// passed to [dartMainRunner]. -""";
diff --git a/sdk/lib/_internal/compiler/implementation/js_emitter/container_builder.dart b/sdk/lib/_internal/compiler/implementation/js_emitter/container_builder.dart new file mode 100644 index 0000000..15ad85a --- /dev/null +++ b/sdk/lib/_internal/compiler/implementation/js_emitter/container_builder.dart
@@ -0,0 +1,678 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart2js.js_emitter; + +/// This class should morph into something that makes it easy to build +/// JavaScript representations of libraries, class-sides, and instance-sides. +/// Initially, it is just a placeholder for code that is moved from +/// [CodeEmitterTask]. +class ContainerBuilder { + final Map<Element, Element> staticGetters = new Map<Element, Element>(); + + /// A cache of synthesized closures for top-level, static or + /// instance methods. + final Map<String, Element> methodClosures = <String, Element>{}; + + CodeEmitterTask task; + + Namer get namer => task.namer; + + Compiler get compiler => task.compiler; + + String get N => task.N; + + JavaScriptBackend get backend => task.backend; + + /** + * Generate stubs to handle invocation of methods with optional + * arguments. + * + * A method like [: foo([x]) :] may be invoked by the following + * calls: [: foo(), foo(1), foo(x: 1) :]. See the sources of this + * function for detailed examples. + */ + void addParameterStub(FunctionElement member, + Selector selector, + DefineStubFunction defineStub, + Set<String> alreadyGenerated) { + FunctionSignature parameters = member.computeSignature(compiler); + int positionalArgumentCount = selector.positionalArgumentCount; + if (positionalArgumentCount == parameters.parameterCount) { + assert(selector.namedArgumentCount == 0); + return; + } + if (parameters.optionalParametersAreNamed + && selector.namedArgumentCount == parameters.optionalParameterCount) { + // If the selector has the same number of named arguments as the element, + // we don't need to add a stub. The call site will hit the method + // directly. + return; + } + ConstantHandler handler = compiler.constantHandler; + List<SourceString> names = selector.getOrderedNamedArguments(); + + String invocationName = namer.invocationName(selector); + if (alreadyGenerated.contains(invocationName)) return; + alreadyGenerated.add(invocationName); + + bool isInterceptedMethod = backend.isInterceptedMethod(member); + + // If the method is intercepted, we need to also pass the actual receiver. + int extraArgumentCount = isInterceptedMethod ? 1 : 0; + // Use '$receiver' to avoid clashes with other parameter names. Using + // '$receiver' works because [:namer.safeName:] used for getting parameter + // names never returns a name beginning with a single '$'. + String receiverArgumentName = r'$receiver'; + + // The parameters that this stub takes. + List<jsAst.Parameter> parametersBuffer = + new List<jsAst.Parameter>(selector.argumentCount + extraArgumentCount); + // The arguments that will be passed to the real method. + List<jsAst.Expression> argumentsBuffer = + new List<jsAst.Expression>( + parameters.parameterCount + extraArgumentCount); + + int count = 0; + if (isInterceptedMethod) { + count++; + parametersBuffer[0] = new jsAst.Parameter(receiverArgumentName); + argumentsBuffer[0] = js(receiverArgumentName); + task.interceptorInvocationNames.add(invocationName); + } + + int optionalParameterStart = positionalArgumentCount + extraArgumentCount; + // Includes extra receiver argument when using interceptor convention + int indexOfLastOptionalArgumentInParameters = optionalParameterStart - 1; + + TreeElements elements = + compiler.enqueuer.resolution.getCachedElements(member); + + int parameterIndex = 0; + parameters.orderedForEachParameter((Element element) { + // Use generic names for closures to facilitate code sharing. + String jsName = member is ClosureInvocationElement + ? 'p${parameterIndex++}' + : backend.namer.safeName(element.name.slowToString()); + assert(jsName != receiverArgumentName); + if (count < optionalParameterStart) { + parametersBuffer[count] = new jsAst.Parameter(jsName); + argumentsBuffer[count] = js(jsName); + } else { + int index = names.indexOf(element.name); + if (index != -1) { + indexOfLastOptionalArgumentInParameters = count; + // The order of the named arguments is not the same as the + // one in the real method (which is in Dart source order). + argumentsBuffer[count] = js(jsName); + parametersBuffer[optionalParameterStart + index] = + new jsAst.Parameter(jsName); + } else { + Constant value = handler.initialVariableValues[element]; + if (value == null) { + argumentsBuffer[count] = task.constantReference(new NullConstant()); + } else { + if (!value.isNull()) { + // If the value is the null constant, we should not pass it + // down to the native method. + indexOfLastOptionalArgumentInParameters = count; + } + argumentsBuffer[count] = task.constantReference(value); + } + } + } + count++; + }); + + List body; + if (member.hasFixedBackendName()) { + body = task.nativeEmitter.generateParameterStubStatements( + member, isInterceptedMethod, invocationName, + parametersBuffer, argumentsBuffer, + indexOfLastOptionalArgumentInParameters); + } else { + body = [js.return_( + js('this')[namer.getNameOfInstanceMember(member)](argumentsBuffer))]; + } + + jsAst.Fun function = js.fun(parametersBuffer, body); + + defineStub(invocationName, function); + + String reflectionName = task.getReflectionName(selector, invocationName); + if (reflectionName != null) { + var reflectable = + js(backend.isAccessibleByReflection(member) ? '1' : '0'); + defineStub('+$reflectionName', reflectable); + } + } + + void addParameterStubs(FunctionElement member, + DefineStubFunction defineStub) { + // We fill the lists depending on the selector. For example, + // take method foo: + // foo(a, b, {c, d}); + // + // We may have multiple ways of calling foo: + // (1) foo(1, 2); + // (2) foo(1, 2, c: 3); + // (3) foo(1, 2, d: 4); + // (4) foo(1, 2, c: 3, d: 4); + // (5) foo(1, 2, d: 4, c: 3); + // + // What we generate at the call sites are: + // (1) foo$2(1, 2); + // (2) foo$3$c(1, 2, 3); + // (3) foo$3$d(1, 2, 4); + // (4) foo$4$c$d(1, 2, 3, 4); + // (5) foo$4$c$d(1, 2, 3, 4); + // + // The stubs we generate are (expressed in Dart): + // (1) foo$2(a, b) => foo$4$c$d(a, b, null, null) + // (2) foo$3$c(a, b, c) => foo$4$c$d(a, b, c, null); + // (3) foo$3$d(a, b, d) => foo$4$c$d(a, b, null, d); + // (4) No stub generated, call is direct. + // (5) No stub generated, call is direct. + + // Keep a cache of which stubs have already been generated, to + // avoid duplicates. Note that even if selectors are + // canonicalized, we would still need this cache: a typed selector + // on A and a typed selector on B could yield the same stub. + Set<String> generatedStubNames = new Set<String>(); + bool isClosureInvocation = + member.name == namer.closureInvocationSelectorName; + if (backend.isNeededForReflection(member) || + (compiler.enabledFunctionApply && isClosureInvocation)) { + // If [Function.apply] is called, we pessimistically compile all + // possible stubs for this closure. + FunctionSignature signature = member.computeSignature(compiler); + Set<Selector> selectors = signature.optionalParametersAreNamed + ? computeSeenNamedSelectors(member) + : computeOptionalSelectors(signature, member); + for (Selector selector in selectors) { + addParameterStub(member, selector, defineStub, generatedStubNames); + } + if (signature.optionalParametersAreNamed && isClosureInvocation) { + addCatchAllParameterStub(member, signature, defineStub); + } + } else { + Set<Selector> selectors = compiler.codegenWorld.invokedNames[member.name]; + if (selectors == null) return; + for (Selector selector in selectors) { + if (!selector.applies(member, compiler)) continue; + addParameterStub(member, selector, defineStub, generatedStubNames); + } + } + } + + Set<Selector> computeSeenNamedSelectors(FunctionElement element) { + Set<Selector> selectors = compiler.codegenWorld.invokedNames[element.name]; + Set<Selector> result = new Set<Selector>(); + if (selectors == null) return result; + for (Selector selector in selectors) { + if (!selector.applies(element, compiler)) continue; + result.add(selector); + } + return result; + } + + void addCatchAllParameterStub(FunctionElement member, + FunctionSignature signature, + DefineStubFunction defineStub) { + // See Primities.applyFunction in js_helper.dart for details. + List<jsAst.Property> properties = <jsAst.Property>[]; + for (Element element in signature.orderedOptionalParameters) { + String jsName = backend.namer.safeName(element.name.slowToString()); + Constant value = compiler.constantHandler.initialVariableValues[element]; + jsAst.Expression reference = null; + if (value == null) { + reference = new jsAst.LiteralNull(); + } else { + reference = task.constantReference(value); + } + properties.add(new jsAst.Property(js.string(jsName), reference)); + } + defineStub( + backend.namer.callCatchAllName, + js.fun([], js.return_(new jsAst.ObjectInitializer(properties)))); + } + + /** + * Compute the set of possible selectors in the presence of optional + * non-named parameters. + */ + Set<Selector> computeOptionalSelectors(FunctionSignature signature, + FunctionElement element) { + Set<Selector> selectors = new Set<Selector>(); + // Add the selector that does not have any optional argument. + selectors.add(new Selector(SelectorKind.CALL, + element.name, + element.getLibrary(), + signature.requiredParameterCount, + <SourceString>[])); + + // For each optional parameter, we increment the number of passed + // argument. + for (int i = 1; i <= signature.optionalParameterCount; i++) { + selectors.add(new Selector(SelectorKind.CALL, + element.name, + element.getLibrary(), + signature.requiredParameterCount + i, + <SourceString>[])); + } + return selectors; + } + + void emitStaticFunctionGetters(CodeBuffer eagerBuffer) { + task.addComment('Static function getters', task.mainBuffer); + for (FunctionElement element in + Elements.sortedByPosition(staticGetters.keys)) { + Element closure = staticGetters[element]; + CodeBuffer buffer = + task.isDeferred(element) ? task.deferredConstants : eagerBuffer; + String closureClass = namer.isolateAccess(closure); + String name = namer.getStaticClosureName(element); + + String closureName = namer.getStaticClosureName(element); + jsAst.Node assignment = js( + 'init.globalFunctions["$closureName"] =' + ' ${namer.globalObjectFor(element)}.$name =' + ' new $closureClass(#, "$closureName")', + namer.elementAccess(element)); + buffer.write(jsAst.prettyPrint(assignment, compiler)); + buffer.write('$N'); + } + } + + void emitStaticFunctionClosures() { + Set<FunctionElement> functionsNeedingGetter = + compiler.codegenWorld.staticFunctionsNeedingGetter; + for (FunctionElement element in + Elements.sortedByPosition(functionsNeedingGetter)) { + String superName = namer.getNameOfClass(compiler.closureClass); + int parameterCount = element.functionSignature.parameterCount; + String name = 'Closure\$$parameterCount'; + assert(task.instantiatedClasses.contains(compiler.closureClass)); + + ClassElement closureClassElement = new ClosureClassElement( + null, new SourceString(name), compiler, element, + element.getCompilationUnit()); + // Now add the methods on the closure class. The instance method does not + // have the correct name. Since [addParameterStubs] use the name to create + // its stubs we simply create a fake element with the correct name. + // Note: the callElement will not have any enclosingElement. + FunctionElement callElement = + new ClosureInvocationElement(namer.closureInvocationSelectorName, + element); + + String invocationName = namer.instanceMethodName(callElement); + String mangledName = namer.getNameOfClass(closureClassElement); + + // Define the constructor with a name so that Object.toString can + // find the class name of the closure class. + ClassBuilder closureBuilder = new ClassBuilder(); + // If a static function is used as a closure we need to add its name + // in case it is used in spawnFunction. + String methodName = namer.STATIC_CLOSURE_NAME_NAME; + List<String> fieldNames = <String>[invocationName, methodName]; + closureBuilder.addProperty('', + js.string("$superName;${fieldNames.join(',')}")); + + addParameterStubs(callElement, closureBuilder.addProperty); + + void emitFunctionTypeSignature(Element method, FunctionType methodType) { + RuntimeTypes rti = backend.rti; + // [:() => null:] is dummy encoding of [this] which is never needed for + // the encoding of the type of the static [method]. + jsAst.Expression encoding = + rti.getSignatureEncoding(methodType, js('null')); + String operatorSignature = namer.operatorSignature(); + // TODO(johnniwinther): Make MiniJsParser support function expressions. + closureBuilder.addProperty(operatorSignature, encoding); + } + + void emitIsFunctionTypeTest(FunctionType functionType) { + String operator = namer.operatorIsType(functionType); + closureBuilder.addProperty(operator, js('true')); + } + + FunctionType methodType = element.computeType(compiler); + Map<FunctionType, bool> functionTypeChecks = + task.getFunctionTypeChecksOn(methodType); + task.generateFunctionTypeTests(element, methodType, functionTypeChecks, + emitFunctionTypeSignature, emitIsFunctionTypeTest); + + closureClassElement = + addClosureIfNew(closureBuilder, closureClassElement, fieldNames); + staticGetters[element] = closureClassElement; + + } + } + + ClassElement addClosureIfNew(ClassBuilder builder, + ClassElement closure, + List<String> fieldNames) { + String key = + jsAst.prettyPrint(builder.toObjectInitializer(), compiler).getText(); + return methodClosures.putIfAbsent(key, () { + String mangledName = namer.getNameOfClass(closure); + emitClosureInPrecompiledFunction(mangledName, fieldNames); + return closure; + }); + } + + void emitClosureInPrecompiledFunction(String mangledName, + List<String> fieldNames) { + List<String> fields = fieldNames; + String constructorName = mangledName; + task.precompiledFunction.add(new jsAst.FunctionDeclaration( + new jsAst.VariableDeclaration(constructorName), + js.fun(fields, fields.map( + (name) => js('this.$name = $name')).toList()))); + task.precompiledFunction.addAll([ + js('$constructorName.builtin\$cls = "$constructorName"'), + js('\$desc=\$collectedClasses.$constructorName'), + js.if_('\$desc instanceof Array', js('\$desc = \$desc[1]')), + js('$constructorName.prototype = \$desc'), + ]); + + task.precompiledConstructorNames.add(js(constructorName)); + } + + /** + * Documentation wanted -- johnniwinther + * + * Invariant: [member] must be a declaration element. + */ + void emitDynamicFunctionGetter(FunctionElement member, + DefineStubFunction defineStub) { + assert(invariant(member, member.isDeclaration)); + assert(task.instantiatedClasses.contains(compiler.boundClosureClass)); + // For every method that has the same name as a property-get we create a + // getter that returns a bound closure. Say we have a class 'A' with method + // 'foo' and somewhere in the code there is a dynamic property get of + // 'foo'. Then we generate the following code (in pseudo Dart/JavaScript): + // + // class A { + // foo(x, y, z) { ... } // Original function. + // get foo { return new BoundClosure499(this, "foo"); } + // } + // class BoundClosure499 extends BoundClosure { + // BoundClosure499(this.self, this.name); + // $call3(x, y, z) { return self[name](x, y, z); } + // } + + bool hasOptionalParameters = member.optionalParameterCount(compiler) != 0; + int parameterCount = member.parameterCount(compiler); + + // Intercepted methods take an extra parameter, which is the + // receiver of the call. + bool inInterceptor = backend.isInterceptedMethod(member); + List<String> fieldNames = <String>[]; + compiler.boundClosureClass.forEachInstanceField((_, Element field) { + fieldNames.add(namer.getNameOfInstanceMember(field)); + }); + + ClassElement classElement = member.getEnclosingClass(); + String name = inInterceptor + ? 'BoundClosure\$i${parameterCount}' + : 'BoundClosure\$${parameterCount}'; + + ClassElement closureClassElement = new ClosureClassElement( + null, new SourceString(name), compiler, member, + member.getCompilationUnit()); + String superName = namer.getNameOfClass(closureClassElement.superclass); + + // Define the constructor with a name so that Object.toString can + // find the class name of the closure class. + ClassBuilder boundClosureBuilder = new ClassBuilder(); + boundClosureBuilder.addProperty('', + js.string("$superName;${fieldNames.join(',')}")); + // Now add the methods on the closure class. The instance method does not + // have the correct name. Since [addParameterStubs] use the name to create + // its stubs we simply create a fake element with the correct name. + // Note: the callElement will not have any enclosingElement. + FunctionElement callElement = new ClosureInvocationElement( + namer.closureInvocationSelectorName, member); + + String invocationName = namer.instanceMethodName(callElement); + + List<String> parameters = <String>[]; + List<jsAst.Expression> arguments = + <jsAst.Expression>[js('this')[fieldNames[0]]]; + if (inInterceptor) { + arguments.add(js('this')[fieldNames[2]]); + } + for (int i = 0; i < parameterCount; i++) { + String name = 'p$i'; + parameters.add(name); + arguments.add(js(name)); + } + + jsAst.Expression fun = js.fun( + parameters, + js.return_( + js('this')[fieldNames[1]]['call'](arguments))); + boundClosureBuilder.addProperty(invocationName, fun); + + addParameterStubs(callElement, boundClosureBuilder.addProperty); + + void emitFunctionTypeSignature(Element method, FunctionType methodType) { + jsAst.Expression encoding = backend.rti.getSignatureEncoding( + methodType, js('this')[fieldNames[0]]); + String operatorSignature = namer.operatorSignature(); + boundClosureBuilder.addProperty(operatorSignature, encoding); + } + + void emitIsFunctionTypeTest(FunctionType functionType) { + String operator = namer.operatorIsType(functionType); + boundClosureBuilder.addProperty(operator, + new jsAst.LiteralBool(true)); + } + + DartType memberType = member.computeType(compiler); + Map<FunctionType, bool> functionTypeChecks = + task.getFunctionTypeChecksOn(memberType); + + task.generateFunctionTypeTests(member, memberType, functionTypeChecks, + emitFunctionTypeSignature, emitIsFunctionTypeTest); + + closureClassElement = + addClosureIfNew(boundClosureBuilder, closureClassElement, fieldNames); + + String closureClass = namer.isolateAccess(closureClassElement); + + // And finally the getter. + String getterName = namer.getterName(member); + String targetName = namer.instanceMethodName(member); + + parameters = <String>[]; + jsAst.PropertyAccess method = + backend.namer.elementAccess(classElement)['prototype'][targetName]; + arguments = <jsAst.Expression>[js('this'), method]; + + if (inInterceptor) { + String receiverArg = fieldNames[2]; + parameters.add(receiverArg); + arguments.add(js(receiverArg)); + } else { + // Put null in the intercepted receiver field. + arguments.add(new jsAst.LiteralNull()); + } + + arguments.add(js.string(targetName)); + + jsAst.Expression getterFunction = js.fun( + parameters, js.return_(js(closureClass).newWith(arguments))); + + defineStub(getterName, getterFunction); + } + + /** + * Documentation wanted -- johnniwinther + * + * Invariant: [member] must be a declaration element. + */ + void emitCallStubForGetter(Element member, + Set<Selector> selectors, + DefineStubFunction defineStub) { + assert(invariant(member, member.isDeclaration)); + LibraryElement memberLibrary = member.getLibrary(); + // If the method is intercepted, the stub gets the + // receiver explicitely and we need to pass it to the getter call. + bool isInterceptedMethod = backend.isInterceptedMethod(member); + + const String receiverArgumentName = r'$receiver'; + + jsAst.Expression buildGetter() { + if (member.isGetter()) { + String getterName = namer.getterName(member); + return js('this')[getterName]( + isInterceptedMethod + ? <jsAst.Expression>[js(receiverArgumentName)] + : <jsAst.Expression>[]); + } else { + String fieldName = member.hasFixedBackendName() + ? member.fixedBackendName() + : namer.instanceFieldName(member); + return js('this')[fieldName]; + } + } + + // Two selectors may match but differ only in type. To avoid generating + // identical stubs for each we track untyped selectors which already have + // stubs. + Set<Selector> generatedSelectors = new Set<Selector>(); + for (Selector selector in selectors) { + if (selector.applies(member, compiler)) { + selector = selector.asUntyped; + if (generatedSelectors.contains(selector)) continue; + generatedSelectors.add(selector); + + String invocationName = namer.invocationName(selector); + Selector callSelector = new Selector.callClosureFrom(selector); + String closureCallName = namer.invocationName(callSelector); + + List<jsAst.Parameter> parameters = <jsAst.Parameter>[]; + List<jsAst.Expression> arguments = <jsAst.Expression>[]; + if (isInterceptedMethod) { + parameters.add(new jsAst.Parameter(receiverArgumentName)); + } + + for (int i = 0; i < selector.argumentCount; i++) { + String name = 'arg$i'; + parameters.add(new jsAst.Parameter(name)); + arguments.add(js(name)); + } + + jsAst.Fun function = js.fun( + parameters, + js.return_(buildGetter()[closureCallName](arguments))); + + defineStub(invocationName, function); + } + } + } + + /** + * Documentation wanted -- johnniwinther + * + * Invariant: [member] must be a declaration element. + */ + void emitExtraAccessors(Element member, ClassBuilder builder) { + assert(invariant(member, member.isDeclaration)); + if (member.isGetter() || member.isField()) { + Set<Selector> selectors = compiler.codegenWorld.invokedNames[member.name]; + if (selectors != null && !selectors.isEmpty) { + emitCallStubForGetter(member, selectors, builder.addProperty); + } + } else if (member.isFunction()) { + if (compiler.codegenWorld.hasInvokedGetter(member, compiler)) { + emitDynamicFunctionGetter(member, builder.addProperty); + } + } + } + + void addMember(Element member, ClassBuilder builder) { + assert(invariant(member, member.isDeclaration)); + + if (member.isField()) { + addMemberField(member, builder); + } else if (member.isFunction() || + member.isGenerativeConstructorBody() || + member.isGenerativeConstructor() || + member.isAccessor()) { + addMemberMethod(member, builder); + } else { + compiler.internalErrorOnElement( + member, 'unexpected kind: "${member.kind}"'); + } + if (member.isInstanceMember()) emitExtraAccessors(member, builder); + } + + void addMemberMethod(FunctionElement member, ClassBuilder builder) { + if (member.isAbstract(compiler)) return; + jsAst.Expression code = backend.generatedCode[member]; + if (code == null) return; + String name = namer.getNameOfMember(member); + if (backend.isInterceptedMethod(member)) { + task.interceptorInvocationNames.add(name); + } + code = extendWithMetadata(member, code); + builder.addProperty(name, code); + String reflectionName = task.getReflectionName(member, name); + if (reflectionName != null) { + var reflectable = + js(backend.isAccessibleByReflection(member) ? '1' : '0'); + builder.addProperty('+$reflectionName', reflectable); + jsAst.Node defaultValues = task.reifyDefaultArguments(member); + if (defaultValues != null) { + String unmangledName = member.name.slowToString(); + builder.addProperty('*$unmangledName', defaultValues); + } + } + code = backend.generatedBailoutCode[member]; + if (code != null) { + builder.addProperty(namer.getBailoutName(member), code); + } + if (member.isInstanceMember()) { + // TODO(ahe): Where is this done for static/top-level methods? + FunctionSignature parameters = member.computeSignature(compiler); + if (!parameters.optionalParameters.isEmpty) { + addParameterStubs(member, builder.addProperty); + } + } + } + + void addMemberField(VariableElement member, ClassBuilder builder) { + // For now, do nothing. + } + + jsAst.Fun extendWithMetadata(FunctionElement element, jsAst.Fun code) { + if (!backend.retainMetadataOf(element)) return code; + return compiler.withCurrentElement(element, () { + List<int> metadata = <int>[]; + FunctionSignature signature = element.functionSignature; + if (element.isConstructor()) { + metadata.add(task.reifyType(element.getEnclosingClass().thisType)); + } else { + metadata.add(task.reifyType(signature.returnType)); + } + signature.forEachParameter((Element parameter) { + metadata + ..add(task.reifyName(parameter.name)) + ..add(task.reifyType(parameter.computeType(compiler))); + }); + Link link = element.metadata; + // TODO(ahe): Why is metadata sometimes null? + if (link != null) { + for (; !link.isEmpty; link = link.tail) { + metadata.add(task.reifyMetadata(link.head)); + } + } + code.body.statements.add(js.string(metadata.join(',')).toStatement()); + return code; + }); + } +}
diff --git a/sdk/lib/_internal/compiler/implementation/js_emitter/declarations.dart b/sdk/lib/_internal/compiler/implementation/js_emitter/declarations.dart new file mode 100644 index 0000000..7a3e055 --- /dev/null +++ b/sdk/lib/_internal/compiler/implementation/js_emitter/declarations.dart
@@ -0,0 +1,61 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart2js.js_emitter; + +/// Enables debugging of fast/slow objects using V8-specific primitives. +const DEBUG_FAST_OBJECTS = false; + +/** + * A convenient type alias for some functions that emit keyed values. + */ +typedef void DefineStubFunction(String invocationName, jsAst.Expression value); + +/** + * [member] is a field (instance, static, or top level). + * + * [name] is the field name that the [Namer] has picked for this field's + * storage, that is, the JavaScript property name. + * + * [accessorName] is the name of the accessor. For instance fields this is + * mostly the same as [name] except when [member] is shadowing a field in its + * superclass. For other fields, they are rarely the same. + * + * [needsGetter] and [needsSetter] represent if a getter or a setter + * respectively is needed. There are many factors in this, for example, if the + * accessor can be inlined. + * + * [needsCheckedSetter] indicates that a checked getter is needed, and in this + * case, [needsSetter] is always false. [needsCheckedSetter] is only true when + * type assertions are enabled (checked mode). + */ +typedef void AcceptField(VariableElement member, + String name, + String accessorName, + bool needsGetter, + bool needsSetter, + bool needsCheckedSetter); + +// Function signatures used in the generation of runtime type information. +typedef void FunctionTypeSignatureEmitter(Element method, + FunctionType methodType); + +// TODO(johnniwinther): Clean up terminology for rti in the emitter. +typedef void FunctionTypeTestEmitter(FunctionType functionType); + +typedef void SubstitutionEmitter(Element element, {bool emitNull}); + +const String GENERATED_BY = """ +// Generated by dart2js, the Dart to JavaScript compiler. +"""; + +const String HOOKS_API_USAGE = """ +// The code supports the following hooks: +// dartPrint(message) - if this function is defined it is called +// instead of the Dart [print] method. +// dartMainRunner(main) - if this function is defined, the Dart [main] +// method will not be invoked directly. +// Instead, a closure that will invoke [main] is +// passed to [dartMainRunner]. +""";
diff --git a/sdk/lib/_internal/compiler/implementation/js_emitter/js_emitter.dart b/sdk/lib/_internal/compiler/implementation/js_emitter/js_emitter.dart new file mode 100644 index 0000000..dfd526b --- /dev/null +++ b/sdk/lib/_internal/compiler/implementation/js_emitter/js_emitter.dart
@@ -0,0 +1,63 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +library dart2js.js_emitter; + +import 'dart:collection' show LinkedHashMap, Queue; + +import '../common.dart'; + +import '../js/js.dart' as jsAst; + +import '../closure.dart' show + ClosureClassElement, + ClosureClassMap, + ClosureFieldElement; + +import '../dart2jslib.dart' show + CodeBuffer; + +import '../elements/modelx.dart' show + FunctionElementX; + +import '../js/js.dart' show + js; + +import '../js_backend/js_backend.dart' show + CheckedModeHelper, + CheckedModeHelper, + ConstantEmitter, + JavaScriptBackend, + JavaScriptBackend, + Namer, + NativeEmitter, + RuntimeTypes, + Substitution, + TypeCheck, + TypeChecks; + +import '../source_file.dart' show + SourceFile; + +import '../source_map_builder.dart' show + SourceMapBuilder; + +import '../util/characters.dart' show + $$, + $A, + $HASH, + $PERIOD, + $Z, + $a, + $z; + +import '../util/uri_extras.dart' show + relativize; + +part 'class_builder.dart'; +part 'closure_invocation_element.dart'; +part 'code_emitter_task.dart'; +part 'container_builder.dart'; +part 'declarations.dart'; +part 'reflection_data_parser.dart';
diff --git a/sdk/lib/_internal/compiler/implementation/js_emitter/reflection_data_parser.dart b/sdk/lib/_internal/compiler/implementation/js_emitter/reflection_data_parser.dart new file mode 100644 index 0000000..d90caf6 --- /dev/null +++ b/sdk/lib/_internal/compiler/implementation/js_emitter/reflection_data_parser.dart
@@ -0,0 +1,119 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of dart2js.js_emitter; + +// TODO(ahe): This code should be integrated in CodeEmitterTask.finishClasses. +String getReflectionDataParser(String classesCollector, Namer namer) { + String metadataField = '"${namer.metadataField}"'; + String reflectableField = namer.reflectableField; + String defaultValuesField = namer.defaultValuesField; + String methodsWithOptionalArgumentsField = + namer.methodsWithOptionalArgumentsField; + return ''' +(function (reflectionData) { +''' +// [map] returns an object literal that V8 shouldn't try to optimize with a +// hidden class. This prevents a potential performance problem where V8 tries +// to build a hidden class for an object used as a hashMap. +''' + function map(x){x={x:x};delete x.x;return x} + if (!init.libraries) init.libraries = []; + if (!init.mangledNames) init.mangledNames = map(); + if (!init.mangledGlobalNames) init.mangledGlobalNames = map(); + if (!init.statics) init.statics = map(); + if (!init.interfaces) init.interfaces = map(); + if (!init.globalFunctions) init.globalFunctions = map(); + var libraries = init.libraries; + var mangledNames = init.mangledNames; + var mangledGlobalNames = init.mangledGlobalNames; + var hasOwnProperty = Object.prototype.hasOwnProperty; + var length = reflectionData.length; + for (var i = 0; i < length; i++) { + var data = reflectionData[i]; +''' +// [data] contains these elements: +// 0. The library name (not unique). +// 1. The library URI (unique). +// 2. A function returning the metadata associated with this library. +// 3. The global object to use for this library. +// 4. An object literal listing the members of the library. +// 5. This element is optional and if present it is true and signals that this +// library is the root library (see dart:mirrors IsolateMirror.rootLibrary). +// +// The entries of [data] are built in [assembleProgram] above. +''' + var name = data[0]; + var uri = data[1]; + var metadata = data[2]; + var globalObject = data[3]; + var descriptor = data[4]; + var isRoot = !!data[5]; + var fields = descriptor && descriptor[""]; + var classes = []; + var functions = []; + function processStatics(descriptor) { + for (var property in descriptor) { + if (!hasOwnProperty.call(descriptor, property)) continue; + if (property === "") continue; + var element = descriptor[property]; + var firstChar = property.substring(0, 1); + var previousProperty; + if (firstChar === "+") { + mangledGlobalNames[previousProperty] = property.substring(1); + if (descriptor[property] == 1) ''' // Break long line. +'''descriptor[previousProperty].$reflectableField = 1; + if (element && element.length) ''' // Break long line. +'''init.interfaces[previousProperty] = element; + } else if (firstChar === "@") { + property = property.substring(1); + ${namer.CURRENT_ISOLATE}[property][$metadataField] = element; + } else if (firstChar === "*") { + globalObject[previousProperty].$defaultValuesField = element; + var optionalMethods = descriptor.$methodsWithOptionalArgumentsField; + if (!optionalMethods) { + descriptor.$methodsWithOptionalArgumentsField = optionalMethods = {} + } + optionalMethods[property] = previousProperty; + } else if (typeof element === "function") { + globalObject[previousProperty = property] = element; + functions.push(property); + init.globalFunctions[property] = element; + } else { + previousProperty = property; + var newDesc = {}; + var previousProp; + for (var prop in element) { + if (!hasOwnProperty.call(element, prop)) continue; + firstChar = prop.substring(0, 1); + if (prop === "static") { + processStatics(init.statics[property] = element[prop]); + } else if (firstChar === "+") { + mangledNames[previousProp] = prop.substring(1); + if (element[prop] == 1) ''' // Break long line. +'''element[previousProp].$reflectableField = 1; + } else if (firstChar === "@" && prop !== "@") { + newDesc[prop.substring(1)][$metadataField] = element[prop]; + } else if (firstChar === "*") { + newDesc[previousProp].$defaultValuesField = element[prop]; + var optionalMethods = newDesc.$methodsWithOptionalArgumentsField; + if (!optionalMethods) { + newDesc.$methodsWithOptionalArgumentsField = optionalMethods={} + } + optionalMethods[prop] = previousProp; + } else { + newDesc[previousProp = prop] = element[prop]; + } + } + $classesCollector[property] = [globalObject, newDesc]; + classes.push(property); + } + } + } + processStatics(descriptor); + libraries.push([name, uri, classes, functions, metadata, fields, isRoot, + globalObject]); + } +})'''; +}
diff --git a/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart b/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart index 5431753..79bb281 100644 --- a/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart +++ b/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart
@@ -14,7 +14,6 @@ import '../resolution/resolution.dart' show Scope; import '../dart2jslib.dart'; import '../dart_types.dart'; -import '../source_file.dart'; import '../tree/tree.dart'; import '../util/util.dart' show Spannable, Link; import '../util/characters.dart' show $CR, $LF; @@ -634,7 +633,7 @@ Dart2JsSourceLocation(this._script, this._span); int _computeLine() { - var sourceFile = _script.file as SourceFile; + var sourceFile = _script.file; if (sourceFile != null) { return sourceFile.getLine(offset) + 1; } @@ -658,7 +657,7 @@ int _computeColumn() { if (length == 0) return 0; - var sourceFile = _script.file as SourceFile; + var sourceFile = _script.file; if (sourceFile != null) { return sourceFile.getColumn(sourceFile.getLine(offset), offset) + 1; }
diff --git a/sdk/lib/_internal/compiler/implementation/mirrors_used.dart b/sdk/lib/_internal/compiler/implementation/mirrors_used.dart index 98707c6..aad7d8b 100644 --- a/sdk/lib/_internal/compiler/implementation/mirrors_used.dart +++ b/sdk/lib/_internal/compiler/implementation/mirrors_used.dart
@@ -134,11 +134,11 @@ for (Node argument in node.send.arguments) { NamedArgument named = argument.asNamedArgument(); if (named == null) continue; - Constant value = compiler.metadataHandler.compileNodeWithDefinitions( + Constant value = compiler.constantHandler.compileNodeWithDefinitions( named.expression, mapping, isConst: true); ConstantMapper mapper = - new ConstantMapper(compiler.metadataHandler, mapping, compiler); + new ConstantMapper(compiler.constantHandler, mapping, compiler); named.expression.accept(mapper); MirrorUsageBuilder builder =
diff --git a/sdk/lib/_internal/compiler/implementation/native_handler.dart b/sdk/lib/_internal/compiler/implementation/native_handler.dart index 9643027..e475aa7 100644 --- a/sdk/lib/_internal/compiler/implementation/native_handler.dart +++ b/sdk/lib/_internal/compiler/implementation/native_handler.dart
@@ -16,7 +16,7 @@ import 'universe/universe.dart' show SideEffects; import 'util/util.dart'; import 'js/js.dart' as js; - +import 'js_emitter/js_emitter.dart' show CodeEmitterTask; /// This class is a temporary work-around until we get a more powerful DartType. class SpecialType {
diff --git a/sdk/lib/_internal/compiler/implementation/resolution/members.dart b/sdk/lib/_internal/compiler/implementation/resolution/members.dart index 2658d01..af4208d 100644 --- a/sdk/lib/_internal/compiler/implementation/resolution/members.dart +++ b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
@@ -25,6 +25,8 @@ Selector setIteratorSelector(ForIn node, Selector selector); Selector setMoveNextSelector(ForIn node, Selector selector); Selector setCurrentSelector(ForIn node, Selector selector); + void setConstant(Node node, Constant constant); + Constant getConstant(Node node); /** * Returns [:true:] if [node] is a type literal. @@ -46,6 +48,7 @@ final Map<Node, DartType> types = new LinkedHashMap<Node, DartType>(); final Set<Node> superUses = new LinkedHashSet<Node>(); final Set<Element> otherDependencies = new LinkedHashSet<Element>(); + final Map<Node, Constant> constants = new Map<Node, Constant>(); final int hashCode = ++hashCodeCounter; static int hashCodeCounter = 0; @@ -140,6 +143,14 @@ return selectors[node.inToken]; } + void setConstant(Node node, Constant constant) { + constants[node] = constant; + } + + Constant getConstant(Node node) { + return constants[node]; + } + bool isTypeLiteral(Send node) { return getType(node) != null; } @@ -348,7 +359,11 @@ TreeElements elements = compiler.enqueuer.resolution.getCachedElements(element); if (elements != null) { - assert(isConstructor); + // TODO(karlklose): Remove the check for [isConstructor]. [elememts] + // should never be non-null, not even for constructors. + assert(invariant(element, isConstructor, + message: 'Non-constructor element $element ' + 'has already been analyzed.')); return elements; } if (element.isSynthesized) { @@ -402,7 +417,12 @@ } else if (tree.initializers != null) { error(tree, MessageKind.FUNCTION_WITH_INITIALIZER); } - visitBody(visitor, tree.body); + + if (!compiler.analyzeSignaturesOnly || tree.isRedirectingFactory) { + // We need to analyze the redirecting factory bodies to ensure that + // we can analyze compile-time constants. + visitor.visit(tree.body); + } // Get the resolution tree and check that the resolved // function doesn't use 'super' if it is mixed into another @@ -448,15 +468,26 @@ ResolverVisitor visitor = visitorFor(element); visitor.useElement(tree, element); - // TODO(johnniwinther): Avoid analyzing initializers if - // [Compiler.analyzeSignaturesOnly] is set. - initializerDo(tree, visitor.visit); + SendSet send = tree.asSendSet(); + if (send != null) { + // TODO(johnniwinther): Avoid analyzing initializers if + // [Compiler.analyzeSignaturesOnly] is set. + visitor.visit(send.arguments.head); + } else if (element.modifiers.isConst()) { + compiler.reportError(element, MessageKind.CONST_WITHOUT_INITIALIZER); + } if (Elements.isStaticOrTopLevelField(element)) { + visitor.addPostProcessAction(element, () { + compiler.constantHandler.compileVariable( + element, isConst: element.modifiers.isConst()); + }); if (tree.asSendSet() != null) { - // TODO(13429): We could do better here by using the - // constant handler to figure out if it's a lazy field or not. - compiler.backend.registerLazyField(visitor.mapping); + if (!element.modifiers.isConst()) { + // TODO(johnniwinther): Determine the const-ness eagerly to avoid + // unnecessary registrations. + compiler.backend.registerLazyField(visitor.mapping); + } } else { compiler.enqueuer.resolution.registerInstantiatedClass( compiler.nullClass, visitor.mapping); @@ -1038,8 +1069,10 @@ } ResolverVisitor visitor = visitorFor(context); node.accept(visitor); - annotation.value = compiler.metadataHandler.compileNodeWithDefinitions( + annotation.value = compiler.constantHandler.compileNodeWithDefinitions( node, visitor.mapping, isConst: true); + compiler.backend.registerMetadataConstant(annotation.value, + visitor.mapping); annotation.resolutionState = STATE_DONE; })); @@ -1390,6 +1423,10 @@ void unimplemented(Node node, String message) { compiler.unimplemented(message, node: node); } + + void addPostProcessAction(Element element, PostProcessAction action) { + compiler.enqueuer.resolution.addPostProcessAction(element, action); + } } abstract class LabelScope { @@ -1652,7 +1689,7 @@ // Remove the guarded when this is fixed. if (!compiler.enqueuer.resolution.queueIsClosed && addTypeVariableBoundsCheck) { - compiler.enqueuer.resolution.addPostProcessAction( + visitor.addPostProcessAction( visitor.enclosingElement, () => checkTypeVariableBounds(node, type)); } @@ -2028,6 +2065,11 @@ } parameterNodes = parameterNodes.tail; }); + addPostProcessAction(enclosingElement, () { + functionParameters.forEachOptionalParameter((Element parameter) { + compiler.constantHandler.compileConstant(parameter); + }); + }); if (inCheckContext) { functionParameters.forEachParameter((Element element) { compiler.enqueuer.resolution.registerIsCheck( @@ -2399,6 +2441,9 @@ // type literal. mapping.setType(node, compiler.typeClass.computeType(compiler)); world.registerTypeLiteral(target, mapping); + + // Don't try to make constants of calls to type literals. + analyzeConstant(node, isConst: !node.isCall); } } @@ -2510,7 +2555,11 @@ } } else if (target.impliesType()) { compiler.backend.registerThrowNoSuchMethod(mapping); - } else if (target.modifiers.isFinal() || target.modifiers.isConst()) { + } else if (target.modifiers.isFinal() || + target.modifiers.isConst() || + (target.isFunction() && + Elements.isStaticOrTopLevelFunction(target) && + !target.isSetter())) { setter = warnAndCreateErroneousElement( node.selector, target.name, MessageKind.CANNOT_RESOLVE_SETTER); compiler.backend.registerThrowNoSuchMethod(mapping); @@ -2615,6 +2664,7 @@ compiler.reportError(node, MessageKind.UNSUPPORTED_LITERAL_SYMBOL, {'value': node.slowNameString}); } + analyzeConstant(node); } visitStringJuxtaposition(StringJuxtaposition node) { @@ -2700,7 +2750,7 @@ // Register a post process to check for cycles in the redirection chain and // set the actual generative constructor at the end of the chain. - compiler.enqueuer.resolution.addPostProcessAction(constructor, () { + addPostProcessAction(constructor, () { compiler.resolver.resolveRedirectionChain(constructor, node); }); @@ -2734,7 +2784,9 @@ Modifiers modifiers = node.modifiers; void reportExtraModifier(String modifier) { Node modifierNode; - for (var nodes = modifiers.nodes; !nodes.isEmpty; nodes = nodes.tail) { + for (Link<Node> nodes = modifiers.nodes.nodes; + !nodes.isEmpty; + nodes = nodes.tail) { if (modifier == nodes.head.asIdentifier().source.stringValue) { modifierNode = nodes.head; break; @@ -2750,7 +2802,14 @@ if (modifiers.isVar() && (modifiers.isConst() || node.type != null)) { reportExtraModifier('var'); } - + if (enclosingElement.isFunction()) { + if (modifiers.isAbstract()) { + reportExtraModifier('abstract'); + } + if (modifiers.isStatic()) { + reportExtraModifier('static'); + } + } visitor.visit(node.definitions); } @@ -2803,7 +2862,7 @@ if (isSymbolConstructor) { if (node.isConst()) { Node argumentNode = node.send.arguments.head; - Constant name = compiler.metadataHandler.compileNodeWithDefinitions( + Constant name = compiler.constantHandler.compileNodeWithDefinitions( argumentNode, mapping, isConst: true); if (!name.isString()) { DartType type = name.computeType(compiler); @@ -2828,10 +2887,20 @@ } else if (isMirrorsUsedConstant) { compiler.mirrorUsageAnalyzerTask.validate(node, mapping); } + if (node.isConst()) { + analyzeConstant(node); + } return null; } + void analyzeConstant(Node node, {bool isConst: true}) { + addPostProcessAction(enclosingElement, () { + compiler.constantHandler.compileNodeWithDefinitions( + node, mapping, isConst: isConst); + }); + } + bool validateSymbol(Node node, String name, {bool reportError: true}) { if (name.isEmpty) return true; if (name.startsWith('_')) { @@ -2915,6 +2984,9 @@ world.registerInstantiatedType(listType, mapping); compiler.backend.registerRequiredType(listType, enclosingElement); visit(node.elements); + if (node.isConst()) { + analyzeConstant(node); + } } visitConditional(Conditional node) { @@ -3130,6 +3202,9 @@ } compiler.backend.registerRequiredType(mapType, enclosingElement); node.visitChildren(this); + if (node.isConst()) { + analyzeConstant(node); + } } visitLiteralMapEntry(LiteralMapEntry node) { @@ -3149,7 +3224,11 @@ while (!cases.isEmpty) { SwitchCase switchCase = cases.head; for (Node labelOrCase in switchCase.labelsAndCases) { - if (labelOrCase is! Label) continue; + CaseMatch caseMatch = labelOrCase.asCaseMatch(); + if (caseMatch != null) { + analyzeConstant(caseMatch.expression); + continue; + } Label label = labelOrCase; String labelName = label.slowToString(); @@ -3355,8 +3434,7 @@ bound = element.bound; } } - compiler.enqueuer.resolution.addPostProcessAction( - element, checkTypeVariableBound); + addPostProcessAction(element, checkTypeVariableBound); } else { variableElement.bound = compiler.objectClass.computeType(compiler); } @@ -3396,8 +3474,7 @@ var visitor = new TypedefCyclicVisitor(compiler, element); type.accept(visitor, null); } - compiler.enqueuer.resolution.addPostProcessAction(element, - checkCyclicReference); + addPostProcessAction(element, checkCyclicReference); } } @@ -3529,7 +3606,8 @@ DartType supertype = resolveSupertype(element, superMixin.superclass); Link<Node> link = superMixin.mixins.nodes; while (!link.isEmpty) { - supertype = applyMixin(supertype, resolveType(link.head), node); + supertype = applyMixin( + supertype, checkMixinType(link.head), link.head); link = link.tail; } element.supertype = supertype; @@ -3580,6 +3658,17 @@ return element.computeType(compiler); } + /// Resolves the mixed type for [mixinNode] and checks that the the mixin type + /// is not black-listed. The mixin type is returned. + DartType checkMixinType(TypeAnnotation mixinNode) { + DartType mixinType = resolveType(mixinNode); + if (isBlackListed(mixinType)) { + compiler.reportError(mixinNode, + MessageKind.CANNOT_MIXIN, {'type': mixinType}); + } + return mixinType; + } + DartType visitNamedMixinApplication(NamedMixinApplication node) { compiler.ensure(element != null); compiler.ensure(element.resolutionState == STATE_STARTED); @@ -3593,10 +3682,10 @@ DartType supertype = resolveSupertype(element, node.superclass); Link<Node> link = node.mixins.nodes; while (!link.tail.isEmpty) { - supertype = applyMixin(supertype, resolveType(link.head), link.head); + supertype = applyMixin(supertype, checkMixinType(link.head), link.head); link = link.tail; } - doApplyMixinTo(element, supertype, resolveType(link.head)); + doApplyMixinTo(element, supertype, checkMixinType(link.head)); return element.computeType(compiler); } @@ -3903,9 +3992,10 @@ void visitIdentifier(Identifier node) { Element element = context.lookup(node.source); if (element == null) { - error(node, MessageKind.CANNOT_RESOLVE_TYPE.error, {'typeName': node}); + compiler.reportError( + node, MessageKind.CANNOT_RESOLVE_TYPE.error, {'typeName': node}); } else if (!element.impliesType()) { - error(node, MessageKind.NOT_A_TYPE.error, {'node': node}); + compiler.reportError(node, MessageKind.NOT_A_TYPE.error, {'node': node}); } else { if (element.isClass()) { loadSupertype(element, node); @@ -3981,6 +4071,11 @@ VariableElement element = new VariableElementX(name, variables, kind, link.head); resolver.defineElement(link.head, element); + if (definitions.modifiers.isConst()) { + compiler.enqueuer.resolution.addPostProcessAction(element, () { + compiler.constantHandler.compileVariable(element, isConst: true); + }); + } } } } @@ -3993,6 +4088,7 @@ final bool defaultValuesAllowed; Link<Element> optionalParameters = const Link<Element>(); int optionalParameterCount = 0; + bool isOptionalParameter = false; bool optionalParametersAreNamed = false; VariableDefinitions currentDefinitions; @@ -4008,6 +4104,7 @@ internalError(node, "expected optional parameters"); } optionalParametersAreNamed = (identical(value, '{')); + isOptionalParameter = true; LinkBuilder<Element> elements = analyzeNodes(node.nodes); optionalParameterCount = elements.length; optionalParameters = elements.toLink(); @@ -4044,7 +4141,17 @@ return element; } + void validateName(Identifier node) { + SourceString name = node.source; + if (isOptionalParameter && + optionalParametersAreNamed && + node.source.isPrivate()) { + compiler.reportError(node, MessageKind.PRIVATE_NAMED_PARAMETER); + } + } + Element visitIdentifier(Identifier node) { + validateName(node); Element variables = new VariableListElementX.node(currentDefinitions, ElementKind.VARIABLE_LIST, enclosingElement); // Ensure a parameter is not typed 'void'. @@ -4057,12 +4164,14 @@ var identifier = node.selector.asIdentifier(); if (identifier != null) { // Normal parameter: [:Type name:]. + validateName(identifier); return identifier.source; } else { // Function type parameter: [:void name(DartType arg):]. var functionExpression = node.selector.asFunctionExpression(); if (functionExpression != null && functionExpression.name.asIdentifier() != null) { + validateName(functionExpression.name); return functionExpression.name.asIdentifier().source; } else { cancel(node, @@ -4106,9 +4215,11 @@ node.selector.asFunctionExpression() != null) { Element variables = new VariableListElementX.node(currentDefinitions, ElementKind.VARIABLE_LIST, enclosingElement); - SourceString source = node.selector.asIdentifier() != null ? - node.selector.asIdentifier().source : - node.selector.asFunctionExpression().name.asIdentifier().source; + Identifier identifier = node.selector.asIdentifier() != null ? + node.selector.asIdentifier() : + node.selector.asFunctionExpression().name.asIdentifier(); + validateName(identifier); + SourceString source = identifier.source; element = new VariableElementX(source, variables, ElementKind.PARAMETER, node); } @@ -4123,6 +4234,14 @@ } Element visitFunctionExpression(FunctionExpression node) { + Modifiers modifiers = currentDefinitions.modifiers; + if (modifiers.isFinal()) { + compiler.reportError(modifiers, + MessageKind.FINAL_FUNCTION_TYPE_PARAMETER); + } + if (modifiers.isVar()) { + compiler.reportError(modifiers, MessageKind.VAR_FUNCTION_TYPE_PARAMETER); + } // This is a function typed parameter. // TODO(ahe): Resolve the function type. return visit(node.name); @@ -4238,7 +4357,7 @@ compiler.backend.registerThrowRuntimeError(resolver.mapping); } if (inConstContext) { - error(diagnosticNode, kind.error, arguments); + compiler.reportError(diagnosticNode, kind.error, arguments); } else { ResolutionWarning warning = new ResolutionWarning(
diff --git a/sdk/lib/_internal/compiler/implementation/scanner/listener.dart b/sdk/lib/_internal/compiler/implementation/scanner/listener.dart index dc912fb..6b955ba 100644 --- a/sdk/lib/_internal/compiler/implementation/scanner/listener.dart +++ b/sdk/lib/_internal/compiler/implementation/scanner/listener.dart
@@ -899,6 +899,7 @@ TypeAnnotation bound = popNode(); Identifier name = popNode(); pushNode(new TypeVariable(name, bound)); + rejectBuiltInIdentifier(name); } void endTypeVariables(int count, Token beginToken, Token endToken) {
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/bailout.dart b/sdk/lib/_internal/compiler/implementation/ssa/bailout.dart index 2548c6a..90f2196 100644 --- a/sdk/lib/_internal/compiler/implementation/ssa/bailout.dart +++ b/sdk/lib/_internal/compiler/implementation/ssa/bailout.dart
@@ -143,7 +143,7 @@ DartType sourceType = source.computeType(compiler); if (!sourceType.treatAsDynamic && sourceType.kind == TypeKind.INTERFACE) { - TypeMask sourceMask = new TypeMask.subtype(sourceType); + TypeMask sourceMask = new TypeMask.subtype(sourceType.element); TypeMask speculatedMask = speculativeType.computeMask(compiler); if (sourceMask.intersection(speculatedMask, compiler).isEmpty) { return false;
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart index 6123f69..70713da 100644 --- a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart +++ b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
@@ -57,10 +57,13 @@ FunctionSignature signature = function.computeSignature(compiler); signature.forEachOptionalParameter((Element parameter) { // This ensures the default value will be computed. - builder.compileVariable(parameter); + Constant constant = + compiler.constantHandler.getConstantForVariable(parameter); + backend.registerCompileTimeConstant(constant, work.resolutionTree); + compiler.constantHandler.addCompileTimeConstantForEmission( + constant); }); } - if (compiler.tracer.enabled) { String name; if (element.isMember()) { @@ -953,21 +956,21 @@ _current = c; } - /** - * Compiles compile-time constants. Never returns [:null:]. If the - * initial value is not a compile-time constants, it reports an - * internal error. - */ - Constant compileConstant(VariableElement element) { - return compiler.constantHandler.compileConstant(element); + Constant getConstantForNode(Node node) { + ConstantHandler handler = compiler.constantHandler; + Constant constant = elements.getConstant(node); + assert(invariant(node, constant != null, + message: 'No constant computed for $node')); + return constant; } - Constant compileVariable(VariableElement element) { - return compiler.constantHandler.compileVariable(element); + HInstruction addConstant(Node node) { + return graph.addConstant(getConstantForNode(node), compiler); } bool isLazilyInitialized(VariableElement element) { - Constant initialValue = compileVariable(element); + Constant initialValue = + compiler.constantHandler.getConstantForVariable(element); return initialValue == null; } @@ -978,17 +981,14 @@ if (result == null) { Element element = localsHandler.closureData.thisElement; ClassElement cls = element.enclosingElement.getEnclosingClass(); - // Use the raw type because we don't have the type context for the - // type parameters. - DartType type = cls.rawType; if (compiler.world.isUsedAsMixin(cls)) { // If the enclosing class is used as a mixin, [:this:] can be // of the class that mixins the enclosing class. These two // classes do not have a subclass relationship, so, for // simplicity, we mark the type as an interface type. - result = new HType.nonNullSubtype(type, compiler); + result = new HType.nonNullSubtype(cls, compiler); } else { - result = new HType.nonNullSubclass(type, compiler); + result = new HType.nonNullSubclass(cls, compiler); } cachedTypeOfThis = result; } @@ -1322,7 +1322,8 @@ && !element.isGenerativeConstructorBody() && (selector.mask == null || selector.mask.isNullable)) { addWithPosition( - new HFieldGet(element, providedArguments[0]), currentNode); + new HFieldGet(null, providedArguments[0], isAssignable: false), + currentNode); } InliningState state = enterInlinedMethod( function, selector, providedArguments, currentNode); @@ -1661,7 +1662,7 @@ includeSuperAndInjectedMembers: true); InterfaceType type = classElement.computeType(compiler); - HType ssaType = new HType.nonNullExact(type, compiler); + HType ssaType = new HType.nonNullExact(classElement, compiler); List<DartType> instantiatedTypes; addInlinedInstantiation(type); if (!currentInlinedInstantiations.isEmpty) { @@ -1807,11 +1808,11 @@ int kind) { if (type == null) return original; type = type.unalias(compiler); - if (type.kind == TypeKind.INTERFACE && !type.isRaw) { - HType subtype = new HType.subtype(type, compiler); - HInstruction representations = buildTypeArgumentRepresentations(type); - add(representations); - return new HTypeConversion.withTypeRepresentation(type, kind, subtype, + if (type.kind == TypeKind.INTERFACE && !type.treatAsRaw) { + HType subtype = new HType.subtype(type.element, compiler); + HInstruction representations = buildTypeArgumentRepresentations(type); + add(representations); + return new HTypeConversion.withTypeRepresentation(type, kind, subtype, original, representations); } else if (type.kind == TypeKind.TYPE_VARIABLE) { HType subtype = original.instructionType; @@ -2495,9 +2496,7 @@ } }); - HType type = new HType.nonNullExact( - compiler.functionClass.computeType(compiler), - compiler); + HType type = new HType.nonNullExact(compiler.functionClass, compiler); push(new HForeignNew(closureClassElement, type, capturedVariables)); Element methodElement = nestedClosureData.closureElement; @@ -2628,7 +2627,7 @@ if (element.isField() && !element.isAssignable()) { // A static final or const. Get its constant value and inline it if // the value can be compiled eagerly. - value = compileVariable(element); + value = compiler.constantHandler.getConstantForVariable(element); } if (value != null) { HInstruction instruction = graph.addConstant(value, compiler); @@ -2955,7 +2954,10 @@ } HInstruction handleConstantForOptionalParameter(Element parameter) { - Constant constant = compileConstant(parameter); + Constant constant = + compiler.constantHandler.getConstantForVariable(parameter); + assert(invariant(parameter, constant != null, + message: 'No constant computed for $parameter')); return graph.addConstant(constant, compiler); } @@ -3481,7 +3483,7 @@ Node currentNode, HInstruction newObject) { if (!backend.classNeedsRti(type.element)) return; - if (!type.isRaw) { + if (!type.treatAsRaw) { List<HInstruction> inputs = <HInstruction>[]; type.typeArguments.forEach((DartType argument) { inputs.add(analyzeTypeArgument(argument)); @@ -3531,7 +3533,7 @@ return inferred.isUnknown() ? backend.extendableArrayType : inferred; } else if (element.isGenerativeConstructor()) { ClassElement cls = element.getEnclosingClass(); - return new HType.nonNullExact(cls.thisType, compiler); + return new HType.nonNullExact(cls.thisType.element, compiler); } else { return new HType.inferredReturnTypeForElement( originalElement, compiler); @@ -3673,9 +3675,13 @@ Element element = elements[node]; if (element.isClass() || element.isTypedef()) { // TODO(karlklose): add type representation - ConstantHandler handler = compiler.constantHandler; - Constant constant = handler.compileNodeWithDefinitions(node, elements); - stack.add(graph.addConstant(constant, compiler)); + if (node.isCall) { + // The node itself is not a constant but we register the selector (the + // identifier that refers to the class/typedef) as a constant. + stack.add(addConstant(node.selector)); + } else { + stack.add(addConstant(node)); + } } else if (element.isTypeVariable()) { HInstruction value = addTypeVariableReference(element.computeType(compiler)); @@ -3806,11 +3812,9 @@ generateRuntimeError(node.send, message.toString()); } } else if (node.isConst()) { - ConstantHandler handler = compiler.constantHandler; - Constant constant = handler.compileNodeWithDefinitions(node, elements); - stack.add(graph.addConstant(constant, compiler)); + stack.add(addConstant(node)); if (isSymbolConstructor) { - ConstructedConstant symbol = constant; + ConstructedConstant symbol = elements.getConstant(node); StringConstant stringConstant = symbol.fields.single; String nameString = stringConstant.toDartString().slowToString(); compiler.enqueuer.codegen.registerConstSymbol(nameString, elements); @@ -3834,12 +3838,12 @@ bool isLength = selector.isGetter() && selector.name == const SourceString("length"); if (isLength || selector.isIndex()) { - DartType classType = element.getEnclosingClass().computeType(compiler); - HType type = new HType.nonNullExact(classType, compiler); + HType type = new HType.nonNullExact( + element.getEnclosingClass(), compiler); return type.isIndexable(compiler); } else if (selector.isIndexSet()) { - DartType classType = element.getEnclosingClass().computeType(compiler); - HType type = new HType.nonNullExact(classType, compiler); + HType type = new HType.nonNullExact( + element.getEnclosingClass(), compiler); return type.isMutableIndexable(compiler); } else { return false; @@ -4126,11 +4130,9 @@ } void visitLiteralSymbol(LiteralSymbol node) { - ConstantHandler handler = compiler.constantHandler; - ConstructedConstant constant = - handler.compileNodeWithDefinitions(node, elements); - stack.add(graph.addConstant(constant, compiler)); - compiler.enqueuer.codegen.registerConstSymbol(node.slowNameString, elements); + stack.add(addConstant(node)); + compiler.enqueuer.codegen.registerConstSymbol( + node.slowNameString, elements); } void visitStringJuxtaposition(StringJuxtaposition node) { @@ -4204,7 +4206,7 @@ } HInstruction value; if (node.isRedirectingFactoryBody) { - FunctionElement element = elements[node.expression]; + FunctionElement element = elements[node.expression].implementation; FunctionElement function = currentElement; List<HInstruction> inputs = <HInstruction>[]; FunctionSignature calleeSignature = element.functionSignature; @@ -4288,9 +4290,7 @@ HInstruction instruction; if (node.isConst()) { - ConstantHandler handler = compiler.constantHandler; - Constant constant = handler.compileNodeWithDefinitions(node, elements); - instruction = graph.addConstant(constant, compiler); + instruction = addConstant(node); } else { List<HInstruction> inputs = <HInstruction>[]; for (Link<Node> link = node.elements.nodes; @@ -4487,9 +4487,7 @@ visitLiteralMap(LiteralMap node) { if (node.isConst()) { - ConstantHandler handler = compiler.constantHandler; - Constant constant = handler.compileNodeWithDefinitions(node, elements); - stack.add(graph.addConstant(constant, compiler)); + stack.add(addConstant(node)); return; } List<HInstruction> inputs = <HInstruction>[]; @@ -4502,8 +4500,7 @@ } HLiteralList keyValuePairs = buildLiteralList(inputs); add(keyValuePairs); - HType mapType = new HType.nonNullSubtype( - backend.mapLiteralClass.computeType(compiler), compiler); + HType mapType = new HType.nonNullSubtype(backend.mapLiteralClass, compiler); pushInvokeStatic(node, backend.getMapMaker(), [keyValuePairs], mapType); } @@ -4528,9 +4525,7 @@ for (Node labelOrCase in switchCase.labelsAndCases) { if (labelOrCase is CaseMatch) { CaseMatch match = labelOrCase; - Constant constant = - compiler.constantHandler.compileNodeWithDefinitions( - match.expression, elements, isConst: true); + Constant constant = getConstantForNode(match.expression); if (firstConstantType == null) { firstConstantType = constant.computeType(compiler); if (nonPrimitiveTypeOverridesEquals(constant)) {
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart index 2c22260..7b0b1a1 100644 --- a/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart +++ b/sdk/lib/_internal/compiler/implementation/ssa/codegen.dart
@@ -1570,8 +1570,9 @@ // [node.element] will be enqueued. We're not using the receiver // type because our optimizations might end up in a state where the // invoke dynamic knows more than the receiver. + ClassElement enclosing = node.element.getEnclosingClass(); HType receiverType = new HType.fromMask( - new TypeMask.nonNullExact(node.element.getEnclosingClass().rawType), + new TypeMask.nonNullExact(enclosing.declaration), compiler); return receiverType.refine(selector, compiler); } @@ -1679,7 +1680,7 @@ // If the selector we need to register a typed getter to the // [world]. The emitter needs to know if it needs to emit a // bound closure for a method. - TypeMask receiverType = new TypeMask.nonNullExact(superClass.rawType); + TypeMask receiverType = new TypeMask.nonNullExact(superClass); selector = new TypedSelector(receiverType, selector); world.registerDynamicGetter(selector); methodName = backend.namer.invocationName(selector); @@ -1696,7 +1697,12 @@ visitFieldGet(HFieldGet node) { use(node.receiver); Element element = node.element; - if (element == backend.jsIndexableLength) { + if (node.isNullCheck) { + // We access a JavaScript member we know all objects besides + // null and undefined have: V8 does not like accessing a member + // that does not exist. + push(new js.PropertyAccess.field(pop(), 'toString'), node); + } else if (element == backend.jsIndexableLength) { // We're accessing a native JavaScript property called 'length' // on a JS String or a JS array. Therefore, the name of that // property should not be mangled. @@ -1709,7 +1715,10 @@ // constant value instead. Element element = compiler.findRequiredElement( compiler.typedDataLibrary, const SourceString('fetchLength')); - Constant constant = compiler.constantHandler.compileConstant(element); + Constant constant = + compiler.constantHandler.getConstantForVariable(element); + assert(invariant(element, constant != null, + message: 'No constant computed for $element')); var jsConstant = backend.emitter.constantReference(constant); push(new js.Call(jsConstant, [pop()]), node); } else { @@ -1817,15 +1826,9 @@ visitConstant(HConstant node) { assert(isGenerateAtUseSite(node)); generateConstant(node.constant); - DartType type = node.constant.computeType(compiler); - if (node.constant is ConstructedConstant || - node.constant is InterceptorConstant) { - ConstantHandler handler = compiler.constantHandler; - handler.registerCompileTimeConstant(node.constant, work.resolutionTree); - } - if (node.constant is! InterceptorConstant) { - world.registerInstantiatedClass(type.element, work.resolutionTree); - } + + backend.registerCompileTimeConstant(node.constant, work.resolutionTree); + compiler.constantHandler.addCompileTimeConstantForEmission(node.constant); } visitNot(HNot node) { @@ -2462,20 +2465,22 @@ TypeMask receiver = input.instructionType.computeMask(compiler); TypeMask mask = node.instructionType.computeMask(compiler); // Figure out if it is beneficial to turn this into a null check. - // V8 generally prefers 'typeof' checks, but for integers and + // V8 generally prefers 'typeof' checks, but for integers and // indexable primitives we cannot compile this test into a single // typeof check so the null check is cheaper. - bool turnIntoNullCheck = (mask.nullable() == receiver) + bool turnIntoNumCheck = input.isIntegerOrNull() && node.isInteger(); + bool turnIntoNullCheck = !turnIntoNumCheck + && (mask.nullable() == receiver) && (node.isInteger() || node.isIndexablePrimitive(compiler)); js.Expression test; if (turnIntoNullCheck) { use(input); test = new js.Binary("==", pop(), new js.LiteralNull()); - } else if (node.isInteger()) { + } else if (node.isInteger() && !turnIntoNumCheck) { // input is !int checkInt(input, '!=='); test = pop(); - } else if (node.isNumber()) { + } else if (node.isNumber() || turnIntoNumCheck) { // input is !num checkNum(input, '!=='); test = pop();
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart b/sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart index 98e5a73..d80e5a8 100644 --- a/sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart +++ b/sdk/lib/_internal/compiler/implementation/ssa/interceptor_simplifier.dart
@@ -85,8 +85,8 @@ return interceptedClasses .where((cls) => cls != compiler.objectClass) .map((cls) => backend.classesMixedIntoNativeClasses.contains(cls) - ? new TypeMask.subtype(cls.rawType) - : new TypeMask.subclass(cls.rawType)) + ? new TypeMask.subtype(cls) + : new TypeMask.subclass(cls)) .every((mask) => receiverMask.intersection(mask, compiler).isEmpty); }
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart index 8c723df..c3dc5a6 100644 --- a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart +++ b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
@@ -175,7 +175,8 @@ // TODO(sra): What is the type of the prototype of an interceptor? if (constant.isInterceptor()) return HType.UNKNOWN; ObjectConstant objectConstant = constant; - return new HBoundedType(new TypeMask.nonNullExact(objectConstant.type)); + TypeMask mask = new TypeMask.nonNullExact(objectConstant.type.element); + return new HBoundedType(mask); } HConstant addConstant(Constant constant, Compiler compiler) { @@ -1124,18 +1125,20 @@ // instructions with generics. It has the generic type context // available. assert(type.kind != TypeKind.TYPE_VARIABLE); - assert(type.isRaw || type.kind == TypeKind.FUNCTION); + assert(type.treatAsRaw || type.kind == TypeKind.FUNCTION); if (type.treatAsDynamic) return this; - if (identical(type.element, compiler.objectClass)) return this; + // The type element is either a class or the void element. + Element element = type.element; + if (identical(element, compiler.objectClass)) return this; if (type.kind != TypeKind.INTERFACE) { return new HTypeConversion(type, kind, HType.UNKNOWN, this); } else if (kind == HTypeConversion.BOOLEAN_CONVERSION_CHECK) { // Boolean conversion checks work on non-nullable booleans. return new HTypeConversion(type, kind, HType.BOOLEAN, this); - } else if (kind == HTypeConversion.CHECKED_MODE_CHECK && !type.isRaw) { - throw 'creating compound check to $type (this = ${this})'; + } else if (kind == HTypeConversion.CHECKED_MODE_CHECK && !type.treatAsRaw) { + throw 'creating compound check to $type (this = ${this})'; } else { - HType subtype = new HType.subtype(type, compiler); + HType subtype = new HType.subtype(element, compiler); return new HTypeConversion(type, kind, subtype, this); } } @@ -1497,6 +1500,7 @@ HInstruction getDartReceiver(Compiler compiler) => receiver; bool onlyThrowsNSM() => true; + bool get isNullCheck => element == null; accept(HVisitor visitor) => visitor.visitFieldGet(this);
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart index 333bd7e..1cd4b7d 100644 --- a/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart +++ b/sdk/lib/_internal/compiler/implementation/ssa/optimize.dart
@@ -201,11 +201,10 @@ HType type = input.instructionType; if (type.isBoolean()) return input; // All values that cannot be 'true' are boolified to false. - DartType booleanType = backend.jsBoolClass.computeType(compiler); TypeMask mask = type.computeMask(compiler); // TODO(kasperl): Get rid of the null check here once all HTypes // have a proper mask. - if (mask != null && !mask.contains(booleanType, compiler)) { + if (mask != null && !mask.contains(backend.jsBoolClass, compiler)) { return graph.addConstantBool(false, compiler); } return node; @@ -637,7 +636,8 @@ } else if (!RuntimeTypes.hasTypeArguments(type)) { TypeMask expressionMask = expressionType.computeMask(compiler); TypeMask typeMask = (element == compiler.nullClass) - ? new TypeMask.subtype(type) : new TypeMask.nonNullSubtype(type); + ? new TypeMask.subtype(element) + : new TypeMask.nonNullSubtype(element); if (expressionMask.union(typeMask, compiler) == typeMask) { return graph.addConstantBool(true, compiler); } else if (expressionMask.intersection(typeMask, compiler).isEmpty) { @@ -651,7 +651,7 @@ HInstruction value = node.inputs[0]; DartType type = node.typeExpression; if (type != null) { - if (!type.isRaw || type.kind == TypeKind.TYPE_VARIABLE) { + if (!type.treatAsRaw || type.kind == TypeKind.TYPE_VARIABLE) { return node; } if (type.kind == TypeKind.FUNCTION) { @@ -694,7 +694,17 @@ } else { var type = receiver.instructionType.computeMask(compiler); if (type.isContainer && type.length != null) { - return graph.addConstantInt(type.length, compiler); + HInstruction constant = graph.addConstantInt(type.length, compiler); + if (type.isNullable) { + // If the container can be null, we update all uses of the + // length access to use the constant instead, but keep the + // length access in the graph, to ensure we still have a + // null check. + node.block.rewrite(node, constant); + return node; + } else { + return constant; + } } } } @@ -769,7 +779,7 @@ HInstruction value = node.inputs.last; if (compiler.enableTypeAssertions) { DartType type = field.computeType(compiler); - if (!type.isRaw || type.kind == TypeKind.TYPE_VARIABLE) { + if (!type.treatAsRaw || type.kind == TypeKind.TYPE_VARIABLE) { // We cannot generate the correct type representation here, so don't // inline this access. return node; @@ -948,7 +958,14 @@ if (current.canThrow() || current.sideEffects.hasSideEffects()) { return false; } - current = current.next; + if (current.next == null && current is HGoto) { + // We do not merge blocks in our SSA graph, so if this block + // just jumps to a single predecessor, visit this predecessor. + assert(current.block.successors.length == 1); + current = current.block.successors[0].first; + } else { + current = current.next; + } } while (current != null); return false; } @@ -1503,7 +1520,6 @@ visitDominatorTree(graph); } - // Update users of [input] that are dominated by [:dominator.first:] // to use [newInput] instead. void changeUsesDominatedBy(HBasicBlock dominator, @@ -1543,7 +1559,7 @@ if (ifUsers.isEmpty && notIfUsers.isEmpty) return; - HType convertedType = new HType.nonNullSubtype(type, compiler); + HType convertedType = new HType.nonNullSubtype(element, compiler); HInstruction input = instruction.expression; for (HIf ifUser in ifUsers) { changeUsesDominatedBy(ifUser.thenBlock, input, convertedType);
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/ssa.dart b/sdk/lib/_internal/compiler/implementation/ssa/ssa.dart index 60014f2..95b020f 100644 --- a/sdk/lib/_internal/compiler/implementation/ssa/ssa.dart +++ b/sdk/lib/_internal/compiler/implementation/ssa/ssa.dart
@@ -27,6 +27,8 @@ show ElementX, ConstructorBodyElementX; +import '../js_emitter/js_emitter.dart' show CodeEmitterTask; + part 'bailout.dart'; part 'builder.dart'; part 'codegen.dart';
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/types.dart b/sdk/lib/_internal/compiler/implementation/ssa/types.dart index 659737c..bfdb564 100644 --- a/sdk/lib/_internal/compiler/implementation/ssa/types.dart +++ b/sdk/lib/_internal/compiler/implementation/ssa/types.dart
@@ -30,8 +30,7 @@ // TODO(ngeoffray): Avoid creating [TypeMask]s with the string // class as base. return isNullable - ? new HBoundedType( - new TypeMask.exact(backend.jsStringClass.rawType)) + ? new HBoundedType(new TypeMask.exact(backend.jsStringClass)) : backend.stringType; } else if (mask.containsOnlyBool(compiler)) { return isNullable ? HType.BOOLEAN_OR_NULL : HType.BOOLEAN; @@ -48,33 +47,33 @@ return new HBoundedType(mask); } - factory HType.exact(DartType type, Compiler compiler) { - TypeMask mask = new TypeMask.exact(type); + factory HType.exact(ClassElement type, Compiler compiler) { + TypeMask mask = new TypeMask.exact(type.declaration); return new HType.fromMask(mask, compiler); } - factory HType.subclass(DartType type, Compiler compiler) { - TypeMask mask = new TypeMask.subclass(type); + factory HType.subclass(ClassElement type, Compiler compiler) { + TypeMask mask = new TypeMask.subclass(type.declaration); return new HType.fromMask(mask, compiler); } - factory HType.subtype(DartType type, Compiler compiler) { - TypeMask mask = new TypeMask.subtype(type); + factory HType.subtype(ClassElement type, Compiler compiler) { + TypeMask mask = new TypeMask.subtype(type.declaration); return new HType.fromMask(mask, compiler); } - factory HType.nonNullExact(DartType type, Compiler compiler) { - TypeMask mask = new TypeMask.nonNullExact(type); + factory HType.nonNullExact(ClassElement type, Compiler compiler) { + TypeMask mask = new TypeMask.nonNullExact(type.declaration); return new HType.fromMask(mask, compiler); } - factory HType.nonNullSubclass(DartType type, Compiler compiler) { - TypeMask mask = new TypeMask.nonNullSubclass(type); + factory HType.nonNullSubclass(ClassElement type, Compiler compiler) { + TypeMask mask = new TypeMask.nonNullSubclass(type.declaration); return new HType.fromMask(mask, compiler); } - factory HType.nonNullSubtype(DartType type, Compiler compiler) { - TypeMask mask = new TypeMask.nonNullSubtype(type); + factory HType.nonNullSubtype(ClassElement type, Compiler compiler) { + TypeMask mask = new TypeMask.nonNullSubtype(type.declaration); return new HType.fromMask(mask, compiler); } @@ -123,8 +122,7 @@ // like [native.SpecialType.JsObject]. static HType fromNativeType(type, Compiler compiler) { if (type == native.SpecialType.JsObject) { - return new HType.nonNullExact( - compiler.objectClass.computeType(compiler), compiler); + return new HType.nonNullExact(compiler.objectClass, compiler); } else if (type.isVoid) { return HType.NULL; } else if (type.element == compiler.nullClass) { @@ -132,11 +130,11 @@ } else if (type.treatAsDynamic) { return HType.UNKNOWN; } else if (compiler.world.hasAnySubtype(type.element)) { - return new HType.nonNullSubtype(type, compiler); + return new HType.nonNullSubtype(type.element, compiler); } else if (compiler.world.hasAnySubclass(type.element)) { - return new HType.nonNullSubclass(type, compiler); + return new HType.nonNullSubclass(type.element, compiler); } else { - return new HType.nonNullExact(type, compiler); + return new HType.nonNullExact(type.element, compiler); } } @@ -190,8 +188,7 @@ } bool implementsInterface(ClassElement interfaceElement, Compiler compiler) { - DartType interfaceType = interfaceElement.computeType(compiler); - TypeMask mask = new TypeMask.subtype(interfaceType); + TypeMask mask = new TypeMask.subtype(interfaceElement); return mask == mask.union(computeMask(compiler), compiler); } @@ -280,8 +277,7 @@ bool canBePrimitiveBoolean(Compiler compiler) => true; TypeMask computeMask(Compiler compiler) { - DartType base = compiler.objectClass.computeType(compiler); - return new TypeMask.subclass(base); + return new TypeMask.subclass(compiler.objectClass); } } @@ -295,8 +291,7 @@ bool canBePrimitiveBoolean(Compiler compiler) => true; TypeMask computeMask(Compiler compiler) { - DartType base = compiler.objectClass.computeType(compiler); - return new TypeMask.nonNullSubclass(base); + return new TypeMask.nonNullSubclass(compiler.objectClass); } } @@ -344,8 +339,7 @@ TypeMask computeMask(Compiler compiler) { JavaScriptBackend backend = compiler.backend; - DartType base = backend.jsBoolClass.computeType(compiler); - return new TypeMask.exact(base); + return new TypeMask.exact(backend.jsBoolClass); } } @@ -359,8 +353,7 @@ TypeMask computeMask(Compiler compiler) { JavaScriptBackend backend = compiler.backend; - DartType base = backend.jsBoolClass.computeType(compiler); - return new TypeMask.nonNullExact(base); + return new TypeMask.nonNullExact(backend.jsBoolClass); } } @@ -372,8 +365,7 @@ TypeMask computeMask(Compiler compiler) { JavaScriptBackend backend = compiler.backend; - DartType base = backend.jsNumberClass.computeType(compiler); - return new TypeMask.subclass(base); + return new TypeMask.subclass(backend.jsNumberClass); } } @@ -386,8 +378,7 @@ TypeMask computeMask(Compiler compiler) { JavaScriptBackend backend = compiler.backend; - DartType base = backend.jsNumberClass.computeType(compiler); - return new TypeMask.nonNullSubclass(base); + return new TypeMask.nonNullSubclass(backend.jsNumberClass); } } @@ -398,8 +389,7 @@ TypeMask computeMask(Compiler compiler) { JavaScriptBackend backend = compiler.backend; - DartType base = backend.jsIntClass.computeType(compiler); - return new TypeMask.exact(base); + return new TypeMask.exact(backend.jsIntClass); } } @@ -412,8 +402,7 @@ TypeMask computeMask(Compiler compiler) { JavaScriptBackend backend = compiler.backend; - DartType base = backend.jsIntClass.computeType(compiler); - return new TypeMask.nonNullExact(base); + return new TypeMask.nonNullExact(backend.jsIntClass); } } @@ -424,8 +413,7 @@ TypeMask computeMask(Compiler compiler) { JavaScriptBackend backend = compiler.backend; - DartType base = backend.jsDoubleClass.computeType(compiler); - return new TypeMask.exact(base); + return new TypeMask.exact(backend.jsDoubleClass); } } @@ -438,8 +426,7 @@ TypeMask computeMask(Compiler compiler) { JavaScriptBackend backend = compiler.backend; - DartType base = backend.jsDoubleClass.computeType(compiler); - return new TypeMask.nonNullExact(base); + return new TypeMask.nonNullExact(backend.jsDoubleClass); } } @@ -460,28 +447,21 @@ bool canBePrimitiveNumber(Compiler compiler) { JavaScriptBackend backend = compiler.backend; - DartType jsNumberType = backend.jsNumberClass.computeType(compiler); - DartType jsIntType = backend.jsIntClass.computeType(compiler); - DartType jsDoubleType = backend.jsDoubleClass.computeType(compiler); - return mask.contains(jsNumberType, compiler) - || mask.contains(jsIntType, compiler) - || mask.contains(jsDoubleType, compiler); + return mask.contains(backend.jsNumberClass, compiler) + || mask.contains(backend.jsIntClass, compiler) + || mask.contains(backend.jsDoubleClass, compiler); } bool canBePrimitiveBoolean(Compiler compiler) { JavaScriptBackend backend = compiler.backend; - DartType jsBoolType = backend.jsBoolClass.computeType(compiler); - return mask.contains(jsBoolType, compiler); + return mask.contains(backend.jsBoolClass, compiler); } bool canBePrimitiveArray(Compiler compiler) { JavaScriptBackend backend = compiler.backend; - DartType jsArrayType = backend.jsArrayClass.rawType; - DartType jsFixedArrayType = backend.jsFixedArrayClass.rawType; - DartType jsExtendableArrayType = backend.jsExtendableArrayClass.rawType; - return mask.contains(jsArrayType, compiler) - || mask.contains(jsFixedArrayType, compiler) - || mask.contains(jsExtendableArrayType, compiler); + return mask.contains(backend.jsArrayClass, compiler) + || mask.contains(backend.jsFixedArrayClass, compiler) + || mask.contains(backend.jsExtendableArrayClass, compiler); } bool isIndexablePrimitive(Compiler compiler) { @@ -511,8 +491,7 @@ bool canBePrimitiveString(Compiler compiler) { JavaScriptBackend backend = compiler.backend; - DartType jsStringType = backend.jsStringClass.computeType(compiler); - return mask.contains(jsStringType, compiler); + return mask.contains(backend.jsStringClass, compiler); } TypeMask computeMask(Compiler compiler) => mask;
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart b/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart index 82718326..a1cf853 100644 --- a/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart +++ b/sdk/lib/_internal/compiler/implementation/ssa/types_propagation.dart
@@ -10,7 +10,7 @@ final Map<int, HInstruction> workmap = new Map<int, HInstruction>(); final List<int> worklist = new List<int>(); final Map<HInstruction, Function> pendingOptimizations = - new Map<HInstruction, Function>(); + new Map<HInstruction, Function>(); final Compiler compiler; String get name => 'type propagator'; @@ -176,7 +176,7 @@ HTypeConversion converted = new HTypeConversion( null, kind, type, input, selector); instruction.block.addBefore(instruction, converted); - input.replaceAllUsersDominatedBy(instruction, converted); + input.replaceAllUsersDominatedBy(instruction, converted); } bool isCheckEnoughForNsmOrAe(HInstruction instruction, @@ -211,7 +211,7 @@ if (targets.length == 1) { Element target = targets.first; ClassElement cls = target.getEnclosingClass(); - HType type = new HType.nonNullSubclass(cls.rawType, compiler); + HType type = new HType.nonNullSubclass(cls, compiler); // TODO(ngeoffray): We currently only optimize on primitive // types. if (!type.isPrimitive(compiler)) return false; @@ -439,7 +439,7 @@ } return desiredType; } - + bool hasBeenSpeculativelyOptimized(HInstruction instruction) { return savedTypes.containsKey(instruction); }
diff --git a/sdk/lib/_internal/compiler/implementation/typechecker.dart b/sdk/lib/_internal/compiler/implementation/typechecker.dart index 1af2669..2b2a399 100644 --- a/sdk/lib/_internal/compiler/implementation/typechecker.dart +++ b/sdk/lib/_internal/compiler/implementation/typechecker.dart
@@ -155,9 +155,7 @@ final ClassElement currentClass; - /// The type of [:this:]. Can only be accessed if [currentClass] is not null. InterfaceType thisType; - /// The type of [:super:]. Can only be accessed if [currentClass] is not null. InterfaceType superType; Link<DartType> cascadeTypes = const Link<DartType>();
diff --git a/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart b/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart index 622e1a2..fb77255 100644 --- a/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart +++ b/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
@@ -414,7 +414,7 @@ Types types = inferrer.compiler.types; bool paramMatches(ConcreteType concrete, VariableElement parameter) { DartType parameterType = parameter.variables.type; - if (parameterType.treatAsDynamic || parameterType.isRaw) { + if (parameterType.treatAsDynamic || parameterType.treatAsRaw) { return true; } for (BaseType baseType in concrete.baseTypes) { @@ -533,7 +533,7 @@ throw new UnsupportedError(""); } - bool contains(DartType type, Compiler compiler) { + bool contains(ClassElement type, Compiler compiler) { throw new UnsupportedError(""); } @@ -816,7 +816,7 @@ Element enclosing = field.enclosingElement; if (enclosing.isClass()) { ClassElement cls = enclosing; - TypeMask receiverMask = new TypeMask.exact(cls.rawType); + TypeMask receiverMask = new TypeMask.exact(cls); TypeMask resultMask = concreteTypeToTypeMask(result); augmentInferredSelectorType(selector, receiverMask, resultMask); } @@ -974,11 +974,11 @@ assert(element != null); if (element == compiler.backend.numImplementation) { return new TypeMask.nonNullSubclass( - compiler.backend.numImplementation.rawType); + compiler.backend.numImplementation); } else if (element == compiler.dynamicClass) { - return new TypeMask.nonNullSubclass(compiler.objectClass.rawType); + return new TypeMask.nonNullSubclass(compiler.objectClass); } else { - return new TypeMask.nonNullExact(element.rawType); + return new TypeMask.nonNullExact(element); } } } @@ -1104,8 +1104,8 @@ // abstract classes than num. TypeMask receiverMask = (receiverType == compiler.backend.numImplementation) - ? new TypeMask.nonNullSubclass(receiverType.rawType) - : new TypeMask.nonNullExact(receiverType.rawType); + ? new TypeMask.nonNullSubclass(receiverType) + : new TypeMask.nonNullExact(receiverType); TypeMask resultMask = concreteTypeToTypeMask(result); augmentInferredSelectorType(selector, receiverMask, resultMask); }
diff --git a/sdk/lib/_internal/compiler/implementation/types/flat_type_mask.dart b/sdk/lib/_internal/compiler/implementation/types/flat_type_mask.dart index 03cd53a..cc17100 100644 --- a/sdk/lib/_internal/compiler/implementation/types/flat_type_mask.dart +++ b/sdk/lib/_internal/compiler/implementation/types/flat_type_mask.dart
@@ -15,46 +15,31 @@ static const int SUBCLASS = 2; static const int SUBTYPE = 3; - final DartType base; + final ClassElement base; final int flags; - FlatTypeMask(DartType base, int kind, bool isNullable) + FlatTypeMask(ClassElement base, int kind, bool isNullable) : this.internal(base, (kind << 1) | (isNullable ? 1 : 0)); - FlatTypeMask.exact(DartType base) + FlatTypeMask.exact(ClassElement base) : this.internal(base, (EXACT << 1) | 1); - FlatTypeMask.subclass(DartType base) + FlatTypeMask.subclass(ClassElement base) : this.internal(base, (SUBCLASS << 1) | 1); - FlatTypeMask.subtype(DartType base) + FlatTypeMask.subtype(ClassElement base) : this.internal(base, (SUBTYPE << 1) | 1); const FlatTypeMask.nonNullEmpty(): base = null, flags = 0; const FlatTypeMask.empty() : base = null, flags = 1; - FlatTypeMask.nonNullExact(DartType base) + FlatTypeMask.nonNullExact(ClassElement base) : this.internal(base, EXACT << 1); - FlatTypeMask.nonNullSubclass(DartType base) + FlatTypeMask.nonNullSubclass(ClassElement base) : this.internal(base, SUBCLASS << 1); - FlatTypeMask.nonNullSubtype(DartType base) + FlatTypeMask.nonNullSubtype(ClassElement base) : this.internal(base, SUBTYPE << 1); - FlatTypeMask.internal(DartType base, this.flags) - : this.base = transformBase(base) { - assert(base == null || !(isExact && base.treatAsDynamic)); - } - - // TODO(kasperl): We temporarily transform the base to be the raw - // variant of the type. Long term, we're going to keep the class - // element corresponding to the type in the mask instead. - static DartType transformBase(DartType base) { - if (base == null) { - return null; - } else if (base.kind != TypeKind.INTERFACE) { - assert(base.kind == TypeKind.INTERFACE); - return null; - } else { - return base.asRaw(); - } + FlatTypeMask.internal(this.base, this.flags) { + assert(base == null || base.isDeclaration); } bool get isEmpty => (flags >> 1) == EMPTY; @@ -81,10 +66,11 @@ TypeMask simplify(Compiler compiler) => this; - bool contains(DartType type, Compiler compiler) { + bool contains(ClassElement type, Compiler compiler) { + assert(type.isDeclaration); if (isEmpty) { return false; - } else if (identical(base.element, type.element)) { + } else if (identical(base, type)) { return true; } else if (isExact) { return false; @@ -97,43 +83,44 @@ } bool containsOnlyInt(Compiler compiler) { - return base.element == compiler.intClass - || base.element == compiler.backend.intImplementation; + return base == compiler.intClass + || base == compiler.backend.intImplementation; } bool containsOnlyDouble(Compiler compiler) { - return base.element == compiler.doubleClass - || base.element == compiler.backend.doubleImplementation; + return base == compiler.doubleClass + || base == compiler.backend.doubleImplementation; } bool containsOnlyNum(Compiler compiler) { - return base.element == compiler.numClass - || base.element == compiler.backend.numImplementation; + return base == compiler.numClass + || base == compiler.backend.numImplementation; } bool containsOnlyNull(Compiler compiler) { - return base.element == compiler.nullClass - || base.element == compiler.backend.nullImplementation; + return base == compiler.nullClass + || base == compiler.backend.nullImplementation; } bool containsOnlyBool(Compiler compiler) { - return base.element == compiler.boolClass - || base.element == compiler.backend.boolImplementation; + return base == compiler.boolClass + || base == compiler.backend.boolImplementation; } bool containsOnlyString(Compiler compiler) { - return base.element == compiler.stringClass - || base.element == compiler.backend.stringImplementation; + return base == compiler.stringClass + || base == compiler.backend.stringImplementation; } bool containsOnly(ClassElement cls) { - return base.element == cls; + assert(cls.isDeclaration); + return base == cls; } bool satisfies(ClassElement cls, Compiler compiler) { + assert(cls.isDeclaration); if (isEmpty) return false; - return base.element == cls - || isSubtypeOf(base, cls.computeType(compiler).asRaw(), compiler); + return base == cls || isSubtypeOf(base, cls, compiler); } /** @@ -143,11 +130,10 @@ ClassElement singleClass(Compiler compiler) { if (isEmpty) return null; if (isNullable) return null; // It is Null and some other class. - ClassElement element = base.element; if (isExact) { - return element; + return base; } else if (isSubclass) { - return compiler.world.hasAnySubclass(element) ? null : element; + return compiler.world.hasAnySubclass(base) ? null : base; } else { assert(isSubtype); return null; @@ -159,8 +145,8 @@ */ bool containsAll(Compiler compiler) { if (isEmpty || isExact) return false; - return identical(base.element, compiler.objectClass) - || identical(base.element, compiler.dynamicClass); + return identical(base, compiler.objectClass) + || identical(base, compiler.dynamicClass); } TypeMask union(TypeMask other, Compiler compiler) { @@ -348,7 +334,7 @@ int combined = (kind << 1) | (flags & other.flags & 1); TypeMask result; for (ClassElement each in candidates) { - TypeMask mask = new FlatTypeMask.internal(each.rawType, combined); + TypeMask mask = new FlatTypeMask.internal(each, combined); result = (result == null) ? mask : result.union(mask, compiler); } return result; @@ -359,7 +345,7 @@ } Iterable<ClassElement> containedClasses(Compiler compiler) { - Iterable<ClassElement> self = [ base.element ]; + Iterable<ClassElement> self = [ base ]; if (isExact) { return self; } else { @@ -408,7 +394,7 @@ // TODO(kasperl): Can't we just avoid creating typed selectors // based of function types? - Element self = base.element; + Element self = base; if (self.isTypedef()) { // A typedef is a function type that doesn't have any // user-defined members. @@ -468,7 +454,7 @@ if (!isNullable) return false; cls = compiler.backend.nullImplementation; } else { - cls = base.element; + cls = base; } // Use [lookupMember] because finding abstract members is okay. @@ -481,7 +467,7 @@ // `null`. if (isEmpty) return false; // A call on an exact mask for an abstract class is dead code. - if (isExact && base.element.isAbstract(compiler)) return false; + if (isExact && base.isAbstract(compiler)) return false; // If the receiver is guaranteed to have a member that // matches what we're looking for, there's no need to // introduce a noSuchMethod handler. It will never be called. @@ -524,17 +510,16 @@ // handler because we may have to call B.noSuchMethod since B // does not implement bar. - Element cls = base.element; - bool hasMatch = hasConcreteMatch(cls, selector, compiler); + bool hasMatch = hasConcreteMatch(base, selector, compiler); if (isExact) return !hasMatch; - if (!cls.isAbstract(compiler) && !hasMatch) return true; + if (!base.isAbstract(compiler) && !hasMatch) return true; Set<ClassElement> subtypesToCheck; if (isSubtype) { - subtypesToCheck = compiler.world.subtypesOf(cls); + subtypesToCheck = compiler.world.subtypesOf(base); } else { assert(isSubclass); - subtypesToCheck = compiler.world.subclassesOf(cls); + subtypesToCheck = compiler.world.subclassesOf(base); } return subtypesToCheck != null @@ -558,8 +543,7 @@ // implemented on the exact receiver type. It could be found in a // subclass or in an inheritance-wise unrelated class in case of // subtype selectors. - ClassElement cls = base.element; - return (cls.isSubclassOf(enclosing)) ? result : null; + return (base.isSubclassOf(enclosing)) ? result : null; } bool operator ==(var other) { @@ -579,22 +563,20 @@ if (isExact) buffer.write('exact='); if (isSubclass) buffer.write('subclass='); if (isSubtype) buffer.write('subtype='); - buffer.write(base.element.name.slowToString()); + buffer.write(base.name.slowToString()); return "[$buffer]"; } - static bool isSubclassOf(DartType x, DartType y, Compiler compiler) { - ClassElement xElement = x.element; - ClassElement yElement = y.element; - Set<ClassElement> subclasses = compiler.world.subclassesOf(yElement); - return (subclasses != null) ? subclasses.contains(xElement) : false; + static bool isSubclassOf(ClassElement x, ClassElement y, Compiler compiler) { + assert(x.isDeclaration && y.isDeclaration); + Set<ClassElement> subclasses = compiler.world.subclassesOf(y); + return (subclasses != null) ? subclasses.contains(x) : false; } - static bool isSubtypeOf(DartType x, DartType y, Compiler compiler) { - ClassElement xElement = x.element; - ClassElement yElement = y.element; - Set<ClassElement> subtypes = compiler.world.subtypesOf(yElement); - return (subtypes != null) ? subtypes.contains(xElement) : false; + static bool isSubtypeOf(ClassElement x, ClassElement y, Compiler compiler) { + assert(x.isDeclaration && y.isDeclaration); + Set<ClassElement> subtypes = compiler.world.subtypesOf(y); + return (subtypes != null) ? subtypes.contains(x) : false; } static Set<ClassElement> commonContainedClasses(FlatTypeMask x, @@ -617,7 +599,7 @@ } static Set<ClassElement> containedSubset(FlatTypeMask x, Compiler compiler) { - ClassElement element = x.base.element; + ClassElement element = x.base; if (x.isExact) { return null; } else if (x.isSubclass) {
diff --git a/sdk/lib/_internal/compiler/implementation/types/forwarding_type_mask.dart b/sdk/lib/_internal/compiler/implementation/types/forwarding_type_mask.dart index c077d5f..8f4c05f 100644 --- a/sdk/lib/_internal/compiler/implementation/types/forwarding_type_mask.dart +++ b/sdk/lib/_internal/compiler/implementation/types/forwarding_type_mask.dart
@@ -54,7 +54,7 @@ return forwardTo.satisfies(cls, compiler); } - bool contains(DartType type, Compiler compiler) { + bool contains(ClassElement type, Compiler compiler) { return forwardTo.contains(type, compiler); }
diff --git a/sdk/lib/_internal/compiler/implementation/types/type_mask.dart b/sdk/lib/_internal/compiler/implementation/types/type_mask.dart index a809af3..27e2df5 100644 --- a/sdk/lib/_internal/compiler/implementation/types/type_mask.dart +++ b/sdk/lib/_internal/compiler/implementation/types/type_mask.dart
@@ -10,21 +10,24 @@ * yield conservative answers that contain too many classes. */ abstract class TypeMask { - factory TypeMask(DartType base, int kind, bool isNullable) + factory TypeMask(ClassElement base, int kind, bool isNullable) => new FlatTypeMask(base, kind, isNullable); const factory TypeMask.empty() = FlatTypeMask.empty; - factory TypeMask.exact(DartType base) => new FlatTypeMask.exact(base); - factory TypeMask.subclass(DartType base) => new FlatTypeMask.subclass(base); - factory TypeMask.subtype(DartType base) => new FlatTypeMask.subtype(base); + factory TypeMask.exact(ClassElement base) + => new FlatTypeMask.exact(base); + factory TypeMask.subclass(ClassElement base) + => new FlatTypeMask.subclass(base); + factory TypeMask.subtype(ClassElement base) + => new FlatTypeMask.subtype(base); const factory TypeMask.nonNullEmpty() = FlatTypeMask.nonNullEmpty; - factory TypeMask.nonNullExact(DartType base) + factory TypeMask.nonNullExact(ClassElement base) => new FlatTypeMask.nonNullExact(base); - factory TypeMask.nonNullSubclass(DartType base) + factory TypeMask.nonNullSubclass(ClassElement base) => new FlatTypeMask.nonNullSubclass(base); - factory TypeMask.nonNullSubtype(DartType base) + factory TypeMask.nonNullSubtype(ClassElement base) => new FlatTypeMask.nonNullSubtype(base); factory TypeMask.unionOf(Iterable<TypeMask> masks, Compiler compiler) { @@ -58,7 +61,7 @@ bool containsOnlyBool(Compiler compiler); bool containsOnlyString(Compiler compiler); bool containsOnly(ClassElement element); - + /** * Returns whether this type mask is an instance of [cls]. */ @@ -67,7 +70,7 @@ /** * Returns whether or not this type mask contains the given type. */ - bool contains(DartType type, Compiler compiler); + bool contains(ClassElement type, Compiler compiler); /** * Returns whether or not this type mask contains all types.
diff --git a/sdk/lib/_internal/compiler/implementation/types/types.dart b/sdk/lib/_internal/compiler/implementation/types/types.dart index d4a83b98..1a47e3b 100644 --- a/sdk/lib/_internal/compiler/implementation/types/types.dart +++ b/sdk/lib/_internal/compiler/implementation/types/types.dart
@@ -68,7 +68,7 @@ TypeMask get dynamicType { if (dynamicTypeCache == null) { - dynamicTypeCache = new TypeMask.subclass(compiler.objectClass.rawType); + dynamicTypeCache = new TypeMask.subclass(compiler.objectClass); } return dynamicTypeCache; } @@ -76,7 +76,7 @@ TypeMask get intType { if (intTypeCache == null) { intTypeCache = new TypeMask.nonNullExact( - compiler.backend.intImplementation.rawType); + compiler.backend.intImplementation); } return intTypeCache; } @@ -84,7 +84,7 @@ TypeMask get doubleType { if (doubleTypeCache == null) { doubleTypeCache = new TypeMask.nonNullExact( - compiler.backend.doubleImplementation.rawType); + compiler.backend.doubleImplementation); } return doubleTypeCache; } @@ -92,7 +92,7 @@ TypeMask get numType { if (numTypeCache == null) { numTypeCache = new TypeMask.nonNullSubclass( - compiler.backend.numImplementation.rawType); + compiler.backend.numImplementation); } return numTypeCache; } @@ -100,7 +100,7 @@ TypeMask get boolType { if (boolTypeCache == null) { boolTypeCache = new TypeMask.nonNullExact( - compiler.backend.boolImplementation.rawType); + compiler.backend.boolImplementation); } return boolTypeCache; } @@ -108,7 +108,7 @@ TypeMask get functionType { if (functionTypeCache == null) { functionTypeCache = new TypeMask.nonNullSubtype( - compiler.backend.functionImplementation.rawType); + compiler.backend.functionImplementation); } return functionTypeCache; } @@ -116,7 +116,7 @@ TypeMask get listType { if (listTypeCache == null) { listTypeCache = new TypeMask.nonNullExact( - compiler.backend.listImplementation.rawType); + compiler.backend.listImplementation); } return listTypeCache; } @@ -124,7 +124,7 @@ TypeMask get constListType { if (constListTypeCache == null) { constListTypeCache = new TypeMask.nonNullExact( - compiler.backend.constListImplementation.rawType); + compiler.backend.constListImplementation); } return constListTypeCache; } @@ -132,7 +132,7 @@ TypeMask get fixedListType { if (fixedListTypeCache == null) { fixedListTypeCache = new TypeMask.nonNullExact( - compiler.backend.fixedListImplementation.rawType); + compiler.backend.fixedListImplementation); } return fixedListTypeCache; } @@ -140,7 +140,7 @@ TypeMask get growableListType { if (growableListTypeCache == null) { growableListTypeCache = new TypeMask.nonNullExact( - compiler.backend.growableListImplementation.rawType); + compiler.backend.growableListImplementation); } return growableListTypeCache; } @@ -148,7 +148,7 @@ TypeMask get mapType { if (mapTypeCache == null) { mapTypeCache = new TypeMask.nonNullSubtype( - compiler.backend.mapImplementation.rawType); + compiler.backend.mapImplementation); } return mapTypeCache; } @@ -156,7 +156,7 @@ TypeMask get constMapType { if (constMapTypeCache == null) { constMapTypeCache = new TypeMask.nonNullSubtype( - compiler.backend.constMapImplementation.rawType); + compiler.backend.constMapImplementation); } return constMapTypeCache; } @@ -164,7 +164,7 @@ TypeMask get stringType { if (stringTypeCache == null) { stringTypeCache = new TypeMask.nonNullExact( - compiler.backend.stringImplementation.rawType); + compiler.backend.stringImplementation); } return stringTypeCache; } @@ -172,7 +172,7 @@ TypeMask get typeType { if (typeTypeCache == null) { typeTypeCache = new TypeMask.nonNullExact( - compiler.backend.typeImplementation.rawType); + compiler.backend.typeImplementation); } return typeTypeCache; } @@ -209,18 +209,17 @@ return cls; } - /// Checks that two [DartType]s are the same modulo normalization. - bool same(DartType type1, DartType type2) { - return (type1 == type2) - || normalize(type1.element) == normalize(type2.element); + /// Checks that two types are the same modulo normalization. + bool same(ClassElement type1, ClassElement type2) { + return (type1 == type2) || normalize(type1) == normalize(type2); } /** * Checks that one of [type1] and [type2] is a subtype of the other. */ - bool related(DartType type1, DartType type2) { - return compiler.types.isSubtype(type1, type2) - || compiler.types.isSubtype(type2, type1); + bool related(ClassElement type1, ClassElement type2) { + return compiler.types.isSubtype(type1.rawType, type2.rawType) + || compiler.types.isSubtype(type2.rawType, type1.rawType); } /** @@ -228,18 +227,20 @@ * exactness, subclassing, subtyping and nullability. The [element] parameter * is for debugging purposes only and can be omitted. */ - TypeMask best(var type1, var type2, [element]) { + FlatTypeMask best(TypeMask type1, TypeMask type2, [element]) { // TODO(polux): Handle [UnionTypeMask]. if (type1 != null) type1 = type1.simplify(compiler); if (type2 != null) type2 = type2.simplify(compiler); - final result = _best(type1, type2); + FlatTypeMask result = _best(type1, type2); // Tests type1 and type2 for equality modulo normalization of native types. // Only called when DUMP_SURPRISING_RESULTS is true. bool similar() { if (type1 == null || type2 == null || type1.isEmpty || type2.isEmpty) { return type1 == type2; } - return same(type1.base, type2.base); + FlatTypeMask flat1 = type1; + FlatTypeMask flat2 = type2; + return same(flat1.base, flat2.base); } if (DUMP_SURPRISING_RESULTS && result == type1 && !similar()) { print("$type1 better than $type2 for $element"); @@ -248,54 +249,56 @@ } /// Helper method for [best]. - TypeMask _best(var type1, var type2) { + FlatTypeMask _best(var type1, var type2) { if (type1 == null) return type2; if (type2 == null) return type1; - if (type1.isContainer) type1 = type1.asFlat; - if (type2.isContainer) type2 = type2.asFlat; - if (type1.isExact) { - if (type2.isExact) { + FlatTypeMask flat1 = type1.isContainer ? type1.asFlat : type1; + FlatTypeMask flat2 = type2.isContainer ? type2.asFlat : type2; + if (flat1.isExact) { + if (flat2.isExact) { // TODO(polux): Update the code to not have this situation. - if (type1.base != type2.base) return type1; - assert(same(type1.base, type2.base)); - return type1.isNullable ? type2 : type1; + if (flat1.base != flat2.base) return flat1; + assert(same(flat1.base, flat2.base)); + return flat1.isNullable ? flat2 : flat1; } else { - return type1; + return flat1; } - } else if (type2.isExact) { - return type2; - } else if (type1.isSubclass) { - if (type2.isSubclass) { - assert(related(type1.base, type2.base)); - if (same(type1.base, type2.base)) { - return type1.isNullable ? type2 : type1; - } else if (compiler.types.isSubtype(type1.base, type2.base)) { - return type1; + } else if (flat2.isExact) { + return flat2; + } else if (flat1.isSubclass) { + if (flat2.isSubclass) { + assert(related(flat1.base, flat2.base)); + if (same(flat1.base, flat2.base)) { + return flat1.isNullable ? flat2 : flat1; + } else if (compiler.types.isSubtype(flat1.base.rawType, + flat2.base.rawType)) { + return flat1; } else { - return type2; + return flat2; } } else { - return type1; + return flat1; } - } else if (type2.isSubclass) { - return type2; - } else if (type1.isSubtype) { - if (type2.isSubtype) { - assert(related(type1.base, type2.base)); - if (same(type1.base, type2.base)) { - return type1.isNullable ? type2 : type1; - } else if (compiler.types.isSubtype(type1.base, type2.base)) { - return type1; + } else if (flat2.isSubclass) { + return flat2; + } else if (flat1.isSubtype) { + if (flat2.isSubtype) { + assert(related(flat1.base, flat2.base)); + if (same(flat1.base, flat2.base)) { + return flat1.isNullable ? flat2 : flat1; + } else if (compiler.types.isSubtype(flat1.base.rawType, + flat2.base.rawType)) { + return flat1; } else { - return type2; + return flat2; } } else { - return type1; + return flat1; } - } else if (type2.isSubtype) { - return type2; + } else if (flat2.isSubtype) { + return flat2; } else { - return type1.isNullable ? type2 : type1; + return flat1.isNullable ? flat2 : flat1; } } @@ -315,7 +318,6 @@ } } }); - compiler.containerTracer.analyze(); typesInferrer.clear(); }
diff --git a/sdk/lib/_internal/compiler/implementation/types/union_type_mask.dart b/sdk/lib/_internal/compiler/implementation/types/union_type_mask.dart index 6c40e56..269b1b5 100644 --- a/sdk/lib/_internal/compiler/implementation/types/union_type_mask.dart +++ b/sdk/lib/_internal/compiler/implementation/types/union_type_mask.dart
@@ -37,8 +37,7 @@ continue; } else { FlatTypeMask flatMask = mask; - assert(flatMask.base == null - || flatMask.base.element != compiler.dynamicClass); + assert(flatMask.base == null || flatMask.base != compiler.dynamicClass); int inListIndex = -1; bool covered = false; @@ -87,13 +86,13 @@ bool isNullable = masks.any((e) => e.isNullable); // Compute the common supertypes of the two types. - ClassElement firstElement = masks[0].base.element; - ClassElement secondElement = masks[1].base.element; + ClassElement firstElement = masks[0].base; + ClassElement secondElement = masks[1].base; Iterable<ClassElement> candidates = compiler.world.commonSupertypesOf(firstElement, secondElement); bool unseenType = false; for (int i = 2; i < masks.length; i++) { - ClassElement element = masks[i].base.element; + ClassElement element = masks[i].base; Set<ClassElement> supertypes = compiler.world.supertypesOf(element); if (supertypes == null) { unseenType = true; @@ -105,7 +104,7 @@ if (candidates.isEmpty || unseenType) { // TODO(kasperl): Get rid of this check. It can only happen when // at least one of the two base types is 'unseen'. - return new TypeMask(compiler.objectClass.rawType, + return new TypeMask(compiler.objectClass, FlatTypeMask.SUBCLASS, isNullable); } @@ -120,7 +119,7 @@ int size; int kind; if (subclasses != null - && masks.every((t) => subclasses.contains(t.base.element))) { + && masks.every((t) => subclasses.contains(t.base))) { // If both [this] and [other] are subclasses of the supertype, // then we prefer to construct a subclass type mask because it // will always be at least as small as the corresponding @@ -140,9 +139,7 @@ } } if (bestElement == compiler.objectClass) bestKind = FlatTypeMask.SUBCLASS; - return new TypeMask(bestElement.computeType(compiler), - bestKind, - isNullable); + return new TypeMask(bestElement, bestKind, isNullable); } TypeMask union(var other, Compiler compiler) { @@ -217,7 +214,7 @@ return disjointMasks.every((mask) => mask.satisfies(cls, compiler)); } - bool contains(DartType type, Compiler compiler) { + bool contains(ClassElement type, Compiler compiler) { return disjointMasks.any((e) => e.contains(type, compiler)); }
diff --git a/sdk/lib/_internal/compiler/implementation/universe/function_set.dart b/sdk/lib/_internal/compiler/implementation/universe/function_set.dart index bae06cb..d5f8784 100644 --- a/sdk/lib/_internal/compiler/implementation/universe/function_set.dart +++ b/sdk/lib/_internal/compiler/implementation/universe/function_set.dart
@@ -146,7 +146,7 @@ // to always be a subclass of Object. return selector.mask != null ? selector.mask - : new TypeMask.subclass(compiler.objectClass.rawType); + : new TypeMask.subclass(compiler.objectClass); } FunctionSetQuery query(Selector selector, @@ -225,8 +225,8 @@ return const TypeMask.empty(); } return compiler.world.hasSubclasses(cls) - ? new TypeMask.nonNullSubclass(cls.rawType) - : new TypeMask.nonNullExact(cls.rawType); + ? new TypeMask.nonNullSubclass(cls) + : new TypeMask.nonNullExact(cls); }), compiler); }
diff --git a/sdk/lib/_internal/compiler/implementation/universe/universe.dart b/sdk/lib/_internal/compiler/implementation/universe/universe.dart index 1bcf514..e0b1548 100644 --- a/sdk/lib/_internal/compiler/implementation/universe/universe.dart +++ b/sdk/lib/_internal/compiler/implementation/universe/universe.dart
@@ -638,13 +638,13 @@ return result; } - factory TypedSelector.exact(DartType base, Selector selector) + factory TypedSelector.exact(ClassElement base, Selector selector) => new TypedSelector(new TypeMask.exact(base), selector); - factory TypedSelector.subclass(DartType base, Selector selector) + factory TypedSelector.subclass(ClassElement base, Selector selector) => new TypedSelector(new TypeMask.subclass(base), selector); - factory TypedSelector.subtype(DartType base, Selector selector) + factory TypedSelector.subtype(ClassElement base, Selector selector) => new TypedSelector(new TypeMask.subtype(base), selector); bool appliesUnnamed(Element element, Compiler compiler) {
diff --git a/sdk/lib/_internal/compiler/implementation/util/util.dart b/sdk/lib/_internal/compiler/implementation/util/util.dart index 2638fd8..c904cc1 100644 --- a/sdk/lib/_internal/compiler/implementation/util/util.dart +++ b/sdk/lib/_internal/compiler/implementation/util/util.dart
@@ -77,6 +77,11 @@ _StackTraceLine(this.index, this.file, this.lineNo, this.columnNo, this.method); + + String toString() { + return 'index=$index, file=$file, ' + 'lineNo=$lineNo, columnNo=$columnNo, method=$method'; + } } // TODO(johnniwinther): Use this format for --throw-on-error. @@ -123,14 +128,31 @@ int lastColon = line.lastIndexOf(':', rightParenPos); int nextToLastColon = line.lastIndexOf(':', lastColon-1); - String lineNo = line.substring(nextToLastColon+1, lastColon); + String lineNo; + String columnNo; + if (nextToLastColon != -1) { + lineNo = line.substring(nextToLastColon+1, lastColon); + columnNo = line.substring(lastColon+1, rightParenPos); + try { + int.parse(lineNo); + } on FormatException catch (e) { + lineNo = columnNo; + columnNo = ''; + nextToLastColon = lastColon; + } + } else { + lineNo = line.substring(lastColon+1, rightParenPos); + columnNo = ''; + nextToLastColon = lastColon; + } + if (lineNo.length > maxLineNoLength) { maxLineNoLength = lineNo.length; } - String columnNo = line.substring(lastColon+1, rightParenPos); if (columnNo.length > maxColumnNoLength) { maxColumnNoLength = columnNo.length; } + String file = line.substring(leftParenPos+1, nextToLastColon); if (filePrefix != null && file.startsWith(filePrefix)) { file = file.substring(filePrefix.length);
diff --git a/sdk/lib/_internal/compiler/implementation/warnings.dart b/sdk/lib/_internal/compiler/implementation/warnings.dart index b44e3ec..3c3729e 100644 --- a/sdk/lib/_internal/compiler/implementation/warnings.dart +++ b/sdk/lib/_internal/compiler/implementation/warnings.dart
@@ -599,6 +599,34 @@ main() => foo(42); """]); + static const MessageKind FINAL_FUNCTION_TYPE_PARAMETER = const MessageKind( + "Error: A function type parameter can't be declared final.", + howToFix: "Try removing 'final'.", + examples: const [""" +foo(final int x(int a)) {} +main() => foo((y) => 42); +""", """ +foo({final int x(int a)}) {} +main() => foo((y) => 42); +""", """ +foo([final int x(int a)]) {} +main() => foo((y) => 42); +"""]); + + static const MessageKind VAR_FUNCTION_TYPE_PARAMETER = const MessageKind( + "Error: A function type parameter can't be declared with 'var'.", + howToFix: "Try removing 'var'.", + examples: const [""" +foo(var int x(int a)) {} +main() => foo((y) => 42); +""", """ +foo({var int x(int a)}) {} +main() => foo((y) => 42); +""", """ +foo([var int x(int a)]) {} +main() => foo((y) => 42); +"""]); + static const MessageKind CANNOT_INSTANTIATE_TYPE_VARIABLE = const MessageKind( "Error: Cannot instantiate type variable '#{typeVariableName}'."); @@ -640,6 +668,19 @@ static const MessageKind CANNOT_IMPLEMENT = const MessageKind( "Error: '#{type}' cannot be implemented."); + static const MessageKind CANNOT_MIXIN = const MessageKind( + "Error: The type '#{type}' can't be mixed in.", + howToFix: "Try removing '#{type}' from the 'with' clause.", + examples: const [""" +class C extends Object with String {} + +main() => new C(); +""", """ +typedef C = Object with String; + +main() => new C(); +"""]); + static const MessageKind DUPLICATE_EXTENDS_IMPLEMENTS = const MessageKind( "Error: '#{type}' can not be both extended and implemented."); @@ -905,6 +946,13 @@ "Error: '#{value}' is not a valid Symbol name because it starts with " "'_'."); + static const MessageKind PRIVATE_NAMED_PARAMETER = const MessageKind( + "Error: Named optional parameter can't have a library private name.", + howToFix: "Try removing the '_' or making the parameter positional or " + "required.", + examples: const ["""foo({int _p}) {} main() => foo();"""] + ); + static const MessageKind UNSUPPORTED_LITERAL_SYMBOL = const MessageKind( "Internal Error: Symbol literal '##{value}' is currently unsupported.");
diff --git a/sdk/lib/_internal/compiler/implementation/world.dart b/sdk/lib/_internal/compiler/implementation/world.dart index 4d25945..17f3b7f 100644 --- a/sdk/lib/_internal/compiler/implementation/world.dart +++ b/sdk/lib/_internal/compiler/implementation/world.dart
@@ -152,15 +152,17 @@ } // Returns whether a subclass of [superclass] implements [type]. - bool hasAnySubclassThatImplements(ClassElement superclass, DartType type) { + bool hasAnySubclassThatImplements(ClassElement superclass, + ClassElement type) { Set<ClassElement> subclasses = typesImplementedBySubclassesOf(superclass); if (subclasses == null) return false; - return subclasses.contains(type.element); + return subclasses.contains(type); } // Returns whether a subclass of any mixin application of [cls] implements // [type]. - bool hasAnySubclassOfMixinUseThatImplements(ClassElement cls, DartType type) { + bool hasAnySubclassOfMixinUseThatImplements(ClassElement cls, + ClassElement type) { Set<MixinApplicationElement> uses = mixinUses[cls]; if (uses == null || uses.isEmpty) return false; return uses.any((use) => hasAnySubclassThatImplements(use, type)); @@ -192,7 +194,7 @@ Element locateSingleElement(Selector selector) { ti.TypeMask mask = selector.mask == null - ? new ti.TypeMask.subclass(compiler.objectClass.rawType) + ? new ti.TypeMask.subclass(compiler.objectClass) : selector.mask; return mask.locateSingleElement(selector, compiler); }
diff --git a/sdk/lib/_internal/lib/io_patch.dart b/sdk/lib/_internal/lib/io_patch.dart index 095c424..dd4444a 100644 --- a/sdk/lib/_internal/lib/io_patch.dart +++ b/sdk/lib/_internal/lib/io_patch.dart
@@ -9,7 +9,7 @@ patch static _setCurrent(path) { throw new UnsupportedError("Directory_SetCurrent"); } - patch static _createTemp(String template) { + patch static _createTemp(String template, bool system) { throw new UnsupportedError("Directory._createTemp"); } patch static int _exists(String path) {
diff --git a/sdk/lib/_internal/lib/isolate_helper.dart b/sdk/lib/_internal/lib/isolate_helper.dart index ac4cc0f..8b0ad62 100644 --- a/sdk/lib/_internal/lib/isolate_helper.dart +++ b/sdk/lib/_internal/lib/isolate_helper.dart
@@ -411,7 +411,7 @@ const String _SPAWNED_SIGNAL = "spawned"; -var globalThis = IsolateNatives.computeGlobalThis(); +var globalThis = Primitives.computeGlobalThis(); var globalWindow = JS('', "#.window", globalThis); var globalWorker = JS('', "#.Worker", globalThis); bool globalPostMessageDefined = @@ -480,8 +480,6 @@ throw new UnsupportedError('Cannot extract URI from "$stack"'); } - static computeGlobalThis() => JS('', 'function() { return this; }()'); - /** * Assume that [e] is a browser message event and extract its message data. * We don't import the dom explicitly so, when workers are disabled, this
diff --git a/sdk/lib/_internal/lib/js_helper.dart b/sdk/lib/_internal/lib/js_helper.dart index ddeb666..0219440 100644 --- a/sdk/lib/_internal/lib/js_helper.dart +++ b/sdk/lib/_internal/lib/js_helper.dart
@@ -279,6 +279,8 @@ return JS('int', '#', hash); } + static computeGlobalThis() => JS('', 'function() { return this; }()'); + /** * This is the low-level method that is used to implement * [print]. It is possible to override this function from JavaScript @@ -1498,13 +1500,19 @@ var isolate, int numberOfArguments, var arg1, - var arg2) { + var arg2, + var arg3, + var arg4) { if (numberOfArguments == 0) { return JS_CALL_IN_ISOLATE(isolate, () => closure()); } else if (numberOfArguments == 1) { return JS_CALL_IN_ISOLATE(isolate, () => closure(arg1)); } else if (numberOfArguments == 2) { return JS_CALL_IN_ISOLATE(isolate, () => closure(arg1, arg2)); + } else if (numberOfArguments == 3) { + return JS_CALL_IN_ISOLATE(isolate, () => closure(arg1, arg2, arg3)); + } else if (numberOfArguments == 4) { + return JS_CALL_IN_ISOLATE(isolate, () => closure(arg1, arg2, arg3, arg4)); } else { throw new Exception( 'Unsupported number of arguments for wrapped closure'); @@ -1523,9 +1531,11 @@ // We use $0 and $1 to not clash with variable names used by the // compiler and/or minifier. function = JS('var', - r'(function ($2, $3) {' - r' return function($0, $1) { ' - r'return $3(#, $2, #, $0, $1) }})(#, #)', + '(function(closure, arity, context, invoke) {' + ' return function(a1, a2, a3, a4) {' + ' return invoke(closure, context, arity, a1, a2, a3, a4);' + ' };' + '})(#,#,#,#)', closure, arity, // Capture the current isolate now. Remember that "#"
diff --git a/sdk/lib/_internal/pub/lib/src/barback/load_transformers.dart b/sdk/lib/_internal/pub/lib/src/barback/load_transformers.dart index 557dbba..be6ef7c 100644 --- a/sdk/lib/_internal/pub/lib/src/barback/load_transformers.dart +++ b/sdk/lib/_internal/pub/lib/src/barback/load_transformers.dart
@@ -46,11 +46,7 @@ /// them (with [configuration] if it's non-null), and return them. Iterable<Transformer> initialize(Uri uri, Map configuration) { var mirrors = currentMirrorSystem(); - // TODO(nweiz): look this up by name once issue 5897 is fixed. - var transformerUri = Uri.parse( - 'http://<<HOST_AND_PORT>>/packages/barback/src/transformer.dart'); - var transformerClass = mirrors.libraries[transformerUri] - .classes[const Symbol('Transformer')]; + var transformerClass = reflectClass(Transformer); // TODO(nweiz): if no valid transformers are found, throw an error message // describing candidates and why they were rejected. @@ -289,7 +285,7 @@ TransformerId id) { var path = id.asset.path.replaceFirst('lib/', ''); // TODO(nweiz): load from a "package:" URI when issue 12474 is fixed. - var hostAndPort = '${server.host}:${server.port}'; + var hostAndPort = '${server.address.address}:${server.port}'; var uri = 'http://$hostAndPort/packages/${id.asset.package}/$path'; var code = 'import "$uri";' + _TRANSFORMER_ISOLATE.replaceAll('<<HOST_AND_PORT>>', hostAndPort);
diff --git a/sdk/lib/_internal/pub/lib/src/barback/server.dart b/sdk/lib/_internal/pub/lib/src/barback/server.dart index a2ce379..3b8c154 100644 --- a/sdk/lib/_internal/pub/lib/src/barback/server.dart +++ b/sdk/lib/_internal/pub/lib/src/barback/server.dart
@@ -29,10 +29,8 @@ /// The server's port. final int port; - /// The server's hostname. - final String host; - // TODO(whesse): replace this with the InternetAddress of the HttpServer, when - // that is exposed. + /// The server's address. + final InternetAddress address; /// The results of requests handled by the server. /// @@ -50,12 +48,13 @@ static Future<BarbackServer> bind(String host, int port, Barback barback, String rootPackage) { return HttpServer.bind(host, port) - .then((server) => new BarbackServer._(server, barback, rootPackage, host)); + .then((server) => new BarbackServer._(server, barback, rootPackage)); } - BarbackServer._(HttpServer server, this.barback, this._rootPackage, this.host) + BarbackServer._(HttpServer server, this.barback, this._rootPackage) : _server = server, - port = server.port { + port = server.port, + address = server.address { _server.listen(_handleRequest, onError: (error) { _resultsController.addError(error); close();
diff --git a/sdk/lib/_internal/pub/lib/src/exit_codes.dart b/sdk/lib/_internal/pub/lib/src/exit_codes.dart index 028fd1c..156e49e 100644 --- a/sdk/lib/_internal/pub/lib/src/exit_codes.dart +++ b/sdk/lib/_internal/pub/lib/src/exit_codes.dart
@@ -10,46 +10,46 @@ library pub.exit_codes; /// The command was used incorrectly. -final USAGE = 64; +const USAGE = 64; /// The input data was incorrect. -final DATA = 65; +const DATA = 65; /// An input file did not exist or was unreadable. -final NO_INPUT = 66; +const NO_INPUT = 66; /// The user specified did not exist. -final NO_USER = 67; +const NO_USER = 67; /// The host specified did not exist. -final NO_HOST = 68; +const NO_HOST = 68; /// A service is unavailable. -final UNAVAILABLE = 69; +const UNAVAILABLE = 69; /// An internal software error has been detected. -final SOFTWARE = 70; +const SOFTWARE = 70; /// An operating system error has been detected. -final OS = 71; +const OS = 71; /// Some system file did not exist or was unreadable. -final OS_FILE = 72; +const OS_FILE = 72; /// A user-specified output file cannot be created. -final CANT_CREATE = 73; +const CANT_CREATE = 73; /// An error occurred while doing I/O on some file. -final IO = 74; +const IO = 74; /// Temporary failure, indicating something that is not really an error. -final TEMP_FAIL = 75; +const TEMP_FAIL = 75; /// The remote system returned something invalid during a protocol exchange. -final PROTOCOL = 76; +const PROTOCOL = 76; /// The user did not have sufficient permissions. -final NO_PERM = 77; +const NO_PERM = 77; /// Something was unconfigured or mis-configured. -final CONFIG = 78; +const CONFIG = 78;
diff --git a/sdk/lib/_internal/pub/lib/src/io.dart b/sdk/lib/_internal/pub/lib/src/io.dart index 41a2543..af8168e 100644 --- a/sdk/lib/_internal/pub/lib/src/io.dart +++ b/sdk/lib/_internal/pub/lib/src/io.dart
@@ -232,12 +232,19 @@ /// suffix appended to it. If [dir] is not provided, a temp directory will be /// created in a platform-dependent temporary location. Returns the path of the /// created directory. -String createTempDir([dir = '']) { - var tempDir = new Directory(dir).createTempSync(); +String createTempDir(String base, String prefix) { + var tempDir = new Directory(base).createTempSync(prefix); log.io("Created temp directory ${tempDir.path}"); return tempDir.path; } +String createSystemTempDir() { + var tempDir = Directory.createSystemTempSync('pub_'); + log.io("Created temp directory ${tempDir.path}"); + return tempDir.path; +} + + /// Lists the contents of [dir]. If [recursive] is `true`, lists subdirectory /// contents (defaults to `false`). If [includeHidden] is `true`, includes files /// and directories beginning with `.` (defaults to `false`). @@ -648,7 +655,7 @@ /// [fn] completes to. Future withTempDir(Future fn(String path)) { return new Future.sync(() { - var tempDir = createTempDir(); + var tempDir = createSystemTempDir(); return new Future.sync(() => fn(tempDir)) .whenComplete(() => deleteEntry(tempDir)); });
diff --git a/sdk/lib/_internal/pub/lib/src/system_cache.dart b/sdk/lib/_internal/pub/lib/src/system_cache.dart index 7dafb8c..63b9817 100644 --- a/sdk/lib/_internal/pub/lib/src/system_cache.dart +++ b/sdk/lib/_internal/pub/lib/src/system_cache.dart
@@ -96,7 +96,7 @@ /// cache so that it can move the directory from it. String createTempDir() { var temp = ensureDir(tempDir); - return io.createTempDir(path.join(temp, 'dir')); + return io.createTempDir(temp, 'dir'); } /// Deletes the system cache's internal temp directory.
diff --git a/sdk/lib/_internal/pub/test/test_pub.dart b/sdk/lib/_internal/pub/test/test_pub.dart index 1f79116..fc449c2 100644 --- a/sdk/lib/_internal/pub/test/test_pub.dart +++ b/sdk/lib/_internal/pub/test/test_pub.dart
@@ -337,7 +337,7 @@ d.file('version', '0.1.2.3') ]).create(); - _sandboxDir = createTempDir(); + _sandboxDir = createSystemTempDir(); d.defaultRoot = sandboxDir; currentSchedule.onComplete.schedule(() => deleteEntry(_sandboxDir), 'deleting the sandbox directory');
diff --git a/sdk/lib/async/zone.dart b/sdk/lib/async/zone.dart index ac6bacd..4f067dd 100644 --- a/sdk/lib/async/zone.dart +++ b/sdk/lib/async/zone.dart
@@ -251,23 +251,44 @@ */ dynamic runUnaryGuarded(f(arg), var arg); - ZoneCallback registerCallback(f()); - ZoneUnaryCallback registerUnaryCallback(f(arg)); + /** + * Registers the given callback in this zone. + * + * It is good practice to register asynchronous or delayed callbacks before + * invoking [run]. This gives the zone a chance to wrap the callback and + * to store information with the callback. For example, a zone may decide + * to store the stack trace (at the time of the registration) with the + * callback. + * + * Returns a potentially new callback that should be used in place of the + * given [callback]. + */ + ZoneCallback registerCallback(callback()); + + /** + * Registers the given callback in this zone. + * + * Similar to [registerCallback] but with a unary callback. + */ + ZoneUnaryCallback registerUnaryCallback(callback(arg)); /** * Equivalent to: * * ZoneCallback registered = registerCallback(f); + * if (runGuarded) return () => this.runGuarded(registered); * return () => this.run(registered); + * */ - ZoneCallback bindCallback(f(), { bool runGuarded }); + ZoneCallback bindCallback(f(), { bool runGuarded: true }); /** * Equivalent to: * * ZoneCallback registered = registerCallback1(f); - * return (arg) => this.run1(registered, arg); + * if (runGuarded) return (arg) => this.runUnaryGuarded(registered, arg); + * return (arg) => thin.runUnary(registered, arg); */ - ZoneUnaryCallback bindUnaryCallback(f(arg), { bool runGuarded }); + ZoneUnaryCallback bindUnaryCallback(f(arg), { bool runGuarded: true }); /** * Runs [f] asynchronously. @@ -427,7 +448,7 @@ } } - ZoneCallback bindCallback(f(), { bool runGuarded }) { + ZoneCallback bindCallback(f(), { bool runGuarded: true }) { ZoneCallback registered = registerCallback(f); if (runGuarded) { return () => this.runGuarded(registered); @@ -436,7 +457,7 @@ } } - ZoneUnaryCallback bindUnaryCallback(f(arg), { bool runGuarded }) { + ZoneUnaryCallback bindUnaryCallback(f(arg), { bool runGuarded: true }) { ZoneUnaryCallback registered = registerUnaryCallback(f); if (runGuarded) { return (arg) => this.runUnaryGuarded(registered, arg);
diff --git a/sdk/lib/convert/utf.dart b/sdk/lib/convert/utf.dart index 6abaa05..3562085 100644 --- a/sdk/lib/convert/utf.dart +++ b/sdk/lib/convert/utf.dart
@@ -7,6 +7,9 @@ /** The Unicode Replacement character `U+FFFD` (�). */ const UNICODE_REPLACEMENT_CHARACTER_RUNE = 0xFFFD; +/** The Unicode Byte Order Marker (BOM) character `U+FEFF`. */ +const UNICODE_BOM_CHARACTER_RUNE = 0xFEFF; + /** * An instance of the default implementation of the [Utf8Codec]. * @@ -48,6 +51,9 @@ * Decodes the UTF-8 [codeUnits] (a list of unsigned 8-bit integers) to the * corresponding string. * + * If the [codeUnits] start with a leading [UNICODE_BOM_CHARACTER_RUNE] this + * character is discarded. + * * If [allowMalformed] is `true` the decoder replaces invalid (or * unterminated) character sequences with the Unicode Replacement character * `U+FFFD` (�). Otherwise it throws a [FormatException]. @@ -303,6 +309,9 @@ /** * Converts the UTF-8 [codeUnits] (a list of unsigned 8-bit integers) to the * corresponding string. + * + * If the [codeUnits] start with a leading [UNICODE_BOM_CHARACTER_RUNE] this + * character is discarded. */ String convert(List<int> codeUnits) { StringBuffer buffer = new StringBuffer(); @@ -346,9 +355,6 @@ const int _LEAD_SURROGATE_MIN = 0xD800; const int _TAIL_SURROGATE_MIN = 0xDC00; -const int _REPLACEMENT_CHARACTER = 0xFFFD; -const int _BOM_CHARACTER = 0xFEFF; - bool _isSurrogate(int codeUnit) => (codeUnit & _SURROGATE_MASK) == _LEAD_SURROGATE_MIN; bool _isLeadSurrogate(int codeUnit) => @@ -356,7 +362,7 @@ bool _isTailSurrogate(int codeUnit) => (codeUnit & _SURROGATE_TAG_MASK) == _TAIL_SURROGATE_MIN; int _combineSurrogatePair(int lead, int tail) => - 0x10000 | ((lead & _SURROGATE_VALUE_MASK) << 10) + 0x10000 + ((lead & _SURROGATE_VALUE_MASK) << 10) | (tail & _SURROGATE_VALUE_MASK); @@ -400,7 +406,7 @@ if (!_allowMalformed) { throw new FormatException("Unfinished UTF-8 octet sequence"); } - _stringSink.writeCharCode(_REPLACEMENT_CHARACTER); + _stringSink.writeCharCode(UNICODE_REPLACEMENT_CHARACTER_RUNE); _value = 0; _expectedUnits = 0; _extraUnits = 0; @@ -430,7 +436,7 @@ "Bad UTF-8 encoding 0x${unit.toRadixString(16)}"); } _isFirstCharacter = false; - _stringSink.writeCharCode(_REPLACEMENT_CHARACTER); + _stringSink.writeCharCode(UNICODE_REPLACEMENT_CHARACTER_RUNE); break multibyte; } else { value = (value << 6) | (unit & 0x3f); @@ -446,16 +452,16 @@ "Overlong encoding of 0x${value.toRadixString(16)}"); } expectedUnits = extraUnits = 0; - value = _REPLACEMENT_CHARACTER; + value = UNICODE_REPLACEMENT_CHARACTER_RUNE; } if (value > _FOUR_BYTE_LIMIT) { if (!_allowMalformed) { throw new FormatException("Character outside valid Unicode range: " "0x${value.toRadixString(16)}"); } - value = _REPLACEMENT_CHARACTER; + value = UNICODE_REPLACEMENT_CHARACTER_RUNE; } - if (!_isFirstCharacter || value != _BOM_CHARACTER) { + if (!_isFirstCharacter || value != UNICODE_BOM_CHARACTER_RUNE) { _stringSink.writeCharCode(value); } _isFirstCharacter = false; @@ -474,7 +480,7 @@ throw new FormatException( "Negative UTF-8 code unit: -0x${(-unit).toRadixString(16)}"); } - _stringSink.writeCharCode(_REPLACEMENT_CHARACTER); + _stringSink.writeCharCode(UNICODE_REPLACEMENT_CHARACTER_RUNE); } else if (unit <= _ONE_BYTE_LIMIT) { _isFirstCharacter = false; _stringSink.writeCharCode(unit); @@ -499,7 +505,7 @@ throw new FormatException( "Bad UTF-8 encoding 0x${unit.toRadixString(16)}"); } - value = _REPLACEMENT_CHARACTER; + value = UNICODE_REPLACEMENT_CHARACTER_RUNE; expectedUnits = extraUnits = 0; _isFirstCharacter = false; _stringSink.writeCharCode(value);
diff --git a/sdk/lib/core/list.dart b/sdk/lib/core/list.dart index d311785..a0473cb 100644 --- a/sdk/lib/core/list.dart +++ b/sdk/lib/core/list.dart
@@ -19,42 +19,49 @@ * The following code illustrates that some List implementations support * only a subset of the API. * - * var fixedLengthList = new List(5); - * fixedLengthList.length = 0; // Error. - * fixedLengthList.add(499); // Error. + * List<int> fixedLengthList = new List(5); + * fixedLengthList.length = 0; // Error + * fixedLengthList.add(499); // Error * fixedLengthList[0] = 87; - * - * var growableList = [1, 2]; + * List<int> growableList = [1, 2]; * growableList.length = 0; * growableList.add(499); * growableList[0] = 87; * - * Lists are [Iterable]. - * Iteration occurs over values in index order. - * Changing the values does not affect iteration, - * but changing the valid indices—that is, - * changing the list's length—between - * iteration steps - * causes a [ConcurrentModificationError]. - * This means that only growable lists can throw ConcurrentModificationError. - * If the length changes temporarily - * and is restored before continuing the iteration, - * the iterator does not detect it. + * Lists are [Iterable]. Iteration occurs over values in index order. Changing + * the values does not affect iteration, but changing the valid + * indices—that is, changing the list's length—between iteration + * steps causes a [ConcurrentModificationError]. This means that only growable + * lists can throw ConcurrentModificationError. If the length changes + * temporarily and is restored before continuing the iteration, the iterator + * does not detect it. */ abstract class List<E> implements Iterable<E> { /** - * Creates a list of the given _length_. + * Creates a list of the given length. * - * The created list is fixed-length if _length_ is provided. - * The list has length 0 and is growable if _length_ is omitted. + * The created list is fixed-length if [length] is provided. * - * An error occurs if _length_ is negative. + * List fixedLengthList = new List(3); + * fixedLengthList.length; // 3 + fixedLengthList.length = 1; // Error + * + * + * The list has length 0 and is growable if [length] is omitted. + * + * List growableList = new List(); + * growableList.length; // 0; + * growableList.length = 3; + * + * An error occurs if [length] is negative. */ external factory List([int length]); /** - * Creates a fixed-length list of the given _length_ - * and initializes the value at each position with [fill]. + * Creates a fixed-length list of the given length, and initializes the + * value at each position with [fill]: + * + * new List<int>.filled(3, 0); // [0, 0, 0] */ external factory List.filled(int length, E fill); @@ -83,11 +90,12 @@ /** * Generates a list of values. * - * Creates a list with _length_ positions - * and fills it with values created by calling [generator] - * for each index in the range `0` .. `length - 1` + * Creates a list with [length] positions and fills it with values created by + * calling [generator] for each index in the range `0` .. `length - 1` * in increasing order. * + * new List<int>.generate(3, (int index) => index * index); // [0, 1, 4] + * * The created list is fixed-length unless [growable] is true. */ factory List.generate(int length, E generator(int index), @@ -127,7 +135,7 @@ * Changes the length of this list. * * If [newLength] is greater than - * the current [length], entries are initialized to [:null:]. + * the current length, entries are initialized to [:null:]. * * Throws an [UnsupportedError] if the list is fixed-length. */ @@ -158,19 +166,35 @@ * Sorts this list according to the order specified by the [compare] function. * * The [compare] function must act as a [Comparator]. + + * List<String> numbers = ['one', 'two', 'three', 'four']; + * // Sort from shortest to longest. + * numbers.sort((x, y) => x.length.compareTo(y.length)); + * numbers.join(', '); // 'one, two, four, three' * * The default List implementations use [Comparable.compare] if * [compare] is omitted. + * + * List<int> nums = [13, 2, -11]; + * nums.sort(); + nums.join(', '); // '-11, 2, 13' */ void sort([int compare(E a, E b)]); /** * Returns the first index of [element] in this list. * - * Searches the list from index [start] to the length of the list. + * Searches the list from index [start] to the end of the list. * The first time an object [:o:] is encountered so that [:o == element:], * the index of [:o:] is returned. + * + * List<String> notes = ['do', 're', 'mi', 're']; + * notes.indexOf('re'); // 1 + * notes.indexOf('re', 2); // 3 + * * Returns -1 if [element] is not found. + * + * notes.indexOf('fa'); // -1 */ int indexOf(E element, [int start = 0]); @@ -182,9 +206,17 @@ * The first time an object [:o:] is encountered so that [:o == element:], * the index of [:o:] is returned. * - * If [start] is not provided, it defaults to [:this.length - 1:]. + * List<String> notes = ['do', 're', 'mi', 're']; + * notes.lastIndexOf('re', 2); // 1 + * + * If [start] is not provided, this method searches from the end of the + * list./Returns + * + * notes.lastIndexOf('re'); // 3 * * Returns -1 if [element] is not found. + * + * notes.lastIndexOf('fa'); // -1 */ int lastIndexOf(E element, [int start]); @@ -223,6 +255,10 @@ * Overwrites objects of `this` with the objects of [iterable], starting * at position [index] in this list. * + * List<String> list = ['a', 'b', 'c']; + * list.setAll(1, ['bee', 'sea']); + * list.join(', '); // 'a, bee, sea' + * * This operation does not increase the length of `this`. * * An error occurs if the [index] is less than 0 or greater than length. @@ -233,11 +269,18 @@ /** * Removes the first occurence of [value] from this list. * - * Returns true if [value] was in the list. - * Returns false otherwise. + * Returns true if [value] was in the list, false otherwise. + * + * List<String> parts = ['head', 'shoulders', 'knees', 'toes']; + * parts.remove('head'); // true + * parts.join(', '); // 'shoulders, knees, toes' * * The method has no effect if [value] was not in the list. * + * // Note: 'head' has already been removed. + * parts.remove('head'); // false + * parts.join(', '); // 'shoulders, knees, toes' + * * An [UnsupportedError] occurs if the list is fixed-length. */ bool remove(Object value); @@ -269,6 +312,10 @@ * * An object [:o:] satisfies [test] if [:test(o):] is true. * + * List<String> numbers = ['one', 'two', 'three', 'four']; + * numbers.removeWhere((item) => item.length == 3); + * numbers.join(', '); // 'three, four' + * * Throws an [UnsupportedError] if this is a fixed-length list. */ void removeWhere(bool test(E element)); @@ -278,16 +325,25 @@ * * An object [:o:] satisfies [test] if [:test(o):] is true. * + * List<String> numbers = ['one', 'two', 'three', 'four']; + * numbers.retainWhere((item) => item.length == 3); + * numbers.join(', '); // 'one, two' + * * Throws an [UnsupportedError] if this is a fixed-length list. */ void retainWhere(bool test(E element)); /** - * Returns a new list containing the objects - * from [start] inclusive to [end] exclusive. + * Returns a new list containing the objects from [start] inclusive to [end] + * exclusive. + * + * List<String> colors = ['red', 'green', 'blue', 'orange', 'pink']; + * colors.sublist(1, 3); // ['green', 'blue'] * * If [end] is omitted, the [length] of `this` is used. * + * colors.sublist(1); // ['green', 'blue', 'orange', 'pink'] + * * An error occurs if [start] is outside the range `0` .. `length` or if * [end] is outside the range `start` .. `length`. */ @@ -304,13 +360,11 @@ * `skip(start).take(end - start)`. That is, it does not throw exceptions * if `this` changes size. * - * Example: - * - * var list = [1, 2, 3, 4, 5]; - * var range = list.getRange(1, 4); - * print(range.join(', ')); // => 2, 3, 4 - * list.length = 3; - * print(range.join(', ')); // => 2, 3 + * List<String> colors = ['red', 'green', 'blue', 'orange', 'pink']; + * Iterable<String> range = colors.getRange(1, 4); + * range.join(', '); // 'green, blue, orange' + * colors.length = 3; + * range.join(', '); // 'green, blue' */ Iterable<E> getRange(int start, int end); @@ -318,6 +372,13 @@ * Copies the objects of [iterable], skipping [skipCount] objects first, * into the range [start] inclusive to [end] exclusive of `this`. * + * List<int> list1 = [1, 2, 3, 4]; + * List<int> list2 = [5, 6, 7, 8, 9]; + * // Copies the 4th and 5th items in list2 as the 2nd and 3rd items + * // of list1. + * list1.setRange(1, 3, list2, 3); + * list1.join(', '); // '1, 8, 9, 4' + * * If [start] equals [end] and [start]..[end] represents a legal range, this * method has no effect. * @@ -325,12 +386,6 @@ * An error occurs if the [iterable] does not have enough objects after * skipping [skipCount] objects. * - * Example: - * - * var list = [1, 2, 3, 4]; - * var list2 = [5, 6, 7, 8, 9]; - * list.setRange(1, 3, list2, 3); - * print(list); // => [1, 8, 9, 4] */ void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]); @@ -354,13 +409,11 @@ * Removes the objects in the range [start] inclusive to [end] exclusive * and replaces them with the contents of the [iterable]. * + * List<int> list = [1, 2, 3, 4]; + * list.replaceRange(1, 3, [6, 7]); + * list.join(', '); // '1, 6, 7, 4' + * * An error occurs if [start]..[end] is not a valid range for `this`. - * - * Example: - * - * var list = [1, 2, 3, 4, 5]; - * list.replaceRange(1, 3, [6, 7, 8, 9]); - * print(list); // [1, 6, 7, 8, 9, 4, 5] */ void replaceRange(int start, int end, Iterable<E> iterable); @@ -370,6 +423,11 @@ * The map uses the indices of this list as keys and the corresponding objects * as values. The `Map.keys` [Iterable] iterates the indices of this list * in numerical order. + * + * List<String> words = ['fee', 'fi', 'fo', 'fum']; + * Map<int, String> map = words.asMap(); + * map[0] + map[1]; // 'feefi'; + * map.keys.toList(); // [0, 1, 2, 3] */ Map<int, E> asMap(); }
diff --git a/sdk/lib/core/map.dart b/sdk/lib/core/map.dart index db187f5..38cb7cf 100644 --- a/sdk/lib/core/map.dart +++ b/sdk/lib/core/map.dart
@@ -5,8 +5,8 @@ part of dart.core; /** - * An unordered collection of key-value pairs, - * from which you retrieve a value by using its associated key. + * An unordered collection of key-value pairs, from which you retrieve a value + * by using its associated key. * * Each key can occur at most once in a map. */ @@ -27,18 +27,36 @@ factory Map.identity() = LinkedHashMap<K, V>.identity; /** - * Creates a Map instance - * where the keys and values are computed from the [iterable]. + * Creates a Map instance in which the keys and values are computed from the + * [iterable]. * * For each element of the [iterable] this constructor computes a key-value * pair, by applying [key] and [value] respectively. * - * The keys computed by the source [iterable] - * do not need to be unique. The last - * occurrence of a key will simply overwrite any previous value. + * The example below creates a new Map from a List. The keys of `map` are + * `list` values converted to strings, and the values of the `map` are the + * squares of the `list` values: + * + * List<int> list = [1, 2, 3]; + * Map<String, int> map = new Map.fromIterable(list, + * key: (item) => item.toString(), + * value: (item) => item * item)); + * + * map['1'] + map['2']; // 1 + 4 + * map['3'] - map['2']; // 9 - 4 * * If no values are specified for [key] and [value] the default is the * identity function. + * + * In the following example, the keys and corresponding values of `map` + * are `list` values: + * + * map = new Map.fromIterable(list); + * map[1] + map[2]; // 1 + 2 + * map[3] - map[2]; // 3 - 2 + * + * The keys computed by the source [iterable] do not need to be unique. The + * last occurrence of a key will simply overwrite any previous value. */ factory Map.fromIterable(Iterable iterable, {K key(element), V value(element)}) = LinkedHashMap<K, V>.fromIterable; @@ -49,6 +67,11 @@ * This constructor iterates over [keys] and [values] and maps each element of * [keys] to the corresponding element of [values]. * + * List<String> letters = ['b', 'c']; + * List<String> words = ['bad', 'cat']; + * Map<String, String> map = new Map.fromIterables(letters, words); + * map['b'] + map['c']; // badcat + * * If [keys] contains the same object multiple times, the last occurrence * overwrites the previous value. * @@ -85,8 +108,15 @@ * updates the map by mapping [key] to the value returned by * [ifAbsent]. Returns the value in the map. * - * It is an error to add or remove keys from the map during the call to - * [ifAbsent]. + * Map<String, int> scores = {'Bob': 36}; + * for (var key in ['Bob', 'Rohan', 'Sophena']) { + * scores.putIfAbsent(key, () => key.length); + * } + * scores['Bob']; // 36 + * scores['Rohan']; // 5 + * scores['Sophena']; // 7 + * + * The code that [ifAbsent] executes must not add or remove keys. */ V putIfAbsent(K key, V ifAbsent());
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart index f1199d0..6c9cfd9 100644 --- a/sdk/lib/html/dart2js/html_dart2js.dart +++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -88,8 +88,20 @@ // Dart issue 1990. class HtmlElement extends Element native "HTMLElement" { factory HtmlElement() { throw new UnsupportedError("Not supported"); } + + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + HtmlElement.created() : super.created(); } +// EntryArray type was removed, so explicitly adding it to allow support for +// older Chrome versions. +// Issue #12573. +abstract class _EntryArray implements List<Entry> native "EntryArray" {} + // Support for Send/ReceivePortSync. int _getNewIsolateId() { if (JS('bool', r'!window.$dart$isolate$counter')) { @@ -186,6 +198,12 @@ if (href != null) e.href = href; return e; } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + AnchorElement.created() : super.created(); @DomName('HTMLAnchorElement.download') @DocsEditable() @@ -431,6 +449,12 @@ @DomName('HTMLAreaElement.HTMLAreaElement') @DocsEditable() factory AreaElement() => document.createElement("area"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + AreaElement.created() : super.created(); @DomName('HTMLAreaElement.alt') @DocsEditable() @@ -507,6 +531,12 @@ } static AudioElement _create_1(src) => JS('AudioElement', 'new Audio(#)', src); static AudioElement _create_2() => JS('AudioElement', 'new Audio()'); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + AudioElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -539,6 +569,12 @@ @DomName('HTMLBRElement.HTMLBRElement') @DocsEditable() factory BRElement() => document.createElement("br"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + BRElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -569,6 +605,12 @@ @DomName('HTMLBaseElement.HTMLBaseElement') @DocsEditable() factory BaseElement() => document.createElement("base"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + BaseElement.created() : super.created(); @DomName('HTMLBaseElement.href') @DocsEditable() @@ -696,6 +738,12 @@ @DomName('HTMLBodyElement.HTMLBodyElement') @DocsEditable() factory BodyElement() => document.createElement("body"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + BodyElement.created() : super.created(); @DomName('HTMLBodyElement.onblur') @DocsEditable() @@ -759,6 +807,12 @@ @DomName('HTMLButtonElement.HTMLButtonElement') @DocsEditable() factory ButtonElement() => document.createElement("button"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + ButtonElement.created() : super.created(); @DomName('HTMLButtonElement.autofocus') @DocsEditable() @@ -885,6 +939,12 @@ if (height != null) e.height = height; return e; } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + CanvasElement.created() : super.created(); /// The height of this canvas element in CSS pixels. @DomName('HTMLCanvasElement.height') @@ -1974,6 +2034,12 @@ @DomName('HTMLContentElement.HTMLContentElement') @DocsEditable() factory ContentElement() => document.createElement("content"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + ContentElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => Element.isTagSupported('content'); @@ -6316,6 +6382,12 @@ @DomName('HTMLDListElement.HTMLDListElement') @DocsEditable() factory DListElement() => document.createElement("dl"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + DListElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -6335,6 +6407,12 @@ @DomName('HTMLDataListElement.HTMLDataListElement') @DocsEditable() factory DataListElement() => document.createElement("datalist"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + DataListElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => Element.isTagSupported('datalist'); @@ -6550,6 +6628,12 @@ @DomName('HTMLDetailsElement.HTMLDetailsElement') @DocsEditable() factory DetailsElement() => document.createElement("details"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + DetailsElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => Element.isTagSupported('details'); @@ -6687,6 +6771,12 @@ class DialogElement extends HtmlElement native "HTMLDialogElement" { // To suppress missing implicit constructor warnings. factory DialogElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + DialogElement.created() : super.created(); @DomName('HTMLDialogElement.open') @DocsEditable() @@ -6941,6 +7031,12 @@ @DomName('HTMLDivElement.HTMLDivElement') @DocsEditable() factory DivElement() => document.createElement("div"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + DivElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -7603,7 +7699,6 @@ @Experimental() Stream<Event> get onPointerLockError => pointerLockErrorEvent.forTarget(this); - /** * Finds all descendant elements of this document that match the specified * group of selectors. @@ -8805,6 +8900,30 @@ } /** + * Custom element creation constructor. + * + * This constructor is used by the DOM when a custom element has been + * created. It can only be invoked by subclasses of Element from + * that classes created constructor. + * + * class CustomElement extends Element { + * factory CustomElement() => new Element.tag('x-custom'); + * + * CustomElement.created() : super.created() { + * // Perform any element initialization. + * } + * } + * document.register('x-custom', CustomElement); + */ + Element.created() : super._created() { + // Validate that this is a custom element & perform any additional + // initialization. + _initializeCustomElement(this); + + createdCallback(); + } + + /** * Creates the HTML element specified by the tag name. * * This is similar to [Document.createElement]. @@ -9147,9 +9266,12 @@ /** * Called by the DOM when this element has been instantiated. + * + * Will be replaced by created constructor. */ @Experimental() - void created() {} + @deprecated + void createdCallback() {} /** * Called by the DOM when this element has been inserted into the live @@ -9165,6 +9287,11 @@ @Experimental() void leftView() {} + /** + * Called by the DOM whenever an attribute on this has been changed. + */ + void attributeChanged(String name, String oldValue, String newValue) {} + // Hooks to support custom WebComponents. @Creates('Null') // Set from Dart code; does not instantiate a native type. @@ -10658,6 +10785,12 @@ @DomName('HTMLEmbedElement.HTMLEmbedElement') @DocsEditable() factory EmbedElement() => document.createElement("embed"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + EmbedElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => Element.isTagSupported('embed'); @@ -11259,6 +11392,9 @@ @DomName('EventTarget') class EventTarget extends Interceptor native "EventTarget" { + // Custom element created callback. + EventTarget._created(); + /** * This is an ease-of-use accessor for event streams which should only be * used when an explicit accessor is not available. @@ -11297,6 +11433,12 @@ @DomName('HTMLFieldSetElement.HTMLFieldSetElement') @DocsEditable() factory FieldSetElement() => document.createElement("fieldset"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FieldSetElement.created() : super.created(); @DomName('HTMLFieldSetElement.disabled') @DocsEditable() @@ -11991,6 +12133,12 @@ @DomName('HTMLFormElement.HTMLFormElement') @DocsEditable() factory FormElement() => document.createElement("form"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FormElement.created() : super.created(); @DomName('HTMLFormElement.acceptCharset') @DocsEditable() @@ -12251,6 +12399,12 @@ @DomName('HTMLHRElement.HTMLHRElement') @DocsEditable() factory HRElement() => document.createElement("hr"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + HRElement.created() : super.created(); } // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -12307,6 +12461,12 @@ @DomName('HTMLHeadElement.HTMLHeadElement') @DocsEditable() factory HeadElement() => document.createElement("head"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + HeadElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -12342,6 +12502,12 @@ @DomName('HTMLHeadingElement.HTMLHeadingElement') @DocsEditable() factory HeadingElement.h6() => document.createElement("h6"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + HeadingElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -12900,6 +13066,12 @@ @DomName('HTMLHtmlElement.HTMLHtmlElement') @DocsEditable() factory HtmlHtmlElement() => document.createElement("html"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + HtmlHtmlElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -13001,7 +13173,7 @@ } /** - * Creates a URL request for the specified [url]. + * Creates and sends a URL request for the specified [url]. * * By default `request` will perform an HTTP GET request, but a different * method (`POST`, `PUT`, `DELETE`, etc) can be used by specifying the @@ -13485,6 +13657,12 @@ @DomName('HTMLIFrameElement.HTMLIFrameElement') @DocsEditable() factory IFrameElement() => document.createElement("iframe"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + IFrameElement.created() : super.created(); @DomName('HTMLIFrameElement.contentWindow') @DocsEditable() @@ -13584,6 +13762,12 @@ if (height != null) e.height = height; return e; } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + ImageElement.created() : super.created(); @DomName('HTMLImageElement.alt') @DocsEditable() @@ -13697,6 +13881,12 @@ @Experimental() // http://lists.w3.org/Archives/Public/public-xg-htmlspeech/2011Feb/att-0020/api-draft.html#extending_html_elements static const EventStreamProvider<Event> speechChangeEvent = const EventStreamProvider<Event>('webkitSpeechChange'); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + InputElement.created() : super.created(); @DomName('HTMLInputElement.accept') @DocsEditable() @@ -14718,6 +14908,12 @@ @DomName('HTMLKeygenElement.HTMLKeygenElement') @DocsEditable() factory KeygenElement() => document.createElement("keygen"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + KeygenElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => Element.isTagSupported('keygen') && (new Element.tag('keygen') is KeygenElement); @@ -14791,6 +14987,12 @@ @DomName('HTMLLIElement.HTMLLIElement') @DocsEditable() factory LIElement() => document.createElement("li"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + LIElement.created() : super.created(); @DomName('HTMLLIElement.type') @DocsEditable() @@ -14816,6 +15018,12 @@ @DomName('HTMLLabelElement.HTMLLabelElement') @DocsEditable() factory LabelElement() => document.createElement("label"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + LabelElement.created() : super.created(); @DomName('HTMLLabelElement.control') @DocsEditable() @@ -14843,6 +15051,12 @@ @DomName('HTMLLegendElement.HTMLLegendElement') @DocsEditable() factory LegendElement() => document.createElement("legend"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + LegendElement.created() : super.created(); @DomName('HTMLLegendElement.form') @DocsEditable() @@ -14862,6 +15076,12 @@ @DomName('HTMLLinkElement.HTMLLinkElement') @DocsEditable() factory LinkElement() => document.createElement("link"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + LinkElement.created() : super.created(); @DomName('HTMLLinkElement.disabled') @DocsEditable() @@ -15009,6 +15229,12 @@ @DomName('HTMLMapElement.HTMLMapElement') @DocsEditable() factory MapElement() => document.createElement("map"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + MapElement.created() : super.created(); @DomName('HTMLMapElement.areas') @DocsEditable() @@ -15223,6 +15449,12 @@ @Experimental() // https://dvcs.w3.org/hg/html-media/raw-file/eme-v0.1/encrypted-media/encrypted-media.html#dom-keyadded static const EventStreamProvider<MediaKeyEvent> needKeyEvent = const EventStreamProvider<MediaKeyEvent>('webkitneedkey'); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + MediaElement.created() : super.created(); @DomName('HTMLMediaElement.HAVE_CURRENT_DATA') @DocsEditable() @@ -16226,6 +16458,12 @@ @DomName('HTMLMenuElement.HTMLMenuElement') @DocsEditable() factory MenuElement() => document.createElement("menu"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + MenuElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -16373,6 +16611,12 @@ @DomName('HTMLMetaElement.HTMLMetaElement') @DocsEditable() factory MetaElement() => document.createElement("meta"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + MetaElement.created() : super.created(); @DomName('HTMLMetaElement.content') @DocsEditable() @@ -16439,6 +16683,12 @@ @DomName('HTMLMeterElement.HTMLMeterElement') @DocsEditable() factory MeterElement() => document.createElement("meter"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + MeterElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => Element.isTagSupported('meter'); @@ -16750,6 +17000,12 @@ class ModElement extends HtmlElement native "HTMLModElement" { // To suppress missing implicit constructor warnings. factory ModElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + ModElement.created() : super.created(); @DomName('HTMLModElement.cite') @DocsEditable() @@ -17708,6 +17964,10 @@ @DomName('Node') class Node extends EventTarget native "Node" { + + // Custom element created callback. + Node._created() : super._created(); + List<Node> get nodes { return new _ChildNodeListLazy(this); } @@ -18387,6 +18647,12 @@ @DomName('HTMLOListElement.HTMLOListElement') @DocsEditable() factory OListElement() => document.createElement("ol"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + OListElement.created() : super.created(); @DomName('HTMLOListElement.reversed') @DocsEditable() @@ -18418,6 +18684,12 @@ @DomName('HTMLObjectElement.HTMLObjectElement') @DocsEditable() factory ObjectElement() => document.createElement("object"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + ObjectElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => Element.isTagSupported('object'); @@ -18498,6 +18770,12 @@ @DomName('HTMLOptGroupElement.HTMLOptGroupElement') @DocsEditable() factory OptGroupElement() => document.createElement("optgroup"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + OptGroupElement.created() : super.created(); @DomName('HTMLOptGroupElement.disabled') @DocsEditable() @@ -18507,20 +18785,21 @@ @DocsEditable() String label; } -// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -@DocsEditable() @DomName('HTMLOptionElement') class OptionElement extends HtmlElement native "HTMLOptionElement" { - // To suppress missing implicit constructor warnings. - factory OptionElement._() { throw new UnsupportedError("Not supported"); } + factory OptionElement({String data, String value, bool defaultSelected, + bool selected}) { + return new OptionElement._(data, value, defaultSelected, selected); + } @DomName('HTMLOptionElement.HTMLOptionElement') @DocsEditable() - factory OptionElement([String data, String value, bool defaultSelected, bool selected]) { + factory OptionElement._([String data, String value, bool defaultSelected, bool selected]) { if (selected != null) { return OptionElement._create_1(data, value, defaultSelected, selected); } @@ -18540,6 +18819,12 @@ static OptionElement _create_3(data, value) => JS('OptionElement', 'new Option(#,#)', data, value); static OptionElement _create_4(data) => JS('OptionElement', 'new Option(#)', data); static OptionElement _create_5() => JS('OptionElement', 'new Option()'); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + OptionElement.created() : super.created(); @DomName('HTMLOptionElement.defaultSelected') @DocsEditable() @@ -18568,6 +18853,7 @@ @DomName('HTMLOptionElement.value') @DocsEditable() String value; + } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -18586,6 +18872,12 @@ @DomName('HTMLOutputElement.HTMLOutputElement') @DocsEditable() factory OutputElement() => document.createElement("output"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + OutputElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => Element.isTagSupported('output'); @@ -18708,6 +19000,12 @@ @DomName('HTMLParagraphElement.HTMLParagraphElement') @DocsEditable() factory ParagraphElement() => document.createElement("p"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + ParagraphElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -18724,6 +19022,12 @@ @DomName('HTMLParamElement.HTMLParamElement') @DocsEditable() factory ParamElement() => document.createElement("param"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + ParamElement.created() : super.created(); @DomName('HTMLParamElement.name') @DocsEditable() @@ -19366,6 +19670,12 @@ @DomName('HTMLPreElement.HTMLPreElement') @DocsEditable() factory PreElement() => document.createElement("pre"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + PreElement.created() : super.created(); @DomName('HTMLPreElement.wrap') @DocsEditable() @@ -19411,6 +19721,12 @@ @DomName('HTMLProgressElement.HTMLProgressElement') @DocsEditable() factory ProgressElement() => document.createElement("progress"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + ProgressElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => Element.isTagSupported('progress'); @@ -19536,6 +19852,12 @@ @DomName('HTMLQuoteElement.HTMLQuoteElement') @DocsEditable() factory QuoteElement() => document.createElement("q"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + QuoteElement.created() : super.created(); @DomName('HTMLQuoteElement.cite') @DocsEditable() @@ -20558,6 +20880,12 @@ @DomName('HTMLScriptElement.HTMLScriptElement') @DocsEditable() factory ScriptElement() => document.createElement("script"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + ScriptElement.created() : super.created(); @DomName('HTMLScriptElement.async') @DocsEditable() @@ -20745,6 +21073,12 @@ @DomName('HTMLSelectElement.HTMLSelectElement') @DocsEditable() factory SelectElement() => document.createElement("select"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + SelectElement.created() : super.created(); @DomName('HTMLSelectElement.autofocus') @DocsEditable() @@ -20988,6 +21322,12 @@ @DomName('HTMLShadowElement.HTMLShadowElement') @DocsEditable() factory ShadowElement() => document.createElement("shadow"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + ShadowElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => Element.isTagSupported('shadow'); @@ -21231,6 +21571,12 @@ @DomName('HTMLSourceElement.HTMLSourceElement') @DocsEditable() factory SourceElement() => document.createElement("source"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + SourceElement.created() : super.created(); @DomName('HTMLSourceElement.media') @DocsEditable() @@ -21288,6 +21634,12 @@ @DomName('HTMLSpanElement.HTMLSpanElement') @DocsEditable() factory SpanElement() => document.createElement("span"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + SpanElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -22187,6 +22539,12 @@ @DomName('HTMLStyleElement.HTMLStyleElement') @DocsEditable() factory StyleElement() => document.createElement("style"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + StyleElement.created() : super.created(); @DomName('HTMLStyleElement.disabled') @DocsEditable() @@ -22278,6 +22636,12 @@ @DomName('HTMLTableCaptionElement.HTMLTableCaptionElement') @DocsEditable() factory TableCaptionElement() => document.createElement("caption"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + TableCaptionElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -22293,6 +22657,12 @@ @DomName('HTMLTableCellElement.HTMLTableCellElement') @DocsEditable() factory TableCellElement() => document.createElement("td"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + TableCellElement.created() : super.created(); @DomName('HTMLTableCellElement.cellIndex') @DocsEditable() @@ -22324,6 +22694,12 @@ @DomName('HTMLTableColElement.HTMLTableColElement') @DocsEditable() factory TableColElement() => document.createElement("col"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + TableColElement.created() : super.created(); @DomName('HTMLTableColElement.span') @DocsEditable() @@ -22390,6 +22766,12 @@ @DomName('HTMLTableElement.HTMLTableElement') @DocsEditable() factory TableElement() => document.createElement("table"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + TableElement.created() : super.created(); @DomName('HTMLTableElement.border') @DocsEditable() @@ -22495,6 +22877,12 @@ @DomName('HTMLTableRowElement.HTMLTableRowElement') @DocsEditable() factory TableRowElement() => document.createElement("tr"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + TableRowElement.created() : super.created(); @JSName('cells') @DomName('HTMLTableRowElement.cells') @@ -22553,6 +22941,12 @@ // To suppress missing implicit constructor warnings. factory TableSectionElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + TableSectionElement.created() : super.created(); @JSName('rows') @DomName('HTMLTableSectionElement.rows') @@ -22669,6 +23063,12 @@ @DomName('HTMLTemplateElement.HTMLTemplateElement') @DocsEditable() factory TemplateElement() => document.createElement("template"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + TemplateElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => Element.isTagSupported('template'); @@ -22942,6 +23342,12 @@ @DomName('HTMLTextAreaElement.HTMLTextAreaElement') @DocsEditable() factory TextAreaElement() => document.createElement("textarea"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + TextAreaElement.created() : super.created(); @DomName('HTMLTextAreaElement.autofocus') @DocsEditable() @@ -23447,6 +23853,12 @@ @DomName('HTMLTitleElement.HTMLTitleElement') @DocsEditable() factory TitleElement() => document.createElement("title"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + TitleElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -23713,6 +24125,12 @@ @DomName('HTMLTrackElement.HTMLTrackElement') @DocsEditable() factory TrackElement() => document.createElement("track"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + TrackElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => Element.isTagSupported('track'); @@ -23990,6 +24408,12 @@ @DomName('HTMLUListElement.HTMLUListElement') @DocsEditable() factory UListElement() => document.createElement("ul"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + UListElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -24001,6 +24425,12 @@ class UnknownElement extends HtmlElement native "HTMLUnknownElement" { // To suppress missing implicit constructor warnings. factory UnknownElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + UnknownElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -24096,6 +24526,12 @@ @DomName('HTMLVideoElement.HTMLVideoElement') @DocsEditable() factory VideoElement() => document.createElement("video"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + VideoElement.created() : super.created(); @DomName('HTMLVideoElement.height') @DocsEditable() @@ -27068,6 +27504,12 @@ abstract class _HTMLAppletElement extends HtmlElement native "HTMLAppletElement" { // To suppress missing implicit constructor warnings. factory _HTMLAppletElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _HTMLAppletElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -27081,6 +27523,12 @@ abstract class _HTMLBaseFontElement extends HtmlElement native "HTMLBaseFontElement" { // To suppress missing implicit constructor warnings. factory _HTMLBaseFontElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _HTMLBaseFontElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -27094,6 +27542,12 @@ abstract class _HTMLDirectoryElement extends HtmlElement native "HTMLDirectoryElement" { // To suppress missing implicit constructor warnings. factory _HTMLDirectoryElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _HTMLDirectoryElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -27107,6 +27561,12 @@ abstract class _HTMLFontElement extends HtmlElement native "HTMLFontElement" { // To suppress missing implicit constructor warnings. factory _HTMLFontElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _HTMLFontElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -27120,6 +27580,12 @@ abstract class _HTMLFrameElement extends HtmlElement native "HTMLFrameElement" { // To suppress missing implicit constructor warnings. factory _HTMLFrameElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _HTMLFrameElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -27133,6 +27599,12 @@ abstract class _HTMLFrameSetElement extends HtmlElement native "HTMLFrameSetElement" { // To suppress missing implicit constructor warnings. factory _HTMLFrameSetElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _HTMLFrameSetElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -27146,6 +27618,12 @@ abstract class _HTMLMarqueeElement extends HtmlElement native "HTMLMarqueeElement" { // To suppress missing implicit constructor warnings. factory _HTMLMarqueeElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _HTMLMarqueeElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -32060,7 +32538,7 @@ _callCreated(receiver) { - return receiver.created(); + return receiver.createdCallback(); } _callEnteredView(receiver) { @@ -32070,6 +32548,9 @@ _callLeftView(receiver) { return receiver.leftView(); } + _callAttributeChanged(receiver, name, oldValue, newValue) { + return receiver.attributeChanged(name, oldValue, newValue); +} _makeCallbackMethod(callback) { return JS('', @@ -32081,6 +32562,16 @@ convertDartClosureToJS(callback, 1)); } +_makeCallbackMethod3(callback) { + return JS('', + '''((function(invokeCallback) { + return function(arg1, arg2, arg3) { + return invokeCallback(this, arg1, arg2, arg3); + }; + })(#))''', + convertDartClosureToJS(callback, 4)); +} + const _typeNameToTag = const { 'HTMLAnchorElement': 'a', 'HTMLAudioElement': 'audio', @@ -32146,6 +32637,8 @@ JS('=Object', '{value: #}', _makeCallbackMethod(_callEnteredView))); JS('void', '#.leftViewCallback = #', properties, JS('=Object', '{value: #}', _makeCallbackMethod(_callLeftView))); + JS('void', '#.attributeChangedCallback = #', properties, + JS('=Object', '{value: #}', _makeCallbackMethod3(_callAttributeChanged))); // TODO(blois): Bug 13220- remove once transition is complete JS('void', '#.enteredDocumentCallback = #', properties, @@ -32172,6 +32665,11 @@ JS('void', '#.register(#, #)', document, tag, options); } + +//// Called by Element.created to do validation & initialization. +void _initializeCustomElement(Element e) { + // TODO(blois): Add validation that this is only in response to an upgrade. +} // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file.
diff --git a/sdk/lib/html/dartium/html_dartium.dart b/sdk/lib/html/dartium/html_dartium.dart index 106ac6c..c9879ea 100644 --- a/sdk/lib/html/dartium/html_dartium.dart +++ b/sdk/lib/html/dartium/html_dartium.dart
@@ -208,6 +208,12 @@ if (href != null) e.href = href; return e; } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + AnchorElement.created() : super.created(); @DomName('HTMLAnchorElement.download') @DocsEditable() @@ -538,6 +544,12 @@ @DomName('HTMLAreaElement.HTMLAreaElement') @DocsEditable() factory AreaElement() => document.createElement("area"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + AreaElement.created() : super.created(); @DomName('HTMLAreaElement.alt') @DocsEditable() @@ -641,6 +653,12 @@ @DocsEditable() static AudioElement _create_1(src) native "HTMLAudioElement__create_1constructorCallback"; + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + AudioElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file @@ -679,6 +697,12 @@ @DomName('HTMLBRElement.HTMLBRElement') @DocsEditable() factory BRElement() => document.createElement("br"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + BRElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file @@ -715,6 +739,12 @@ @DomName('HTMLBaseElement.HTMLBaseElement') @DocsEditable() factory BaseElement() => document.createElement("base"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + BaseElement.created() : super.created(); @DomName('HTMLBaseElement.href') @DocsEditable() @@ -862,6 +892,12 @@ @DomName('HTMLBodyElement.HTMLBodyElement') @DocsEditable() factory BodyElement() => document.createElement("body"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + BodyElement.created() : super.created(); @DomName('HTMLBodyElement.onblur') @DocsEditable() @@ -928,6 +964,12 @@ @DomName('HTMLButtonElement.HTMLButtonElement') @DocsEditable() factory ButtonElement() => document.createElement("button"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + ButtonElement.created() : super.created(); @DomName('HTMLButtonElement.autofocus') @DocsEditable() @@ -1103,6 +1145,12 @@ if (height != null) e.height = height; return e; } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + CanvasElement.created() : super.created(); /// The height of this canvas element in CSS pixels. @DomName('HTMLCanvasElement.height') @@ -2370,6 +2418,12 @@ @DomName('HTMLContentElement.HTMLContentElement') @DocsEditable() factory ContentElement() => document.createElement("content"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + ContentElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => true; @@ -6885,6 +6939,12 @@ @DomName('HTMLDListElement.HTMLDListElement') @DocsEditable() factory DListElement() => document.createElement("dl"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + DListElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file @@ -6907,6 +6967,12 @@ @DomName('HTMLDataListElement.HTMLDataListElement') @DocsEditable() factory DataListElement() => document.createElement("datalist"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + DataListElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => true; @@ -7146,6 +7212,12 @@ @DomName('HTMLDetailsElement.HTMLDetailsElement') @DocsEditable() factory DetailsElement() => document.createElement("details"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + DetailsElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => true; @@ -7298,6 +7370,12 @@ class DialogElement extends HtmlElement { // To suppress missing implicit constructor warnings. factory DialogElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + DialogElement.created() : super.created(); @DomName('HTMLDialogElement.open') @DocsEditable() @@ -7485,6 +7563,12 @@ @DomName('HTMLDivElement.HTMLDivElement') @DocsEditable() factory DivElement() => document.createElement("div"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + DivElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file @@ -8144,7 +8228,6 @@ @Experimental() Stream<Event> get onPointerLockError => pointerLockErrorEvent.forTarget(this); - /** * Finds all descendant elements of this document that match the specified * group of selectors. @@ -9373,6 +9456,30 @@ } /** + * Custom element creation constructor. + * + * This constructor is used by the DOM when a custom element has been + * created. It can only be invoked by subclasses of Element from + * that classes created constructor. + * + * class CustomElement extends Element { + * factory CustomElement() => new Element.tag('x-custom'); + * + * CustomElement.created() : super.created() { + * // Perform any element initialization. + * } + * } + * document.register('x-custom', CustomElement); + */ + Element.created() : super._created() { + // Validate that this is a custom element & perform any additional + // initialization. + _initializeCustomElement(this); + + createdCallback(); + } + + /** * Creates the HTML element specified by the tag name. * * This is similar to [Document.createElement]. @@ -9715,9 +9822,12 @@ /** * Called by the DOM when this element has been instantiated. + * + * Will be replaced by created constructor. */ @Experimental() - void created() {} + @deprecated + void createdCallback() {} /** * Called by the DOM when this element has been inserted into the live @@ -9733,6 +9843,11 @@ @Experimental() void leftView() {} + /** + * Called by the DOM whenever an attribute on this has been changed. + */ + void attributeChanged(String name, String oldValue, String newValue) {} + // Hooks to support custom WebComponents. Element _xtag; @@ -11056,6 +11171,12 @@ @DomName('HTMLEmbedElement.HTMLEmbedElement') @DocsEditable() factory EmbedElement() => document.createElement("embed"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + EmbedElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => true; @@ -11687,6 +11808,9 @@ @DomName('EventTarget') class EventTarget extends NativeFieldWrapperClass1 { + // Custom element created callback. + EventTarget._created(); + /** * This is an ease-of-use accessor for event streams which should only be * used when an explicit accessor is not available. @@ -11725,6 +11849,12 @@ @DomName('HTMLFieldSetElement.HTMLFieldSetElement') @DocsEditable() factory FieldSetElement() => document.createElement("fieldset"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FieldSetElement.created() : super.created(); @DomName('HTMLFieldSetElement.disabled') @DocsEditable() @@ -12477,6 +12607,12 @@ @DomName('HTMLFormElement.HTMLFormElement') @DocsEditable() factory FormElement() => document.createElement("form"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FormElement.created() : super.created(); @DomName('HTMLFormElement.acceptCharset') @DocsEditable() @@ -12763,6 +12899,12 @@ @DomName('HTMLHRElement.HTMLHRElement') @DocsEditable() factory HRElement() => document.createElement("hr"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + HRElement.created() : super.created(); } // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file @@ -12819,6 +12961,12 @@ @DomName('HTMLHeadElement.HTMLHeadElement') @DocsEditable() factory HeadElement() => document.createElement("head"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + HeadElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file @@ -12857,6 +13005,12 @@ @DomName('HTMLHeadingElement.HTMLHeadingElement') @DocsEditable() factory HeadingElement.h6() => document.createElement("h6"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + HeadingElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file @@ -13395,6 +13549,12 @@ class HtmlElement extends Element { // To suppress missing implicit constructor warnings. factory HtmlElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + HtmlElement.created() : super.created(); @DomName('HTMLElement.contentEditable') @DocsEditable() @@ -13566,6 +13726,12 @@ @DomName('HTMLHtmlElement.HTMLHtmlElement') @DocsEditable() factory HtmlHtmlElement() => document.createElement("html"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + HtmlHtmlElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file @@ -13671,7 +13837,7 @@ } /** - * Creates a URL request for the specified [url]. + * Creates and sends a URL request for the specified [url]. * * By default `request` will perform an HTTP GET request, but a different * method (`POST`, `PUT`, `DELETE`, etc) can be used by specifying the @@ -14140,6 +14306,12 @@ @DomName('HTMLIFrameElement.HTMLIFrameElement') @DocsEditable() factory IFrameElement() => document.createElement("iframe"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + IFrameElement.created() : super.created(); @DomName('HTMLIFrameElement.contentWindow') @DocsEditable() @@ -14273,6 +14445,12 @@ if (height != null) e.height = height; return e; } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + ImageElement.created() : super.created(); @DomName('HTMLImageElement.alt') @DocsEditable() @@ -14424,6 +14602,12 @@ @Experimental() // http://lists.w3.org/Archives/Public/public-xg-htmlspeech/2011Feb/att-0020/api-draft.html#extending_html_elements static const EventStreamProvider<Event> speechChangeEvent = const EventStreamProvider<Event>('webkitSpeechChange'); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + InputElement.created() : super.created(); @DomName('HTMLInputElement.accept') @DocsEditable() @@ -15620,6 +15804,12 @@ @DomName('HTMLKeygenElement.HTMLKeygenElement') @DocsEditable() factory KeygenElement() => document.createElement("keygen"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + KeygenElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => true; @@ -15714,6 +15904,12 @@ @DomName('HTMLLIElement.HTMLLIElement') @DocsEditable() factory LIElement() => document.createElement("li"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + LIElement.created() : super.created(); @DomName('HTMLLIElement.type') @DocsEditable() @@ -15752,6 +15948,12 @@ @DomName('HTMLLabelElement.HTMLLabelElement') @DocsEditable() factory LabelElement() => document.createElement("label"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + LabelElement.created() : super.created(); @DomName('HTMLLabelElement.control') @DocsEditable() @@ -15786,6 +15988,12 @@ @DomName('HTMLLegendElement.HTMLLegendElement') @DocsEditable() factory LegendElement() => document.createElement("legend"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + LegendElement.created() : super.created(); @DomName('HTMLLegendElement.form') @DocsEditable() @@ -15808,6 +16016,12 @@ @DomName('HTMLLinkElement.HTMLLinkElement') @DocsEditable() factory LinkElement() => document.createElement("link"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + LinkElement.created() : super.created(); @DomName('HTMLLinkElement.disabled') @DocsEditable() @@ -16015,6 +16229,12 @@ @DomName('HTMLMapElement.HTMLMapElement') @DocsEditable() factory MapElement() => document.createElement("map"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + MapElement.created() : super.created(); @DomName('HTMLMapElement.areas') @DocsEditable() @@ -16273,6 +16493,12 @@ @Experimental() // https://dvcs.w3.org/hg/html-media/raw-file/eme-v0.1/encrypted-media/encrypted-media.html#dom-keyadded static const EventStreamProvider<MediaKeyEvent> needKeyEvent = const EventStreamProvider<MediaKeyEvent>('webkitneedkey'); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + MediaElement.created() : super.created(); @DomName('HTMLMediaElement.HAVE_CURRENT_DATA') @DocsEditable() @@ -17474,6 +17700,12 @@ @DomName('HTMLMenuElement.HTMLMenuElement') @DocsEditable() factory MenuElement() => document.createElement("menu"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + MenuElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file @@ -17611,6 +17843,12 @@ @DomName('HTMLMetaElement.HTMLMetaElement') @DocsEditable() factory MetaElement() => document.createElement("meta"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + MetaElement.created() : super.created(); @DomName('HTMLMetaElement.content') @DocsEditable() @@ -17690,6 +17928,12 @@ @DomName('HTMLMeterElement.HTMLMeterElement') @DocsEditable() factory MeterElement() => document.createElement("meter"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + MeterElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => true; @@ -18087,6 +18331,12 @@ class ModElement extends HtmlElement { // To suppress missing implicit constructor warnings. factory ModElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + ModElement.created() : super.created(); @DomName('HTMLModElement.cite') @DocsEditable() @@ -19024,6 +19274,10 @@ @DomName('Node') class Node extends EventTarget { + + // Custom element created callback. + Node._created() : super._created(); + List<Node> get nodes { return new _ChildNodeListLazy(this); } @@ -19736,6 +19990,12 @@ @DomName('HTMLOListElement.HTMLOListElement') @DocsEditable() factory OListElement() => document.createElement("ol"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + OListElement.created() : super.created(); @DomName('HTMLOListElement.reversed') @DocsEditable() @@ -19782,6 +20042,12 @@ @DomName('HTMLObjectElement.HTMLObjectElement') @DocsEditable() factory ObjectElement() => document.createElement("object"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + ObjectElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => true; @@ -19895,6 +20161,12 @@ @DomName('HTMLOptGroupElement.HTMLOptGroupElement') @DocsEditable() factory OptGroupElement() => document.createElement("optgroup"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + OptGroupElement.created() : super.created(); @DomName('HTMLOptGroupElement.disabled') @DocsEditable() @@ -19913,27 +20185,32 @@ void set label(String value) native "HTMLOptGroupElement_label_Setter"; } -// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -// WARNING: Do not edit - generated code. - -@DocsEditable() @DomName('HTMLOptionElement') class OptionElement extends HtmlElement { - // To suppress missing implicit constructor warnings. - factory OptionElement._() { throw new UnsupportedError("Not supported"); } + factory OptionElement({String data, String value, bool defaultSelected, + bool selected}) { + return new OptionElement._(data, value, defaultSelected, selected); + } @DomName('HTMLOptionElement.HTMLOptionElement') @DocsEditable() - factory OptionElement([String data, String value, bool defaultSelected, bool selected]) { + factory OptionElement._([String data, String value, bool defaultSelected, bool selected]) { return OptionElement._create_1(data, value, defaultSelected, selected); } @DocsEditable() static OptionElement _create_1(data, value, defaultSelected, selected) native "HTMLOptionElement__create_1constructorCallback"; + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + OptionElement.created() : super.created(); @DomName('HTMLOptionElement.defaultSelected') @DocsEditable() @@ -20003,6 +20280,12 @@ @DomName('HTMLOutputElement.HTMLOutputElement') @DocsEditable() factory OutputElement() => document.createElement("output"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + OutputElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => true; @@ -20144,6 +20427,12 @@ @DomName('HTMLParagraphElement.HTMLParagraphElement') @DocsEditable() factory ParagraphElement() => document.createElement("p"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + ParagraphElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file @@ -20163,6 +20452,12 @@ @DomName('HTMLParamElement.HTMLParamElement') @DocsEditable() factory ParamElement() => document.createElement("param"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + ParamElement.created() : super.created(); @DomName('HTMLParamElement.name') @DocsEditable() @@ -20881,6 +21176,12 @@ @DomName('HTMLPreElement.HTMLPreElement') @DocsEditable() factory PreElement() => document.createElement("pre"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + PreElement.created() : super.created(); @DomName('HTMLPreElement.wrap') @DocsEditable() @@ -20937,6 +21238,12 @@ @DomName('HTMLProgressElement.HTMLProgressElement') @DocsEditable() factory ProgressElement() => document.createElement("progress"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + ProgressElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => true; @@ -21080,6 +21387,12 @@ @DomName('HTMLQuoteElement.HTMLQuoteElement') @DocsEditable() factory QuoteElement() => document.createElement("q"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + QuoteElement.created() : super.created(); @DomName('HTMLQuoteElement.cite') @DocsEditable() @@ -22100,6 +22413,12 @@ @DomName('HTMLScriptElement.HTMLScriptElement') @DocsEditable() factory ScriptElement() => document.createElement("script"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + ScriptElement.created() : super.created(); @DomName('HTMLScriptElement.async') @DocsEditable() @@ -22334,6 +22653,12 @@ @DomName('HTMLSelectElement.HTMLSelectElement') @DocsEditable() factory SelectElement() => document.createElement("select"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + SelectElement.created() : super.created(); @DomName('HTMLSelectElement.autofocus') @DocsEditable() @@ -22616,6 +22941,12 @@ @DomName('HTMLShadowElement.HTMLShadowElement') @DocsEditable() factory ShadowElement() => document.createElement("shadow"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + ShadowElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => true; @@ -22921,6 +23252,12 @@ @DomName('HTMLSourceElement.HTMLSourceElement') @DocsEditable() factory SourceElement() => document.createElement("source"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + SourceElement.created() : super.created(); @DomName('HTMLSourceElement.media') @DocsEditable() @@ -22996,6 +23333,12 @@ @DomName('HTMLSpanElement.HTMLSpanElement') @DocsEditable() factory SpanElement() => document.createElement("span"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + SpanElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file @@ -24059,6 +24402,12 @@ @DomName('HTMLStyleElement.HTMLStyleElement') @DocsEditable() factory StyleElement() => document.createElement("style"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + StyleElement.created() : super.created(); @DomName('HTMLStyleElement.disabled') @DocsEditable() @@ -24179,6 +24528,12 @@ @DomName('HTMLTableCaptionElement.HTMLTableCaptionElement') @DocsEditable() factory TableCaptionElement() => document.createElement("caption"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + TableCaptionElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file @@ -24197,6 +24552,12 @@ @DomName('HTMLTableCellElement.HTMLTableCellElement') @DocsEditable() factory TableCellElement() => document.createElement("td"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + TableCellElement.created() : super.created(); @DomName('HTMLTableCellElement.cellIndex') @DocsEditable() @@ -24243,6 +24604,12 @@ @DomName('HTMLTableColElement.HTMLTableColElement') @DocsEditable() factory TableColElement() => document.createElement("col"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + TableColElement.created() : super.created(); @DomName('HTMLTableColElement.span') @DocsEditable() @@ -24287,6 +24654,12 @@ @DomName('HTMLTableElement.HTMLTableElement') @DocsEditable() factory TableElement() => document.createElement("table"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + TableElement.created() : super.created(); @DomName('HTMLTableElement.border') @DocsEditable() @@ -24394,6 +24767,12 @@ @DomName('HTMLTableRowElement.HTMLTableRowElement') @DocsEditable() factory TableRowElement() => document.createElement("tr"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + TableRowElement.created() : super.created(); @DomName('HTMLTableRowElement.cells') @DocsEditable() @@ -24437,6 +24816,12 @@ // To suppress missing implicit constructor warnings. factory TableSectionElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + TableSectionElement.created() : super.created(); @DomName('HTMLTableSectionElement.rows') @DocsEditable() @@ -24551,6 +24936,12 @@ @DomName('HTMLTemplateElement.HTMLTemplateElement') @DocsEditable() factory TemplateElement() => document.createElement("template"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + TemplateElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => true; @@ -24823,6 +25214,12 @@ @DomName('HTMLTextAreaElement.HTMLTextAreaElement') @DocsEditable() factory TextAreaElement() => document.createElement("textarea"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + TextAreaElement.created() : super.created(); @DomName('HTMLTextAreaElement.autofocus') @DocsEditable() @@ -25530,6 +25927,12 @@ @DomName('HTMLTitleElement.HTMLTitleElement') @DocsEditable() factory TitleElement() => document.createElement("title"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + TitleElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file @@ -25783,6 +26186,12 @@ @DomName('HTMLTrackElement.HTMLTrackElement') @DocsEditable() factory TrackElement() => document.createElement("track"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + TrackElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => true; @@ -26078,6 +26487,12 @@ @DomName('HTMLUListElement.HTMLUListElement') @DocsEditable() factory UListElement() => document.createElement("ul"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + UListElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file @@ -26092,6 +26507,12 @@ class UnknownElement extends HtmlElement { // To suppress missing implicit constructor warnings. factory UnknownElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + UnknownElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file @@ -26114,13 +26535,13 @@ if ((blob_OR_source_OR_stream is Blob || blob_OR_source_OR_stream == null)) { return _createObjectURL_1(blob_OR_source_OR_stream); } - if ((blob_OR_source_OR_stream is MediaSource || blob_OR_source_OR_stream == null)) { + if ((blob_OR_source_OR_stream is MediaStream || blob_OR_source_OR_stream == null)) { return _createObjectURL_2(blob_OR_source_OR_stream); } - if ((blob_OR_source_OR_stream is _WebKitMediaSource || blob_OR_source_OR_stream == null)) { + if ((blob_OR_source_OR_stream is MediaSource || blob_OR_source_OR_stream == null)) { return _createObjectURL_3(blob_OR_source_OR_stream); } - if ((blob_OR_source_OR_stream is MediaStream || blob_OR_source_OR_stream == null)) { + if ((blob_OR_source_OR_stream is _WebKitMediaSource || blob_OR_source_OR_stream == null)) { return _createObjectURL_4(blob_OR_source_OR_stream); } throw new ArgumentError("Incorrect number or type of arguments"); @@ -26216,6 +26637,12 @@ @DomName('HTMLVideoElement.HTMLVideoElement') @DocsEditable() factory VideoElement() => document.createElement("video"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + VideoElement.created() : super.created(); @DomName('HTMLVideoElement.height') @DocsEditable() @@ -29094,6 +29521,12 @@ abstract class _HTMLAppletElement extends HtmlElement { // To suppress missing implicit constructor warnings. factory _HTMLAppletElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _HTMLAppletElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file @@ -29110,6 +29543,12 @@ abstract class _HTMLBaseFontElement extends HtmlElement { // To suppress missing implicit constructor warnings. factory _HTMLBaseFontElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _HTMLBaseFontElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file @@ -29126,6 +29565,12 @@ abstract class _HTMLDirectoryElement extends HtmlElement { // To suppress missing implicit constructor warnings. factory _HTMLDirectoryElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _HTMLDirectoryElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file @@ -29142,6 +29587,12 @@ abstract class _HTMLFontElement extends HtmlElement { // To suppress missing implicit constructor warnings. factory _HTMLFontElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _HTMLFontElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file @@ -29158,6 +29609,12 @@ abstract class _HTMLFrameElement extends HtmlElement { // To suppress missing implicit constructor warnings. factory _HTMLFrameElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _HTMLFrameElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file @@ -29174,6 +29631,12 @@ abstract class _HTMLFrameSetElement extends HtmlElement { // To suppress missing implicit constructor warnings. factory _HTMLFrameSetElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _HTMLFrameSetElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file @@ -29190,6 +29653,12 @@ abstract class _HTMLMarqueeElement extends HtmlElement { // To suppress missing implicit constructor warnings. factory _HTMLMarqueeElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _HTMLMarqueeElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file @@ -34446,33 +34915,6 @@ } } } -// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - - -// testRunner implementation. -// FIXME: provide a separate lib for testRunner. - -var _testRunner; - -TestRunner get testRunner { - if (_testRunner == null) - _testRunner = new TestRunner._(_NPObject.retrieve("testRunner")); - return _testRunner; -} - -class TestRunner { - final _NPObject _npObject; - - TestRunner._(this._npObject); - - display() => _npObject.invoke('display'); - dumpAsText() => _npObject.invoke('dumpAsText'); - notifyDone() => _npObject.invoke('notifyDone'); - setCanOpenWindows() => _npObject.invoke('setCanOpenWindows'); - waitUntilDone() => _npObject.invoke('waitUntilDone'); -} // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. @@ -34763,6 +35205,10 @@ if (_isBuiltinType(cls)) { throw new UnsupportedError("Invalid custom element from $libName."); } + var className = MirrorSystem.getName(cls.simpleName); + if (!cls.constructors.containsKey(new Symbol('$className.created'))) { + throw new UnsupportedError('Class is missing constructor $className.created'); + } _register(document, tag, type, extendsTagName); } @@ -34770,13 +35216,8 @@ String extendsTagName) native "Utils_register"; static Element createElement(Document document, String tagName) native "Utils_createElement"; -} -class _NPObject extends NativeFieldWrapperClass1 { - _NPObject.internal(); - static _NPObject retrieve(String key) native "NPObject_retrieve"; - property(String propertyName) native "NPObject_property"; - invoke(String methodName, [List args = null]) native "NPObject_invoke"; + static void initializeCustomElement(HtmlElement element) native "Utils_initializeCustomElement"; } class _DOMWindowCrossFrame extends NativeFieldWrapperClass1 implements @@ -34991,3 +35432,7 @@ get _pureIsolateTimerFactoryClosure => ((int milliSeconds, void callback(Timer time), bool repeating) => new _PureIsolateTimer(milliSeconds, callback, repeating)); + +void _initializeCustomElement(Element e) { + _Utils.initializeCustomElement(e); +}
diff --git a/sdk/lib/io/directory.dart b/sdk/lib/io/directory.dart index 671064c..6aa18f8 100644 --- a/sdk/lib/io/directory.dart +++ b/sdk/lib/io/directory.dart
@@ -68,25 +68,59 @@ void createSync({bool recursive: false}); /** - * Creates a temporary directory with a name based on the current - * path. The path is used as a template, and additional - * characters are appended to it to make a unique temporary - * directory name. If the path is the empty string, a default - * system temp directory and name are used for the template. + * Creates a temporary directory in this directory. Additional random + * characters are appended to [template] to produce a unique directory + * name. + * + * Returns a [:Future<Directory>:] that completes with the newly + * created temporary directory. + * + * Deprecated behavior, to be removed Oct 18, 2013: If the path is the + * empty string, the directory is created in the default system temp + * directory. This capability has been moved to the static function + * [createSystemTemp]. + */ + Future<Directory> createTemp([String template]); + + /** + * Synchronously creates a temporary directory in this directory. + * Additional random characters are appended to [template] to produce + * a unique directory name. + * + * Returns the newly created temporary directory. + * + * Deprecated behavior, to be removed Oct 18, 2013: If the path is the + * empty string, the directory is created in the default system temp + * directory. This capability has been moved to the static function + * [createSystemTemp]. + */ + Directory createTempSync([String template]); + + /** + * Creates a temporary directory in the system temp directory. + * The location of the system temp directory is platform-dependent, + * and may be set by an environment variable. + * Additional random characters are appended to [template] to produce + * a unique directory name. * * Returns a [:Future<Directory>:] that completes with the newly * created temporary directory. */ - Future<Directory> createTemp(); + static Future<Directory> createSystemTemp([String template]) => + _Directory.createSystemTemp(template); /** - * Synchronously creates a temporary directory with a name based on the - * current path. The path is used as a template, and additional - * characters are appended to it to make a unique temporary directory name. - * If the path is the empty string, a default system temp directory and name - * are used for the template. Returns the newly created temporary directory. + * Synchronously creates a temporary directory in the system temp directory. + * The location of the system temp directory is platform-dependent, + * and may be set by an environment variable. + * Additional random characters are appended to [template] to produce + * a unique directory name. + * + * Returns a [:Future<Directory>:] that completes with the newly + * created temporary directory. */ - Directory createTempSync(); + static Directory createSystemTempSync([String template]) => + _Directory.createSystemTempSync(template); Future<String> resolveSymbolicLinks();
diff --git a/sdk/lib/io/directory_impl.dart b/sdk/lib/io/directory_impl.dart index d1258fb..ac048de 100644 --- a/sdk/lib/io/directory_impl.dart +++ b/sdk/lib/io/directory_impl.dart
@@ -5,15 +5,6 @@ part of dart.io; class _Directory extends FileSystemEntity implements Directory { - static const CREATE_REQUEST = 0; - static const DELETE_REQUEST = 1; - static const EXISTS_REQUEST = 2; - static const CREATE_TEMP_REQUEST = 3; - static const LIST_START_REQUEST = 4; - static const LIST_NEXT_REQUEST = 5; - static const LIST_STOP_REQUEST = 6; - static const RENAME_REQUEST = 7; - final String path; _Directory(String this.path) { @@ -25,7 +16,7 @@ external static _current(); external static _setCurrent(path); - external static _createTemp(String template); + external static _createTemp(String template, bool system); external static int _exists(String path); external static _create(String path); external static _deleteNative(String path, bool recursive); @@ -158,8 +149,18 @@ } } - Future<Directory> createTemp() { - return _IOService.dispatch(_DIRECTORY_CREATE_TEMP, [path]).then((response) { + // TODO(13720): Make template argument mandatory on Oct 18, 2013. + Future<Directory> createTemp([String template]) { + if (path == '') { + if (template == null) template = ''; + return createSystemTemp(template); + // TODO(13720): On Oct 18, 2013, replace this with + // an error. createTemp cannot be called on a Directory with empty path. + } + String fullTemplate = "$path${Platform.pathSeparator}"; + if (template != null) fullTemplate = "$fullTemplate$template"; + return _IOService.dispatch(_DIRECTORY_CREATE_TEMP, [fullTemplate]) + .then((response) { if (_isErrorResponse(response)) { throw _exceptionOrErrorFromResponse( response, "Creation of temporary directory failed"); @@ -168,11 +169,41 @@ }); } - Directory createTempSync() { - var result = _createTemp(path); + // TODO(13720): Make template argument mandatory on Oct 18, 2013. + Directory createTempSync([String template]) { + if (path == '') { + if (template == null) template = ''; + return createSystemTempSync(template); + // TODO(13720): On Oct 18, 2013, replace this with + // an error. createTemp cannot be called on a Directory with empty path. + } + String fullTemplate = "$path${Platform.pathSeparator}"; + if (template != null) fullTemplate = "$fullTemplate$template"; + var result = _createTemp(fullTemplate, false); if (result is OSError) { throw new DirectoryException("Creation of temporary directory failed", - path, + fullTemplate, + result); + } + return new Directory(result); + } + + static Future<Directory> createSystemTemp(String template) { + return _IOService.dispatch(_DIRECTORY_CREATE_SYSTEM_TEMP, + [template]).then((response) { + if (response is List && response[0] != _SUCCESS_RESPONSE) { + throw new _Directory(template)._exceptionOrErrorFromResponse( + response, "Creation of temporary directory failed"); + } + return new Directory(response); + }); + } + + static Directory createSystemTempSync(String template) { + var result = _createTemp(template, true); + if (result is OSError) { + throw new DirectoryException("Creation of temporary directory failed", + template, result); } return new Directory(result);
diff --git a/sdk/lib/io/file_impl.dart b/sdk/lib/io/file_impl.dart index 1dce796..4df878a 100644 --- a/sdk/lib/io/file_impl.dart +++ b/sdk/lib/io/file_impl.dart
@@ -531,17 +531,13 @@ class _RandomAccessFile implements RandomAccessFile { final String path; int _id; + bool _asyncDispatched = false; SendPort _fileService; _RandomAccessFile(int this._id, String this.path); Future<RandomAccessFile> close() { - if (closed) return _closedException(); - // Set the id_ to 0 (NULL) to ensure the no more async requests - // can be issued for this file. - int id = _id; - _id = 0; - return _IOService.dispatch(_FILE_CLOSE, [id]).then((result) { + return _dispatch(_FILE_CLOSE, [_id], markClosed: true).then((result) { if (result != -1) { _id = result; return this; @@ -554,7 +550,7 @@ external static int _close(int id); void closeSync() { - _checkNotClosed(); + _checkAvailable(); var id = _close(_id); if (id == -1) { throw new FileException("Cannot close file", path); @@ -563,8 +559,7 @@ } Future<int> readByte() { - if (closed) return _closedException(); - return _IOService.dispatch(_FILE_READ_BYTE, [_id]).then((response) { + return _dispatch(_FILE_READ_BYTE, [_id]).then((response) { if (_isErrorResponse(response)) { throw _exceptionFromResponse(response, "readByte failed", path); } @@ -575,7 +570,7 @@ external static _readByte(int id); int readByteSync() { - _checkNotClosed(); + _checkAvailable(); var result = _readByte(_id); if (result is OSError) { throw new FileException("readByte failed", path, result); @@ -587,8 +582,7 @@ if (bytes is !int) { throw new ArgumentError(bytes); } - if (closed) return _closedException(); - return _IOService.dispatch(_FILE_READ, [_id, bytes]).then((response) { + return _dispatch(_FILE_READ, [_id, bytes]).then((response) { if (_isErrorResponse(response)) { throw _exceptionFromResponse(response, "read failed", path); } @@ -599,7 +593,7 @@ external static _read(int id, int bytes); List<int> readSync(int bytes) { - _checkNotClosed(); + _checkAvailable(); if (bytes is !int) { throw new ArgumentError(bytes); } @@ -616,11 +610,10 @@ (end != null && end is !int)) { throw new ArgumentError(); } - if (closed) return _closedException(); if (start == null) start = 0; if (end == null) end = buffer.length; int length = end - start; - return _IOService.dispatch(_FILE_READ_INTO, [_id, length]).then((response) { + return _dispatch(_FILE_READ_INTO, [_id, length]).then((response) { if (_isErrorResponse(response)) { throw _exceptionFromResponse(response, "readInto failed", path); } @@ -642,7 +635,7 @@ external static _readInto(int id, List<int> buffer, int start, int end); int readIntoSync(List<int> buffer, [int start, int end]) { - _checkNotClosed(); + _checkAvailable(); if (buffer is !List || (start != null && start is !int) || (end != null && end is !int)) { @@ -663,8 +656,7 @@ if (value is !int) { throw new ArgumentError(value); } - if (closed) return _closedException(); - return _IOService.dispatch(_FILE_WRITE_BYTE, [_id, value]).then((response) { + return _dispatch(_FILE_WRITE_BYTE, [_id, value]).then((response) { if (_isErrorResponse(response)) { throw _exceptionFromResponse(response, "writeByte failed", path); } @@ -675,7 +667,7 @@ external static _writeByte(int id, int value); int writeByteSync(int value) { - _checkNotClosed(); + _checkAvailable(); if (value is !int) { throw new ArgumentError(value); } @@ -693,8 +685,6 @@ throw new ArgumentError("Invalid arguments to writeFrom"); } - if (closed) return _closedException(); - _BufferAndStart result; try { result = _ensureFastAndSerializableByteData(buffer, start, end); @@ -707,7 +697,7 @@ request[1] = result.buffer; request[2] = result.start; request[3] = end - (start - result.start); - return _IOService.dispatch(_FILE_WRITE_FROM, request).then((response) { + return _dispatch(_FILE_WRITE_FROM, request).then((response) { if (_isErrorResponse(response)) { throw _exceptionFromResponse(response, "writeFrom failed", path); } @@ -718,7 +708,7 @@ external static _writeFrom(int id, List<int> buffer, int start, int end); void writeFromSync(List<int> buffer, [int start, int end]) { - _checkNotClosed(); + _checkAvailable(); if (buffer is !List || (start != null && start is !int) || (end != null && end is !int)) { @@ -757,8 +747,7 @@ } Future<int> position() { - if (closed) return _closedException(); - return _IOService.dispatch(_FILE_POSITION, [_id]).then((response) { + return _dispatch(_FILE_POSITION, [_id]).then((response) { if (_isErrorResponse(response)) { throw _exceptionFromResponse(response, "position failed", path); } @@ -769,7 +758,7 @@ external static _position(int id); int positionSync() { - _checkNotClosed(); + _checkAvailable(); var result = _position(_id); if (result is OSError) { throw new FileException("position failed", path, result); @@ -778,8 +767,7 @@ } Future<RandomAccessFile> setPosition(int position) { - if (closed) return _closedException(); - return _IOService.dispatch(_FILE_SET_POSITION, [_id, position]) + return _dispatch(_FILE_SET_POSITION, [_id, position]) .then((response) { if (_isErrorResponse(response)) { throw _exceptionFromResponse(response, "setPosition failed", path); @@ -791,7 +779,7 @@ external static _setPosition(int id, int position); void setPositionSync(int position) { - _checkNotClosed(); + _checkAvailable(); var result = _setPosition(_id, position); if (result is OSError) { throw new FileException("setPosition failed", path, result); @@ -799,8 +787,7 @@ } Future<RandomAccessFile> truncate(int length) { - if (closed) return _closedException(); - return _IOService.dispatch(_FILE_TRUNCATE, [_id, length]).then((response) { + return _dispatch(_FILE_TRUNCATE, [_id, length]).then((response) { if (_isErrorResponse(response)) { throw _exceptionFromResponse(response, "truncate failed", path); } @@ -811,7 +798,7 @@ external static _truncate(int id, int length); void truncateSync(int length) { - _checkNotClosed(); + _checkAvailable(); var result = _truncate(_id, length); if (result is OSError) { throw new FileException("truncate failed", path, result); @@ -819,8 +806,7 @@ } Future<int> length() { - if (closed) return _closedException(); - return _IOService.dispatch(_FILE_LENGTH, [_id]).then((response) { + return _dispatch(_FILE_LENGTH, [_id]).then((response) { if (_isErrorResponse(response)) { throw _exceptionFromResponse(response, "length failed", path); } @@ -831,7 +817,7 @@ external static _length(int id); int lengthSync() { - _checkNotClosed(); + _checkAvailable(); var result = _length(_id); if (result is OSError) { throw new FileException("length failed", path, result); @@ -840,8 +826,7 @@ } Future<RandomAccessFile> flush() { - if (closed) return _closedException(); - return _IOService.dispatch(_FILE_FLUSH, [_id]).then((response) { + return _dispatch(_FILE_FLUSH, [_id]).then((response) { if (_isErrorResponse(response)) { throw _exceptionFromResponse(response, "flush failed", @@ -854,7 +839,7 @@ external static _flush(int id); void flushSync() { - _checkNotClosed(); + _checkAvailable(); var result = _flush(_id); if (result is OSError) { throw new FileException("flush failed", path, result); @@ -863,13 +848,32 @@ bool get closed => _id == 0; - void _checkNotClosed() { + Future _dispatch(int request, List data, { bool markClosed: false }) { + if (closed) { + return new Future.error(new FileException("File closed", path)); + } + if (_asyncDispatched) { + var msg = "An async operation is currently pending"; + return new Future.error(new FileException(msg, path)); + } + if (markClosed) { + // Set the id_ to 0 (NULL) to ensure the no more async requests + // can be issued for this file. + _id = 0; + } + _asyncDispatched = true; + return _IOService.dispatch(request, data) + .whenComplete(() { + _asyncDispatched = false; + }); + } + + void _checkAvailable() { + if (_asyncDispatched) { + throw new FileException("An async operation is currently pending", path); + } if (closed) { throw new FileException("File closed", path); } } - - Future _closedException() { - return new Future.error(new FileException("File closed", path)); - } }
diff --git a/sdk/lib/io/http.dart b/sdk/lib/io/http.dart index 31f6b97..ee63d1a 100644 --- a/sdk/lib/io/http.dart +++ b/sdk/lib/io/http.dart
@@ -186,6 +186,13 @@ int get port; /** + * Returns the address that the server is listening on. This can be + * used to get the actual address used, when the address is fetched by + * a lookup from a hostname. + */ + InternetAddress get address; + + /** * Sets the timeout, in seconds, for sessions of this [HttpServer]. * The default timeout is 20 minutes. */
diff --git a/sdk/lib/io/http_impl.dart b/sdk/lib/io/http_impl.dart index 99c2806..fcaf191 100644 --- a/sdk/lib/io/http_impl.dart +++ b/sdk/lib/io/http_impl.dart
@@ -2012,6 +2012,11 @@ return _serverSocket.port; } + InternetAddress get address { + if (closed) throw new HttpException("HttpServer is not bound to a socket"); + return _serverSocket.address; + } + set sessionTimeout(int timeout) { _sessionManager.sessionTimeout = timeout; }
diff --git a/sdk/lib/io/io_service.dart b/sdk/lib/io/io_service.dart index 760d022..037cdd1 100644 --- a/sdk/lib/io/io_service.dart +++ b/sdk/lib/io/io_service.dart
@@ -4,6 +4,7 @@ part of dart.io; +// This list must be kept in sync with the list in runtime/bin/io_service.h const int _FILE_EXISTS = 0; const int _FILE_CREATE = 1; const int _FILE_DELETE = 2; @@ -37,11 +38,12 @@ const int _DIRECTORY_DELETE = 30; const int _DIRECTORY_EXISTS = 31; const int _DIRECTORY_CREATE_TEMP = 32; -const int _DIRECTORY_LIST_START = 33; -const int _DIRECTORY_LIST_NEXT = 34; -const int _DIRECTORY_LIST_STOP = 35; -const int _DIRECTORY_RENAME = 36; -const int _SSL_PROCESS_FILTER = 37; +const int _DIRECTORY_CREATE_SYSTEM_TEMP = 33; +const int _DIRECTORY_LIST_START = 34; +const int _DIRECTORY_LIST_NEXT = 35; +const int _DIRECTORY_LIST_STOP = 36; +const int _DIRECTORY_RENAME = 37; +const int _SSL_PROCESS_FILTER = 38; class _IOService { external static Future dispatch(int request, List data);
diff --git a/sdk/lib/io/socket.dart b/sdk/lib/io/socket.dart index c5b4b8d..ce8ace5 100644 --- a/sdk/lib/io/socket.dart +++ b/sdk/lib/io/socket.dart
@@ -202,6 +202,11 @@ int get port; /** + * Returns the address used by this socket. + */ + InternetAddress get address; + + /** * Closes the socket. The returned future completes when the socket * is fully closed and is no longer bound. */ @@ -258,6 +263,11 @@ int get port; /** + * Returns the address used by this socket. + */ + InternetAddress get address; + + /** * Closes the socket. The returned future completes when the socket * is fully closed and is no longer bound. */
diff --git a/sdk/lib/io/stdio.dart b/sdk/lib/io/stdio.dart index 3725526..766eee0 100644 --- a/sdk/lib/io/stdio.dart +++ b/sdk/lib/io/stdio.dart
@@ -29,17 +29,6 @@ } -class _StdinEventSink implements EventSink<String> { - Function _add; - Function _addError; - Function _close; - _StdinEventSink(this._add, this._addError, this._close); - - void add(String string) => _add(string); - void addError(errorEvent) => _addError(errorEvent); - void close() => _close(); -} - /** * [Stdin] allows both synchronous and asynchronous reads from the standard * input stream.
diff --git a/sdk/lib/io/websocket_impl.dart b/sdk/lib/io/websocket_impl.dart index b13709c..e2bc326 100644 --- a/sdk/lib/io/websocket_impl.dart +++ b/sdk/lib/io/websocket_impl.dart
@@ -572,9 +572,7 @@ StreamController _controller; StreamSubscription _subscription; bool _issuedPause = false; - // Only report error if the last message was a user-provided message and not a - // ping or pong message. - bool _reportError = false; + bool _closed = false; Completer _closeCompleter = new Completer(); Completer _completer; @@ -602,6 +600,14 @@ } } + void _cancel() { + if (_subscription != null) { + var subscription = _subscription; + _subscription = null; + subscription.cancel(); + } + } + _ensureController() { if (_controller != null) return; _controller = new StreamController(sync: true, @@ -612,19 +618,20 @@ new _WebSocketOutgoingTransformer(webSocket)); socket.addStream(stream) .then((_) { - _done(); - _closeCompleter.complete(webSocket); - }, - onError: (error) { - if (_reportError) { - if (!_done(error)) { - _closeCompleter.completeError(error); - } - } else { - _done(); - _closeCompleter.complete(webSocket); - } - }); + _done(); + _closeCompleter.complete(webSocket); + }, onError: (error) { + _closed = true; + _cancel(); + if (error is ArgumentError) { + if (!_done(error)) { + _closeCompleter.completeError(error); + } + } else { + _done(); + _closeCompleter.complete(webSocket); + } + }); } bool _done([error]) { @@ -639,11 +646,14 @@ } Future addStream(var stream) { + if (_closed) { + stream.listen(null).cancel(); + return new Future.value(webSocket); + } _ensureController(); _completer = new Completer(); _subscription = stream.listen( (data) { - _reportError = true; _controller.add(data); }, onDone: () { @@ -663,17 +673,23 @@ Future close() { _ensureController(); Future closeSocket() { - return socket.close().then((_) => webSocket); + return socket.close().catchError((_) {}).then((_) => webSocket); } _controller.close(); return _closeCompleter.future.then((_) => closeSocket()); } void add(data) { + if (_closed) return; _ensureController(); - _reportError = false; _controller.add(data); } + + void closeSocket() { + _closed = true; + _cancel(); + close(); + } } @@ -786,21 +802,20 @@ } }, onError: (error) { - if (error is ArgumentError) { - close(WebSocketStatus.INVALID_FRAME_PAYLOAD_DATA); + if (error is FormatException) { + _close(WebSocketStatus.INVALID_FRAME_PAYLOAD_DATA); } else { - close(WebSocketStatus.PROTOCOL_ERROR); + _close(WebSocketStatus.PROTOCOL_ERROR); } - _controller.addError(error); _controller.close(); }, onDone: () { if (_readyState == WebSocket.OPEN) { _readyState = WebSocket.CLOSING; if (!_isReservedStatusCode(transformer.closeCode)) { - close(transformer.closeCode); + _close(transformer.closeCode); } else { - close(); + _close(); } _readyState = WebSocket.CLOSED; } @@ -840,7 +855,7 @@ _consumer.add(new _WebSocketPing()); _pingTimer = new Timer(_pingInterval, () { // No pong received. - close(WebSocketStatus.GOING_AWAY); + _close(WebSocketStatus.GOING_AWAY); }); }); } @@ -858,16 +873,24 @@ Future get done => _sink.done; Future close([int code, String reason]) { - if (!_writeClosed) { - if (_isReservedStatusCode(code)) { - throw new WebSocketException("Reserved status code $code"); - } + if (_isReservedStatusCode(code)) { + throw new WebSocketException("Reserved status code $code"); + } + if (_outCloseCode == null) { _outCloseCode = code; _outCloseReason = reason; - _writeClosed = true; } - if (!(_sink as _StreamSinkImpl)._isBound) _sink.close(); - return _sink.done; + return _sink.close(); + } + + void _close([int code, String reason]) { + if (_writeClosed) return; + if (_outCloseCode == null) { + _outCloseCode = code; + _outCloseReason = reason; + } + _writeClosed = true; + _consumer.closeSocket(); } static bool _isReservedStatusCode(int code) {
diff --git a/sdk/lib/js/dart2js/js_dart2js.dart b/sdk/lib/js/dart2js/js_dart2js.dart index 7f806b7..64b4af0 100644 --- a/sdk/lib/js/dart2js/js_dart2js.dart +++ b/sdk/lib/js/dart2js/js_dart2js.dart
@@ -5,11 +5,9 @@ library dart.js; import 'dart:_foreign_helper' show JS; -import 'dart:_js_helper' show convertDartClosureToJS; +import 'dart:_js_helper' show Primitives, convertDartClosureToJS; -JsObject get context { - return new JsObject._fromJs(JS('=Object', 'window')); -} +final JsObject context = new JsObject._fromJs(Primitives.computeGlobalThis()); JsObject jsify(dynamic data) => data == null ? null : new JsObject._json(data);
diff --git a/sdk/lib/js/dartium/js_dartium.dart b/sdk/lib/js/dartium/js_dartium.dart index 2ec2c0e..a0c48ea 100644 --- a/sdk/lib/js/dartium/js_dartium.dart +++ b/sdk/lib/js/dartium/js_dartium.dart
@@ -76,15 +76,21 @@ SendPortSync _jsPortDeleteProperty = window.lookupPort('dart-js-delete-property'); SendPortSync _jsPortConvert = window.lookupPort('dart-js-convert'); + +JsObject _context; + /** * Returns a proxy to the global JavaScript context for this page. */ JsObject get context { - var port = _jsPortSync; - if (port == null) { - return null; + if (_context == null) { + var port = _jsPortSync; + if (port == null) { + return null; + } + _context = _deserialize(_jsPortSync.callSync([])); } - return _deserialize(_jsPortSync.callSync([])); + return _context; } /**
diff --git a/sdk/lib/svg/dart2js/svg_dart2js.dart b/sdk/lib/svg/dart2js/svg_dart2js.dart index be59cd9..0f88099 100644 --- a/sdk/lib/svg/dart2js/svg_dart2js.dart +++ b/sdk/lib/svg/dart2js/svg_dart2js.dart
@@ -51,6 +51,12 @@ @DomName('SVGAElement.SVGAElement') @DocsEditable() factory AElement() => _SvgElementFactoryProvider.createSvgElement_tag("a"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + AElement.created() : super.created(); @DomName('SVGAElement.target') @DocsEditable() @@ -86,6 +92,12 @@ @DomName('SVGAltGlyphElement.SVGAltGlyphElement') @DocsEditable() factory AltGlyphElement() => _SvgElementFactoryProvider.createSvgElement_tag("altGlyph"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + AltGlyphElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => SvgElement.isTagSupported('altGlyph') && (new SvgElement.tag('altGlyph') is AltGlyphElement); @@ -176,6 +188,12 @@ @DomName('SVGAnimateElement.SVGAnimateElement') @DocsEditable() factory AnimateElement() => _SvgElementFactoryProvider.createSvgElement_tag("animate"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + AnimateElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => SvgElement.isTagSupported('animate') && (new SvgElement.tag('animate') is AnimateElement); @@ -198,6 +216,12 @@ @DomName('SVGAnimateMotionElement.SVGAnimateMotionElement') @DocsEditable() factory AnimateMotionElement() => _SvgElementFactoryProvider.createSvgElement_tag("animateMotion"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + AnimateMotionElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => SvgElement.isTagSupported('animateMotion') && (new SvgElement.tag('animateMotion') is AnimateMotionElement); @@ -220,6 +244,12 @@ @DomName('SVGAnimateTransformElement.SVGAnimateTransformElement') @DocsEditable() factory AnimateTransformElement() => _SvgElementFactoryProvider.createSvgElement_tag("animateTransform"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + AnimateTransformElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => SvgElement.isTagSupported('animateTransform') && (new SvgElement.tag('animateTransform') is AnimateTransformElement); @@ -455,6 +485,12 @@ @DomName('SVGAnimationElement.SVGAnimationElement') @DocsEditable() factory AnimationElement() => _SvgElementFactoryProvider.createSvgElement_tag("animation"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + AnimationElement.created() : super.created(); @DomName('SVGAnimationElement.targetElement') @DocsEditable() @@ -527,6 +563,12 @@ @DomName('SVGCircleElement.SVGCircleElement') @DocsEditable() factory CircleElement() => _SvgElementFactoryProvider.createSvgElement_tag("circle"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + CircleElement.created() : super.created(); @DomName('SVGCircleElement.cx') @DocsEditable() @@ -561,6 +603,12 @@ @DomName('SVGClipPathElement.SVGClipPathElement') @DocsEditable() factory ClipPathElement() => _SvgElementFactoryProvider.createSvgElement_tag("clipPath"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + ClipPathElement.created() : super.created(); @DomName('SVGClipPathElement.clipPathUnits') @DocsEditable() @@ -587,6 +635,12 @@ @DomName('SVGDefsElement.SVGDefsElement') @DocsEditable() factory DefsElement() => _SvgElementFactoryProvider.createSvgElement_tag("defs"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + DefsElement.created() : super.created(); // From SVGExternalResourcesRequired @@ -609,6 +663,12 @@ @DomName('SVGDescElement.SVGDescElement') @DocsEditable() factory DescElement() => _SvgElementFactoryProvider.createSvgElement_tag("desc"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + DescElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -1015,6 +1075,12 @@ @DomName('SVGEllipseElement.SVGEllipseElement') @DocsEditable() factory EllipseElement() => _SvgElementFactoryProvider.createSvgElement_tag("ellipse"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + EllipseElement.created() : super.created(); @DomName('SVGEllipseElement.cx') @DocsEditable() @@ -1072,6 +1138,12 @@ @DomName('SVGFEBlendElement.SVGFEBlendElement') @DocsEditable() factory FEBlendElement() => _SvgElementFactoryProvider.createSvgElement_tag("feBlend"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FEBlendElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => SvgElement.isTagSupported('feBlend') && (new SvgElement.tag('feBlend') is FEBlendElement); @@ -1153,6 +1225,12 @@ @DomName('SVGFEColorMatrixElement.SVGFEColorMatrixElement') @DocsEditable() factory FEColorMatrixElement() => _SvgElementFactoryProvider.createSvgElement_tag("feColorMatrix"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FEColorMatrixElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => SvgElement.isTagSupported('feColorMatrix') && (new SvgElement.tag('feColorMatrix') is FEColorMatrixElement); @@ -1230,6 +1308,12 @@ @DomName('SVGFEComponentTransferElement.SVGFEComponentTransferElement') @DocsEditable() factory FEComponentTransferElement() => _SvgElementFactoryProvider.createSvgElement_tag("feComponentTransfer"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FEComponentTransferElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => SvgElement.isTagSupported('feComponentTransfer') && (new SvgElement.tag('feComponentTransfer') is FEComponentTransferElement); @@ -1271,6 +1355,12 @@ class FECompositeElement extends SvgElement implements FilterPrimitiveStandardAttributes native "SVGFECompositeElement" { // To suppress missing implicit constructor warnings. factory FECompositeElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FECompositeElement.created() : super.created(); @DomName('SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_ARITHMETIC') @DocsEditable() @@ -1369,6 +1459,12 @@ @DomName('SVGFEConvolveMatrixElement.SVGFEConvolveMatrixElement') @DocsEditable() factory FEConvolveMatrixElement() => _SvgElementFactoryProvider.createSvgElement_tag("feConvolveMatrix"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FEConvolveMatrixElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => SvgElement.isTagSupported('feConvolveMatrix') && (new SvgElement.tag('feConvolveMatrix') is FEConvolveMatrixElement); @@ -1478,6 +1574,12 @@ @DomName('SVGFEDiffuseLightingElement.SVGFEDiffuseLightingElement') @DocsEditable() factory FEDiffuseLightingElement() => _SvgElementFactoryProvider.createSvgElement_tag("feDiffuseLighting"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FEDiffuseLightingElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => SvgElement.isTagSupported('feDiffuseLighting') && (new SvgElement.tag('feDiffuseLighting') is FEDiffuseLightingElement); @@ -1543,6 +1645,12 @@ @DomName('SVGFEDisplacementMapElement.SVGFEDisplacementMapElement') @DocsEditable() factory FEDisplacementMapElement() => _SvgElementFactoryProvider.createSvgElement_tag("feDisplacementMap"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FEDisplacementMapElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => SvgElement.isTagSupported('feDisplacementMap') && (new SvgElement.tag('feDisplacementMap') is FEDisplacementMapElement); @@ -1628,6 +1736,12 @@ @DomName('SVGFEDistantLightElement.SVGFEDistantLightElement') @DocsEditable() factory FEDistantLightElement() => _SvgElementFactoryProvider.createSvgElement_tag("feDistantLight"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FEDistantLightElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => SvgElement.isTagSupported('feDistantLight') && (new SvgElement.tag('feDistantLight') is FEDistantLightElement); @@ -1659,6 +1773,12 @@ @DomName('SVGFEFloodElement.SVGFEFloodElement') @DocsEditable() factory FEFloodElement() => _SvgElementFactoryProvider.createSvgElement_tag("feFlood"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FEFloodElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => SvgElement.isTagSupported('feFlood') && (new SvgElement.tag('feFlood') is FEFloodElement); @@ -1704,6 +1824,12 @@ @DomName('SVGFEFuncAElement.SVGFEFuncAElement') @DocsEditable() factory FEFuncAElement() => _SvgElementFactoryProvider.createSvgElement_tag("feFuncA"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FEFuncAElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => SvgElement.isTagSupported('feFuncA') && (new SvgElement.tag('feFuncA') is FEFuncAElement); @@ -1727,6 +1853,12 @@ @DomName('SVGFEFuncBElement.SVGFEFuncBElement') @DocsEditable() factory FEFuncBElement() => _SvgElementFactoryProvider.createSvgElement_tag("feFuncB"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FEFuncBElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => SvgElement.isTagSupported('feFuncB') && (new SvgElement.tag('feFuncB') is FEFuncBElement); @@ -1750,6 +1882,12 @@ @DomName('SVGFEFuncGElement.SVGFEFuncGElement') @DocsEditable() factory FEFuncGElement() => _SvgElementFactoryProvider.createSvgElement_tag("feFuncG"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FEFuncGElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => SvgElement.isTagSupported('feFuncG') && (new SvgElement.tag('feFuncG') is FEFuncGElement); @@ -1773,6 +1911,12 @@ @DomName('SVGFEFuncRElement.SVGFEFuncRElement') @DocsEditable() factory FEFuncRElement() => _SvgElementFactoryProvider.createSvgElement_tag("feFuncR"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FEFuncRElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => SvgElement.isTagSupported('feFuncR') && (new SvgElement.tag('feFuncR') is FEFuncRElement); @@ -1796,6 +1940,12 @@ @DomName('SVGFEGaussianBlurElement.SVGFEGaussianBlurElement') @DocsEditable() factory FEGaussianBlurElement() => _SvgElementFactoryProvider.createSvgElement_tag("feGaussianBlur"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FEGaussianBlurElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => SvgElement.isTagSupported('feGaussianBlur') && (new SvgElement.tag('feGaussianBlur') is FEGaussianBlurElement); @@ -1857,6 +2007,12 @@ @DomName('SVGFEImageElement.SVGFEImageElement') @DocsEditable() factory FEImageElement() => _SvgElementFactoryProvider.createSvgElement_tag("feImage"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FEImageElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => SvgElement.isTagSupported('feImage') && (new SvgElement.tag('feImage') is FEImageElement); @@ -1918,6 +2074,12 @@ @DomName('SVGFEMergeElement.SVGFEMergeElement') @DocsEditable() factory FEMergeElement() => _SvgElementFactoryProvider.createSvgElement_tag("feMerge"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FEMergeElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => SvgElement.isTagSupported('feMerge') && (new SvgElement.tag('feMerge') is FEMergeElement); @@ -1963,6 +2125,12 @@ @DomName('SVGFEMergeNodeElement.SVGFEMergeNodeElement') @DocsEditable() factory FEMergeNodeElement() => _SvgElementFactoryProvider.createSvgElement_tag("feMergeNode"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FEMergeNodeElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => SvgElement.isTagSupported('feMergeNode') && (new SvgElement.tag('feMergeNode') is FEMergeNodeElement); @@ -1986,6 +2154,12 @@ class FEMorphologyElement extends SvgElement implements FilterPrimitiveStandardAttributes native "SVGFEMorphologyElement" { // To suppress missing implicit constructor warnings. factory FEMorphologyElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FEMorphologyElement.created() : super.created(); @DomName('SVGFEMorphologyElement.SVG_MORPHOLOGY_OPERATOR_DILATE') @DocsEditable() @@ -2060,6 +2234,12 @@ @DomName('SVGFEOffsetElement.SVGFEOffsetElement') @DocsEditable() factory FEOffsetElement() => _SvgElementFactoryProvider.createSvgElement_tag("feOffset"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FEOffsetElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => SvgElement.isTagSupported('feOffset') && (new SvgElement.tag('feOffset') is FEOffsetElement); @@ -2117,6 +2297,12 @@ @DomName('SVGFEPointLightElement.SVGFEPointLightElement') @DocsEditable() factory FEPointLightElement() => _SvgElementFactoryProvider.createSvgElement_tag("fePointLight"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FEPointLightElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => SvgElement.isTagSupported('fePointLight') && (new SvgElement.tag('fePointLight') is FEPointLightElement); @@ -2152,6 +2338,12 @@ @DomName('SVGFESpecularLightingElement.SVGFESpecularLightingElement') @DocsEditable() factory FESpecularLightingElement() => _SvgElementFactoryProvider.createSvgElement_tag("feSpecularLighting"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FESpecularLightingElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => SvgElement.isTagSupported('feSpecularLighting') && (new SvgElement.tag('feSpecularLighting') is FESpecularLightingElement); @@ -2213,6 +2405,12 @@ @DomName('SVGFESpotLightElement.SVGFESpotLightElement') @DocsEditable() factory FESpotLightElement() => _SvgElementFactoryProvider.createSvgElement_tag("feSpotLight"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FESpotLightElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => SvgElement.isTagSupported('feSpotLight') && (new SvgElement.tag('feSpotLight') is FESpotLightElement); @@ -2268,6 +2466,12 @@ @DomName('SVGFETileElement.SVGFETileElement') @DocsEditable() factory FETileElement() => _SvgElementFactoryProvider.createSvgElement_tag("feTile"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FETileElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => SvgElement.isTagSupported('feTile') && (new SvgElement.tag('feTile') is FETileElement); @@ -2317,6 +2521,12 @@ @DomName('SVGFETurbulenceElement.SVGFETurbulenceElement') @DocsEditable() factory FETurbulenceElement() => _SvgElementFactoryProvider.createSvgElement_tag("feTurbulence"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FETurbulenceElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => SvgElement.isTagSupported('feTurbulence') && (new SvgElement.tag('feTurbulence') is FETurbulenceElement); @@ -2410,6 +2620,12 @@ @DomName('SVGFilterElement.SVGFilterElement') @DocsEditable() factory FilterElement() => _SvgElementFactoryProvider.createSvgElement_tag("filter"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FilterElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => SvgElement.isTagSupported('filter') && (new SvgElement.tag('filter') is FilterElement); @@ -2514,6 +2730,12 @@ @DomName('SVGForeignObjectElement.SVGForeignObjectElement') @DocsEditable() factory ForeignObjectElement() => _SvgElementFactoryProvider.createSvgElement_tag("foreignObject"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + ForeignObjectElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => SvgElement.isTagSupported('foreignObject') && (new SvgElement.tag('foreignObject') is ForeignObjectElement); @@ -2555,6 +2777,12 @@ @DomName('SVGGElement.SVGGElement') @DocsEditable() factory GElement() => _SvgElementFactoryProvider.createSvgElement_tag("g"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + GElement.created() : super.created(); // From SVGExternalResourcesRequired @@ -2573,6 +2801,12 @@ class GraphicsElement extends SvgElement implements Tests native "SVGGraphicsElement" { // To suppress missing implicit constructor warnings. factory GraphicsElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + GraphicsElement.created() : super.created(); @DomName('SVGGraphicsElement.farthestViewportElement') @DocsEditable() @@ -2648,6 +2882,12 @@ @DomName('SVGImageElement.SVGImageElement') @DocsEditable() factory ImageElement() => _SvgElementFactoryProvider.createSvgElement_tag("image"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + ImageElement.created() : super.created(); @DomName('SVGImageElement.height') @DocsEditable() @@ -2862,6 +3102,12 @@ @DomName('SVGLineElement.SVGLineElement') @DocsEditable() factory LineElement() => _SvgElementFactoryProvider.createSvgElement_tag("line"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + LineElement.created() : super.created(); @DomName('SVGLineElement.x1') @DocsEditable() @@ -2900,6 +3146,12 @@ @DomName('SVGLinearGradientElement.SVGLinearGradientElement') @DocsEditable() factory LinearGradientElement() => _SvgElementFactoryProvider.createSvgElement_tag("linearGradient"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + LinearGradientElement.created() : super.created(); @DomName('SVGLinearGradientElement.x1') @DocsEditable() @@ -2932,6 +3184,12 @@ @DomName('SVGMarkerElement.SVGMarkerElement') @DocsEditable() factory MarkerElement() => _SvgElementFactoryProvider.createSvgElement_tag("marker"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + MarkerElement.created() : super.created(); @DomName('SVGMarkerElement.SVG_MARKERUNITS_STROKEWIDTH') @DocsEditable() @@ -3024,6 +3282,12 @@ @DomName('SVGMaskElement.SVGMaskElement') @DocsEditable() factory MaskElement() => _SvgElementFactoryProvider.createSvgElement_tag("mask"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + MaskElement.created() : super.created(); @DomName('SVGMaskElement.height') @DocsEditable() @@ -3162,6 +3426,12 @@ class MetadataElement extends SvgElement native "SVGMetadataElement" { // To suppress missing implicit constructor warnings. factory MetadataElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + MetadataElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -3280,6 +3550,12 @@ @DomName('SVGPathElement.SVGPathElement') @DocsEditable() factory PathElement() => _SvgElementFactoryProvider.createSvgElement_tag("path"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + PathElement.created() : super.created(); @DomName('SVGPathElement.animatedNormalizedPathSegList') @DocsEditable() @@ -4075,6 +4351,12 @@ @DomName('SVGPatternElement.SVGPatternElement') @DocsEditable() factory PatternElement() => _SvgElementFactoryProvider.createSvgElement_tag("pattern"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + PatternElement.created() : super.created(); @DomName('SVGPatternElement.height') @DocsEditable() @@ -4223,6 +4505,12 @@ @DomName('SVGPolygonElement.SVGPolygonElement') @DocsEditable() factory PolygonElement() => _SvgElementFactoryProvider.createSvgElement_tag("polygon"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + PolygonElement.created() : super.created(); @DomName('SVGPolygonElement.animatedPoints') @DocsEditable() @@ -4253,6 +4541,12 @@ @DomName('SVGPolylineElement.SVGPolylineElement') @DocsEditable() factory PolylineElement() => _SvgElementFactoryProvider.createSvgElement_tag("polyline"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + PolylineElement.created() : super.created(); @DomName('SVGPolylineElement.animatedPoints') @DocsEditable() @@ -4357,6 +4651,12 @@ @DomName('SVGRadialGradientElement.SVGRadialGradientElement') @DocsEditable() factory RadialGradientElement() => _SvgElementFactoryProvider.createSvgElement_tag("radialGradient"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + RadialGradientElement.created() : super.created(); @DomName('SVGRadialGradientElement.cx') @DocsEditable() @@ -4423,6 +4723,12 @@ @DomName('SVGRectElement.SVGRectElement') @DocsEditable() factory RectElement() => _SvgElementFactoryProvider.createSvgElement_tag("rect"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + RectElement.created() : super.created(); @DomName('SVGRectElement.height') @DocsEditable() @@ -4503,6 +4809,12 @@ @DomName('SVGScriptElement.SVGScriptElement') @DocsEditable() factory ScriptElement() => _SvgElementFactoryProvider.createSvgElement_tag("script"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + ScriptElement.created() : super.created(); @DomName('SVGScriptElement.type') @DocsEditable() @@ -4538,6 +4850,12 @@ @DomName('SVGSetElement.SVGSetElement') @DocsEditable() factory SetElement() => _SvgElementFactoryProvider.createSvgElement_tag("set"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + SetElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => SvgElement.isTagSupported('set') && (new SvgElement.tag('set') is SetElement); @@ -4557,6 +4875,12 @@ @DomName('SVGStopElement.SVGStopElement') @DocsEditable() factory StopElement() => _SvgElementFactoryProvider.createSvgElement_tag("stop"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + StopElement.created() : super.created(); @JSName('offset') @DomName('SVGStopElement.offset') @@ -4667,6 +4991,12 @@ @DomName('SVGStyleElement.SVGStyleElement') @DocsEditable() factory StyleElement() => _SvgElementFactoryProvider.createSvgElement_tag("style"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + StyleElement.created() : super.created(); @DomName('SVGStyleElement.disabled') @DocsEditable() @@ -4856,6 +5186,12 @@ } // To suppress missing implicit constructor warnings. factory SvgElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + SvgElement.created() : super.created(); // Shadowing definition. AnimatedString get _svgClassName => JS("AnimatedString", "#.className", this); @@ -4904,6 +5240,12 @@ // To suppress missing implicit constructor warnings. factory SvgSvgElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + SvgSvgElement.created() : super.created(); @DomName('SVGSVGElement.contentScriptType') @DocsEditable() @@ -5107,6 +5449,12 @@ @DomName('SVGSwitchElement.SVGSwitchElement') @DocsEditable() factory SwitchElement() => _SvgElementFactoryProvider.createSvgElement_tag("switch"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + SwitchElement.created() : super.created(); // From SVGExternalResourcesRequired @@ -5129,6 +5477,12 @@ @DomName('SVGSymbolElement.SVGSymbolElement') @DocsEditable() factory SymbolElement() => _SvgElementFactoryProvider.createSvgElement_tag("symbol"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + SymbolElement.created() : super.created(); // From SVGExternalResourcesRequired @@ -5161,6 +5515,12 @@ @DomName('SVGTSpanElement.SVGTSpanElement') @DocsEditable() factory TSpanElement() => _SvgElementFactoryProvider.createSvgElement_tag("tspan"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + TSpanElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -5191,6 +5551,12 @@ class TextContentElement extends GraphicsElement implements ExternalResourcesRequired native "SVGTextContentElement" { // To suppress missing implicit constructor warnings. factory TextContentElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + TextContentElement.created() : super.created(); @DomName('SVGTextContentElement.LENGTHADJUST_SPACING') @DocsEditable() @@ -5269,6 +5635,12 @@ @DomName('SVGTextElement.SVGTextElement') @DocsEditable() factory TextElement() => _SvgElementFactoryProvider.createSvgElement_tag("text"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + TextElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -5281,6 +5653,12 @@ class TextPathElement extends TextContentElement implements UriReference native "SVGTextPathElement" { // To suppress missing implicit constructor warnings. factory TextPathElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + TextPathElement.created() : super.created(); @DomName('SVGTextPathElement.TEXTPATH_METHODTYPE_ALIGN') @DocsEditable() @@ -5335,6 +5713,12 @@ class TextPositioningElement extends TextContentElement native "SVGTextPositioningElement" { // To suppress missing implicit constructor warnings. factory TextPositioningElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + TextPositioningElement.created() : super.created(); @DomName('SVGTextPositioningElement.dx') @DocsEditable() @@ -5371,6 +5755,12 @@ @DomName('SVGTitleElement.SVGTitleElement') @DocsEditable() factory TitleElement() => _SvgElementFactoryProvider.createSvgElement_tag("title"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + TitleElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -5592,6 +5982,12 @@ @DomName('SVGUseElement.SVGUseElement') @DocsEditable() factory UseElement() => _SvgElementFactoryProvider.createSvgElement_tag("use"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + UseElement.created() : super.created(); @DomName('SVGUseElement.animatedInstanceRoot') @DocsEditable() @@ -5662,6 +6058,12 @@ @DomName('SVGViewElement.SVGViewElement') @DocsEditable() factory ViewElement() => _SvgElementFactoryProvider.createSvgElement_tag("view"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + ViewElement.created() : super.created(); @DomName('SVGViewElement.viewTarget') @DocsEditable() @@ -5869,6 +6271,12 @@ class _GradientElement extends SvgElement implements UriReference, ExternalResourcesRequired native "SVGGradientElement" { // To suppress missing implicit constructor warnings. factory _GradientElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _GradientElement.created() : super.created(); @DomName('SVGGradientElement.SVG_SPREADMETHOD_PAD') @DocsEditable() @@ -5921,6 +6329,12 @@ abstract class _SVGAltGlyphDefElement extends SvgElement native "SVGAltGlyphDefElement" { // To suppress missing implicit constructor warnings. factory _SVGAltGlyphDefElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _SVGAltGlyphDefElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -5933,6 +6347,12 @@ abstract class _SVGAltGlyphItemElement extends SvgElement native "SVGAltGlyphItemElement" { // To suppress missing implicit constructor warnings. factory _SVGAltGlyphItemElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _SVGAltGlyphItemElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -5945,6 +6365,12 @@ abstract class _SVGAnimateColorElement extends AnimationElement native "SVGAnimateColorElement" { // To suppress missing implicit constructor warnings. factory _SVGAnimateColorElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _SVGAnimateColorElement.created() : super.created(); } // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -5970,6 +6396,12 @@ abstract class _SVGComponentTransferFunctionElement extends SvgElement native "SVGComponentTransferFunctionElement" { // To suppress missing implicit constructor warnings. factory _SVGComponentTransferFunctionElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _SVGComponentTransferFunctionElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -5986,6 +6418,12 @@ @DomName('SVGCursorElement.SVGCursorElement') @DocsEditable() factory _SVGCursorElement() => _SvgElementFactoryProvider.createSvgElement_tag("cursor"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _SVGCursorElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => SvgElement.isTagSupported('cursor') && (new SvgElement.tag('cursor') is _SVGCursorElement); @@ -6007,6 +6445,12 @@ abstract class _SVGFEDropShadowElement extends SvgElement implements FilterPrimitiveStandardAttributes native "SVGFEDropShadowElement" { // To suppress missing implicit constructor warnings. factory _SVGFEDropShadowElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _SVGFEDropShadowElement.created() : super.created(); // From SVGFilterPrimitiveStandardAttributes } @@ -6021,6 +6465,12 @@ abstract class _SVGFontElement extends SvgElement native "SVGFontElement" { // To suppress missing implicit constructor warnings. factory _SVGFontElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _SVGFontElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -6033,6 +6483,12 @@ abstract class _SVGFontFaceElement extends SvgElement native "SVGFontFaceElement" { // To suppress missing implicit constructor warnings. factory _SVGFontFaceElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _SVGFontFaceElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -6045,6 +6501,12 @@ abstract class _SVGFontFaceFormatElement extends SvgElement native "SVGFontFaceFormatElement" { // To suppress missing implicit constructor warnings. factory _SVGFontFaceFormatElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _SVGFontFaceFormatElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -6057,6 +6519,12 @@ abstract class _SVGFontFaceNameElement extends SvgElement native "SVGFontFaceNameElement" { // To suppress missing implicit constructor warnings. factory _SVGFontFaceNameElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _SVGFontFaceNameElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -6069,6 +6537,12 @@ abstract class _SVGFontFaceSrcElement extends SvgElement native "SVGFontFaceSrcElement" { // To suppress missing implicit constructor warnings. factory _SVGFontFaceSrcElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _SVGFontFaceSrcElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -6081,6 +6555,12 @@ abstract class _SVGFontFaceUriElement extends SvgElement native "SVGFontFaceUriElement" { // To suppress missing implicit constructor warnings. factory _SVGFontFaceUriElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _SVGFontFaceUriElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -6097,6 +6577,12 @@ @DomName('SVGGlyphElement.SVGGlyphElement') @DocsEditable() factory _SVGGlyphElement() => _SvgElementFactoryProvider.createSvgElement_tag("glyph"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _SVGGlyphElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -6109,6 +6595,12 @@ abstract class _SVGGlyphRefElement extends SvgElement implements UriReference native "SVGGlyphRefElement" { // To suppress missing implicit constructor warnings. factory _SVGGlyphRefElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _SVGGlyphRefElement.created() : super.created(); // From SVGURIReference } @@ -6127,6 +6619,12 @@ @DomName('SVGHKernElement.SVGHKernElement') @DocsEditable() factory _SVGHKernElement() => _SvgElementFactoryProvider.createSvgElement_tag("hkern"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _SVGHKernElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -6142,6 +6640,12 @@ @DomName('SVGMPathElement.SVGMPathElement') @DocsEditable() factory _SVGMPathElement() => _SvgElementFactoryProvider.createSvgElement_tag("mpath"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _SVGMPathElement.created() : super.created(); // From SVGExternalResourcesRequired @@ -6158,6 +6662,12 @@ abstract class _SVGMissingGlyphElement extends SvgElement native "SVGMissingGlyphElement" { // To suppress missing implicit constructor warnings. factory _SVGMissingGlyphElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _SVGMissingGlyphElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file // for details. All rights reserved. Use of this source code is governed by a @@ -6186,6 +6696,12 @@ @DomName('SVGTRefElement.SVGTRefElement') @DocsEditable() factory _SVGTRefElement() => _SvgElementFactoryProvider.createSvgElement_tag("tref"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _SVGTRefElement.created() : super.created(); // From SVGURIReference } @@ -6204,4 +6720,10 @@ @DomName('SVGVKernElement.SVGVKernElement') @DocsEditable() factory _SVGVKernElement() => _SvgElementFactoryProvider.createSvgElement_tag("vkern"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _SVGVKernElement.created() : super.created(); }
diff --git a/sdk/lib/svg/dartium/svg_dartium.dart b/sdk/lib/svg/dartium/svg_dartium.dart index 2201493..785f717 100644 --- a/sdk/lib/svg/dartium/svg_dartium.dart +++ b/sdk/lib/svg/dartium/svg_dartium.dart
@@ -42,6 +42,12 @@ @DomName('SVGAElement.SVGAElement') @DocsEditable() factory AElement() => _SvgElementFactoryProvider.createSvgElement_tag("a"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + AElement.created() : super.created(); @DomName('SVGAElement.target') @DocsEditable() @@ -76,6 +82,12 @@ @DomName('SVGAltGlyphElement.SVGAltGlyphElement') @DocsEditable() factory AltGlyphElement() => _SvgElementFactoryProvider.createSvgElement_tag("altGlyph"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + AltGlyphElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => true; @@ -190,6 +202,12 @@ @DomName('SVGAnimateElement.SVGAnimateElement') @DocsEditable() factory AnimateElement() => _SvgElementFactoryProvider.createSvgElement_tag("animate"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + AnimateElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => true; @@ -215,6 +233,12 @@ @DomName('SVGAnimateMotionElement.SVGAnimateMotionElement') @DocsEditable() factory AnimateMotionElement() => _SvgElementFactoryProvider.createSvgElement_tag("animateMotion"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + AnimateMotionElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => true; @@ -240,6 +264,12 @@ @DomName('SVGAnimateTransformElement.SVGAnimateTransformElement') @DocsEditable() factory AnimateTransformElement() => _SvgElementFactoryProvider.createSvgElement_tag("animateTransform"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + AnimateTransformElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => true; @@ -534,6 +564,12 @@ @DomName('SVGAnimationElement.SVGAnimationElement') @DocsEditable() factory AnimationElement() => _SvgElementFactoryProvider.createSvgElement_tag("animation"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + AnimationElement.created() : super.created(); @DomName('SVGAnimationElement.targetElement') @DocsEditable() @@ -605,6 +641,12 @@ @DomName('SVGCircleElement.SVGCircleElement') @DocsEditable() factory CircleElement() => _SvgElementFactoryProvider.createSvgElement_tag("circle"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + CircleElement.created() : super.created(); @DomName('SVGCircleElement.cx') @DocsEditable() @@ -640,6 +682,12 @@ @DomName('SVGClipPathElement.SVGClipPathElement') @DocsEditable() factory ClipPathElement() => _SvgElementFactoryProvider.createSvgElement_tag("clipPath"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + ClipPathElement.created() : super.created(); @DomName('SVGClipPathElement.clipPathUnits') @DocsEditable() @@ -667,6 +715,12 @@ @DomName('SVGDefsElement.SVGDefsElement') @DocsEditable() factory DefsElement() => _SvgElementFactoryProvider.createSvgElement_tag("defs"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + DefsElement.created() : super.created(); @DomName('SVGDefsElement.externalResourcesRequired') @DocsEditable() @@ -690,6 +744,12 @@ @DomName('SVGDescElement.SVGDescElement') @DocsEditable() factory DescElement() => _SvgElementFactoryProvider.createSvgElement_tag("desc"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + DescElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file @@ -1115,6 +1175,12 @@ @DomName('SVGEllipseElement.SVGEllipseElement') @DocsEditable() factory EllipseElement() => _SvgElementFactoryProvider.createSvgElement_tag("ellipse"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + EllipseElement.created() : super.created(); @DomName('SVGEllipseElement.cx') @DocsEditable() @@ -1178,6 +1244,12 @@ @DomName('SVGFEBlendElement.SVGFEBlendElement') @DocsEditable() factory FEBlendElement() => _SvgElementFactoryProvider.createSvgElement_tag("feBlend"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FEBlendElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => true; @@ -1260,6 +1332,12 @@ @DomName('SVGFEColorMatrixElement.SVGFEColorMatrixElement') @DocsEditable() factory FEColorMatrixElement() => _SvgElementFactoryProvider.createSvgElement_tag("feColorMatrix"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FEColorMatrixElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => true; @@ -1338,6 +1416,12 @@ @DomName('SVGFEComponentTransferElement.SVGFEComponentTransferElement') @DocsEditable() factory FEComponentTransferElement() => _SvgElementFactoryProvider.createSvgElement_tag("feComponentTransfer"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FEComponentTransferElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => true; @@ -1380,6 +1464,12 @@ class FECompositeElement extends SvgElement implements FilterPrimitiveStandardAttributes { // To suppress missing implicit constructor warnings. factory FECompositeElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FECompositeElement.created() : super.created(); @DomName('SVGFECompositeElement.SVG_FECOMPOSITE_OPERATOR_ARITHMETIC') @DocsEditable() @@ -1479,6 +1569,12 @@ @DomName('SVGFEConvolveMatrixElement.SVGFEConvolveMatrixElement') @DocsEditable() factory FEConvolveMatrixElement() => _SvgElementFactoryProvider.createSvgElement_tag("feConvolveMatrix"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FEConvolveMatrixElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => true; @@ -1589,6 +1685,12 @@ @DomName('SVGFEDiffuseLightingElement.SVGFEDiffuseLightingElement') @DocsEditable() factory FEDiffuseLightingElement() => _SvgElementFactoryProvider.createSvgElement_tag("feDiffuseLighting"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FEDiffuseLightingElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => true; @@ -1655,6 +1757,12 @@ @DomName('SVGFEDisplacementMapElement.SVGFEDisplacementMapElement') @DocsEditable() factory FEDisplacementMapElement() => _SvgElementFactoryProvider.createSvgElement_tag("feDisplacementMap"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FEDisplacementMapElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => true; @@ -1741,6 +1849,12 @@ @DomName('SVGFEDistantLightElement.SVGFEDistantLightElement') @DocsEditable() factory FEDistantLightElement() => _SvgElementFactoryProvider.createSvgElement_tag("feDistantLight"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FEDistantLightElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => true; @@ -1775,6 +1889,12 @@ @DomName('SVGFEFloodElement.SVGFEFloodElement') @DocsEditable() factory FEFloodElement() => _SvgElementFactoryProvider.createSvgElement_tag("feFlood"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FEFloodElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => true; @@ -1821,6 +1941,12 @@ @DomName('SVGFEFuncAElement.SVGFEFuncAElement') @DocsEditable() factory FEFuncAElement() => _SvgElementFactoryProvider.createSvgElement_tag("feFuncA"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FEFuncAElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => true; @@ -1847,6 +1973,12 @@ @DomName('SVGFEFuncBElement.SVGFEFuncBElement') @DocsEditable() factory FEFuncBElement() => _SvgElementFactoryProvider.createSvgElement_tag("feFuncB"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FEFuncBElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => true; @@ -1873,6 +2005,12 @@ @DomName('SVGFEFuncGElement.SVGFEFuncGElement') @DocsEditable() factory FEFuncGElement() => _SvgElementFactoryProvider.createSvgElement_tag("feFuncG"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FEFuncGElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => true; @@ -1899,6 +2037,12 @@ @DomName('SVGFEFuncRElement.SVGFEFuncRElement') @DocsEditable() factory FEFuncRElement() => _SvgElementFactoryProvider.createSvgElement_tag("feFuncR"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FEFuncRElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => true; @@ -1925,6 +2069,12 @@ @DomName('SVGFEGaussianBlurElement.SVGFEGaussianBlurElement') @DocsEditable() factory FEGaussianBlurElement() => _SvgElementFactoryProvider.createSvgElement_tag("feGaussianBlur"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FEGaussianBlurElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => true; @@ -1987,6 +2137,12 @@ @DomName('SVGFEImageElement.SVGFEImageElement') @DocsEditable() factory FEImageElement() => _SvgElementFactoryProvider.createSvgElement_tag("feImage"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FEImageElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => true; @@ -2045,6 +2201,12 @@ @DomName('SVGFEMergeElement.SVGFEMergeElement') @DocsEditable() factory FEMergeElement() => _SvgElementFactoryProvider.createSvgElement_tag("feMerge"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FEMergeElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => true; @@ -2091,6 +2253,12 @@ @DomName('SVGFEMergeNodeElement.SVGFEMergeNodeElement') @DocsEditable() factory FEMergeNodeElement() => _SvgElementFactoryProvider.createSvgElement_tag("feMergeNode"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FEMergeNodeElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => true; @@ -2117,6 +2285,12 @@ class FEMorphologyElement extends SvgElement implements FilterPrimitiveStandardAttributes { // To suppress missing implicit constructor warnings. factory FEMorphologyElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FEMorphologyElement.created() : super.created(); @DomName('SVGFEMorphologyElement.SVG_MORPHOLOGY_OPERATOR_DILATE') @DocsEditable() @@ -2192,6 +2366,12 @@ @DomName('SVGFEOffsetElement.SVGFEOffsetElement') @DocsEditable() factory FEOffsetElement() => _SvgElementFactoryProvider.createSvgElement_tag("feOffset"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FEOffsetElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => true; @@ -2250,6 +2430,12 @@ @DomName('SVGFEPointLightElement.SVGFEPointLightElement') @DocsEditable() factory FEPointLightElement() => _SvgElementFactoryProvider.createSvgElement_tag("fePointLight"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FEPointLightElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => true; @@ -2288,6 +2474,12 @@ @DomName('SVGFESpecularLightingElement.SVGFESpecularLightingElement') @DocsEditable() factory FESpecularLightingElement() => _SvgElementFactoryProvider.createSvgElement_tag("feSpecularLighting"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FESpecularLightingElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => true; @@ -2350,6 +2542,12 @@ @DomName('SVGFESpotLightElement.SVGFESpotLightElement') @DocsEditable() factory FESpotLightElement() => _SvgElementFactoryProvider.createSvgElement_tag("feSpotLight"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FESpotLightElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => true; @@ -2408,6 +2606,12 @@ @DomName('SVGFETileElement.SVGFETileElement') @DocsEditable() factory FETileElement() => _SvgElementFactoryProvider.createSvgElement_tag("feTile"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FETileElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => true; @@ -2458,6 +2662,12 @@ @DomName('SVGFETurbulenceElement.SVGFETurbulenceElement') @DocsEditable() factory FETurbulenceElement() => _SvgElementFactoryProvider.createSvgElement_tag("feTurbulence"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FETurbulenceElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => true; @@ -2552,6 +2762,12 @@ @DomName('SVGFilterElement.SVGFilterElement') @DocsEditable() factory FilterElement() => _SvgElementFactoryProvider.createSvgElement_tag("filter"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + FilterElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => true; @@ -2675,6 +2891,12 @@ @DomName('SVGForeignObjectElement.SVGForeignObjectElement') @DocsEditable() factory ForeignObjectElement() => _SvgElementFactoryProvider.createSvgElement_tag("foreignObject"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + ForeignObjectElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => true; @@ -2717,6 +2939,12 @@ @DomName('SVGGElement.SVGGElement') @DocsEditable() factory GElement() => _SvgElementFactoryProvider.createSvgElement_tag("g"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + GElement.created() : super.created(); @DomName('SVGGElement.externalResourcesRequired') @DocsEditable() @@ -2736,6 +2964,12 @@ class GraphicsElement extends SvgElement implements Tests { // To suppress missing implicit constructor warnings. factory GraphicsElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + GraphicsElement.created() : super.created(); @DomName('SVGGraphicsElement.farthestViewportElement') @DocsEditable() @@ -2810,6 +3044,12 @@ @DomName('SVGImageElement.SVGImageElement') @DocsEditable() factory ImageElement() => _SvgElementFactoryProvider.createSvgElement_tag("image"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + ImageElement.created() : super.created(); @DomName('SVGImageElement.height') @DocsEditable() @@ -3041,6 +3281,12 @@ @DomName('SVGLineElement.SVGLineElement') @DocsEditable() factory LineElement() => _SvgElementFactoryProvider.createSvgElement_tag("line"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + LineElement.created() : super.created(); @DomName('SVGLineElement.x1') @DocsEditable() @@ -3080,6 +3326,12 @@ @DomName('SVGLinearGradientElement.SVGLinearGradientElement') @DocsEditable() factory LinearGradientElement() => _SvgElementFactoryProvider.createSvgElement_tag("linearGradient"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + LinearGradientElement.created() : super.created(); @DomName('SVGLinearGradientElement.x1') @DocsEditable() @@ -3115,6 +3367,12 @@ @DomName('SVGMarkerElement.SVGMarkerElement') @DocsEditable() factory MarkerElement() => _SvgElementFactoryProvider.createSvgElement_tag("marker"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + MarkerElement.created() : super.created(); @DomName('SVGMarkerElement.SVG_MARKERUNITS_STROKEWIDTH') @DocsEditable() @@ -3206,6 +3464,12 @@ @DomName('SVGMaskElement.SVGMaskElement') @DocsEditable() factory MaskElement() => _SvgElementFactoryProvider.createSvgElement_tag("mask"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + MaskElement.created() : super.created(); @DomName('SVGMaskElement.height') @DocsEditable() @@ -3370,6 +3634,12 @@ class MetadataElement extends SvgElement { // To suppress missing implicit constructor warnings. factory MetadataElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + MetadataElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file @@ -3501,6 +3771,12 @@ @DomName('SVGPathElement.SVGPathElement') @DocsEditable() factory PathElement() => _SvgElementFactoryProvider.createSvgElement_tag("path"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + PathElement.created() : super.created(); @DomName('SVGPathElement.animatedNormalizedPathSegList') @DocsEditable() @@ -4573,6 +4849,12 @@ @DomName('SVGPatternElement.SVGPatternElement') @DocsEditable() factory PatternElement() => _SvgElementFactoryProvider.createSvgElement_tag("pattern"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + PatternElement.created() : super.created(); @DomName('SVGPatternElement.height') @DocsEditable() @@ -4730,6 +5012,12 @@ @DomName('SVGPolygonElement.SVGPolygonElement') @DocsEditable() factory PolygonElement() => _SvgElementFactoryProvider.createSvgElement_tag("polygon"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + PolygonElement.created() : super.created(); @DomName('SVGPolygonElement.animatedPoints') @DocsEditable() @@ -4761,6 +5049,12 @@ @DomName('SVGPolylineElement.SVGPolylineElement') @DocsEditable() factory PolylineElement() => _SvgElementFactoryProvider.createSvgElement_tag("polyline"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + PolylineElement.created() : super.created(); @DomName('SVGPolylineElement.animatedPoints') @DocsEditable() @@ -4877,6 +5171,12 @@ @DomName('SVGRadialGradientElement.SVGRadialGradientElement') @DocsEditable() factory RadialGradientElement() => _SvgElementFactoryProvider.createSvgElement_tag("radialGradient"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + RadialGradientElement.created() : super.created(); @DomName('SVGRadialGradientElement.cx') @DocsEditable() @@ -4965,6 +5265,12 @@ @DomName('SVGRectElement.SVGRectElement') @DocsEditable() factory RectElement() => _SvgElementFactoryProvider.createSvgElement_tag("rect"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + RectElement.created() : super.created(); @DomName('SVGRectElement.height') @DocsEditable() @@ -5049,6 +5355,12 @@ @DomName('SVGScriptElement.SVGScriptElement') @DocsEditable() factory ScriptElement() => _SvgElementFactoryProvider.createSvgElement_tag("script"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + ScriptElement.created() : super.created(); @DomName('SVGScriptElement.type') @DocsEditable() @@ -5087,6 +5399,12 @@ @DomName('SVGSetElement.SVGSetElement') @DocsEditable() factory SetElement() => _SvgElementFactoryProvider.createSvgElement_tag("set"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + SetElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => true; @@ -5109,6 +5427,12 @@ @DomName('SVGStopElement.SVGStopElement') @DocsEditable() factory StopElement() => _SvgElementFactoryProvider.createSvgElement_tag("stop"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + StopElement.created() : super.created(); @DomName('SVGStopElement.offset') @DocsEditable() @@ -5224,6 +5548,12 @@ @DomName('SVGStyleElement.SVGStyleElement') @DocsEditable() factory StyleElement() => _SvgElementFactoryProvider.createSvgElement_tag("style"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + StyleElement.created() : super.created(); @DomName('SVGStyleElement.disabled') @DocsEditable() @@ -5434,6 +5764,12 @@ } // To suppress missing implicit constructor warnings. factory SvgElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + SvgElement.created() : super.created(); @DomName('SVGElement.className') @DocsEditable() @@ -5499,6 +5835,12 @@ // To suppress missing implicit constructor warnings. factory SvgSvgElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + SvgSvgElement.created() : super.created(); @DomName('SVGSVGElement.contentScriptType') @DocsEditable() @@ -5702,6 +6044,12 @@ @DomName('SVGSwitchElement.SVGSwitchElement') @DocsEditable() factory SwitchElement() => _SvgElementFactoryProvider.createSvgElement_tag("switch"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + SwitchElement.created() : super.created(); @DomName('SVGSwitchElement.externalResourcesRequired') @DocsEditable() @@ -5725,6 +6073,12 @@ @DomName('SVGSymbolElement.SVGSymbolElement') @DocsEditable() factory SymbolElement() => _SvgElementFactoryProvider.createSvgElement_tag("symbol"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + SymbolElement.created() : super.created(); @DomName('SVGSymbolElement.externalResourcesRequired') @DocsEditable() @@ -5756,6 +6110,12 @@ @DomName('SVGTSpanElement.SVGTSpanElement') @DocsEditable() factory TSpanElement() => _SvgElementFactoryProvider.createSvgElement_tag("tspan"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + TSpanElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file @@ -5800,6 +6160,12 @@ class TextContentElement extends GraphicsElement implements ExternalResourcesRequired { // To suppress missing implicit constructor warnings. factory TextContentElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + TextContentElement.created() : super.created(); @DomName('SVGTextContentElement.LENGTHADJUST_SPACING') @DocsEditable() @@ -5879,6 +6245,12 @@ @DomName('SVGTextElement.SVGTextElement') @DocsEditable() factory TextElement() => _SvgElementFactoryProvider.createSvgElement_tag("text"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + TextElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file @@ -5894,6 +6266,12 @@ class TextPathElement extends TextContentElement implements UriReference { // To suppress missing implicit constructor warnings. factory TextPathElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + TextPathElement.created() : super.created(); @DomName('SVGTextPathElement.TEXTPATH_METHODTYPE_ALIGN') @DocsEditable() @@ -5949,6 +6327,12 @@ class TextPositioningElement extends TextContentElement { // To suppress missing implicit constructor warnings. factory TextPositioningElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + TextPositioningElement.created() : super.created(); @DomName('SVGTextPositioningElement.dx') @DocsEditable() @@ -5988,6 +6372,12 @@ @DomName('SVGTitleElement.SVGTitleElement') @DocsEditable() factory TitleElement() => _SvgElementFactoryProvider.createSvgElement_tag("title"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + TitleElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file @@ -6225,6 +6615,12 @@ @DomName('SVGUseElement.SVGUseElement') @DocsEditable() factory UseElement() => _SvgElementFactoryProvider.createSvgElement_tag("use"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + UseElement.created() : super.created(); @DomName('SVGUseElement.animatedInstanceRoot') @DocsEditable() @@ -6292,6 +6688,12 @@ @DomName('SVGViewElement.SVGViewElement') @DocsEditable() factory ViewElement() => _SvgElementFactoryProvider.createSvgElement_tag("view"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + ViewElement.created() : super.created(); @DomName('SVGViewElement.viewTarget') @DocsEditable() @@ -6522,6 +6924,12 @@ class _GradientElement extends SvgElement implements UriReference, ExternalResourcesRequired { // To suppress missing implicit constructor warnings. factory _GradientElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _GradientElement.created() : super.created(); @DomName('SVGGradientElement.SVG_SPREADMETHOD_PAD') @DocsEditable() @@ -6573,6 +6981,12 @@ abstract class _SVGAltGlyphDefElement extends SvgElement { // To suppress missing implicit constructor warnings. factory _SVGAltGlyphDefElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _SVGAltGlyphDefElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file @@ -6588,6 +7002,12 @@ abstract class _SVGAltGlyphItemElement extends SvgElement { // To suppress missing implicit constructor warnings. factory _SVGAltGlyphItemElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _SVGAltGlyphItemElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file @@ -6603,6 +7023,12 @@ abstract class _SVGAnimateColorElement extends AnimationElement { // To suppress missing implicit constructor warnings. factory _SVGAnimateColorElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _SVGAnimateColorElement.created() : super.created(); } // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file @@ -6631,6 +7057,12 @@ abstract class _SVGComponentTransferFunctionElement extends SvgElement { // To suppress missing implicit constructor warnings. factory _SVGComponentTransferFunctionElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _SVGComponentTransferFunctionElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file @@ -6650,6 +7082,12 @@ @DomName('SVGCursorElement.SVGCursorElement') @DocsEditable() factory _SVGCursorElement() => _SvgElementFactoryProvider.createSvgElement_tag("cursor"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _SVGCursorElement.created() : super.created(); /// Checks if this type is supported on the current platform. static bool get supported => true; @@ -6668,6 +7106,12 @@ abstract class _SVGFEDropShadowElement extends SvgElement implements FilterPrimitiveStandardAttributes { // To suppress missing implicit constructor warnings. factory _SVGFEDropShadowElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _SVGFEDropShadowElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file @@ -6683,6 +7127,12 @@ abstract class _SVGFontElement extends SvgElement { // To suppress missing implicit constructor warnings. factory _SVGFontElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _SVGFontElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file @@ -6698,6 +7148,12 @@ abstract class _SVGFontFaceElement extends SvgElement { // To suppress missing implicit constructor warnings. factory _SVGFontFaceElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _SVGFontFaceElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file @@ -6713,6 +7169,12 @@ abstract class _SVGFontFaceFormatElement extends SvgElement { // To suppress missing implicit constructor warnings. factory _SVGFontFaceFormatElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _SVGFontFaceFormatElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file @@ -6728,6 +7190,12 @@ abstract class _SVGFontFaceNameElement extends SvgElement { // To suppress missing implicit constructor warnings. factory _SVGFontFaceNameElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _SVGFontFaceNameElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file @@ -6743,6 +7211,12 @@ abstract class _SVGFontFaceSrcElement extends SvgElement { // To suppress missing implicit constructor warnings. factory _SVGFontFaceSrcElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _SVGFontFaceSrcElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file @@ -6758,6 +7232,12 @@ abstract class _SVGFontFaceUriElement extends SvgElement { // To suppress missing implicit constructor warnings. factory _SVGFontFaceUriElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _SVGFontFaceUriElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file @@ -6777,6 +7257,12 @@ @DomName('SVGGlyphElement.SVGGlyphElement') @DocsEditable() factory _SVGGlyphElement() => _SvgElementFactoryProvider.createSvgElement_tag("glyph"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _SVGGlyphElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file @@ -6792,6 +7278,12 @@ abstract class _SVGGlyphRefElement extends SvgElement implements UriReference { // To suppress missing implicit constructor warnings. factory _SVGGlyphRefElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _SVGGlyphRefElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file @@ -6811,6 +7303,12 @@ @DomName('SVGHKernElement.SVGHKernElement') @DocsEditable() factory _SVGHKernElement() => _SvgElementFactoryProvider.createSvgElement_tag("hkern"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _SVGHKernElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file @@ -6829,6 +7327,12 @@ @DomName('SVGMPathElement.SVGMPathElement') @DocsEditable() factory _SVGMPathElement() => _SvgElementFactoryProvider.createSvgElement_tag("mpath"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _SVGMPathElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file @@ -6844,6 +7348,12 @@ abstract class _SVGMissingGlyphElement extends SvgElement { // To suppress missing implicit constructor warnings. factory _SVGMissingGlyphElement._() { throw new UnsupportedError("Not supported"); } + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _SVGMissingGlyphElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file @@ -6878,6 +7388,12 @@ @DomName('SVGTRefElement.SVGTRefElement') @DocsEditable() factory _SVGTRefElement() => _SvgElementFactoryProvider.createSvgElement_tag("tref"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _SVGTRefElement.created() : super.created(); } // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file @@ -6897,5 +7413,11 @@ @DomName('SVGVKernElement.SVGVKernElement') @DocsEditable() factory _SVGVKernElement() => _SvgElementFactoryProvider.createSvgElement_tag("vkern"); + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + _SVGVKernElement.created() : super.created(); }
diff --git a/tests/co19/co19-analyzer.status b/tests/co19/co19-analyzer.status index c911f20..2859980 100644 --- a/tests/co19/co19-analyzer.status +++ b/tests/co19/co19-analyzer.status
@@ -3,25 +3,12 @@ # BSD-style license that can be found in the LICENSE file. [ $compiler == dartanalyzer ] -# not clear: g([var foo = foo + 10]) is parameter 'foo' in the scope of its own initialzer? -Language/06_Functions/2_Formal_Parameters_A02_t02: fail - -# not clear: null..[1](1)[2](2).foo(3, bar: 4)=5 - it seems that verything before =5 it not assignable -Language/07_Classes/6_Constructors/1_Generative_Constructors_A04_t15: fail - # invalid argument for constant constructor Language/07_Classes/6_Constructors/3_Constant_Constructors_A05_t02: fail -# TBF: _f is private, so does not collide -Language/07_Classes/1_Instance_Methods_A05_t08: fail - # TBD: should we check that argument for dynamic parameter of constant constructor is not compatible with operation that is performed with it? Language/12_Expressions/01_Constants_A16_t03: fail -# TBD: should we report _error_ when constant creation uses arguments with types incompatible with parameters? -Language/12_Expressions/12_Instance_Creation/2_Const_A09_t02: fail -Language/12_Expressions/12_Instance_Creation/2_Const_A09_t03: fail - # TBF: infinite look: class A {const A();final m = const A();} Language/12_Expressions/01_Constants_A17_t03: fail @@ -29,16 +16,6 @@ Language/15_Types/4_Interface_Types_A11_t01: Skip Language/15_Types/4_Interface_Types_A11_t02: Skip -# TBF: Hence, a static warning will not be issued if f has no declared return type, since the return type would be dynamic and dynamic may be assigned to void. -Language/13_Statements/11_Return_A07_t01: fail - -# TBF: typedef int func2(int); - "int is not a type" -Language/15_Types/6_Type_dynamic_A03_t01: fail -Language/15_Types/6_Type_dynamic_A04_t01: fail - - -LibTest/core/Uri/decodeQueryComponent_A02_t01: fail # co19 Issue 591 - # co19 issue #380, Strings class has been removed LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A04_t01: fail, OK @@ -49,9 +26,6 @@ LibTest/core/Set/isSubsetOf_A01_t02: fail, OK # co19 issue #425, Only static fields can be declared as 'const' -Language/05_Variables/05_Variables_A12_t01: fail, OK -Language/05_Variables/05_Variables_A12_t06: fail, OK -Language/05_Variables/05_Variables_A13_t01: fail, OK Language/07_Classes/07_Classes_A02_t11: fail, OK # co19 issue #442, undefined name "Expect" @@ -90,7 +64,6 @@ Language/12_Expressions/12_Instance_Creation_A01_t06: fail, OK # co19 issue #433 (wrongly closed), missing @static-warning annotation -Language/12_Expressions/15_Method_Invocation/3_Static_Invocation_A03_t01: fail, OK Language/12_Expressions/15_Method_Invocation/3_Static_Invocation_A03_t07: fail, OK # co19 issue #541: tests contain unqualified reference to static members defined in superclass @@ -100,20 +73,54 @@ # co19 issue #543: invocation of a non-function Language/12_Expressions/14_Function_Invocation/4_Function_Expression_Invocation_A03_t02: fail, OK -# co19 issue #562: malformed superclass -Language/14_Libraries_and_Scripts/1_Imports_A03_t27: fail, OK - -# co19 issue #563: implicitly named libraries are allowed -Language/14_Libraries_and_Scripts/2_Exports_A05_t01: fail, OK - # co19 issue #564: URI can be any number adjacent string literals Language/14_Libraries_and_Scripts/5_URIs_A01_t24: fail, OK Language/14_Libraries_and_Scripts/5_URIs_A01_t25: fail, OK -# co19 issue #596: initializing final variable at declaration and in constructor -Language/07_Classes/6_Constructors/1_Generative_Constructors_A12_t02: fail, OK -Language/07_Classes/6_Constructors/1_Generative_Constructors_A20_t02: fail, OK +# co19 issue #609, return type of "factory M" is M, so we need static warning for "return;". +Language/13_Statements/11_Return_A07_t01: fail, OK -# co19 issue #597: concrete class with abstract method -Language/07_Classes/4_Abstract_Instance_Members_A07_t08: fail, OK - +Language/09_Mixins/1_Mixin_Application_A01_t01: Fail # co19-roll r607: Please triage this failure +Language/12_Expressions/01_Constants_A22_t01: Fail # co19-roll r607: Please triage this failure +Language/12_Expressions/07_Maps_A13_t01: Fail # co19-roll r607: Please triage this failure +Language/12_Expressions/12_Instance_Creation_A01_t08: Fail # co19-roll r607: Please triage this failure +Language/12_Expressions/13_Property_Extraction_A02_t02: Fail # co19-roll r607: Please triage this failure +Language/12_Expressions/13_Property_Extraction_A04_t02: Fail # co19-roll r607: Please triage this failure +Language/12_Expressions/13_Property_Extraction_A04_t03: Fail # co19-roll r607: Please triage this failure +Language/12_Expressions/15_Method_Invocation/1_Ordinary_Invocation_A03_t03: Fail # co19-roll r607: Please triage this failure +Language/12_Expressions/15_Method_Invocation/1_Ordinary_Invocation_A03_t04: Fail # co19-roll r607: Please triage this failure +Language/12_Expressions/15_Method_Invocation/1_Ordinary_Invocation_A04_t04: Fail # co19-roll r607: Please triage this failure +Language/12_Expressions/15_Method_Invocation/4_Super_Invocation_A02_t05: Fail # co19-roll r607: Please triage this failure +Language/12_Expressions/16_Getter_Lookup_A02_t05: Fail # co19-roll r607: Please triage this failure +Language/12_Expressions/16_Getter_Lookup_A02_t06: Fail # co19-roll r607: Please triage this failure +Language/12_Expressions/17_Getter_Invocation_A07_t01: Fail # co19-roll r607: Please triage this failure +Language/12_Expressions/17_Getter_Invocation_A07_t02: Fail # co19-roll r607: Please triage this failure +Language/12_Expressions/18_Assignment_A01_t07: Fail # co19-roll r607: Please triage this failure +Language/12_Expressions/18_Assignment_A04_t09: Fail # co19-roll r607: Please triage this failure +Language/13_Statements/02_Expression_Statements_A01_t13: Fail # co19-roll r607: Please triage this failure +Language/15_Types/3_Type_Declarations/1_Typedef_A07_t08: Fail # co19-roll r607: Please triage this failure +Language/15_Types/3_Type_Declarations/1_Typedef_A07_t09: Fail # co19-roll r607: Please triage this failure +LibTest/collection/HasNextIterator/HasNextIterator_A01_t01: Fail # co19-roll r607: Please triage this failure +LibTest/collection/LinkedHashSet/LinkedHashSet.from_A01_t01: Fail # co19-roll r607: Please triage this failure +LibTest/collection/LinkedHashSet/LinkedHashSet_class_A01_t01: Fail # co19-roll r607: Please triage this failure +LibTest/collection/LinkedList/LinkedList_A01_t01: Fail # co19-roll r607: Please triage this failure +LibTest/collection/LinkedList/first_A01_t02: Fail # co19-roll r607: Please triage this failure +LibTest/collection/LinkedList/reduce_A01_t01: Fail # co19-roll r607: Please triage this failure +LibTest/core/Invocation/isAccessor_A01_t01: Fail # co19-roll r607: Please triage this failure +LibTest/core/Invocation/isAccessor_A01_t02: Fail # co19-roll r607: Please triage this failure +LibTest/core/Invocation/isGetter_A01_t01: Fail # co19-roll r607: Please triage this failure +LibTest/core/Invocation/isGetter_A01_t02: Fail # co19-roll r607: Please triage this failure +LibTest/core/Invocation/isMethod_A01_t01: Fail # co19-roll r607: Please triage this failure +LibTest/core/Invocation/isMethod_A01_t02: Fail # co19-roll r607: Please triage this failure +LibTest/core/Invocation/isSetter_A01_t01: Fail # co19-roll r607: Please triage this failure +LibTest/core/Invocation/isSetter_A01_t02: Fail # co19-roll r607: Please triage this failure +LibTest/core/Invocation/memberName_A01_t01: Fail # co19-roll r607: Please triage this failure +LibTest/core/Invocation/namedArguments_A01_t01: Fail # co19-roll r607: Please triage this failure +LibTest/core/Invocation/positionalArguments_A01_t01: Fail # co19-roll r607: Please triage this failure +LibTest/core/RuneIterator/currentAsString_A01_t02: Fail # co19-roll r607: Please triage this failure +LibTest/core/RuneIterator/current_A01_t02: Fail # co19-roll r607: Please triage this failure +LibTest/core/Runes/isEmpty_A01_t02: Fail # co19-roll r607: Please triage this failure +LibTest/core/Runes/isNotEmpty_A01_t02: Fail # co19-roll r607: Please triage this failure +LibTest/core/Runes/lastWhere_A02_t01: Fail # co19-roll r607: Please triage this failure +LibTest/core/Runes/length_A01_t02: Fail # co19-roll r607: Please triage this failure +LibTest/core/Symbol/Symbol_A01_t04: Fail # co19-roll r607: Please triage this failure
diff --git a/tests/co19/co19-analyzer2.status b/tests/co19/co19-analyzer2.status index 4a00538..cb338fd 100644 --- a/tests/co19/co19-analyzer2.status +++ b/tests/co19/co19-analyzer2.status
@@ -3,9 +3,6 @@ # BSD-style license that can be found in the LICENSE file. [ $compiler == dart2analyzer ] -# not clear: g([var foo = foo + 10]) is parameter 'foo' in the scope of its own initialzer? -Language/06_Functions/2_Formal_Parameters_A02_t02: fail - # not clear: null..[1](1)[2](2).foo(3, bar: 4)=5 - it seems that verything before =5 it not assignable Language/07_Classes/6_Constructors/1_Generative_Constructors_A04_t15: fail @@ -32,55 +29,18 @@ # TBF: Hence, a static warning will not be issued if f has no declared return type, since the return type would be dynamic and dynamic may be assigned to void. Language/13_Statements/11_Return_A07_t01: fail -# TBF: typedef int func2(int); - "int is not a type" -Language/15_Types/6_Type_dynamic_A03_t01: fail -Language/15_Types/6_Type_dynamic_A04_t01: fail - - -LibTest/core/Uri/decodeQueryComponent_A02_t01: fail # co19 Issue 591 - -# co19 issue #380, Strings class has been removed -LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A04_t01: fail, OK - -# co19 issue #400, collection library reorg -LibTest/core/String/concat_A01_t01: fail, OK -LibTest/core/String/concat_A02_t01: fail, OK -LibTest/core/Set/isSubsetOf_A01_t01: fail, OK -LibTest/core/Set/isSubsetOf_A01_t02: fail, OK - -# co19 issue #425, Only static fields can be declared as 'const' -Language/05_Variables/05_Variables_A12_t01: fail, OK -Language/05_Variables/05_Variables_A12_t06: fail, OK -Language/05_Variables/05_Variables_A13_t01: fail, OK -Language/07_Classes/07_Classes_A02_t11: fail, OK - # co19 issue #442, undefined name "Expect" Language/15_Types/4_Interface_Types_A08_t03: fail, OK # co19 issue #455, undeclared identifier is static warning Language/12_Expressions/14_Function_Invocation/3_Unqualified_Invocation_A01_t10: fail, OK -Language/13_Statements/04_Local_Function_Declaration_A02_t02: fail, OK Language/14_Libraries_and_Scripts/1_Imports_A02_t12: fail, OK Language/14_Libraries_and_Scripts/1_Imports_A02_t15: fail, OK -# co19 issue #513, rules for finals were loosened, contradiction in spec was fixed -Language/07_Classes/6_Constructors/1_Generative_Constructors_A21_t01: fail, OK - -# co19 issue #515, it is a compile-time error if there is more than one entity with the same name declared in the same scope -Language/07_Classes/3_Setters_A08_t03: fail, OK - -# co19 issue #593: Conditional expressions are now allowed as constant expressions -Language/12_Expressions/01_Constants_A15_t16: fail, OK - # co19 issue #438, Static variables are initialized lazily, need not be constants Language/12_Expressions/01_Constants_A16_t01: fail, OK Language/12_Expressions/01_Constants_A16_t02: fail, OK -# co19 issue #420, "throw" requires expression, "rethrow" should be used instead -Language/12_Expressions/08_Throw_A05_t01: fail, OK -Language/12_Expressions/08_Throw_A05_t02: fail, OK -Language/12_Expressions/08_Throw_A05_t03: fail, OK - # co19 issue #454 (wrongly closed) Language/12_Expressions/12_Instance_Creation/1_New_A01_t04: fail, OK @@ -90,7 +50,6 @@ Language/12_Expressions/12_Instance_Creation_A01_t06: fail, OK # co19 issue #433 (wrongly closed), missing @static-warning annotation -Language/12_Expressions/15_Method_Invocation/3_Static_Invocation_A03_t01: fail, OK Language/12_Expressions/15_Method_Invocation/3_Static_Invocation_A03_t07: fail, OK # co19 issue #541: tests contain unqualified reference to static members defined in superclass @@ -100,20 +59,51 @@ # co19 issue #543: invocation of a non-function Language/12_Expressions/14_Function_Invocation/4_Function_Expression_Invocation_A03_t02: fail, OK -# co19 issue #562: malformed superclass -Language/14_Libraries_and_Scripts/1_Imports_A03_t27: fail, OK - -# co19 issue #563: implicitly named libraries are allowed -Language/14_Libraries_and_Scripts/2_Exports_A05_t01: fail, OK - # co19 issue #564: URI can be any number adjacent string literals Language/14_Libraries_and_Scripts/5_URIs_A01_t24: fail, OK Language/14_Libraries_and_Scripts/5_URIs_A01_t25: fail, OK -# co19 issue #596: initializing final variable at declaration and in constructor -Language/07_Classes/6_Constructors/1_Generative_Constructors_A12_t02: fail, OK -Language/07_Classes/6_Constructors/1_Generative_Constructors_A20_t02: fail, OK - -# co19 issue #597: concrete class with abstract method -Language/07_Classes/4_Abstract_Instance_Members_A07_t08: fail, OK - +Language/09_Mixins/1_Mixin_Application_A01_t01: Fail # co19-roll r607: Please triage this failure +Language/12_Expressions/01_Constants_A22_t01: Fail # co19-roll r607: Please triage this failure +Language/12_Expressions/07_Maps_A13_t01: Fail # co19-roll r607: Please triage this failure +Language/12_Expressions/12_Instance_Creation_A01_t08: Fail # co19-roll r607: Please triage this failure +Language/12_Expressions/13_Property_Extraction_A02_t02: Fail # co19-roll r607: Please triage this failure +Language/12_Expressions/13_Property_Extraction_A04_t02: Fail # co19-roll r607: Please triage this failure +Language/12_Expressions/13_Property_Extraction_A04_t03: Fail # co19-roll r607: Please triage this failure +Language/12_Expressions/15_Method_Invocation/1_Ordinary_Invocation_A03_t03: Fail # co19-roll r607: Please triage this failure +Language/12_Expressions/15_Method_Invocation/1_Ordinary_Invocation_A03_t04: Fail # co19-roll r607: Please triage this failure +Language/12_Expressions/15_Method_Invocation/1_Ordinary_Invocation_A04_t04: Fail # co19-roll r607: Please triage this failure +Language/12_Expressions/15_Method_Invocation/4_Super_Invocation_A02_t05: Fail # co19-roll r607: Please triage this failure +Language/12_Expressions/16_Getter_Lookup_A02_t05: Fail # co19-roll r607: Please triage this failure +Language/12_Expressions/16_Getter_Lookup_A02_t06: Fail # co19-roll r607: Please triage this failure +Language/12_Expressions/17_Getter_Invocation_A07_t01: Fail # co19-roll r607: Please triage this failure +Language/12_Expressions/17_Getter_Invocation_A07_t02: Fail # co19-roll r607: Please triage this failure +Language/12_Expressions/18_Assignment_A01_t07: Fail # co19-roll r607: Please triage this failure +Language/12_Expressions/18_Assignment_A04_t09: Fail # co19-roll r607: Please triage this failure +Language/13_Statements/02_Expression_Statements_A01_t13: Fail # co19-roll r607: Please triage this failure +Language/15_Types/3_Type_Declarations/1_Typedef_A07_t08: Fail # co19-roll r607: Please triage this failure +Language/15_Types/3_Type_Declarations/1_Typedef_A07_t09: Fail # co19-roll r607: Please triage this failure +LibTest/collection/HasNextIterator/HasNextIterator_A01_t01: Fail # co19-roll r607: Please triage this failure +LibTest/collection/LinkedHashSet/LinkedHashSet.from_A01_t01: Fail # co19-roll r607: Please triage this failure +LibTest/collection/LinkedHashSet/LinkedHashSet_class_A01_t01: Fail # co19-roll r607: Please triage this failure +LibTest/collection/LinkedList/LinkedList_A01_t01: Fail # co19-roll r607: Please triage this failure +LibTest/collection/LinkedList/first_A01_t02: Fail # co19-roll r607: Please triage this failure +LibTest/collection/LinkedList/reduce_A01_t01: Fail # co19-roll r607: Please triage this failure +LibTest/core/Invocation/isAccessor_A01_t01: Fail # co19-roll r607: Please triage this failure +LibTest/core/Invocation/isAccessor_A01_t02: Fail # co19-roll r607: Please triage this failure +LibTest/core/Invocation/isGetter_A01_t01: Fail # co19-roll r607: Please triage this failure +LibTest/core/Invocation/isGetter_A01_t02: Fail # co19-roll r607: Please triage this failure +LibTest/core/Invocation/isMethod_A01_t01: Fail # co19-roll r607: Please triage this failure +LibTest/core/Invocation/isMethod_A01_t02: Fail # co19-roll r607: Please triage this failure +LibTest/core/Invocation/isSetter_A01_t01: Fail # co19-roll r607: Please triage this failure +LibTest/core/Invocation/isSetter_A01_t02: Fail # co19-roll r607: Please triage this failure +LibTest/core/Invocation/memberName_A01_t01: Fail # co19-roll r607: Please triage this failure +LibTest/core/Invocation/namedArguments_A01_t01: Fail # co19-roll r607: Please triage this failure +LibTest/core/Invocation/positionalArguments_A01_t01: Fail # co19-roll r607: Please triage this failure +LibTest/core/RuneIterator/currentAsString_A01_t02: Fail # co19-roll r607: Please triage this failure +LibTest/core/RuneIterator/current_A01_t02: Fail # co19-roll r607: Please triage this failure +LibTest/core/Runes/isEmpty_A01_t02: Fail # co19-roll r607: Please triage this failure +LibTest/core/Runes/isNotEmpty_A01_t02: Fail # co19-roll r607: Please triage this failure +LibTest/core/Runes/lastWhere_A02_t01: Fail # co19-roll r607: Please triage this failure +LibTest/core/Runes/length_A01_t02: Fail # co19-roll r607: Please triage this failure +LibTest/core/Symbol/Symbol_A01_t04: Fail # co19-roll r607: Please triage this failure
diff --git a/tests/co19/co19-co19.status b/tests/co19/co19-co19.status index 3bd647f..5dcead1 100644 --- a/tests/co19/co19-co19.status +++ b/tests/co19/co19-co19.status
@@ -10,13 +10,32 @@ [ $runtime == vm || $compiler == dart2dart || $compiler == dart2js ] +Language/12_Expressions/05_Strings_A02_t46: fail, pass, ok # co19 issue 612 +Language/12_Expressions/05_Strings_A02_t48: fail, pass, ok # co19 issue 612 Language/07_Classes/6_Constructors/1_Generative_Constructors_A12_t02: fail # co19-roll r587: Please triage this failure Language/07_Classes/6_Constructors/1_Generative_Constructors_A20_t02: fail # co19-roll r587: Please triage this failure -LibTest/core/Uri/decodeQueryComponent_A02_t01: fail # co19 Issue 591 LibTest/core/Uri/toFilePath_A01_t01: pass, fail, ok # co19 Issue 592 # Maybe we should wait until isolate library is sealed before triaging these. LibTest/isolate/isolate_api/spawnFunction_A04_t01: fail, timeout # co19-roll r546: Please triage this failure LibTest/isolate/isolate_api/streamSpawnFunction_A02_t01: fail, timeout # co19-roll r546: Please triage this failure +Language/15_Types/1_Static_Types_A03_t01: Fail # co19-roll r607: Please triage this failure + +Language/09_Mixins/1_Mixin_Application_A01_t01: CompileTimeError # co19-roll r607: Please triage this failure +LibTest/collection/LinkedHashSet/LinkedHashSet_class_A01_t01: CompileTimeError # co19-roll r607: Please triage this failure +LibTest/collection/LinkedList/first_A01_t02: CompileTimeError # co19-roll r607: Please triage this failure +Language/12_Expressions/18_Assignment_A01_t07: RuntimeError # co19-roll r607: Please triage this failure +Language/12_Expressions/18_Assignment_A04_t09: RuntimeError # co19-roll r607: Please triage this failure +Language/13_Statements/04_Local_Function_Declaration_A04_t01: MissingCompileTimeError # co19-roll r607: Please triage this failure +Language/13_Statements/02_Expression_Statements_A01_t13: MissingCompileTimeError # co19-roll r607: Please triage this failure +Language/12_Expressions/15_Method_Invocation/1_Ordinary_Invocation_A03_t03: RuntimeError # co19-roll r607: Please triage this failure +LibTest/collection/HasNextIterator/HasNextIterator_A01_t01: RuntimeError # co19-roll r607: Please triage this failure +LibTest/collection/LinkedHashSet/LinkedHashSet.from_A01_t01: RuntimeError # co19-roll r607: Please triage this failure +LibTest/core/Runes/lastWhere_A02_t01: RuntimeError # co19-roll r607: Please triage this failure +LibTest/collection/LinkedList/LinkedList_A01_t01: RuntimeError # co19-roll r607: Please triage this failure +LibTest/collection/LinkedList/forEach_A02_t01: RuntimeError # co19-roll r607: Please triage this failure +LibTest/collection/LinkedList/reduce_A01_t01: RuntimeError # co19-roll r607: Please triage this failure +LibTest/core/Invocation/namedArguments_A01_t01: RuntimeError # co19-roll r607: Please triage this failure +LibTest/core/Symbol/Symbol_A01_t04: RuntimeError # co19-roll r607: Please triage this failure [ $runtime == vm || $compiler == dart2dart || $compiler == dart2js ] LibTest/typed_data/ByteData/elementSizeInBytes_A01_t01: fail # co19-roll r569: Please triage this failure @@ -32,21 +51,15 @@ LibTest/math/atan_A01_t01: PASS, FAIL, OK # co19 issue 44 LibTest/math/cos_A01_t01: PASS, FAIL, OK # co19 issue 44 LibTest/math/exp_A01_t01: PASS, FAIL, OK # co19 issue 44 -LibTest/math/max_A01_t03: FAIL, OK # co19 issue 467 -LibTest/math/min_A01_t03: FAIL, OK # co19 issue 467 LibTest/math/sin_A01_t01: PASS, FAIL, OK # co19 issue 44 LibTest/math/tan_A01_t01: PASS, FAIL, OK # co19 issue 44 -LibTest/collection/Queue/iterator_current_A01_t02: FAIL, OK # co19 issue 475 - LibTest/core/double/ceil_A01_t03: FAIL, OK # co19 issue 389 LibTest/core/double/ceil_A01_t04: FAIL, OK # co19 issue 389 LibTest/core/double/floor_A01_t03: FAIL, OK # co19 issue 389 LibTest/core/double/floor_A01_t04: FAIL, OK # co19 issue 389 LibTest/core/double/round_A01_t02: FAIL, OK # co19 issue 389 LibTest/core/double/round_A01_t04: FAIL, OK # co19 issue 389 -LibTest/core/double/truncate_A01_t03: FAIL, OK # co19 issue 389 -LibTest/core/double/truncate_A01_t04: FAIL, OK # co19 issue 389 LibTest/async/Stream/Stream.periodic_A01_t01: TIMEOUT, PASS, FAIL, OK # co19 issue 538 LibTest/async/Stream/Stream.periodic_A03_t01: PASS, FAIL, OK # co19 issue 538 @@ -61,61 +74,19 @@ LibTest/isolate/SendPort/send_A02_t03: SKIP # co19 issue 495 LibTest/isolate/isolate_api/streamSpawnFunction_A02_t02: PASS, FAIL, OK # co19 issue 540 -LibTest/isolate/isolate_api/streamSpawnFunction_A02_t03: PASS, FAIL, OK # co19 issue 540 LibTest/isolate/IsolateStream/contains_A02_t01: PASS, FAIL, OK # co19 issue 540 LibTest/async/EventTransformStream/listen_A04_t01: Pass, Timeout # co19 issue 542 LibTest/typed_data/Int8List/Int8List.fromList_A01_t02: Fail # co19-roll r559: Please triage this failure -LibTest/typed_data/Float32List/removeAll_A01_t01: Fail # co19 issue 548 -LibTest/typed_data/Float32List/retainAll_A01_t01: Fail # co19 issue 548 -LibTest/typed_data/Float32x4List/removeAll_A01_t01: Fail # co19 issue 548 -LibTest/typed_data/Float32x4List/retainAll_A01_t01: Fail # co19 issue 548 -LibTest/typed_data/Float64List/removeAll_A01_t01: Fail # co19 issue 548 -LibTest/typed_data/Float64List/retainAll_A01_t01: Fail # co19 issue 548 -LibTest/typed_data/Int16List/removeAll_A01_t01: Fail # co19 issue 548 -LibTest/typed_data/Int16List/retainAll_A01_t01: Fail # co19 issue 548 -LibTest/typed_data/Int32List/removeAll_A01_t01: Fail # co19 issue 548 -LibTest/typed_data/Int32List/retainAll_A01_t01: Fail # co19 issue 548 -LibTest/typed_data/Int64List/removeAll_A01_t01: Fail # co19 issue 548 -LibTest/typed_data/Int64List/retainAll_A01_t01: Fail # co19 issue 548 -LibTest/typed_data/Int8List/removeAll_A01_t01: Fail # co19 issue 548 -LibTest/typed_data/Int8List/retainAll_A01_t01: Fail # co19 issue 548 -LibTest/typed_data/Uint16List/removeAll_A01_t01: Fail # co19 issue 548 -LibTest/typed_data/Uint16List/retainAll_A01_t01: Fail # co19 issue 548 -LibTest/typed_data/Uint32List/removeAll_A01_t01: Fail # co19 issue 548 -LibTest/typed_data/Uint32List/retainAll_A01_t01: Fail # co19 issue 548 -LibTest/typed_data/Uint64List/removeAll_A01_t01: Fail # co19 issue 548 -LibTest/typed_data/Uint64List/retainAll_A01_t01: Fail # co19 issue 548 -LibTest/typed_data/Uint8ClampedList/removeAll_A01_t01: Fail # co19 issue 548 -LibTest/typed_data/Uint8ClampedList/retainAll_A01_t01: Fail # co19 issue 548 -LibTest/typed_data/Uint8List/removeAll_A01_t01: Fail # co19 issue 548 -LibTest/typed_data/Uint8List/retainAll_A01_t01: Fail # co19 issue 548 - -LibTest/core/String/concat_A01_t01: Fail # co19 issue 561 -LibTest/core/String/concat_A02_t01: Fail # co19 issue 561 - -[ $compiler != dartanalyzer && $compiler != dart2analyzer ] -# Dart2js/Dart2dart succeedes due to a bug in their parser (issue 13223). -Language/12_Expressions/21_Bitwise_Expressions_A01_t01: Fail # co19 Issue 595 - ### CHECKED MODE FAILURES ### [ ($runtime == vm || $compiler == dart2js) && $checked] Language/07_Classes/6_Constructors/2_Factories_A12_t02: fail # co19-roll r587: Please triage this failure Language/13_Statements/09_Switch_A05_t01: FAIL, OK # co19 issue 498 -Language/14_Libraries_and_Scripts/1_Imports_A03_t26: FAIL, OK # co19 issue 498 Language/14_Libraries_and_Scripts/1_Imports_A03_t46: PASS, FAIL, OK # co19 issue 560 Language/14_Libraries_and_Scripts/1_Imports_A03_t66: PASS, FAIL, OK # co19 issue 560 -Language/15_Types/1_Static_Types_A03_t01: Fail # co19-roll r559: Please triage this failure LibTest/async/EventTransformStream/contains_A01_t01: FAIL, OK # co19 issue 498 -LibTest/core/DateTime/compareTo_A02_t01: FAIL, OK # co19 issue 498 LibTest/core/List/removeAt_A02_t01: FAIL, OK # co19 issue 498 -LibTest/core/TypeError/column_A01_t01: FAIL, OK # co19 issue 510 -LibTest/core/TypeError/dstName_A01_t01: FAIL, OK # co19 issue 510 -LibTest/core/TypeError/dstType_A01_t01: FAIL, OK # co19 issue 510 -LibTest/core/TypeError/failedAssertion_A01_t01: FAIL, OK # co19 issue 510 -LibTest/core/TypeError/line_A01_t01: FAIL, OK # co19 issue 510 -LibTest/core/TypeError/srcType_A01_t01: FAIL, OK # co19 issue 510 -LibTest/core/TypeError/url_A01_t01: FAIL, OK # co19 issue 510 +LibTest/collection/DoubleLinkedQueue/removeFirst_A01_t01: RuntimeError # co19-roll r607: Please triage this failure
diff --git a/tests/co19/co19-dart2dart.status b/tests/co19/co19-dart2dart.status index 788a3df..5da24a9 100644 --- a/tests/co19/co19-dart2dart.status +++ b/tests/co19/co19-dart2dart.status
@@ -4,6 +4,15 @@ [ $compiler == dart2dart ] LibTest/async/Stream/Stream.periodic_A01_t01: Pass, Fail # Issue 12562. +LibTest/core/Symbol/Symbol_A01_t02: CompileTimeError # co19-roll r607: Please triage this failure + +Language/12_Expressions/12_Instance_Creation/1_New_A04_t02: RuntimeError # co19-roll r607: Please triage this failure +Language/12_Expressions/17_Getter_Invocation_A07_t02: Pass, RuntimeError # co19-roll r607: Please triage this failure +LibTest/core/Invocation/memberName_A01_t01: Pass, RuntimeError # co18-roll r607: Please triage this failure +LibTest/core/Invocation/positionalArguments_A01_t01: RuntimeError # co19-roll r607: Please triage this failure +LibTest/core/RegExp/Pattern_semantics/splitQueryString_A02_t01: RuntimeError # co19-roll r607: Please triage this failure +LibTest/core/Symbol/Symbol_A01_t03: RuntimeError # co19-roll r607: Please triage this failure +LibTest/core/Symbol/Symbol_A01_t05: RuntimeError # co19-roll r607: Please triage this failure Language/07_Classes/9_Superclasses/1_Inheritance_and_Overriding_A01_t03: Fail # TODO(dart2dart-team): Please triage this failure. @@ -13,20 +22,9 @@ Language/03_Overview/1_Scoping_A02_t05: Fail # Inherited from dart2js Language/03_Overview/1_Scoping_A02_t06: Fail # inherited from dart2js -Language/05_Variables/05_Variables_A07_t07: Fail # Inherited from dart2js -Language/05_Variables/05_Variables_A07_t08: Fail # Inherited from dart2js -Language/05_Variables/05_Variables_A08_t01: Fail # Inherited from dart2js -Language/05_Variables/05_Variables_A08_t02: Fail # Inherited from dart2js Language/05_Variables/1_Evaluation_of_Implicit_Variable_Getters_A01_t02: Fail # Inherited from VM (circular initialization?). Language/05_Variables/1_Evaluation_of_Implicit_Variable_Getters_A01_t05: Fail # Inherited from dart2js -Language/06_Functions/2_Formal_Parameters/1_Required_Formals_A02_t06: Fail # http://dartbug.com/5519 -Language/06_Functions/2_Formal_Parameters/1_Required_Formals_A02_t07: Fail # http://dartbug.com/5519 -Language/06_Functions/2_Formal_Parameters/2_Optional_Formals_A02_t01: Fail # http://dartbug.com/5519 -Language/06_Functions/2_Formal_Parameters/2_Optional_Formals_A02_t02: Fail # http://dartbug.com/5519 -Language/06_Functions/2_Formal_Parameters/2_Optional_Formals_A03_t03: Fail # inherited from VM -Language/06_Functions/2_Formal_Parameters/2_Optional_Formals_A03_t04: Fail # http://dartbug.com/5519 Language/06_Functions/4_External_Functions_A01_t01: Fail # inherited from VM -Language/07_Classes/07_Classes_A02_t11: Fail # http://dartbug.com/5519 Language/07_Classes/3_Setters_A04_t01: Fail # inherited from VM Language/07_Classes/3_Setters_A04_t02: Fail # inherited from VM Language/07_Classes/3_Setters_A04_t03: Fail # inherited from VM @@ -35,20 +33,17 @@ Language/07_Classes/3_Setters_A04_t06: Fail # inherited from VM Language/07_Classes/3_Setters_A04_t07: Fail # inherited from VM Language/07_Classes/6_Constructors/1_Generative_Constructors_A09_t01: Fail # http://dartbug.com/5519 -Language/07_Classes/6_Constructors/3_Constant_Constructors_A04_t01: Fail # inherited from VM -Language/07_Classes/6_Constructors/3_Constant_Constructors_A04_t02: Fail # inherited from VM -Language/07_Classes/6_Constructors/3_Constant_Constructors_A04_t03: Fail # inherited from VM -Language/07_Classes/6_Constructors/3_Constant_Constructors_A05_t01: Fail # inherited from VM -Language/07_Classes/6_Constructors/3_Constant_Constructors_A05_t02: Fail # inherited from VM -Language/07_Classes/6_Constructors/3_Constant_Constructors_A05_t03: Fail # inherited from VM +Language/07_Classes/6_Constructors/3_Constant_Constructors_A05_t04: Fail # Issue 13652 Language/07_Classes/6_Constructors_A02_t01: Fail # http://dartbug.com/5519 -Language/12_Expressions/07_Maps_A12_t03: Fail # http://dartbug.com/5519 +Language/12_Expressions/01_Constants_A03_t01: Fail # Issue 13652 +Language/13_Statements/09_Switch_A02_t04: Fail # co19 issue 605 +Language/12_Expressions/00_Object_Identity/1_Object_Identity_A04_t02: Fail # co19 issue 606 + LibTest/core/Match/operator_subscript_A01_t01: Fail # inherited from VM LibTest/core/Match/operator_subscript_A01_t01: Fail, OK # co19 issue 294 LibTest/core/RegExp/Pattern_semantics/firstMatch_Atom_A02_t01: Fail # inherited from VM LibTest/core/RegExp/Pattern_semantics/firstMatch_Atom_A02_t01: Fail, OK # co19 issue 294 LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A03_t01: Fail # inherited from VM -LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A04_t01: Fail # inherited from VM LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterEscape_A06_t02: Fail LibTest/core/RegExp/Pattern_semantics/firstMatch_DecimalEscape_A01_t02: Fail # inherited from VM LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: Fail # inherited from VM @@ -66,14 +61,11 @@ LibTest/isolate/isolate_api/spawnUri_A01_t03: Fail, OK # Problems with the test: encoded file name LibTest/isolate/isolate_api/spawnUri_A01_t04: Fail, OK # Problems with the test: encoded file name LibTest/isolate/isolate_api/spawnUri_A01_t05: Fail, OK # Problems with the test: encoded file name +LibTest/isolate/IsolateSink/add_A01_t01: CompileTimeError # Issue 13683 +LibTest/isolate/SendPort/send_A02_t01: CompileTimeError # Issue 13683 LibTest/math/exp_A01_t01: Fail # Issue co19 - 44 LibTest/math/sin_A01_t01: Fail # Inherited from VM. LibTest/math/tan_A01_t01: Fail # Issue co19 - 44 -LibTest/typed_data/Float32x4/toUint32x4_A01_t01: Fail # co19 Issue 601 -LibTest/typed_data/Float32x4/toUint32x4_A01_t02: Fail # co19 Issue 601 -LibTest/typed_data/Uint32x4/toFloat32x4_A01_t01: Fail # co19 Issue 601 -LibTest/typed_data/Uint32x4/toFloat32x4_A01_t02: Fail # co19 Issue 601 -LibTest/typed_data/Float32x4/clamp_A02_t01: RuntimeError # co19 Issue 600 LibTest/typed_data/Float32x4/clamp_A01_t01: RuntimeError # co19 Issue 600 @@ -101,8 +93,6 @@ Language/14_Libraries_and_Scripts/1_Imports_A01_t17: Fail # co19 Issue 603 Language/14_Libraries_and_Scripts/1_Imports_A04_t01: Fail # co19 Issue 603 -Language/14_Libraries_and_Scripts/2_Exports_A05_t01: Fail # co19 Issue 604 - # co19-roll r546 (11.08.2013) caused these failures [ $compiler == dart2dart ] @@ -124,60 +114,9 @@ Language/07_Classes/4_Abstract_Instance_Members_A03_t04: Fail # co19-roll r559: Please triage this failure Language/07_Classes/6_Constructors/2_Factories_A10_t01: crash # co19-roll r587: Please triage this failure Language/07_Classes/6_Constructors/2_Factories_A10_t04: crash # co19-roll r587: Please triage this failure -Language/12_Expressions/01_Constants_A03_t02: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A03_t03: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A03_t04: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A03_t05: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A05_t02: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A05_t03: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A05_t04: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A08_t02: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A09_t02: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A10_t02: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A10_t03: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A11_t02: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A11_t03: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A11_t04: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A12_t02: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A12_t03: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A13_t02: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A13_t03: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A13_t04: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A13_t05: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A14_t02: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A15_t06: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A15_t07: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A15_t08: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A15_t09: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A15_t10: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A15_t11: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A15_t12: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A15_t13: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A15_t14: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A15_t15: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A15_t16: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A15_t17: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A15_t18: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A15_t20: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A15_t21: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A15_t31: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A16_t03: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A17_t01: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A17_t02: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A17_t03: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A19_t02: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A19_t03: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A19_t04: fail # co19-roll r546: Please triage this failure Language/12_Expressions/01_Constants_A20_t02: fail # co19-roll r546: Please triage this failure Language/12_Expressions/01_Constants_A20_t03: fail # co19-roll r546: Please triage this failure Language/12_Expressions/05_Strings/1_String_Interpolation_A01_t09: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/05_Strings_A02_t46: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/05_Strings_A02_t48: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/06_Lists_A03_t01: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/06_Lists_A03_t02: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/07_Maps_A02_t01: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/07_Maps_A02_t02: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/07_Maps_A12_t01: fail # co19-roll r546: Please triage this failure Language/12_Expressions/12_Instance_Creation/1_New_A02_t03: fail # co19-roll r546: Please triage this failure Language/12_Expressions/12_Instance_Creation/1_New_A02_t05: fail # co19-roll r546: Please triage this failure Language/12_Expressions/12_Instance_Creation/1_New_A02_t06: fail # co19-roll r546: Please triage this failure @@ -190,10 +129,6 @@ Language/12_Expressions/12_Instance_Creation/1_New_A06_t06: fail # co19-roll r546: Please triage this failure Language/12_Expressions/12_Instance_Creation/1_New_A06_t12: fail # co19-roll r546: Please triage this failure Language/12_Expressions/12_Instance_Creation/1_New_A09_t09: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/12_Instance_Creation/2_Const_A06_t01: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/12_Instance_Creation/2_Const_A06_t02: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/12_Instance_Creation/2_Const_A10_t01: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/14_Function_Invocation/4_Function_Expression_Invocation_A05_t01: fail # co19-roll r546: Please triage this failure Language/12_Expressions/15_Method_Invocation/3_Static_Invocation_A04_t09: fail # co19-roll r546: Please triage this failure Language/12_Expressions/22_Equality_A01_t01: fail # co19-roll r546: Please triage this failure Language/12_Expressions/22_Equality_A01_t19: fail # co19-roll r546: Please triage this failure @@ -201,9 +136,6 @@ Language/12_Expressions/22_Equality_A05_t01: fail # co19-roll r546: Please triage this failure Language/12_Expressions/27_Unary_Expressions_A01_t01: fail # co19-roll r546: Please triage this failure Language/12_Expressions/30_Identifier_Reference_A02_t01: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/30_Identifier_Reference_A04_t09: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/30_Identifier_Reference_A05_t01: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/30_Identifier_Reference_A05_t12: fail # co19-roll r546: Please triage this failure Language/12_Expressions/30_Identifier_Reference_A08_t02: fail # co19-roll r546: Please triage this failure Language/12_Expressions/32_Type_Test_A04_t02: fail # co19-roll r546: Please triage this failure Language/12_Expressions/32_Type_Test_A04_t03: fail # co19-roll r546: Please triage this failure @@ -221,7 +153,6 @@ Language/14_Libraries_and_Scripts/1_Imports_A03_t08: fail # co19-roll r546: Please triage this failure Language/14_Libraries_and_Scripts/1_Imports_A03_t09: fail # co19-roll r546: Please triage this failure Language/14_Libraries_and_Scripts/1_Imports_A03_t10: fail # co19-roll r546: Please triage this failure -Language/14_Libraries_and_Scripts/1_Imports_A03_t27: fail # co19-roll r546: Please triage this failure Language/14_Libraries_and_Scripts/1_Imports_A03_t28: fail # co19-roll r546: Please triage this failure Language/14_Libraries_and_Scripts/1_Imports_A03_t29: fail # co19-roll r546: Please triage this failure Language/14_Libraries_and_Scripts/1_Imports_A03_t30: fail # co19-roll r546: Please triage this failure @@ -257,4 +188,4 @@ LibTest/json/stringify_A02_t01: fail # co19-roll r587: Please triage this failure LibTest/json/stringify_A03_t02: fail # co19-roll r587: Please triage this failure LibTest/json/printOn_A02_t01: fail # co19-roll r587: Please triage this failure -LibTest/json/printOn_A03_t02: fail # co19-roll r587: Please triage this failure +LibTest/json/printOn_A03_t02: fail # co19-roll r587: Please triage this failure \ No newline at end of file
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status index 9bc5de1..0021c0c 100644 --- a/tests/co19/co19-dart2js.status +++ b/tests/co19/co19-dart2js.status
@@ -5,6 +5,7 @@ [ $compiler == dart2js && $runtime == jsshell ] LibTest/isolate/isolate_api/spawnUri_A02_t01: Crash # TODO(ahe): Please triage this crash. LibTest/core/List/sort_A01_t04: Fail, Pass, Timeout # Must be a bug in jsshell, test sometimes times out. +LibTest/core/RegExp/Pattern_semantics/splitQueryString_A02_t01: RuntimeError # co19-roll r607: Please triage this failure [ $compiler == dart2js && $checked && $runtime == ie9 ] LibTest/core/Uri/encodeQueryComponent_A01_t02: Pass, Timeout # co19-roll r576: Please triage this failure @@ -21,7 +22,6 @@ LibTest/core/double/INFINITY_A01_t04: RuntimeError # TODO(ahe): Please triage this failure. LibTest/core/double/NEGATIVE_INFINITY_A01_t04: RuntimeError # TODO(ahe): Please triage this failure. LibTest/core/List/List_A03_t01: RuntimeError # TODO(kasperl): Please triage this failure. -LibTest/core/List/sort_A01_t04: Pass, Slow # http://dartbug.com/11846 LibTest/typed_data/ByteData/getFloat32_A02_t02: fail # co19-roll r569: Please triage this failure LibTest/typed_data/ByteData/getFloat64_A02_t02: fail # co19-roll r569: Please triage this failure @@ -64,7 +64,7 @@ LibTest/isolate/isolate_api/spawnFunction_A03_t01: Fail, Pass # TODO(ahe): Please triage this failure. LibTest/isolate/isolate_api/spawnUri_A02_t02: Fail, Pass # TODO(ahe): Please triage this failure. LibTest/isolate/isolate_api/spawnUri_A02_t03: Fail, Pass # TODO(ahe): Please triage this failure. - +LibTest/core/Uri/Uri_A06_t03: Pass, Slow [ $compiler == dart2js ] @@ -101,10 +101,11 @@ LibTest/core/double/round_A01_t01: Fail # TODO(ngeoaffray): Please triage these failure. LibTest/core/int/operator_truncating_division_A01_t01: Fail # TODO(ngeoaffray): Please triage these failure. LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A03_t01: Fail # TODO(ngeoaffray): Please triage these failure. -LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A04_t01: Fail # TODO(ngeoaffray): Please triage these failure. [ $compiler == dart2js && $checked ] Language/07_Classes/6_Constructors/1_Generative_Constructors_A17_t03: Fail # TODO(ahe): Please triage this failure. +Language/15_Types/2_Dynamic_Type_System_A01_t02: RuntimeError # co19-roll r607: Please triage this failure +Language/15_Types/8_Parameterized_Types_A03_t07: RuntimeError # co19-roll r607: Please triage this failure [ $compiler == dart2js ] @@ -127,8 +128,11 @@ LibTest/core/int/isOdd_A01_t01: RuntimeError, OK # co19 issue 277 LibTest/core/int/isEven_A01_t01: RuntimeError, OK # co19 issue 277 +Language/12_Expressions/01_Constants_A20_t03: MissingCompileTimeError # co19 Issue 611 + [ $compiler == dart2js ] -LibTest/isolate/SendPort/send_A02_t01: CompileTimeError # Compile-time error: error: not a compile-time constant +LibTest/isolate/IsolateSink/add_A01_t01: CompileTimeError # Issue 13683 +LibTest/isolate/SendPort/send_A02_t01: CompileTimeError # Issue 13683 LibTest/isolate/isolate_api/spawnUri_A02_t01: RuntimeError # Runtime error: Expect.throws() fails LibTest/isolate/isolate_api/spawnUri_A01_t01: RuntimeError # Runtime error: UnsupportedError: Currently spawnUri is not supported without web workers. @@ -223,19 +227,10 @@ LibTest/typed_data/ByteData/setUint8_A02_t02: fail # Issue 12989 LibTest/typed_data/ByteData/setUint8_A02_t02: fail # Issue 12989 -LibTest/typed_data/Float32x4/toUint32x4_A01_t01: RuntimeError # co19 Issue 601 -LibTest/typed_data/Float32x4/toUint32x4_A01_t02: RuntimeError # co19 Issue 601 -LibTest/typed_data/Uint32x4/toFloat32x4_A01_t01: RuntimeError # co19 Issue 601 -LibTest/typed_data/Uint32x4/toFloat32x4_A01_t02: RuntimeError # co19 Issue 601 -LibTest/typed_data/Float32x4/clamp_A02_t01: RuntimeError # co19 Issue 600 - Language/14_Libraries_and_Scripts/1_Imports_A01_t17: Fail # co19 Issue 603 Language/14_Libraries_and_Scripts/1_Imports_A04_t01: Fail # co19 Issue 603 -Language/14_Libraries_and_Scripts/2_Exports_A05_t01: Fail # co19 Issue 604 - [ $compiler == dart2js && $jscl ] -LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A04_t01: Fail, Pass # issue 3333 LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A03_t01: Fail, Pass # issue 3333 LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: RuntimeError, OK # This is not rejected by V8. LibTest/core/RegExp/Pattern_semantics/firstMatch_Term_A04_t01: RuntimeError, OK # co19 issue 92. @@ -254,6 +249,10 @@ LibTest/core/int/toRadixString_A01_t01: RuntimeError, OK # Bad test: uses Expect.fail, Expect.throws, assumes case of result, and uses unsupported radixes. [ $compiler == dart2js && $runtime == ie9 ] +Language/12_Expressions/00_Object_Identity/1_Object_Identity_A05_t02: RuntimeError # co19-roll r607: Please triage this failure +Language/12_Expressions/02_Null_A02_t01: RuntimeError # co19-roll r607: Please triage this failure +Language/12_Expressions/17_Getter_Invocation_A07_t02: RuntimeError # co19-roll r607: Please triage this failure +LibTest/collection/LinkedList/add_A01_t01: Pass, Timeout # co19-roll r607: Please triage this failure LibTest/core/Uri/Uri_A06_t03: Pass, Timeout # Issue 13511 LibTest/math/cos_A01_t01: Fail # co19 issue 44 @@ -314,21 +313,7 @@ # Missing compile-time errors. # [ $compiler == dart2js ] -Language/05_Variables/05_Variables_A07_t07: MissingCompileTimeError # Checks that a compile-time error occurs if a global constant variable is not initialized at declaration. -Language/05_Variables/05_Variables_A07_t08: MissingCompileTimeError # Checks that a compile-time error occurs if a global typed constant variable is not initialized at declaration. -Language/05_Variables/05_Variables_A08_t01: MissingCompileTimeError # Checks that a compile-time error occurs if a constant variable is not initialized. -Language/06_Functions/2_Formal_Parameters/1_Required_Formals_A02_t06: MissingCompileTimeError # Checks that a functionSignature parameter cannot be final. -Language/06_Functions/2_Formal_Parameters/1_Required_Formals_A02_t07: MissingCompileTimeError # Checks that a functionSignature parameter cannot be declared as variable. -Language/06_Functions/2_Formal_Parameters/2_Optional_Formals_A03_t03: MissingCompileTimeError # TODO(ahe): Enforce optional parameter semantics. -Language/06_Functions/2_Formal_Parameters/2_Optional_Formals_A03_t04: MissingCompileTimeError # TODO(ahe): Enforce optional parameter semantics. -Language/07_Classes/07_Classes_A02_t11: MissingCompileTimeError # Checks that it is a compile-time error if a static final variable declaration does not include explicit initializer. -Language/12_Expressions/01_Constants_A20_t03: MissingCompileTimeError # Checks that an identifier expression that denotes a type parameter can not be assigned to a constant variable. Language/12_Expressions/05_Strings/1_String_Interpolation_A01_t09: MissingCompileTimeError # Checks that it is a compile-time error if a string interpolation construct does not start with IDENTIFIER_NO_DOLLAR or opening brace. -Language/12_Expressions/05_Strings_A02_t46: MissingCompileTimeError # Checks that multi-line strings that contain characters and sequences prohibited by this grammar, cause compile-time errors. -Language/12_Expressions/05_Strings_A02_t48: MissingCompileTimeError # Checks that multi-line strings that contain characters and sequences prohibited by this grammar, cause compile-time errors. -Language/12_Expressions/30_Identifier_Reference_A04_t09: MissingCompileTimeError # Checks that it is a compile-time error when a built-in identifier dynamic is used as the declared name of a type variable. -Language/12_Expressions/30_Identifier_Reference_A05_t01: MissingCompileTimeError # Checks that it is a compile-time error when a built-in identifier "abstract" is used as a type annotation of a local variable. -Language/12_Expressions/30_Identifier_Reference_A05_t12: MissingCompileTimeError # Checks that it is a compile-time error when a built-in identifier "static" is used as a type annotation of a local variable. Language/16_Reference/1_Lexical_Rules/1_Reserved_Words_A40_t04: MissingCompileTimeError # Checks that other Unicode whitespaces are not allowed: check NO-BREAK SPACE (U+00A0) Language/16_Reference/1_Lexical_Rules_A02_t06: MissingCompileTimeError # Checks that Unicode whitespaces other than WHITESPACE are not permitted in the source code. Checks symbol U+00a0. @@ -345,6 +330,9 @@ Language/07_Classes/3_Setters_A04_t06: CompileTimeError # http://dartbug.com/5023 Language/07_Classes/3_Setters_A04_t07: CompileTimeError # http://dartbug.com/5023 +Language/07_Classes/6_Constructors/3_Constant_Constructors_A05_t04: CompileTimeError # Issue 13652 +Language/12_Expressions/01_Constants_A03_t01: CompileTimeError # Issue 13652 + [ $compiler == dart2js && $runtime == ie9 ] # These are most likey due to the fact that IE9 doesn't support typed data @@ -414,7 +402,6 @@ LibTest/typed_data/ByteData/setUint8_A01_t01: fail # co19-roll r569: Please triage this failure LibTest/typed_data/ByteData/toString_A01_t01: fail # co19-roll r569: Please triage this failure - [ $compiler == dart2js ] Language/03_Overview/1_Scoping_A02_t28: fail # co19-roll r559: Please triage this failure Language/05_Variables/05_Variables_A05_t01: fail # co19-roll r546: Please triage this failure @@ -427,8 +414,6 @@ Language/07_Classes/4_Abstract_Instance_Members_A03_t04: fail # co19-roll r559: Please triage this failure Language/12_Expressions/00_Object_Identity/1_Object_Identity_A02_t02: fail # co19-roll r546: Please triage this failure Language/12_Expressions/00_Object_Identity/1_Object_Identity_A06_t01: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/00_Object_Identity/1_Object_Identity_A06_t02: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/01_Constants_A03_t01: fail # co19-roll r546: Please triage this failure Language/12_Expressions/03_Numbers_A01_t06: fail # co19-roll r546: Please triage this failure Language/12_Expressions/03_Numbers_A01_t09: fail # co19-roll r546: Please triage this failure Language/12_Expressions/05_Strings_A20_t01: fail # co19-roll r546: Please triage this failure @@ -459,7 +444,6 @@ Language/14_Libraries_and_Scripts/1_Imports_A03_t08: fail # co19-roll r546: Please triage this failure Language/14_Libraries_and_Scripts/1_Imports_A03_t09: fail # co19-roll r546: Please triage this failure Language/14_Libraries_and_Scripts/1_Imports_A03_t10: fail # co19-roll r546: Please triage this failure -Language/14_Libraries_and_Scripts/1_Imports_A03_t27: fail # co19-roll r546: Please triage this failure Language/14_Libraries_and_Scripts/1_Imports_A03_t28: fail # co19-roll r546: Please triage this failure Language/14_Libraries_and_Scripts/1_Imports_A03_t29: fail # co19-roll r546: Please triage this failure Language/14_Libraries_and_Scripts/1_Imports_A03_t30: fail # co19-roll r546: Please triage this failure @@ -484,7 +468,6 @@ LibTest/isolate/isolate_api/spawnUri_A02_t02: fail # co19-roll r546: Please triage this failure LibTest/isolate/isolate_api/spawnUri_A02_t03: fail # co19-roll r546: Please triage this failure LibTest/isolate/isolate_api/streamSpawnFunction_A02_t02: fail # co19-roll r546: Please triage this failure -LibTest/isolate/IsolateSink/add_A01_t01: fail # co19-roll r546: Please triage this failure LibTest/isolate/IsolateSink/addError_A01_t01: fail # co19-roll r546: Please triage this failure LibTest/isolate/IsolateSink/addError_A01_t02: fail # co19-roll r546: Please triage this failure LibTest/isolate/IsolateStream/any_A02_t01: fail # co19-roll r546: Please triage this failure @@ -532,6 +515,7 @@ LibTest/typed_data/Uint8List/Uint8List.view_A05_t02: RuntimeError # co19-roll r559: Please triage this failure LibTest/typed_data/Uint8List/Uint8List.view_A05_t03: RuntimeError # co19-roll r559: Please triage this failure Utils/tests/Expect/identical_A01_t01: fail # co19-roll r546: Please triage this failure +Language/12_Expressions/15_Method_Invocation/4_Super_Invocation_A02_t05: CompileTimeError # co19-roll r607: Please triage this failure [ $compiler == dart2js && $checked ] Language/10_Generics/09_Generics_A03_t01: fail # co19-roll r546: Please triage this failure @@ -540,7 +524,6 @@ Language/12_Expressions/06_Lists_A09_t01: fail # co19-roll r546: Please triage this failure Language/12_Expressions/06_Lists_A09_t04: fail # co19-roll r546: Please triage this failure Language/12_Expressions/07_Maps_A10_t05: fail # co19-roll r546: Please triage this failure -Language/12_Expressions/07_Maps_A11_t01: fail # co19-roll r546: Please triage this failure Language/12_Expressions/12_Instance_Creation/1_New_A07_t01: fail # co19-roll r546: Please triage this failure Language/12_Expressions/12_Instance_Creation/1_New_A12_t02: fail # co19-roll r546: Please triage this failure Language/12_Expressions/12_Instance_Creation/2_Const_A09_t02: Fail # co19-roll r559: Please triage this failure @@ -595,6 +578,9 @@ LibTest/async/Timer/Timer_A01_t01: fail # co19-roll r546: Please triage this failure LibTest/typed_data/Float32x4List/Float32x4List.view_A01_t02: fail # co19-roll r587: Please triage this failure LibTest/typed_data/Float32x4List/Float32x4List.view_A06_t01: fail # co19-roll r587: Please triage this failure +Language/12_Expressions/00_Object_Identity/1_Object_Identity_A05_t02: RuntimeError # co19-roll r607: Please triage this failure +Language/12_Expressions/02_Null_A02_t01: RuntimeError # co19-roll r607: Please triage this failure +Language/12_Expressions/17_Getter_Invocation_A07_t02: RuntimeError # co19-roll r607: Please triage this failure [ $compiler == dart2js && $minified ] Language/12_Expressions/14_Function_Invocation/4_Function_Expression_Invocation_A01_t02: fail # co19-roll r559: Please triage this failure @@ -627,10 +613,12 @@ Language/07_Classes/6_Constructors/2_Factories_A10_t02: fail # co19-roll r587: Please triage this failure Language/07_Classes/6_Constructors/2_Factories_A10_t03: fail # co19-roll r587: Please triage this failure Language/10_Generics/09_Generics_A01_t17: fail # co19-roll r587: Please triage this failure +Language/15_Types/5_Function_Types_A07_t01: CompileTimeError # co19-roll r607: Please triage this failure +Language/15_Types/5_Function_Types_A07_t01: CompileTimeError # co19-roll r607: Please triage this failure +LibTest/core/Symbol/Symbol_A01_t02: CompileTimeError # co19-roll r607: Please triage this failure +Language/12_Expressions/07_Maps_A13_t01: MissingCompileTimeError # co19-roll r607: Please triage this failure [ $compiler == dart2js ] -Language/07_Classes/6_Constructors/3_Constant_Constructors_A05_t04: fail # co19-roll r587: Please triage this failure -Language/07_Classes/6_Constructors/3_Constant_Constructors_A05_t04: fail # co19-roll r587: Please triage this failure LibTest/json/stringify_A01_t01: fail # co19-roll r587: Please triage this failure LibTest/json/stringify_A02_t01: fail # co19-roll r587: Please triage this failure LibTest/json/printOn_A01_t01: fail # co19-roll r587: Please triage this failure
diff --git a/tests/co19/co19-dartium.status b/tests/co19/co19-dartium.status new file mode 100644 index 0000000..471d509 --- /dev/null +++ b/tests/co19/co19-dartium.status
@@ -0,0 +1,117 @@ +# Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +# for details. All rights reserved. Use of this source code is governed by a +# BSD-style license that can be found in the LICENSE file. + +[ $compiler == none && $runtime == dartium ] +Language/03_Overview/2_Privacy_A01_t06: Fail # Issue 13719: Please triage this failure. +Language/05_Variables/05_Variables_A05_t01: Fail # Issue 13719: Please triage this failure. +Language/05_Variables/05_Variables_A05_t02: Fail # Issue 13719: Please triage this failure. +Language/05_Variables/05_Variables_A06_t01: Fail # Issue 13719: Please triage this failure. +Language/05_Variables/05_Variables_A06_t02: Fail # Issue 13719: Please triage this failure. +Language/05_Variables/05_Variables_A06_t03: Fail # Issue 13719: Please triage this failure. +Language/05_Variables/05_Variables_A06_t04: Fail # Issue 13719: Please triage this failure. +Language/05_Variables/05_Variables_A06_t05: Fail # Issue 13719: Please triage this failure. +Language/05_Variables/05_Variables_A06_t06: Fail # Issue 13719: Please triage this failure. +Language/05_Variables/05_Variables_A16_t02: Fail # Issue 13719: Please triage this failure. +Language/05_Variables/1_Evaluation_of_Implicit_Variable_Getters_A01_t02: Fail # Issue 13719: Please triage this failure. +Language/05_Variables/1_Evaluation_of_Implicit_Variable_Getters_A01_t05: Fail # Issue 13719: Please triage this failure. +Language/07_Classes/6_Constructors/1_Generative_Constructors_A09_t01: Fail # Issue 13719: Please triage this failure. +Language/07_Classes/6_Constructors/1_Generative_Constructors_A12_t02: Fail # Issue 13719: Please triage this failure. +Language/07_Classes/6_Constructors/1_Generative_Constructors_A20_t02: Fail # Issue 13719: Please triage this failure. +Language/09_Mixins/1_Mixin_Application_A01_t01: Fail # co19-roll r607: Please triage this failure +Language/12_Expressions/00_Object_Identity/1_Object_Identity_A04_t02: Fail # Issue 13719: Please triage this failure. +Language/12_Expressions/01_Constants_A16_t01: Fail # Issue 13719: Please triage this failure. +Language/12_Expressions/01_Constants_A16_t02: Fail # Issue 13719: Please triage this failure. +Language/12_Expressions/01_Constants_A16_t04: Fail # Issue 13719: Please triage this failure. +Language/12_Expressions/01_Constants_A16_t05: Fail # Issue 13719: Please triage this failure. +Language/12_Expressions/12_Instance_Creation/1_New_A06_t12: Fail # Issue 13719: Please triage this failure. +Language/12_Expressions/12_Instance_Creation/1_New_A09_t09: Fail # Issue 13719: Please triage this failure. +Language/12_Expressions/12_Instance_Creation/2_Const_A10_t01: Fail # Issue 13719: Please triage this failure. +Language/12_Expressions/15_Method_Invocation/1_Ordinary_Invocation_A03_t03: Fail # co19-roll r607: Please triage this failure +Language/12_Expressions/15_Method_Invocation/3_Static_Invocation_A04_t09: Fail # Issue 13719: Please triage this failure. +Language/12_Expressions/18_Assignment_A01_t07: Fail # co19-roll r607: Please triage this failure +Language/12_Expressions/18_Assignment_A04_t09: Fail # co19-roll r607: Please triage this failure +Language/12_Expressions/30_Identifier_Reference_A08_t02: Fail # Issue 13719: Please triage this failure. +Language/12_Expressions/32_Type_Test_A04_t02: Fail # Issue 13719: Please triage this failure. +Language/12_Expressions/32_Type_Test_A04_t03: Fail # Issue 13719: Please triage this failure. +Language/12_Expressions/32_Type_Test_A04_t04: Fail # Issue 13719: Please triage this failure. +Language/12_Expressions/33_Type_Cast_A03_t02: Fail # Issue 13719: Please triage this failure. +Language/12_Expressions/33_Type_Cast_A03_t03: Fail # Issue 13719: Please triage this failure. +Language/13_Statements/02_Expression_Statements_A01_t13: Fail # co19-roll r607: Please triage this failure +Language/13_Statements/03_Variable_Declaration_A04_t01: Fail # co19-roll r607: Please triage this failure +Language/13_Statements/03_Variable_Declaration_A04_t02: Fail # co19-roll r607: Please triage this failure +Language/13_Statements/03_Variable_Declaration_A04_t05: Fail # co19-roll r607: Please triage this failure +Language/13_Statements/03_Variable_Declaration_A04_t06: Fail # co19-roll r607: Please triage this failure +Language/13_Statements/03_Variable_Declaration_A04_t07: Fail # Issue 13719: Please triage this failure. +Language/13_Statements/03_Variable_Declaration_A04_t08: Fail # Issue 13719: Please triage this failure. +Language/13_Statements/04_Local_Function_Declaration_A04_t01: Fail # co19-roll r607: Please triage this failure +Language/13_Statements/06_For_A01_t11: Fail # Issue 13719: Please triage this failure. +Language/13_Statements/09_Switch_A01_t02: Fail # Issue 13719: Please triage this failure. +Language/13_Statements/09_Switch_A02_t04: Fail # Issue 13719: Please triage this failure. +Language/13_Statements/12_Labels_A01_t03: Fail # Issue 13719: Please triage this failure. +Language/14_Libraries_and_Scripts/2_Exports_A04_t02: Fail # Issue 13719: Please triage this failure. +Language/14_Libraries_and_Scripts/2_Exports_A04_t03: Fail # Issue 13719: Please triage this failure. +Language/14_Libraries_and_Scripts/4_Scripts_A03_t02: Fail # Issue 13719: Please triage this failure. +Language/14_Libraries_and_Scripts/5_URIs_A01_t04: Fail # Issue 13719: Please triage this failure. +Language/14_Libraries_and_Scripts/5_URIs_A01_t05: Fail # Issue 13719: Please triage this failure. +Language/14_Libraries_and_Scripts/5_URIs_A01_t14: Fail # Issue 13719: Please triage this failure. +Language/14_Libraries_and_Scripts/5_URIs_A01_t15: Fail # Issue 13719: Please triage this failure. +Language/14_Libraries_and_Scripts/5_URIs_A01_t24: Fail # Issue 13719: Please triage this failure. +Language/14_Libraries_and_Scripts/5_URIs_A01_t25: Fail # Issue 13719: Please triage this failure. +Language/15_Types/1_Static_Types_A03_t01: Fail # co19-roll r607: Please triage this failure +Language/15_Types/3_Type_Declarations/1_Typedef_A07_t08: Fail # co19-roll r607: Please triage this failure +Language/15_Types/3_Type_Declarations/1_Typedef_A07_t09: Fail # co19-roll r607: Please triage this failure +LibTest/async/Completer/completeError_A02_t01: Pass, Fail # Issue 13719: Please triage this failure. +LibTest/async/Stream/Stream.periodic_A01_t01: Timeout # Issue 13719: Please triage this failure. +LibTest/collection/HasNextIterator/HasNextIterator_A01_t01: Fail # co19-roll r607: Please triage this failure +LibTest/collection/LinkedHashSet/LinkedHashSet_class_A01_t01: Fail # co19-roll r607: Please triage this failure +LibTest/collection/LinkedHashSet/LinkedHashSet.from_A01_t01: Fail # co19-roll r607: Please triage this failure +LibTest/collection/LinkedList/first_A01_t02: Fail # co19-roll r607: Please triage this failure +LibTest/collection/LinkedList/forEach_A02_t01: Fail # co19-roll r607: Please triage this failure +LibTest/collection/LinkedList/LinkedList_A01_t01: Fail # co19-roll r607: Please triage this failure +LibTest/collection/LinkedList/reduce_A01_t01: Fail # co19-roll r607: Please triage this failure +LibTest/core/DateTime/parse_A03_t01: Fail # Issue 13719: Please triage this failure. +LibTest/core/double/ceil_A01_t03: Fail # Issue 13719: Please triage this failure. +LibTest/core/double/ceil_A01_t04: Fail # Issue 13719: Please triage this failure. +LibTest/core/double/floor_A01_t03: Fail # Issue 13719: Please triage this failure. +LibTest/core/double/floor_A01_t04: Fail # Issue 13719: Please triage this failure. +LibTest/core/double/round_A01_t02: Fail # Issue 13719: Please triage this failure. +LibTest/core/double/round_A01_t04: Fail # Issue 13719: Please triage this failure. +LibTest/core/int/toRadixString_A01_t01: Fail # Issue 13719: Please triage this failure. +LibTest/core/Invocation/namedArguments_A01_t01: Fail # co19-roll r607: Please triage this failure +LibTest/core/Invocation/positionalArguments_A01_t01: Fail # co19-roll r607: Please triage this failure +LibTest/core/Match/operator_subscript_A01_t01: Fail # Issue 13719: Please triage this failure. +LibTest/core/RegExp/firstMatch_A01_t01: Fail # Issue 13719: Please triage this failure. +LibTest/core/RegExp/Pattern_semantics/firstMatch_Atom_A02_t01: Fail # Issue 13719: Please triage this failure. +LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A03_t01: Fail # Issue 13719: Please triage this failure. +LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterEscape_A06_t02: Fail # Issue 13719: Please triage this failure. +LibTest/core/RegExp/Pattern_semantics/firstMatch_DecimalEscape_A01_t02: Fail # Issue 13719: Please triage this failure. +LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: Fail # Issue 13719: Please triage this failure. +LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t05: Fail # Issue 13719: Please triage this failure. +LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t06: Fail # Issue 13719: Please triage this failure. +LibTest/core/RegExp/Pattern_semantics/firstMatch_Term_A03_t01: Fail # Issue 13719: Please triage this failure. +LibTest/core/RegExp/Pattern_semantics/splitQueryString_A02_t01: Fail # co19-roll r607: Please triage this failure +LibTest/core/Runes/lastWhere_A02_t01: Fail # co19-roll r607: Please triage this failure +LibTest/core/Symbol/Symbol_A01_t03: Fail # co19-roll r607: Please triage this failure +LibTest/core/Symbol/Symbol_A01_t04: Fail # co19-roll r607: Please triage this failure +LibTest/core/Symbol/Symbol_A01_t05: Fail # co19-roll r607: Please triage this failure +LibTest/isolate/isolate_api/spawnFunction_A04_t01: Timeout # Issue 13719: Please triage this failure. +LibTest/isolate/isolate_api/spawnFunction_A04_t02: Timeout # Issue 13719: Please triage this failure. +LibTest/isolate/isolate_api/spawnFunction_A04_t03: Timeout # Issue 13719: Please triage this failure. +LibTest/isolate/isolate_api/spawnUri_A01_t01: Timeout # Issue 13719: Please triage this failure. +LibTest/isolate/isolate_api/spawnUri_A01_t02: Timeout # Issue 13719: Please triage this failure. +LibTest/isolate/isolate_api/spawnUri_A01_t03: Timeout # Issue 13719: Please triage this failure. +LibTest/isolate/isolate_api/spawnUri_A01_t04: Timeout # Issue 13719: Please triage this failure. +LibTest/isolate/isolate_api/spawnUri_A01_t05: Timeout # Issue 13719: Please triage this failure. +LibTest/isolate/isolate_api/spawnUri_A02_t02: Fail # Issue 13719: Please triage this failure. +LibTest/isolate/isolate_api/spawnUri_A02_t03: Fail # Issue 13719: Please triage this failure. +LibTest/isolate/isolate_api/streamSpawnFunction_A02_t01: Timeout # Issue 13719: Please triage this failure. +LibTest/isolate/isolate_api/streamSpawnFunction_A02_t02: Timeout # Issue 13719: Please triage this failure. +LibTest/isolate/IsolateSink/addError_A01_t01: Fail # Issue 13719: Please triage this failure. +LibTest/isolate/IsolateSink/addError_A01_t02: Fail # Issue 13719: Please triage this failure. +LibTest/isolate/IsolateStream/any_A02_t01: Fail # Issue 13719: Please triage this failure. +LibTest/isolate/ReceivePort/receive_A01_t02: Fail # Issue 13719: Please triage this failure. +LibTest/isolate/SendPort/send_A01_t01: Fail # Issue 13719: Please triage this failure. +LibTest/typed_data/ByteData/elementSizeInBytes_A01_t01: Fail # Issue 13719: Please triage this failure. +LibTest/typed_data/Float32x4/clamp_A01_t01: Fail # Issue 13719: Please triage this failure. +LibTest/typed_data/Int8List/Int8List.fromList_A01_t02: Fail # Issue 13719: Please triage this failure. \ No newline at end of file
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status index 719fc5d..6796d88 100644 --- a/tests/co19/co19-runtime.status +++ b/tests/co19/co19-runtime.status
@@ -2,13 +2,13 @@ # for details. All rights reserved. Use of this source code is governed by a # BSD-style license that can be found in the LICENSE file. -[ $runtime == vm ] +[ $compiler == none && $runtime == vm ] Language/12_Expressions/01_Constants_A16_t04: fail # Issue 392 Language/12_Expressions/01_Constants_A16_t05: fail # Issue 392 - -[ $runtime == vm && $system == windows ] -LibTest/core/Stopwatch/elapsed_A01_t01: Pass, Fail # Issue 11382. -LibTest/core/Stopwatch/elapsed_A01_t03: Pass, Fail # Issue 12383. +Language/13_Statements/03_Variable_Declaration_A04_t01: MissingCompileTimeError # Issue 7052 +Language/13_Statements/03_Variable_Declaration_A04_t02: MissingCompileTimeError # Issue 7052 +Language/13_Statements/03_Variable_Declaration_A04_t05: MissingCompileTimeError # Issue 7052 +Language/13_Statements/03_Variable_Declaration_A04_t06: MissingCompileTimeError # Issue 7052 [ $compiler == none && $runtime == vm ] Language/05_Variables/1_Evaluation_of_Implicit_Variable_Getters_A01_t02: Fail # Dart issue 5802 @@ -18,7 +18,6 @@ LibTest/core/RegExp/Pattern_semantics/firstMatch_Atom_A02_t01: Fail # Issue 12508 LibTest/core/RegExp/Pattern_semantics/firstMatch_DecimalEscape_A01_t02: Fail # Issue 12508 LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A03_t01: Fail # Issue 12508 -LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterClassEscape_A04_t01: Fail # Issue 12508 LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t01: Fail # Issue 12508 LibTest/core/RegExp/Pattern_semantics/firstMatch_CharacterEscape_A06_t02: Fail # Issue 12508 LibTest/core/RegExp/Pattern_semantics/firstMatch_NonEmptyClassRanges_A01_t05: Fail # Issue 12508 @@ -70,12 +69,10 @@ Language/05_Variables/05_Variables_A06_t06: fail # Dart issue 12543 Language/05_Variables/05_Variables_A16_t02: fail # Dart issue 12544 Language/07_Classes/6_Constructors/1_Generative_Constructors_A09_t01: fail # Dart issue 12543 -Language/12_Expressions/05_Strings_A02_t46: fail # Dart issue 12547 -Language/12_Expressions/05_Strings_A02_t48: fail # Dart issue 12547 +Language/12_Expressions/00_Object_Identity/1_Object_Identity_A04_t02: fail # co19 issue 606 Language/12_Expressions/12_Instance_Creation/1_New_A06_t12: fail # Dart issue 12549 Language/12_Expressions/12_Instance_Creation/1_New_A09_t09: fail # Dart issue 1372 Language/12_Expressions/12_Instance_Creation/2_Const_A10_t01: fail # co19 issue 525 -Language/12_Expressions/14_Function_Invocation/4_Function_Expression_Invocation_A05_t01: fail # Dart issue 12550 Language/12_Expressions/15_Method_Invocation/3_Static_Invocation_A04_t09: fail # Dart issue 12549 Language/12_Expressions/30_Identifier_Reference_A08_t02: fail # Dart issue 12593 Language/12_Expressions/32_Type_Test_A04_t02: fail # co19 issue 503 @@ -86,12 +83,11 @@ Language/13_Statements/03_Variable_Declaration_A04_t07: fail # co19 issue 535 Language/13_Statements/03_Variable_Declaration_A04_t08: fail # co19 issue 535 Language/13_Statements/06_For_A01_t11: fail # Dart issue 5675 +Language/13_Statements/09_Switch_A02_t04: fail # co19 issue 605 Language/13_Statements/09_Switch_A01_t02: fail # Dart issue 12908 Language/13_Statements/12_Labels_A01_t03: fail # Dart issue 2238 -Language/14_Libraries_and_Scripts/1_Imports_A03_t27: fail # Dart issue 12915 Language/14_Libraries_and_Scripts/2_Exports_A04_t02: fail # Dart issue 12916 Language/14_Libraries_and_Scripts/2_Exports_A04_t03: fail # Dart issue 12916 -Language/14_Libraries_and_Scripts/2_Exports_A05_t01: fail # Dart issue 12918 Language/14_Libraries_and_Scripts/5_URIs_A01_t04: fail # Issue 12521 Language/14_Libraries_and_Scripts/5_URIs_A01_t05: fail # Issue 12521 Language/14_Libraries_and_Scripts/5_URIs_A01_t14: fail # Issue 12521 @@ -136,6 +132,7 @@ LibTest/typed_data/Float32x4List/skip_A01_t01: Fail # Dart issue 12861 LibTest/typed_data/Float32x4List/take_A01_t01: Fail # Dart issue 12861 LibTest/typed_data/Float32x4List/take_A02_t01: Fail # Dart issue 12861 +Language/12_Expressions/12_Instance_Creation_A01_t08: CompileTimeError # co19-roll r607: Please triage this failure [ $compiler == none && $runtime == vm && $system == windows && $mode == debug ] Language/15_Types/4_Interface_Types_A11_t01: pass, timeout # Issue 13349 @@ -146,8 +143,15 @@ LibTest/typed_data/Float32x4/clamp_A02_t01: Pass, Fail # Issue 13543 LibTest/typed_data/Float32x4/reciprocalSqrt_A01_t01: Pass, Fail # Issue 13543 LibTest/typed_data/Float32x4/reciprocal_A01_t01: Pass, Fail # Issue 13543 -LibTest/typed_data/Float32x4/toUint32x4_A01_t01: Fail # co19 Issue 601 -LibTest/typed_data/Float32x4/toUint32x4_A01_t02: Fail # co19 Issue 601 -LibTest/typed_data/Uint32x4/toFloat32x4_A01_t01: Fail # co19 Issue 601 -LibTest/typed_data/Uint32x4/toFloat32x4_A01_t02: Fail # co19 Issue 601 +Language/15_Types/3_Type_Declarations/1_Typedef_A07_t08: MissingCompileTimeError # co19-roll r607: Please triage this failure +Language/15_Types/3_Type_Declarations/1_Typedef_A07_t09: MissingCompileTimeError # co19-roll r607: Please triage this failure +LibTest/core/Invocation/positionalArguments_A01_t01: RuntimeError # co19-roll r607: Please triage this failure +LibTest/core/RegExp/Pattern_semantics/splitQueryString_A02_t01: RuntimeError # co19-roll r607: Please triage this failure +LibTest/core/Symbol/Symbol_A01_t03: RuntimeError # co19-roll r607: Please triage this failure +LibTest/core/Symbol/Symbol_A01_t05: RuntimeError # co19-roll r607: Please triage this failure + +[ $compiler == none && $runtime == vm && $mode == debug && $checked ] +LibTest/collection/LinkedList/add_A01_t01: Pass, Crash # co19-roll r607: Please triage this failure +LibTest/collection/LinkedList/iterator_current_A01_t01: Pass, Crash # co19-roll r607: Please triage this failure +LibTest/collection/LinkedList/single_A01_t01: Pass, Crash # co19-roll r607: Please triage this failure
diff --git a/tests/co19/test_config.dart b/tests/co19/test_config.dart index 547ea88..d37b5fa 100644 --- a/tests/co19/test_config.dart +++ b/tests/co19/test_config.dart
@@ -20,7 +20,8 @@ "tests/co19/co19-analyzer2.status", "tests/co19/co19-runtime.status", "tests/co19/co19-dart2dart.status", - "tests/co19/co19-dart2js.status"]); + "tests/co19/co19-dart2js.status", + "tests/co19/co19-dartium.status"]); bool isTestFile(String filename) => _testRegExp.hasMatch(filename); bool get listRecursively => true;
diff --git a/tests/compiler/dart2js/compiler_helper.dart b/tests/compiler/dart2js/compiler_helper.dart index 8af47af..3e76675 100644 --- a/tests/compiler/dart2js/compiler_helper.dart +++ b/tests/compiler/dart2js/compiler_helper.dart
@@ -148,14 +148,13 @@ element = compiler.coreLibrary.find(sourceName); } Expect.isNotNull(element, 'Could not locate $name'); - var dartType = element.computeType(compiler); switch (how) { - case 'exact': return new types.TypeMask.exact(dartType); - case 'nonNullExact': return new types.TypeMask.nonNullExact(dartType); - case 'subclass': return new types.TypeMask.subclass(dartType); - case 'nonNullSubclass': return new types.TypeMask.nonNullSubclass(dartType); - case 'subtype': return new types.TypeMask.subtype(dartType); - case 'nonNullSubtype': return new types.TypeMask.nonNullSubtype(dartType); + case 'exact': return new types.TypeMask.exact(element); + case 'nonNullExact': return new types.TypeMask.nonNullExact(element); + case 'subclass': return new types.TypeMask.subclass(element); + case 'nonNullSubclass': return new types.TypeMask.nonNullSubclass(element); + case 'subtype': return new types.TypeMask.subtype(element); + case 'nonNullSubtype': return new types.TypeMask.nonNullSubtype(element); } Expect.fail('Unknown HType constructor $how'); }
diff --git a/tests/compiler/dart2js/cpa_inference_test.dart b/tests/compiler/dart2js/cpa_inference_test.dart index ab3b4be..044d9f3 100644 --- a/tests/compiler/dart2js/cpa_inference_test.dart +++ b/tests/compiler/dart2js/cpa_inference_test.dart
@@ -1375,7 +1375,7 @@ final String source2 = r""" import 'dart:foreign'; - + main () { var x = "__dynamic_for_test".truncate(); JS('double', 'foo'); @@ -1480,24 +1480,24 @@ for (ClassElement cls in [a, b, c, d]) { Expect.equals(convert(singleton(cls)), - new TypeMask.nonNullExact(cls.rawType)); + new TypeMask.nonNullExact(cls)); } for (ClassElement cls in [a, b, c, d]) { Expect.equals(convert(singleton(cls).union(nullSingleton)), - new TypeMask.exact(cls.rawType)); + new TypeMask.exact(cls)); } Expect.equals(convert(singleton(a).union(singleton(b))), - new TypeMask.nonNullSubclass(a.rawType)); + new TypeMask.nonNullSubclass(a)); Expect.equals( convert(singleton(a).union(singleton(b)).union(nullSingleton)), - new TypeMask.subclass(a.rawType)); + new TypeMask.subclass(a)); Expect.equals( convert(singleton(b).union(singleton(d))).simplify(result.compiler), - new TypeMask.nonNullSubtype(a.rawType)); + new TypeMask.nonNullSubtype(a)); }); } @@ -1545,20 +1545,20 @@ Expect.equals( inferredType(foo).simplify(result.compiler), - new TypeMask.nonNullSubclass(abc.rawType)); + new TypeMask.nonNullSubclass(abc)); Expect.equals( - inferredType(new TypedSelector.subclass(x.rawType, foo)), - new TypeMask.nonNullExact(b.rawType)); + inferredType(new TypedSelector.subclass(x, foo)), + new TypeMask.nonNullExact(b)); Expect.equals( - inferredType(new TypedSelector.subclass(y.rawType, foo)), - new TypeMask.nonNullExact(c.rawType)); + inferredType(new TypedSelector.subclass(y, foo)), + new TypeMask.nonNullExact(c)); Expect.equals( - inferredType(new TypedSelector.subclass(z.rawType, foo)), - new TypeMask.nonNullExact(a.rawType)); + inferredType(new TypedSelector.subclass(z, foo)), + new TypeMask.nonNullExact(a)); Expect.equals( inferredType(new TypedSelector.subclass( - xy.rawType, foo)).simplify(result.compiler), - new TypeMask.nonNullSubclass(bc.rawType)); + xy, foo)).simplify(result.compiler), + new TypeMask.nonNullSubclass(bc)); Selector bar = new Selector.call(buildSourceString("bar"), null, 0);
diff --git a/tests/compiler/dart2js/dart_backend_test.dart b/tests/compiler/dart2js/dart_backend_test.dart index 508010c..5469890 100644 --- a/tests/compiler/dart2js/dart_backend_test.dart +++ b/tests/compiler/dart2js/dart_backend_test.dart
@@ -269,14 +269,14 @@ 'var globalVarInitialized=6,globalVarInitialized2=7;' 'class A{A(){}A.fromFoo(){}static staticfoo(){}foo(){}' 'static const field=5;}' - 'p_globalfoo(){}' - 'var p_globalVar;var p_globalVarInitialized=6,p_globalVarInitialized2=7;' - 'class p_A{p_A(){}p_A.p_fromFoo(){}static p_staticfoo(){}foo(){}' - 'static const p_field=5;}' - 'main(){p_globalVar;p_globalVarInitialized;' - 'p_globalVarInitialized2;p_globalfoo();' - 'p_A.p_field;p_A.p_staticfoo();' - 'new p_A();new p_A.p_fromFoo();new p_A().foo();' + 'A_globalfoo(){}' + 'var A_globalVar;var A_globalVarInitialized=6,A_globalVarInitialized2=7;' + 'class A_A{A_A(){}A_A.A_fromFoo(){}static A_staticfoo(){}foo(){}' + 'static const A_field=5;}' + 'main(){A_globalVar;A_globalVarInitialized;' + 'A_globalVarInitialized2;A_globalfoo();' + 'A_A.A_field;A_A.A_staticfoo();' + 'new A_A();new A_A.A_fromFoo();new A_A().foo();' 'globalVar;globalVarInitialized;globalVarInitialized2;globalfoo();' 'A.field;A.staticfoo();' 'new A();new A.fromFoo();new A().foo();}'; @@ -383,11 +383,11 @@ var expectedResult = 'topfoo(){}' 'class A{foo(){}}' - 'p_topfoo(){var x=5;}' - 'class p_A{num foo(){}p_A.fromFoo(){}A myliba;List<p_A> mylist;}' + 'A_topfoo(){var x=5;}' + 'class A_A{num foo(){}A_A.fromFoo(){}A myliba;List<A_A> mylist;}' 'A getA()=>null;' - 'main(){var a=new A();a.foo();var b=new p_A.fromFoo();b.foo();' - 'var GREATVAR=b.myliba;b.mylist;a=getA();p_topfoo();topfoo();}'; + 'main(){var a=new A();a.foo();var b=new A_A.fromFoo();b.foo();' + 'var GREATVAR=b.myliba;b.mylist;a=getA();A_topfoo();topfoo();}'; testDart2DartWithLibrary(mainSrc, librarySrc, continuation: (String result) { Expect.equals(expectedResult, result); }); } @@ -426,9 +426,9 @@ var expectedResult = 'get topgetset=>5;' 'set topgetset(arg){}' - 'get p_topgetset=>6;' - 'set p_topgetset(arg){}' - 'main(){p_topgetset;p_topgetset=6;topgetset;topgetset=5;}'; + 'get A_topgetset=>6;' + 'set A_topgetset(arg){}' + 'main(){A_topgetset;A_topgetset=6;topgetset;topgetset=5;}'; testDart2DartWithLibrary(mainSrc, librarySrc, continuation: (String result) { Expect.equals(expectedResult, result); }); } @@ -504,12 +504,12 @@ 'class T{}' 'class B<T>{}' 'class A<T> extends B<T>{T f;}' - 'typedef void p_MyFunction<p_T extends num>(p_T arg);' - 'class p_T{}' - 'class p_B<p_T>{}' - 'class p_A<p_T> extends p_B<p_T>{p_T f;}' - 'main(){p_MyFunction myf1;MyFunction myf2;new p_A<int>().f;' - 'new p_T();new A<int>().f;new T();}'; + 'typedef void A_MyFunction<A_T extends num>(A_T arg);' + 'class A_T{}' + 'class A_B<A_T>{}' + 'class A_A<A_T> extends A_B<A_T>{A_T f;}' + 'main(){A_MyFunction myf1;MyFunction myf2;new A_A<int>().f;' + 'new A_T();new A<int>().f;new T();}'; testDart2DartWithLibrary(mainSrc, librarySrc, continuation: (String result) { Expect.equals(expectedResult, result); }); } @@ -536,9 +536,9 @@ var expectedResult = 'class I{}' 'class A<T extends I>{}' - 'class p_I{}' - 'class p_A<p_T extends p_I>{}' - 'main(){new p_A();new A();}'; + 'class A_I{}' + 'class A_A<A_T extends A_I>{}' + 'main(){new A_A();new A();}'; testDart2DartWithLibrary(mainSrc, librarySrc, continuation: (String result) { Expect.equals(expectedResult, result); }); } @@ -555,8 +555,8 @@ } '''; var expectedResult = - 'p_main(){}' - 'main(){p_main();}'; + 'A_main(){}' + 'main(){A_main();}'; testDart2DartWithLibrary(mainSrc, librarySrc, continuation: (String result) { Expect.equals(expectedResult, result); }); } @@ -667,8 +667,8 @@ } '''; var expectedResult = 'import "dart:html" as p;' - 'class A{static String get p_userAgent=>p.window.navigator.userAgent;}' - 'main(){A.p_userAgent;}'; + 'class A{static String get A_userAgent=>p.window.navigator.userAgent;}' + 'main(){A.A_userAgent;}'; testDart2Dart(src, continuation: (String result) { Expect.equals(expectedResult, result); }); } @@ -684,8 +684,8 @@ print('local'); } '''; - var expectedResult = "p_print(x){throw 'fisk';}" - "main(){print('corelib');p_print('local');}"; + var expectedResult = "A_print(x){throw 'fisk';}" + "main(){print('corelib');A_print('local');}"; testDart2Dart(src, continuation: (String result) { Expect.equals(expectedResult, result); }); } @@ -701,7 +701,7 @@ new A.named(); } '''; - var expectedResult = "class A{A(){}}main(){new A();new p_Unresolved();}"; + var expectedResult = "class A{A(){}}main(){new A();new A_Unresolved();}"; testDart2Dart(src, continuation: (String result) { Expect.equals(expectedResult, result); }); }
diff --git a/tests/compiler/dart2js/field_type_simple_inferer_test.dart b/tests/compiler/dart2js/field_type_simple_inferer_test.dart index 4aee0ac..7961fe6 100644 --- a/tests/compiler/dart2js/field_type_simple_inferer_test.dart +++ b/tests/compiler/dart2js/field_type_simple_inferer_test.dart
@@ -515,7 +515,7 @@ runTest(TEST_15, {'f': (compiler) { ClassElement cls = compiler.typesTask.compiler.backend.jsIndexableClass; - return new TypeMask.nonNullSubtype(cls.rawType); + return new TypeMask.nonNullSubtype(cls); }}); runTest(TEST_16, {'f': subclassOfInterceptor}); runTest(TEST_17, {'f': (compiler) => compiler.typesTask.intType.nullable()});
diff --git a/tests/compiler/dart2js/licm_test.dart b/tests/compiler/dart2js/licm_test.dart index 0b16cba..3e1a98a 100644 --- a/tests/compiler/dart2js/licm_test.dart +++ b/tests/compiler/dart2js/licm_test.dart
@@ -25,6 +25,6 @@ '''; main() { - compileAndMatch( - TEST, 'main', new RegExp("if \\(count == null\\)(.|\\n)*while")); + compileAndMatch(TEST, 'main', + new RegExp('if \\(typeof count !== "number"\\)(.|\\n)*while')); }
diff --git a/tests/compiler/dart2js/list_tracer_node_type_test.dart b/tests/compiler/dart2js/list_tracer_node_type_test.dart index dfefd9b..4296d74 100644 --- a/tests/compiler/dart2js/list_tracer_node_type_test.dart +++ b/tests/compiler/dart2js/list_tracer_node_type_test.dart
@@ -68,26 +68,19 @@ main() { asyncTest(() => compileAll(TEST1).then((generated) { - // Check that we only do a null check on the receiver for - // [: a[0] + 42 :]. We can do a null check because we inferred that - // the list is of type int or null. - Expect.isFalse(generated.contains('if (typeof t1')); - Expect.isTrue(generated.contains('if (t1 == null)')); + Expect.isTrue(generated.contains('if (typeof t1')); })); asyncTest(() => compileAll(TEST2).then((generated) { - Expect.isFalse(generated.contains('if (typeof t1')); - Expect.isTrue(generated.contains('if (t1 == null)')); + Expect.isTrue(generated.contains('if (typeof t1')); })); asyncTest(() => compileAll(TEST3).then((generated) { - Expect.isFalse(generated.contains('if (typeof t1')); - Expect.isTrue(generated.contains('if (t1 == null)')); + Expect.isTrue(generated.contains('if (typeof t1')); })); asyncTest(() => compileAll(TEST4).then((generated) { - Expect.isFalse(generated.contains('if (typeof t1')); - Expect.isTrue(generated.contains('if (t1 == null)')); + Expect.isTrue(generated.contains('if (typeof t1')); })); asyncTest(() => compileAll(TEST5).then((generated) {
diff --git a/tests/compiler/dart2js/list_tracer_test.dart b/tests/compiler/dart2js/list_tracer_test.dart index 936dd17..5668c63 100644 --- a/tests/compiler/dart2js/list_tracer_test.dart +++ b/tests/compiler/dart2js/list_tracer_test.dart
@@ -222,12 +222,13 @@ checkType('listPassedToClosure', typesTask.dynamicType); checkType('listReturnedFromClosure', typesTask.dynamicType); checkType('listUsedWithNonOkSelector', typesTask.dynamicType); - checkType('listPassedAsOptionalParameter', typesTask.dynamicType); - checkType('listPassedAsNamedParameter', typesTask.dynamicType); + checkType('listPassedAsOptionalParameter', typesTask.numType); + checkType('listPassedAsNamedParameter', typesTask.numType); if (!allocation.contains('filled')) { checkType('listUnset', new TypeMask.nonNullEmpty()); - checkType('listOnlySetWithConstraint', new TypeMask.nonNullEmpty()); + // TODO(ngeoffray): Re-enable this test. + // checkType('listOnlySetWithConstraint', new TypeMask.nonNullEmpty()); } })); }
diff --git a/tests/compiler/dart2js/mirrors_used_test.dart b/tests/compiler/dart2js/mirrors_used_test.dart index 065da51..1f25936 100644 --- a/tests/compiler/dart2js/mirrors_used_test.dart +++ b/tests/compiler/dart2js/mirrors_used_test.dart
@@ -92,20 +92,14 @@ }); } - // There should at least be three metadata constants: - // 1. The type literal 'Foo'. - // 2. The list 'const [Foo]'. - // 3. The constructed constant for 'MirrorsUsed'. - Expect.isTrue(compiler.metadataHandler.compiledConstants.length >= 3); + // There should at least be one metadata constant: + // 1. The constructed constant for 'MirrorsUsed'. + Expect.isTrue(compiler.backend.metadataConstants.length >= 1); // Make sure that most of the metadata constants aren't included in the // generated code. - for (Constant constant in compiler.metadataHandler.compiledConstants) { - if (constant is TypeConstant && '${constant.representedType}' == 'Foo') { - // The type literal 'Foo' is retained as a constant because it is being - // passed to reflectClass. - continue; - } + for (var dependency in compiler.backend.metadataConstants) { + Constant constant = dependency.constant; Expect.isFalse( compiler.constantHandler.compiledConstants.contains(constant), '$constant'); @@ -114,7 +108,7 @@ // The type literal 'Foo' is both used as metadata, and as a plain value in // the program. Make sure that it isn't duplicated. int fooConstantCount = 0; - for (Constant constant in compiler.metadataHandler.compiledConstants) { + for (Constant constant in compiler.constantHandler.compiledConstants) { if (constant is TypeConstant && '${constant.representedType}' == 'Foo') { fooConstantCount++; }
diff --git a/tests/compiler/dart2js/mock_compiler.dart b/tests/compiler/dart2js/mock_compiler.dart index 5fb2d85..73eea5c 100644 --- a/tests/compiler/dart2js/mock_compiler.dart +++ b/tests/compiler/dart2js/mock_compiler.dart
@@ -250,6 +250,7 @@ // Set up the library imports. importHelperLibrary(coreLibrary); libraryLoader.importLibrary(jsHelperLibrary, coreLibrary, null); + libraryLoader.importLibrary(foreignLibrary, coreLibrary, null); libraryLoader.importLibrary(interceptorsLibrary, coreLibrary, null); libraryLoader.importLibrary(isolateHelperLibrary, coreLibrary, null);
diff --git a/tests/compiler/dart2js/patch_test.dart b/tests/compiler/dart2js/patch_test.dart index 9881810..34bf187 100644 --- a/tests/compiler/dart2js/patch_test.dart +++ b/tests/compiler/dart2js/patch_test.dart
@@ -730,7 +730,7 @@ // typed selector. var selector = new Selector.call( buildSourceString('method'), compiler.coreLibrary, 0); - var typedSelector = new TypedSelector.exact(cls.rawType, selector); + var typedSelector = new TypedSelector.exact(cls, selector); Element method = cls.implementation.lookupLocalMember(buildSourceString('method')); Expect.isTrue(selector.applies(method, compiler)); @@ -740,7 +740,7 @@ // for a typed selector. selector = new Selector.call( buildSourceString('clear'), compiler.coreLibrary, 0); - typedSelector = new TypedSelector.exact(cls.rawType, selector); + typedSelector = new TypedSelector.exact(cls, selector); method = cls.lookupLocalMember(buildSourceString('clear')); Expect.isTrue(selector.applies(method, compiler)); Expect.isTrue(typedSelector.applies(method, compiler)); @@ -749,7 +749,7 @@ // for a typed selector on a subclass. cls = ensure(compiler, "B", compiler.coreLibrary.find); cls.ensureResolved(compiler); - typedSelector = new TypedSelector.exact(cls.rawType, selector); + typedSelector = new TypedSelector.exact(cls, selector); Expect.isTrue(selector.applies(method, compiler)); Expect.isTrue(typedSelector.applies(method, compiler)); }));
diff --git a/tests/compiler/dart2js/simple_inferrer_closure_test.dart b/tests/compiler/dart2js/simple_inferrer_closure_test.dart index a8093aa..4746044 100644 --- a/tests/compiler/dart2js/simple_inferrer_closure_test.dart +++ b/tests/compiler/dart2js/simple_inferrer_closure_test.dart
@@ -145,6 +145,6 @@ typesInferrer.getReturnTypeOfElement(element).simplify(compiler)); } var cls = findElement(compiler, 'A'); - checkReturnInClass('A', 'foo', new TypeMask.nonNullExact(cls.rawType)); + checkReturnInClass('A', 'foo', new TypeMask.nonNullExact(cls)); })); }
diff --git a/tests/compiler/dart2js/simple_inferrer_test.dart b/tests/compiler/dart2js/simple_inferrer_test.dart index 45b882a..879f819 100644 --- a/tests/compiler/dart2js/simple_inferrer_test.dart +++ b/tests/compiler/dart2js/simple_inferrer_test.dart
@@ -505,6 +505,39 @@ return a; } +testReturnNull1(a) { + if (a == null) return a; + return null; +} + +testReturnNull2(a) { + if (a != null) return null; + return a; +} + +testReturnNull3(a) { + if (a == null) return 42; + return a; +} + +testReturnNull4() { + var a = topLeveGetter(); + if (a == null) return a; + return null; +} + +testReturnNull5() { + var a = topLeveGetter(); + if (a != null) return null; + return a; +} + +testReturnNull6() { + var a = topLeveGetter(); + if (a == null) return 42; + return a; +} + testReturnInvokeDynamicGetter() => new A().myFactory(); var topLevelConstList = const [42]; @@ -656,6 +689,12 @@ testSpecialization1(); testSpecialization2(); testSpecialization3(); + testReturnNull1(topLevelGetter()); + testReturnNull2(topLevelGetter()); + testReturnNull3(topLevelGetter()); + testReturnNull4(); + testReturnNull5(); + testReturnNull6(); } """; @@ -692,7 +731,7 @@ checkReturn('returnInt8', typesTask.intType); checkReturn('returnEmpty1', const TypeMask.nonNullEmpty()); checkReturn('returnEmpty2', const TypeMask.nonNullEmpty()); - TypeMask intType = new TypeMask.nonNullSubtype(compiler.intClass.rawType); + TypeMask intType = new TypeMask.nonNullSubtype(compiler.intClass); checkReturn('testIsCheck1', intType); checkReturn('testIsCheck2', intType); checkReturn('testIsCheck3', intType.nullable()); @@ -725,7 +764,7 @@ checkReturn('testIf1', typesTask.intType.nullable()); checkReturn('testIf2', typesTask.intType.nullable()); checkReturn('returnAsString', - new TypeMask.subtype(compiler.stringClass.computeType(compiler))); + new TypeMask.subtype(compiler.stringClass)); checkReturn('returnIntAsNum', typesTask.intType); checkReturn('returnAsTypedef', typesTask.functionType.nullable()); checkReturn('returnTopLevelGetter', typesTask.intType); @@ -780,16 +819,22 @@ checkFactoryConstructor(String className, String factoryName) { var cls = findElement(compiler, className); var element = cls.localLookup(buildSourceString(factoryName)); - Expect.equals(new TypeMask.nonNullExact(cls.rawType), + Expect.equals(new TypeMask.nonNullExact(cls), typesInferrer.getReturnTypeOfElement(element)); } checkFactoryConstructor('A', ''); checkReturn('testCascade1', typesTask.growableListType); checkReturn('testCascade2', new TypeMask.nonNullExact( - findElement(compiler, 'CascadeHelper').rawType)); + findElement(compiler, 'CascadeHelper'))); checkReturn('testSpecialization1', typesTask.numType); checkReturn('testSpecialization2', typesTask.dynamicType); checkReturn('testSpecialization3', typesTask.intType.nullable()); + checkReturn('testReturnNull1', typesTask.nullType); + checkReturn('testReturnNull2', typesTask.nullType); + checkReturn('testReturnNull3', typesTask.dynamicType); + checkReturn('testReturnNull4', typesTask.nullType); + checkReturn('testReturnNull5', typesTask.nullType); + checkReturn('testReturnNull6', typesTask.dynamicType); })); }
diff --git a/tests/compiler/dart2js/simple_inferrer_try_catch_test.dart b/tests/compiler/dart2js/simple_inferrer_try_catch_test.dart index aa29c72..55ed3a7 100644 --- a/tests/compiler/dart2js/simple_inferrer_try_catch_test.dart +++ b/tests/compiler/dart2js/simple_inferrer_try_catch_test.dart
@@ -183,7 +183,7 @@ checkReturn('returnInt4', typesTask.intType); checkReturn('returnInt5', typesTask.intType); checkReturn('returnInt6', - new TypeMask.nonNullSubtype(compiler.intClass.rawType)); + new TypeMask.nonNullSubtype(compiler.intClass)); var subclassOfInterceptor = findTypeMask(compiler, 'Interceptor', 'nonNullSubclass');
diff --git a/tests/compiler/dart2js/type_combination_test.dart b/tests/compiler/dart2js/type_combination_test.dart index f1a1366..8947932 100644 --- a/tests/compiler/dart2js/type_combination_test.dart +++ b/tests/compiler/dart2js/type_combination_test.dart
@@ -518,7 +518,7 @@ rule(jsIndexable, nonPrimitive1, CONFLICTING); rule(jsIndexable, nonPrimitive2, CONFLICTING); rule(jsIndexable, potentialArray, new HType.nonNullSubtype( - compiler.backend.jsArrayClass.computeType(compiler), compiler)); + compiler.backend.jsArrayClass, compiler)); rule(jsIndexable, potentialString, jsString); rule(jsIndexable, BOOLEAN_OR_NULL, CONFLICTING); rule(jsIndexable, NUMBER_OR_NULL, CONFLICTING); @@ -668,7 +668,7 @@ void testRegressions(MockCompiler compiler) { HType nonNullPotentialString = new HType.nonNullSubtype( - patternClass.computeType(compiler), compiler); + patternClass, compiler); Expect.equals( potentialString, jsStringOrNull.union(nonNullPotentialString, compiler)); } @@ -690,41 +690,41 @@ patternClass = compiler.coreLibrary.find(buildSourceString('Pattern')); nonPrimitive1 = new HType.nonNullSubtype( - compiler.mapClass.computeType(compiler), compiler); + compiler.mapClass, compiler); nonPrimitive2 = new HType.nonNullSubtype( - compiler.functionClass.computeType(compiler), compiler); + compiler.functionClass, compiler); potentialArray = new HType.subtype( - compiler.listClass.computeType(compiler), compiler); + compiler.listClass, compiler); potentialString = new HType.subtype( - patternClass.computeType(compiler), compiler); + patternClass, compiler); jsInterceptor = new HType.nonNullSubclass( - compiler.backend.jsInterceptorClass.computeType(compiler), compiler); + compiler.backend.jsInterceptorClass, compiler); jsArrayOrNull = new HType.subclass( - compiler.backend.jsArrayClass.computeType(compiler), compiler); + compiler.backend.jsArrayClass, compiler); jsReadableArray = new HType.nonNullSubclass( - compiler.backend.jsArrayClass.computeType(compiler), compiler); + compiler.backend.jsArrayClass, compiler); jsMutableArrayOrNull = new HType.subclass( - compiler.backend.jsMutableArrayClass.computeType(compiler), compiler); + compiler.backend.jsMutableArrayClass, compiler); jsMutableArray = new HType.nonNullSubclass( - compiler.backend.jsMutableArrayClass.computeType(compiler), compiler); + compiler.backend.jsMutableArrayClass, compiler); jsFixedArrayOrNull = new HType.exact( - compiler.backend.jsFixedArrayClass.computeType(compiler), compiler); + compiler.backend.jsFixedArrayClass, compiler); jsFixedArray = new HType.nonNullExact( - compiler.backend.jsFixedArrayClass.computeType(compiler), compiler); + compiler.backend.jsFixedArrayClass, compiler); jsExtendableArrayOrNull = new HType.exact( - compiler.backend.jsExtendableArrayClass.computeType(compiler), compiler); + compiler.backend.jsExtendableArrayClass, compiler); jsExtendableArray = new HType.nonNullExact( - compiler.backend.jsExtendableArrayClass.computeType(compiler), compiler); + compiler.backend.jsExtendableArrayClass, compiler); jsIndexableOrNull = new HType.subtype( - compiler.backend.jsIndexableClass.computeType(compiler), compiler); + compiler.backend.jsIndexableClass, compiler); jsIndexable = new HType.nonNullSubtype( - compiler.backend.jsIndexableClass.computeType(compiler), compiler); + compiler.backend.jsIndexableClass, compiler); jsInterceptorOrNull = new HType.subclass( - compiler.backend.jsInterceptorClass.computeType(compiler), compiler); + compiler.backend.jsInterceptorClass, compiler); jsStringOrNull = new HType.exact( - compiler.backend.jsStringClass.computeType(compiler), compiler); + compiler.backend.jsStringClass, compiler); jsString = new HType.nonNullExact( - compiler.backend.jsStringClass.computeType(compiler), compiler); + compiler.backend.jsStringClass, compiler); testUnion(compiler); testIntersection(compiler);
diff --git a/tests/compiler/dart2js/type_representation_test.dart b/tests/compiler/dart2js/type_representation_test.dart index 5e6b7c5..e222971 100644 --- a/tests/compiler/dart2js/type_representation_test.dart +++ b/tests/compiler/dart2js/type_representation_test.dart
@@ -94,7 +94,7 @@ // List expect('$List_rep', List_.rawType); // List<dynamic> - expect('[$List_rep, null]', instantiate(List_, [dynamic_])); + expect('$List_rep', instantiate(List_, [dynamic_])); // List<int> expect('[$List_rep, $int_rep]', instantiate(List_, [int_])); // List<Typedef> @@ -102,11 +102,12 @@ instantiate(List_, [Typedef_])); // Map<K,V> - expect('[$Map_rep, $Map_K_rep, $Map_V_rep]', Map_.computeType(env.compiler)); + expect('[$Map_rep, $Map_K_rep, $Map_V_rep]', + Map_.computeType(env.compiler)); // Map expect('$Map_rep', Map_.rawType); // Map<dynamic,dynamic> - expect('[$Map_rep, null, null]', instantiate(Map_, [dynamic_, dynamic_])); + expect('$Map_rep', instantiate(Map_, [dynamic_, dynamic_])); // Map<int,String> expect('[$Map_rep, $int_rep, $String_rep]', instantiate(Map_, [int_, String_]));
diff --git a/tests/compiler/dart2js/union_type_test.dart b/tests/compiler/dart2js/union_type_test.dart index 2b48e04..7cc13ba 100644 --- a/tests/compiler/dart2js/union_type_test.dart +++ b/tests/compiler/dart2js/union_type_test.dart
@@ -15,9 +15,9 @@ compiler.stringClass.ensureResolved(compiler); FlatTypeMask mask1 = - new FlatTypeMask.exact(new InterfaceType(compiler.intClass)); + new FlatTypeMask.exact(compiler.intClass); FlatTypeMask mask2 = - new FlatTypeMask.exact(new InterfaceType(compiler.stringClass)); + new FlatTypeMask.exact(compiler.stringClass); UnionTypeMask union1 = mask1.nonNullable().union(mask2, compiler); UnionTypeMask union2 = mask2.nonNullable().union(mask1, compiler); Expect.equals(union1, union2);
diff --git a/tests/compiler/dart2js_extra/field_initializer_test.dart b/tests/compiler/dart2js_extra/field_initializer_test.dart index cb4a34b..b06f763 100644 --- a/tests/compiler/dart2js_extra/field_initializer_test.dart +++ b/tests/compiler/dart2js_extra/field_initializer_test.dart
@@ -15,7 +15,7 @@ static const i = false; static const j = n; static const k = 4.99; - static const l; + static const l = null; static const m = l; static const n = 42; }
diff --git a/tests/corelib/corelib.status b/tests/corelib/corelib.status index 2c2c7b9..7902d5a 100644 --- a/tests/corelib/corelib.status +++ b/tests/corelib/corelib.status
@@ -81,6 +81,7 @@ int_parse_radix_test: fail list_insert_test: fail list_removeat_test: fail +symbol_test/01: fail # test issue 13730; It is static type warning if "const" instance creation argument type is not compatible with parameter type [ $compiler == dart2analyzer ] symbol_test/02: Fail
diff --git a/tests/html/custom/attribute_changed_callback_test.dart b/tests/html/custom/attribute_changed_callback_test.dart index 955399f..3a9271a 100644 --- a/tests/html/custom/attribute_changed_callback_test.dart +++ b/tests/html/custom/attribute_changed_callback_test.dart
@@ -3,13 +3,17 @@ // BSD-style license that can be found in the LICENSE file. library attribute_changed_callback_test; -import 'package:unittest/unittest.dart'; -import 'package:unittest/html_config.dart'; + import 'dart:html'; +import 'dart:js' as js; +import 'package:unittest/html_individual_config.dart'; +import 'package:unittest/unittest.dart'; +import '../utils.dart'; class A extends HtmlElement { static final tag = 'x-a'; factory A() => new Element.tag(tag); + A.created() : super.created(); static var attributeChangedInvocations = 0; @@ -21,10 +25,11 @@ class B extends HtmlElement { static final tag = 'x-b'; factory B() => new Element.tag(tag); + B.created() : super.created(); static var invocations = []; - void created() { + void createdCallback() { invocations.add('created'); } @@ -33,44 +38,75 @@ } } +// Pump custom events polyfill events. +void customElementsTakeRecords() { + if (js.context.hasProperty('CustomElements')) { + js.context['CustomElements'].callMethod('takeRecords'); + } +} + main() { - useHtmlConfiguration(); + useHtmlIndividualConfiguration(); // Adapted from Blink's fast/dom/custom/attribute-changed-callback test. - test('transfer attribute changed callback', () { - document.register(A.tag, A); - var element = new A(); - - element.attributes['a'] = 'b'; - expect(A.attributeChangedInvocations, 1); + var registered = false; + setUp(() { + return loadPolyfills().then((_) { + if (!registered) { + registered = true; + document.register(A.tag, A); + document.register(B.tag, B); + } + }); }); - test('add, change and remove an attribute', () { - document.register(B.tag, B); - var b = new B(); - b.id = 'x'; - expect(B.invocations, ['created', 'id: null => x']); + group('fully_supported', () { + test('transfer attribute changed callback', () { + var element = new A(); - B.invocations = []; - b.attributes.remove('id'); - expect(B.invocations, ['id: x => null']); + element.attributes['a'] = 'b'; + expect(A.attributeChangedInvocations, 1); + }); - B.invocations = []; - b.attributes['data-s'] = 't'; - expect(B.invocations, ['data-s: null => t']); + test('add, change and remove an attribute', () { + var b = new B(); - B.invocations = []; - b.classList.toggle('u'); - expect(B.invocations, ['class: null => u']); + B.invocations = []; + b.attributes['data-s'] = 't'; + expect(B.invocations, ['data-s: null => t']); - b.attributes['data-v'] = 'w'; - B.invocations = []; - b.attributes['data-v'] = 'x'; - expect(B.invocations, ['data-v: w => x']); + b.attributes['data-v'] = 'w'; + B.invocations = []; + b.attributes['data-v'] = 'x'; + expect(B.invocations, ['data-v: w => x']); - B.invocations = []; - b.attributes['data-v'] = 'x'; - expect(B.invocations, []); + B.invocations = []; + b.attributes['data-v'] = 'x'; + expect(B.invocations, []); + + b.attributes.remove('data-v'); + expect(B.invocations, ['data-v: x => null']); + }); + }); + + group('unsupported_on_polyfill', () { + test('add, change ID', () { + var b = new B(); + b.id = 'x'; + expect(B.invocations, ['created', 'id: null => x']); + + B.invocations = []; + b.attributes.remove('id'); + expect(B.invocations, ['id: x => null']); + }); + + test('add, change classes', () { + var b = new B(); + + B.invocations = []; + b.classes.toggle('u'); + expect(B.invocations, ['class: null => u']); + }); }); }
diff --git a/tests/html/custom/constructor_calls_created_synchronously_test.dart b/tests/html/custom/constructor_calls_created_synchronously_test.dart index edd689a..2238df6 100644 --- a/tests/html/custom/constructor_calls_created_synchronously_test.dart +++ b/tests/html/custom/constructor_calls_created_synchronously_test.dart
@@ -7,14 +7,16 @@ import 'package:unittest/html_config.dart'; import 'dart:html'; import '../utils.dart'; +import 'dart:mirrors'; class A extends HtmlElement { static final tag = 'x-a'; factory A() => new Element.tag(tag); + A.created() : super.created(); static int ncallbacks = 0; - void created() { + void createdCallback() { ncallbacks++; } }
diff --git a/tests/html/custom/created_callback_test.dart b/tests/html/custom/created_callback_test.dart index ebd3fba..dfcd28f 100644 --- a/tests/html/custom/created_callback_test.dart +++ b/tests/html/custom/created_callback_test.dart
@@ -6,15 +6,17 @@ import 'package:unittest/unittest.dart'; import 'package:unittest/html_config.dart'; import 'dart:html'; +import 'dart:js' as js; import '../utils.dart'; class A extends HtmlElement { static final tag = 'x-a'; factory A() => new Element.tag(tag); + A.created() : super.created(); static int createdInvocations = 0; - void created() { + void createdCallback() { createdInvocations++; } } @@ -22,16 +24,18 @@ class B extends HtmlElement { static final tag = 'x-b'; factory B() => new Element.tag(tag); + B.created() : super.created(); } class C extends HtmlElement { static final tag = 'x-c'; factory C() => new Element.tag(tag); + C.created() : super.created(); static int createdInvocations = 0; static var div; - void created() { + void createdCallback() { createdInvocations++; if (this.id != 'u') { @@ -60,7 +64,17 @@ // Adapted from Blink's // fast/dom/custom/created-callback test. - setUp(loadPolyfills); + var registered = false; + setUp(() { + return loadPolyfills().then((_) { + if (!registered) { + registered = true; + document.register(B.tag, B); + document.register(C.tag, C); + ErrorConstructorElement.register(); + } + }); + }); test('transfer created callback', () { document.register(A.tag, A); @@ -68,10 +82,7 @@ expect(A.createdInvocations, 1); }); - test(':unresolved and created callback timing', () { - document.register(B.tag, B); - document.register(C.tag, C); - + test('unresolved and created callback timing', () { var div = new DivElement(); C.div = div; div.setInnerHtml(""" @@ -87,6 +98,194 @@ expect(div.query('#w') is B, isTrue); }); + test('nesting of constructors', NestedElement.test); + + test('access while upgrading gets unupgraded element', + AccessWhileUpgradingElement.test); + + test('cannot call created constructor', () { + expect(() { + new B.created(); + }, throws); + }); + + test('cannot register without created', () { + expect(() { + document.register(MissingCreatedElement.tag, MissingCreatedElement); + }, throws); + }); + + test('throw on createElement does not upgrade', () { + ErrorConstructorElement.callCount = 0; + + var e; + expectGlobalError(() { + e = new Element.tag(ErrorConstructorElement.tag); + }); + expect(ErrorConstructorElement.callCount, 1); + expect(e is HtmlElement, isTrue); + expect(e is ErrorConstructorElement, isFalse); + + var dummy = new DivElement(); + dummy.append(e); + e = dummy.firstChild; + expect(ErrorConstructorElement.callCount, 1); + }); + + test('throw on innerHtml does not upgrade', () { + ErrorConstructorElement.callCount = 0; + + var dummy = new DivElement(); + var tag = ErrorConstructorElement.tag; + expectGlobalError(() { + dummy.setInnerHtml('<$tag></$tag>', + treeSanitizer: new NullTreeSanitizer()); + }); + + expect(ErrorConstructorElement.callCount, 1); + + var e = dummy.firstChild; + // Accessing should not re-run the constructor. + expect(ErrorConstructorElement.callCount, 1); + expect(e is HtmlElement, isTrue); + expect(e is ErrorConstructorElement, isFalse); + }); + + // Issue - 13711 Need to fix the handling of the created constructor. + // test('created cannot be called from nested constructor', + // NestedCreatedConstructorElement.test); + + // TODO(vsm): Port additional test from upstream here: // http://src.chromium.org/viewvc/blink/trunk/LayoutTests/fast/dom/custom/created-callback.html?r1=156141&r2=156185 } + + +class NestedElement extends HtmlElement { + static final tag = 'x-nested'; + + final Element b = new B(); + + factory NestedElement() => new Element.tag(tag); + NestedElement.created() : super.created(); + + static void register() { + document.register(tag, NestedElement); + } + + static void test() { + register(); + + var e = new NestedElement(); + expect(e.b, isNotNull); + expect(e.b is B, isTrue); + expect(e is NestedElement, isTrue); + } +} + + +class AccessWhileUpgradingElement extends HtmlElement { + static final tag = 'x-access-while-upgrading'; + + static Element upgradingContext; + static Element upgradingContextChild; + + final foo = runInitializerCode(); + + factory AccessWhileUpgradingElement() => new Element.tag(tag); + AccessWhileUpgradingElement.created() : super.created(); + + static runInitializerCode() { + upgradingContextChild = upgradingContext.firstChild; + + return 666; + } + + static void register() { + document.register(tag, AccessWhileUpgradingElement); + } + + static void test() { + register(); + + upgradingContext = new DivElement(); + upgradingContext.setInnerHtml('<$tag></$tag>', + treeSanitizer: new NullTreeSanitizer()); + var child = upgradingContext.firstChild; + + expect(child.foo, 666); + expect(upgradingContextChild is HTMLElement, isTrue); + expect(upgradingContextChild is AccessWhileUpgradingElement, isFalse, + reason: 'Elements accessed while upgrading should not be upgraded.'); + } +} + +class MissingCreatedElement extends HtmlElement { + static final tag = 'x-missing-created'; + + factory MissingCreatedElement() => new Element.tag(tag); +} + +class ErrorConstructorElement extends HtmlElement { + static final tag = 'x-throws-in-constructor'; + static int callCount = 0; + + factory ErrorConstructorElement() => new Element.tag(tag); + + ErrorConstructorElement.created() : super.created() { + ++callCount; + throw new Exception('Just messin with ya'); + } + + static void register() { + document.register(tag, ErrorConstructorElement); + } +} + +class NestedCreatedConstructorElement extends HtmlElement { + static final tag = 'x-nested-created-constructor'; + + // Should not be able to call this here. + final B b = constructB(); + static B constructedB; + + factory NestedCreatedConstructorElement() => new Element.tag(tag); + NestedCreatedConstructorElement.created() : super.created(); + + static void register() { + document.register(tag, NestedCreatedConstructorElement); + } + + // Try to run the created constructor, and record the results. + static constructB() { + // This should throw an exception. + constructedB = new B.created(); + return constructedB; + } + + static void test() { + register(); + + // Exception should have occurred on upgrade. + var e = new Element.tag(tag); + expect(e is NestedCreatedConstructorElement, isFalse); + expect(e is HtmlElement, isTrue); + // Should not have been set. + expect(constructedB, isNull); + } +} + +void expectGlobalError(Function test) { + js.context['testExpectsGlobalError'] = true; + try { + test(); + } catch(e) { + rethrow; + } finally { + js.context['testExpectsGlobalError'] = false; + } + var errors = js.context['testSuppressedGlobalErrors']; + expect(errors['length'], 1); + // Clear out the errors; + js.context['testSuppressedGlobalErrors']['length'] = 0; +}
diff --git a/tests/html/custom/document_register_basic_test.dart b/tests/html/custom/document_register_basic_test.dart index c8964e5..7e094e8b 100644 --- a/tests/html/custom/document_register_basic_test.dart +++ b/tests/html/custom/document_register_basic_test.dart
@@ -11,6 +11,7 @@ class Foo extends HtmlElement { static final tag = 'x-foo'; factory Foo() => new Element.tag(tag); + Foo.created() : super.created(); get thisIsACustomClass => true; } @@ -18,6 +19,7 @@ class Bar extends HtmlElement { static final tag = 'x-bar'; factory Bar() => new Element.tag(tag); + Bar.created() : super.created(); get thisIsACustomClass => true; } @@ -25,6 +27,7 @@ class Baz extends Foo { static final tag = 'x-baz'; factory Baz() => new Element.tag(tag); + Baz.created() : super.created(); get thisIsAlsoACustomClass => true; }
diff --git a/tests/html/custom/document_register_type_extensions_test.dart b/tests/html/custom/document_register_type_extensions_test.dart index 79b036d..3f43234 100644 --- a/tests/html/custom/document_register_type_extensions_test.dart +++ b/tests/html/custom/document_register_type_extensions_test.dart
@@ -14,12 +14,14 @@ '<x-foo></x-foo>', '<?XML:NAMESPACE PREFIX = PUBLIC NS = "URN:COMPONENT" /><x-foo></x-foo>']; factory Foo() => new Element.tag(tag); + Foo.created() : super.created(); } class Bar extends InputElement { static const tag = 'x-bar'; static const outerHtmlString = '<input is="x-bar">'; factory Bar() => new Element.tag('input', tag); + Bar.created() : super.created(); } class Baz extends Foo { @@ -28,16 +30,19 @@ '<x-baz></x-baz>', '<?XML:NAMESPACE PREFIX = PUBLIC NS = "URN:COMPONENT" /><x-baz></x-baz>']; factory Baz() => new Element.tag(tag); + Baz.created() : super.created(); } class Qux extends Bar { static const tag = 'x-qux'; factory Qux() => new Element.tag('input', tag); + Qux.created() : super.created(); } class FooBad extends DivElement { static const tag = 'x-foo'; factory FooBad() => new Element.tag('div', tag); + FooBad.created() : super.created(); } main() {
diff --git a/tests/html/custom/entered_left_view_test.dart b/tests/html/custom/entered_left_view_test.dart index 79f65c8..a523854 100644 --- a/tests/html/custom/entered_left_view_test.dart +++ b/tests/html/custom/entered_left_view_test.dart
@@ -14,8 +14,9 @@ var invocations = []; class Foo extends HtmlElement { factory Foo() => null; + Foo.created() : super.created(); - void created() { + void createdCallback() { invocations.add('created'); } @@ -27,7 +28,7 @@ invocations.add('left'); } - void attributeChanged() { + void attributeChanged(String name, String oldValue, String newValue) { invocations.add('attribute changed'); } } @@ -62,7 +63,7 @@ }); group('standard_events', () { - var a = new Element.tag('x-a'); + var a; setUp(() { invocations = []; }); @@ -105,7 +106,7 @@ }); group('viewless_document', () { - var a = docB.createElement('x-a'); + var a; setUp(() { invocations = []; });
diff --git a/tests/html/custom_elements_test.dart b/tests/html/custom_elements_test.dart index 3ad83a1..718898c 100644 --- a/tests/html/custom_elements_test.dart +++ b/tests/html/custom_elements_test.dart
@@ -19,8 +19,10 @@ class CustomType extends HtmlElement with CustomMixin{ factory CustomType() => null; + CustomType.created(): super.created(); + bool createdCalled; // = false; - void created() { + void createdCallback() { createdCalled = true; customCreatedCount++; }
diff --git a/tests/html/html.status b/tests/html/html.status index 4905e0b..5db1caa 100644 --- a/tests/html/html.status +++ b/tests/html/html.status
@@ -13,10 +13,10 @@ custom/document_register_type_extensions_test/namespaces: Fail # Polyfill does not support createElementNS custom/document_register_basic_test: Fail # Polyfill is not case-sensitive custom/entered_left_view_test/viewless_document: Fail # Polyfill does not handle this +custom/attribute_changed_callback_test/unsupported_on_polyfill: Fail # Polyfill does not support [ $compiler == dart2js && $browser ] -# Issue 9325 failures -custom/attribute_changed_callback_test: Fail +custom/created_callback_test: Fail # Support for created constructor. [ $compiler == none && ($runtime == drt || $runtime == dartium) && $mode == debug && $system == macos] audiobuffersourcenode_test: Pass, Fail, Crash # http://crbug.com/256601 @@ -29,9 +29,9 @@ postmessage_structured_test/typed_arrays: Fail xhr_test: Pass, Fail # Issue 12648 custom/attribute_changed_callback_test: Fail # 12643 -custom/entered_left_view_test: Fail # 13313 xhr_test/json: Fail # Issue 13069 uri_test: Fail Issue 13581 +async_test: Fail # Background timers not implemented. [ $compiler == none && $runtime == drt && $system == windows ] worker_test/functional: Pass, Crash # Issue 9929. @@ -85,8 +85,6 @@ xhr_test: Pass, Fail # Issue 11884 xhr_cross_origin_test: Pass, Fail # Issue 11884 -fileapi_test/directoryReader: Fail # Issue 12573 - [ $runtime == chrome || $runtime == chromeOnAndroid || $runtime == drt || $runtime == safari ] audiocontext_test: Skip # Issue 9322
diff --git a/tests/html/htmloptionscollection_test.dart b/tests/html/htmloptionscollection_test.dart index 8af54c7..9a633ab 100644 --- a/tests/html/htmloptionscollection_test.dart +++ b/tests/html/htmloptionscollection_test.dart
@@ -33,7 +33,7 @@ // OPTIONALS optionsCollection[0] = new OptionElement(value: '42', data: 'Option42'); expect(() { - optionsCollection[0] = new OptionElement('Option42', '42'); + optionsCollection[0] = new OptionElement(data: 'Option42', value: '42'); }, throws); }); }
diff --git a/tests/html/js_test.dart b/tests/html/js_test.dart index ff6753d..290a0fb 100644 --- a/tests/html/js_test.dart +++ b/tests/html/js_test.dart
@@ -151,6 +151,12 @@ _injectJs(); useHtmlConfiguration(); + test('context instances should be identical', () { + var c1 = context; + var c2 = context; + expect(identical(c1, c2), isTrue); + }); + test('read global field', () { expect(context['x'], equals(42)); expect(context['y'], isNull);
diff --git a/tests/html/selectelement_test.dart b/tests/html/selectelement_test.dart index 717502f..f88c4af 100644 --- a/tests/html/selectelement_test.dart +++ b/tests/html/selectelement_test.dart
@@ -16,9 +16,11 @@ var options = [ new OptionElement(), new DivElement(), - new OptionElement('data', 'two', false, true), + new OptionElement(data: 'data', value: 'two', defaultSelected: false, + selected: true), new DivElement(), - new OptionElement('data', 'two', false, true), + new OptionElement(data: 'data', value: 'two', defaultSelected: false, + selected: true), new OptionElement(), ]; element.children.addAll(options); @@ -32,9 +34,11 @@ var options = [ new OptionElement(), new DivElement(), - new OptionElement('data', 'two', false, true), + new OptionElement(data: 'data', value: 'two', defaultSelected: false, + selected: true), new DivElement(), - new OptionElement('data', 'two', false, true), + new OptionElement(data: 'data', value: 'two', defaultSelected: false, + selected: true), new OptionElement(), ]; element.children.addAll(options); @@ -47,8 +51,10 @@ var element = new SelectElement(); var options = [ new OptionElement(), - new OptionElement('data', 'two', false, true), - new OptionElement('data', 'two', false, true), + new OptionElement(data: 'data', value: 'two', defaultSelected: false, + selected: true), + new OptionElement(data: 'data', value: 'two', defaultSelected: false, + selected: true), new OptionElement(), ]; element.children.addAll(options);
diff --git a/tests/isolate/isolate.status b/tests/isolate/isolate.status index 700d27c..a74948a 100644 --- a/tests/isolate/isolate.status +++ b/tests/isolate/isolate.status
@@ -89,9 +89,11 @@ [ $compiler == dart2js && ( $runtime == ff || $runtime == safari || $runtime == drt || $runtime == chrome ) ] isolate_stress_test: Pass, Slow # Issue 10697 -[ $compiler == none && ($runtime == drt || $runtime == dartium) ] +[ $compiler == none && $runtime == drt ] isolate_stress_test: Skip # Issue 12537 spawn_uri_multi_test/01: Fail # Issue 13615 +nested_spawn_stream2_test: Fail # Issue 13433 +cross_isolate_message_stream_test: Fail # Issue 13433 [ $csp ] spawn_uri_multi_test/none: Fail # http://dartbug.com/13454 @@ -99,3 +101,6 @@ [ $jscl || $runtime == ie9 ] spawn_uri_multi_test/none: RuntimeError # http://dartbug.com/13544 + +[ $compiler == none && $runtime == dartium ] +global_error_handler2_test: Fail # Issue 13719: Please triage this failure.
diff --git a/tests/language/compile_time_constant11_test.dart b/tests/language/compile_time_constant11_test.dart new file mode 100644 index 0000000..67ff3fe --- /dev/null +++ b/tests/language/compile_time_constant11_test.dart
@@ -0,0 +1,25 @@ +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// Check that conditional expression can be a compile-time constant. + +import "package:expect/expect.dart"; + +const C1 = true; +const C2 = false; + +const nephew = C1 ? C2 ? "Tick" : "Trick" : "Track"; + +main() { + const a = true ? 5 : 10; + const b = C2 ? "Track" : C1 ? "Trick" : "Tick"; + + Expect.equals(5, a); + Expect.equals("Trick", nephew); + Expect.equals(nephew, b); + Expect.identical(nephew, b); + var s = const Symbol(nephew); + var msg = "Donald is $nephew's uncle."; + Expect.equals("Donald is Trick's uncle.", msg); +}
diff --git a/tests/language/const_conditional_test.dart b/tests/language/const_conditional_test.dart new file mode 100644 index 0000000..97d4a93 --- /dev/null +++ b/tests/language/const_conditional_test.dart
@@ -0,0 +1,56 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// Test for conditionals as compile-time constants. + +import 'package:expect/expect.dart'; + +class Marker { + final field; + const Marker(this.field); +} + +var var0 = const Marker(0); +var var1 = const Marker(1); +const const0 = const Marker(0); +const const1 = const Marker(1); + +const trueConst = true; +const falseConst = false; +var nonConst = true; +const zeroConst = 0; + +const cond1 = trueConst ? const0 : const1; +const cond1a = trueConst ? nonConst : const1; /// 01: compile-time error +const cond1b = trueConst ? const0 : nonConst; /// 02: compile-time error + +const cond2 = falseConst ? const0 : const1; +const cond2a = falseConst ? nonConst : const1; /// 03: compile-time error +const cond2b = falseConst ? const0 : nonConst; /// 04: compile-time error + +const cond3 = nonConst ? const0 : const1; /// 05: compile-time error +const cond3a = nonConst ? nonConst : const1; /// 06: compile-time error +const cond3b = nonConst ? const0 : nonConst; /// 07: compile-time error + +const cond4 = zeroConst ? const0 : const1; /// 08: compile-time error +const cond4a = zeroConst ? nonConst : const1; /// 09: compile-time error +const cond4b = zeroConst ? const0 : nonConst; /// 10: compile-time error + +void main() { + Expect.identical(var0, cond1); + Expect.identical(nonConst, cond1a); /// 01: continued + Expect.identical(var0, cond1b); /// 02: continued + + Expect.identical(var1, cond2); + Expect.identical(var1, cond2a); /// 03: continued + Expect.identical(nonConst, cond2b); /// 04: continued + + Expect.identical(var0, cond3); /// 05: continued + Expect.identical(nonConst, cond3a); /// 06: continued + Expect.identical(var0, cond3b); /// 07: continued + + Expect.identical(var1, cond4); /// 08: continued + Expect.identical(var1, cond4a); /// 09: continued + Expect.identical(nonConst, cond4b); /// 10: continued +} \ No newline at end of file
diff --git a/tests/language/constant_locals_test.dart b/tests/language/constant_locals_test.dart new file mode 100644 index 0000000..bd85240 --- /dev/null +++ b/tests/language/constant_locals_test.dart
@@ -0,0 +1,30 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// Test that constant local variables have constant initializers. + +import "package:expect/expect.dart"; + +void main() { + const c1; /// 01: compile-time error + const c2 = 0; + const c3 = field; /// 02: compile-time error + const c4 = finalField; /// 03: compile-time error + const c5 = constField; + const c6 = method(); /// 04: compile-time error + const c7 = new Class(); /// 05: compile-time error + const c8 = const Class(); +} + +var field = 0; + +final finalField = 0; + +const constField = 0; + +method() => 0; + +class Class { + const Class(); +} \ No newline at end of file
diff --git a/tests/language/language.status b/tests/language/language.status index e567204..bd6e7e2 100644 --- a/tests/language/language.status +++ b/tests/language/language.status
@@ -25,6 +25,18 @@ on_catch_malformed_type_test: Fail # Issue 8601 mixin_forwarding_constructor2_test: Fail # Issue 13641 +[ $compiler == none && $runtime == vm ] +class_keyword_test/02: MissingCompileTimeError # Issue 13627 + + +[ $compiler == none && $runtime == vm && $checked ] +compile_time_constant_checked3_test/01: MissingCompileTimeError # Issue 13685 +compile_time_constant_checked3_test/02: MissingCompileTimeError # Issue 13685 +compile_time_constant_checked3_test/03: MissingCompileTimeError # Issue 13685 +compile_time_constant_checked3_test/04: MissingCompileTimeError # Issue 13685 +compile_time_constant_checked3_test/05: MissingCompileTimeError # Issue 13685 +compile_time_constant_checked3_test/06: MissingCompileTimeError # Issue 13685 + [ $compiler == none && $unchecked ] # Only checked mode reports an error on type assignment # problems in compile time constants. @@ -56,3 +68,21 @@ [ $compiler == dart2js && $runtime == ie9 ] lazy_static3_test: Fail # Issue 13469 + +[ $compiler == none && $runtime == dartium ] +assertion_test: Fail # Issue 13719: Please triage this failure. +call_test: Fail # Issue 13719: Please triage this failure. +dynamic_prefix_core_test: Fail # Issue 13719: Please triage this failure. +first_class_types_literals_test: Fail # Issue 13719: Please triage this failure. +generic_test: Fail # Issue 13719: Please triage this failure. +list_literal1_test/01: Fail # Issue 13719: Please triage this failure. +list_literal4_test: Fail # Issue 13719: Please triage this failure. +map_literal1_test/01: Fail # Issue 13719: Please triage this failure. +map_literal4_test: Fail # Issue 13719: Please triage this failure. +named_parameters_type_test/01: Fail # Issue 13719: Please triage this failure. +named_parameters_type_test/02: Fail # Issue 13719: Please triage this failure. +named_parameters_type_test/03: Fail # Issue 13719: Please triage this failure. +positional_parameters_type_test/01: Fail # Issue 13719: Please triage this failure. +positional_parameters_type_test/02: Fail # Issue 13719: Please triage this failure. +type_checks_in_factory_method_test: Fail # Issue 13719: Please triage this failure. +vm/type_vm_test: Fail # Issue 13719: Please triage this failure.
diff --git a/tests/language/language_analyzer.status b/tests/language/language_analyzer.status index d229d47..536168e 100644 --- a/tests/language/language_analyzer.status +++ b/tests/language/language_analyzer.status
@@ -3,17 +3,7 @@ # BSD-style license that can be found in the LICENSE file. [ $compiler == dartanalyzer ] - -# Missing compile-time errors for parameters marked static. -static_parameter_test/02: Fail -static_parameter_test/03: Fail -static_parameter_test/04: Fail -static_parameter_test/06: Fail -static_parameter_test/07: Fail -static_parameter_test/08: Fail -static_parameter_test/10: Fail -static_parameter_test/11: Fail -static_parameter_test/12: Fail +switch_bad_case_test/02: Fail # missing error in double in switch case expr # Runtime negative test. No static errors or warnings. closure_call_wrong_argument_count_negative_test: skip
diff --git a/tests/language/language_analyzer2.status b/tests/language/language_analyzer2.status index f43b9e8..17a459a 100644 --- a/tests/language/language_analyzer2.status +++ b/tests/language/language_analyzer2.status
@@ -3,6 +3,7 @@ # BSD-style license that can be found in the LICENSE file. [ $compiler == dart2analyzer ] +switch_bad_case_test/02: Fail # Missing compile-time errors for parameters marked static. static_parameter_test/02: Fail @@ -123,9 +124,6 @@ # test issue 11590, runtime only negative test field_method4_negative_test: fail -# test issue 11591, assigning to the final variable is warning, not error -getter_no_setter_test/01: fail - # test issue 11592, Function type alias (typedef) is not a constant first_class_types_constants_test: fail @@ -133,8 +131,6 @@ import_combinators_negative_test: fail interface_static_non_final_fields_negative_test: fail -instantiate_type_variable_test/01: fail # Issue 11595 - # test issue 11698, no setter, so warning, not error assign_instance_method_negative_test: fail @@ -185,7 +181,6 @@ # test issue 12191, ambiguous import is always warning now prefix3_negative_test: fail # Issue 12191 -library_ambiguous_test/00: fail # Issue 12191 # test issue 12289, assignment in assert statement type_error_test: fail # Issue 12289
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status index 4bb4278..87857b1 100644 --- a/tests/language/language_dart2js.status +++ b/tests/language/language_dart2js.status
@@ -5,7 +5,6 @@ [ $compiler == dart2js || $compiler == dart2dart ] bad_constructor_test/05: CompileTimeError # Issue 13669 block_scope_test: CompileTimeError # Issue 13204. -null_test/03: MissingCompileTimeError # Issue 12445. black_listed_test/none: CompileTimeError # Issue 12446. malformed_test/05: MissingCompileTimeError # Issue 12695 malformed_test/06: MissingCompileTimeError # Issue 12695 @@ -79,6 +78,7 @@ mixin_mixin6_test: Fail # Issue 12605. [ $compiler == dart2js ] +switch_bad_case_test/02: MissingCompileTimeError # switch case of type double malformed_test/none: RuntimeError # Issue 12695 function_type_alias9_test/00: Crash # Issue 9792 branch_canonicalization_test: RuntimeError # Issue 638. @@ -130,7 +130,6 @@ function_type_alias5_test/01: MissingCompileTimeError # Issue 12754 function_type_alias5_test/02: MissingCompileTimeError # Issue 12754 method_override5_test: RuntimeError # Issue 12809 -parameter_initializer6_negative_test: Fail # Issue 3502 named_parameters_aggregated_test/03: MissingCompileTimeError # Issue 12812 external_test/11: MissingCompileTimeError # Issue 12887 external_test/12: MissingCompileTimeError # Issue 12887 @@ -145,8 +144,6 @@ map_literal4_test: RuntimeError # Issue 12891 built_in_identifier_test/01: CompileTimeError # Issue 13022 -const_syntax_test/03: MissingCompileTimeError # Issue 12932 -const_syntax_test/04: MissingCompileTimeError # Issue 12932 constructor9_test/01: MissingCompileTimeError # Issue 12934 list_literal1_test/01: MissingCompileTimeError # Issue 12993 map_literal1_test/01: MissingCompileTimeError # Issue 12993 @@ -164,7 +161,6 @@ final_syntax_test/03: MissingCompileTimeError # Issue 13020 final_syntax_test/04: MissingCompileTimeError # Issue 13020 -assign_top_method_test: RuntimeError # Issue 13075 null_test/none: RuntimeError # Issue 12482 @@ -205,6 +201,7 @@ malformed_test/none: CompileTimeError # Issue 12695 mixin_super_constructor_named_test: Fail # Issue 12631 mixin_super_constructor_positionals_test: Fail # Issue 12631 +switch_bad_case_test/02: Fail # missing switch type check for double built_in_identifier_prefix_test: Fail # Issue 6972 constructor_initializer_test/none: Fail # Issue 12633 @@ -245,21 +242,6 @@ setter_override_test/03: Fail # Issue 11496 setter_override2_test/02: Fail # Issue 11496 -compile_time_constant10_test/01: Fail # Issue 5519 -compile_time_constant10_test/02: Fail # Issue 5519 -compile_time_constant_arguments_test/01: Fail # Issue 5519 -compile_time_constant_arguments_test/02: Fail # Issue 5519 -compile_time_constant_arguments_test/03: Fail # Issue 5519 -compile_time_constant_arguments_test/05: Fail # Issue 5519 -compile_time_constant_arguments_test/06: Fail # Issue 5519 -const_syntax_test/03: Fail # Issue 12933 -const_syntax_test/04: Fail # Issue 12933 -const_syntax_test/05: Fail # Issue 12933 -const_syntax_test/06: Fail # Issue 12933 -const_syntax_test/07: Fail # Issue 12933 -const_syntax_test/08: Fail # Issue 12933 -const_syntax_test/10: Fail # Issue 12933 -compile_time_constant_c_test/02: Fail # Issue 12933 constructor9_test/01: Fail # Issue 12935 constructor_named_arguments_test/01: Fail # Issue 5519 final_syntax_test/01: Fail # Issue 13020 @@ -299,7 +281,6 @@ function_type_alias5_test/00: Fail # Issue 12755 function_type_alias5_test/01: Fail # Issue 12755 function_type_alias5_test/02: Fail # Issue 12755 -parameter_initializer6_negative_test: Fail # Issue 3502 # DartVM problem. constructor5_test: Fail @@ -329,8 +310,6 @@ compile_time_constant_checked3_test/05: Fail, OK compile_time_constant_checked3_test/06: Fail, OK -final_is_not_const_test/01: Fail # Issue 12692 - [ $compiler == dart2dart && $minified ] super_getter_setter_test: Fail # Issue 11065. f_bounded_quantification4_test: Fail # Issue 12605.
diff --git a/tests/language/list_length_tracer_test.dart b/tests/language/list_length_tracer_test.dart new file mode 100644 index 0000000..f8c1070 --- /dev/null +++ b/tests/language/list_length_tracer_test.dart
@@ -0,0 +1,16 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// Test that dart2js' optimization on list length does not fold a +// length getter to a constant if the receiver can be null. + +import "package:expect/expect.dart"; + +var a = 42; +var b; + +main() { + Expect.throws(() => b.length); + b = const [42]; +}
diff --git a/tests/language/list_tracer_call_last_test.dart b/tests/language/list_tracer_call_last_test.dart new file mode 100644 index 0000000..dbaf136 --- /dev/null +++ b/tests/language/list_tracer_call_last_test.dart
@@ -0,0 +1,13 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// dart2js used to fail this test, by inferring that `a.last()` +// returns the element type of the `a` list. + +main() { + var a = [() => 123]; + if (a.last() is! num) { + throw 'Test failed'; + } +}
diff --git a/tests/language/list_tracer_closure_test.dart b/tests/language/list_tracer_closure_test.dart new file mode 100644 index 0000000..acb226e --- /dev/null +++ b/tests/language/list_tracer_closure_test.dart
@@ -0,0 +1,19 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// Regression test for dart2js' inferrer: if we closurize a method, we +// still need to collect the users of the parameters for the trace +// container pass to work. + +main() { + var a = new List(); + a.add; + var b = new List(); + var c = new List(1); + b.add(c); + b[0][0] = 42; + if (c[0] is! int) { + throw 'Test failed'; + } +}
diff --git a/tests/language/mixin_black_listed_test.dart b/tests/language/mixin_black_listed_test.dart new file mode 100644 index 0000000..809274b --- /dev/null +++ b/tests/language/mixin_black_listed_test.dart
@@ -0,0 +1,52 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// Check mixin of black-listed types. + +import 'package:expect/expect.dart'; + +class C {} +class D {} + +class C1 extends Object +with String /// 01: compile-time error +{} + +class D1 extends Object with C +, Null /// 02: compile-time error +{} + +class E1 extends Object with +int, /// 03: compile-time error +C {} + +class F1 extends Object with C +, double /// 04: compile-time error +, D {} + +typedef C2 = Object with num; /// 05: compile-time error + +typedef D2 = Object with C +, bool /// 06: compile-time error +; + +typedef E2 = Object with +String, /// 07: compile-time error +C; + +typedef F2 = Object with C, +dynamic, /// 08: compile-time error +D; + + +main() { + Expect.isNotNull(new C1()); + Expect.isNotNull(new D1()); + Expect.isNotNull(new E1()); + Expect.isNotNull(new F1()); + Expect.isNotNull(new C2()); /// 05: continued + Expect.isNotNull(new D2()); + Expect.isNotNull(new E2()); + Expect.isNotNull(new F2()); +}
diff --git a/tests/language/switch_bad_case_test.dart b/tests/language/switch_bad_case_test.dart new file mode 100644 index 0000000..8211521 --- /dev/null +++ b/tests/language/switch_bad_case_test.dart
@@ -0,0 +1,36 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// Test reporting a compile-time error if case expressions do not all have +// the same type or are of type double. + +import "package:expect/expect.dart"; + +void main() { + Expect.equals("IV", caesarSays(4)); + Expect.equals(null, caesarSays(2)); + Expect.equals(null, archimedesSays(3.14)); +} + +caesarSays(n) { + switch (n) { + case 1: + return "I"; + case 4: + return "IV"; + case "M": /// 01: compile-time error + return 1000; /// 01: continued + } + return null; +} + +archimedesSays(n) { + switch (n) { /// 02: continued + case 3.14: /// 02: compile-time error + return "Pi"; /// 02: continued + case 2.71828: /// 02: continued + return "Huh?"; /// 02: continued + } /// 02: continued + return null; +}
diff --git a/tests/language/switch_int_double_test.dart b/tests/language/switch_int_double_test.dart deleted file mode 100644 index 8ae95e2..0000000 --- a/tests/language/switch_int_double_test.dart +++ /dev/null
@@ -1,27 +0,0 @@ -// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -// Test reporting a compile-time error if case expressions do not all have -// the same type. - -import "package:expect/expect.dart"; - -void main() { - Expect.equals(100, test(1.0)); - Expect.equals(75, test(0.75)); - Expect.equals(null, test(0.5)); -} - -int test(num ratio) { - switch (ratio) { - case 0.75: - return 75; - case 1.0: - return 100; - case 2: /// 01: compile-time error - return 200; /// 01: continued - case 'foo': /// 02: compile-time error - return 400; /// 02: continued - } -} \ No newline at end of file
diff --git a/tests/language/vm/function_equality_vm_test.dart b/tests/language/vm/function_equality_vm_test.dart new file mode 100644 index 0000000..4077c66 --- /dev/null +++ b/tests/language/vm/function_equality_vm_test.dart
@@ -0,0 +1,19 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// Test function equality with null. + +import "package:expect/expect.dart"; + +class A { + foo() { } +} + +main() { + var a = new A(); + var f = a.foo; + Expect.isFalse(f == null); + Expect.isFalse(null == f); +} +
diff --git a/tests/lib/convert/unicode_tests.dart b/tests/lib/convert/unicode_tests.dart index 52a7b09..47bd510 100644 --- a/tests/lib/convert/unicode_tests.dart +++ b/tests/lib/convert/unicode_tests.dart
@@ -63,6 +63,9 @@ const SMALLEST_4_UTF8_UNIT_BYTES = const [ 0xF0, 0x90, 0x80, 0x80 ]; const SMALLEST_4_UTF8_UNIT_STRING = "\u{10000}"; +const BIGGEST_4_UTF8_UNIT_BYTES = const [ 0xF4, 0x8F, 0xBF, 0xBF ]; +const BIGGEST_4_UTF8_UNIT_STRING = "\u{10FFFF}"; + const _TEST_PAIRS = const [ const [ const [], "" ], const [ INTER_BYTES, INTER_STRING ], @@ -78,6 +81,7 @@ const [ SMALLEST_3_UTF8_UNIT_BYTES, SMALLEST_3_UTF8_UNIT_STRING ], const [ BIGGEST_3_UTF8_UNIT_BYTES, BIGGEST_3_UTF8_UNIT_STRING ], const [ SMALLEST_4_UTF8_UNIT_BYTES, SMALLEST_4_UTF8_UNIT_STRING ], + const [ BIGGEST_4_UTF8_UNIT_BYTES, BIGGEST_4_UTF8_UNIT_STRING ], ]; List<List> _expandTestPairs() {
diff --git a/tests/lib/convert/utf85_test.dart b/tests/lib/convert/utf85_test.dart new file mode 100644 index 0000000..3b5edc0 --- /dev/null +++ b/tests/lib/convert/utf85_test.dart
@@ -0,0 +1,15 @@ +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +library utf8_test; +import "package:expect/expect.dart"; +import 'dart:convert'; + +main() { + for (int i = 0; i <= 0x10FFFF; i++) { + if (i == UNICODE_BOM_CHARACTER_RUNE) continue; + Expect.equals(i, + UTF8.decode(UTF8.encode(new String.fromCharCode(i))).runes.first); + } +}
diff --git a/tests/lib/lib.status b/tests/lib/lib.status index 4276ffc..61ba7ee 100644 --- a/tests/lib/lib.status +++ b/tests/lib/lib.status
@@ -40,6 +40,10 @@ mirrors/redirecting_factory_test/02: RuntimeError # Issue 6490 mirrors/closures_test/none: RuntimeError # Issue 6490 mirrors/library_metadata2_test/01: CompileTimeError # Issue 13633 +async/stream_controller_async_test: Pass, Fail # Issue 13608 + +[ $compiler == dart2js && $checked ] +mirrors/redirection_type_shuffling_test: RuntimeError # Issue 13706 [ $runtime == safari ] mirrors/return_type_test: Pass, Timeout # Issue 12858 @@ -138,9 +142,6 @@ mirrors/hierarchy_test: Fail # TODO(ahe): This test is slightly broken. http://dartbug.com/12464 mirrors/mixin_test/01: Fail, OK # TODO(ahe): Slight broken test to ensure test coverage on dart2js. mirrors/typedef_test/01: Fail, OK # Incorrect dart2js behavior. -mirrors/redirecting_factory_test/none: Fail # Issue 13365 -mirrors/redirecting_factory_test/01: Fail # Issue 13365 -mirrors/redirecting_factory_test/02: Fail # Issue 13365 mirrors/closures_test/01: Fail, OK # Incorrect dart2js behavior. [ $compiler == none && $runtime == drt ] @@ -179,11 +180,23 @@ mirrors/typevariable_mirror_metadata_test: Fail # Issue 13510 [ $compiler == dart2analyzer ] -mirrors/library_metadata2_test/01: Fail # http://dartbug.com/12950 mirrors/typedef_test/none: Fail # Issue 13093 mirrors/generics_test/none: Fail # Issue 13432 +mirrors/invoke_named_test/none: Fail # http://dartbug.com/13612 mirrors/parameter_metadata_test: Fail # Issue 13510 mirrors/method_mirror_returntype_test: Fail # Issue 13510 mirrors/function_type_mirror_test: Fail # Issue 13510 mirrors/typevariable_mirror_metadata_test: Fail # Issue 13510 + +[ $compiler == none && $runtime == dartium ] +async/run_async3_test: Fail # Issue 13719: Please triage this failure. +async/run_async4_test: Fail # Issue 13719: Please triage this failure. +async/run_async6_test: Fail # Issue 13719: Please triage this failure. +async/timer_not_available_test: Fail # Issue 13719: Please triage this failure. +mirrors/closures_test/01: Fail # Issue 13719: Please triage this failure. +mirrors/hierarchy_test: Fail # Issue 13719: Please triage this failure. +mirrors/library_uri_io_test: Fail # Issue 13719: Please triage this failure. +mirrors/local_isolate_test: Fail # Issue 13719: Please triage this failure. +mirrors/mixin_test/01: Fail # Issue 13719: Please triage this failure. +mirrors/typedef_test/01: Fail # Issue 13719: Please triage this failure.
diff --git a/tests/lib/mirrors/circular_factory_redirection_test.dart b/tests/lib/mirrors/circular_factory_redirection_test.dart new file mode 100644 index 0000000..a7b1882 --- /dev/null +++ b/tests/lib/mirrors/circular_factory_redirection_test.dart
@@ -0,0 +1,37 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import "dart:mirrors"; +import "package:expect/expect.dart"; + +class A { + A(); + A.circular() = B.circular; /// 01: compile-time error + const A.circular2() = B.circular2; /// 02: compile-time error +} +class B { + B(); + B.circular() = C.circular; /// 01: continued + const B.circular2() = C.circular2; /// 02: continued +} +class C { + C(); + C.circular() = A.circular; /// 01: continued + const C.circular2() = A.circular2; /// 02: continued +} + +main() { + ClassMirror cm = reflectClass(A); + + new A.circular(); /// 01: continued + new A.circular2(); /// 02: continued + + Expect.throws(() => cm.newInstance(#circular, []), + (e) => e is NoSuchMethodError, + 'Should disallow circular redirection (non-const)'); + + Expect.throws(() => cm.newInstance(#circular2, []), + (e) => e is NoSuchMethodError, + 'Should disallow circular redirection (const)'); +}
diff --git a/tests/lib/mirrors/redirecting_factory_test.dart b/tests/lib/mirrors/redirecting_factory_test.dart index 1d0059f..6509069 100644 --- a/tests/lib/mirrors/redirecting_factory_test.dart +++ b/tests/lib/mirrors/redirecting_factory_test.dart
@@ -14,14 +14,14 @@ factory Class.redirectingFactoryNoOptional(a, b) = Class.factoryNoOptional; factory Class.factoryUnnamedOptional(a, [b = 42]) => new Class<T1, T2>(a - b); - factory Class.redirectingFactoryUnnamedOptional(a, [b]) = + factory Class.redirectingFactoryUnnamedOptional(a, [b = 5]) = Class.factoryUnnamedOptional; - factory Class.factoryNamedOptional(a, {b: 0}) { + factory Class.factoryNamedOptional(a, {b: 42}) { return new Class<T1, T2>(a - b); } - factory Class.redirectingFactoryNamedOptional(a, {b: 42}) = + factory Class.redirectingFactoryNamedOptional(a, {b: 5}) = Class.factoryNamedOptional; factory Class.factoryMoreNamedOptional(a, {b: 0, c: 2}) {
diff --git a/tests/lib/mirrors/redirection_type_shuffling_test.dart b/tests/lib/mirrors/redirection_type_shuffling_test.dart new file mode 100644 index 0000000..582b414 --- /dev/null +++ b/tests/lib/mirrors/redirection_type_shuffling_test.dart
@@ -0,0 +1,36 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import "dart:mirrors"; +import "package:expect/expect.dart"; + +class G<A extends int, B extends String> { + G(); + factory G.swap() = G<B,A>; /// static type warning + factory G.retain() = G<A,B>; +} + +bool get inCheckedMode { + try { + var i = 1; + String s = i; + return false; + } catch(e) { + return true; + } +} + +main() { + ClassMirror cm = reflect(new G<int, String>()).type; + + if (inCheckedMode) { + Expect.throws(() => cm.newInstance(#swap, []), + (e) => e is MirroredCompilationError, + 'Checked mode should not allow violation of type bounds'); + } else { + Expect.isTrue(cm.newInstance(#swap, []).reflectee is G<String,int>); + } + + Expect.isTrue(cm.newInstance(#retain, []).reflectee is G<int,String>); +}
diff --git a/tests/standalone/debugger/step_in_equals_test.dart b/tests/standalone/debugger/step_in_equals_test.dart new file mode 100644 index 0000000..0e10e5d --- /dev/null +++ b/tests/standalone/debugger/step_in_equals_test.dart
@@ -0,0 +1,59 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import "debug_lib.dart"; + +class MyClass { + operator ==(other) { + print(other); + return true; // Breakpoint #3. + } +} + +main() { + if (RunScript(testScript)) return; + var a = new MyClass(); + var b = null; + var x = a == b; // Breakpoint #1. + print(x); + b = 123; + a == b; // Breakpoint #2. + print("after 2"); + if (a == null) { // Breakpoint #4. + throw "unreachable"; + } + print("after 4"); + if (null == a) { + throw "unreachable"; + } + print("ok"); +} + +var testScript = [ + MatchFrames(["main"]), + SetBreakpoint(18), + SetBreakpoint(21), + SetBreakpoint(10), + SetBreakpoint(23), + Resume(), + MatchFrames(["main"]), // At breakpoint #1. + StepInto(), + MatchFrames(["main"]), // Don't step into == method because of null. + Resume(), + MatchFrames(["main"]), // At breakpoint #2. + StepInto(), + StepInto(), + MatchFrames(["MyClass.==", "main"]), // At MyClass.== entry. + Resume(), + MatchFrames(["MyClass.==", "main"]), // At breakpoint #3. + Resume(), + MatchFrames(["main"]), // At breakpoint #4. + StepInto(), + MatchFrames(["main"]), // After breakpoint #4. + Step(), + MatchFrames(["main"]), // At null == a. + StepInto(), + MatchFrames(["main"]), // After null == a. + Resume() +];
diff --git a/tests/standalone/float_array_test.dart b/tests/standalone/float_array_test.dart index 2fe83a2..2be1711 100644 --- a/tests/standalone/float_array_test.dart +++ b/tests/standalone/float_array_test.dart
@@ -4,6 +4,8 @@ // // Dart test program for testing native float arrays. +// VMOptions=--optimization_counter_threshold=10 + // Library tag to be able to run in html test framework. library FloatArrayTest; @@ -186,23 +188,34 @@ a[index] = value; } +testPolymorphicLoad(var list) { + return list[0]; +} + main() { var a32 = new Float32List(5); - for (int i = 0; i < 2000; i++) { + for (int i = 0; i < 20; i++) { testCreateFloat32Array(); testSetRange32(); testIndexOutOfRange32(); testIndexOf32(); storeIt32(a32, 1, 2.0); + testPolymorphicLoad(a32); } var a64 = new Float64List(5); - for (int i = 0; i < 2000; i++) { + for (int i = 0; i < 20; i++) { testCreateFloat64Array(); testSetRange64(); testIndexOutOfRange64(); testIndexOf64(); storeIt64(a64, 1, 2.0); + testPolymorphicLoad(a64); } + var f32x4 = new Float32x4List(5); + for (int i = 0; i < 20; i++) { + testPolymorphicLoad(f32x4); + } + // These two take a long time in checked mode. testBadValues32(); testBadValues64();
diff --git a/tests/standalone/io/directory_test.dart b/tests/standalone/io/directory_test.dart index aaedf1c..ea1e21c 100644 --- a/tests/standalone/io/directory_test.dart +++ b/tests/standalone/io/directory_test.dart
@@ -452,9 +452,8 @@ var os = Platform.operatingSystem; if (os == "windows") nestingDepth = 2; if (createdDirectories.length < nestingDepth) { - temp = new Directory( - '${temp.path}/nested_temp_dir_${createdDirectories.length}_'); - temp.createTemp().then(createPhaseCallback); + temp.createTemp('nested_temp_dir_${createdDirectories.length}_') + .then(createPhaseCallback); } else { deletePhaseCallback(); }
diff --git a/tests/standalone/io/file_system_watcher_test.dart b/tests/standalone/io/file_system_watcher_test.dart index fef2d6e..41f4948 100644 --- a/tests/standalone/io/file_system_watcher_test.dart +++ b/tests/standalone/io/file_system_watcher_test.dart
@@ -29,7 +29,7 @@ throw e; }); - runAsync(file.createSync); + file.createSync(); } @@ -54,7 +54,7 @@ throw e; }); - runAsync(() => file.writeAsStringSync('a')); + file.writeAsStringSync('a'); } @@ -82,7 +82,7 @@ throw e; }); - runAsync(() => file.renameSync(dir.path + '/file2')); + file.renameSync(dir.path + '/file2'); } @@ -107,7 +107,7 @@ throw e; }); - runAsync(file.deleteSync); + file.deleteSync(); } @@ -130,10 +130,8 @@ throw e; }); - runAsync(() { - file.createSync(); - file.writeAsStringSync('a'); - }); + file.createSync(); + file.writeAsStringSync('a'); } @@ -175,12 +173,10 @@ state = newState; }); - runAsync(() { - file.createSync(); - file.writeAsStringSync('a'); - file.renameSync(file2.path); - file2.deleteSync(); - }); + file.createSync(); + file.writeAsStringSync('a'); + file.renameSync(file2.path); + file2.deleteSync(); } @@ -209,7 +205,7 @@ throw e; }); - runAsync(file.createSync()); + file.createSync(); } @@ -232,7 +228,7 @@ throw e; }); - runAsync(file.createSync); + file.createSync(); new Timer(const Duration(milliseconds: 300), () { sub.cancel();
diff --git a/tests/standalone/io/file_test.dart b/tests/standalone/io/file_test.dart index 3b8c383..4e3cc3d 100644 --- a/tests/standalone/io/file_test.dart +++ b/tests/standalone/io/file_test.dart
@@ -1082,6 +1082,29 @@ }); } + static void testDoubleAsyncOperation() { + asyncTestStarted(); + var file = new File(Platform.executable).openSync(); + var completer = new Completer(); + int done = 0; + bool error = false; + void getLength() { + file.length() + .catchError((e) { error = true; }) + .whenComplete(() { + if (++done == 2) { + asyncTestDone("testDoubleAsyncOperation"); + Expect.isTrue(error); + file.lengthSync(); + file.closeSync(); + } + }); + } + getLength(); + getLength(); + Expect.throws(() => file.lengthSync()); + } + static void testLastModifiedSync() { var modified = new File(Platform.executable).lastModifiedSync(); Expect.isTrue(modified is DateTime); @@ -1300,6 +1323,7 @@ testRename(); testRenameSync(); testLastModified(); + testDoubleAsyncOperation(); asyncEnd(); }); }
diff --git a/tests/standalone/io/http_server_test.dart b/tests/standalone/io/http_server_test.dart index b470b4d..f5018b4 100644 --- a/tests/standalone/io/http_server_test.dart +++ b/tests/standalone/io/http_server_test.dart
@@ -41,6 +41,8 @@ ServerSocket.bind("127.0.0.1", 0).then((s) { socket = s; server = new HttpServer.listenOn(socket); + Expect.equals(server.address.address, '127.0.0.1'); + Expect.equals(server.address.host, '127.0.0.1'); server.listen((HttpRequest request) { request.listen( (_) {}, @@ -51,6 +53,7 @@ test(() { server.close(); Expect.throws(() => server.port); + Expect.throws(() => server.address); socket.close(); asyncEnd(); });
diff --git a/tests/standalone/io/print_sync_script.dart b/tests/standalone/io/print_sync_script.dart new file mode 100644 index 0000000..82f866b --- /dev/null +++ b/tests/standalone/io/print_sync_script.dart
@@ -0,0 +1,22 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:io'; + +String get bigString { + var buffer = new StringBuffer(); + for (var i = 0; i < 1000; i++) { + buffer.write(i); + for (var i = 0; i < 200; i++) { + buffer.write('='); + } + buffer.writeln(); + } + return buffer.toString(); +} + +main() { + stdout; // Be sure to mark stdout as non-blocking. + print(bigString); +}
diff --git a/tests/standalone/io/print_sync_test.dart b/tests/standalone/io/print_sync_test.dart new file mode 100644 index 0000000..05f8014 --- /dev/null +++ b/tests/standalone/io/print_sync_test.dart
@@ -0,0 +1,19 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import 'dart:io'; + +import "package:expect/expect.dart"; +import "package:async_helper/async_helper.dart"; + +void main() { + asyncStart(); + Process.run(Platform.executable, + [new Uri.file(Platform.script) + .resolve('print_sync_script.dart').toString()]) + .then((out) { + asyncEnd(); + Expect.equals(1002, out.stdout.split('\n').length); + }); +}
diff --git a/tests/standalone/io/regress_7191_script.dart b/tests/standalone/io/regress_7191_script.dart index 9f7c780..9f6a346 100644 --- a/tests/standalone/io/regress_7191_script.dart +++ b/tests/standalone/io/regress_7191_script.dart
@@ -16,7 +16,10 @@ p.stderr.listen((_) { }); // When receiving data again, kill sub-process and exit. subscription.onData((data) { - p.kill(); + // If a SIGTERM is sent before the child-process's main is invoked, + // there is a change that the SIGTERM is ignore on Mac OS X. Use + // SIGKILL to get around the issue. + p.kill(ProcessSignal.SIGKILL); p.exitCode.then((_) => exit(0)); }); // Close stdout. If handles are incorrectly inherited this will
diff --git a/tests/standalone/io/secure_socket_bad_data_test.dart b/tests/standalone/io/secure_socket_bad_data_test.dart index 0b6f813..bf7af89 100644 --- a/tests/standalone/io/secure_socket_bad_data_test.dart +++ b/tests/standalone/io/secure_socket_bad_data_test.dart
@@ -141,17 +141,20 @@ Future test(bool hostnameInConnect) { - return RawServerSocket.bind(HOST_NAME, 0) - .then((server) { + return RawServerSocket.bind(HOST_NAME, 0).then((server) { server.listen((client) { RawSecureSocket.secureServer(client, CERTIFICATE) - .then((secureClient) { - Expect.throws(() => client.add([0])); - return runServer(secureClient); - }) - .then((_) => server.close()); + .then((secureClient) { + Expect.throws(() => client.add([0])); + return runServer(secureClient); + }, + onError: (e) { + Expect.isTrue(e is HandshakeException); + Expect.isTrue(e.toString().contains( + 'received a record with an incorrect Message Authentication')); + }) + .whenComplete(server.close); }); - return connectClient(server.port, hostnameInConnect).then(runClient); }); }
diff --git a/tests/standalone/io/socket_ipv6_test.dart b/tests/standalone/io/socket_ipv6_test.dart index bded728..e3a2e91 100644 --- a/tests/standalone/io/socket_ipv6_test.dart +++ b/tests/standalone/io/socket_ipv6_test.dart
@@ -5,6 +5,7 @@ import 'dart:io'; import "package:async_helper/async_helper.dart"; +import "package:expect/expect.dart"; const ANY = InternetAddressType.ANY; @@ -13,6 +14,8 @@ InternetAddress.lookup("::0", type: ANY).then((serverAddr) { InternetAddress.lookup("::1", type: ANY).then((clientAddr) { ServerSocket.bind(serverAddr.first, 0).then((server) { + Expect.equals('::0', server.address.host); + Expect.equals('::', server.address.address); server.listen((socket) { socket.destroy(); server.close(); @@ -30,6 +33,8 @@ asyncStart(); InternetAddress.lookup("::0", type: ANY).then((serverAddr) { ServerSocket.bind(serverAddr.first, 0).then((server) { + Expect.equals('::0', server.address.host); + Expect.equals('::', server.address.address); server.listen((socket) { socket.destroy(); server.close(); @@ -46,6 +51,8 @@ asyncStart(); InternetAddress.lookup("::1", type: ANY).then((clientAddr) { ServerSocket.bind("127.0.0.1", 0).then((server) { + Expect.equals('127.0.0.1', server.address.host); + Expect.equals('127.0.0.1', server.address.address); server.listen((socket) { throw "Unexpected socket"; }); @@ -60,6 +67,8 @@ void testIPv4toIPv4() { asyncStart(); ServerSocket.bind("127.0.0.1", 0).then((server) { + Expect.equals('127.0.0.1', server.address.host); + Expect.equals('127.0.0.1', server.address.address); server.listen((socket) { socket.destroy(); server.close(); @@ -87,7 +96,7 @@ void testIPv4Lookup() { asyncStart(); InternetAddress.lookup("127.0.0.1").then((list) { - if (list.length < 0) throw "no addresse"; + if (list.length < 0) throw "no address"; for (var entry in list) { if (entry.type != InternetAddressType.IP_V4) { throw "Wrong IP type"; @@ -104,7 +113,7 @@ ServerSocket.bind(serverAddr.first, 0, v6Only: true) .then((server) { server.listen((socket) { - throw "Unexpcted socket"; + throw "Unexpected socket"; }); Socket.connect("127.0.0.1", server.port).catchError((error) { server.close();
diff --git a/tests/standalone/io/web_socket_error_test.dart b/tests/standalone/io/web_socket_error_test.dart new file mode 100644 index 0000000..439ad1d --- /dev/null +++ b/tests/standalone/io/web_socket_error_test.dart
@@ -0,0 +1,106 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. +// +// VMOptions= +// VMOptions=--short_socket_read +// VMOptions=--short_socket_write +// VMOptions=--short_socket_read --short_socket_write + +library dart.io; + +import "dart:async"; +import "dart:io"; +import "dart:math"; +import "dart:typed_data"; + +import "package:async_helper/async_helper.dart"; +import "package:expect/expect.dart"; +import "package:path/path.dart"; + +part "../../../sdk/lib/io/crypto.dart"; + + +const String webSocketGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; +const String CERT_NAME = 'localhost_cert'; +const String HOST_NAME = 'localhost'; + +/** + * A SecurityConfiguration lets us run the tests over HTTP or HTTPS. + */ +class SecurityConfiguration { + final bool secure; + + SecurityConfiguration({bool this.secure}); + + Future<HttpServer> createServer({int backlog: 0}) => + secure ? HttpServer.bindSecure(HOST_NAME, + 0, + backlog: backlog, + certificateName: CERT_NAME) + : HttpServer.bind(HOST_NAME, + 0, + backlog: backlog); + + Future<WebSocket> createClient(int port) => + WebSocket.connect('${secure ? "wss" : "ws"}://$HOST_NAME:$port/'); + + + void testForceCloseServerEnd(int totalConnections) { + createServer().then((server) { + server.listen((request) { + var response = request.response; + response.statusCode = HttpStatus.SWITCHING_PROTOCOLS; + response.headers.set(HttpHeaders.CONNECTION, "upgrade"); + response.headers.set(HttpHeaders.UPGRADE, "websocket"); + String key = request.headers.value("Sec-WebSocket-Key"); + _SHA1 sha1 = new _SHA1(); + sha1.add("$key$webSocketGUID".codeUnits); + String accept = _CryptoUtils.bytesToBase64(sha1.close()); + response.headers.add("Sec-WebSocket-Accept", accept); + response.headers.contentLength = 0; + response.detachSocket().then((socket) { + socket.destroy(); + }); + }); + + int closeCount = 0; + for (int i = 0; i < totalConnections; i++) { + createClient(server.port).then((webSocket) { + webSocket.add("Hello, world!"); + webSocket.listen( + (message) { + Expect.fail("unexpected message"); + }, + onDone: () { + closeCount++; + if (closeCount == totalConnections) { + server.close(); + } + }); + }); + } + }); + } + + void runTests() { + testForceCloseServerEnd(10); + } +} + + +void initializeSSL() { + var testPkcertDatabase = join(dirname(Platform.script), 'pkcert'); + SecureSocket.initialize(database: testPkcertDatabase, + password: "dartdart"); +} + + +main() { + asyncStart(); + new SecurityConfiguration(secure: false).runTests(); + initializeSSL(); + new SecurityConfiguration(secure: true).runTests(); + asyncEnd(); +} +
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status index 30a2a3a..f778bf7 100644 --- a/tests/standalone/standalone.status +++ b/tests/standalone/standalone.status
@@ -51,11 +51,7 @@ io/directory_non_ascii_test: Pass, Fail io/process_non_ascii_test: Pass, Fail -[ $runtime == vm ] -io/http_server_early_client_close_test: Crash, Pass # Issue 12982 -io/secure_socket_bad_data_test: Crash, Pass # 12982 - -[ $compiler == none && $runtime == drt ] +[ $compiler == none && ($runtime == drt || $runtime == dartium) ] typed_data_isolate_test: Skip # This test uses dart:io io/*: Skip # Don't run tests using dart:io in the browser package/*: Skip # Do not run those in Dartium. @@ -177,3 +173,8 @@ io/test_extension_fail_test: Fail io/dart_std_io_pipe_test: Fail io/file_read_special_device_test: Fail + +[ $compiler == none && $runtime == dartium ] +assert_test: Fail # Issue 13719: Please triage this failure. +javascript_int_overflow_literal_test/01: Fail # Issue 13719: Please triage this failure. +javascript_int_overflow_test: Fail # Issue 13719: Please triage this failure.
diff --git a/tests/utils/utils.status b/tests/utils/utils.status index f2e6744..ab84052 100644 --- a/tests/utils/utils.status +++ b/tests/utils/utils.status
@@ -22,3 +22,8 @@ [ $compiler == none && $runtime == drt && $system == linux ] png_layout_test: Fail # Issue 13540 + +[ $compiler == none && $runtime == dartium ] +dart2js_test: Skip # Uses dart:io. +png_layout_test: Skip # dartium doesn't support layout tests +txt_layout_test: Skip # dartium doesn't support layout tests
diff --git a/tools/VERSION b/tools/VERSION index 7dc526d..0a86806 100644 --- a/tools/VERSION +++ b/tools/VERSION
@@ -1,4 +1,4 @@ MAJOR 0 -MINOR 7 -BUILD 6 -PATCH 4 +MINOR 8 +BUILD 0 +PATCH 0
diff --git a/tools/bots/compiler.py b/tools/bots/compiler.py index f4264ab..b64ed3e 100644 --- a/tools/bots/compiler.py +++ b/tools/bots/compiler.py
@@ -20,6 +20,7 @@ import bot +DARTIUM_BUILDER = r'none-dartium-(linux|mac|windows)' DART2JS_BUILDER = ( r'dart2js-(linux|mac|windows)(-(jsshell))?-(debug|release)(-(checked|host-checked))?(-(host-checked))?(-(minified))?(-(x64))?-?(\d*)-?(\d*)') WEB_BUILDER = ( @@ -45,6 +46,7 @@ dart2js_pattern = re.match(DART2JS_BUILDER, builder_name) web_pattern = re.match(WEB_BUILDER, builder_name) + dartium_pattern = re.match(DARTIUM_BUILDER, builder_name) if web_pattern: compiler = 'dart2js' @@ -81,6 +83,11 @@ arch = 'x64' shard_index = dart2js_pattern.group(13) total_shards = dart2js_pattern.group(14) + elif dartium_pattern: + compiler = 'none' + runtime = 'dartium' + mode = 'release' + system = dartium_pattern.group(1) else : return None @@ -104,7 +111,8 @@ def NeedsXterm(compiler, runtime): - return runtime in ['ie9', 'ie10', 'chrome', 'safari', 'opera', 'ff', 'drt'] + return runtime in ['ie9', 'ie10', 'chrome', 'safari', 'opera', 'ff', 'drt', + 'dartium'] def TestStepName(name, flags): @@ -117,9 +125,9 @@ # supported platforms. def UseBrowserController(runtime, system): supported_platforms = { - 'linux': ['ff', 'chromeOnAndroid', 'chrome'], - 'mac': ['safari', 'chrome'], - 'windows': ['ie9', 'ie10', 'ff', 'chrome'] + 'linux': ['ff', 'chromeOnAndroid', 'chrome', 'dartium'], + 'mac': ['safari', 'chrome', 'dartium'], + 'windows': ['ie9', 'ie10', 'ff', 'chrome', 'dartium'] } # Platforms that we run on the fyi waterfall only. fyi_supported_platforms = { @@ -187,7 +195,8 @@ bot.RunProcess(cmd) -def TestCompiler(runtime, mode, system, flags, is_buildbot, test_set, arch): +def TestCompiler(runtime, mode, system, flags, is_buildbot, test_set, arch, + compiler=None): """ test the compiler. Args: - runtime: either 'd8', 'jsshell', or one of the browsers, see GetBuildInfo @@ -198,8 +207,12 @@ emulating one. - test_set: Specification of a non standard test set, default None - arch: The architecture to run on. + - compiler: The compiler to use for test.py (default is 'dart2js'). """ + if not compiler: + compiler = 'dart2js' + def GetPath(runtime): """ Helper to get the path to the Chrome or Firefox executable for a particular platform on the buildbot. Throws a KeyError if runtime is not @@ -219,7 +232,8 @@ 'Local', 'Google', 'Chrome', 'Application', 'chrome.exe')} return path_dict[runtime] - if (runtime == 'ff' or runtime == 'chrome') and is_buildbot: + if (compiler == 'dart2js' and (runtime == 'ff' or runtime == 'chrome') + and is_buildbot): # Print out browser version numbers if we're running on the buildbot (where # we know the paths to these browser installations). version_query_string = '"%s" --version' % GetPath(runtime) @@ -248,23 +262,26 @@ TestStep("dart2js_unit", mode, system, 'none', 'vm', ['dart2js'], unit_test_flags, arch) - if system == 'windows' and runtime == 'ie10': - TestStep("dart2js", mode, system, 'dart2js', runtime, ['html'], flags, arch) + if compiler == 'dart2js' and system == 'windows' and runtime == 'ie10': + TestStep("%s-%s" % (compiler, runtime), mode, system, compiler, runtime, + ['html'], flags, arch) else: # Run the default set of test suites. - TestStep("dart2js", mode, system, 'dart2js', runtime, [], flags, arch) + TestStep("%s-%s" % (compiler, runtime), mode, system, compiler, + runtime, [], flags, arch) - # TODO(kasperl): Consider running peg and css tests too. - extras = ['dart2js_extra', 'dart2js_native'] - extras_flags = flags - if (system == 'linux' - and runtime == 'd8' - and not '--host-checked' in extras_flags): - # Run the extra tests in checked mode, but only on linux/d8. - # Other systems have less resources and tend to time out. - extras_flags = extras_flags + ['--host-checked'] - TestStep("dart2js_extra", mode, system, 'dart2js', runtime, extras, - extras_flags, arch) + if compiler == 'dart2js': + # TODO(kasperl): Consider running peg and css tests too. + extras = ['dart2js_extra', 'dart2js_native'] + extras_flags = flags + if (system == 'linux' + and runtime == 'd8' + and not '--host-checked' in extras_flags): + # Run the extra tests in checked mode, but only on linux/d8. + # Other systems have less resources and tend to time out. + extras_flags = extras_flags + ['--host-checked'] + TestStep("dart2js_extra", mode, system, 'dart2js', runtime, extras, + extras_flags, arch) def _DeleteTempWebdriverProfiles(directory): @@ -364,13 +381,14 @@ TestCompiler(build_info.runtime, build_info.mode, build_info.system, list(test_flags), build_info.is_buildbot, build_info.test_set, - build_info.arch) + build_info.arch, compiler=build_info.compiler) # See comment in GetHasHardCodedCheckedMode, this is a hack. if (GetHasHardCodedCheckedMode(build_info)): TestCompiler(build_info.runtime, build_info.mode, build_info.system, test_flags + ['--checked'], build_info.is_buildbot, - build_info.test_set, build_info.arch) + build_info.test_set, build_info.arch, + compiler=build_info.compiler) if build_info.runtime != 'd8': CleanUpTemporaryFiles(build_info.system, build_info.runtime)
diff --git a/tools/dom/scripts/generator.py b/tools/dom/scripts/generator.py index 3bb58bc..ef81ebd 100644 --- a/tools/dom/scripts/generator.py +++ b/tools/dom/scripts/generator.py
@@ -11,7 +11,8 @@ import monitored import os import re -from htmlrenamer import html_interface_renames, typed_array_renames +from htmlrenamer import custom_html_constructors, html_interface_renames, \ + typed_array_renames _pure_interfaces = monitored.Set('generator._pure_interfaces', [ # TODO(sra): DOMStringMap should be a class implementing Map<String,String>. @@ -313,7 +314,8 @@ info.idl_args = idl_args info.declared_name = name info.name = name - info.constructor_name = None + info.constructor_name = ('_' if interface.id in custom_html_constructors + else None) info.js_name = name info.type_name = interface.id info.param_infos = _BuildArguments(idl_args, interface, constructor=True)
diff --git a/tools/dom/scripts/htmldartgenerator.py b/tools/dom/scripts/htmldartgenerator.py index 7b7ca8e..97fa1ba 100644 --- a/tools/dom/scripts/htmldartgenerator.py +++ b/tools/dom/scripts/htmldartgenerator.py
@@ -11,9 +11,9 @@ DartDomNameOfAttribute, FindMatchingAttribute, \ TypeOrNothing, ConvertToFuture, GetCallbackInfo from copy import deepcopy -from htmlrenamer import convert_to_future_members, keep_overloaded_members, \ - private_html_members, dom_private_html_members, renamed_html_members, renamed_overloads, \ - removed_html_members +from htmlrenamer import convert_to_future_members, custom_html_constructors, \ + keep_overloaded_members, private_html_members, dom_private_html_members, renamed_html_members, \ + renamed_overloads, removed_html_members import logging import monitored import sys @@ -598,7 +598,8 @@ if not self._members_emitter: return - if base_class != self.RootClassName(): + if (base_class != self.RootClassName() and + self._interface.id not in custom_html_constructors): self._members_emitter.Emit( ' // To suppress missing implicit constructor warnings.\n' ' factory $CLASSNAME._() { '
diff --git a/tools/dom/scripts/htmlrenamer.py b/tools/dom/scripts/htmlrenamer.py index 791591b..7f85044 100644 --- a/tools/dom/scripts/htmlrenamer.py +++ b/tools/dom/scripts/htmlrenamer.py
@@ -161,6 +161,13 @@ 'EventTarget.removeEventListener', ]) +# Classes where we have customized constructors, but we need to keep the old +# constructor for dispatch purposes. +custom_html_constructors = monitored.Set( + 'htmlrenamer.custom_html_constructors', [ + 'HTMLOptionElement', +]) + # Members from the standard dom that should not be exposed publicly in dart:html # but need to be exposed internally to implement dart:html on top of a standard # browser. They are exposed simply by placing an underscore in front of the
diff --git a/tools/dom/scripts/systemhtml.py b/tools/dom/scripts/systemhtml.py index 7c5ec12..8c5aa83 100644 --- a/tools/dom/scripts/systemhtml.py +++ b/tools/dom/scripts/systemhtml.py
@@ -593,6 +593,20 @@ self._backend.AddConstructors( constructors, factory_provider, factory_constructor_name) + isElement = False + for parent in self._database.Hierarchy(self._interface): + if parent.id == 'Element': + isElement = True + if isElement and self._interface.id != 'Element': + self._implementation_members_emitter.Emit( + ' /**\n' + ' * Constructor instantiated by the DOM when a custom element has been created.\n' + ' *\n' + ' * This can only be called by subclasses from their created constructor.\n' + ' */\n' + ' $CLASSNAME.created() : super.created();\n', + CLASSNAME=self._interface_type_info.implementation_name()) + self._backend.EmitSupportCheck() merged_interface = self._interface_type_info.merged_interface()
diff --git a/tools/dom/scripts/systemnative.py b/tools/dom/scripts/systemnative.py index 8dbe0e2..1235e80 100644 --- a/tools/dom/scripts/systemnative.py +++ b/tools/dom/scripts/systemnative.py
@@ -551,7 +551,8 @@ [attr], 'void', False, - 'SetterRaisesException' in attr.ext_attrs) + 'SetterRaisesException' in attr.ext_attrs, + requires_custom_element_callback=True) def AddIndexer(self, element_type): """Adds all the methods required to complete implementation of List.""" @@ -730,7 +731,8 @@ arguments, return_type, return_type_is_nullable, - raises_dom_exception): + raises_dom_exception, + requires_custom_element_callback=False): ext_attrs = node.ext_attrs @@ -789,7 +791,7 @@ if 'Reflect' in ext_attrs: cpp_arguments = [self._GenerateWebCoreReflectionAttributeName(node)] - if ext_attrs.get('CustomElementCallbacks') == 'Enable': + if ext_attrs.get('CustomElementCallbacks') == 'Enable' or requires_custom_element_callback: self._cpp_impl_includes.add('"core/dom/CustomElementCallbackDispatcher.h"') needs_custom_element_callbacks = True
diff --git a/tools/dom/src/dart2js_CustomElementSupport.dart b/tools/dom/src/dart2js_CustomElementSupport.dart index aa2c8f0..a3fa0bf 100644 --- a/tools/dom/src/dart2js_CustomElementSupport.dart +++ b/tools/dom/src/dart2js_CustomElementSupport.dart
@@ -5,7 +5,7 @@ part of dart.dom.html; _callCreated(receiver) { - return receiver.created(); + return receiver.createdCallback(); } _callEnteredView(receiver) { @@ -15,6 +15,9 @@ _callLeftView(receiver) { return receiver.leftView(); } + _callAttributeChanged(receiver, name, oldValue, newValue) { + return receiver.attributeChanged(name, oldValue, newValue); +} _makeCallbackMethod(callback) { return JS('', @@ -26,6 +29,16 @@ convertDartClosureToJS(callback, 1)); } +_makeCallbackMethod3(callback) { + return JS('', + '''((function(invokeCallback) { + return function(arg1, arg2, arg3) { + return invokeCallback(this, arg1, arg2, arg3); + }; + })(#))''', + convertDartClosureToJS(callback, 4)); +} + const _typeNameToTag = const { 'HTMLAnchorElement': 'a', 'HTMLAudioElement': 'audio', @@ -91,6 +104,8 @@ JS('=Object', '{value: #}', _makeCallbackMethod(_callEnteredView))); JS('void', '#.leftViewCallback = #', properties, JS('=Object', '{value: #}', _makeCallbackMethod(_callLeftView))); + JS('void', '#.attributeChangedCallback = #', properties, + JS('=Object', '{value: #}', _makeCallbackMethod3(_callAttributeChanged))); // TODO(blois): Bug 13220- remove once transition is complete JS('void', '#.enteredDocumentCallback = #', properties, @@ -117,3 +132,8 @@ JS('void', '#.register(#, #)', document, tag, options); } + +//// Called by Element.created to do validation & initialization. +void _initializeCustomElement(Element e) { + // TODO(blois): Add validation that this is only in response to an upgrade. +}
diff --git a/tools/dom/src/native_DOMImplementation.dart b/tools/dom/src/native_DOMImplementation.dart index 8991ee1..2c82ddd 100644 --- a/tools/dom/src/native_DOMImplementation.dart +++ b/tools/dom/src/native_DOMImplementation.dart
@@ -106,7 +106,6 @@ static window() native "Utils_window"; static forwardingPrint(String message) native "Utils_forwardingPrint"; - static void spawnDomFunction(Function f, int replyTo) native "Utils_spawnDomFunction"; static int _getNewIsolateId() native "Utils_getNewIsolateId"; // The following methods were added for debugger integration to make working @@ -289,6 +288,10 @@ if (_isBuiltinType(cls)) { throw new UnsupportedError("Invalid custom element from $libName."); } + var className = MirrorSystem.getName(cls.simpleName); + if (!cls.constructors.containsKey(new Symbol('$className.created'))) { + throw new UnsupportedError('Class is missing constructor $className.created'); + } _register(document, tag, type, extendsTagName); } @@ -296,13 +299,8 @@ String extendsTagName) native "Utils_register"; static Element createElement(Document document, String tagName) native "Utils_createElement"; -} -class _NPObject extends NativeFieldWrapperClass1 { - _NPObject.internal(); - static _NPObject retrieve(String key) native "NPObject_retrieve"; - property(String propertyName) native "NPObject_property"; - invoke(String methodName, [List args = null]) native "NPObject_invoke"; + static void initializeCustomElement(HtmlElement element) native "Utils_initializeCustomElement"; } class _DOMWindowCrossFrame extends NativeFieldWrapperClass1 implements @@ -366,79 +364,10 @@ bool get isNotEmpty => Maps.isNotEmpty(this); } -// TODO(vsm): Remove DOM isolate code. This is only used to support -// printing and timers in background isolates. Background isolates -// should just forward to the main DOM isolate instead of requiring a -// special DOM isolate. - -_makeSendPortFuture(spawnRequest) { - final completer = new Completer<SendPort>.sync(); - final port = new ReceivePort(); - port.receive((result, _) { - completer.complete(result); - port.close(); - }); - // TODO: SendPort.hashCode is ugly way to access port id. - spawnRequest(port.toSendPort().hashCode); - return completer.future; -} - -Future<SendPort> _spawnDomFunction(Function f) => - _makeSendPortFuture((portId) { _Utils.spawnDomFunction(f, portId); }); - -final Future<SendPort> __HELPER_ISOLATE_PORT = - _spawnDomFunction(_helperIsolateMain); - -// Tricky part. -// Once __HELPER_ISOLATE_PORT gets resolved, it will still delay in .then -// and to delay Timer.run is used. However, Timer.run will try to register -// another Timer and here we got stuck: event cannot be posted as then -// callback is not executed because it's delayed with timer. -// Therefore once future is resolved, it's unsafe to call .then on it -// in Timer code. -SendPort __SEND_PORT; - -_sendToHelperIsolate(msg, SendPort replyTo) { - if (__SEND_PORT != null) { - __SEND_PORT.send(msg, replyTo); - } else { - __HELPER_ISOLATE_PORT.then((port) { - __SEND_PORT = port; - __SEND_PORT.send(msg, replyTo); - }); - } -} - -final _TIMER_REGISTRY = new Map<SendPort, Timer>(); - -const _NEW_TIMER = 'NEW_TIMER'; -const _CANCEL_TIMER = 'CANCEL_TIMER'; -const _TIMER_PING = 'TIMER_PING'; -const _PRINT = 'PRINT'; - -_helperIsolateMain() { - port.receive((msg, replyTo) { - final cmd = msg[0]; - if (cmd == _NEW_TIMER) { - final duration = new Duration(milliseconds: msg[1]); - bool periodic = msg[2]; - ping() { replyTo.send(_TIMER_PING); }; - _TIMER_REGISTRY[replyTo] = periodic ? - new Timer.periodic(duration, (_) { ping(); }) : - new Timer(duration, ping); - } else if (cmd == _CANCEL_TIMER) { - _TIMER_REGISTRY.remove(replyTo).cancel(); - } else if (cmd == _PRINT) { - final message = msg[1]; - // TODO(antonm): we need somehow identify those isolates. - print('[From isolate] $message'); - } - }); -} - final _printClosure = window.console.log; final _pureIsolatePrintClosure = (s) { - _sendToHelperIsolate([_PRINT, s], null); + throw new UnimplementedError("Printing from a background isolate " + "is not supported in the browser"); }; final _forwardingPrintClosure = _Utils.forwardingPrint; @@ -477,43 +406,11 @@ return new _Timer(milliSeconds, callback, repeating); }; - -class _PureIsolateTimer implements Timer { - bool _isActive = true; - final ReceivePort _port = new ReceivePort(); - SendPort _sendPort; // Effectively final. - - static SendPort _SEND_PORT; - - _PureIsolateTimer(int milliSeconds, callback, repeating) { - _sendPort = _port.toSendPort(); - _port.receive((msg, replyTo) { - assert(msg == _TIMER_PING); - _isActive = repeating; - callback(this); - if (!repeating) _cancel(); - }); - - _send([_NEW_TIMER, milliSeconds, repeating]); - } - - void cancel() { - _cancel(); - _send([_CANCEL_TIMER]); - } - - void _cancel() { - _isActive = false; - _port.close(); - } - - _send(msg) { - _sendToHelperIsolate(msg, _sendPort); - } - - bool get isActive => _isActive; -} - get _pureIsolateTimerFactoryClosure => ((int milliSeconds, void callback(Timer time), bool repeating) => - new _PureIsolateTimer(milliSeconds, callback, repeating)); + throw new UnimplementedError("Timers on background isolates " + "are not supported in the browser")); + +void _initializeCustomElement(Element e) { + _Utils.initializeCustomElement(e); +}
diff --git a/tools/dom/src/native_DOMPublic.dart b/tools/dom/src/native_DOMPublic.dart deleted file mode 100644 index f38c63d..0000000 --- a/tools/dom/src/native_DOMPublic.dart +++ /dev/null
@@ -1,28 +0,0 @@ -// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -part of html; - -// testRunner implementation. -// FIXME: provide a separate lib for testRunner. - -var _testRunner; - -TestRunner get testRunner { - if (_testRunner == null) - _testRunner = new TestRunner._(_NPObject.retrieve("testRunner")); - return _testRunner; -} - -class TestRunner { - final _NPObject _npObject; - - TestRunner._(this._npObject); - - display() => _npObject.invoke('display'); - dumpAsText() => _npObject.invoke('dumpAsText'); - notifyDone() => _npObject.invoke('notifyDone'); - setCanOpenWindows() => _npObject.invoke('setCanOpenWindows'); - waitUntilDone() => _npObject.invoke('waitUntilDone'); -}
diff --git a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate index bf62f8b..554ad3f 100644 --- a/tools/dom/templates/html/dart2js/html_dart2js.darttemplate +++ b/tools/dom/templates/html/dart2js/html_dart2js.darttemplate
@@ -119,8 +119,20 @@ // Dart issue 1990. class HtmlElement extends Element native "HTMLElement" { factory HtmlElement() { throw new UnsupportedError("Not supported"); } + + /** + * Constructor instantiated by the DOM when a custom element has been created. + * + * This can only be called by subclasses from their created constructor. + */ + HtmlElement.created() : super.created(); } +// EntryArray type was removed, so explicitly adding it to allow support for +// older Chrome versions. +// Issue #12573. +abstract class _EntryArray implements List<Entry> native "EntryArray" {} + // Support for Send/ReceivePortSync. int _getNewIsolateId() { if (JS('bool', r'!window.$dart$isolate$counter')) {
diff --git a/tools/dom/templates/html/dartium/html_dartium.darttemplate b/tools/dom/templates/html/dartium/html_dartium.darttemplate index cde3552..ca7cc03 100644 --- a/tools/dom/templates/html/dartium/html_dartium.darttemplate +++ b/tools/dom/templates/html/dartium/html_dartium.darttemplate
@@ -81,7 +81,6 @@ part '$AUXILIARY_DIR/dartium_KeyEvent.dart'; part '$AUXILIARY_DIR/dartium_Platform.dart'; -part '$AUXILIARY_DIR/native_DOMPublic.dart'; part '$AUXILIARY_DIR/native_DOMImplementation.dart'; Window _window;
diff --git a/tools/dom/templates/html/impl/impl_Document.darttemplate b/tools/dom/templates/html/impl/impl_Document.darttemplate index 7cc7f09..3e66c9c 100644 --- a/tools/dom/templates/html/impl/impl_Document.darttemplate +++ b/tools/dom/templates/html/impl/impl_Document.darttemplate
@@ -9,7 +9,6 @@ { $!MEMBERS - /** * Finds all descendant elements of this document that match the specified * group of selectors.
diff --git a/tools/dom/templates/html/impl/impl_Element.darttemplate b/tools/dom/templates/html/impl/impl_Element.darttemplate index 5732c1e..100e017 100644 --- a/tools/dom/templates/html/impl/impl_Element.darttemplate +++ b/tools/dom/templates/html/impl/impl_Element.darttemplate
@@ -334,6 +334,30 @@ } /** + * Custom element creation constructor. + * + * This constructor is used by the DOM when a custom element has been + * created. It can only be invoked by subclasses of Element from + * that classes created constructor. + * + * class CustomElement extends Element { + * factory CustomElement() => new Element.tag('x-custom'); + * + * CustomElement.created() : super.created() { + * // Perform any element initialization. + * } + * } + * document.register('x-custom', CustomElement); + */ + Element.created() : super._created() { + // Validate that this is a custom element & perform any additional + // initialization. + _initializeCustomElement(this); + + createdCallback(); + } + + /** * Creates the HTML element specified by the tag name. * * This is similar to [Document.createElement]. @@ -676,9 +700,12 @@ /** * Called by the DOM when this element has been instantiated. + * + * Will be replaced by created constructor. */ @Experimental() - void created() {} + @deprecated + void createdCallback() {} /** * Called by the DOM when this element has been inserted into the live @@ -694,6 +721,11 @@ @Experimental() void leftView() {} + /** + * Called by the DOM whenever an attribute on this has been changed. + */ + void attributeChanged(String name, String oldValue, String newValue) {} + // Hooks to support custom WebComponents. $if DART2JS
diff --git a/tools/dom/templates/html/impl/impl_EventTarget.darttemplate b/tools/dom/templates/html/impl/impl_EventTarget.darttemplate index 60f8fcc..06b24fb 100644 --- a/tools/dom/templates/html/impl/impl_EventTarget.darttemplate +++ b/tools/dom/templates/html/impl/impl_EventTarget.darttemplate
@@ -60,6 +60,9 @@ */ $(ANNOTATIONS)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC { + // Custom element created callback. + EventTarget._created(); + /** * This is an ease-of-use accessor for event streams which should only be * used when an explicit accessor is not available.
diff --git a/tools/dom/templates/html/impl/impl_HTMLOptionElement.darttemplate b/tools/dom/templates/html/impl/impl_HTMLOptionElement.darttemplate new file mode 100644 index 0000000..b40c7be --- /dev/null +++ b/tools/dom/templates/html/impl/impl_HTMLOptionElement.darttemplate
@@ -0,0 +1,13 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +part of $LIBRARYNAME; + +$(ANNOTATIONS)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC { + factory OptionElement({String data, String value, bool defaultSelected, + bool selected}) { + return new OptionElement._(data, value, defaultSelected, selected); + } +$!MEMBERS +}
diff --git a/tools/dom/templates/html/impl/impl_Node.darttemplate b/tools/dom/templates/html/impl/impl_Node.darttemplate index 8f2fc4a..b93bbc7 100644 --- a/tools/dom/templates/html/impl/impl_Node.darttemplate +++ b/tools/dom/templates/html/impl/impl_Node.darttemplate
@@ -201,6 +201,10 @@ $(ANNOTATIONS)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC { + + // Custom element created callback. + Node._created() : super._created(); + List<Node> get nodes { return new _ChildNodeListLazy(this); }
diff --git a/tools/dom/templates/html/impl/impl_XMLHttpRequest.darttemplate b/tools/dom/templates/html/impl/impl_XMLHttpRequest.darttemplate index 646d6c3..642ce56 100644 --- a/tools/dom/templates/html/impl/impl_XMLHttpRequest.darttemplate +++ b/tools/dom/templates/html/impl/impl_XMLHttpRequest.darttemplate
@@ -87,7 +87,7 @@ } /** - * Creates a URL request for the specified [url]. + * Creates and sends a URL request for the specified [url]. * * By default `request` will perform an HTTP GET request, but a different * method (`POST`, `PUT`, `DELETE`, etc) can be used by specifying the
diff --git a/tools/full-coverage.dart b/tools/full-coverage.dart new file mode 100644 index 0000000..b48da50 --- /dev/null +++ b/tools/full-coverage.dart
@@ -0,0 +1,485 @@ +// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +import "dart:async"; +import "dart:convert"; +import "dart:io"; +import "dart:isolate"; +import "dart:mirrors"; + +import "package:args/args.dart"; +import "package:path/path.dart"; + +/// [Environment] stores gathered arguments information. +class Environment { + String sdkRoot; + String pkgRoot; + var input; + var output; + int workers; + bool prettyPrint; + bool lcov; + bool expectMarkers; + bool verbose; +} + +/// [Resolver] resolves imports with respect to a given environment. +class Resolver { + const DART_PREFIX = "dart:"; + const PACKAGE_PREFIX = "package:"; + const FILE_PREFIX = "file://"; + const HTTP_PREFIX = "http://"; + + Map _env; + List failed = []; + + Resolver(this._env); + + /// Returns the absolute path wrt. to the given environment or null, if the + /// import could not be resolved. + resolve(String import) { + if (import.startsWith(DART_PREFIX)) { + var slashPos = import.indexOf("/"); + var filePath; + if (slashPos != -1) { + var path = import.substring(DART_PREFIX.length, slashPos); + // Drop patch files, since we don't have their source in the compiled + // SDK. + if (path.endsWith("-patch")) { + failed.add(import); + return null; + } + // Canonicalize path. For instance: _collection-dev => _collection_dev. + path = path.replaceAll("-", "_"); + filePath = "${_env["sdkRoot"]}" + "/${path}${import.substring(slashPos, import.length)}"; + } else { + // Resolve 'dart:something' to be something/something.dart in the SDK. + var lib = import.substring(DART_PREFIX.length, import.length); + filePath = "${_env["sdkRoot"]}/${lib}/${lib}.dart"; + } + return filePath; + } + if (import.startsWith(PACKAGE_PREFIX)) { + var filePath = + "${_env["pkgRoot"]}" + "/${import.substring(PACKAGE_PREFIX.length, import.length)}"; + return filePath; + } + if (import.startsWith(FILE_PREFIX)) { + var filePath = fromUri(Uri.parse(import)); + return filePath; + } + if (import.startsWith(HTTP_PREFIX)) { + return import; + } + // We cannot deal with anything else. + failed.add(import); + return null; + } +} + +/// Converts the given hitmap to lcov format and appends the result to +/// env.output. +/// +/// Returns a [Future] that completes as soon as all map entries have been +/// emitted. +Future lcov(Map hitmap) { + var emitOne = (key) { + var v = hitmap[key]; + StringBuffer entry = new StringBuffer(); + entry.write("SF:${key}\n"); + v.keys.toList() + ..sort() + ..forEach((k) { + entry.write("DA:${k},${v[k]}\n"); + }); + entry.write("end_of_record\n"); + env.output.write(entry.toString()); + return new Future.value(null); + }; + + return Future.forEach(hitmap.keys, emitOne); +} + +/// Converts the given hitmap to a pretty-print format and appends the result +/// to env.output. +/// +/// Returns a [Future] that completes as soon as all map entries have been +/// emitted. +Future prettyPrint(Map hitMap, List failedLoads) { + var emitOne = (key) { + var v = hitMap[key]; + var c = new Completer(); + loadResource(key).then((lines) { + if (lines == null) { + failedLoads.add(key); + c.complete(); + return; + } + env.output.write("${key}\n"); + for (var line = 1; line <= lines.length; line++) { + String prefix = " "; + if (v.containsKey(line)) { + prefix = v[line].toString(); + StringBuffer b = new StringBuffer(); + for (int i = prefix.length; i < 7; i++) { + b.write(" "); + } + b.write(prefix); + prefix = b.toString(); + } + env.output.write("${prefix}|${lines[line-1]}\n"); + } + c.complete(); + }); + return c.future; + }; + + return Future.forEach(hitMap.keys, emitOne); +} + +/// Load an import resource and return a [Future] with a [List] of its lines. +/// Returns [null] instead of a list if the resource could not be loaded. +Future<List> loadResource(String import) { + if (import.startsWith("http")) { + Completer c = new Completer(); + HttpClient client = new HttpClient(); + client.getUrl(Uri.parse(import)) + .then((HttpClientRequest request) { + return request.close(); + }) + .then((HttpClientResponse response) { + response.transform(new StringDecoder()).toList().then((data) { + c.complete(data); + httpClient.close(); + }); + }) + .catchError((e) { + c.complete(null); + }); + return c.future; + } else { + File f = new File(import); + return f.readAsLines() + .catchError((e) { + return new Future.value(null); + }); + } +} + +/// Creates a single hitmap from a raw json object. Throws away all entries that +/// are not resolvable. +Map createHitmap(String rawJson, Resolver resolver) { + Map<String, Map<int,int>> hitMap = {}; + + addToMap(source, line, count) { + if (!hitMap[source].containsKey(line)) { + hitMap[source][line] = 0; + } + hitMap[source][line] += count; + } + + JSON.decode(rawJson).forEach((Map e) { + String source = resolver.resolve(e["source"]); + if (source == null) { + // Couldnt resolve import, so skip this entry. + return; + } + if (!hitMap.containsKey(source)) { + hitMap[source] = {}; + } + var hits = e["hits"]; + // hits is a flat array of the following format: + // [ <line|linerange>, <hitcount>,...] + // line: number. + // linerange: "<line>-<line>". + for (var i = 0; i < hits.length; i += 2) { + var k = hits[i]; + if (k is num) { + // Single line. + addToMap(source, k, hits[i+1]); + } + if (k is String) { + // Linerange. We expand line ranges to actual lines at this point. + var splitPos = k.indexOf("-"); + int start = int.parse(k.substring(0, splitPos)); + int end = int.parse(k.substring(splitPos + 1, k.length)); + for (var j = start; j <= end; j++) { + addToMap(source, j, hits[i+1]); + } + } + } + }); + return hitMap; +} + +/// Merges [newMap] into [result]. +mergeHitmaps(Map newMap, Map result) { + newMap.forEach((String file, Map v) { + if (result.containsKey(file)) { + v.forEach((int line, int cnt) { + if (result[file][line] == null) { + result[file][line] = cnt; + } else { + result[file][line] += cnt; + } + }); + } else { + result[file] = v; + } + }); +} + +/// Given an absolute path absPath, this function returns a [List] of files +/// are contained by it if it is a directory, or a [List] containing the file if +/// it is a file. +List filesToProcess(String absPath) { + if (FileSystemEntity.isDirectorySync(absPath)) { + Directory d = new Directory(absPath); + List files = []; + d.listSync(recursive: true).forEach((FileSystemEntity entity) { + if (entity is File) { + files.add(entity as File); + } + }); + return files; + } else if (FileSystemEntity.isFileSync(absPath)) { + return [ new File(absPath) ]; + } +} + +worker() { + final start = new DateTime.now().millisecondsSinceEpoch; + String me = currentMirrorSystem().isolate.debugName; + + port.receive((Message message, reply) { + if (message.type == Message.SHUTDOWN) { + port.close(); + } + + if (message.type == Message.WORK) { + var env = message.payload[0]; + List files = message.payload[1]; + Resolver resolver = new Resolver(env); + var workerHitmap = {}; + files.forEach((File fileEntry) { + // Read file sync, as it only contains 1 object. + String contents = fileEntry.readAsStringSync(); + if (contents.length > 0) { + mergeHitmaps(createHitmap(contents, resolver), workerHitmap); + } + }); + if (env["verbose"]) { + final end = new DateTime.now().millisecondsSinceEpoch; + print("worker[${me}]: Finished processing files. " + "Took ${end - start} ms."); + } + reply.send(new Message(Message.RESULT, [workerHitmap, resolver.failed])); + } + + }); +} + +class Message { + static const int SHUTDOWN = 1; + static const int RESULT = 2; + static const int WORK = 3; + + final int type; + final payload; + + Message(this.type, this.payload); +} + +final env = new Environment(); + +main() { + parseArgs(); + + List files = filesToProcess(env.input); + int filesPerWorker = files.length ~/ env.workers; + List workerPorts = []; + int doneCnt = 0; + + List failedResolves = []; + List failedLoads = []; + Map globalHitmap = {}; + int start = new DateTime.now().millisecondsSinceEpoch; + + if (env.verbose) { + print("Environment:"); + print(" # files: ${files.length}"); + print(" # workers: ${env.workers}"); + print(" sdk-root: ${env.sdkRoot}"); + print(" package-root: ${env.pkgRoot}"); + } + + port.receive((Message message, reply) { + if (message.type == Message.RESULT) { + mergeHitmaps(message.payload[0], globalHitmap); + failedResolves.addAll(message.payload[1]); + doneCnt++; + } + + // All workers are done. Process the data. + if (doneCnt == env.workers) { + workerPorts.forEach((p) => p.send(new Message(Message.SHUTDOWN, null))); + if (env.verbose) { + final end = new DateTime.now().millisecondsSinceEpoch; + print("Done creating a global hitmap. Took ${end - start} ms."); + } + + Future out; + if (env.prettyPrint) { + out = prettyPrint(globalHitmap, failedLoads); + } + if (env.lcov) { + out = lcov(globalHitmap); + } + + out.then((_) { + env.output.close().then((_) { + if (env.verbose) { + final end = new DateTime.now().millisecondsSinceEpoch; + print("Done flushing output. Took ${end - start} ms."); + } + }); + port.close(); + + if (env.verbose) { + if (failedResolves.length > 0) { + print("Failed to resolve:"); + failedResolves.toSet().forEach((e) { + print(" ${e}"); + }); + } + if (failedLoads.length > 0) { + print("Failed to load:"); + failedLoads.toSet().forEach((e) { + print(" ${e}"); + }); + } + } + + }); + } + }); + + Map sharedEnv = { + "sdkRoot": env.sdkRoot, + "pkgRoot": env.pkgRoot, + "verbose": env.verbose, + }; + + // Create workers. + for (var i = 1; i < env.workers; i++) { + var p = spawnFunction(worker); + workerPorts.add(p); + var start = files.length - filesPerWorker; + var end = files.length; + var workerFiles = files.getRange(start, end).toList(); + files.removeRange(start, end); + p.send(new Message(Message.WORK, [sharedEnv, workerFiles]), port); + } + // Let the last worker deal with the rest of the files (which should be only + // off by at max (#workers - 1). + var p = spawnFunction(worker); + workerPorts.add(p); + p.send(new Message(Message.WORK, [sharedEnv, files]), port); + + return 0; +} + +/// Checks the validity of the provided arguments. Does not initialize actual +/// processing. +parseArgs() { + var parser = new ArgParser(); + + parser.addOption("sdk-root", abbr: "s", + help: "path to the SDK root"); + parser.addOption("package-root", abbr: "p", + help: "path to the package root", + defaultsTo: "."); + parser.addOption("in", abbr: "i", + help: "input(s): may be file or directory", + defaultsTo: "stdin"); + parser.addOption("out", abbr: "o", + help: "output: may be file or stdout", + defaultsTo: "stdout"); + parser.addOption("workers", abbr: "j", + help: "number of workers", + defaultsTo: "1"); + parser.addFlag("pretty-print", abbr: "r", + help: "convert coverage data to pretty print format", + negatable: false); + parser.addFlag("lcov", abbr :"l", + help: "convert coverage data to lcov format", + negatable: false); + parser.addFlag("verbose", abbr :"v", + help: "verbose output", + negatable: false); + parser.addFlag("help", abbr: "h", + help: "show this help", + negatable: false); + + var args = parser.parse(new Options().arguments); + + if (args["help"]) { + print("Usage: coverage [OPTION...]\n"); + print(parser.getUsage()); + exit(0); + } + + if (args["sdk-root"] == null) { + if (Platform.environment.containsKey("SDK_ROOT")) { + env.sdkRoot = + join(absolute(normalize(Platform.environment["SDK_ROOT"])), "lib"); + } else { + throw "No SDK root found, please specify one using --sdk-root."; + } + } else { + env.sdkRoot = join(absolute(normalize(args["sdk-root"])), "lib"); + } + if (!FileSystemEntity.isDirectorySync(env.sdkRoot)) { + throw "Provided SDK root ${args["sdk-root"]} is not a valid SDK " + "top-level directory"; + } + + if (args["package-root"] == null) { + env.pkgRoot = absolute(normalize("./packages")); + } else { + env.pkgRoot = absolute(normalize(args["package-root"])); + if (!FileSystemEntity.isDirectorySync(env.pkgRoot)) { + throw "Provided package root ${args["package-root"]} is not directory."; + } + } + + if (args["in"] == "stdin") { + env.input = "stdin"; + } else { + env.input = absolute(normalize(args["in"])); + if (!FileSystemEntity.isDirectorySync(env.input) && + !FileSystemEntity.isFileSync(env.input)) { + throw "Provided input ${args["in"]} is neither a directory, nor a file."; + } + } + + if (args["out"] == "stdout") { + env.output = stdout; + } else { + env.output = absolute(normalize(args["out"])); + env.output = new File(env.output).openWrite(); + } + + if (args["pretty-print"] && + args["lcov"]) { + throw "Choose either pretty-print or lcov output"; + } + + env.prettyPrint = args["pretty-print"]; + env.lcov = args["lcov"]; + env.verbose = args["verbose"]; + env.workers = int.parse("${args["workers"]}"); +}
diff --git a/tools/testing/dart/browser_controller.dart b/tools/testing/dart/browser_controller.dart index f370863..b8727ea 100644 --- a/tools/testing/dart/browser_controller.dart +++ b/tools/testing/dart/browser_controller.dart
@@ -53,6 +53,8 @@ return new Firefox(); } else if (name == 'chrome') { return new Chrome(); + } else if (name == 'dartium') { + return new Dartium(); } else if (name == 'safari') { return new Safari(); } else if (name.startsWith('ie')) { @@ -63,7 +65,7 @@ } static const List<String> SUPPORTED_BROWSERS = - const ['safari', 'ff', 'firefox', 'chrome', 'ie9', 'ie10']; + const ['safari', 'ff', 'firefox', 'chrome', 'ie9', 'ie10', 'dartium']; static const List<String> BROWSERS_WITH_WINDOW_SUPPORT = const ['safari', 'ff', 'firefox', 'chrome']; @@ -109,8 +111,11 @@ * Start the browser using the supplied argument. * This sets up the error handling and usage logging. */ - Future<bool> startBrowser(String command, List<String> arguments) { - return Process.start(command, arguments).then((startedProcess) { + Future<bool> startBrowser(String command, + List<String> arguments, + {Map<String,String> environment}) { + return Process.start(command, arguments, environment: environment) + .then((startedProcess) { process = startedProcess; // Used to notify when exiting, and as a return value on calls to // close(). @@ -316,24 +321,25 @@ class Chrome extends Browser { - static String _binary = _getBinary(); - + String _binary; String _version = "Version not found yet"; - // This is extracted to a function since we may need to support several - // locations. - static String _getWindowsBinary() { - return "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe"; + Chrome() { + _binary = _getBinary(); } - static String _getBinary() { - if (Platform.isWindows) return _getWindowsBinary(); - if (Platform.isMacOS) { + String _getBinary() { + if (Platform.isWindows) { + return "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe"; + } else if (Platform.isMacOS) { return "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"; } - if (Platform.isLinux) return 'google-chrome'; + assert(Platform.isLinux); + return 'google-chrome'; } + Map<String, String> _getEnvironment() => null; + Future<bool> _getVersion() { if (Platform.isWindows) { // The version flag does not work on windows. @@ -375,7 +381,7 @@ var args = ["--user-data-dir=${userDir.path}", url, "--disable-extensions", "--disable-popup-blocking", "--bwsi", "--no-first-run"]; - return startBrowser(_binary, args); + return startBrowser(_binary, args, environment: _getEnvironment()); }); }).catchError((e) { _logEvent("Running $_binary --version failed with $e"); @@ -386,6 +392,27 @@ String toString() => "Chrome"; } +class Dartium extends Chrome { + String _getBinary() { + if (Platform.operatingSystem == 'macos') { + return new Path('client/tests/dartium/Chromium.app/Contents/' + 'MacOS/Chromium').toNativePath(); + } + return new Path('client/tests/dartium/chrome').toNativePath(); + } + + Map<String, String> _getEnvironment() { + var environment = new Map<String,String>.from(Platform.environment); + // By setting this environment variable, dartium will forward "print()" + // calls in dart to the top-level javascript function "dartPrint()" if + // available. + environment['DART_FORWARDING_PRINT'] = '1'; + return environment; + } + + String toString() => "Dartium"; +} + class IE extends Browser { static const String binary = @@ -619,7 +646,7 @@ // If we do we need to provide developers with this information. // We don't add urls to the cache until we have run it. Map<int, String> testCache = new Map<int, String>(); - List<int> doubleReportingTests = new List<int>(); + Map<int, String> doubleReportingOutputs = new Map<int, String>(); BrowserTestingServer testingServer; @@ -696,7 +723,7 @@ void handleResults(String browserId, String output, int testId) { var status = browserStatus[browserId]; if (testCache.containsKey(testId)) { - doubleReportingTests.add(testId); + doubleReportingOutputs[testId] = output; return; } @@ -831,15 +858,23 @@ } void printDoubleReportingTests() { - if (doubleReportingTests.length == 0) return; + if (doubleReportingOutputs.length == 0) return; // TODO(ricow): die on double reporting. // Currently we just report this here, we could have a callback to the // encapsulating environment. print(""); print("Double reporting tests"); - for (var id in doubleReportingTests) { + for (var id in doubleReportingOutputs.keys) { print(" ${testCache[id]}"); } + + DebugLogger.warning("Double reporting tests:"); + for (var id in doubleReportingOutputs.keys) { + DebugLogger.warning("${testCache[id]}, output: "); + DebugLogger.warning("${doubleReportingOutputs[id]}"); + DebugLogger.warning(""); + DebugLogger.warning(""); + } } Future<bool> terminate() {
diff --git a/tools/testing/dart/browser_test.dart b/tools/testing/dart/browser_test.dart index dbfd7e5..e37d029 100644 --- a/tools/testing/dart/browser_test.dart +++ b/tools/testing/dart/browser_test.dart
@@ -55,7 +55,7 @@ </html> """; -String dartTestWrapper(bool usePackageImport, String libraryPathComponent) { +String dartUnittestWrapper(bool usePackageImport, String libraryPathComponent) { // Tests inside "pkg" import unittest using "package:". All others use a // relative path. The imports need to agree, so use a matching form here. var unitTest; @@ -77,3 +77,15 @@ } """; } + +String dartTestWrapper(String libraryPathComponent) { + return """ +import '$libraryPathComponent' as test; + +main() { + print("dart-calling-main"); + test.main(); + print("dart-main-done"); +} +"""; +} \ No newline at end of file
diff --git a/tools/testing/dart/co19_test.dart b/tools/testing/dart/co19_test.dart index dd92951..db7a6b1 100644 --- a/tools/testing/dart/co19_test.dart +++ b/tools/testing/dart/co19_test.dart
@@ -41,6 +41,8 @@ '--minified'], const <String>['-mrelease', '-rd8,jsshell', '-cdart2js', '--use-sdk', '--checked'], + const <String>['-mrelease', '-rdartium', '-cnone', '--use-sdk', + '--use_browser_controller', '--write-debug-log'], ]; void main() {
diff --git a/tools/testing/dart/test_options.dart b/tools/testing/dart/test_options.dart index dc0f5ff..38d45a7 100644 --- a/tools/testing/dart/test_options.dart +++ b/tools/testing/dart/test_options.dart
@@ -452,7 +452,7 @@ Set<String> _blacklistedOptions = new Set<String>.from([ 'progress', 'failure-summary', 'step_name', 'report', 'tasks', 'verbose', 'time', 'dart', 'drt', 'dartium', 'build_directory', 'append_logs', - 'write_debug_log', 'local_ip', 'shard', 'shards', + 'local_ip', 'shard', 'shards', ]); List<String> _constructReproducingCommandArguments(Map config) { @@ -676,7 +676,7 @@ if (configuration['mode'] == 'debug') { timeout *= 2; } - if (const ['drt', 'dartium'].contains(configuration['runtime'])) { + if (const ['drt'].contains(configuration['runtime'])) { timeout *= 4; // Allow additional time for browser testing to run. } break;
diff --git a/tools/testing/dart/test_runner.dart b/tools/testing/dart/test_runner.dart index b93c3de..0a2e31f 100644 --- a/tools/testing/dart/test_runner.dart +++ b/tools/testing/dart/test_runner.dart
@@ -1154,14 +1154,6 @@ return Expectation.PASS; } - // We're not as strict, if the exitCode indicated an uncaught exception - // we say it passed nonetheless - // TODO(kustermann): As soon as the VM team makes sure we get correct - // exit codes, we should remove this. - if (exitCode == DART_VM_EXITCODE_UNCAUGHT_EXCEPTION) { - return Expectation.PASS; - } - return Expectation.MISSING_COMPILETIME_ERROR; } if (testCase.info.hasRuntimeError) {
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart index e98f6f1..64a495f 100644 --- a/tools/testing/dart/test_suite.dart +++ b/tools/testing/dart/test_suite.dart
@@ -712,6 +712,7 @@ enqueueStandardTest(info, testName, expectations); } else if (TestUtils.isBrowserRuntime(configuration['runtime'])) { bool isWrappingRequired = configuration['compiler'] != 'dart2js'; + if (info.optionsFromFile['isMultiHtmlTest']) { // A browser multi-test has multiple expectations for one test file. // Find all the different sub-test expecations for one entire test file. @@ -917,14 +918,25 @@ return url; } - void _createWrapperFile(String dartWrapperFilename, dartLibraryFilename) { + void _createWrapperFile(String dartWrapperFilename, + Path dartLibraryFilename, + {bool useUnittestWrapper: false}) { File file = new File(dartWrapperFilename); RandomAccessFile dartWrapper = file.openSync(mode: FileMode.WRITE); var usePackageImport = dartLibraryFilename.segments().contains("pkg"); var libraryPathComponent = _createUrlPathFromFile(dartLibraryFilename); - dartWrapper.writeStringSync(dartTestWrapper(usePackageImport, - libraryPathComponent)); + var generatedSource; + if (useUnittestWrapper) { + // FIXME(kustermann): This is broken, we can't do unittest-based wrapping + // of tests (e.g. async operations are not wrapped in expectAsync()). + generatedSource = dartUnittestWrapper(usePackageImport, + libraryPathComponent); + } else { + generatedSource = dartTestWrapper(libraryPathComponent); + } + + dartWrapper.writeStringSync(generatedSource); dartWrapper.closeSync(); } @@ -987,7 +999,6 @@ // Use existing HTML document if available. String htmlPath; if (customHtml.existsSync()) { - // If necessary, run the Polymer deploy steps. // TODO(jmesserly): this should be generalized for any tests that // require Pub deploy, not just polymer. @@ -1028,7 +1039,13 @@ htmlPath = '$tempDir/test.html'; if (isWrappingRequired && !isWebTest) { // test.dart will import the dart test. - _createWrapperFile(dartWrapperFilename, filePath); + if (configuration['use_browser_controller'] && + configuration['runtime'] == 'dartium') { + _createWrapperFile(dartWrapperFilename, filePath); + } else { + _createWrapperFile( + dartWrapperFilename, filePath, useUnittestWrapper: true); + } } else { dartWrapperFilename = filename; }
diff --git a/utils/peg/pegparser.dart b/utils/peg/pegparser.dart index ba1526b..8666550 100644 --- a/utils/peg/pegparser.dart +++ b/utils/peg/pegparser.dart
@@ -2,7 +2,7 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -library Peg Parser; +library PegParser; /* * The following functions are combinators for building Rules. @@ -62,7 +62,7 @@ // Find the range of character codes and construct an array of flags for codes // within the range. - List<int> codes = characters.codeUnits; + List<int> codes = characters.codeUnits.toList(); codes.sort((a, b) => a < b ? -1 : a > b ? 1 : 0); int lo = codes[0]; int hi = codes[codes.length - 1]; @@ -165,7 +165,7 @@ * MANY is a value generating matcher. The value is a list of the matches of * [rule]. The list may be empty if [:min == 0:]. */ -_Rule MANY(rule, [separator = null, int min = 1]) { +_Rule MANY(rule, {separator: null, int min: 1}) { assert(0 <= min && min <= 1); return new _RepeatRule(_compile(rule), _compileOptional(separator), min); } @@ -274,7 +274,7 @@ tokens.sort((a, b) => a.startsWith("'") == b.startsWith("'") ? a.compareTo(b) - : a.startsWith("'") ? +1 : -1); + : a.startsWith("'") ? 1 : -1); var expected = tokens.join(' or '); var found = state.max_pos == state._end ? 'end of file' : "'${state._text[state.max_pos]}'"; @@ -314,7 +314,7 @@ class _ParserState { - _ParserState(this._text, [_Rule whitespace = null]) { + _ParserState(this._text, {_Rule whitespace}) { _end = this._text.length; whitespaceRule = whitespace; max_rule = [];
diff --git a/utils/tests/peg/peg_test.dart b/utils/tests/peg/peg_test.dart index 692dc15..b48453b 100644 --- a/utils/tests/peg/peg_test.dart +++ b/utils/tests/peg/peg_test.dart
@@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. library peg_tests; +import 'dart:core' hide Symbol; import '../../peg/pegparser.dart'; testParens() { @@ -144,7 +145,7 @@ ['(', expression, ')', (e) => e] ]); - var postfixes = OR([['(', MANY(assignment_e, ',', 0), ')', binary('apply')], + var postfixes = OR([['(', MANY(assignment_e, separator: ',', min: 0), ')', binary('apply')], ['++', unary('postinc')], ['--', unary('postdec')], ['.', id, binary('field')], @@ -295,7 +296,7 @@ if (exception is ParseError) ast = exception; else - throw; + rethrow; } print('${printList(ast)}'); } @@ -315,7 +316,13 @@ if (expected is String) formatted = printList(ast); - Expect.equals(expected, formatted, "parse: $input"); + //Expect.equals(expected, formatted, "parse: $input"); + if (expected != formatted) { + throw new ArgumentError( + "parse: $input" + "\n expected: $expected" + "\n found: $formatted"); + } } // Prints the list in [1,2,3] notation, including nested lists.