fix #29182, generate top level const fields lazily

This fixes an ordering issue, but also may help load time.

R=vsm@google.com

Review-Url: https://codereview.chromium.org/2797443007 .
This commit is contained in:
Jennifer Messerly 2017-04-04 16:18:41 -07:00
parent 774f261165
commit e4e7dffadb
22 changed files with 32864 additions and 12458 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

View file

@ -41,7 +41,6 @@ import '../js_ast/js_ast.dart' show js;
import 'ast_builder.dart' show AstBuilder;
import 'compiler.dart' show BuildUnit, CompilerOptions, JSModuleFile;
import 'element_helpers.dart';
import 'element_loader.dart' show ElementLoader;
import 'extension_types.dart' show ExtensionTypeSet;
import 'js_interop.dart';
import 'js_metalet.dart' as JS;
@ -72,6 +71,10 @@ class CodeGenerator extends GeneralizingAstVisitor
/// Imported libraries, and the temporaries used to refer to them.
final _imports = new Map<LibraryElement, JS.TemporaryId>();
/// The list of dart:_runtime SDK functions; these are assumed by other code
/// in the SDK to be generated before anything else.
final _internalSdkFunctions = <JS.ModuleItem>[];
/// The list of output module items, in the order they need to be emitted in.
final _moduleItems = <JS.ModuleItem>[];
@ -105,8 +108,6 @@ class CodeGenerator extends GeneralizingAstVisitor
final _hasDeferredSupertype = new HashSet<ClassElement>();
final _eagerTopLevelFields = new HashSet<Element>.identity();
/// The type provider from the current Analysis [context].
final TypeProvider types;
@ -134,9 +135,24 @@ class CodeGenerator extends GeneralizingAstVisitor
/// The current function body being compiled.
FunctionBody _currentFunction;
/// Helper class for emitting elements in the proper order to allow
/// JS to load the module.
ElementLoader _loader;
HashMap<TypeDefiningElement, AstNode> _declarationNodes;
/// The stack of currently emitting elements, if generating top-level code
/// for them. This is not used when inside method bodies, because order does
/// not matter for those.
final _topLevelElements = <TypeDefiningElement>[];
/// The current element being loaded.
/// We can use this to determine if we're loading top-level code or not:
///
/// _currentElements.last == _topLevelElements.last
//
// TODO(jmesserly): ideally we'd only track types here, in other words,
// TypeDefiningElement. However we still rely on this for [currentLibrary] so
// we need something to be pushed always.
final _currentElements = <Element>[];
final _deferredProperties = new HashMap<PropertyAccessorElement, JS.Method>();
BuildUnit _buildUnit;
@ -182,7 +198,9 @@ class CodeGenerator extends GeneralizingAstVisitor
_getLibrary(c, 'dart:_internal').getType('PrivateSymbol'),
dartJSLibrary = _getLibrary(c, 'dart:js');
LibraryElement get currentLibrary => _loader.currentElement.library;
Element get currentElement => _currentElements.last;
LibraryElement get currentLibrary => currentElement.library;
/// The main entry point to JavaScript code generation.
///
@ -285,19 +303,17 @@ class CodeGenerator extends GeneralizingAstVisitor
}
}
// Collect all Element -> Node mappings, in case we need to forward declare
// any nodes.
var nodes = new HashMap<Element, AstNode>.identity();
var sdkBootstrappingFns = new List<FunctionElement>();
// Collect all class/type Element -> Node mappings
// in case we need to forward declare any classes.
_declarationNodes = new HashMap<TypeDefiningElement, AstNode>.identity();
for (var unit in compilationUnits) {
if (isSdkInternalRuntime(
resolutionMap.elementDeclaredByCompilationUnit(unit).library)) {
sdkBootstrappingFns.addAll(
resolutionMap.elementDeclaredByCompilationUnit(unit).functions);
for (var declaration in unit.declarations) {
var element = declaration.element;
if (element is TypeDefiningElement) {
_declarationNodes[element] = declaration;
}
}
_collectElements(unit, nodes);
}
_loader = new ElementLoader(nodes);
if (compilationUnits.isNotEmpty) {
_constants = new ConstFieldVisitor(context,
dummySource: resolutionMap
@ -308,15 +324,16 @@ class CodeGenerator extends GeneralizingAstVisitor
// Add implicit dart:core dependency so it is first.
emitLibraryName(dartCoreLibrary);
// Emit SDK bootstrapping functions first, if any.
sdkBootstrappingFns.forEach(_emitDeclaration);
// Visit each compilation unit and emit its code.
//
// NOTE: declarations are not necessarily emitted in this order.
// Order will be changed as needed so the resulting code can execute.
// This is done by forward declaring items.
compilationUnits.forEach(_finishDeclarationsInUnit);
compilationUnits.forEach(_emitCompilationUnit);
assert(_deferredProperties.isEmpty);
// Visit directives (for exports)
compilationUnits.forEach(_emitExportDirectives);
// Declare imports
_finishImports(items);
@ -324,6 +341,7 @@ class CodeGenerator extends GeneralizingAstVisitor
// Discharge the type table cache variables and
// hoisted definitions.
items.addAll(_typeTable.discharge());
items.addAll(_internalSdkFunctions);
// Track the module name for each library in the module.
// This data is only required for debugging.
@ -432,7 +450,7 @@ class CodeGenerator extends GeneralizingAstVisitor
for (var item in items) {
if (item is JS.Block && !item.isScope) {
_copyAndFlattenBlocks(result, item.statements);
} else {
} else if (item != null) {
result.add(item);
}
}
@ -485,21 +503,6 @@ class CodeGenerator extends GeneralizingAstVisitor
});
}
/// Collect toplevel elements and nodes we need to emit, and returns
/// an ordered map of these.
static void _collectElements(
CompilationUnit unit, Map<Element, AstNode> map) {
for (var declaration in unit.declarations) {
if (declaration is TopLevelVariableDeclaration) {
for (var field in declaration.variables.variables) {
map[field.element] = field;
}
} else {
map[declaration.element] = declaration;
}
}
}
/// Called to emit all top-level declarations.
///
/// During the course of emitting one item, we may emit another. For example
@ -508,40 +511,112 @@ class CodeGenerator extends GeneralizingAstVisitor
///
/// Because D depends on B, we'll emit B first if needed. However C is not
/// used by top-level JavaScript code, so we can ignore that dependency.
void _emitDeclaration(Element e) {
var item = _loader.emitDeclaration(e, (AstNode node) {
// TODO(jmesserly): this is not really the right place for this.
// Ideally we do this per function body.
//
// We'll need to be consistent about when we're generating functions, and
// only run this on the outermost function, and not any closures.
inferNullableTypes(node);
return _visit(node) as JS.Node;
});
void _emitTypeDeclaration(TypeDefiningElement e) {
var node = _declarationNodes.remove(e);
if (node == null) return null; // not from this module or already loaded.
if (item != null) _moduleItems.add(item);
_currentElements.add(e);
// TODO(jmesserly): this is not really the right place for this.
// Ideally we do this per function body.
//
// We'll need to be consistent about when we're generating functions, and
// only run this on the outermost function, and not any closures.
inferNullableTypes(node);
_moduleItems.add(_visit(node));
var last = _currentElements.removeLast();
assert(identical(e, last));
}
void _declareBeforeUse(Element e) {
_loader.declareBeforeUse(e, _emitDeclaration);
/// Start generating top-level code for the element [e].
///
/// Subsequent [emitDeclaration] calls will cause those elements to be
/// generated before this one, until [finishTopLevel] is called.
void _startTopLevelCodeForClass(TypeDefiningElement e) {
assert(identical(e, currentElement));
_topLevelElements.add(e);
}
void _finishDeclarationsInUnit(CompilationUnit unit) {
/// Finishes the top-level code for the element [e].
void _finishTopLevelCodeForClass(TypeDefiningElement e) {
var last = _topLevelElements.removeLast();
assert(identical(e, last));
}
/// To emit top-level module items, we sometimes need to reorder them.
///
/// This function takes care of that, and also detects cases where reordering
/// failed, and we need to resort to lazy loading, by marking the element as
/// lazy. All elements need to be aware of this possibility and generate code
/// accordingly.
///
/// If we are not emitting top-level code, this does nothing, because all
/// declarations are assumed to be available before we start execution.
/// See [startTopLevel].
void _declareBeforeUse(TypeDefiningElement e) {
if (e == null) return;
var topLevel = _topLevelElements;
if (topLevel.isNotEmpty && identical(currentElement, topLevel.last)) {
// If the item is from our library, try to emit it now.
_emitTypeDeclaration(e);
}
}
void _emitCompilationUnit(CompilationUnit unit) {
// NOTE: this method isn't the right place to initialize
// per-compilation-unit state. Declarations can be visited out of order,
// this is only to catch things that haven't been emitted yet.
//
// See _emitDeclaration.
// See _emitTypeDeclaration.
var library = unit.element.library;
bool internalSdk = isSdkInternalRuntime(library);
_currentElements.add(library);
List<VariableDeclaration> fields;
for (var declaration in unit.declarations) {
if (declaration is TopLevelVariableDeclaration) {
inferNullableTypes(declaration);
if (internalSdk && declaration.variables.isFinal) {
_emitInternalSdkFields(declaration.variables.variables);
} else {
(fields ??= []).addAll(declaration.variables.variables);
}
continue;
}
if (fields != null) {
_emitTopLevelFields(fields);
fields = null;
}
var element = declaration.element;
if (element != null) {
_emitDeclaration(element);
if (element is TypeDefiningElement) {
_emitTypeDeclaration(element);
continue;
}
inferNullableTypes(declaration);
var item = _visit(declaration);
if (internalSdk && element is FunctionElement) {
_internalSdkFunctions.add(item);
} else {
declaration.accept(this);
_moduleItems.add(item);
}
}
if (fields != null) _emitTopLevelFields(fields);
_currentElements.removeLast();
}
void _emitExportDirectives(CompilationUnit unit) {
for (var directive in unit.directives) {
_currentElements.add(directive.element);
directive.accept(this);
_currentElements.removeLast();
}
}
@ -575,48 +650,21 @@ class CodeGenerator extends GeneralizingAstVisitor
var exportedNames =
new NamespaceBuilder().createExportNamespaceForDirective(element);
var libraryName = emitLibraryName(currentLibrary);
// TODO(jmesserly): we could collect all of the names for bulk re-export,
// but this is easier to implement for now.
void emitExport(Element export, {String suffix: ''}) {
var name = _emitTopLevelName(export, suffix: suffix);
if (export is TypeDefiningElement ||
export is FunctionElement ||
_eagerTopLevelFields.contains(export)) {
// classes, typedefs, functions, and eager init fields can be assigned
// directly.
// TODO(jmesserly): we don't know about eager init fields from other
// modules we import, so we will never go down this code path for them.
_moduleItems
.add(js.statement('#.# = #;', [libraryName, name.selector, name]));
}
}
// We only need to export main as it is the only method party of the
// We only need to export main as it is the only method part of the
// publicly exposed JS API for a library.
// TODO(jacobr): add a library level annotation indicating that all
// contents of a library need to be exposed to JS.
// https://github.com/dart-lang/sdk/issues/26368
var export = exportedNames.get('main');
if (export == null) return;
if (export is PropertyAccessorElement) {
export = (export as PropertyAccessorElement).variable;
}
if (export is FunctionElement) {
// Don't allow redefining names from this library.
if (currentNames.containsKey(export.name)) return;
// Don't allow redefining names from this library.
if (currentNames.containsKey(export.name)) return;
if (export.isSynthetic && export is PropertyInducingElement) {
_emitDeclaration(export.getter);
_emitDeclaration(export.setter);
} else {
_emitDeclaration(export);
var name = _emitTopLevelName(export);
_moduleItems.add(js.statement(
'#.# = #;', [emitLibraryName(currentLibrary), name.selector, name]));
}
emitExport(export);
}
@override
@ -1313,7 +1361,7 @@ class CodeGenerator extends GeneralizingAstVisitor
var type = element.type;
if (type.isObject) return null;
_loader.startTopLevel(element);
_startTopLevelCodeForClass(element);
// List of "direct" supertypes (supertype + mixins)
var basetypes = [type.superclass]..addAll(type.mixins);
@ -1336,7 +1384,7 @@ class CodeGenerator extends GeneralizingAstVisitor
? baseclasses.first
: _callHelper('mixin(#)', [baseclasses]);
_loader.finishTopLevel(element);
_finishTopLevelCodeForClass(element);
return heritage;
}
@ -1792,17 +1840,7 @@ class CodeGenerator extends GeneralizingAstVisitor
/// otherwise define them as lazy properties.
void _emitStaticFields(List<FieldDeclaration> staticFields,
ClassElement classElem, List<JS.Statement> body) {
var lazyStatics = <VariableDeclaration>[];
for (FieldDeclaration member in staticFields) {
for (VariableDeclaration field in member.fields.variables) {
JS.Statement eagerField = _emitConstantStaticField(classElem, field);
if (eagerField != null) {
body.add(eagerField);
} else {
lazyStatics.add(field);
}
}
}
var lazyStatics = staticFields.expand((f) => f.fields.variables).toList();
if (lazyStatics.isNotEmpty) {
body.add(_emitLazyFields(classElem, lazyStatics));
}
@ -2133,12 +2171,7 @@ class CodeGenerator extends GeneralizingAstVisitor
new JS.Method(name, fun, isStatic: true), node, node.element);
}
// For const constructors we need to ensure default values are
// available for use by top-level constant initializers.
ClassDeclaration cls = node.parent;
if (node.constKeyword != null) _loader.startTopLevel(cls.element);
var params = visitFormalParameterList(node.parameters);
if (node.constKeyword != null) _loader.finishTopLevel(cls.element);
// Factory constructors are essentially static methods.
if (node.factoryKeyword != null) {
@ -2187,9 +2220,7 @@ class CodeGenerator extends GeneralizingAstVisitor
// nice to do them first.
// Also for const constructors we need to ensure default values are
// available for use by top-level constant initializers.
if (node.constKeyword != null) _loader.startTopLevel(cls.element);
var init = _emitArgumentInitializers(node, constructor: true);
if (node.constKeyword != null) _loader.finishTopLevel(cls.element);
if (init != null) body.add(init);
// Redirecting constructors: these are not allowed to have initializers,
@ -2297,9 +2328,6 @@ class CodeGenerator extends GeneralizingAstVisitor
List<FieldDeclaration> fieldDecls,
Map<FieldElement, JS.TemporaryId> virtualFields,
[ConstructorDeclaration ctor]) {
bool isConst = ctor != null && ctor.constKeyword != null;
if (isConst) _loader.startTopLevel(cls.element);
// Run field initializers if they can have side-effects.
var fields = new Map<FieldElement, JS.Expression>();
var unsetFields = new Map<FieldElement, VariableDeclaration>();
@ -2351,7 +2379,6 @@ class CodeGenerator extends GeneralizingAstVisitor
body.add(js.statement('this.# = #;', [access, initialValue]));
});
if (isConst) _loader.finishTopLevel(cls.element);
return _statement(body);
}
@ -2520,25 +2547,24 @@ class CodeGenerator extends GeneralizingAstVisitor
if (_externalOrNative(node)) return null;
// If we have a getter/setter pair, they need to be defined together.
if (node.isGetter) {
if (node.isGetter || node.isSetter) {
PropertyAccessorElement element = node.element;
var props = <JS.Method>[_emitTopLevelProperty(node)];
var setter = element.correspondingSetter;
if (setter != null) {
props.add(_loader.emitDeclaration(
setter, (node) => _emitTopLevelProperty(node)));
}
return _callHelperStatement('copyProperties(#, { # });',
[emitLibraryName(currentLibrary), props]);
}
if (node.isSetter) {
PropertyAccessorElement element = node.element;
var props = <JS.Method>[_emitTopLevelProperty(node)];
var getter = element.correspondingGetter;
if (getter != null) {
props.add(_loader.emitDeclaration(
getter, (node) => _emitTopLevelProperty(node)));
var pairAccessor = node.isGetter
? element.correspondingSetter
: element.correspondingGetter;
var jsCode = _emitTopLevelProperty(node);
var props = <JS.Method>[jsCode];
if (pairAccessor != null) {
// If we have a getter/setter pair, they need to be defined together.
// If this is the first one, save the generated code for later.
// If this is the second one, get the saved code and emit both.
var pairCode = _deferredProperties.remove(pairAccessor);
if (pairCode == null) {
_deferredProperties[element] = jsCode;
return null;
}
props.add(pairCode);
}
return _callHelperStatement('copyProperties(#, { # });',
[emitLibraryName(currentLibrary), props]);
@ -2631,7 +2657,7 @@ class CodeGenerator extends GeneralizingAstVisitor
if (type is ParameterizedType && !type.typeArguments.every(_typeIsLoaded)) {
return false;
}
return _loader.isLoaded(type.element);
return !_declarationNodes.containsKey(type.element);
}
JS.Expression _emitFunctionTagged(JS.Expression fn, DartType type,
@ -2852,10 +2878,10 @@ class CodeGenerator extends GeneralizingAstVisitor
var element = accessor;
if (accessor is PropertyAccessorElement) element = accessor.variable;
_declareBeforeUse(element);
// type literal
if (element is TypeDefiningElement) {
_declareBeforeUse(element);
var typeName = _emitType(fillDynamicTypeArgs(element.type));
// If the type is a type literal expression in Dart code, wrap the raw
@ -3157,7 +3183,9 @@ class CodeGenerator extends GeneralizingAstVisitor
}
var element = type.element;
_declareBeforeUse(element);
if (element is TypeDefiningElement) {
_declareBeforeUse(element);
}
var interop = _emitJSInterop(element);
// Type parameters don't matter as JS interop types cannot be reified.
@ -3391,7 +3419,9 @@ class CodeGenerator extends GeneralizingAstVisitor
var element = accessor;
if (accessor is PropertyAccessorElement) element = accessor.variable;
_declareBeforeUse(element);
if (element is TypeDefiningElement) {
_declareBeforeUse(element);
}
if (element is LocalVariableElement || element is ParameterElement) {
return _emitSetLocal(node, element, rhs);
@ -4010,11 +4040,11 @@ class CodeGenerator extends GeneralizingAstVisitor
return new JS.Yield(_visit(node.expression));
}
/// This is not used--we emit top-level fields as we are emitting the
/// compilation unit, see [_emitCompilationUnit].
@override
visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
for (var variable in node.variables.variables) {
_emitDeclaration(variable.element);
}
assert(false);
}
/// This is not used--we emit fields as we are emitting the class,
@ -4050,9 +4080,9 @@ class CodeGenerator extends GeneralizingAstVisitor
@override
visitVariableDeclaration(VariableDeclaration node) {
if (node.element is PropertyInducingElement) {
// Static and instance fields are handled elsewhere.
assert(node.element is TopLevelVariableElement);
return _emitTopLevelField(node);
// All fields are handled elsewhere.
assert(false);
return null;
}
var name = new JS.Identifier(node.name.name,
@ -4061,87 +4091,21 @@ class CodeGenerator extends GeneralizingAstVisitor
return new JS.VariableInitialization(name, _visitInitializer(node));
}
/// Try to emit a constant static field.
///
/// If the field's initializer does not cause side effects, and if all of
/// dependencies are safe to refer to while we are initializing the class,
/// then we can initialize it eagerly:
///
/// // Baz must be const constructor, and the name "Baz" must be defined
/// // by this point.
/// Foo.bar = dart.const(new Baz(42));
///
/// Otherwise, we'll need to generate a lazy-static field. That ensures
/// correct visible behavior, as well as avoiding referencing something that
/// isn't defined yet (because it is defined later in the module).
JS.Statement _emitConstantStaticField(
ClassElement classElem, VariableDeclaration field) {
PropertyInducingElement element = field.element;
assert(element.isStatic);
_loader.startCheckingReferences();
JS.Expression jsInit = _visitInitializer(field);
bool isLoaded = _loader.finishCheckingReferences();
bool eagerInit =
isLoaded && (field.isConst || _constants.isFieldInitConstant(field));
var fieldName = field.name.name;
if (eagerInit &&
!JS.invalidStaticFieldName(fieldName) &&
!_classProperties.staticFieldOverrides.contains(element)) {
return annotate(
js.statement('#.# = #;', [
_emitTopLevelName(classElem),
_emitMemberName(fieldName, isStatic: true),
jsInit
]),
field,
field.element);
}
// This means it should be treated as a lazy field.
// TODO(jmesserly): we're throwing away the initializer expression,
// which will force us to regenerate it.
return null;
/// Emits a list of top-level field.
void _emitTopLevelFields(List<VariableDeclaration> fields) {
_moduleItems.add(_emitLazyFields(currentLibrary, fields));
}
/// Emits a top-level field.
JS.ModuleItem _emitTopLevelField(VariableDeclaration field) {
TopLevelVariableElement element = field.element;
assert(element.isStatic);
bool eagerInit;
JS.Expression jsInit;
if (field.isConst || _constants.isFieldInitConstant(field)) {
// If the field is constant, try and generate it at the top level.
_loader.startTopLevel(element);
jsInit = _visitInitializer(field);
_loader.finishTopLevel(element);
eagerInit = _loader.isLoaded(element);
} else {
// TODO(jmesserly): we're visiting the initializer here, and again
// later on when we emit lazy fields. That seems busted.
jsInit = _visitInitializer(field);
eagerInit = false;
}
// Treat dart:runtime stuff as safe to eagerly evaluate.
// TODO(jmesserly): it'd be nice to avoid this special case.
var isJSTopLevel = field.isFinal && isSdkInternalRuntime(element.library);
if (eagerInit || isJSTopLevel) {
// Remember that we emitted it this way, so re-export can take advantage
// of this fact.
_eagerTopLevelFields.add(element);
return annotate(
js.statement('# = #;', [_emitTopLevelName(element), jsInit]),
/// Treat dart:_runtime fields as safe to eagerly evaluate.
// TODO(jmesserly): it'd be nice to avoid this special case.
void _emitInternalSdkFields(List<VariableDeclaration> fields) {
for (var field in fields) {
_moduleItems.add(annotate(
js.statement('# = #;',
[_emitTopLevelName(field.element), _visitInitializer(field)]),
field,
element);
field.element));
}
assert(element.library == currentLibrary);
return _emitLazyFields(element.library, [field]);
}
JS.Expression _visitInitializer(VariableDeclaration node) {
@ -4157,6 +4121,8 @@ class CodeGenerator extends GeneralizingAstVisitor
for (var node in fields) {
var name = node.name.name;
var element = node.element;
assert(element.getAncestor((e) => identical(e, target)) != null,
"target is $target but enclosing element is ${element.enclosingElement}");
var access = _emitMemberName(name, isStatic: true);
methods.add(annotate(
new JS.Method(
@ -5934,7 +5900,7 @@ class CodeGenerator extends GeneralizingAstVisitor
bool _inWhitelistCode(AstNode node, {isCall: false}) {
if (!options.useAngular2Whitelist) return false;
var path = _loader.currentElement.source.fullName;
var path = currentElement.source.fullName;
var filename = path.split("/").last;
if (_uncheckedWhitelist.containsKey(filename)) {
var whitelisted = _uncheckedWhitelist[filename];

View file

@ -1,117 +0,0 @@
// Copyright (c) 2015, 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:collection' show HashMap;
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:func/func.dart';
import '../js_ast/js_ast.dart' as JS;
/// Helper that tracks order of elements visited by the compiler, detecting
/// if the top level item can be loaded eagerly or not.
class ElementLoader {
final HashMap<Element, AstNode> _declarationNodes;
/// The stack of currently emitting elements, if generating top-level code
/// for them. This is not used when inside method bodies, because order does
/// not matter for those.
final _topLevelElements = new List<Element>();
/// The current element being loaded.
/// We can use this to determine if we're loading top-level code or not:
///
/// _currentElements.last == _topLevelElements.last
final _currentElements = new List<Element>();
bool _checkReferences;
ElementLoader(this._declarationNodes) {
assert(!_declarationNodes.containsKey(null));
}
Element get currentElement => _currentElements.last;
bool isLoaded(Element e) => !_declarationNodes.containsKey(e);
/// True if the element is currently being loaded.
bool _isLoading(Element e) => _currentElements.contains(e);
/// Start generating top-level code for the element [e].
///
/// Subsequent [emitDeclaration] calls will cause those elements to be
/// generated before this one, until [finishTopLevel] is called.
void startTopLevel(Element e) {
assert(identical(e, currentElement));
_topLevelElements.add(e);
}
/// Finishes the top-level code for the element [e].
void finishTopLevel(Element e) {
var last = _topLevelElements.removeLast();
assert(identical(e, last));
}
/// Starts recording calls to [declareBeforeUse], until
/// [finishCheckingReferences] is called.
void startCheckingReferences() {
// This function should not be reentrant, and we should not current be
// emitting top-level code.
assert(_checkReferences == null);
assert(_topLevelElements.isEmpty ||
!identical(currentElement, _topLevelElements.last));
// Assume true until proven otherwise
_checkReferences = true;
}
/// Finishes recording references, and returns `true` if all referenced
/// items were loaded (or if no items were referenced).
bool finishCheckingReferences() {
var result = _checkReferences;
_checkReferences = null;
return result;
}
/// Ensures a top-level declaration is generated, and returns `true` if it
/// is part of the current module.
/*=T*/ emitDeclaration/*<T extends JS.Node>*/(
Element e, Func1<AstNode, JS.Node/*=T*/ > visit) {
var node = _declarationNodes.remove(e);
if (node == null) return null; // not from this module or already loaded.
_currentElements.add(e);
var result = visit(node);
var last = _currentElements.removeLast();
assert(identical(e, last));
return result;
}
/// To emit top-level module items, we sometimes need to reorder them.
///
/// This function takes care of that, and also detects cases where reordering
/// failed, and we need to resort to lazy loading, by marking the element as
/// lazy. All elements need to be aware of this possibility and generate code
/// accordingly.
///
/// If we are not emitting top-level code, this does nothing, because all
/// declarations are assumed to be available before we start execution.
/// See [startTopLevel].
void declareBeforeUse(Element e, VoidFunc1<Element> emit) {
if (e == null) return;
if (_checkReferences != null) {
_checkReferences = _checkReferences && isLoaded(e) && !_isLoading(e);
return;
}
var topLevel = _topLevelElements;
if (topLevel.isNotEmpty && identical(currentElement, topLevel.last)) {
// If the item is from our library, try to emit it now.
emit(e);
}
}
}

View file

@ -10,10 +10,23 @@ define(['dart_sdk'], function(dart_sdk) {
let VoidTovoid = () => (VoidTovoid = dart.constFn(dart.definiteFunctionType(dart.void, [])))();
let dynamicTovoid = () => (dynamicTovoid = dart.constFn(dart.definiteFunctionType(dart.void, [dart.dynamic])))();
let FnTovoid = () => (FnTovoid = dart.constFn(dart.definiteFunctionType(dart.void, [VoidTodynamic()])))();
async_helper._initialized = false;
dart.defineLazy(async_helper, {
get _initialized() {
return false;
},
set _initialized(_) {}
});
async_helper._Action0 = dart.typedef('_Action0', () => dart.functionType(dart.void, []));
async_helper._onAsyncEnd = null;
async_helper._asyncLevel = 0;
dart.defineLazy(async_helper, {
get _onAsyncEnd() {
return null;
},
set _onAsyncEnd(_) {},
get _asyncLevel() {
return 0;
},
set _asyncLevel(_) {}
});
async_helper._buildException = function(msg) {
return core.Exception.new(dart.str`Fatal: ${msg}. This is most likely a bug in your test.`);
};

View file

@ -115,12 +115,18 @@ closure.Foo$ = dart.generic(T => {
return Foo;
});
closure.Foo = Foo();
/** @final {string} */
closure.Foo.some_static_constant = "abc";
/** @final {string} */
closure.Foo.some_static_final = "abc";
/** @type {string} */
closure.Foo.some_static_var = "abc";
dart.defineLazy(closure.Foo, {
get some_static_constant() {
return "abc";
},
get some_static_final() {
return "abc";
},
get some_static_var() {
return "abc";
},
set some_static_var(_) {}
});
closure.Bar = class Bar extends core.Object {};
closure.Baz = class Baz extends dart.mixin(closure.Foo$(core.int), closure.Bar) {
new(i: number) {
@ -137,12 +143,16 @@ dart.defineLazy(closure, {
return;
}, VoidToNull());
},
set closure(_) {}
set closure(_) {},
get some_top_level_constant() {
return "abc";
},
get some_top_level_final() {
return "abc";
},
get some_top_level_var() {
return "abc";
},
set some_top_level_var(_) {}
});
/** @final {string} */
closure.some_top_level_constant = "abc";
/** @final {string} */
closure.some_top_level_final = "abc";
/** @type {string} */
closure.some_top_level_var = "abc";
dart.trackLibraries("closure", {"closure.dart": closure}, null);

View file

@ -75,7 +75,11 @@ define(['dart_sdk'], function(dart_sdk) {
new() {
}
};
src__varargs.rest = dart.const(new src__varargs._Rest());
dart.defineLazy(src__varargs, {
get rest() {
return dart.const(new src__varargs._Rest());
}
});
src__varargs.spread = function(args) {
dart.throw(new core.StateError('The spread function cannot be called, ' + 'it should be compiled away.'));
};

View file

@ -25,18 +25,23 @@ dart.fn(es6_modules.f, VoidTodynamic());
es6_modules._f = function() {
};
dart.fn(es6_modules._f, VoidTodynamic());
es6_modules.constant = "abc";
es6_modules.finalConstant = "abc";
dart.defineLazy(es6_modules, {
get constant() {
return "abc";
},
get finalConstant() {
return "abc";
},
get lazy() {
return dart.fn(() => {
core.print('lazy');
return "abc";
}, VoidToString())();
}
});
es6_modules.mutable = "abc";
dart.defineLazy(es6_modules, {
},
get mutable() {
return "abc";
},
set mutable(_) {},
get lazyMutable() {
return dart.fn(() => {
core.print('lazyMutable');

View file

@ -7,12 +7,12 @@ define(['dart_sdk'], function(dart_sdk) {
const map_keys = Object.create(null);
let VoidTodynamic = () => (VoidTodynamic = dart.constFn(dart.definiteFunctionType(dart.dynamic, [])))();
map_keys.main = function() {
core.print(dart.map({'1': 2, '3': 4, '5': 6}));
core.print(dart.map([1, 2, 3, 4, 5, 6]));
core.print(dart.map({'1': 2, [dart.str`${dart.notNull(math.Random.new().nextInt(2)) + 2}`]: 4, '5': 6}));
core.print(dart.map({'1': 2, '3': 4, '5': 6}, core.String, core.int));
core.print(dart.map([1, 2, 3, 4, 5, 6], core.int, core.int));
core.print(dart.map({'1': 2, [dart.str`${dart.notNull(math.Random.new().nextInt(2)) + 2}`]: 4, '5': 6}, core.String, core.int));
let x = '3';
core.print(dart.map(['1', 2, x, 4, '5', 6]));
core.print(dart.map(['1', 2, null, 4, '5', 6]));
core.print(dart.map(['1', 2, x, 4, '5', 6], core.String, core.int));
core.print(dart.map(['1', 2, null, 4, '5', 6], core.String, core.int));
};
dart.fn(map_keys.main, VoidTodynamic());
dart.trackLibraries("map_keys", {"map_keys.dart": map_keys}, null);

View file

@ -1 +1 @@
{"version":3,"sourceRoot":"","sources":["../../gen/codegen_tests/map_keys.dart"],"names":["print","x"],"mappings":";;;;;;;;AAMA,kBAAI,WAAG;AAEL,IAAA,AAAAA,UAAK,CAAC,eAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAC,CAAC;AAAC,AAEhC,IAAA,AAAAA,UAAK,CAAC,UAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAC,CAAC;AAAC,AAE1B,IAAA,AAAAA,UAAK,CAAC,eAAM,CAAC,GAAE,WAAC,aAAE,AAAA,iBAAY,SAAS,CAAC,CAAC,IAAG,CAAC,AAAC,EAAC,GAAE,CAAC,OAAO,CAAC,EAAC,CAAC;AAAC,AAC7D,YAAW,GAAG;AAAC,AAEf,IAAA,AAAAA,UAAK,CAAC,UAAC,GAAG,EAAE,CAAC,EAAEC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAC,CAAC;AAAC,AAE9B,IAAA,AAAAD,UAAK,CAAC,UAAC,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAC,CAAC;AAAC,GAEnC,AAAA;AAAA","file":"map_keys.js"}
{"version":3,"sourceRoot":"","sources":["../../gen/codegen_tests/map_keys.dart"],"names":["print","x"],"mappings":";;;;;;;;AAMA,kBAAI,WAAG;AAEL,IAAA,AAAAA,UAAK,CAAC,eAAM,CAAC,OAAO,CAAC,OAAO,CAAC,yBAAC,CAAC;AAAC,AAEhC,IAAA,AAAAA,UAAK,CAAC,UAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,sBAAC,CAAC;AAAC,AAE1B,IAAA,AAAAA,UAAK,CAAC,eAAM,CAAC,GAAE,WAAC,aAAE,AAAA,iBAAY,SAAS,CAAC,CAAC,IAAG,CAAC,AAAC,EAAC,GAAE,CAAC,OAAO,CAAC,yBAAC,CAAC;AAAC,AAC7D,YAAW,GAAG;AAAC,AAEf,IAAA,AAAAA,UAAK,CAAC,UAAC,GAAG,EAAE,CAAC,EAAEC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,yBAAC,CAAC;AAAC,AAE9B,IAAA,AAAAD,UAAK,CAAC,UAAC,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,yBAAC,CAAC;AAAC,GAEnC,AAAA;AAAA","file":"map_keys.js"}

View file

@ -29,18 +29,23 @@ dart.fn(node_modules.f, VoidTodynamic());
node_modules._f = function() {
};
dart.fn(node_modules._f, VoidTodynamic());
node_modules.constant = "abc";
node_modules.finalConstant = "abc";
dart.defineLazy(node_modules, {
get constant() {
return "abc";
},
get finalConstant() {
return "abc";
},
get lazy() {
return dart.fn(() => {
core.print('lazy');
return "abc";
}, VoidToString())();
}
});
node_modules.mutable = "abc";
dart.defineLazy(node_modules, {
},
get mutable() {
return "abc";
},
set mutable(_) {},
get lazyMutable() {
return dart.fn(() => {
core.print('lazyMutable');

View file

@ -11,11 +11,23 @@ define(['dart_sdk'], function(dart_sdk) {
let StringToElement = () => (StringToElement = dart.constFn(dart.definiteFunctionType(html.Element, [core.String])))();
let EventTovoid = () => (EventTovoid = dart.constFn(dart.definiteFunctionType(dart.void, [html.Event])))();
let VoidTovoid = () => (VoidTovoid = dart.constFn(dart.definiteFunctionType(dart.void, [])))();
sunflower.SEED_RADIUS = 2;
sunflower.SCALE_FACTOR = 4;
sunflower.MAX_D = 300;
sunflower.centerX = sunflower.MAX_D / 2;
sunflower.centerY = sunflower.centerX;
dart.defineLazy(sunflower, {
get SEED_RADIUS() {
return 2;
},
get SCALE_FACTOR() {
return 4;
},
get MAX_D() {
return 300;
},
get centerX() {
return sunflower.MAX_D / 2;
},
get centerY() {
return sunflower.centerX;
}
});
sunflower.querySelector = function(selector) {
return html.document.querySelector(selector);
};
@ -23,29 +35,24 @@ define(['dart_sdk'], function(dart_sdk) {
dart.defineLazy(sunflower, {
get canvas() {
return html.CanvasElement.as(sunflower.querySelector("#canvas"));
}
});
dart.defineLazy(sunflower, {
},
get context() {
return html.CanvasRenderingContext2D.as(sunflower.canvas[dartx.getContext]('2d'));
}
});
dart.defineLazy(sunflower, {
},
get slider() {
return html.InputElement.as(sunflower.querySelector("#slider"));
}
});
dart.defineLazy(sunflower, {
},
get notes() {
return sunflower.querySelector("#notes");
}
});
dart.defineLazy(sunflower, {
},
get PHI() {
return (dart.notNull(math.sqrt(5)) + 1) / 2;
}
},
get seeds() {
return 0;
},
set seeds(_) {}
});
sunflower.seeds = 0;
sunflower.main = function() {
sunflower.slider[dartx.addEventListener]('change', dart.fn(e => sunflower.draw(), EventTovoid()));
sunflower.draw();
@ -133,10 +140,20 @@ define(['dart_sdk'], function(dart_sdk) {
if (color != null) this.color = color;
}
};
painter.ORANGE = "orange";
painter.RED = "red";
painter.BLUE = "blue";
painter.TAU = math.PI * 2;
dart.defineLazy(painter, {
get ORANGE() {
return "orange";
},
get RED() {
return "red";
},
get BLUE() {
return "blue";
},
get TAU() {
return math.PI * 2;
}
});
painter.querySelector = function(selector) {
return html.document.querySelector(selector);
};
@ -144,9 +161,7 @@ define(['dart_sdk'], function(dart_sdk) {
dart.defineLazy(painter, {
get canvas() {
return html.CanvasElement.as(painter.querySelector("#canvas"));
}
});
dart.defineLazy(painter, {
},
get context() {
return html.CanvasRenderingContext2D.as(painter.canvas[dartx.getContext]('2d'));
}

View file

@ -1 +1 @@
{"version":3,"sourceRoot":"","sources":["../../codegen/sunflower/sunflower.dart","../../codegen/sunflower/circle.dart","../../codegen/sunflower/painter.dart"],"names":["MAX_D","centerX","document","selector","querySelector","canvas","sqrt","slider","draw","seeds","context","i","TAU","PHI","SCALE_FACTOR","r","cos","theta","centerY","sin","x","y","SEED_RADIUS","notes","ORANGE","color","radius","PI"],"mappings":"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","file":"sunflower.js"}
{"version":3,"sourceRoot":"","sources":["../../codegen/sunflower/sunflower.dart","../../codegen/sunflower/circle.dart","../../codegen/sunflower/painter.dart"],"names":["MAX_D","centerX","document","selector","querySelector","canvas","sqrt","slider","draw","seeds","context","i","TAU","PHI","SCALE_FACTOR","r","cos","theta","centerY","sin","x","y","SEED_RADIUS","notes","ORANGE","color","radius","PI"],"mappings":"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","file":"sunflower.js"}

View file

@ -21,7 +21,11 @@ define(['dart_sdk'], function(dart_sdk) {
new() {
}
};
src__varargs.rest = dart.const(new src__varargs._Rest());
dart.defineLazy(src__varargs, {
get rest() {
return dart.const(new src__varargs._Rest());
}
});
src__varargs.spread = function(args) {
dart.throw(new core.StateError('The spread function cannot be called, ' + 'it should be compiled away.'));
};

View file

@ -156,9 +156,13 @@ main(List<String> arguments) {
compiler = new ModuleCompiler(analyzerOptions);
}
JSModuleFile module = null;
var exception, stackTrace;
try {
module = compiler.compile(unit, options);
} catch (e) {}
} catch (e, st) {
exception = e;
stackTrace = st;
}
bool expectedCompileTimeError =
contents.contains(': compile-time error\n');
@ -167,7 +171,8 @@ main(List<String> arguments) {
if (module == null) {
expect(crashing, isTrue,
reason: "test $name crashes during compilation.");
reason: "test $name crashes during compilation.\n"
"$exception\n$stackTrace");
} else if (module.isValid) {
_writeModule(
path.join(codegenOutputDir, name),