| Index: pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart
|
| diff --git a/pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart b/pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart
|
| index 9dd74c0d4658aac86bc380ebb3856769278a9d35..7f9d2e092fc7333727537d1818b76c7eb11578ef 100644
|
| --- a/pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart
|
| +++ b/pkg/compiler/lib/src/js_emitter/old_emitter/emitter.dart
|
| @@ -16,6 +16,7 @@ class OldEmitter implements Emitter {
|
| final InterceptorEmitter interceptorEmitter = new InterceptorEmitter();
|
| final MetadataEmitter metadataEmitter = new MetadataEmitter();
|
|
|
| + // TODO(johnniwinther): Wrap these fields in a caching strategy.
|
| final Set<ConstantValue> cachedEmittedConstants;
|
| final CodeBuffer cachedEmittedConstantsBuffer = new CodeBuffer();
|
| final Map<Element, ClassBuilder> cachedClassBuilders;
|
| @@ -30,8 +31,7 @@ class OldEmitter implements Emitter {
|
| TypeTestRegistry get typeTestRegistry => task.typeTestRegistry;
|
|
|
| // The full code that is written to each hunk part-file.
|
| - Map<OutputUnit, CodeBuffer> outputBuffers = new Map<OutputUnit, CodeBuffer>();
|
| - final CodeBuffer deferredConstants = new CodeBuffer();
|
| + Map<OutputUnit, CodeOutput> outputBuffers = new Map<OutputUnit, CodeOutput>();
|
|
|
| /** Shorter access to [isolatePropertiesName]. Both here in the code, as
|
| well as in the generated code. */
|
| @@ -61,14 +61,6 @@ class OldEmitter implements Emitter {
|
| String get n => compiler.enableMinification ? "" : "\n";
|
| String get N => compiler.enableMinification ? "\n" : ";\n";
|
|
|
| - CodeBuffer getBuffer(OutputUnit outputUnit) {
|
| - return outputBuffers.putIfAbsent(outputUnit, () => new CodeBuffer());
|
| - }
|
| -
|
| - CodeBuffer get mainBuffer {
|
| - return getBuffer(compiler.deferredLoadTask.mainOutputUnit);
|
| - }
|
| -
|
| /**
|
| * List of expressions and statements that will be included in the
|
| * precompiled function.
|
| @@ -133,8 +125,8 @@ class OldEmitter implements Emitter {
|
| _cspPrecompiledConstructorNames.clear();
|
| }
|
|
|
| - void addComment(String comment, CodeBuffer buffer) {
|
| - buffer.write(jsAst.prettyPrint(js.comment(comment), compiler));
|
| + void addComment(String comment, CodeOutput output) {
|
| + output.addBuffer(jsAst.prettyPrint(js.comment(comment), compiler));
|
| }
|
|
|
| @override
|
| @@ -330,14 +322,14 @@ class OldEmitter implements Emitter {
|
| jsAst.Expression defineClass = js('''
|
| function(name, fields) {
|
| var accessors = [];
|
| -
|
| +
|
| var str = "function " + name + "(";
|
| var body = "";
|
| if (#hasIsolateSupport) { var fieldNames = ""; }
|
| -
|
| +
|
| for (var i = 0; i < fields.length; i++) {
|
| if(i != 0) str += ", ";
|
| -
|
| +
|
| var field = generateAccessor(fields[i], accessors, name);
|
| if (#hasIsolateSupport) { fieldNames += "'" + field + "',"; }
|
| var parameter = "parameter_" + field;
|
| @@ -356,7 +348,7 @@ class OldEmitter implements Emitter {
|
| str += name + ".$fieldNamesProperty=[" + fieldNames + "];\\n";
|
| }
|
| str += accessors.join("");
|
| -
|
| +
|
| return str;
|
| }''', { 'hasIsolateSupport': hasIsolateSupport });
|
|
|
| @@ -576,9 +568,9 @@ class OldEmitter implements Emitter {
|
| 'allowNativesSubclassing': true});
|
| }
|
|
|
| - void emitFinishIsolateConstructorInvocation(CodeBuffer buffer) {
|
| + void emitFinishIsolateConstructorInvocation(CodeOutput output) {
|
| String isolate = namer.isolateName;
|
| - buffer.write("$isolate = $finishIsolateConstructorName($isolate)$N");
|
| + output.add("$isolate = $finishIsolateConstructorName($isolate)$N");
|
| }
|
|
|
| /// In minified mode we want to keep the name for the most common core types.
|
| @@ -758,7 +750,7 @@ class OldEmitter implements Emitter {
|
| }
|
| }
|
|
|
| - void emitStaticNonFinalFieldInitializations(CodeBuffer buffer,
|
| + void emitStaticNonFinalFieldInitializations(CodeOutput output,
|
| OutputUnit outputUnit) {
|
| JavaScriptConstantCompiler handler = backend.constants;
|
| Iterable<VariableElement> staticNonFinalFields =
|
| @@ -788,14 +780,14 @@ class OldEmitter implements Emitter {
|
| jsAst.Expression init =
|
| js('$isolateProperties.# = #',
|
| [namer.getNameOfGlobalField(element), initialValue]);
|
| - buffer.write(jsAst.prettyPrint(init, compiler,
|
| - monitor: compiler.dumpInfoTask));
|
| - buffer.write('$N');
|
| + output.addBuffer(jsAst.prettyPrint(init, compiler,
|
| + monitor: compiler.dumpInfoTask));
|
| + output.add('$N');
|
| });
|
| }
|
| }
|
|
|
| - void emitLazilyInitializedStaticFields(CodeBuffer buffer) {
|
| + void emitLazilyInitializedStaticFields(CodeOutput output) {
|
| JavaScriptConstantCompiler handler = backend.constants;
|
| List<VariableElement> lazyFields =
|
| handler.getLazilyInitializedFieldsForEmission();
|
| @@ -805,9 +797,9 @@ class OldEmitter implements Emitter {
|
| jsAst.Expression init =
|
| buildLazilyInitializedStaticField(element, isolateProperties);
|
| if (init == null) continue;
|
| - buffer.write(
|
| + output.addBuffer(
|
| jsAst.prettyPrint(init, compiler, monitor: compiler.dumpInfoTask));
|
| - buffer.write("$N");
|
| + output.add("$N");
|
| }
|
| }
|
| }
|
| @@ -866,25 +858,25 @@ class OldEmitter implements Emitter {
|
| return namer.constantName(a).compareTo(namer.constantName(b));
|
| }
|
|
|
| - void emitCompileTimeConstants(CodeBuffer buffer, OutputUnit outputUnit) {
|
| + void emitCompileTimeConstants(CodeOutput output, OutputUnit outputUnit) {
|
| List<ConstantValue> constants = outputConstantLists[outputUnit];
|
| if (constants == null) return;
|
| - bool isMainBuffer = buffer == mainBuffer;
|
| - if (compiler.hasIncrementalSupport && isMainBuffer) {
|
| - buffer = cachedEmittedConstantsBuffer;
|
| + CodeOutput constantOutput = output;
|
| + if (compiler.hasIncrementalSupport && outputUnit.isMainOutput) {
|
| + constantOutput = cachedEmittedConstantsBuffer;
|
| }
|
| for (ConstantValue constant in constants) {
|
| - if (compiler.hasIncrementalSupport && isMainBuffer) {
|
| + if (compiler.hasIncrementalSupport && outputUnit.isMainOutput) {
|
| if (cachedEmittedConstants.contains(constant)) continue;
|
| cachedEmittedConstants.add(constant);
|
| }
|
| jsAst.Expression init = buildConstantInitializer(constant);
|
| - buffer.write(jsAst.prettyPrint(init, compiler,
|
| - monitor: compiler.dumpInfoTask));
|
| - buffer.write('$N');
|
| + constantOutput.addBuffer(jsAst.prettyPrint(init, compiler,
|
| + monitor: compiler.dumpInfoTask));
|
| + constantOutput.add('$N');
|
| }
|
| - if (compiler.hasIncrementalSupport && isMainBuffer) {
|
| - mainBuffer.write(cachedEmittedConstantsBuffer);
|
| + if (compiler.hasIncrementalSupport && outputUnit.isMainOutput) {
|
| + output.addBuffer(constantOutput);
|
| }
|
| }
|
|
|
| @@ -901,8 +893,8 @@ class OldEmitter implements Emitter {
|
| '${namer.isolateName}.$makeConstListProperty(#)');
|
| }
|
|
|
| - void emitMakeConstantList(CodeBuffer buffer) {
|
| - buffer.write(
|
| + void emitMakeConstantList(CodeOutput output) {
|
| + output.addBuffer(
|
| jsAst.prettyPrint(
|
| // Functions are stored in the hidden class and not as properties in
|
| // the object. We never actually look at the value, but only want
|
| @@ -914,7 +906,7 @@ class OldEmitter implements Emitter {
|
| }''',
|
| [namer.isolateName, makeConstListProperty]),
|
| compiler, monitor: compiler.dumpInfoTask));
|
| - buffer.write(N);
|
| + output.add(N);
|
| }
|
|
|
| /// Returns the code equivalent to:
|
| @@ -987,7 +979,7 @@ class OldEmitter implements Emitter {
|
| return 'ZxYxX';
|
| }
|
|
|
| - emitMain(CodeBuffer buffer) {
|
| + emitMain(CodeOutput output) {
|
| if (compiler.isMockCompilation) return;
|
| Element main = compiler.mainFunction;
|
| jsAst.Expression mainCallClosure = null;
|
| @@ -1004,23 +996,23 @@ class OldEmitter implements Emitter {
|
| }
|
|
|
| if (backend.needToInitializeIsolateAffinityTag) {
|
| - buffer.write(
|
| + output.addBuffer(
|
| jsAst.prettyPrint(generateIsolateAffinityTagInitialization(),
|
| compiler, monitor: compiler.dumpInfoTask));
|
| - buffer.write(N);
|
| + output.add(N);
|
| }
|
| if (backend.needToInitializeDispatchProperty) {
|
| assert(backend.needToInitializeIsolateAffinityTag);
|
| - buffer.write(
|
| + output.addBuffer(
|
| jsAst.prettyPrint(generateDispatchPropertyNameInitialization(),
|
| compiler, monitor: compiler.dumpInfoTask));
|
| - buffer.write(N);
|
| + output.add(N);
|
| }
|
|
|
| jsAst.Expression currentScriptAccess =
|
| generateEmbeddedGlobalAccess(embeddedNames.CURRENT_SCRIPT);
|
|
|
| - addComment('BEGIN invoke [main].', buffer);
|
| + addComment('BEGIN invoke [main].', output);
|
| // This code finds the currently executing script by listening to the
|
| // onload event of all script tags and getting the first script which
|
| // finishes. Since onload is called immediately after execution this should
|
| @@ -1057,14 +1049,14 @@ class OldEmitter implements Emitter {
|
| })''', {'currentScript': currentScriptAccess,
|
| 'mainCallClosure': mainCallClosure});
|
|
|
| - buffer.write(';');
|
| - buffer.write(jsAst.prettyPrint(invokeMain,
|
| - compiler, monitor: compiler.dumpInfoTask));
|
| - buffer.write(N);
|
| - addComment('END invoke [main].', buffer);
|
| + output.add(';');
|
| + output.addBuffer(jsAst.prettyPrint(invokeMain,
|
| + compiler, monitor: compiler.dumpInfoTask));
|
| + output.add(N);
|
| + addComment('END invoke [main].', output);
|
| }
|
|
|
| - void emitInitFunction(CodeBuffer buffer) {
|
| + void emitInitFunction(CodeOutput output) {
|
| String isolate = namer.currentIsolate;
|
| jsAst.Expression allClassesAccess =
|
| generateEmbeddedGlobalAccess(embeddedNames.ALL_CLASSES);
|
| @@ -1094,17 +1086,17 @@ class OldEmitter implements Emitter {
|
| getterName, lazyValue) {
|
| if (!#lazies) #lazies = Object.create(null);
|
| #lazies[fieldName] = getterName;
|
| -
|
| +
|
| var sentinelUndefined = {};
|
| var sentinelInProgress = {};
|
| prototype[fieldName] = sentinelUndefined;
|
| -
|
| +
|
| prototype[getterName] = function () {
|
| var result = $isolate[fieldName];
|
| try {
|
| if (result === sentinelUndefined) {
|
| $isolate[fieldName] = sentinelInProgress;
|
| -
|
| +
|
| try {
|
| result = $isolate[fieldName] = lazyValue();
|
| } finally {
|
| @@ -1117,7 +1109,7 @@ class OldEmitter implements Emitter {
|
| if (result === sentinelInProgress)
|
| #cyclicThrow(staticName);
|
| }
|
| -
|
| +
|
| return result;
|
| } finally {
|
| $isolate[getterName] = function() { return this[fieldName]; };
|
| @@ -1175,7 +1167,7 @@ class OldEmitter implements Emitter {
|
| }
|
| return Isolate;
|
| }
|
| -
|
| +
|
| }''', {'allClasses': allClassesAccess,
|
| 'interceptorsByTag': interceptorsByTagAccess,
|
| 'leafTags': leafTagsAccess,
|
| @@ -1188,12 +1180,14 @@ class OldEmitter implements Emitter {
|
| 'hasIncrementalSupport': compiler.hasIncrementalSupport,
|
| 'lazyInitializerProperty': lazyInitializerProperty,});
|
|
|
| - buffer.write(jsAst.prettyPrint(decl,
|
| - compiler, monitor: compiler.dumpInfoTask).getText());
|
| - if (compiler.enableMinification) buffer.write('\n');
|
| + output.addBuffer(
|
| + jsAst.prettyPrint(decl, compiler, monitor: compiler.dumpInfoTask));
|
| + if (compiler.enableMinification) {
|
| + output.add('\n');
|
| + }
|
| }
|
|
|
| - void emitConvertToFastObjectFunction() {
|
| + void emitConvertToFastObjectFunction(CodeOutput output) {
|
| List<jsAst.Statement> debugCode = <jsAst.Statement>[];
|
| if (DEBUG_FAST_OBJECTS) {
|
| debugCode.add(js.statement(r'''
|
| @@ -1220,11 +1214,11 @@ class OldEmitter implements Emitter {
|
| return properties;
|
| }''', [debugCode]);
|
|
|
| - mainBuffer.write(jsAst.prettyPrint(convertToFastObject, compiler));
|
| - mainBuffer.write(N);
|
| + output.addBuffer(jsAst.prettyPrint(convertToFastObject, compiler));
|
| + output.add(N);
|
| }
|
|
|
| - void writeLibraryDescriptors(CodeBuffer buffer, LibraryElement library) {
|
| + void writeLibraryDescriptors(CodeOutput output, LibraryElement library) {
|
| var uri = "";
|
| if (!compiler.enableMinification || backend.mustPreserveUris) {
|
| uri = library.canonicalUri;
|
| @@ -1252,20 +1246,23 @@ class OldEmitter implements Emitter {
|
|
|
| compiler.dumpInfoTask.registerElementAst(library, metadata);
|
| compiler.dumpInfoTask.registerElementAst(library, initializers);
|
| - buffer
|
| - ..write('["$libraryName",$_')
|
| - ..write('"${uri}",$_')
|
| - ..write(metadata == null ? "" : jsAst.prettyPrint(metadata,
|
| - compiler,
|
| - monitor: compiler.dumpInfoTask))
|
| - ..write(',$_')
|
| - ..write(namer.globalObjectFor(library))
|
| - ..write(',$_')
|
| - ..write(jsAst.prettyPrint(initializers,
|
| - compiler,
|
| - monitor: compiler.dumpInfoTask))
|
| - ..write(library == compiler.mainApp ? ',${n}1' : "")
|
| - ..write('],$n');
|
| + output
|
| + ..add('["$libraryName",$_')
|
| + ..add('"${uri}",$_');
|
| + if (metadata != null) {
|
| + output.addBuffer(jsAst.prettyPrint(metadata,
|
| + compiler,
|
| + monitor: compiler.dumpInfoTask));
|
| + }
|
| + output
|
| + ..add(',$_')
|
| + ..add(namer.globalObjectFor(library))
|
| + ..add(',$_')
|
| + ..addBuffer(jsAst.prettyPrint(initializers,
|
| + compiler,
|
| + monitor: compiler.dumpInfoTask))
|
| + ..add(library == compiler.mainApp ? ',${n}1' : "")
|
| + ..add('],$n');
|
| }
|
|
|
| void emitPrecompiledConstructor(OutputUnit outputUnit,
|
| @@ -1292,7 +1289,7 @@ class OldEmitter implements Emitter {
|
| ''' /* next string is not a raw string */ '''
|
| if (#hasIsolateSupport) {
|
| #constructorName.$fieldNamesProperty = #fieldNamesArray;
|
| - }
|
| + }
|
| }''',
|
| {"constructorName": constructorName,
|
| "constructorNameString": js.string(constructorName),
|
| @@ -1374,7 +1371,7 @@ class OldEmitter implements Emitter {
|
| }
|
| }
|
|
|
| - void emitMangledNames() {
|
| + void emitMangledNames(CodeOutput mainBuffer) {
|
| if (!mangledFieldNames.isEmpty) {
|
| var keys = mangledFieldNames.keys.toList();
|
| keys.sort();
|
| @@ -1387,13 +1384,13 @@ class OldEmitter implements Emitter {
|
| jsAst.Expression mangledNamesAccess =
|
| generateEmbeddedGlobalAccess(embeddedNames.MANGLED_NAMES);
|
| var map = new jsAst.ObjectInitializer(properties);
|
| - mainBuffer.write(
|
| + mainBuffer.addBuffer(
|
| jsAst.prettyPrint(
|
| js.statement('# = #', [mangledNamesAccess, map]),
|
| compiler,
|
| monitor: compiler.dumpInfoTask));
|
| if (compiler.enableMinification) {
|
| - mainBuffer.write(';');
|
| + mainBuffer.add(';');
|
| }
|
| }
|
| if (!mangledGlobalFieldNames.isEmpty) {
|
| @@ -1407,13 +1404,13 @@ class OldEmitter implements Emitter {
|
| jsAst.Expression mangledGlobalNamesAccess =
|
| generateEmbeddedGlobalAccess(embeddedNames.MANGLED_GLOBAL_NAMES);
|
| var map = new jsAst.ObjectInitializer(properties);
|
| - mainBuffer.write(
|
| + mainBuffer.addBuffer(
|
| jsAst.prettyPrint(
|
| js.statement('# = #', [mangledGlobalNamesAccess, map]),
|
| compiler,
|
| monitor: compiler.dumpInfoTask));
|
| if (compiler.enableMinification) {
|
| - mainBuffer.write(';');
|
| + mainBuffer.add(';');
|
| }
|
| }
|
| }
|
| @@ -1437,27 +1434,39 @@ class OldEmitter implements Emitter {
|
|
|
| void emitMainOutputUnit(Map<OutputUnit, String> deferredLoadHashes,
|
| CodeBuffer nativeBuffer) {
|
| - bool isProgramSplit = compiler.deferredLoadTask.isProgramSplit;
|
| + LineColumnCollector lineColumnCollector;
|
| + List<CodeOutputListener> codeOutputListeners;
|
| + if (generateSourceMap) {
|
| + lineColumnCollector = new LineColumnCollector();
|
| + codeOutputListeners = <CodeOutputListener>[lineColumnCollector];
|
| + }
|
| +
|
| OutputUnit mainOutputUnit = compiler.deferredLoadTask.mainOutputUnit;
|
| + CodeOutput mainOutput =
|
| + new StreamCodeOutput(compiler.outputProvider('', 'js'),
|
| + codeOutputListeners);
|
| + outputBuffers[mainOutputUnit] = mainOutput;
|
| +
|
| + bool isProgramSplit = compiler.deferredLoadTask.isProgramSplit;
|
|
|
| - mainBuffer.write(buildGeneratedBy());
|
| - addComment(HOOKS_API_USAGE, mainBuffer);
|
| + mainOutput.add(buildGeneratedBy());
|
| + addComment(HOOKS_API_USAGE, mainOutput);
|
|
|
| if (isProgramSplit) {
|
| /// For deferred loading we communicate the initializers via this global
|
| /// variable. The deferred hunks will add their initialization to this.
|
| /// The semicolon is important in minified mode, without it the
|
| /// following parenthesis looks like a call to the object literal.
|
| - mainBuffer..write(
|
| + mainOutput.add(
|
| 'self.${deferredInitializers} = self.${deferredInitializers} || '
|
| 'Object.create(null);$n');
|
| }
|
|
|
| // Using a named function here produces easier to read stack traces in
|
| // Chrome/V8.
|
| - mainBuffer.write('(function(${namer.currentIsolate})$_{\n');
|
| + mainOutput.add('(function(${namer.currentIsolate})$_{\n');
|
| if (compiler.hasIncrementalSupport) {
|
| - mainBuffer.write(jsAst.prettyPrint(js.statement(
|
| + mainOutput.addBuffer(jsAst.prettyPrint(js.statement(
|
| """
|
| {
|
| #helper = #helper || Object.create(null);
|
| @@ -1477,9 +1486,9 @@ class OldEmitter implements Emitter {
|
| if (isProgramSplit) {
|
| /// We collect all the global state of the, so it can be passed to the
|
| /// initializer of deferred files.
|
| - mainBuffer.write('var ${globalsHolder}$_=${_}Object.create(null)$N');
|
| + mainOutput.add('var ${globalsHolder}$_=${_}Object.create(null)$N');
|
| }
|
| - mainBuffer.write('function dart()$_{$n'
|
| + mainOutput.add('function dart()$_{$n'
|
| '${_}${_}this.x$_=${_}0$N'
|
| '${_}${_}delete this.x$N'
|
| '}$n');
|
| @@ -1489,22 +1498,22 @@ class OldEmitter implements Emitter {
|
| // to these objects. Later on, we attempt to turn these objects into
|
| // fast objects by calling "convertToFastObject" (see
|
| // [emitConvertToFastObjectFunction]).
|
| - mainBuffer.write('var ${globalObject}$_=${_}');
|
| + mainOutput.add('var ${globalObject}$_=${_}');
|
| if(isProgramSplit) {
|
| - mainBuffer.write('${globalsHolder}.$globalObject$_=${_}');
|
| + mainOutput.add('${globalsHolder}.$globalObject$_=${_}');
|
| }
|
| - mainBuffer.write('new dart$N');
|
| + mainOutput.add('new dart$N');
|
| }
|
|
|
| - mainBuffer.write('function ${namer.isolateName}()$_{}\n');
|
| + mainOutput.add('function ${namer.isolateName}()$_{}\n');
|
| if (isProgramSplit) {
|
| - mainBuffer
|
| - .write('${globalsHolder}.${namer.isolateName}$_=$_'
|
| - '${namer.isolateName}$N'
|
| - '${globalsHolder}.$initName$_=${_}$initName$N');
|
| + mainOutput
|
| + .add('${globalsHolder}.${namer.isolateName}$_=$_'
|
| + '${namer.isolateName}$N'
|
| + '${globalsHolder}.$initName$_=${_}$initName$N');
|
| }
|
| - mainBuffer.write('init()$N$n');
|
| - mainBuffer.write('$isolateProperties$_=$_$isolatePropertiesName$N');
|
| + mainOutput.add('init()$N$n');
|
| + mainOutput.add('$isolateProperties$_=$_$isolatePropertiesName$N');
|
|
|
| emitStaticFunctions(task.outputStaticLists[mainOutputUnit]);
|
|
|
| @@ -1516,7 +1525,7 @@ class OldEmitter implements Emitter {
|
| }
|
|
|
| if (compiler.enableMinification) {
|
| - mainBuffer.write(';');
|
| + mainOutput.add(';');
|
| }
|
|
|
| if (elementDescriptors.isNotEmpty) {
|
| @@ -1525,70 +1534,67 @@ class OldEmitter implements Emitter {
|
| if (libraries == null) libraries = [];
|
| emitLibraries(libraries);
|
| emitTypedefs();
|
| - emitMangledNames();
|
| + emitMangledNames(mainOutput);
|
|
|
| checkEverythingEmitted(elementDescriptors.keys);
|
|
|
| - CodeBuffer libraryBuffer = new CodeBuffer();
|
| - for (LibraryElement library in Elements.sortedByPosition(libraries)) {
|
| - writeLibraryDescriptors(libraryBuffer, library);
|
| - elementDescriptors.remove(library);
|
| - }
|
| -
|
| - mainBuffer
|
| - ..write('(')
|
| - ..write(
|
| + mainOutput
|
| + ..add('(')
|
| + ..addBuffer(
|
| jsAst.prettyPrint(
|
| getReflectionDataParser(this, backend),
|
| compiler))
|
| - ..write(')')
|
| - ..write('([$n')
|
| - ..write(libraryBuffer)
|
| - ..write('])$N');
|
| + ..add(')')
|
| + ..add('([$n');
|
| + for (LibraryElement library in Elements.sortedByPosition(libraries)) {
|
| + writeLibraryDescriptors(mainOutput, library);
|
| + elementDescriptors.remove(library);
|
| + }
|
| + mainOutput.add('])$N');
|
| }
|
|
|
| - interceptorEmitter.emitGetInterceptorMethods(mainBuffer);
|
| - interceptorEmitter.emitOneShotInterceptors(mainBuffer);
|
| + interceptorEmitter.emitGetInterceptorMethods(mainOutput);
|
| + interceptorEmitter.emitOneShotInterceptors(mainOutput);
|
|
|
| if (task.outputContainsConstantList) {
|
| - emitMakeConstantList(mainBuffer);
|
| + emitMakeConstantList(mainOutput);
|
| }
|
|
|
| // Constants in checked mode call into RTI code to set type information
|
| // which may need getInterceptor (and one-shot interceptor) methods, so
|
| // we have to make sure that [emitGetInterceptorMethods] and
|
| // [emitOneShotInterceptors] have been called.
|
| - emitCompileTimeConstants(mainBuffer, mainOutputUnit);
|
| + emitCompileTimeConstants(mainOutput, mainOutputUnit);
|
|
|
| - emitDeferredBoilerPlate(mainBuffer, deferredLoadHashes);
|
| + emitDeferredBoilerPlate(mainOutput, deferredLoadHashes);
|
|
|
| // Static field initializations require the classes and compile-time
|
| // constants to be set up.
|
| - emitStaticNonFinalFieldInitializations(mainBuffer, mainOutputUnit);
|
| - interceptorEmitter.emitInterceptedNames(mainBuffer);
|
| - interceptorEmitter.emitMapTypeToInterceptor(mainBuffer);
|
| - emitLazilyInitializedStaticFields(mainBuffer);
|
| + emitStaticNonFinalFieldInitializations(mainOutput, mainOutputUnit);
|
| + interceptorEmitter.emitInterceptedNames(mainOutput);
|
| + interceptorEmitter.emitMapTypeToInterceptor(mainOutput);
|
| + emitLazilyInitializedStaticFields(mainOutput);
|
|
|
| - mainBuffer.writeln();
|
| - mainBuffer.write(nativeBuffer);
|
| + mainOutput.add('\n');
|
| + mainOutput.addBuffer(nativeBuffer);
|
|
|
| - metadataEmitter.emitMetadata(mainBuffer);
|
| + metadataEmitter.emitMetadata(mainOutput);
|
|
|
| isolateProperties = isolatePropertiesName;
|
| // The following code should not use the short-hand for the
|
| // initialStatics.
|
| - mainBuffer.write('${namer.currentIsolate}$_=${_}null$N');
|
| + mainOutput.add('${namer.currentIsolate}$_=${_}null$N');
|
|
|
| - emitFinishIsolateConstructorInvocation(mainBuffer);
|
| - mainBuffer.write(
|
| + emitFinishIsolateConstructorInvocation(mainOutput);
|
| + mainOutput.add(
|
| '${namer.currentIsolate}$_=${_}new ${namer.isolateName}()$N');
|
|
|
| - emitConvertToFastObjectFunction();
|
| + emitConvertToFastObjectFunction(mainOutput);
|
| for (String globalObject in Namer.reservedGlobalObjectNames) {
|
| - mainBuffer.write('$globalObject = convertToFastObject($globalObject)$N');
|
| + mainOutput.add('$globalObject = convertToFastObject($globalObject)$N');
|
| }
|
| if (DEBUG_FAST_OBJECTS) {
|
| - mainBuffer.write(r'''
|
| + mainOutput.add(r'''
|
| // The following only works on V8 when run with option
|
| // "--allow-natives-syntax". We use'new Function' because the
|
| // miniparser does not understand V8 native syntax.
|
| @@ -1617,7 +1623,7 @@ class OldEmitter implements Emitter {
|
| }
|
| ''');
|
| for (String object in Namer.userGlobalObjects) {
|
| - mainBuffer.write('''
|
| + mainOutput.add('''
|
| if (typeof print === "function") {
|
| print("Size of $object: "
|
| + String(Object.getOwnPropertyNames($object).length)
|
| @@ -1629,31 +1635,30 @@ class OldEmitter implements Emitter {
|
|
|
| jsAst.FunctionDeclaration precompiledFunctionAst =
|
| buildCspPrecompiledFunctionFor(mainOutputUnit);
|
| - emitInitFunction(mainBuffer);
|
| - emitMain(mainBuffer);
|
| - mainBuffer.write('})()\n');
|
| + emitInitFunction(mainOutput);
|
| + emitMain(mainOutput);
|
| + mainOutput.add('})()\n');
|
|
|
| if (compiler.useContentSecurityPolicy) {
|
| - mainBuffer.write(
|
| + mainOutput.addBuffer(
|
| jsAst.prettyPrint(
|
| precompiledFunctionAst,
|
| compiler,
|
| monitor: compiler.dumpInfoTask,
|
| - allowVariableMinification: false).getText());
|
| + allowVariableMinification: false));
|
| }
|
|
|
| - String assembledCode = mainBuffer.getText();
|
| if (generateSourceMap) {
|
| - outputSourceMap(assembledCode, mainBuffer, '',
|
| - compiler.sourceMapUri, compiler.outputUri);
|
| - mainBuffer.write(
|
| + mainOutput.add(
|
| generateSourceMapTag(compiler.sourceMapUri, compiler.outputUri));
|
| - assembledCode = mainBuffer.getText();
|
| }
|
|
|
| - compiler.outputProvider('', 'js')
|
| - ..add(assembledCode)
|
| - ..close();
|
| + mainOutput.close();
|
| +
|
| + if (generateSourceMap) {
|
| + outputSourceMap(mainOutput, lineColumnCollector, '',
|
| + compiler.sourceMapUri, compiler.outputUri);
|
| + }
|
| }
|
|
|
| /// Used by incremental compilation to patch up the prototype of
|
| @@ -1802,6 +1807,7 @@ function(originalDescriptor, name, holder, isStatic, globalFunctionsAccess) {
|
| if (libraries == null) libraries = [];
|
| emitLibraries(libraries);
|
|
|
| + // TODO(johnniwinther): Avoid creating [CodeBuffer]s.
|
| CodeBuffer buffer = new CodeBuffer();
|
| outputBuffers[outputUnit] = buffer;
|
| for (LibraryElement library in Elements.sortedByPosition(libraries)) {
|
| @@ -1816,6 +1822,7 @@ function(originalDescriptor, name, holder, isStatic, globalFunctionsAccess) {
|
|
|
| CodeBuffer buildNativesBuffer() {
|
| // Emit native classes on [nativeBuffer].
|
| + // TODO(johnniwinther): Avoid creating a [CodeBuffer].
|
| final CodeBuffer nativeBuffer = new CodeBuffer();
|
|
|
| if (nativeClasses.isEmpty) return nativeBuffer;
|
| @@ -1823,8 +1830,7 @@ function(originalDescriptor, name, holder, isStatic, globalFunctionsAccess) {
|
|
|
| addComment('Native classes', nativeBuffer);
|
|
|
| - nativeEmitter.generateNativeClasses(nativeClasses, mainBuffer,
|
| - additionalProperties);
|
| + nativeEmitter.generateNativeClasses(nativeClasses, additionalProperties);
|
|
|
| nativeEmitter.finishGenerateNativeClasses();
|
| nativeEmitter.assembleCode(nativeBuffer);
|
| @@ -1849,7 +1855,6 @@ function(originalDescriptor, name, holder, isStatic, globalFunctionsAccess) {
|
| !backend.htmlLibraryIsLoaded) {
|
| compiler.reportHint(NO_LOCATION_SPANNABLE, MessageKind.PREAMBLE);
|
| }
|
| -
|
| // Return the total program size.
|
| return outputBuffers.values.fold(0, (a, b) => a + b.length);
|
| }
|
| @@ -1888,18 +1893,18 @@ function(originalDescriptor, name, holder, isStatic, globalFunctionsAccess) {
|
| () => new ClassBuilder(owner, namer));
|
| }
|
|
|
| - /// Emits support-code for deferred loading into [buffer].
|
| - void emitDeferredBoilerPlate(CodeBuffer buffer,
|
| + /// Emits support-code for deferred loading into [output].
|
| + void emitDeferredBoilerPlate(CodeOutput output,
|
| Map<OutputUnit, String> deferredLoadHashes) {
|
| // Function for checking if a hunk is loaded given its hash.
|
| - buffer.write(jsAst.prettyPrint(
|
| + output.addBuffer(jsAst.prettyPrint(
|
| js('# = function(hunkHash) {'
|
| ' return !!$deferredInitializers[hunkHash];'
|
| '}', generateEmbeddedGlobalAccess(embeddedNames.IS_HUNK_LOADED)),
|
| compiler, monitor: compiler.dumpInfoTask));
|
| - buffer.write('$N');
|
| + output.add('$N');
|
| // Function for initializing a loaded hunk, given its hash.
|
| - buffer.write(jsAst.prettyPrint(
|
| + output.addBuffer(jsAst.prettyPrint(
|
| js('# = function(hunkHash) {'
|
| ' $deferredInitializers[hunkHash]('
|
| '$globalsHolder, ${namer.currentIsolate})'
|
| @@ -1907,7 +1912,7 @@ function(originalDescriptor, name, holder, isStatic, globalFunctionsAccess) {
|
| generateEmbeddedGlobalAccess(
|
| embeddedNames.INITIALIZE_LOADED_HUNK)),
|
| compiler, monitor: compiler.dumpInfoTask));
|
| - buffer.write('$N');
|
| + output.add('$N');
|
| // Write a javascript mapping from Deferred import load ids (derrived
|
| // from the import prefix.) to a list of lists of uris of hunks to load,
|
| // and a corresponding mapping to a list of hashes used by
|
| @@ -1941,11 +1946,10 @@ function(originalDescriptor, name, holder, isStatic, globalFunctionsAccess) {
|
| new jsAst.ObjectInitializer(properties, isOneLiner: true);
|
|
|
| jsAst.Node globalName = generateEmbeddedGlobalAccess(name);
|
| - buffer.write(jsAst.prettyPrint(
|
| + output.addBuffer(jsAst.prettyPrint(
|
| js("# = #", [globalName, initializer]),
|
| compiler, monitor: compiler.dumpInfoTask));
|
| - buffer.write('$N');
|
| -
|
| + output.add('$N');
|
| }
|
|
|
| emitMapping(embeddedNames.DEFERRED_LIBRARY_URIS, deferredLibraryUris);
|
| @@ -1964,39 +1968,54 @@ function(originalDescriptor, name, holder, isStatic, globalFunctionsAccess) {
|
| for (OutputUnit outputUnit in compiler.deferredLoadTask.allOutputUnits) {
|
| if (outputUnit == compiler.deferredLoadTask.mainOutputUnit) continue;
|
|
|
| - CodeBuffer libraryDescriptorBuffer = deferredBuffers[outputUnit];
|
| + CodeOutput libraryDescriptorBuffer = deferredBuffers[outputUnit];
|
|
|
| - CodeBuffer outputBuffer = new CodeBuffer();
|
| + List<CodeOutputListener> outputListeners = <CodeOutputListener>[];
|
| + Hasher hasher = new Hasher();
|
| + outputListeners.add(hasher);
|
|
|
| - outputBuffer..write(buildGeneratedBy())
|
| - ..write('${deferredInitializers}.current$_=$_'
|
| - 'function$_(${globalsHolder}) {$N');
|
| + LineColumnCollector lineColumnCollector;
|
| + if (generateSourceMap) {
|
| + lineColumnCollector = new LineColumnCollector();
|
| + outputListeners.add(lineColumnCollector);
|
| + }
|
| +
|
| + String partPrefix = deferredPartFileName(outputUnit, addExtension: false);
|
| + CodeOutput output = new StreamCodeOutput(
|
| + compiler.outputProvider(partPrefix, 'part.js'),
|
| + outputListeners);
|
| +
|
| + outputBuffers[outputUnit] = output;
|
| +
|
| + output
|
| + ..add(buildGeneratedBy())
|
| + ..add('${deferredInitializers}.current$_=$_'
|
| + 'function$_(${globalsHolder}) {$N');
|
| for (String globalObject in Namer.reservedGlobalObjectNames) {
|
| - outputBuffer
|
| - .write('var $globalObject$_=$_'
|
| - '${globalsHolder}.$globalObject$N');
|
| + output
|
| + .add('var $globalObject$_=$_'
|
| + '${globalsHolder}.$globalObject$N');
|
| }
|
| - outputBuffer
|
| - ..write('var init$_=$_${globalsHolder}.init$N')
|
| - ..write('var ${namer.isolateName}$_=$_'
|
| + output
|
| + ..add('var init$_=$_${globalsHolder}.init$N')
|
| + ..add('var ${namer.isolateName}$_=$_'
|
| '${globalsHolder}.${namer.isolateName}$N');
|
| if (libraryDescriptorBuffer != null) {
|
| // TODO(ahe): This defines a lot of properties on the
|
| // Isolate.prototype object. We know this will turn it into a
|
| // slow object in V8, so instead we should do something similar
|
| // to Isolate.$finishIsolateConstructor.
|
| - outputBuffer
|
| - ..write('var ${namer.currentIsolate}$_=$_$isolatePropertiesName;$n')
|
| - ..write('(')
|
| - ..write(
|
| + output
|
| + ..add('var ${namer.currentIsolate}$_=$_$isolatePropertiesName;$n')
|
| + ..add('(')
|
| + ..addBuffer(
|
| jsAst.prettyPrint(
|
| getReflectionDataParser(this, backend),
|
| compiler, monitor: compiler.dumpInfoTask))
|
| - ..write(')')
|
| - ..write('([$n')
|
| + ..add(')')
|
| + ..add('([$n')
|
| ..addBuffer(libraryDescriptorBuffer)
|
| - ..write('])$N');
|
| -
|
| + ..add('])$N');
|
| }
|
|
|
| // Set the currentIsolate variable to the current isolate (which is
|
| @@ -2008,33 +2027,33 @@ function(originalDescriptor, name, holder, isStatic, globalFunctionsAccess) {
|
| // After we have done the setup it must point to the current Isolate.
|
| // Otherwise all methods/functions accessing isolate variables will
|
| // access the wrong object.
|
| - outputBuffer.write("${namer.currentIsolate}$_=${_}arguments[1]$N");
|
| + output.add("${namer.currentIsolate}$_=${_}arguments[1]$N");
|
|
|
| - emitCompileTimeConstants(outputBuffer, outputUnit);
|
| - emitStaticNonFinalFieldInitializations(outputBuffer, outputUnit);
|
| - outputBuffer.write('}$N');
|
| + emitCompileTimeConstants(output, outputUnit);
|
| + emitStaticNonFinalFieldInitializations(output, outputUnit);
|
| + output.add('}$N');
|
|
|
| if (compiler.useContentSecurityPolicy) {
|
| jsAst.FunctionDeclaration precompiledFunctionAst =
|
| buildCspPrecompiledFunctionFor(outputUnit);
|
|
|
| - outputBuffer.write(
|
| + output.addBuffer(
|
| jsAst.prettyPrint(
|
| precompiledFunctionAst, compiler,
|
| monitor: compiler.dumpInfoTask,
|
| - allowVariableMinification: false).getText());
|
| + allowVariableMinification: false));
|
| }
|
|
|
| // Make a unique hash of the code (before the sourcemaps are added)
|
| // This will be used to retrieve the initializing function from the global
|
| // variable.
|
| - String hash = hashOfString(outputBuffer.getText());
|
| + String hash = hasher.getHash();
|
|
|
| - outputBuffer.write('${deferredInitializers}["$hash"]$_=$_'
|
| - '${deferredInitializers}.current$N');
|
| + output.add('${deferredInitializers}["$hash"]$_=$_'
|
| + '${deferredInitializers}.current$N');
|
|
|
| - String partPrefix = deferredPartFileName(outputUnit, addExtension: false);
|
| if (generateSourceMap) {
|
| +
|
| Uri mapUri, partUri;
|
| Uri sourceMapUri = compiler.sourceMapUri;
|
| Uri outputUri = compiler.outputUri;
|
| @@ -2055,16 +2074,14 @@ function(originalDescriptor, name, holder, isStatic, globalFunctionsAccess) {
|
| partUri = compiler.outputUri.replace(pathSegments: partSegments);
|
| }
|
|
|
| - outputSourceMap(outputBuffer.getText(), outputBuffer, partName,
|
| - mapUri, partUri);
|
| - outputBuffer.write(generateSourceMapTag(mapUri, partUri));
|
| + output.add(generateSourceMapTag(mapUri, partUri));
|
| + output.close();
|
| + outputSourceMap(output, lineColumnCollector, partName,
|
| + mapUri, partUri);
|
| + } else {
|
| + output.close();
|
| }
|
|
|
| - outputBuffers[outputUnit] = outputBuffer;
|
| - compiler.outputProvider(partPrefix, 'part.js')
|
| - ..add(outputBuffer.getText())
|
| - ..close();
|
| -
|
| hunkHashes[outputUnit] = hash;
|
| }
|
| return hunkHashes;
|
| @@ -2076,15 +2093,17 @@ function(originalDescriptor, name, holder, isStatic, globalFunctionsAccess) {
|
| return '// Generated by dart2js, the Dart to JavaScript compiler$suffix.\n';
|
| }
|
|
|
| - void outputSourceMap(String code, CodeBuffer buffer, String name,
|
| - [Uri sourceMapUri, Uri fileUri]) {
|
| + void outputSourceMap(CodeOutput output,
|
| + LineColumnProvider lineColumnProvider,
|
| + String name,
|
| + [Uri sourceMapUri,
|
| + Uri fileUri]) {
|
| if (!generateSourceMap) return;
|
| // Create a source file for the compilation output. This allows using
|
| // [:getLine:] to transform offsets to line numbers in [SourceMapBuilder].
|
| - SourceFile compiledFile = new StringSourceFile(null, code);
|
| SourceMapBuilder sourceMapBuilder =
|
| - new SourceMapBuilder(sourceMapUri, fileUri, compiledFile);
|
| - buffer.forEachSourceLocation(sourceMapBuilder.addMapping);
|
| + new SourceMapBuilder(sourceMapUri, fileUri, lineColumnProvider);
|
| + output.forEachSourceLocation(sourceMapBuilder.addMapping);
|
| String sourceMap = sourceMapBuilder.build();
|
| compiler.outputProvider(name, 'js.map')
|
| ..add(sourceMap)
|
|
|