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 'ast_builder.dart' show AstBuilder;
import 'compiler.dart' show BuildUnit, CompilerOptions, JSModuleFile; import 'compiler.dart' show BuildUnit, CompilerOptions, JSModuleFile;
import 'element_helpers.dart'; import 'element_helpers.dart';
import 'element_loader.dart' show ElementLoader;
import 'extension_types.dart' show ExtensionTypeSet; import 'extension_types.dart' show ExtensionTypeSet;
import 'js_interop.dart'; import 'js_interop.dart';
import 'js_metalet.dart' as JS; import 'js_metalet.dart' as JS;
@ -72,6 +71,10 @@ class CodeGenerator extends GeneralizingAstVisitor
/// Imported libraries, and the temporaries used to refer to them. /// Imported libraries, and the temporaries used to refer to them.
final _imports = new Map<LibraryElement, JS.TemporaryId>(); 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. /// The list of output module items, in the order they need to be emitted in.
final _moduleItems = <JS.ModuleItem>[]; final _moduleItems = <JS.ModuleItem>[];
@ -105,8 +108,6 @@ class CodeGenerator extends GeneralizingAstVisitor
final _hasDeferredSupertype = new HashSet<ClassElement>(); final _hasDeferredSupertype = new HashSet<ClassElement>();
final _eagerTopLevelFields = new HashSet<Element>.identity();
/// The type provider from the current Analysis [context]. /// The type provider from the current Analysis [context].
final TypeProvider types; final TypeProvider types;
@ -134,9 +135,24 @@ class CodeGenerator extends GeneralizingAstVisitor
/// The current function body being compiled. /// The current function body being compiled.
FunctionBody _currentFunction; FunctionBody _currentFunction;
/// Helper class for emitting elements in the proper order to allow HashMap<TypeDefiningElement, AstNode> _declarationNodes;
/// JS to load the module.
ElementLoader _loader; /// 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; BuildUnit _buildUnit;
@ -182,7 +198,9 @@ class CodeGenerator extends GeneralizingAstVisitor
_getLibrary(c, 'dart:_internal').getType('PrivateSymbol'), _getLibrary(c, 'dart:_internal').getType('PrivateSymbol'),
dartJSLibrary = _getLibrary(c, 'dart:js'); 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. /// 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 // Collect all class/type Element -> Node mappings
// any nodes. // in case we need to forward declare any classes.
var nodes = new HashMap<Element, AstNode>.identity(); _declarationNodes = new HashMap<TypeDefiningElement, AstNode>.identity();
var sdkBootstrappingFns = new List<FunctionElement>();
for (var unit in compilationUnits) { for (var unit in compilationUnits) {
if (isSdkInternalRuntime( for (var declaration in unit.declarations) {
resolutionMap.elementDeclaredByCompilationUnit(unit).library)) { var element = declaration.element;
sdkBootstrappingFns.addAll( if (element is TypeDefiningElement) {
resolutionMap.elementDeclaredByCompilationUnit(unit).functions); _declarationNodes[element] = declaration;
}
} }
_collectElements(unit, nodes);
} }
_loader = new ElementLoader(nodes);
if (compilationUnits.isNotEmpty) { if (compilationUnits.isNotEmpty) {
_constants = new ConstFieldVisitor(context, _constants = new ConstFieldVisitor(context,
dummySource: resolutionMap dummySource: resolutionMap
@ -308,15 +324,16 @@ class CodeGenerator extends GeneralizingAstVisitor
// Add implicit dart:core dependency so it is first. // Add implicit dart:core dependency so it is first.
emitLibraryName(dartCoreLibrary); emitLibraryName(dartCoreLibrary);
// Emit SDK bootstrapping functions first, if any.
sdkBootstrappingFns.forEach(_emitDeclaration);
// Visit each compilation unit and emit its code. // Visit each compilation unit and emit its code.
// //
// NOTE: declarations are not necessarily emitted in this order. // NOTE: declarations are not necessarily emitted in this order.
// Order will be changed as needed so the resulting code can execute. // Order will be changed as needed so the resulting code can execute.
// This is done by forward declaring items. // 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 // Declare imports
_finishImports(items); _finishImports(items);
@ -324,6 +341,7 @@ class CodeGenerator extends GeneralizingAstVisitor
// Discharge the type table cache variables and // Discharge the type table cache variables and
// hoisted definitions. // hoisted definitions.
items.addAll(_typeTable.discharge()); items.addAll(_typeTable.discharge());
items.addAll(_internalSdkFunctions);
// Track the module name for each library in the module. // Track the module name for each library in the module.
// This data is only required for debugging. // This data is only required for debugging.
@ -432,7 +450,7 @@ class CodeGenerator extends GeneralizingAstVisitor
for (var item in items) { for (var item in items) {
if (item is JS.Block && !item.isScope) { if (item is JS.Block && !item.isScope) {
_copyAndFlattenBlocks(result, item.statements); _copyAndFlattenBlocks(result, item.statements);
} else { } else if (item != null) {
result.add(item); 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. /// Called to emit all top-level declarations.
/// ///
/// During the course of emitting one item, we may emit another. For example /// 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 /// 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. /// used by top-level JavaScript code, so we can ignore that dependency.
void _emitDeclaration(Element e) { void _emitTypeDeclaration(TypeDefiningElement e) {
var item = _loader.emitDeclaration(e, (AstNode node) { var node = _declarationNodes.remove(e);
// TODO(jmesserly): this is not really the right place for this. if (node == null) return null; // not from this module or already loaded.
// 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;
});
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) { /// Start generating top-level code for the element [e].
_loader.declareBeforeUse(e, _emitDeclaration); ///
/// 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 // NOTE: this method isn't the right place to initialize
// per-compilation-unit state. Declarations can be visited out of order, // per-compilation-unit state. Declarations can be visited out of order,
// this is only to catch things that haven't been emitted yet. // 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) { 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; var element = declaration.element;
if (element != null) { if (element is TypeDefiningElement) {
_emitDeclaration(element); _emitTypeDeclaration(element);
continue;
}
inferNullableTypes(declaration);
var item = _visit(declaration);
if (internalSdk && element is FunctionElement) {
_internalSdkFunctions.add(item);
} else { } else {
declaration.accept(this); _moduleItems.add(item);
} }
} }
if (fields != null) _emitTopLevelFields(fields);
_currentElements.removeLast();
}
void _emitExportDirectives(CompilationUnit unit) {
for (var directive in unit.directives) { for (var directive in unit.directives) {
_currentElements.add(directive.element);
directive.accept(this); directive.accept(this);
_currentElements.removeLast();
} }
} }
@ -575,48 +650,21 @@ class CodeGenerator extends GeneralizingAstVisitor
var exportedNames = var exportedNames =
new NamespaceBuilder().createExportNamespaceForDirective(element); new NamespaceBuilder().createExportNamespaceForDirective(element);
var libraryName = emitLibraryName(currentLibrary); // We only need to export main as it is the only method part of the
// 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
// publicly exposed JS API for a library. // publicly exposed JS API for a library.
// TODO(jacobr): add a library level annotation indicating that all // TODO(jacobr): add a library level annotation indicating that all
// contents of a library need to be exposed to JS. // contents of a library need to be exposed to JS.
// https://github.com/dart-lang/sdk/issues/26368 // https://github.com/dart-lang/sdk/issues/26368
var export = exportedNames.get('main'); var export = exportedNames.get('main');
if (export == null) return; if (export is FunctionElement) {
if (export is PropertyAccessorElement) { // Don't allow redefining names from this library.
export = (export as PropertyAccessorElement).variable; if (currentNames.containsKey(export.name)) return;
}
// Don't allow redefining names from this library. var name = _emitTopLevelName(export);
if (currentNames.containsKey(export.name)) return; _moduleItems.add(js.statement(
'#.# = #;', [emitLibraryName(currentLibrary), name.selector, name]));
if (export.isSynthetic && export is PropertyInducingElement) {
_emitDeclaration(export.getter);
_emitDeclaration(export.setter);
} else {
_emitDeclaration(export);
} }
emitExport(export);
} }
@override @override
@ -1313,7 +1361,7 @@ class CodeGenerator extends GeneralizingAstVisitor
var type = element.type; var type = element.type;
if (type.isObject) return null; if (type.isObject) return null;
_loader.startTopLevel(element); _startTopLevelCodeForClass(element);
// List of "direct" supertypes (supertype + mixins) // List of "direct" supertypes (supertype + mixins)
var basetypes = [type.superclass]..addAll(type.mixins); var basetypes = [type.superclass]..addAll(type.mixins);
@ -1336,7 +1384,7 @@ class CodeGenerator extends GeneralizingAstVisitor
? baseclasses.first ? baseclasses.first
: _callHelper('mixin(#)', [baseclasses]); : _callHelper('mixin(#)', [baseclasses]);
_loader.finishTopLevel(element); _finishTopLevelCodeForClass(element);
return heritage; return heritage;
} }
@ -1792,17 +1840,7 @@ class CodeGenerator extends GeneralizingAstVisitor
/// otherwise define them as lazy properties. /// otherwise define them as lazy properties.
void _emitStaticFields(List<FieldDeclaration> staticFields, void _emitStaticFields(List<FieldDeclaration> staticFields,
ClassElement classElem, List<JS.Statement> body) { ClassElement classElem, List<JS.Statement> body) {
var lazyStatics = <VariableDeclaration>[]; var lazyStatics = staticFields.expand((f) => f.fields.variables).toList();
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);
}
}
}
if (lazyStatics.isNotEmpty) { if (lazyStatics.isNotEmpty) {
body.add(_emitLazyFields(classElem, lazyStatics)); body.add(_emitLazyFields(classElem, lazyStatics));
} }
@ -2133,12 +2171,7 @@ class CodeGenerator extends GeneralizingAstVisitor
new JS.Method(name, fun, isStatic: true), node, node.element); 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); var params = visitFormalParameterList(node.parameters);
if (node.constKeyword != null) _loader.finishTopLevel(cls.element);
// Factory constructors are essentially static methods. // Factory constructors are essentially static methods.
if (node.factoryKeyword != null) { if (node.factoryKeyword != null) {
@ -2187,9 +2220,7 @@ class CodeGenerator extends GeneralizingAstVisitor
// nice to do them first. // nice to do them first.
// Also for const constructors we need to ensure default values are // Also for const constructors we need to ensure default values are
// available for use by top-level constant initializers. // available for use by top-level constant initializers.
if (node.constKeyword != null) _loader.startTopLevel(cls.element);
var init = _emitArgumentInitializers(node, constructor: true); var init = _emitArgumentInitializers(node, constructor: true);
if (node.constKeyword != null) _loader.finishTopLevel(cls.element);
if (init != null) body.add(init); if (init != null) body.add(init);
// Redirecting constructors: these are not allowed to have initializers, // Redirecting constructors: these are not allowed to have initializers,
@ -2297,9 +2328,6 @@ class CodeGenerator extends GeneralizingAstVisitor
List<FieldDeclaration> fieldDecls, List<FieldDeclaration> fieldDecls,
Map<FieldElement, JS.TemporaryId> virtualFields, Map<FieldElement, JS.TemporaryId> virtualFields,
[ConstructorDeclaration ctor]) { [ConstructorDeclaration ctor]) {
bool isConst = ctor != null && ctor.constKeyword != null;
if (isConst) _loader.startTopLevel(cls.element);
// Run field initializers if they can have side-effects. // Run field initializers if they can have side-effects.
var fields = new Map<FieldElement, JS.Expression>(); var fields = new Map<FieldElement, JS.Expression>();
var unsetFields = new Map<FieldElement, VariableDeclaration>(); var unsetFields = new Map<FieldElement, VariableDeclaration>();
@ -2351,7 +2379,6 @@ class CodeGenerator extends GeneralizingAstVisitor
body.add(js.statement('this.# = #;', [access, initialValue])); body.add(js.statement('this.# = #;', [access, initialValue]));
}); });
if (isConst) _loader.finishTopLevel(cls.element);
return _statement(body); return _statement(body);
} }
@ -2520,25 +2547,24 @@ class CodeGenerator extends GeneralizingAstVisitor
if (_externalOrNative(node)) return null; if (_externalOrNative(node)) return null;
// If we have a getter/setter pair, they need to be defined together. if (node.isGetter || node.isSetter) {
if (node.isGetter) {
PropertyAccessorElement element = node.element; PropertyAccessorElement element = node.element;
var props = <JS.Method>[_emitTopLevelProperty(node)]; var pairAccessor = node.isGetter
var setter = element.correspondingSetter; ? element.correspondingSetter
if (setter != null) { : element.correspondingGetter;
props.add(_loader.emitDeclaration(
setter, (node) => _emitTopLevelProperty(node))); var jsCode = _emitTopLevelProperty(node);
} var props = <JS.Method>[jsCode];
return _callHelperStatement('copyProperties(#, { # });', if (pairAccessor != null) {
[emitLibraryName(currentLibrary), props]); // 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 (node.isSetter) { // If this is the second one, get the saved code and emit both.
PropertyAccessorElement element = node.element; var pairCode = _deferredProperties.remove(pairAccessor);
var props = <JS.Method>[_emitTopLevelProperty(node)]; if (pairCode == null) {
var getter = element.correspondingGetter; _deferredProperties[element] = jsCode;
if (getter != null) { return null;
props.add(_loader.emitDeclaration( }
getter, (node) => _emitTopLevelProperty(node))); props.add(pairCode);
} }
return _callHelperStatement('copyProperties(#, { # });', return _callHelperStatement('copyProperties(#, { # });',
[emitLibraryName(currentLibrary), props]); [emitLibraryName(currentLibrary), props]);
@ -2631,7 +2657,7 @@ class CodeGenerator extends GeneralizingAstVisitor
if (type is ParameterizedType && !type.typeArguments.every(_typeIsLoaded)) { if (type is ParameterizedType && !type.typeArguments.every(_typeIsLoaded)) {
return false; return false;
} }
return _loader.isLoaded(type.element); return !_declarationNodes.containsKey(type.element);
} }
JS.Expression _emitFunctionTagged(JS.Expression fn, DartType type, JS.Expression _emitFunctionTagged(JS.Expression fn, DartType type,
@ -2852,10 +2878,10 @@ class CodeGenerator extends GeneralizingAstVisitor
var element = accessor; var element = accessor;
if (accessor is PropertyAccessorElement) element = accessor.variable; if (accessor is PropertyAccessorElement) element = accessor.variable;
_declareBeforeUse(element);
// type literal // type literal
if (element is TypeDefiningElement) { if (element is TypeDefiningElement) {
_declareBeforeUse(element);
var typeName = _emitType(fillDynamicTypeArgs(element.type)); var typeName = _emitType(fillDynamicTypeArgs(element.type));
// If the type is a type literal expression in Dart code, wrap the raw // 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; var element = type.element;
_declareBeforeUse(element); if (element is TypeDefiningElement) {
_declareBeforeUse(element);
}
var interop = _emitJSInterop(element); var interop = _emitJSInterop(element);
// Type parameters don't matter as JS interop types cannot be reified. // Type parameters don't matter as JS interop types cannot be reified.
@ -3391,7 +3419,9 @@ class CodeGenerator extends GeneralizingAstVisitor
var element = accessor; var element = accessor;
if (accessor is PropertyAccessorElement) element = accessor.variable; if (accessor is PropertyAccessorElement) element = accessor.variable;
_declareBeforeUse(element); if (element is TypeDefiningElement) {
_declareBeforeUse(element);
}
if (element is LocalVariableElement || element is ParameterElement) { if (element is LocalVariableElement || element is ParameterElement) {
return _emitSetLocal(node, element, rhs); return _emitSetLocal(node, element, rhs);
@ -4010,11 +4040,11 @@ class CodeGenerator extends GeneralizingAstVisitor
return new JS.Yield(_visit(node.expression)); 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 @override
visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) { visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
for (var variable in node.variables.variables) { assert(false);
_emitDeclaration(variable.element);
}
} }
/// This is not used--we emit fields as we are emitting the class, /// This is not used--we emit fields as we are emitting the class,
@ -4050,9 +4080,9 @@ class CodeGenerator extends GeneralizingAstVisitor
@override @override
visitVariableDeclaration(VariableDeclaration node) { visitVariableDeclaration(VariableDeclaration node) {
if (node.element is PropertyInducingElement) { if (node.element is PropertyInducingElement) {
// Static and instance fields are handled elsewhere. // All fields are handled elsewhere.
assert(node.element is TopLevelVariableElement); assert(false);
return _emitTopLevelField(node); return null;
} }
var name = new JS.Identifier(node.name.name, var name = new JS.Identifier(node.name.name,
@ -4061,87 +4091,21 @@ class CodeGenerator extends GeneralizingAstVisitor
return new JS.VariableInitialization(name, _visitInitializer(node)); return new JS.VariableInitialization(name, _visitInitializer(node));
} }
/// Try to emit a constant static field. /// Emits a list of top-level field.
/// void _emitTopLevelFields(List<VariableDeclaration> fields) {
/// If the field's initializer does not cause side effects, and if all of _moduleItems.add(_emitLazyFields(currentLibrary, fields));
/// 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 top-level field. /// Treat dart:_runtime fields as safe to eagerly evaluate.
JS.ModuleItem _emitTopLevelField(VariableDeclaration field) { // TODO(jmesserly): it'd be nice to avoid this special case.
TopLevelVariableElement element = field.element; void _emitInternalSdkFields(List<VariableDeclaration> fields) {
assert(element.isStatic); for (var field in fields) {
_moduleItems.add(annotate(
bool eagerInit; js.statement('# = #;',
JS.Expression jsInit; [_emitTopLevelName(field.element), _visitInitializer(field)]),
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]),
field, field,
element); field.element));
} }
assert(element.library == currentLibrary);
return _emitLazyFields(element.library, [field]);
} }
JS.Expression _visitInitializer(VariableDeclaration node) { JS.Expression _visitInitializer(VariableDeclaration node) {
@ -4157,6 +4121,8 @@ class CodeGenerator extends GeneralizingAstVisitor
for (var node in fields) { for (var node in fields) {
var name = node.name.name; var name = node.name.name;
var element = node.element; 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); var access = _emitMemberName(name, isStatic: true);
methods.add(annotate( methods.add(annotate(
new JS.Method( new JS.Method(
@ -5934,7 +5900,7 @@ class CodeGenerator extends GeneralizingAstVisitor
bool _inWhitelistCode(AstNode node, {isCall: false}) { bool _inWhitelistCode(AstNode node, {isCall: false}) {
if (!options.useAngular2Whitelist) return false; if (!options.useAngular2Whitelist) return false;
var path = _loader.currentElement.source.fullName; var path = currentElement.source.fullName;
var filename = path.split("/").last; var filename = path.split("/").last;
if (_uncheckedWhitelist.containsKey(filename)) { if (_uncheckedWhitelist.containsKey(filename)) {
var whitelisted = _uncheckedWhitelist[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 VoidTovoid = () => (VoidTovoid = dart.constFn(dart.definiteFunctionType(dart.void, [])))();
let dynamicTovoid = () => (dynamicTovoid = dart.constFn(dart.definiteFunctionType(dart.void, [dart.dynamic])))(); let dynamicTovoid = () => (dynamicTovoid = dart.constFn(dart.definiteFunctionType(dart.void, [dart.dynamic])))();
let FnTovoid = () => (FnTovoid = dart.constFn(dart.definiteFunctionType(dart.void, [VoidTodynamic()])))(); 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._Action0 = dart.typedef('_Action0', () => dart.functionType(dart.void, []));
async_helper._onAsyncEnd = null; dart.defineLazy(async_helper, {
async_helper._asyncLevel = 0; get _onAsyncEnd() {
return null;
},
set _onAsyncEnd(_) {},
get _asyncLevel() {
return 0;
},
set _asyncLevel(_) {}
});
async_helper._buildException = function(msg) { async_helper._buildException = function(msg) {
return core.Exception.new(dart.str`Fatal: ${msg}. This is most likely a bug in your test.`); 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; return Foo;
}); });
closure.Foo = Foo(); closure.Foo = Foo();
/** @final {string} */ dart.defineLazy(closure.Foo, {
closure.Foo.some_static_constant = "abc"; get some_static_constant() {
/** @final {string} */ return "abc";
closure.Foo.some_static_final = "abc"; },
/** @type {string} */ get some_static_final() {
closure.Foo.some_static_var = "abc"; return "abc";
},
get some_static_var() {
return "abc";
},
set some_static_var(_) {}
});
closure.Bar = class Bar extends core.Object {}; closure.Bar = class Bar extends core.Object {};
closure.Baz = class Baz extends dart.mixin(closure.Foo$(core.int), closure.Bar) { closure.Baz = class Baz extends dart.mixin(closure.Foo$(core.int), closure.Bar) {
new(i: number) { new(i: number) {
@ -137,12 +143,16 @@ dart.defineLazy(closure, {
return; return;
}, VoidToNull()); }, 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); dart.trackLibraries("closure", {"closure.dart": closure}, null);

View file

@ -75,7 +75,11 @@ define(['dart_sdk'], function(dart_sdk) {
new() { 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) { src__varargs.spread = function(args) {
dart.throw(new core.StateError('The spread function cannot be called, ' + 'it should be compiled away.')); 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() { es6_modules._f = function() {
}; };
dart.fn(es6_modules._f, VoidTodynamic()); dart.fn(es6_modules._f, VoidTodynamic());
es6_modules.constant = "abc";
es6_modules.finalConstant = "abc";
dart.defineLazy(es6_modules, { dart.defineLazy(es6_modules, {
get constant() {
return "abc";
},
get finalConstant() {
return "abc";
},
get lazy() { get lazy() {
return dart.fn(() => { return dart.fn(() => {
core.print('lazy'); core.print('lazy');
return "abc"; return "abc";
}, VoidToString())(); }, VoidToString())();
} },
}); get mutable() {
es6_modules.mutable = "abc"; return "abc";
dart.defineLazy(es6_modules, { },
set mutable(_) {},
get lazyMutable() { get lazyMutable() {
return dart.fn(() => { return dart.fn(() => {
core.print('lazyMutable'); core.print('lazyMutable');

View file

@ -7,12 +7,12 @@ define(['dart_sdk'], function(dart_sdk) {
const map_keys = Object.create(null); const map_keys = Object.create(null);
let VoidTodynamic = () => (VoidTodynamic = dart.constFn(dart.definiteFunctionType(dart.dynamic, [])))(); let VoidTodynamic = () => (VoidTodynamic = dart.constFn(dart.definiteFunctionType(dart.dynamic, [])))();
map_keys.main = function() { 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.String, core.int));
core.print(dart.map([1, 2, 3, 4, 5, 6])); 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.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'; let x = '3';
core.print(dart.map(['1', 2, x, 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.print(dart.map(['1', 2, null, 4, '5', 6], core.String, core.int));
}; };
dart.fn(map_keys.main, VoidTodynamic()); dart.fn(map_keys.main, VoidTodynamic());
dart.trackLibraries("map_keys", {"map_keys.dart": map_keys}, null); 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() { node_modules._f = function() {
}; };
dart.fn(node_modules._f, VoidTodynamic()); dart.fn(node_modules._f, VoidTodynamic());
node_modules.constant = "abc";
node_modules.finalConstant = "abc";
dart.defineLazy(node_modules, { dart.defineLazy(node_modules, {
get constant() {
return "abc";
},
get finalConstant() {
return "abc";
},
get lazy() { get lazy() {
return dart.fn(() => { return dart.fn(() => {
core.print('lazy'); core.print('lazy');
return "abc"; return "abc";
}, VoidToString())(); }, VoidToString())();
} },
}); get mutable() {
node_modules.mutable = "abc"; return "abc";
dart.defineLazy(node_modules, { },
set mutable(_) {},
get lazyMutable() { get lazyMutable() {
return dart.fn(() => { return dart.fn(() => {
core.print('lazyMutable'); 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 StringToElement = () => (StringToElement = dart.constFn(dart.definiteFunctionType(html.Element, [core.String])))();
let EventTovoid = () => (EventTovoid = dart.constFn(dart.definiteFunctionType(dart.void, [html.Event])))(); let EventTovoid = () => (EventTovoid = dart.constFn(dart.definiteFunctionType(dart.void, [html.Event])))();
let VoidTovoid = () => (VoidTovoid = dart.constFn(dart.definiteFunctionType(dart.void, [])))(); let VoidTovoid = () => (VoidTovoid = dart.constFn(dart.definiteFunctionType(dart.void, [])))();
sunflower.SEED_RADIUS = 2; dart.defineLazy(sunflower, {
sunflower.SCALE_FACTOR = 4; get SEED_RADIUS() {
sunflower.MAX_D = 300; return 2;
sunflower.centerX = sunflower.MAX_D / 2; },
sunflower.centerY = sunflower.centerX; 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) { sunflower.querySelector = function(selector) {
return html.document.querySelector(selector); return html.document.querySelector(selector);
}; };
@ -23,29 +35,24 @@ define(['dart_sdk'], function(dart_sdk) {
dart.defineLazy(sunflower, { dart.defineLazy(sunflower, {
get canvas() { get canvas() {
return html.CanvasElement.as(sunflower.querySelector("#canvas")); return html.CanvasElement.as(sunflower.querySelector("#canvas"));
} },
});
dart.defineLazy(sunflower, {
get context() { get context() {
return html.CanvasRenderingContext2D.as(sunflower.canvas[dartx.getContext]('2d')); return html.CanvasRenderingContext2D.as(sunflower.canvas[dartx.getContext]('2d'));
} },
});
dart.defineLazy(sunflower, {
get slider() { get slider() {
return html.InputElement.as(sunflower.querySelector("#slider")); return html.InputElement.as(sunflower.querySelector("#slider"));
} },
});
dart.defineLazy(sunflower, {
get notes() { get notes() {
return sunflower.querySelector("#notes"); return sunflower.querySelector("#notes");
} },
});
dart.defineLazy(sunflower, {
get PHI() { get PHI() {
return (dart.notNull(math.sqrt(5)) + 1) / 2; return (dart.notNull(math.sqrt(5)) + 1) / 2;
} },
get seeds() {
return 0;
},
set seeds(_) {}
}); });
sunflower.seeds = 0;
sunflower.main = function() { sunflower.main = function() {
sunflower.slider[dartx.addEventListener]('change', dart.fn(e => sunflower.draw(), EventTovoid())); sunflower.slider[dartx.addEventListener]('change', dart.fn(e => sunflower.draw(), EventTovoid()));
sunflower.draw(); sunflower.draw();
@ -133,10 +140,20 @@ define(['dart_sdk'], function(dart_sdk) {
if (color != null) this.color = color; if (color != null) this.color = color;
} }
}; };
painter.ORANGE = "orange"; dart.defineLazy(painter, {
painter.RED = "red"; get ORANGE() {
painter.BLUE = "blue"; return "orange";
painter.TAU = math.PI * 2; },
get RED() {
return "red";
},
get BLUE() {
return "blue";
},
get TAU() {
return math.PI * 2;
}
});
painter.querySelector = function(selector) { painter.querySelector = function(selector) {
return html.document.querySelector(selector); return html.document.querySelector(selector);
}; };
@ -144,9 +161,7 @@ define(['dart_sdk'], function(dart_sdk) {
dart.defineLazy(painter, { dart.defineLazy(painter, {
get canvas() { get canvas() {
return html.CanvasElement.as(painter.querySelector("#canvas")); return html.CanvasElement.as(painter.querySelector("#canvas"));
} },
});
dart.defineLazy(painter, {
get context() { get context() {
return html.CanvasRenderingContext2D.as(painter.canvas[dartx.getContext]('2d')); 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":";;;;;;;;;;;;;;IAYM;YAAc,EAAC;KAAA;IACf;YAAe,EAAC;KAAA;IAChB;YAAQ,IAAG;KAAA;IACX;YAAU,AAAAA,gBAAK,GAAG,CAAC,AAAA;KAAA;IACnB;YAAUC,kBAAO;KAAA;;AAEvB,4BAAqB,SAAC,QAAe,EAAE;UAAG,AAAAC,cAAQ,eAAeC,QAAQ,CAAC;GAAC,AAAA;AAAA;;IACrE;YAAS,uBAAA,AAAAC,uBAAa,CAAC,SAAS,CAAC,CAAiB;KAAA;IAClD;YAAU,kCAAA,AAAAC,gBAAM,mBAAY,IAAI,CAAC,CAA4B;KAAA;IAC7D;YAAS,sBAAA,AAAAD,uBAAa,CAAC,SAAS,CAAC,CAAgB;KAAA;IACjD;YAAQ,AAAAA,wBAAa,CAAC,QAAQ,CAAC;KAAA;IAE/B;YAAM,EAAA,aAACE,AAAA,SAAI,CAAC,CAAC,CAAC,IAAG,CAAC,AAAC,IAAG,CAAC,AAAA;KAAA;IACzB;YAAQ,EAAC;KAAA;IAAT,eAAS;;AAEb,mBAAS,WAAG;AACV,IAAA,AAAAC,gBAAM,yBAAkB,QAAQ,EAAE,QAAA,AAAC,CAAC,IAAK,AAAAC,cAAI,EAAE,AAAA,gBAAA,CAAC;AAAC,AACjD,IAAA,AAAAA,cAAI,EAAE;AAAC,GACR,AAAA;AAAA;AAED,mBACS,WAAG;AACV,IAAA,AAAAC,eAAK,GAAG,eAAU,AAAAF,gBAAM,MAAM,CAAC,AAAA;AAAC,AAChC,IAAA,AAAAG,iBAAO,WAAW,CAAC,EAAE,CAAC,EAAEV,eAAK,EAAEA,eAAK,CAAC;AAAC,AACtC,SAAK,IAAI,IAAI,CAAC,AAAA,AAAA,EAAE,AAAAW,CAAC,gBAAGF,eAAK,CAAA,EAAE,AAAAE,CAAC,EAAE,EAAE;AAC9B,kBAAc,AAAA,AAAAA,CAAC,GAAGC,WAAG,AAAA,gBAAGC,aAAG,CAAA;AAAC,AAC5B,cAAU,aAAA,AAAAP,SAAI,CAACK,CAAC,CAAC,IAAGG,sBAAY,AAAA;AAAC,AACjC,cAAU,AAAAb,iBAAO,GAAG,AAAAc,CAAC,gBAAG,AAAAC,QAAG,CAACC,KAAK,CAAC,CAAA,AAAA;AAAC,AACnC,cAAU,AAAAC,iBAAO,GAAG,AAAAH,CAAC,gBAAG,AAAAI,QAAG,CAACF,KAAK,CAAC,CAAA,AAAA;AAAC,AACnC,MAAA,AAAA,4BAAkBG,CAAC,EAAEC,CAAC,EAAEC,qBAAW,CAAC,MAAMZ,iBAAO,CAAC;AAAC,KACpD;AAAA,AACD,IAAA,AAAA,AAAAa,eAAK,YAAK,GAAG,WAAC,eAAM,QAAO,AAAA;AAAC,GAC7B,AAAA;AAAA;;;;;;;;;;;;;;;;;;;;ICnCC,IAAO,CAAM,EAAE,CAAM,EAAE,MAAW,EAAlC;;;;AAAmC,AAAC,KAAA;;;;;;;;;;;;;ICYtC;oBAEiBC,cAAM;KAevB;;;;;;;IAbE,KACU,OAAgC,EAAE;AAC1C,MAAAd,AACE,OADK,YACQ;MADfA,AAEE,AAAA,OAFK,UAEM,GAAG,CAAC,AAAA;MAFjBA,AAGE,AAAA,OAHK,UAGM,GAAGe,UAAK,AAAA;MAHrBf,AAIE,AAAA,OAJK,YAIQ,GAAGe,UAAK,AAAA;MAJvBf,AAKE,OALK,YAKCU,MAAC,EAAEC,MAAC,EAAEK,WAAM,EAAE,CAAC,EAAEd,WAAG,EAAE,KAAK,CAAC;MALpCF,AAME,OANK,cAMG;MANVA,AAOE,OAPK,YAOQ;MAPfA,AAQE,OARK,SAQK;AAAC,KACd,AAAA;;;;;;;;AFWH;IACE,IAAc,CAAK,EAAE,CAAK,EAAE,MAAU,EAAG,KAAY,EAArD;;AACM,gBAAMU,CAAC,EAAEC,CAAC,EAAEK,MAAM;AAAC,AAAC,AACxB,UAAI,AAAAD,KAAK,IAAI,IAAI,AAAA,EAAE,AAAA,AAAA,AAAA,IAAI,MAAM,GAAGA,KAAK,AAAA;AAAC,AAAA,AACvC,KAAA,AAAA;;AAEH;IE1CM;YAAS,SAAQ;KAAA;IACjB;YAAM,MAAK;KAAA;IACX;YAAO,OAAM;KAAA;IACb;YAAM,AAAAE,QAAE,GAAG,CAAC,AAAA;KAAA;;AAElB,0BAAqB,SAAC,QAAe,EAAE;UAAG,AAAAzB,cAAQ,eAAeC,QAAQ,CAAC;GAAC,AAAA;AAAA;;IAErE;YAAS,uBAAA,AAAAC,qBAAa,CAAC,SAAS,CAAC,CAAiB;KAAA;IAClD;YAAU,kCAAA,AAAAC,cAAM,mBAAY,IAAI,CAAC,CAA4B;KAAA","file":"sunflower.js"}

View file

@ -21,7 +21,11 @@ define(['dart_sdk'], function(dart_sdk) {
new() { 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) { src__varargs.spread = function(args) {
dart.throw(new core.StateError('The spread function cannot be called, ' + 'it should be compiled away.')); 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); compiler = new ModuleCompiler(analyzerOptions);
} }
JSModuleFile module = null; JSModuleFile module = null;
var exception, stackTrace;
try { try {
module = compiler.compile(unit, options); module = compiler.compile(unit, options);
} catch (e) {} } catch (e, st) {
exception = e;
stackTrace = st;
}
bool expectedCompileTimeError = bool expectedCompileTimeError =
contents.contains(': compile-time error\n'); contents.contains(': compile-time error\n');
@ -167,7 +171,8 @@ main(List<String> arguments) {
if (module == null) { if (module == null) {
expect(crashing, isTrue, expect(crashing, isTrue,
reason: "test $name crashes during compilation."); reason: "test $name crashes during compilation.\n"
"$exception\n$stackTrace");
} else if (module.isValid) { } else if (module.isValid) {
_writeModule( _writeModule(
path.join(codegenOutputDir, name), path.join(codegenOutputDir, name),