Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(10)

Side by Side Diff: pkg/compiler/lib/src/js_emitter/full_emitter/emitter.dart

Issue 1859343004: dartfmt pkg/compiler (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library dart2js.js_emitter.full_emitter; 5 library dart2js.js_emitter.full_emitter;
6 6
7 import 'dart:convert'; 7 import 'dart:convert';
8 import 'dart:collection' show HashMap; 8 import 'dart:collection' show HashMap;
9 9
10 import 'package:js_runtime/shared/embedded_names.dart' as embeddedNames; 10 import 'package:js_runtime/shared/embedded_names.dart' as embeddedNames;
11 import 'package:js_runtime/shared/embedded_names.dart' show 11 import 'package:js_runtime/shared/embedded_names.dart'
12 JsBuiltin, 12 show JsBuiltin, JsGetName;
13 JsGetName;
14 13
15 import '../headers.dart'; 14 import '../headers.dart';
16 import '../js_emitter.dart' hide Emitter; 15 import '../js_emitter.dart' hide Emitter;
17 import '../js_emitter.dart' as js_emitter show Emitter; 16 import '../js_emitter.dart' as js_emitter show Emitter;
18 import '../model.dart'; 17 import '../model.dart';
19 import '../program_builder/program_builder.dart'; 18 import '../program_builder/program_builder.dart';
20 import '../constant_ordering.dart' show deepCompareConstants; 19 import '../constant_ordering.dart' show deepCompareConstants;
21 20
22 import '../../common.dart'; 21 import '../../common.dart';
23 import '../../common/names.dart' show 22 import '../../common/names.dart' show Names;
24 Names; 23 import '../../compiler.dart' show Compiler;
25 import '../../compiler.dart' show
26 Compiler;
27 import '../../constants/values.dart'; 24 import '../../constants/values.dart';
28 import '../../core_types.dart' show 25 import '../../core_types.dart' show CoreClasses;
29 CoreClasses; 26 import '../../dart_types.dart' show DartType;
30 import '../../dart_types.dart' show
31 DartType;
32 import '../../deferred_load.dart' show OutputUnit; 27 import '../../deferred_load.dart' show OutputUnit;
33 import '../../elements/elements.dart' show 28 import '../../elements/elements.dart'
34 ClassElement, 29 show
35 ConstructorBodyElement, 30 ClassElement,
36 Element, 31 ConstructorBodyElement,
37 Elements, 32 Element,
38 ElementKind, 33 Elements,
39 FieldElement, 34 ElementKind,
40 FunctionElement, 35 FieldElement,
41 FunctionSignature, 36 FunctionElement,
42 LibraryElement, 37 FunctionSignature,
43 MetadataAnnotation, 38 LibraryElement,
44 MethodElement, 39 MetadataAnnotation,
45 MemberElement, 40 MethodElement,
46 Name, 41 MemberElement,
47 ParameterElement, 42 Name,
48 TypedefElement, 43 ParameterElement,
49 TypeVariableElement, 44 TypedefElement,
50 VariableElement; 45 TypeVariableElement,
46 VariableElement;
51 import '../../hash/sha1.dart' show Hasher; 47 import '../../hash/sha1.dart' show Hasher;
52 import '../../io/code_output.dart'; 48 import '../../io/code_output.dart';
53 import '../../io/line_column_provider.dart' show 49 import '../../io/line_column_provider.dart'
54 LineColumnCollector, 50 show LineColumnCollector, LineColumnProvider;
55 LineColumnProvider; 51 import '../../io/source_map_builder.dart' show SourceMapBuilder;
56 import '../../io/source_map_builder.dart' show
57 SourceMapBuilder;
58 import '../../js/js.dart' as jsAst; 52 import '../../js/js.dart' as jsAst;
59 import '../../js/js.dart' show js; 53 import '../../js/js.dart' show js;
60 import '../../js_backend/backend_helpers.dart' show 54 import '../../js_backend/backend_helpers.dart' show BackendHelpers;
61 BackendHelpers; 55 import '../../js_backend/js_backend.dart'
62 import '../../js_backend/js_backend.dart' show 56 show
63 CheckedModeHelper, 57 CheckedModeHelper,
64 CompoundName, 58 CompoundName,
65 ConstantEmitter, 59 ConstantEmitter,
66 CustomElementsAnalysis, 60 CustomElementsAnalysis,
67 GetterName, 61 GetterName,
68 JavaScriptBackend, 62 JavaScriptBackend,
69 JavaScriptConstantCompiler, 63 JavaScriptConstantCompiler,
70 Namer, 64 Namer,
71 RuntimeTypes, 65 RuntimeTypes,
72 SetterName, 66 SetterName,
73 Substitution, 67 Substitution,
74 TypeCheck, 68 TypeCheck,
75 TypeChecks, 69 TypeChecks,
76 TypeVariableHandler; 70 TypeVariableHandler;
77 import '../../universe/call_structure.dart' show 71 import '../../universe/call_structure.dart' show CallStructure;
78 CallStructure; 72 import '../../universe/selector.dart' show Selector;
79 import '../../universe/selector.dart' show 73 import '../../util/characters.dart' show $$, $A, $HASH, $PERIOD, $Z, $a, $z;
80 Selector; 74 import '../../util/uri_extras.dart' show relativize;
81 import '../../util/characters.dart' show 75 import '../../util/util.dart' show equalElements;
82 $$,
83 $A,
84 $HASH,
85 $PERIOD,
86 $Z,
87 $a,
88 $z;
89 import '../../util/uri_extras.dart' show
90 relativize;
91 import '../../util/util.dart' show
92 equalElements;
93 76
94 part 'class_builder.dart'; 77 part 'class_builder.dart';
95 part 'class_emitter.dart'; 78 part 'class_emitter.dart';
96 part 'code_emitter_helper.dart'; 79 part 'code_emitter_helper.dart';
97 part 'container_builder.dart'; 80 part 'container_builder.dart';
98 part 'declarations.dart'; 81 part 'declarations.dart';
99 part 'deferred_output_unit_hash.dart'; 82 part 'deferred_output_unit_hash.dart';
100 part 'interceptor_emitter.dart'; 83 part 'interceptor_emitter.dart';
101 part 'nsm_emitter.dart'; 84 part 'nsm_emitter.dart';
102 part 'setup_program_builder.dart'; 85 part 'setup_program_builder.dart';
103 86
104
105 class Emitter implements js_emitter.Emitter { 87 class Emitter implements js_emitter.Emitter {
106 final Compiler compiler; 88 final Compiler compiler;
107 final CodeEmitterTask task; 89 final CodeEmitterTask task;
108 90
109 // The following fields will be set to copies of the program-builder's 91 // The following fields will be set to copies of the program-builder's
110 // collector. 92 // collector.
111 Map<OutputUnit, List<VariableElement>> outputStaticNonFinalFieldLists; 93 Map<OutputUnit, List<VariableElement>> outputStaticNonFinalFieldLists;
112 Map<OutputUnit, Set<LibraryElement>> outputLibraryLists; 94 Map<OutputUnit, Set<LibraryElement>> outputLibraryLists;
113 List<TypedefElement> typedefsNeededForReflection; 95 List<TypedefElement> typedefsNeededForReflection;
114 96
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
195 containerBuilder.emitter = this; 177 containerBuilder.emitter = this;
196 classEmitter.emitter = this; 178 classEmitter.emitter = this;
197 nsmEmitter.emitter = this; 179 nsmEmitter.emitter = this;
198 interceptorEmitter.emitter = this; 180 interceptorEmitter.emitter = this;
199 } 181 }
200 182
201 DiagnosticReporter get reporter => compiler.reporter; 183 DiagnosticReporter get reporter => compiler.reporter;
202 184
203 List<jsAst.Node> cspPrecompiledFunctionFor(OutputUnit outputUnit) { 185 List<jsAst.Node> cspPrecompiledFunctionFor(OutputUnit outputUnit) {
204 return _cspPrecompiledFunctions.putIfAbsent( 186 return _cspPrecompiledFunctions.putIfAbsent(
205 outputUnit, 187 outputUnit, () => new List<jsAst.Node>());
206 () => new List<jsAst.Node>());
207 } 188 }
208 189
209 List<jsAst.Expression> cspPrecompiledConstructorNamesFor( 190 List<jsAst.Expression> cspPrecompiledConstructorNamesFor(
210 OutputUnit outputUnit) { 191 OutputUnit outputUnit) {
211 return _cspPrecompiledConstructorNames.putIfAbsent( 192 return _cspPrecompiledConstructorNames.putIfAbsent(
212 outputUnit, 193 outputUnit, () => new List<jsAst.Expression>());
213 () => new List<jsAst.Expression>());
214 } 194 }
215 195
216 /// Erases the precompiled information for csp mode for all output units. 196 /// Erases the precompiled information for csp mode for all output units.
217 /// Used by the incremental compiler. 197 /// Used by the incremental compiler.
218 void clearCspPrecompiledNodes() { 198 void clearCspPrecompiledNodes() {
219 _cspPrecompiledFunctions.clear(); 199 _cspPrecompiledFunctions.clear();
220 _cspPrecompiledConstructorNames.clear(); 200 _cspPrecompiledConstructorNames.clear();
221 } 201 }
222 202
223 @override 203 @override
224 String get patchVersion => "full"; 204 String get patchVersion => "full";
225 205
226 @override 206 @override
227 bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant) { 207 bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant) {
228 if (constant.isFunction) return true; // Already emitted. 208 if (constant.isFunction) return true; // Already emitted.
229 if (constant.isPrimitive) return true; // Inlined. 209 if (constant.isPrimitive) return true; // Inlined.
230 if (constant.isDummy) return true; // Inlined. 210 if (constant.isDummy) return true; // Inlined.
231 // The name is null when the constant is already a JS constant. 211 // The name is null when the constant is already a JS constant.
232 // TODO(floitsch): every constant should be registered, so that we can 212 // TODO(floitsch): every constant should be registered, so that we can
233 // share the ones that take up too much space (like some strings). 213 // share the ones that take up too much space (like some strings).
234 if (namer.constantName(constant) == null) return true; 214 if (namer.constantName(constant) == null) return true;
235 return false; 215 return false;
236 } 216 }
237 217
238 @override 218 @override
239 int compareConstants(ConstantValue a, ConstantValue b) { 219 int compareConstants(ConstantValue a, ConstantValue b) {
240 // Inlined constants don't affect the order and sometimes don't even have 220 // Inlined constants don't affect the order and sometimes don't even have
(...skipping 22 matching lines...) Expand all
263 if (value.isFunction) { 243 if (value.isFunction) {
264 FunctionConstantValue functionConstant = value; 244 FunctionConstantValue functionConstant = value;
265 return isolateStaticClosureAccess(functionConstant.element); 245 return isolateStaticClosureAccess(functionConstant.element);
266 } 246 }
267 247
268 // We are only interested in the "isInlined" part, but it does not hurt to 248 // We are only interested in the "isInlined" part, but it does not hurt to
269 // test for the other predicates. 249 // test for the other predicates.
270 if (isConstantInlinedOrAlreadyEmitted(value)) { 250 if (isConstantInlinedOrAlreadyEmitted(value)) {
271 return constantEmitter.generate(value); 251 return constantEmitter.generate(value);
272 } 252 }
273 return js('#.#', [namer.globalObjectForConstant(value), 253 return js('#.#',
274 namer.constantName(value)]); 254 [namer.globalObjectForConstant(value), namer.constantName(value)]);
275 } 255 }
276 256
277 jsAst.Expression constantInitializerExpression(ConstantValue value) { 257 jsAst.Expression constantInitializerExpression(ConstantValue value) {
278 return constantEmitter.generate(value); 258 return constantEmitter.generate(value);
279 } 259 }
280 260
281 String get name => 'CodeEmitter'; 261 String get name => 'CodeEmitter';
282 262
283 String get finishIsolateConstructorName 263 String get finishIsolateConstructorName =>
284 => '${namer.isolateName}.\$finishIsolateConstructor'; 264 '${namer.isolateName}.\$finishIsolateConstructor';
285 String get isolatePropertiesName 265 String get isolatePropertiesName =>
286 => '${namer.isolateName}.${namer.isolatePropertiesName}'; 266 '${namer.isolateName}.${namer.isolatePropertiesName}';
287 String get lazyInitializerProperty 267 String get lazyInitializerProperty => r'$lazy';
288 => r'$lazy'; 268 String get lazyInitializerName =>
289 String get lazyInitializerName 269 '${namer.isolateName}.${lazyInitializerProperty}';
290 => '${namer.isolateName}.${lazyInitializerProperty}';
291 String get initName => 'init'; 270 String get initName => 'init';
292 271
293 jsAst.Name get makeConstListProperty 272 jsAst.Name get makeConstListProperty =>
294 => namer.internalGlobal('makeConstantList'); 273 namer.internalGlobal('makeConstantList');
295 274
296 /// The name of the property that contains all field names. 275 /// The name of the property that contains all field names.
297 /// 276 ///
298 /// This property is added to constructors when isolate support is enabled. 277 /// This property is added to constructors when isolate support is enabled.
299 static const String FIELD_NAMES_PROPERTY_NAME = r"$__fields__"; 278 static const String FIELD_NAMES_PROPERTY_NAME = r"$__fields__";
300 279
301 /// For deferred loading we communicate the initializers via this global var. 280 /// For deferred loading we communicate the initializers via this global var.
302 final String deferredInitializers = r"$dart_deferred_initializers$"; 281 final String deferredInitializers = r"$dart_deferred_initializers$";
303 282
304 /// Contains the global state that is needed to initialize and load a 283 /// Contains the global state that is needed to initialize and load a
305 /// deferred library. 284 /// deferred library.
306 String get globalsHolder => r"$globals$"; 285 String get globalsHolder => r"$globals$";
307 286
308 @override 287 @override
309 bool get supportsReflection => true; 288 bool get supportsReflection => true;
310 289
311 @override 290 @override
312 jsAst.Expression generateEmbeddedGlobalAccess(String global) { 291 jsAst.Expression generateEmbeddedGlobalAccess(String global) {
313 return js(generateEmbeddedGlobalAccessString(global)); 292 return js(generateEmbeddedGlobalAccessString(global));
314 } 293 }
315 294
316 String generateEmbeddedGlobalAccessString(String global) { 295 String generateEmbeddedGlobalAccessString(String global) {
317 // TODO(floitsch): don't use 'init' as global embedder storage. 296 // TODO(floitsch): don't use 'init' as global embedder storage.
318 return '$initName.$global'; 297 return '$initName.$global';
319 } 298 }
320 299
321 jsAst.PropertyAccess globalPropertyAccess(Element element) { 300 jsAst.PropertyAccess globalPropertyAccess(Element element) {
322 jsAst.Name name = namer.globalPropertyName(element); 301 jsAst.Name name = namer.globalPropertyName(element);
323 jsAst.PropertyAccess pa = new jsAst.PropertyAccess( 302 jsAst.PropertyAccess pa = new jsAst.PropertyAccess(
324 new jsAst.VariableUse(namer.globalObjectFor(element)), 303 new jsAst.VariableUse(namer.globalObjectFor(element)), name);
325 name);
326 return pa; 304 return pa;
327 } 305 }
328 306
329 @override 307 @override
330 jsAst.Expression isolateLazyInitializerAccess(FieldElement element) { 308 jsAst.Expression isolateLazyInitializerAccess(FieldElement element) {
331 return jsAst.js('#.#', [namer.globalObjectFor(element), 309 return jsAst.js('#.#',
332 namer.lazyInitializerName(element)]); 310 [namer.globalObjectFor(element), namer.lazyInitializerName(element)]);
333 } 311 }
334 312
335 @override 313 @override
336 jsAst.Expression isolateStaticClosureAccess(FunctionElement element) { 314 jsAst.Expression isolateStaticClosureAccess(FunctionElement element) {
337 return jsAst.js('#.#()', 315 return jsAst.js('#.#()',
338 [namer.globalObjectFor(element), namer.staticClosureName(element)]); 316 [namer.globalObjectFor(element), namer.staticClosureName(element)]);
339 } 317 }
340 318
341 @override 319 @override
342 jsAst.PropertyAccess staticFieldAccess(FieldElement element) { 320 jsAst.PropertyAccess staticFieldAccess(FieldElement element) {
343 return globalPropertyAccess(element); 321 return globalPropertyAccess(element);
344 } 322 }
345 323
346 @override 324 @override
347 jsAst.PropertyAccess staticFunctionAccess(FunctionElement element) { 325 jsAst.PropertyAccess staticFunctionAccess(FunctionElement element) {
348 return globalPropertyAccess(element); 326 return globalPropertyAccess(element);
349 } 327 }
350 328
351 @override 329 @override
352 jsAst.PropertyAccess constructorAccess(ClassElement element) { 330 jsAst.PropertyAccess constructorAccess(ClassElement element) {
353 return globalPropertyAccess(element); 331 return globalPropertyAccess(element);
354 } 332 }
355 333
356 @override 334 @override
357 jsAst.PropertyAccess prototypeAccess(ClassElement element, 335 jsAst.PropertyAccess prototypeAccess(
358 bool hasBeenInstantiated) { 336 ClassElement element, bool hasBeenInstantiated) {
359 return jsAst.js('#.prototype', constructorAccess(element)); 337 return jsAst.js('#.prototype', constructorAccess(element));
360 } 338 }
361 339
362 @override 340 @override
363 jsAst.PropertyAccess interceptorClassAccess(ClassElement element) { 341 jsAst.PropertyAccess interceptorClassAccess(ClassElement element) {
364 return globalPropertyAccess(element); 342 return globalPropertyAccess(element);
365 } 343 }
366 344
367 @override 345 @override
368 jsAst.PropertyAccess typeAccess(Element element) { 346 jsAst.PropertyAccess typeAccess(Element element) {
369 return globalPropertyAccess(element); 347 return globalPropertyAccess(element);
370 } 348 }
371 349
372 @override 350 @override
373 jsAst.Template templateForBuiltin(JsBuiltin builtin) { 351 jsAst.Template templateForBuiltin(JsBuiltin builtin) {
374 switch (builtin) { 352 switch (builtin) {
375 case JsBuiltin.dartObjectConstructor: 353 case JsBuiltin.dartObjectConstructor:
376 return jsAst.js.expressionTemplateYielding( 354 return jsAst.js
377 typeAccess(coreClasses.objectClass)); 355 .expressionTemplateYielding(typeAccess(coreClasses.objectClass));
378 356
379 case JsBuiltin.isCheckPropertyToJsConstructorName: 357 case JsBuiltin.isCheckPropertyToJsConstructorName:
380 int isPrefixLength = namer.operatorIsPrefix.length; 358 int isPrefixLength = namer.operatorIsPrefix.length;
381 return jsAst.js.expressionTemplateFor('#.substring($isPrefixLength)'); 359 return jsAst.js.expressionTemplateFor('#.substring($isPrefixLength)');
382 360
383 case JsBuiltin.isFunctionType: 361 case JsBuiltin.isFunctionType:
384 return backend.rtiEncoder.templateForIsFunctionType; 362 return backend.rtiEncoder.templateForIsFunctionType;
385 363
386 case JsBuiltin.rawRtiToJsConstructorName: 364 case JsBuiltin.rawRtiToJsConstructorName:
387 return jsAst.js.expressionTemplateFor("#.$typeNameProperty"); 365 return jsAst.js.expressionTemplateFor("#.$typeNameProperty");
388 366
389 case JsBuiltin.rawRuntimeType: 367 case JsBuiltin.rawRuntimeType:
390 return jsAst.js.expressionTemplateFor("#.constructor"); 368 return jsAst.js.expressionTemplateFor("#.constructor");
391 369
392 case JsBuiltin.createFunctionTypeRti: 370 case JsBuiltin.createFunctionTypeRti:
393 return backend.rtiEncoder.templateForCreateFunctionType; 371 return backend.rtiEncoder.templateForCreateFunctionType;
394 372
395 case JsBuiltin.isSubtype: 373 case JsBuiltin.isSubtype:
396 // TODO(floitsch): move this closer to where is-check properties are 374 // TODO(floitsch): move this closer to where is-check properties are
397 // built. 375 // built.
398 String isPrefix = namer.operatorIsPrefix; 376 String isPrefix = namer.operatorIsPrefix;
399 return jsAst.js.expressionTemplateFor( 377 return jsAst.js
400 "('$isPrefix' + #) in #.prototype"); 378 .expressionTemplateFor("('$isPrefix' + #) in #.prototype");
401 379
402 case JsBuiltin.isGivenTypeRti: 380 case JsBuiltin.isGivenTypeRti:
403 return jsAst.js.expressionTemplateFor('#.$typeNameProperty === #'); 381 return jsAst.js.expressionTemplateFor('#.$typeNameProperty === #');
404 382
405 case JsBuiltin.getMetadata: 383 case JsBuiltin.getMetadata:
406 String metadataAccess = 384 String metadataAccess =
407 generateEmbeddedGlobalAccessString(embeddedNames.METADATA); 385 generateEmbeddedGlobalAccessString(embeddedNames.METADATA);
408 return jsAst.js.expressionTemplateFor("$metadataAccess[#]"); 386 return jsAst.js.expressionTemplateFor("$metadataAccess[#]");
409 387
410 case JsBuiltin.getType: 388 case JsBuiltin.getType:
411 String typesAccess = 389 String typesAccess =
412 generateEmbeddedGlobalAccessString(embeddedNames.TYPES); 390 generateEmbeddedGlobalAccessString(embeddedNames.TYPES);
413 return jsAst.js.expressionTemplateFor("$typesAccess[#]"); 391 return jsAst.js.expressionTemplateFor("$typesAccess[#]");
414 392
415 case JsBuiltin.createDartClosureFromNameOfStaticFunction: 393 case JsBuiltin.createDartClosureFromNameOfStaticFunction:
416 // The global-functions map contains a map from name to tear-off 394 // The global-functions map contains a map from name to tear-off
417 // getters. 395 // getters.
418 String functionGettersMap = 396 String functionGettersMap =
419 generateEmbeddedGlobalAccessString(embeddedNames.GLOBAL_FUNCTIONS); 397 generateEmbeddedGlobalAccessString(embeddedNames.GLOBAL_FUNCTIONS);
420 return jsAst.js.expressionTemplateFor("$functionGettersMap[#]()"); 398 return jsAst.js.expressionTemplateFor("$functionGettersMap[#]()");
421 399
422 default: 400 default:
423 reporter.internalError(NO_LOCATION_SPANNABLE, 401 reporter.internalError(
424 "Unhandled Builtin: $builtin"); 402 NO_LOCATION_SPANNABLE, "Unhandled Builtin: $builtin");
425 return null; 403 return null;
426 } 404 }
427 } 405 }
428 406
429 List<jsAst.Statement> buildTrivialNsmHandlers(){ 407 List<jsAst.Statement> buildTrivialNsmHandlers() {
430 return nsmEmitter.buildTrivialNsmHandlers(); 408 return nsmEmitter.buildTrivialNsmHandlers();
431 } 409 }
432 410
433 jsAst.Statement buildNativeInfoHandler( 411 jsAst.Statement buildNativeInfoHandler(
434 jsAst.Expression infoAccess, 412 jsAst.Expression infoAccess,
435 jsAst.Expression constructorAccess, 413 jsAst.Expression constructorAccess,
436 jsAst.Expression subclassReadGenerator(jsAst.Expression subclass), 414 jsAst.Expression subclassReadGenerator(jsAst.Expression subclass),
437 jsAst.Expression interceptorsByTagAccess, 415 jsAst.Expression interceptorsByTagAccess,
438 jsAst.Expression leafTagsAccess) { 416 jsAst.Expression leafTagsAccess) {
439 return NativeGenerator.buildNativeInfoHandler(infoAccess, constructorAccess, 417 return NativeGenerator.buildNativeInfoHandler(infoAccess, constructorAccess,
440 subclassReadGenerator, 418 subclassReadGenerator, interceptorsByTagAccess, leafTagsAccess);
441 interceptorsByTagAccess,
442 leafTagsAccess);
443 } 419 }
444 420
445 jsAst.ObjectInitializer generateInterceptedNamesSet() { 421 jsAst.ObjectInitializer generateInterceptedNamesSet() {
446 return interceptorEmitter.generateInterceptedNamesSet(); 422 return interceptorEmitter.generateInterceptedNamesSet();
447 } 423 }
448 424
449 /// In minified mode we want to keep the name for the most common core types. 425 /// In minified mode we want to keep the name for the most common core types.
450 bool _isNativeTypeNeedingReflectionName(Element element) { 426 bool _isNativeTypeNeedingReflectionName(Element element) {
451 if (!element.isClass) return false; 427 if (!element.isClass) return false;
452 return (element == coreClasses.intClass || 428 return (element == coreClasses.intClass ||
453 element == coreClasses.doubleClass || 429 element == coreClasses.doubleClass ||
454 element == coreClasses.numClass || 430 element == coreClasses.numClass ||
455 element == coreClasses.stringClass || 431 element == coreClasses.stringClass ||
456 element == coreClasses.boolClass || 432 element == coreClasses.boolClass ||
457 element == coreClasses.nullClass || 433 element == coreClasses.nullClass ||
458 element == coreClasses.listClass); 434 element == coreClasses.listClass);
459 } 435 }
460 436
461 /// Returns the "reflection name" of an [Element] or [Selector]. 437 /// Returns the "reflection name" of an [Element] or [Selector].
462 /// The reflection name of a getter 'foo' is 'foo'. 438 /// The reflection name of a getter 'foo' is 'foo'.
463 /// The reflection name of a setter 'foo' is 'foo='. 439 /// The reflection name of a setter 'foo' is 'foo='.
464 /// The reflection name of a method 'foo' is 'foo:N:M:O', where N is the 440 /// The reflection name of a method 'foo' is 'foo:N:M:O', where N is the
465 /// number of required arguments, M is the number of optional arguments, and 441 /// number of required arguments, M is the number of optional arguments, and
466 /// O is the named arguments. 442 /// O is the named arguments.
467 /// The reflection name of a constructor is similar to a regular method but 443 /// The reflection name of a constructor is similar to a regular method but
468 /// starts with 'new '. 444 /// starts with 'new '.
469 /// The reflection name of class 'C' is 'C'. 445 /// The reflection name of class 'C' is 'C'.
470 /// An anonymous mixin application has no reflection name. 446 /// An anonymous mixin application has no reflection name.
471 /// This is used by js_mirrors.dart. 447 /// This is used by js_mirrors.dart.
472 String getReflectionName(elementOrSelector, jsAst.Name mangledName) { 448 String getReflectionName(elementOrSelector, jsAst.Name mangledName) {
473 String name = elementOrSelector.name; 449 String name = elementOrSelector.name;
474 if (backend.shouldRetainName(name) || 450 if (backend.shouldRetainName(name) ||
475 elementOrSelector is Element && 451 elementOrSelector is Element &&
476 // Make sure to retain names of unnamed constructors, and 452 // Make sure to retain names of unnamed constructors, and
477 // for common native types. 453 // for common native types.
478 ((name == '' && 454 ((name == '' &&
479 backend.isAccessibleByReflection(elementOrSelector)) || 455 backend.isAccessibleByReflection(elementOrSelector)) ||
480 _isNativeTypeNeedingReflectionName(elementOrSelector))) { 456 _isNativeTypeNeedingReflectionName(elementOrSelector))) {
481
482 // TODO(ahe): Enable the next line when I can tell the difference between 457 // TODO(ahe): Enable the next line when I can tell the difference between
483 // an instance method and a global. They may have the same mangled name. 458 // an instance method and a global. They may have the same mangled name.
484 // if (recordedMangledNames.contains(mangledName)) return null; 459 // if (recordedMangledNames.contains(mangledName)) return null;
485 recordedMangledNames.add(mangledName); 460 recordedMangledNames.add(mangledName);
486 return getReflectionNameInternal(elementOrSelector, mangledName); 461 return getReflectionNameInternal(elementOrSelector, mangledName);
487 } 462 }
488 return null; 463 return null;
489 } 464 }
490 465
491 String getReflectionNameInternal(elementOrSelector, 466 String getReflectionNameInternal(elementOrSelector, jsAst.Name mangledName) {
492 jsAst.Name mangledName) {
493 String name = namer.privateName(elementOrSelector.memberName); 467 String name = namer.privateName(elementOrSelector.memberName);
494 if (elementOrSelector.isGetter) return name; 468 if (elementOrSelector.isGetter) return name;
495 if (elementOrSelector.isSetter) { 469 if (elementOrSelector.isSetter) {
496 if (mangledName is! SetterName) return '$name='; 470 if (mangledName is! SetterName) return '$name=';
497 SetterName setterName = mangledName; 471 SetterName setterName = mangledName;
498 jsAst.Name base = setterName.base; 472 jsAst.Name base = setterName.base;
499 jsAst.Name getter = namer.deriveGetterName(base); 473 jsAst.Name getter = namer.deriveGetterName(base);
500 mangledFieldNames.putIfAbsent(getter, () => name); 474 mangledFieldNames.putIfAbsent(getter, () => name);
501 assert(mangledFieldNames[getter] == name); 475 assert(mangledFieldNames[getter] == name);
502 recordedMangledNames.add(getter); 476 recordedMangledNames.add(getter);
503 // TODO(karlklose,ahe): we do not actually need to store information 477 // TODO(karlklose,ahe): we do not actually need to store information
504 // about the name of this setter in the output, but it is needed for 478 // about the name of this setter in the output, but it is needed for
505 // marking the function as invokable by reflection. 479 // marking the function as invokable by reflection.
506 return '$name='; 480 return '$name=';
507 } 481 }
508 if (elementOrSelector is Element && elementOrSelector.isClosure) { 482 if (elementOrSelector is Element && elementOrSelector.isClosure) {
509 // Closures are synthesized and their name might conflict with existing 483 // Closures are synthesized and their name might conflict with existing
510 // globals. Assign an illegal name, and make sure they don't clash 484 // globals. Assign an illegal name, and make sure they don't clash
511 // with each other. 485 // with each other.
512 return " $name"; 486 return " $name";
513 } 487 }
514 if (elementOrSelector is Selector 488 if (elementOrSelector is Selector ||
515 || elementOrSelector.isFunction 489 elementOrSelector.isFunction ||
516 || elementOrSelector.isConstructor) { 490 elementOrSelector.isConstructor) {
517 int positionalParameterCount; 491 int positionalParameterCount;
518 String namedArguments = ''; 492 String namedArguments = '';
519 bool isConstructor = false; 493 bool isConstructor = false;
520 if (elementOrSelector is Selector) { 494 if (elementOrSelector is Selector) {
521 CallStructure callStructure = elementOrSelector.callStructure; 495 CallStructure callStructure = elementOrSelector.callStructure;
522 positionalParameterCount = callStructure.positionalArgumentCount; 496 positionalParameterCount = callStructure.positionalArgumentCount;
523 namedArguments = namedParametersAsReflectionNames(callStructure); 497 namedArguments = namedParametersAsReflectionNames(callStructure);
524 } else { 498 } else {
525 FunctionElement function = elementOrSelector; 499 FunctionElement function = elementOrSelector;
526 if (function.isConstructor) { 500 if (function.isConstructor) {
(...skipping 25 matching lines...) Expand all
552 Element element = elementOrSelector; 526 Element element = elementOrSelector;
553 if (element.isGenerativeConstructorBody) { 527 if (element.isGenerativeConstructorBody) {
554 return null; 528 return null;
555 } else if (element.isClass) { 529 } else if (element.isClass) {
556 ClassElement cls = element; 530 ClassElement cls = element;
557 if (cls.isUnnamedMixinApplication) return null; 531 if (cls.isUnnamedMixinApplication) return null;
558 return cls.name; 532 return cls.name;
559 } else if (element.isTypedef) { 533 } else if (element.isTypedef) {
560 return element.name; 534 return element.name;
561 } 535 }
562 throw reporter.internalError(element, 536 throw reporter.internalError(
563 'Do not know how to reflect on this $element.'); 537 element, 'Do not know how to reflect on this $element.');
564 } 538 }
565 539
566 String namedParametersAsReflectionNames(CallStructure structure) { 540 String namedParametersAsReflectionNames(CallStructure structure) {
567 if (structure.isUnnamed) return ''; 541 if (structure.isUnnamed) return '';
568 String names = structure.getOrderedNamedArguments().join(':'); 542 String names = structure.getOrderedNamedArguments().join(':');
569 return ':$names'; 543 return ':$names';
570 } 544 }
571 545
572 jsAst.Statement buildCspPrecompiledFunctionFor( 546 jsAst.Statement buildCspPrecompiledFunctionFor(OutputUnit outputUnit) {
573 OutputUnit outputUnit) {
574 if (compiler.options.useContentSecurityPolicy) { 547 if (compiler.options.useContentSecurityPolicy) {
575 // TODO(ahe): Compute a hash code. 548 // TODO(ahe): Compute a hash code.
576 // TODO(sigurdm): Avoid this precompiled function. Generated 549 // TODO(sigurdm): Avoid this precompiled function. Generated
577 // constructor-functions and getter/setter functions can be stored in the 550 // constructor-functions and getter/setter functions can be stored in the
578 // library-description table. Setting properties on these can be moved to 551 // library-description table. Setting properties on these can be moved to
579 // finishClasses. 552 // finishClasses.
580 return js.statement(r""" 553 return js.statement(
554 r"""
581 #precompiled = function ($collectedClasses$) { 555 #precompiled = function ($collectedClasses$) {
582 #norename; 556 #norename;
583 var $desc; 557 var $desc;
584 #functions; 558 #functions;
585 return #result; 559 return #result;
586 };""", 560 };""",
587 {'norename': new jsAst.Comment("// ::norenaming:: "), 561 {
588 'precompiled': generateEmbeddedGlobalAccess(embeddedNames.PRECOMPILED), 562 'norename': new jsAst.Comment("// ::norenaming:: "),
589 'functions': cspPrecompiledFunctionFor(outputUnit), 563 'precompiled':
590 'result': new jsAst.ArrayInitializer( 564 generateEmbeddedGlobalAccess(embeddedNames.PRECOMPILED),
591 cspPrecompiledConstructorNamesFor(outputUnit))}); 565 'functions': cspPrecompiledFunctionFor(outputUnit),
566 'result': new jsAst.ArrayInitializer(
567 cspPrecompiledConstructorNamesFor(outputUnit))
568 });
592 } else { 569 } else {
593 return js.comment("Constructors are generated at runtime."); 570 return js.comment("Constructors are generated at runtime.");
594 } 571 }
595 } 572 }
596 573
597 void assembleClass(Class cls, ClassBuilder enclosingBuilder, 574 void assembleClass(
598 Fragment fragment) { 575 Class cls, ClassBuilder enclosingBuilder, Fragment fragment) {
599 ClassElement classElement = cls.element; 576 ClassElement classElement = cls.element;
600 reporter.withCurrentElement(classElement, () { 577 reporter.withCurrentElement(classElement, () {
601 if (compiler.options.hasIncrementalSupport) { 578 if (compiler.options.hasIncrementalSupport) {
602 ClassBuilder cachedBuilder = 579 ClassBuilder cachedBuilder =
603 cachedClassBuilders.putIfAbsent(classElement, () { 580 cachedClassBuilders.putIfAbsent(classElement, () {
604 ClassBuilder builder = 581 ClassBuilder builder = new ClassBuilder.forClass(classElement, namer);
605 new ClassBuilder.forClass(classElement, namer); 582 classEmitter.emitClass(cls, builder, fragment);
606 classEmitter.emitClass(cls, builder, fragment); 583 return builder;
607 return builder; 584 });
608 });
609 invariant(classElement, cachedBuilder.fields.isEmpty); 585 invariant(classElement, cachedBuilder.fields.isEmpty);
610 invariant(classElement, cachedBuilder.superName == null); 586 invariant(classElement, cachedBuilder.superName == null);
611 invariant(classElement, cachedBuilder.functionType == null); 587 invariant(classElement, cachedBuilder.functionType == null);
612 invariant(classElement, cachedBuilder.fieldMetadata == null); 588 invariant(classElement, cachedBuilder.fieldMetadata == null);
613 enclosingBuilder.properties.addAll(cachedBuilder.properties); 589 enclosingBuilder.properties.addAll(cachedBuilder.properties);
614 } else { 590 } else {
615 classEmitter.emitClass(cls, enclosingBuilder, fragment); 591 classEmitter.emitClass(cls, enclosingBuilder, fragment);
616 } 592 }
617 }); 593 });
618 } 594 }
619 595
620 void assembleStaticFunctions(Iterable<Method> staticFunctions, 596 void assembleStaticFunctions(
621 Fragment fragment) { 597 Iterable<Method> staticFunctions, Fragment fragment) {
622 if (staticFunctions == null) return; 598 if (staticFunctions == null) return;
623 599
624 for (Method method in staticFunctions) { 600 for (Method method in staticFunctions) {
625 Element element = method.element; 601 Element element = method.element;
626 // We need to filter out null-elements for the interceptors. 602 // We need to filter out null-elements for the interceptors.
627 // TODO(floitsch): use the precomputed interceptors here. 603 // TODO(floitsch): use the precomputed interceptors here.
628 if (element == null) continue; 604 if (element == null) continue;
629 ClassBuilder builder = new ClassBuilder.forStatics(element, namer); 605 ClassBuilder builder = new ClassBuilder.forStatics(element, namer);
630 containerBuilder.addMemberMethod(method, builder); 606 containerBuilder.addMemberMethod(method, builder);
631 getElementDescriptor(element, fragment).properties 607 getElementDescriptor(element, fragment)
608 .properties
632 .addAll(builder.properties); 609 .addAll(builder.properties);
633 } 610 }
634 } 611 }
635 612
636 jsAst.Statement buildStaticNonFinalFieldInitializations( 613 jsAst.Statement buildStaticNonFinalFieldInitializations(
637 OutputUnit outputUnit) { 614 OutputUnit outputUnit) {
638 jsAst.Statement buildInitialization(Element element, 615 jsAst.Statement buildInitialization(
639 jsAst.Expression initialValue) { 616 Element element, jsAst.Expression initialValue) {
640 return js.statement('${namer.staticStateHolder}.# = #', 617 return js.statement('${namer.staticStateHolder}.# = #',
641 [namer.globalPropertyName(element), initialValue]); 618 [namer.globalPropertyName(element), initialValue]);
642 } 619 }
643 620
644 bool inMainUnit = (outputUnit == compiler.deferredLoadTask.mainOutputUnit); 621 bool inMainUnit = (outputUnit == compiler.deferredLoadTask.mainOutputUnit);
645 JavaScriptConstantCompiler handler = backend.constants; 622 JavaScriptConstantCompiler handler = backend.constants;
646 List<jsAst.Statement> parts = <jsAst.Statement>[]; 623 List<jsAst.Statement> parts = <jsAst.Statement>[];
647 624
648 Iterable<Element> fields = outputStaticNonFinalFieldLists[outputUnit]; 625 Iterable<Element> fields = outputStaticNonFinalFieldLists[outputUnit];
649 // If the outputUnit does not contain any static non-final fields, then 626 // If the outputUnit does not contain any static non-final fields, then
650 // [fields] is `null`. 627 // [fields] is `null`.
651 if (fields != null) { 628 if (fields != null) {
652 for (Element element in fields) { 629 for (Element element in fields) {
653 reporter.withCurrentElement(element, () { 630 reporter.withCurrentElement(element, () {
654 ConstantValue constant = handler.getInitialValueFor(element); 631 ConstantValue constant = handler.getInitialValueFor(element);
655 parts.add(buildInitialization(element, constantReference(constant))); 632 parts.add(buildInitialization(element, constantReference(constant)));
656 }); 633 });
657 } 634 }
658 } 635 }
659 636
660 if (inMainUnit && outputStaticNonFinalFieldLists.length > 1) { 637 if (inMainUnit && outputStaticNonFinalFieldLists.length > 1) {
661 // In the main output-unit we output a stub initializer for deferred 638 // In the main output-unit we output a stub initializer for deferred
662 // variables, so that `isolateProperties` stays a fast object. 639 // variables, so that `isolateProperties` stays a fast object.
663 outputStaticNonFinalFieldLists.forEach( 640 outputStaticNonFinalFieldLists.forEach(
664 (OutputUnit fieldsOutputUnit, Iterable<VariableElement> fields) { 641 (OutputUnit fieldsOutputUnit, Iterable<VariableElement> fields) {
665 if (fieldsOutputUnit == outputUnit) return; // Skip the main unit. 642 if (fieldsOutputUnit == outputUnit) return; // Skip the main unit.
666 for (Element element in fields) { 643 for (Element element in fields) {
667 reporter.withCurrentElement(element, () { 644 reporter.withCurrentElement(element, () {
668 parts.add(buildInitialization(element, jsAst.number(0))); 645 parts.add(buildInitialization(element, jsAst.number(0)));
669 }); 646 });
670 } 647 }
671 }); 648 });
672 } 649 }
673 650
674 return new jsAst.Block(parts); 651 return new jsAst.Block(parts);
675 } 652 }
676 653
677 jsAst.Statement buildLazilyInitializedStaticFields( 654 jsAst.Statement buildLazilyInitializedStaticFields(
678 Iterable<StaticField> lazyFields, {bool isMainFragment: true}) { 655 Iterable<StaticField> lazyFields,
656 {bool isMainFragment: true}) {
679 if (lazyFields.isNotEmpty) { 657 if (lazyFields.isNotEmpty) {
680 needsLazyInitializer = true; 658 needsLazyInitializer = true;
681 List<jsAst.Expression> laziesInfo = 659 List<jsAst.Expression> laziesInfo =
682 buildLaziesInfo(lazyFields, isMainFragment); 660 buildLaziesInfo(lazyFields, isMainFragment);
683 return js.statement(''' 661 return js.statement(
662 '''
684 (function(lazies) { 663 (function(lazies) {
685 for (var i = 0; i < lazies.length; ) { 664 for (var i = 0; i < lazies.length; ) {
686 var fieldName = lazies[i++]; 665 var fieldName = lazies[i++];
687 var getterName = lazies[i++]; 666 var getterName = lazies[i++];
688 var lazyValue = lazies[i++]; 667 var lazyValue = lazies[i++];
689 if (#notMinified) { 668 if (#notMinified) {
690 var staticName = lazies[i++]; 669 var staticName = lazies[i++];
691 } 670 }
692 if (#isDeferredFragment) { 671 if (#isDeferredFragment) {
693 var fieldHolder = lazies[i++]; 672 var fieldHolder = lazies[i++];
(...skipping 10 matching lines...) Expand all
704 } 683 }
705 } else { 684 } else {
706 if (#notMinified) { 685 if (#notMinified) {
707 #lazy(fieldName, getterName, lazyValue, staticName, fieldHolder); 686 #lazy(fieldName, getterName, lazyValue, staticName, fieldHolder);
708 } else { 687 } else {
709 #lazy(fieldName, getterName, lazyValue, null, fieldHolder); 688 #lazy(fieldName, getterName, lazyValue, null, fieldHolder);
710 } 689 }
711 } 690 }
712 } 691 }
713 })(#laziesInfo) 692 })(#laziesInfo)
714 ''', {'notMinified': !compiler.options.enableMinification, 693 ''',
694 {
695 'notMinified': !compiler.options.enableMinification,
715 'laziesInfo': new jsAst.ArrayInitializer(laziesInfo), 696 'laziesInfo': new jsAst.ArrayInitializer(laziesInfo),
716 'lazy': js(lazyInitializerName), 697 'lazy': js(lazyInitializerName),
717 'isMainFragment': isMainFragment, 698 'isMainFragment': isMainFragment,
718 'isDeferredFragment': !isMainFragment}); 699 'isDeferredFragment': !isMainFragment
700 });
719 } else { 701 } else {
720 return js.comment("No lazy statics."); 702 return js.comment("No lazy statics.");
721 } 703 }
722 } 704 }
723 705
724 List<jsAst.Expression> buildLaziesInfo( 706 List<jsAst.Expression> buildLaziesInfo(
725 Iterable<StaticField> lazies, bool isMainFragment) { 707 Iterable<StaticField> lazies, bool isMainFragment) {
726 List<jsAst.Expression> laziesInfo = <jsAst.Expression>[]; 708 List<jsAst.Expression> laziesInfo = <jsAst.Expression>[];
727 for (StaticField field in lazies) { 709 for (StaticField field in lazies) {
728 laziesInfo.add(js.quoteName(field.name)); 710 laziesInfo.add(js.quoteName(field.name));
729 laziesInfo.add(js.quoteName(namer.deriveLazyInitializerName(field.name))); 711 laziesInfo.add(js.quoteName(namer.deriveLazyInitializerName(field.name)));
730 laziesInfo.add(field.code); 712 laziesInfo.add(field.code);
731 if (!compiler.options.enableMinification) { 713 if (!compiler.options.enableMinification) {
732 laziesInfo.add(js.quoteName(field.name)); 714 laziesInfo.add(js.quoteName(field.name));
733 } 715 }
734 if (!isMainFragment) { 716 if (!isMainFragment) {
735 laziesInfo.add(js('#', field.holder.name)); 717 laziesInfo.add(js('#', field.holder.name));
736 } 718 }
737 } 719 }
738 return laziesInfo; 720 return laziesInfo;
739 } 721 }
740 722
741 // TODO(sra): Remove this unused function. 723 // TODO(sra): Remove this unused function.
742 jsAst.Expression buildLazilyInitializedStaticField( 724 jsAst.Expression buildLazilyInitializedStaticField(VariableElement element,
743 VariableElement element, {String isolateProperties}) { 725 {String isolateProperties}) {
744 jsAst.Expression code = backend.generatedCode[element]; 726 jsAst.Expression code = backend.generatedCode[element];
745 // The code is null if we ended up not needing the lazily 727 // The code is null if we ended up not needing the lazily
746 // initialized field after all because of constant folding 728 // initialized field after all because of constant folding
747 // before code generation. 729 // before code generation.
748 if (code == null) return null; 730 if (code == null) return null;
749 // The code only computes the initial value. We build the lazy-check 731 // The code only computes the initial value. We build the lazy-check
750 // here: 732 // here:
751 // lazyInitializer(fieldName, getterName, initial, name, prototype); 733 // lazyInitializer(fieldName, getterName, initial, name, prototype);
752 // The name is used for error reporting. The 'initial' must be a 734 // The name is used for error reporting. The 'initial' must be a
753 // closure that constructs the initial value. 735 // closure that constructs the initial value.
754 if (isolateProperties != null) { 736 if (isolateProperties != null) {
755 // This is currently only used in incremental compilation to patch 737 // This is currently only used in incremental compilation to patch
756 // in new lazy values. 738 // in new lazy values.
757 return js('#(#,#,#,#,#)', 739 return js('#(#,#,#,#,#)', [
758 [js(lazyInitializerName), 740 js(lazyInitializerName),
759 js.quoteName(namer.globalPropertyName(element)), 741 js.quoteName(namer.globalPropertyName(element)),
760 js.quoteName(namer.lazyInitializerName(element)), 742 js.quoteName(namer.lazyInitializerName(element)),
761 code, 743 code,
762 js.string(element.name), 744 js.string(element.name),
763 isolateProperties]); 745 isolateProperties
746 ]);
764 } 747 }
765 748
766 if (compiler.options.enableMinification) { 749 if (compiler.options.enableMinification) {
767 return js('#(#,#,#)', 750 return js('#(#,#,#)', [
768 [js(lazyInitializerName), 751 js(lazyInitializerName),
769 js.quoteName(namer.globalPropertyName(element)), 752 js.quoteName(namer.globalPropertyName(element)),
770 js.quoteName(namer.lazyInitializerName(element)), 753 js.quoteName(namer.lazyInitializerName(element)),
771 code]); 754 code
755 ]);
772 } else { 756 } else {
773 return js('#(#,#,#,#)', 757 return js('#(#,#,#,#)', [
774 [js(lazyInitializerName), 758 js(lazyInitializerName),
775 js.quoteName(namer.globalPropertyName(element)), 759 js.quoteName(namer.globalPropertyName(element)),
776 js.quoteName(namer.lazyInitializerName(element)), 760 js.quoteName(namer.lazyInitializerName(element)),
777 code, 761 code,
778 js.string(element.name)]); 762 js.string(element.name)
763 ]);
779 } 764 }
780 } 765 }
781 766
782 jsAst.Statement buildMetadata(Program program, OutputUnit outputUnit) { 767 jsAst.Statement buildMetadata(Program program, OutputUnit outputUnit) {
783 List<jsAst.Statement> parts = <jsAst.Statement>[]; 768 List<jsAst.Statement> parts = <jsAst.Statement>[];
784 769
785 jsAst.Expression types = program.metadataTypesForOutputUnit(outputUnit); 770 jsAst.Expression types = program.metadataTypesForOutputUnit(outputUnit);
786 771
787 if (outputUnit == compiler.deferredLoadTask.mainOutputUnit) { 772 if (outputUnit == compiler.deferredLoadTask.mainOutputUnit) {
788 jsAst.Expression metadataAccess = 773 jsAst.Expression metadataAccess =
789 generateEmbeddedGlobalAccess(embeddedNames.METADATA); 774 generateEmbeddedGlobalAccess(embeddedNames.METADATA);
790 jsAst.Expression typesAccess = 775 jsAst.Expression typesAccess =
791 generateEmbeddedGlobalAccess(embeddedNames.TYPES); 776 generateEmbeddedGlobalAccess(embeddedNames.TYPES);
792 777
793 parts..add(js.statement('# = #;', [metadataAccess, program.metadata])) 778 parts
794 ..add(js.statement('# = #;', [typesAccess, types])); 779 ..add(js.statement('# = #;', [metadataAccess, program.metadata]))
780 ..add(js.statement('# = #;', [typesAccess, types]));
795 } else if (types != null) { 781 } else if (types != null) {
796 parts.add(js.statement('var ${namer.deferredTypesName} = #;', 782 parts.add(js.statement('var ${namer.deferredTypesName} = #;', types));
797 types));
798 } 783 }
799 return new jsAst.Block(parts); 784 return new jsAst.Block(parts);
800 } 785 }
801 786
802 jsAst.Statement buildCompileTimeConstants(List<Constant> constants, 787 jsAst.Statement buildCompileTimeConstants(List<Constant> constants,
803 {bool isMainFragment}) { 788 {bool isMainFragment}) {
804 assert(isMainFragment != null); 789 assert(isMainFragment != null);
805 790
806 if (constants.isEmpty) return js.comment("No constants in program."); 791 if (constants.isEmpty) return js.comment("No constants in program.");
807 List<jsAst.Statement> parts = <jsAst.Statement>[]; 792 List<jsAst.Statement> parts = <jsAst.Statement>[];
808 if (compiler.options.hasIncrementalSupport && isMainFragment) { 793 if (compiler.options.hasIncrementalSupport && isMainFragment) {
809 parts = cachedEmittedConstantsAst; 794 parts = cachedEmittedConstantsAst;
810 } 795 }
811 for (Constant constant in constants) { 796 for (Constant constant in constants) {
812 ConstantValue constantValue = constant.value; 797 ConstantValue constantValue = constant.value;
813 if (compiler.options.hasIncrementalSupport && isMainFragment) { 798 if (compiler.options.hasIncrementalSupport && isMainFragment) {
814 if (cachedEmittedConstants.contains(constantValue)) continue; 799 if (cachedEmittedConstants.contains(constantValue)) continue;
815 cachedEmittedConstants.add(constantValue); 800 cachedEmittedConstants.add(constantValue);
816 } 801 }
817 parts.add(buildConstantInitializer(constantValue)); 802 parts.add(buildConstantInitializer(constantValue));
818 } 803 }
819 804
820 return new jsAst.Block(parts); 805 return new jsAst.Block(parts);
821 } 806 }
822 807
823 jsAst.Statement buildConstantInitializer(ConstantValue constant) { 808 jsAst.Statement buildConstantInitializer(ConstantValue constant) {
824 jsAst.Name name = namer.constantName(constant); 809 jsAst.Name name = namer.constantName(constant);
825 jsAst.Statement initializer = js.statement('#.# = #', 810 jsAst.Statement initializer = js.statement('#.# = #', [
826 [namer.globalObjectForConstant(constant), name, 811 namer.globalObjectForConstant(constant),
827 constantInitializerExpression(constant)]); 812 name,
813 constantInitializerExpression(constant)
814 ]);
828 compiler.dumpInfoTask.registerConstantAst(constant, initializer); 815 compiler.dumpInfoTask.registerConstantAst(constant, initializer);
829 return initializer; 816 return initializer;
830 } 817 }
831 818
832 jsAst.Expression constantListGenerator(jsAst.Expression array) { 819 jsAst.Expression constantListGenerator(jsAst.Expression array) {
833 // TODO(floitsch): there is no harm in caching the template. 820 // TODO(floitsch): there is no harm in caching the template.
834 return js('${namer.isolateName}.#(#)', [makeConstListProperty, array]); 821 return js('${namer.isolateName}.#(#)', [makeConstListProperty, array]);
835 } 822 }
836 823
837 jsAst.Statement buildMakeConstantList(bool outputContainsConstantList) { 824 jsAst.Statement buildMakeConstantList(bool outputContainsConstantList) {
838 if (outputContainsConstantList) { 825 if (outputContainsConstantList) {
839 return js.statement(r''' 826 return js.statement(
827 r'''
840 // Functions are stored in the hidden class and not as properties in 828 // Functions are stored in the hidden class and not as properties in
841 // the object. We never actually look at the value, but only want 829 // the object. We never actually look at the value, but only want
842 // to know if the property exists. 830 // to know if the property exists.
843 #.# = function (list) { 831 #.# = function (list) {
844 list.immutable$list = Array; 832 list.immutable$list = Array;
845 list.fixed$length = Array; 833 list.fixed$length = Array;
846 return list; 834 return list;
847 }''', 835 }''',
848 [namer.isolateName, makeConstListProperty]); 836 [namer.isolateName, makeConstListProperty]);
849 } else { 837 } else {
850 return js.comment("Output contains no constant list."); 838 return js.comment("Output contains no constant list.");
851 } 839 }
852 } 840 }
853 841
854 jsAst.Statement buildFunctionThatReturnsNull() { 842 jsAst.Statement buildFunctionThatReturnsNull() {
855 return js.statement('#.# = function() {}', 843 return js.statement('#.# = function() {}',
856 [namer.isolateName, 844 [namer.isolateName, backend.rtiEncoder.getFunctionThatReturnsNullName]);
857 backend.rtiEncoder.getFunctionThatReturnsNullName]);
858 } 845 }
859 846
860 jsAst.Expression generateFunctionThatReturnsNull() { 847 jsAst.Expression generateFunctionThatReturnsNull() {
861 return js("#.#", [namer.isolateName, 848 return js("#.#",
862 backend.rtiEncoder.getFunctionThatReturnsNullName]); 849 [namer.isolateName, backend.rtiEncoder.getFunctionThatReturnsNullName]);
863 } 850 }
864 851
865 buildMain(jsAst.Statement invokeMain) { 852 buildMain(jsAst.Statement invokeMain) {
866 if (compiler.isMockCompilation) return js.comment("Mock compilation"); 853 if (compiler.isMockCompilation) return js.comment("Mock compilation");
867 854
868 List<jsAst.Statement> parts = <jsAst.Statement>[]; 855 List<jsAst.Statement> parts = <jsAst.Statement>[];
869 856
870 if (NativeGenerator.needsIsolateAffinityTagInitialization(backend)) { 857 if (NativeGenerator.needsIsolateAffinityTagInitialization(backend)) {
871 parts.add( 858 parts.add(NativeGenerator.generateIsolateAffinityTagInitialization(
872 NativeGenerator.generateIsolateAffinityTagInitialization( 859 backend,
873 backend, 860 generateEmbeddedGlobalAccess,
874 generateEmbeddedGlobalAccess, 861 js(
875 js(""" 862 """
876 // On V8, the 'intern' function converts a string to a symbol, which 863 // On V8, the 'intern' function converts a string to a symbol, which
877 // makes property access much faster. 864 // makes property access much faster.
878 function (s) { 865 function (s) {
879 var o = {}; 866 var o = {};
880 o[s] = 1; 867 o[s] = 1;
881 return Object.keys(convertToFastObject(o))[0]; 868 return Object.keys(convertToFastObject(o))[0];
882 }""", []))); 869 }""",
870 [])));
883 } 871 }
884 872
885 parts..add(js.comment('BEGIN invoke [main].')) 873 parts
886 ..add(invokeMain) 874 ..add(js.comment('BEGIN invoke [main].'))
887 ..add(js.comment('END invoke [main].')); 875 ..add(invokeMain)
876 ..add(js.comment('END invoke [main].'));
888 877
889 return new jsAst.Block(parts); 878 return new jsAst.Block(parts);
890 } 879 }
891 880
892 jsAst.Statement buildInitFunction(bool outputContainsConstantList) { 881 jsAst.Statement buildInitFunction(bool outputContainsConstantList) {
893 jsAst.Expression allClassesAccess = 882 jsAst.Expression allClassesAccess =
894 generateEmbeddedGlobalAccess(embeddedNames.ALL_CLASSES); 883 generateEmbeddedGlobalAccess(embeddedNames.ALL_CLASSES);
895 jsAst.Expression getTypeFromNameAccess = 884 jsAst.Expression getTypeFromNameAccess =
896 generateEmbeddedGlobalAccess(embeddedNames.GET_TYPE_FROM_NAME); 885 generateEmbeddedGlobalAccess(embeddedNames.GET_TYPE_FROM_NAME);
897 jsAst.Expression interceptorsByTagAccess = 886 jsAst.Expression interceptorsByTagAccess =
898 generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTORS_BY_TAG); 887 generateEmbeddedGlobalAccess(embeddedNames.INTERCEPTORS_BY_TAG);
899 jsAst.Expression leafTagsAccess = 888 jsAst.Expression leafTagsAccess =
900 generateEmbeddedGlobalAccess(embeddedNames.LEAF_TAGS); 889 generateEmbeddedGlobalAccess(embeddedNames.LEAF_TAGS);
901 jsAst.Expression finishedClassesAccess = 890 jsAst.Expression finishedClassesAccess =
902 generateEmbeddedGlobalAccess(embeddedNames.FINISHED_CLASSES); 891 generateEmbeddedGlobalAccess(embeddedNames.FINISHED_CLASSES);
903 jsAst.Expression cyclicThrow = 892 jsAst.Expression cyclicThrow =
904 staticFunctionAccess(backend.helpers.cyclicThrowHelper); 893 staticFunctionAccess(backend.helpers.cyclicThrowHelper);
905 jsAst.Expression laziesAccess = 894 jsAst.Expression laziesAccess =
906 generateEmbeddedGlobalAccess(embeddedNames.LAZIES); 895 generateEmbeddedGlobalAccess(embeddedNames.LAZIES);
907 896
908 return js.statement(''' 897 return js.statement(
898 '''
909 function init() { 899 function init() {
910 $isolatePropertiesName = Object.create(null); 900 $isolatePropertiesName = Object.create(null);
911 #allClasses = map(); 901 #allClasses = map();
912 #getTypeFromName = function(name) {return #allClasses[name];}; 902 #getTypeFromName = function(name) {return #allClasses[name];};
913 #interceptorsByTag = map(); 903 #interceptorsByTag = map();
914 #leafTags = map(); 904 #leafTags = map();
915 #finishedClasses = map(); 905 #finishedClasses = map();
916 906
917 if (#needsLazyInitializer) { 907 if (#needsLazyInitializer) {
918 // [staticName] is only provided in non-minified mode. If missing, we 908 // [staticName] is only provided in non-minified mode. If missing, we
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
1008 } 998 }
1009 Isolate.#functionThatReturnsNullProperty = 999 Isolate.#functionThatReturnsNullProperty =
1010 oldIsolate.#functionThatReturnsNullProperty; 1000 oldIsolate.#functionThatReturnsNullProperty;
1011 if (#hasIncrementalSupport) { 1001 if (#hasIncrementalSupport) {
1012 Isolate.#lazyInitializerProperty = 1002 Isolate.#lazyInitializerProperty =
1013 oldIsolate.#lazyInitializerProperty; 1003 oldIsolate.#lazyInitializerProperty;
1014 } 1004 }
1015 return Isolate; 1005 return Isolate;
1016 } 1006 }
1017 1007
1018 }''', {'allClasses': allClassesAccess, 1008 }''',
1019 'getTypeFromName': getTypeFromNameAccess, 1009 {
1020 'interceptorsByTag': interceptorsByTagAccess, 1010 'allClasses': allClassesAccess,
1021 'leafTags': leafTagsAccess, 1011 'getTypeFromName': getTypeFromNameAccess,
1022 'finishedClasses': finishedClassesAccess, 1012 'interceptorsByTag': interceptorsByTagAccess,
1023 'needsLazyInitializer': needsLazyInitializer, 1013 'leafTags': leafTagsAccess,
1024 'lazies': laziesAccess, 'cyclicThrow': cyclicThrow, 1014 'finishedClasses': finishedClassesAccess,
1025 'isolatePropertiesName': namer.isolatePropertiesName, 1015 'needsLazyInitializer': needsLazyInitializer,
1026 'outputContainsConstantList': outputContainsConstantList, 1016 'lazies': laziesAccess,
1027 'makeConstListProperty': makeConstListProperty, 1017 'cyclicThrow': cyclicThrow,
1028 'functionThatReturnsNullProperty': 1018 'isolatePropertiesName': namer.isolatePropertiesName,
1029 backend.rtiEncoder.getFunctionThatReturnsNullName, 1019 'outputContainsConstantList': outputContainsConstantList,
1030 'hasIncrementalSupport': compiler.options.hasIncrementalSupport, 1020 'makeConstListProperty': makeConstListProperty,
1031 'lazyInitializerProperty': lazyInitializerProperty,}); 1021 'functionThatReturnsNullProperty':
1022 backend.rtiEncoder.getFunctionThatReturnsNullName,
1023 'hasIncrementalSupport': compiler.options.hasIncrementalSupport,
1024 'lazyInitializerProperty': lazyInitializerProperty,
1025 });
1032 } 1026 }
1033 1027
1034 jsAst.Statement buildConvertToFastObjectFunction() { 1028 jsAst.Statement buildConvertToFastObjectFunction() {
1035 List<jsAst.Statement> debugCode = <jsAst.Statement>[]; 1029 List<jsAst.Statement> debugCode = <jsAst.Statement>[];
1036 if (DEBUG_FAST_OBJECTS) { 1030 if (DEBUG_FAST_OBJECTS) {
1037 debugCode.add(js.statement(r''' 1031 debugCode.add(js.statement(r'''
1038 // The following only works on V8 when run with option 1032 // The following only works on V8 when run with option
1039 // "--allow-natives-syntax". We use'new Function' because the 1033 // "--allow-natives-syntax". We use'new Function' because the
1040 // miniparser does not understand V8 native syntax. 1034 // miniparser does not understand V8 native syntax.
1041 if (typeof print === "function") { 1035 if (typeof print === "function") {
1042 var HasFastProperties = 1036 var HasFastProperties =
1043 new Function("a", "return %HasFastProperties(a)"); 1037 new Function("a", "return %HasFastProperties(a)");
1044 print("Size of global object: " 1038 print("Size of global object: "
1045 + String(Object.getOwnPropertyNames(properties).length) 1039 + String(Object.getOwnPropertyNames(properties).length)
1046 + ", fast properties " + HasFastProperties(properties)); 1040 + ", fast properties " + HasFastProperties(properties));
1047 }''')); 1041 }'''));
1048 } 1042 }
1049 1043
1050 return js.statement(r''' 1044 return js.statement(
1045 r'''
1051 function convertToFastObject(properties) { 1046 function convertToFastObject(properties) {
1052 // Create an instance that uses 'properties' as prototype. This should 1047 // Create an instance that uses 'properties' as prototype. This should
1053 // make 'properties' a fast object. 1048 // make 'properties' a fast object.
1054 function MyClass() {}; 1049 function MyClass() {};
1055 MyClass.prototype = properties; 1050 MyClass.prototype = properties;
1056 new MyClass(); 1051 new MyClass();
1057 #; 1052 #;
1058 return properties; 1053 return properties;
1059 }''', [debugCode]); 1054 }''',
1055 [debugCode]);
1060 } 1056 }
1061 1057
1062 jsAst.Statement buildConvertToSlowObjectFunction() { 1058 jsAst.Statement buildConvertToSlowObjectFunction() {
1063 return js.statement(r''' 1059 return js.statement(r'''
1064 function convertToSlowObject(properties) { 1060 function convertToSlowObject(properties) {
1065 // Add and remove a property to make the object transition into hashmap 1061 // Add and remove a property to make the object transition into hashmap
1066 // mode. 1062 // mode.
1067 properties.__MAGIC_SLOW_PROPERTY = 1; 1063 properties.__MAGIC_SLOW_PROPERTY = 1;
1068 delete properties.__MAGIC_SLOW_PROPERTY; 1064 delete properties.__MAGIC_SLOW_PROPERTY;
1069 return properties; 1065 return properties;
(...skipping 15 matching lines...) Expand all
1085 var object = new cls(); 1081 var object = new cls();
1086 return object.__proto__ && 1082 return object.__proto__ &&
1087 object.__proto__.p === cls.prototype.p; 1083 object.__proto__.p === cls.prototype.p;
1088 })(); 1084 })();
1089 '''); 1085 ''');
1090 } 1086 }
1091 1087
1092 return supportsDirectProtoAccess; 1088 return supportsDirectProtoAccess;
1093 } 1089 }
1094 1090
1095 jsAst.Expression generateLibraryDescriptor(LibraryElement library, 1091 jsAst.Expression generateLibraryDescriptor(
1096 Fragment fragment) { 1092 LibraryElement library, Fragment fragment) {
1097 var uri = ""; 1093 var uri = "";
1098 if (!compiler.options.enableMinification || backend.mustPreserveUris) { 1094 if (!compiler.options.enableMinification || backend.mustPreserveUris) {
1099 uri = library.canonicalUri; 1095 uri = library.canonicalUri;
1100 if (uri.scheme == 'file' && compiler.options.outputUri != null) { 1096 if (uri.scheme == 'file' && compiler.options.outputUri != null) {
1101 uri = relativize( 1097 uri =
1102 compiler.options.outputUri, library.canonicalUri, false); 1098 relativize(compiler.options.outputUri, library.canonicalUri, false);
1103 } 1099 }
1104 } 1100 }
1105 1101
1106 String libraryName = (!compiler.options.enableMinification || 1102 String libraryName = (!compiler.options.enableMinification ||
1107 backend.mustRetainLibraryNames) ? library.libraryName : ""; 1103 backend.mustRetainLibraryNames) ? library.libraryName : "";
1108 1104
1109 jsAst.Fun metadata = task.metadataCollector.buildMetadataFunction(library); 1105 jsAst.Fun metadata = task.metadataCollector.buildMetadataFunction(library);
1110 1106
1111 ClassBuilder descriptor = elementDescriptors[fragment][library]; 1107 ClassBuilder descriptor = elementDescriptors[fragment][library];
1112 1108
1113 jsAst.ObjectInitializer initializer; 1109 jsAst.ObjectInitializer initializer;
1114 if (descriptor == null) { 1110 if (descriptor == null) {
1115 // Nothing of the library was emitted. 1111 // Nothing of the library was emitted.
1116 // TODO(floitsch): this should not happen. We currently have an example 1112 // TODO(floitsch): this should not happen. We currently have an example
1117 // with language/prefix6_negative_test.dart where we have an instance 1113 // with language/prefix6_negative_test.dart where we have an instance
1118 // method without its corresponding class. 1114 // method without its corresponding class.
1119 initializer = new jsAst.ObjectInitializer([]); 1115 initializer = new jsAst.ObjectInitializer([]);
1120 } else { 1116 } else {
1121 initializer = descriptor.toObjectInitializer(); 1117 initializer = descriptor.toObjectInitializer();
1122 } 1118 }
1123 1119
1124 compiler.dumpInfoTask.registerElementAst(library, metadata); 1120 compiler.dumpInfoTask.registerElementAst(library, metadata);
1125 compiler.dumpInfoTask.registerElementAst(library, initializer); 1121 compiler.dumpInfoTask.registerElementAst(library, initializer);
1126 1122
1127 List<jsAst.Expression> parts = <jsAst.Expression>[]; 1123 List<jsAst.Expression> parts = <jsAst.Expression>[];
1128 parts..add(js.string(libraryName)) 1124 parts
1129 ..add(js.string(uri.toString())) 1125 ..add(js.string(libraryName))
1130 ..add(metadata == null ? new jsAst.ArrayHole() : metadata) 1126 ..add(js.string(uri.toString()))
1131 ..add(js('#', namer.globalObjectFor(library))) 1127 ..add(metadata == null ? new jsAst.ArrayHole() : metadata)
1132 ..add(initializer); 1128 ..add(js('#', namer.globalObjectFor(library)))
1129 ..add(initializer);
1133 if (library == compiler.mainApp) { 1130 if (library == compiler.mainApp) {
1134 parts.add(js.number(1)); 1131 parts.add(js.number(1));
1135 } 1132 }
1136 1133
1137 return new jsAst.ArrayInitializer(parts); 1134 return new jsAst.ArrayInitializer(parts);
1138 } 1135 }
1139 1136
1140 void assemblePrecompiledConstructor(OutputUnit outputUnit, 1137 void assemblePrecompiledConstructor(
1141 jsAst.Name constructorName, 1138 OutputUnit outputUnit,
1142 jsAst.Expression constructorAst, 1139 jsAst.Name constructorName,
1143 List<jsAst.Name> fields) { 1140 jsAst.Expression constructorAst,
1144 cspPrecompiledFunctionFor(outputUnit).add( 1141 List<jsAst.Name> fields) {
1145 new jsAst.FunctionDeclaration(constructorName, constructorAst)); 1142 cspPrecompiledFunctionFor(outputUnit)
1143 .add(new jsAst.FunctionDeclaration(constructorName, constructorAst));
1146 1144
1147 String fieldNamesProperty = FIELD_NAMES_PROPERTY_NAME; 1145 String fieldNamesProperty = FIELD_NAMES_PROPERTY_NAME;
1148 bool hasIsolateSupport = compiler.hasIsolateSupport; 1146 bool hasIsolateSupport = compiler.hasIsolateSupport;
1149 jsAst.Node fieldNamesArray; 1147 jsAst.Node fieldNamesArray;
1150 if (hasIsolateSupport) { 1148 if (hasIsolateSupport) {
1151 fieldNamesArray = 1149 fieldNamesArray =
1152 new jsAst.ArrayInitializer(fields.map(js.quoteName).toList()); 1150 new jsAst.ArrayInitializer(fields.map(js.quoteName).toList());
1153 } else { 1151 } else {
1154 fieldNamesArray = new jsAst.LiteralNull(); 1152 fieldNamesArray = new jsAst.LiteralNull();
1155 } 1153 }
1156 1154
1157 cspPrecompiledFunctionFor(outputUnit).add(js.statement(r''' 1155 cspPrecompiledFunctionFor(outputUnit).add(js.statement(
1156 r'''
1158 { 1157 {
1159 #constructorName.#typeNameProperty = #constructorNameString; 1158 #constructorName.#typeNameProperty = #constructorNameString;
1160 // IE does not have a name property. 1159 // IE does not have a name property.
1161 if (!("name" in #constructorName)) 1160 if (!("name" in #constructorName))
1162 #constructorName.name = #constructorNameString; 1161 #constructorName.name = #constructorNameString;
1163 $desc = $collectedClasses$.#constructorName[1]; 1162 $desc = $collectedClasses$.#constructorName[1];
1164 #constructorName.prototype = $desc; 1163 #constructorName.prototype = $desc;
1165 ''' /* next string is not a raw string */ ''' 1164 ''' /* next string is not a raw string */ '''
1166 if (#hasIsolateSupport) { 1165 if (#hasIsolateSupport) {
1167 #constructorName.$fieldNamesProperty = #fieldNamesArray; 1166 #constructorName.$fieldNamesProperty = #fieldNamesArray;
1168 } 1167 }
1169 }''', 1168 }''',
1170 {"constructorName": constructorName, 1169 {
1171 "typeNameProperty": typeNameProperty, 1170 "constructorName": constructorName,
1172 "constructorNameString": js.quoteName(constructorName), 1171 "typeNameProperty": typeNameProperty,
1173 "hasIsolateSupport": hasIsolateSupport, 1172 "constructorNameString": js.quoteName(constructorName),
1174 "fieldNamesArray": fieldNamesArray})); 1173 "hasIsolateSupport": hasIsolateSupport,
1174 "fieldNamesArray": fieldNamesArray
1175 }));
1175 1176
1176 cspPrecompiledConstructorNamesFor(outputUnit).add(js('#', constructorName)); 1177 cspPrecompiledConstructorNamesFor(outputUnit).add(js('#', constructorName));
1177 } 1178 }
1178 1179
1179 void assembleTypedefs(Program program) { 1180 void assembleTypedefs(Program program) {
1180 Fragment mainFragment = program.mainFragment; 1181 Fragment mainFragment = program.mainFragment;
1181 OutputUnit mainOutputUnit = mainFragment.outputUnit; 1182 OutputUnit mainOutputUnit = mainFragment.outputUnit;
1182 1183
1183 // Emit all required typedef declarations into the main output unit. 1184 // Emit all required typedef declarations into the main output unit.
1184 // TODO(karlklose): unify required classes and typedefs to declarations 1185 // TODO(karlklose): unify required classes and typedefs to declarations
1185 // and have builders for each kind. 1186 // and have builders for each kind.
1186 for (TypedefElement typedef in typedefsNeededForReflection) { 1187 for (TypedefElement typedef in typedefsNeededForReflection) {
1187 LibraryElement library = typedef.library; 1188 LibraryElement library = typedef.library;
1188 // TODO(karlklose): add a TypedefBuilder and move this code there. 1189 // TODO(karlklose): add a TypedefBuilder and move this code there.
1189 DartType type = typedef.alias; 1190 DartType type = typedef.alias;
1190 // TODO(zarah): reify type variables once reflection on type arguments of 1191 // TODO(zarah): reify type variables once reflection on type arguments of
1191 // typedefs is supported. 1192 // typedefs is supported.
1192 jsAst.Expression typeIndex = 1193 jsAst.Expression typeIndex =
1193 task.metadataCollector.reifyType(type, ignoreTypeVariables: true); 1194 task.metadataCollector.reifyType(type, ignoreTypeVariables: true);
1194 ClassBuilder builder = new ClassBuilder.forStatics(typedef, namer); 1195 ClassBuilder builder = new ClassBuilder.forStatics(typedef, namer);
1195 builder.addPropertyByName(embeddedNames.TYPEDEF_TYPE_PROPERTY_NAME, 1196 builder.addPropertyByName(
1196 typeIndex); 1197 embeddedNames.TYPEDEF_TYPE_PROPERTY_NAME, typeIndex);
1197 builder.addPropertyByName(embeddedNames.TYPEDEF_PREDICATE_PROPERTY_NAME, 1198 builder.addPropertyByName(
1198 js.boolean(true)); 1199 embeddedNames.TYPEDEF_PREDICATE_PROPERTY_NAME, js.boolean(true));
1199 1200
1200 // We can be pretty sure that the objectClass is initialized, since 1201 // We can be pretty sure that the objectClass is initialized, since
1201 // typedefs are only emitted with reflection, which requires lots of 1202 // typedefs are only emitted with reflection, which requires lots of
1202 // classes. 1203 // classes.
1203 assert(coreClasses.objectClass != null); 1204 assert(coreClasses.objectClass != null);
1204 builder.superName = namer.className(coreClasses.objectClass); 1205 builder.superName = namer.className(coreClasses.objectClass);
1205 jsAst.Node declaration = builder.toObjectInitializer(); 1206 jsAst.Node declaration = builder.toObjectInitializer();
1206 jsAst.Name mangledName = namer.globalPropertyName(typedef); 1207 jsAst.Name mangledName = namer.globalPropertyName(typedef);
1207 String reflectionName = getReflectionName(typedef, mangledName); 1208 String reflectionName = getReflectionName(typedef, mangledName);
1208 getElementDescriptor(library, mainFragment) 1209 getElementDescriptor(library, mainFragment)
1209 ..addProperty(mangledName, declaration) 1210 ..addProperty(mangledName, declaration)
1210 ..addPropertyByName("+$reflectionName", js.string('')); 1211 ..addPropertyByName("+$reflectionName", js.string(''));
1211 // Also emit a trivial constructor for CSP mode. 1212 // Also emit a trivial constructor for CSP mode.
1212 jsAst.Name constructorName = mangledName; 1213 jsAst.Name constructorName = mangledName;
1213 jsAst.Expression constructorAst = js('function() {}'); 1214 jsAst.Expression constructorAst = js('function() {}');
1214 List<jsAst.Name> fieldNames = []; 1215 List<jsAst.Name> fieldNames = [];
1215 assemblePrecompiledConstructor(mainOutputUnit, 1216 assemblePrecompiledConstructor(
1216 constructorName, 1217 mainOutputUnit, constructorName, constructorAst, fieldNames);
1217 constructorAst,
1218 fieldNames);
1219 } 1218 }
1220 } 1219 }
1221 1220
1222 jsAst.Statement buildGlobalObjectSetup(bool isProgramSplit) { 1221 jsAst.Statement buildGlobalObjectSetup(bool isProgramSplit) {
1223 List<jsAst.Statement> parts = <jsAst.Statement>[]; 1222 List<jsAst.Statement> parts = <jsAst.Statement>[];
1224 1223
1225 parts.add(js.comment(""" 1224 parts.add(js.comment("""
1226 // The global objects start as so-called "slow objects". For V8, this 1225 // The global objects start as so-called "slow objects". For V8, this
1227 // means that it won't try to make map transitions as we add properties 1226 // means that it won't try to make map transitions as we add properties
1228 // to these objects. Later on, we attempt to turn these objects into 1227 // to these objects. Later on, we attempt to turn these objects into
1229 // fast objects by calling "convertToFastObject" (see 1228 // fast objects by calling "convertToFastObject" (see
1230 // [emitConvertToFastObjectFunction]). 1229 // [emitConvertToFastObjectFunction]).
1231 """)); 1230 """));
1232 1231
1233 for (String globalObject in Namer.reservedGlobalObjectNames) { 1232 for (String globalObject in Namer.reservedGlobalObjectNames) {
1234 if (isProgramSplit) { 1233 if (isProgramSplit) {
1235 String template = 1234 String template =
1236 "var #globalObject = #globalsHolder.#globalObject = map();"; 1235 "var #globalObject = #globalsHolder.#globalObject = map();";
1237 parts.add(js.statement(template, {"globalObject": globalObject, 1236 parts.add(js.statement(template,
1238 "globalsHolder": globalsHolder})); 1237 {"globalObject": globalObject, "globalsHolder": globalsHolder}));
1239 } else { 1238 } else {
1240 parts.add(js.statement("var #globalObject = map();", 1239 parts.add(js.statement(
1241 {"globalObject": globalObject})); 1240 "var #globalObject = map();", {"globalObject": globalObject}));
1242 } 1241 }
1243
1244 } 1242 }
1245 1243
1246 return new jsAst.Block(parts); 1244 return new jsAst.Block(parts);
1247 } 1245 }
1248 1246
1249 jsAst.Statement buildConvertGlobalObjectToFastObjects() { 1247 jsAst.Statement buildConvertGlobalObjectToFastObjects() {
1250 List<jsAst.Statement> parts = <jsAst.Statement>[]; 1248 List<jsAst.Statement> parts = <jsAst.Statement>[];
1251 1249
1252 for (String globalObject in Namer.reservedGlobalObjectNames) { 1250 for (String globalObject in Namer.reservedGlobalObjectNames) {
1253 parts.add(js.statement( 1251 parts.add(js.statement(
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1285 + String(Object.getOwnPropertyNames(C).length) 1283 + String(Object.getOwnPropertyNames(C).length)
1286 + ", fast properties " + HasFastProperties(C)); 1284 + ", fast properties " + HasFastProperties(C));
1287 var names = Object.getOwnPropertyNames($); 1285 var names = Object.getOwnPropertyNames($);
1288 for (var i = 0; i < names.length; i++) { 1286 for (var i = 0; i < names.length; i++) {
1289 print("$." + names[i]); 1287 print("$." + names[i]);
1290 } 1288 }
1291 } 1289 }
1292 ''')); 1290 '''));
1293 1291
1294 for (String object in Namer.userGlobalObjects) { 1292 for (String object in Namer.userGlobalObjects) {
1295 parts.add(js.statement(''' 1293 parts.add(js.statement(
1294 '''
1296 if (typeof print === "function") { 1295 if (typeof print === "function") {
1297 print("Size of " + #objectString + ": " 1296 print("Size of " + #objectString + ": "
1298 + String(Object.getOwnPropertyNames(#object).length) 1297 + String(Object.getOwnPropertyNames(#object).length)
1299 + ", fast properties " + HasFastProperties(#object)); 1298 + ", fast properties " + HasFastProperties(#object));
1300 } 1299 }
1301 ''', {"object": object, "objectString": js.string(object)})); 1300 ''',
1301 {"object": object, "objectString": js.string(object)}));
1302 } 1302 }
1303 } 1303 }
1304 1304
1305 return new jsAst.Block(parts); 1305 return new jsAst.Block(parts);
1306 } 1306 }
1307 1307
1308 jsAst.Statement buildMangledNames() { 1308 jsAst.Statement buildMangledNames() {
1309 List<jsAst.Statement> parts = <jsAst.Statement>[]; 1309 List<jsAst.Statement> parts = <jsAst.Statement>[];
1310 1310
1311 if (!mangledFieldNames.isEmpty) { 1311 if (!mangledFieldNames.isEmpty) {
1312 List<jsAst.Name> keys = mangledFieldNames.keys.toList()..sort(); 1312 List<jsAst.Name> keys = mangledFieldNames.keys.toList()..sort();
1313 var properties = []; 1313 var properties = [];
1314 for (jsAst.Name key in keys) { 1314 for (jsAst.Name key in keys) {
1315 var value = js.string(mangledFieldNames[key]); 1315 var value = js.string(mangledFieldNames[key]);
1316 properties.add(new jsAst.Property(key, value)); 1316 properties.add(new jsAst.Property(key, value));
1317 } 1317 }
1318 1318
1319 jsAst.Expression mangledNamesAccess = 1319 jsAst.Expression mangledNamesAccess =
1320 generateEmbeddedGlobalAccess(embeddedNames.MANGLED_NAMES); 1320 generateEmbeddedGlobalAccess(embeddedNames.MANGLED_NAMES);
1321 var map = new jsAst.ObjectInitializer(properties); 1321 var map = new jsAst.ObjectInitializer(properties);
1322 parts.add(js.statement('# = #', [mangledNamesAccess, map])); 1322 parts.add(js.statement('# = #', [mangledNamesAccess, map]));
1323 } 1323 }
1324 1324
1325 if (!mangledGlobalFieldNames.isEmpty) { 1325 if (!mangledGlobalFieldNames.isEmpty) {
1326 List<jsAst.Name> keys = mangledGlobalFieldNames.keys.toList() 1326 List<jsAst.Name> keys = mangledGlobalFieldNames.keys.toList()..sort();
1327 ..sort();
1328 List<jsAst.Property> properties = <jsAst.Property>[]; 1327 List<jsAst.Property> properties = <jsAst.Property>[];
1329 for (jsAst.Name key in keys) { 1328 for (jsAst.Name key in keys) {
1330 jsAst.Literal value = js.string(mangledGlobalFieldNames[key]); 1329 jsAst.Literal value = js.string(mangledGlobalFieldNames[key]);
1331 properties.add(new jsAst.Property(js.quoteName(key), value)); 1330 properties.add(new jsAst.Property(js.quoteName(key), value));
1332 } 1331 }
1333 jsAst.Expression mangledGlobalNamesAccess = 1332 jsAst.Expression mangledGlobalNamesAccess =
1334 generateEmbeddedGlobalAccess(embeddedNames.MANGLED_GLOBAL_NAMES); 1333 generateEmbeddedGlobalAccess(embeddedNames.MANGLED_GLOBAL_NAMES);
1335 jsAst.ObjectInitializer map = new jsAst.ObjectInitializer(properties); 1334 jsAst.ObjectInitializer map = new jsAst.ObjectInitializer(properties);
1336 parts.add(js.statement('# = #', [mangledGlobalNamesAccess, map])); 1335 parts.add(js.statement('# = #', [mangledGlobalNamesAccess, map]));
1337 } 1336 }
1338 1337
1339 return new jsAst.Block(parts); 1338 return new jsAst.Block(parts);
1340 } 1339 }
1341 1340
1342 void checkEverythingEmitted(Iterable<Element> elements) { 1341 void checkEverythingEmitted(Iterable<Element> elements) {
1343 List<Element> pendingStatics; 1342 List<Element> pendingStatics;
1344 if (!compiler.options.hasIncrementalSupport) { 1343 if (!compiler.options.hasIncrementalSupport) {
1345 pendingStatics = 1344 pendingStatics =
1346 Elements.sortedByPosition(elements.where((e) => !e.isLibrary)); 1345 Elements.sortedByPosition(elements.where((e) => !e.isLibrary));
1347 1346
1348 pendingStatics.forEach((element) => 1347 pendingStatics.forEach((element) => reporter.reportInfo(
1349 reporter.reportInfo( 1348 element, MessageKind.GENERIC, {'text': 'Pending statics.'}));
1350 element, MessageKind.GENERIC, {'text': 'Pending statics.'}));
1351 } 1349 }
1352 1350
1353 if (pendingStatics != null && !pendingStatics.isEmpty) { 1351 if (pendingStatics != null && !pendingStatics.isEmpty) {
1354 reporter.internalError(pendingStatics.first, 1352 reporter.internalError(
1355 'Pending statics (see above).'); 1353 pendingStatics.first, 'Pending statics (see above).');
1356 } 1354 }
1357 } 1355 }
1358 1356
1359 void assembleLibrary(Library library, Fragment fragment) { 1357 void assembleLibrary(Library library, Fragment fragment) {
1360 LibraryElement libraryElement = library.element; 1358 LibraryElement libraryElement = library.element;
1361 1359
1362 assembleStaticFunctions(library.statics, fragment); 1360 assembleStaticFunctions(library.statics, fragment);
1363 1361
1364 ClassBuilder libraryBuilder = 1362 ClassBuilder libraryBuilder =
1365 getElementDescriptor(libraryElement, fragment); 1363 getElementDescriptor(libraryElement, fragment);
(...skipping 11 matching lines...) Expand all
1377 } 1375 }
1378 } 1376 }
1379 assembleTypedefs(program); 1377 assembleTypedefs(program);
1380 } 1378 }
1381 1379
1382 jsAst.Statement buildDeferredHeader() { 1380 jsAst.Statement buildDeferredHeader() {
1383 /// For deferred loading we communicate the initializers via this global 1381 /// For deferred loading we communicate the initializers via this global
1384 /// variable. The deferred hunks will add their initialization to this. 1382 /// variable. The deferred hunks will add their initialization to this.
1385 /// The semicolon is important in minified mode, without it the 1383 /// The semicolon is important in minified mode, without it the
1386 /// following parenthesis looks like a call to the object literal. 1384 /// following parenthesis looks like a call to the object literal.
1387 return js.statement('self.#deferredInitializers = ' 1385 return js.statement(
1388 'self.#deferredInitializers || Object.create(null);', 1386 'self.#deferredInitializers = '
1389 {'deferredInitializers': deferredInitializers}); 1387 'self.#deferredInitializers || Object.create(null);',
1388 {'deferredInitializers': deferredInitializers});
1390 } 1389 }
1391 1390
1392 jsAst.Program buildOutputAstForMain(Program program, 1391 jsAst.Program buildOutputAstForMain(Program program,
1393 Map<OutputUnit, _DeferredOutputUnitHash> deferredLoadHashes) { 1392 Map<OutputUnit, _DeferredOutputUnitHash> deferredLoadHashes) {
1394 MainFragment mainFragment = program.mainFragment; 1393 MainFragment mainFragment = program.mainFragment;
1395 OutputUnit mainOutputUnit = mainFragment.outputUnit; 1394 OutputUnit mainOutputUnit = mainFragment.outputUnit;
1396 bool isProgramSplit = program.isSplit; 1395 bool isProgramSplit = program.isSplit;
1397 1396
1398 List<jsAst.Statement> statements = <jsAst.Statement>[]; 1397 List<jsAst.Statement> statements = <jsAst.Statement>[];
1399 1398
1400 statements..add(buildGeneratedBy()) 1399 statements..add(buildGeneratedBy())..add(js.comment(HOOKS_API_USAGE));
1401 ..add(js.comment(HOOKS_API_USAGE));
1402 1400
1403 if (isProgramSplit) { 1401 if (isProgramSplit) {
1404 statements.add(buildDeferredHeader()); 1402 statements.add(buildDeferredHeader());
1405 } 1403 }
1406 1404
1407 // Collect the AST for the decriptors 1405 // Collect the AST for the decriptors
1408 Map<Element, ClassBuilder> descriptors = elementDescriptors[mainFragment]; 1406 Map<Element, ClassBuilder> descriptors = elementDescriptors[mainFragment];
1409 if (descriptors == null) descriptors = const {}; 1407 if (descriptors == null) descriptors = const {};
1410 1408
1411 checkEverythingEmitted(descriptors.keys); 1409 checkEverythingEmitted(descriptors.keys);
1412 1410
1413 Iterable<LibraryElement> libraries = outputLibraryLists[mainOutputUnit]; 1411 Iterable<LibraryElement> libraries = outputLibraryLists[mainOutputUnit];
1414 if (libraries == null) libraries = <LibraryElement>[]; 1412 if (libraries == null) libraries = <LibraryElement>[];
1415 1413
1416 List<jsAst.Expression> parts = <jsAst.Expression>[]; 1414 List<jsAst.Expression> parts = <jsAst.Expression>[];
1417 for (LibraryElement library in Elements.sortedByPosition(libraries)) { 1415 for (LibraryElement library in Elements.sortedByPosition(libraries)) {
1418 parts.add(generateLibraryDescriptor(library, mainFragment)); 1416 parts.add(generateLibraryDescriptor(library, mainFragment));
1419 descriptors.remove(library); 1417 descriptors.remove(library);
1420 } 1418 }
1421 1419
1422 if (descriptors.isNotEmpty) { 1420 if (descriptors.isNotEmpty) {
1423 List<Element> remainingLibraries = descriptors.keys 1421 List<Element> remainingLibraries =
1424 .where((Element e) => e is LibraryElement) 1422 descriptors.keys.where((Element e) => e is LibraryElement).toList();
1425 .toList();
1426 1423
1427 // The remaining descriptors are only accessible through reflection. 1424 // The remaining descriptors are only accessible through reflection.
1428 // The program builder does not collect libraries that only 1425 // The program builder does not collect libraries that only
1429 // contain typedefs that are used for reflection. 1426 // contain typedefs that are used for reflection.
1430 for (LibraryElement element in remainingLibraries) { 1427 for (LibraryElement element in remainingLibraries) {
1431 assert(element is LibraryElement || 1428 assert(element is LibraryElement ||
1432 compiler.options.hasIncrementalSupport); 1429 compiler.options.hasIncrementalSupport);
1433 if (element is LibraryElement) { 1430 if (element is LibraryElement) {
1434 parts.add(generateLibraryDescriptor(element, mainFragment)); 1431 parts.add(generateLibraryDescriptor(element, mainFragment));
1435 descriptors.remove(element); 1432 descriptors.remove(element);
1436 } 1433 }
1437 } 1434 }
1438 } 1435 }
1439 jsAst.ArrayInitializer descriptorsAst = new jsAst.ArrayInitializer(parts); 1436 jsAst.ArrayInitializer descriptorsAst = new jsAst.ArrayInitializer(parts);
1440 1437
1441 // Using a named function here produces easier to read stack traces in 1438 // Using a named function here produces easier to read stack traces in
1442 // Chrome/V8. 1439 // Chrome/V8.
1443 statements.add(js.statement(""" 1440 statements.add(js.statement(
1441 """
1444 (function() { 1442 (function() {
1445 // No renaming in the top-level function to save the locals for the 1443 // No renaming in the top-level function to save the locals for the
1446 // nested context where they will be used more. We have to put the 1444 // nested context where they will be used more. We have to put the
1447 // comment into a hole as the parser strips out comments right away. 1445 // comment into a hole as the parser strips out comments right away.
1448 #disableVariableRenaming; 1446 #disableVariableRenaming;
1449 #supportsDirectProtoAccess; 1447 #supportsDirectProtoAccess;
1450 1448
1451 if (#hasIncrementalSupport) { 1449 if (#hasIncrementalSupport) {
1452 #helper = #helper || Object.create(null); 1450 #helper = #helper || Object.create(null);
1453 #helper.patch = function(a) { eval(a)}; 1451 #helper.patch = function(a) { eval(a)};
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
1543 #convertToFastObject; 1541 #convertToFastObject;
1544 #convertToSlowObject; 1542 #convertToSlowObject;
1545 1543
1546 #convertGlobalObjectsToFastObjects; 1544 #convertGlobalObjectsToFastObjects;
1547 #debugFastObjects; 1545 #debugFastObjects;
1548 1546
1549 #init; 1547 #init;
1550 1548
1551 #main; 1549 #main;
1552 })(); 1550 })();
1553 """, { 1551 """,
1554 "disableVariableRenaming": js.comment("/* ::norenaming:: */"), 1552 {
1555 "hasIncrementalSupport": compiler.options.hasIncrementalSupport, 1553 "disableVariableRenaming": js.comment("/* ::norenaming:: */"),
1556 "helper": js('this.#', [namer.incrementalHelperName]), 1554 "hasIncrementalSupport": compiler.options.hasIncrementalSupport,
1557 "schemaChange": buildSchemaChangeFunction(), 1555 "helper": js('this.#', [namer.incrementalHelperName]),
1558 "addMethod": buildIncrementalAddMethod(), 1556 "schemaChange": buildSchemaChangeFunction(),
1559 "isProgramSplit": isProgramSplit, 1557 "addMethod": buildIncrementalAddMethod(),
1560 "supportsDirectProtoAccess": buildSupportsDirectProtoAccess(), 1558 "isProgramSplit": isProgramSplit,
1561 "globalsHolder": globalsHolder, 1559 "supportsDirectProtoAccess": buildSupportsDirectProtoAccess(),
1562 "globalObjectSetup": buildGlobalObjectSetup(isProgramSplit), 1560 "globalsHolder": globalsHolder,
1563 "isolateName": namer.isolateName, 1561 "globalObjectSetup": buildGlobalObjectSetup(isProgramSplit),
1564 "isolatePropertiesName": js(isolatePropertiesName), 1562 "isolateName": namer.isolateName,
1565 "initName": initName, 1563 "isolatePropertiesName": js(isolatePropertiesName),
1566 "functionThatReturnsNull": buildFunctionThatReturnsNull(), 1564 "initName": initName,
1567 "mangledNames": buildMangledNames(), 1565 "functionThatReturnsNull": buildFunctionThatReturnsNull(),
1568 "setupProgram": buildSetupProgram(program, compiler, backend, namer, this) , 1566 "mangledNames": buildMangledNames(),
1569 "setupProgramName": setupProgramName, 1567 "setupProgram":
1570 "descriptors": descriptorsAst, 1568 buildSetupProgram(program, compiler, backend, namer, this),
1571 "cspPrecompiledFunctions": buildCspPrecompiledFunctionFor(mainOutputUnit), 1569 "setupProgramName": setupProgramName,
1572 "getInterceptorMethods": interceptorEmitter.buildGetInterceptorMethods(), 1570 "descriptors": descriptorsAst,
1573 "oneShotInterceptors": interceptorEmitter.buildOneShotInterceptors(), 1571 "cspPrecompiledFunctions":
1574 "makeConstantList": 1572 buildCspPrecompiledFunctionFor(mainOutputUnit),
1575 buildMakeConstantList(program.outputContainsConstantList), 1573 "getInterceptorMethods":
1576 "compileTimeConstants": buildCompileTimeConstants(mainFragment.constants, 1574 interceptorEmitter.buildGetInterceptorMethods(),
1577 isMainFragment: true), 1575 "oneShotInterceptors": interceptorEmitter.buildOneShotInterceptors(),
1578 "deferredBoilerPlate": buildDeferredBoilerPlate(deferredLoadHashes), 1576 "makeConstantList":
1579 "staticNonFinalInitializers": buildStaticNonFinalFieldInitializations( 1577 buildMakeConstantList(program.outputContainsConstantList),
1580 mainOutputUnit), 1578 "compileTimeConstants": buildCompileTimeConstants(
1581 "typeToInterceptorMap": 1579 mainFragment.constants,
1582 interceptorEmitter.buildTypeToInterceptorMap(program), 1580 isMainFragment: true),
1583 "lazyStaticFields": buildLazilyInitializedStaticFields( 1581 "deferredBoilerPlate": buildDeferredBoilerPlate(deferredLoadHashes),
1584 mainFragment.staticLazilyInitializedFields), 1582 "staticNonFinalInitializers":
1585 "metadata": buildMetadata(program, mainOutputUnit), 1583 buildStaticNonFinalFieldInitializations(mainOutputUnit),
1586 "convertToFastObject": buildConvertToFastObjectFunction(), 1584 "typeToInterceptorMap":
1587 "convertToSlowObject": buildConvertToSlowObjectFunction(), 1585 interceptorEmitter.buildTypeToInterceptorMap(program),
1588 "convertGlobalObjectsToFastObjects": 1586 "lazyStaticFields": buildLazilyInitializedStaticFields(
1589 buildConvertGlobalObjectToFastObjects(), 1587 mainFragment.staticLazilyInitializedFields),
1590 "debugFastObjects": buildDebugFastObjectCode(), 1588 "metadata": buildMetadata(program, mainOutputUnit),
1591 "init": buildInitFunction(program.outputContainsConstantList), 1589 "convertToFastObject": buildConvertToFastObjectFunction(),
1592 "main": buildMain(mainFragment.invokeMain) 1590 "convertToSlowObject": buildConvertToSlowObjectFunction(),
1593 })); 1591 "convertGlobalObjectsToFastObjects":
1592 buildConvertGlobalObjectToFastObjects(),
1593 "debugFastObjects": buildDebugFastObjectCode(),
1594 "init": buildInitFunction(program.outputContainsConstantList),
1595 "main": buildMain(mainFragment.invokeMain)
1596 }));
1594 1597
1595 return new jsAst.Program(statements); 1598 return new jsAst.Program(statements);
1596 } 1599 }
1597 1600
1598 void emitMainOutputUnit(OutputUnit mainOutputUnit, jsAst.Program program) { 1601 void emitMainOutputUnit(OutputUnit mainOutputUnit, jsAst.Program program) {
1599 LineColumnCollector lineColumnCollector; 1602 LineColumnCollector lineColumnCollector;
1600 List<CodeOutputListener> codeOutputListeners; 1603 List<CodeOutputListener> codeOutputListeners;
1601 if (generateSourceMap) { 1604 if (generateSourceMap) {
1602 lineColumnCollector = new LineColumnCollector(); 1605 lineColumnCollector = new LineColumnCollector();
1603 codeOutputListeners = <CodeOutputListener>[lineColumnCollector]; 1606 codeOutputListeners = <CodeOutputListener>[lineColumnCollector];
1604 } 1607 }
1605 1608
1606 CodeOutput mainOutput = 1609 CodeOutput mainOutput = new StreamCodeOutput(
1607 new StreamCodeOutput(compiler.outputProvider('', 'js'), 1610 compiler.outputProvider('', 'js'), codeOutputListeners);
1608 codeOutputListeners);
1609 outputBuffers[mainOutputUnit] = mainOutput; 1611 outputBuffers[mainOutputUnit] = mainOutput;
1610 1612
1611 1613 mainOutput.addBuffer(jsAst.createCodeBuffer(program, compiler,
1612 mainOutput.addBuffer(jsAst.createCodeBuffer( 1614 monitor: compiler.dumpInfoTask));
1613 program, compiler, monitor: compiler.dumpInfoTask));
1614 1615
1615 if (compiler.options.deferredMapUri != null) { 1616 if (compiler.options.deferredMapUri != null) {
1616 outputDeferredMap(); 1617 outputDeferredMap();
1617 } 1618 }
1618 1619
1619 if (generateSourceMap) { 1620 if (generateSourceMap) {
1620 mainOutput.add(generateSourceMapTag( 1621 mainOutput.add(generateSourceMapTag(
1621 compiler.options.sourceMapUri, compiler.options.outputUri)); 1622 compiler.options.sourceMapUri, compiler.options.outputUri));
1622 } 1623 }
1623 1624
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
1767 descriptors.remove(library); 1768 descriptors.remove(library);
1768 } 1769 }
1769 1770
1770 outputs[outputUnit] = new jsAst.ArrayInitializer(parts); 1771 outputs[outputUnit] = new jsAst.ArrayInitializer(parts);
1771 } 1772 }
1772 } 1773 }
1773 1774
1774 return outputs; 1775 return outputs;
1775 } 1776 }
1776 1777
1777 void finalizeTokensInAst(jsAst.Program main, 1778 void finalizeTokensInAst(
1778 Iterable<jsAst.Program> deferredParts) { 1779 jsAst.Program main, Iterable<jsAst.Program> deferredParts) {
1779 jsAst.TokenCounter counter = new jsAst.TokenCounter(); 1780 jsAst.TokenCounter counter = new jsAst.TokenCounter();
1780 counter.countTokens(main); 1781 counter.countTokens(main);
1781 deferredParts.forEach(counter.countTokens); 1782 deferredParts.forEach(counter.countTokens);
1782 task.metadataCollector.finalizeTokens(); 1783 task.metadataCollector.finalizeTokens();
1783 if (backend.namer is jsAst.TokenFinalizer) { 1784 if (backend.namer is jsAst.TokenFinalizer) {
1784 var finalizer = backend.namer; 1785 var finalizer = backend.namer;
1785 finalizer.finalizeTokens(); 1786 finalizer.finalizeTokens();
1786 } 1787 }
1787 } 1788 }
1788 1789
1789 int emitProgram(ProgramBuilder programBuilder) { 1790 int emitProgram(ProgramBuilder programBuilder) {
1790 Program program = 1791 Program program =
1791 programBuilder.buildProgram(storeFunctionTypesInMetadata: true); 1792 programBuilder.buildProgram(storeFunctionTypesInMetadata: true);
1792 1793
1793 outputStaticNonFinalFieldLists = 1794 outputStaticNonFinalFieldLists =
1794 programBuilder.collector.outputStaticNonFinalFieldLists; 1795 programBuilder.collector.outputStaticNonFinalFieldLists;
1795 outputLibraryLists = programBuilder.collector.outputLibraryLists; 1796 outputLibraryLists = programBuilder.collector.outputLibraryLists;
1796 typedefsNeededForReflection = 1797 typedefsNeededForReflection =
1797 programBuilder.collector.typedefsNeededForReflection; 1798 programBuilder.collector.typedefsNeededForReflection;
1798 1799
1799 assembleProgram(program); 1800 assembleProgram(program);
1800 1801
1801 // Construct the ASTs for all deferred output units. 1802 // Construct the ASTs for all deferred output units.
1802 Map<OutputUnit, jsAst.Program> deferredParts = 1803 Map<OutputUnit, jsAst.Program> deferredParts =
1803 buildOutputAstForDeferredCode(program); 1804 buildOutputAstForDeferredCode(program);
1804 1805
1805 Map<OutputUnit, _DeferredOutputUnitHash> deferredHashTokens = 1806 Map<OutputUnit, _DeferredOutputUnitHash> deferredHashTokens =
1806 new Map<OutputUnit, _DeferredOutputUnitHash>.fromIterables( 1807 new Map<OutputUnit, _DeferredOutputUnitHash>.fromIterables(
1807 deferredParts.keys, 1808 deferredParts.keys, deferredParts.keys.map((OutputUnit unit) {
1808 deferredParts.keys.map((OutputUnit unit) { 1809 return new _DeferredOutputUnitHash(unit);
1809 return new _DeferredOutputUnitHash(unit); 1810 }));
1810 })
1811 );
1812 1811
1813 jsAst.Program mainOutput = 1812 jsAst.Program mainOutput =
1814 buildOutputAstForMain(program, deferredHashTokens); 1813 buildOutputAstForMain(program, deferredHashTokens);
1815 1814
1816 finalizeTokensInAst(mainOutput, deferredParts.values); 1815 finalizeTokensInAst(mainOutput, deferredParts.values);
1817 1816
1818 // Emit deferred units first, so we have their hashes. 1817 // Emit deferred units first, so we have their hashes.
1819 // Map from OutputUnit to a hash of its content. The hash uniquely 1818 // Map from OutputUnit to a hash of its content. The hash uniquely
1820 // identifies the code of the output-unit. It does not include 1819 // identifies the code of the output-unit. It does not include
1821 // boilerplate JS code, like the sourcemap directives or the hash 1820 // boilerplate JS code, like the sourcemap directives or the hash
1822 // itself. 1821 // itself.
1823 Map<OutputUnit, String> deferredLoadHashes = 1822 Map<OutputUnit, String> deferredLoadHashes =
1824 emitDeferredOutputUnits(deferredParts); 1823 emitDeferredOutputUnits(deferredParts);
1825 1824
1826 deferredHashTokens.forEach((OutputUnit key, _DeferredOutputUnitHash token) { 1825 deferredHashTokens.forEach((OutputUnit key, _DeferredOutputUnitHash token) {
1827 token.setHash(deferredLoadHashes[key]); 1826 token.setHash(deferredLoadHashes[key]);
1828 }); 1827 });
1829 emitMainOutputUnit(program.mainFragment.outputUnit, mainOutput); 1828 emitMainOutputUnit(program.mainFragment.outputUnit, mainOutput);
1830 1829
1831 if (backend.requiresPreamble && 1830 if (backend.requiresPreamble && !backend.htmlLibraryIsLoaded) {
1832 !backend.htmlLibraryIsLoaded) { 1831 reporter.reportHintMessage(NO_LOCATION_SPANNABLE, MessageKind.PREAMBLE);
1833 reporter.reportHintMessage(
1834 NO_LOCATION_SPANNABLE, MessageKind.PREAMBLE);
1835 } 1832 }
1836 // Return the total program size. 1833 // Return the total program size.
1837 return outputBuffers.values.fold(0, (a, b) => a + b.length); 1834 return outputBuffers.values.fold(0, (a, b) => a + b.length);
1838 } 1835 }
1839 1836
1840 String generateSourceMapTag(Uri sourceMapUri, Uri fileUri) { 1837 String generateSourceMapTag(Uri sourceMapUri, Uri fileUri) {
1841 if (sourceMapUri != null && fileUri != null) { 1838 if (sourceMapUri != null && fileUri != null) {
1842 String sourceMapFileName = relativize(fileUri, sourceMapUri, false); 1839 String sourceMapFileName = relativize(fileUri, sourceMapUri, false);
1843 return ''' 1840 return '''
1844 1841
1845 //# sourceMappingURL=$sourceMapFileName 1842 //# sourceMappingURL=$sourceMapFileName
1846 '''; 1843 ''';
1847 } 1844 }
1848 return ''; 1845 return '';
1849 } 1846 }
1850 1847
1851 ClassBuilder getElementDescriptor(Element element, Fragment fragment) { 1848 ClassBuilder getElementDescriptor(Element element, Fragment fragment) {
1852 Element owner = element.library; 1849 Element owner = element.library;
1853 if (!element.isLibrary && 1850 if (!element.isLibrary &&
1854 !element.isTopLevel && 1851 !element.isTopLevel &&
1855 !backend.isNative(element)) { 1852 !backend.isNative(element)) {
1856 // For static (not top level) elements, record their code in a buffer 1853 // For static (not top level) elements, record their code in a buffer
1857 // specific to the class. For now, not supported for native classes and 1854 // specific to the class. For now, not supported for native classes and
1858 // native elements. 1855 // native elements.
1859 ClassElement cls = 1856 ClassElement cls = element.enclosingClassOrCompilationUnit.declaration;
1860 element.enclosingClassOrCompilationUnit.declaration;
1861 if (compiler.codegenWorld.directlyInstantiatedClasses.contains(cls) && 1857 if (compiler.codegenWorld.directlyInstantiatedClasses.contains(cls) &&
1862 !backend.isNative(cls) && 1858 !backend.isNative(cls) &&
1863 compiler.deferredLoadTask.outputUnitForElement(element) == 1859 compiler.deferredLoadTask.outputUnitForElement(element) ==
1864 compiler.deferredLoadTask.outputUnitForElement(cls)) { 1860 compiler.deferredLoadTask.outputUnitForElement(cls)) {
1865 owner = cls; 1861 owner = cls;
1866 } 1862 }
1867 } 1863 }
1868 if (owner == null) { 1864 if (owner == null) {
1869 reporter.internalError(element, 'Owner is null.'); 1865 reporter.internalError(element, 'Owner is null.');
1870 } 1866 }
1871 return elementDescriptors 1867 return elementDescriptors
1872 .putIfAbsent(fragment, () => new Map<Element, ClassBuilder>()) 1868 .putIfAbsent(fragment, () => new Map<Element, ClassBuilder>())
1873 .putIfAbsent(owner, () { 1869 .putIfAbsent(owner, () {
1874 return new ClassBuilder(owner, namer, owner.isClass); 1870 return new ClassBuilder(owner, namer, owner.isClass);
1875 }); 1871 });
1876 } 1872 }
1877 1873
1878 /// Emits support-code for deferred loading into [output]. 1874 /// Emits support-code for deferred loading into [output].
1879 jsAst.Statement buildDeferredBoilerPlate( 1875 jsAst.Statement buildDeferredBoilerPlate(
1880 Map<OutputUnit, _DeferredOutputUnitHash> deferredLoadHashes) { 1876 Map<OutputUnit, _DeferredOutputUnitHash> deferredLoadHashes) {
1881 List<jsAst.Statement> parts = <jsAst.Statement>[]; 1877 List<jsAst.Statement> parts = <jsAst.Statement>[];
1882 1878
1883 parts.add(js.statement(''' 1879 parts.add(js.statement(
1880 '''
1884 { 1881 {
1885 // Function for checking if a hunk is loaded given its hash. 1882 // Function for checking if a hunk is loaded given its hash.
1886 #isHunkLoaded = function(hunkHash) { 1883 #isHunkLoaded = function(hunkHash) {
1887 return !!$deferredInitializers[hunkHash]; 1884 return !!$deferredInitializers[hunkHash];
1888 }; 1885 };
1889 #deferredInitialized = new Object(null); 1886 #deferredInitialized = new Object(null);
1890 // Function for checking if a hunk is initialized given its hash. 1887 // Function for checking if a hunk is initialized given its hash.
1891 #isHunkInitialized = function(hunkHash) { 1888 #isHunkInitialized = function(hunkHash) {
1892 return #deferredInitialized[hunkHash]; 1889 return #deferredInitialized[hunkHash];
1893 }; 1890 };
1894 // Function for initializing a loaded hunk, given its hash. 1891 // Function for initializing a loaded hunk, given its hash.
1895 #initializeLoadedHunk = function(hunkHash) { 1892 #initializeLoadedHunk = function(hunkHash) {
1896 $deferredInitializers[hunkHash]( 1893 $deferredInitializers[hunkHash](
1897 #globalsHolder, ${namer.staticStateHolder}); 1894 #globalsHolder, ${namer.staticStateHolder});
1898 #deferredInitialized[hunkHash] = true; 1895 #deferredInitialized[hunkHash] = true;
1899 }; 1896 };
1900 } 1897 }
1901 ''', {"globalsHolder": globalsHolder, 1898 ''',
1902 "isHunkLoaded": generateEmbeddedGlobalAccess( 1899 {
1903 embeddedNames.IS_HUNK_LOADED), 1900 "globalsHolder": globalsHolder,
1904 "isHunkInitialized": generateEmbeddedGlobalAccess( 1901 "isHunkLoaded":
1905 embeddedNames.IS_HUNK_INITIALIZED), 1902 generateEmbeddedGlobalAccess(embeddedNames.IS_HUNK_LOADED),
1906 "initializeLoadedHunk": generateEmbeddedGlobalAccess( 1903 "isHunkInitialized":
1907 embeddedNames.INITIALIZE_LOADED_HUNK), 1904 generateEmbeddedGlobalAccess(embeddedNames.IS_HUNK_INITIALIZED),
1908 "deferredInitialized": generateEmbeddedGlobalAccess( 1905 "initializeLoadedHunk": generateEmbeddedGlobalAccess(
1909 embeddedNames.DEFERRED_INITIALIZED)})); 1906 embeddedNames.INITIALIZE_LOADED_HUNK),
1907 "deferredInitialized":
1908 generateEmbeddedGlobalAccess(embeddedNames.DEFERRED_INITIALIZED)
1909 }));
1910 1910
1911 // Write a javascript mapping from Deferred import load ids (derrived 1911 // Write a javascript mapping from Deferred import load ids (derrived
1912 // from the import prefix.) to a list of lists of uris of hunks to load, 1912 // from the import prefix.) to a list of lists of uris of hunks to load,
1913 // and a corresponding mapping to a list of hashes used by 1913 // and a corresponding mapping to a list of hashes used by
1914 // INITIALIZE_LOADED_HUNK and IS_HUNK_LOADED. 1914 // INITIALIZE_LOADED_HUNK and IS_HUNK_LOADED.
1915 Map<String, List<jsAst.LiteralString>> deferredLibraryUris = 1915 Map<String, List<jsAst.LiteralString>> deferredLibraryUris =
1916 new Map<String, List<jsAst.LiteralString>>(); 1916 new Map<String, List<jsAst.LiteralString>>();
1917 Map<String, List<_DeferredOutputUnitHash>> deferredLibraryHashes = 1917 Map<String, List<_DeferredOutputUnitHash>> deferredLibraryHashes =
1918 new Map<String, List<_DeferredOutputUnitHash>>(); 1918 new Map<String, List<_DeferredOutputUnitHash>>();
1919 compiler.deferredLoadTask.hunksToLoad.forEach( 1919 compiler.deferredLoadTask.hunksToLoad
1920 (String loadId, List<OutputUnit>outputUnits) { 1920 .forEach((String loadId, List<OutputUnit> outputUnits) {
1921 List<jsAst.LiteralString> uris = new List<jsAst.LiteralString>(); 1921 List<jsAst.LiteralString> uris = new List<jsAst.LiteralString>();
1922 List<_DeferredOutputUnitHash> hashes = 1922 List<_DeferredOutputUnitHash> hashes =
1923 new List<_DeferredOutputUnitHash>(); 1923 new List<_DeferredOutputUnitHash>();
1924 deferredLibraryHashes[loadId] = new List<_DeferredOutputUnitHash>(); 1924 deferredLibraryHashes[loadId] = new List<_DeferredOutputUnitHash>();
1925 for (OutputUnit outputUnit in outputUnits) { 1925 for (OutputUnit outputUnit in outputUnits) {
1926 uris.add(js.escapedString( 1926 uris.add(
1927 backend.deferredPartFileName(outputUnit.name))); 1927 js.escapedString(backend.deferredPartFileName(outputUnit.name)));
1928 hashes.add(deferredLoadHashes[outputUnit]); 1928 hashes.add(deferredLoadHashes[outputUnit]);
1929 } 1929 }
1930 1930
1931 deferredLibraryUris[loadId] = uris; 1931 deferredLibraryUris[loadId] = uris;
1932 deferredLibraryHashes[loadId] = hashes; 1932 deferredLibraryHashes[loadId] = hashes;
1933 }); 1933 });
1934 1934
1935 void emitMapping(String name, Map<String, List<jsAst.Expression>> mapping) { 1935 void emitMapping(String name, Map<String, List<jsAst.Expression>> mapping) {
1936 List<jsAst.Property> properties = new List<jsAst.Property>(); 1936 List<jsAst.Property> properties = new List<jsAst.Property>();
1937 mapping.forEach((String key, List<jsAst.Expression> values) { 1937 mapping.forEach((String key, List<jsAst.Expression> values) {
1938 properties.add(new jsAst.Property(js.escapedString(key), 1938 properties.add(new jsAst.Property(
1939 new jsAst.ArrayInitializer(values))); 1939 js.escapedString(key), new jsAst.ArrayInitializer(values)));
1940 }); 1940 });
1941 jsAst.Node initializer = 1941 jsAst.Node initializer =
1942 new jsAst.ObjectInitializer(properties, isOneLiner: true); 1942 new jsAst.ObjectInitializer(properties, isOneLiner: true);
1943 1943
1944 jsAst.Node globalName = generateEmbeddedGlobalAccess(name); 1944 jsAst.Node globalName = generateEmbeddedGlobalAccess(name);
1945 parts.add(js.statement("# = #", [globalName, initializer])); 1945 parts.add(js.statement("# = #", [globalName, initializer]));
1946 } 1946 }
1947 1947
1948 emitMapping(embeddedNames.DEFERRED_LIBRARY_URIS, deferredLibraryUris); 1948 emitMapping(embeddedNames.DEFERRED_LIBRARY_URIS, deferredLibraryUris);
1949 emitMapping(embeddedNames.DEFERRED_LIBRARY_HASHES, 1949 emitMapping(embeddedNames.DEFERRED_LIBRARY_HASHES, deferredLibraryHashes);
1950 deferredLibraryHashes);
1951 1950
1952 return new jsAst.Block(parts); 1951 return new jsAst.Block(parts);
1953 } 1952 }
1954 1953
1955 Map <OutputUnit, jsAst.Program> buildOutputAstForDeferredCode( 1954 Map<OutputUnit, jsAst.Program> buildOutputAstForDeferredCode(
1956 Program program) { 1955 Program program) {
1957 if (!program.isSplit) return const <OutputUnit, jsAst.Program>{}; 1956 if (!program.isSplit) return const <OutputUnit, jsAst.Program>{};
1958 1957
1959 Map<OutputUnit, jsAst.Program> result = 1958 Map<OutputUnit, jsAst.Program> result =
1960 new Map<OutputUnit, jsAst.Program>(); 1959 new Map<OutputUnit, jsAst.Program>();
1961 1960
1962 Map<OutputUnit, jsAst.Expression> deferredAsts = 1961 Map<OutputUnit, jsAst.Expression> deferredAsts =
1963 buildDescriptorsForOutputUnits(program); 1962 buildDescriptorsForOutputUnits(program);
1964 1963
1965 for (Fragment fragment in program.deferredFragments) { 1964 for (Fragment fragment in program.deferredFragments) {
1966 OutputUnit outputUnit = fragment.outputUnit; 1965 OutputUnit outputUnit = fragment.outputUnit;
1967 jsAst.Expression libraryDescriptor = deferredAsts[outputUnit]; 1966 jsAst.Expression libraryDescriptor = deferredAsts[outputUnit];
1968 List<jsAst.Statement> body = <jsAst.Statement>[]; 1967 List<jsAst.Statement> body = <jsAst.Statement>[];
1969 1968
1970 // No renaming in the top-level function to save the locals for the 1969 // No renaming in the top-level function to save the locals for the
1971 // nested context where they will be used more. 1970 // nested context where they will be used more.
1972 body.add(js.comment("/* ::norenaming:: ")); 1971 body.add(js.comment("/* ::norenaming:: "));
1973 1972
1974 for (String globalObject in Namer.reservedGlobalObjectNames) { 1973 for (String globalObject in Namer.reservedGlobalObjectNames) {
1975 body.add(js.statement('var #object = #globalsHolder.#object;', 1974 body.add(js.statement('var #object = #globalsHolder.#object;',
1976 {'globalsHolder': globalsHolder, 1975 {'globalsHolder': globalsHolder, 'object': globalObject}));
1977 'object': globalObject}));
1978 } 1976 }
1979 body..add(js.statement('var init = #globalsHolder.init;', 1977 body
1980 {'globalsHolder': globalsHolder})) 1978 ..add(js.statement('var init = #globalsHolder.init;',
1981 ..add(js.statement('var $setupProgramName = ' 1979 {'globalsHolder': globalsHolder}))
1982 '#globalsHolder.$setupProgramName;', 1980 ..add(js.statement(
1983 {'globalsHolder': globalsHolder})) 1981 'var $setupProgramName = '
1984 ..add(js.statement('var ${namer.isolateName} = ' 1982 '#globalsHolder.$setupProgramName;',
1985 '#globalsHolder.${namer.isolateName};', 1983 {'globalsHolder': globalsHolder}))
1986 {'globalsHolder': globalsHolder})); 1984 ..add(js.statement(
1985 'var ${namer.isolateName} = '
1986 '#globalsHolder.${namer.isolateName};',
1987 {'globalsHolder': globalsHolder}));
1987 String typesAccess = 1988 String typesAccess =
1988 generateEmbeddedGlobalAccessString(embeddedNames.TYPES); 1989 generateEmbeddedGlobalAccessString(embeddedNames.TYPES);
1989 if (libraryDescriptor != null) { 1990 if (libraryDescriptor != null) {
1990 // The argument to reflectionDataParser is assigned to a temporary 1991 // The argument to reflectionDataParser is assigned to a temporary
1991 // 'dart' so that 'dart.' will appear as the prefix to dart methods 1992 // 'dart' so that 'dart.' will appear as the prefix to dart methods
1992 // in stack traces and profile entries. 1993 // in stack traces and profile entries.
1993 body.add(js.statement('var dart = #', libraryDescriptor)); 1994 body.add(js.statement('var dart = #', libraryDescriptor));
1994 1995
1995 if (compiler.options.useContentSecurityPolicy) { 1996 if (compiler.options.useContentSecurityPolicy) {
1996 body.add(buildCspPrecompiledFunctionFor(outputUnit)); 1997 body.add(buildCspPrecompiledFunctionFor(outputUnit));
1997 } 1998 }
1998 body.add( 1999 body.add(
1999 js.statement('$setupProgramName(dart, ${typesAccess}.length);')); 2000 js.statement('$setupProgramName(dart, ${typesAccess}.length);'));
2000 } 2001 }
2001 2002
2002 body..add(buildMetadata(program, outputUnit)) 2003 body
2003 ..add(js.statement('${typesAccess}.push.apply(${typesAccess}, ' 2004 ..add(buildMetadata(program, outputUnit))
2004 '${namer.deferredTypesName});')); 2005 ..add(js.statement('${typesAccess}.push.apply(${typesAccess}, '
2006 '${namer.deferredTypesName});'));
2005 2007
2006 body.add(buildCompileTimeConstants(fragment.constants, 2008 body.add(
2007 isMainFragment: false)); 2009 buildCompileTimeConstants(fragment.constants, isMainFragment: false));
2008 body.add(buildStaticNonFinalFieldInitializations(outputUnit)); 2010 body.add(buildStaticNonFinalFieldInitializations(outputUnit));
2009 body.add(buildLazilyInitializedStaticFields( 2011 body.add(buildLazilyInitializedStaticFields(
2010 fragment.staticLazilyInitializedFields, isMainFragment: false)); 2012 fragment.staticLazilyInitializedFields,
2013 isMainFragment: false));
2011 2014
2012 List<jsAst.Statement> statements = <jsAst.Statement>[]; 2015 List<jsAst.Statement> statements = <jsAst.Statement>[];
2013 2016
2014 statements 2017 statements
2015 ..add(buildGeneratedBy()) 2018 ..add(buildGeneratedBy())
2016 ..add(buildDeferredHeader()) 2019 ..add(buildDeferredHeader())
2017 ..add(js.statement('${deferredInitializers}.current = ' 2020 ..add(js.statement(
2018 """function (#, ${namer.staticStateHolder}) { 2021 '${deferredInitializers}.current = '
2022 """function (#, ${namer.staticStateHolder}) {
2019 # 2023 #
2020 } 2024 }
2021 """, [globalsHolder, body])); 2025 """,
2026 [globalsHolder, body]));
2022 2027
2023 result[outputUnit] = new jsAst.Program(statements); 2028 result[outputUnit] = new jsAst.Program(statements);
2024 } 2029 }
2025 2030
2026 return result; 2031 return result;
2027 } 2032 }
2028 2033
2029 /// Returns a map from OutputUnit to a hash of its content. The hash uniquely 2034 /// Returns a map from OutputUnit to a hash of its content. The hash uniquely
2030 /// identifies the code of the output-unit. It does not include 2035 /// identifies the code of the output-unit. It does not include
2031 /// boilerplate JS code, like the sourcemap directives or the hash 2036 /// boilerplate JS code, like the sourcemap directives or the hash
2032 /// itself. 2037 /// itself.
2033 Map<OutputUnit, String> emitDeferredOutputUnits( 2038 Map<OutputUnit, String> emitDeferredOutputUnits(
2034 Map<OutputUnit, jsAst.Program> outputAsts) { 2039 Map<OutputUnit, jsAst.Program> outputAsts) {
2035
2036 Map<OutputUnit, String> hunkHashes = new Map<OutputUnit, String>(); 2040 Map<OutputUnit, String> hunkHashes = new Map<OutputUnit, String>();
2037 2041
2038 for (OutputUnit outputUnit in outputAsts.keys) { 2042 for (OutputUnit outputUnit in outputAsts.keys) {
2039 List<CodeOutputListener> outputListeners = <CodeOutputListener>[]; 2043 List<CodeOutputListener> outputListeners = <CodeOutputListener>[];
2040 Hasher hasher = new Hasher(); 2044 Hasher hasher = new Hasher();
2041 outputListeners.add(hasher); 2045 outputListeners.add(hasher);
2042 2046
2043 LineColumnCollector lineColumnCollector; 2047 LineColumnCollector lineColumnCollector;
2044 if (generateSourceMap) { 2048 if (generateSourceMap) {
2045 lineColumnCollector = new LineColumnCollector(); 2049 lineColumnCollector = new LineColumnCollector();
2046 outputListeners.add(lineColumnCollector); 2050 outputListeners.add(lineColumnCollector);
2047 } 2051 }
2048 2052
2049 String partPrefix = 2053 String partPrefix =
2050 backend.deferredPartFileName(outputUnit.name, addExtension: false); 2054 backend.deferredPartFileName(outputUnit.name, addExtension: false);
2051 CodeOutput output = new StreamCodeOutput( 2055 CodeOutput output = new StreamCodeOutput(
2052 compiler.outputProvider(partPrefix, 'part.js'), 2056 compiler.outputProvider(partPrefix, 'part.js'), outputListeners);
2053 outputListeners);
2054 2057
2055 outputBuffers[outputUnit] = output; 2058 outputBuffers[outputUnit] = output;
2056 2059
2057 output.addBuffer(jsAst.createCodeBuffer( 2060 output.addBuffer(jsAst.createCodeBuffer(outputAsts[outputUnit], compiler,
2058 outputAsts[outputUnit], compiler, monitor: compiler.dumpInfoTask)); 2061 monitor: compiler.dumpInfoTask));
2059 2062
2060 // Make a unique hash of the code (before the sourcemaps are added) 2063 // Make a unique hash of the code (before the sourcemaps are added)
2061 // This will be used to retrieve the initializing function from the global 2064 // This will be used to retrieve the initializing function from the global
2062 // variable. 2065 // variable.
2063 String hash = hasher.getHash(); 2066 String hash = hasher.getHash();
2064 2067
2065 output.add('$N${deferredInitializers}["$hash"]$_=$_' 2068 output.add('$N${deferredInitializers}["$hash"]$_=$_'
2066 '${deferredInitializers}.current$N'); 2069 '${deferredInitializers}.current$N');
2067 2070
2068 if (generateSourceMap) { 2071 if (generateSourceMap) {
2069 Uri mapUri, partUri; 2072 Uri mapUri, partUri;
2070 Uri sourceMapUri = compiler.options.sourceMapUri; 2073 Uri sourceMapUri = compiler.options.sourceMapUri;
2071 Uri outputUri = compiler.options.outputUri; 2074 Uri outputUri = compiler.options.outputUri;
2072 2075
2073 String partName = "$partPrefix.part"; 2076 String partName = "$partPrefix.part";
2074 2077
2075 if (sourceMapUri != null) { 2078 if (sourceMapUri != null) {
2076 String mapFileName = partName + ".js.map"; 2079 String mapFileName = partName + ".js.map";
2077 List<String> mapSegments = sourceMapUri.pathSegments.toList(); 2080 List<String> mapSegments = sourceMapUri.pathSegments.toList();
2078 mapSegments[mapSegments.length - 1] = mapFileName; 2081 mapSegments[mapSegments.length - 1] = mapFileName;
2079 mapUri = compiler.options.sourceMapUri 2082 mapUri =
2080 .replace(pathSegments: mapSegments); 2083 compiler.options.sourceMapUri.replace(pathSegments: mapSegments);
2081 } 2084 }
2082 2085
2083 if (outputUri != null) { 2086 if (outputUri != null) {
2084 String partFileName = partName + ".js"; 2087 String partFileName = partName + ".js";
2085 List<String> partSegments = outputUri.pathSegments.toList(); 2088 List<String> partSegments = outputUri.pathSegments.toList();
2086 partSegments[partSegments.length - 1] = partFileName; 2089 partSegments[partSegments.length - 1] = partFileName;
2087 partUri = compiler.options.outputUri.replace( 2090 partUri =
2088 pathSegments: partSegments); 2091 compiler.options.outputUri.replace(pathSegments: partSegments);
2089 } 2092 }
2090 2093
2091 output.add(generateSourceMapTag(mapUri, partUri)); 2094 output.add(generateSourceMapTag(mapUri, partUri));
2092 output.close(); 2095 output.close();
2093 outputSourceMap(output, lineColumnCollector, partName, 2096 outputSourceMap(output, lineColumnCollector, partName, mapUri, partUri);
2094 mapUri, partUri);
2095 } else { 2097 } else {
2096 output.close(); 2098 output.close();
2097 } 2099 }
2098 2100
2099 hunkHashes[outputUnit] = hash; 2101 hunkHashes[outputUnit] = hash;
2100 } 2102 }
2101 return hunkHashes; 2103 return hunkHashes;
2102 } 2104 }
2103 2105
2104 jsAst.Comment buildGeneratedBy() { 2106 jsAst.Comment buildGeneratedBy() {
2105 List<String> options = []; 2107 List<String> options = [];
2106 if (compiler.mirrorsLibrary != null) options.add('mirrors'); 2108 if (compiler.mirrorsLibrary != null) options.add('mirrors');
2107 if (compiler.options.useContentSecurityPolicy) options.add("CSP"); 2109 if (compiler.options.useContentSecurityPolicy) options.add("CSP");
2108 return new jsAst.Comment(generatedBy(compiler, flavor: options.join(", "))); 2110 return new jsAst.Comment(generatedBy(compiler, flavor: options.join(", ")));
2109 } 2111 }
2110 2112
2111 void outputSourceMap(CodeOutput output, 2113 void outputSourceMap(
2112 LineColumnProvider lineColumnProvider, 2114 CodeOutput output, LineColumnProvider lineColumnProvider, String name,
2113 String name, 2115 [Uri sourceMapUri, Uri fileUri]) {
2114 [Uri sourceMapUri,
2115 Uri fileUri]) {
2116 if (!generateSourceMap) return; 2116 if (!generateSourceMap) return;
2117 // Create a source file for the compilation output. This allows using 2117 // Create a source file for the compilation output. This allows using
2118 // [:getLine:] to transform offsets to line numbers in [SourceMapBuilder]. 2118 // [:getLine:] to transform offsets to line numbers in [SourceMapBuilder].
2119 SourceMapBuilder sourceMapBuilder = 2119 SourceMapBuilder sourceMapBuilder =
2120 new SourceMapBuilder(sourceMapUri, fileUri, lineColumnProvider); 2120 new SourceMapBuilder(sourceMapUri, fileUri, lineColumnProvider);
2121 output.forEachSourceLocation(sourceMapBuilder.addMapping); 2121 output.forEachSourceLocation(sourceMapBuilder.addMapping);
2122 String sourceMap = sourceMapBuilder.build(); 2122 String sourceMap = sourceMapBuilder.build();
2123 compiler.outputProvider(name, 'js.map') 2123 compiler.outputProvider(name, 'js.map')
2124 ..add(sourceMap) 2124 ..add(sourceMap)
2125 ..close(); 2125 ..close();
2126 } 2126 }
2127 2127
2128 void outputDeferredMap() { 2128 void outputDeferredMap() {
2129 Map<String, dynamic> mapping = new Map<String, dynamic>(); 2129 Map<String, dynamic> mapping = new Map<String, dynamic>();
2130 // Json does not support comments, so we embed the explanation in the 2130 // Json does not support comments, so we embed the explanation in the
2131 // data. 2131 // data.
2132 mapping["_comment"] = "This mapping shows which compiled `.js` files are " 2132 mapping["_comment"] = "This mapping shows which compiled `.js` files are "
2133 "needed for a given deferred library import."; 2133 "needed for a given deferred library import.";
2134 mapping.addAll(compiler.deferredLoadTask.computeDeferredMap()); 2134 mapping.addAll(compiler.deferredLoadTask.computeDeferredMap());
2135 compiler.outputProvider( 2135 compiler.outputProvider(
2136 compiler.options.deferredMapUri.path, 'deferred_map') 2136 compiler.options.deferredMapUri.path, 'deferred_map')
2137 ..add(const JsonEncoder.withIndent(" ").convert(mapping)) 2137 ..add(const JsonEncoder.withIndent(" ").convert(mapping))
2138 ..close(); 2138 ..close();
2139 } 2139 }
2140 2140
2141 void invalidateCaches() { 2141 void invalidateCaches() {
2142 if (!compiler.options.hasIncrementalSupport) return; 2142 if (!compiler.options.hasIncrementalSupport) return;
2143 if (cachedElements.isEmpty) return; 2143 if (cachedElements.isEmpty) return;
2144 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { 2144 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) {
2145 if (element.isInstanceMember) { 2145 if (element.isInstanceMember) {
2146 cachedClassBuilders.remove(element.enclosingClass); 2146 cachedClassBuilders.remove(element.enclosingClass);
2147 2147
2148 nativeEmitter.cachedBuilders.remove(element.enclosingClass); 2148 nativeEmitter.cachedBuilders.remove(element.enclosingClass);
2149
2150 } 2149 }
2151 } 2150 }
2152 } 2151 }
2153 } 2152 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698