| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 } |
| OLD | NEW |