| 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.new_js_emitter.model_emitter; | 5 library dart2js.new_js_emitter.model_emitter; |
| 6 | 6 |
| 7 import '../../constants/values.dart' show ConstantValue, FunctionConstantValue; | 7 import '../../constants/values.dart' show ConstantValue, FunctionConstantValue; |
| 8 import '../../dart2jslib.dart' show Compiler; | 8 import '../../dart2jslib.dart' show Compiler; |
| 9 import '../../dart_types.dart' show DartType; | 9 import '../../dart_types.dart' show DartType; |
| 10 import '../../elements/elements.dart' show ClassElement, FunctionElement; | 10 import '../../elements/elements.dart' show ClassElement, FunctionElement; |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 153 String mainCode = js.prettyPrint(mainAst, compiler).getText(); | 153 String mainCode = js.prettyPrint(mainAst, compiler).getText(); |
| 154 compiler.outputProvider(mainFragment.outputFileName, 'js') | 154 compiler.outputProvider(mainFragment.outputFileName, 'js') |
| 155 ..add(buildGeneratedBy(compiler)) | 155 ..add(buildGeneratedBy(compiler)) |
| 156 ..add(mainCode) | 156 ..add(mainCode) |
| 157 ..close(); | 157 ..close(); |
| 158 totalSize += mainCode.length; | 158 totalSize += mainCode.length; |
| 159 | 159 |
| 160 return totalSize; | 160 return totalSize; |
| 161 } | 161 } |
| 162 | 162 |
| 163 js.LiteralString unparse(Compiler compiler, js.Node value) { | 163 /// Unparses the given [value]. |
| 164 /// |
| 165 /// Pretty-prints the given [value] and, if [protectForEval] is |
| 166 /// true, wraps the resulting string in parenthesis. The result is escaped |
| 167 /// and returned. |
| 168 js.LiteralString unparse(Compiler compiler, js.Node value, |
| 169 {bool protectForEval: true}) { |
| 164 String text = js.prettyPrint(value, compiler).getText(); | 170 String text = js.prettyPrint(value, compiler).getText(); |
| 165 if (value is js.Fun) text = '($text)'; | 171 if (protectForEval) { |
| 166 if (value is js.LiteralExpression && | 172 if (value is js.Fun) text = '($text)'; |
| 167 (value.template.startsWith("function ") || | 173 if (value is js.LiteralExpression && |
| 168 value.template.startsWith("{"))) { | 174 (value.template.startsWith("function ") || |
| 169 text = '($text)'; | 175 value.template.startsWith("{"))) { |
| 176 text = '($text)'; |
| 177 } |
| 170 } | 178 } |
| 171 return js.js.escapedString(text); | 179 return js.js.escapedString(text); |
| 172 } | 180 } |
| 173 | 181 |
| 174 String buildGeneratedBy(compiler) { | 182 String buildGeneratedBy(compiler) { |
| 175 var suffix = ''; | 183 var suffix = ''; |
| 176 if (compiler.hasBuildId) suffix = ' version: ${compiler.buildId}'; | 184 if (compiler.hasBuildId) suffix = ' version: ${compiler.buildId}'; |
| 177 return '// Generated by dart2js, the Dart to JavaScript compiler$suffix.\n'; | 185 return '// Generated by dart2js, the Dart to JavaScript compiler$suffix.\n'; |
| 178 } | 186 } |
| 179 | 187 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 194 'parseFunctionDescriptor': | 202 'parseFunctionDescriptor': |
| 195 js.js.statement(parseFunctionDescriptorBoilerplate, | 203 js.js.statement(parseFunctionDescriptorBoilerplate, |
| 196 {'argumentCount': js.string(namer.requiredParameterField), | 204 {'argumentCount': js.string(namer.requiredParameterField), |
| 197 'defaultArgumentValues': js.string(namer.defaultValuesField), | 205 'defaultArgumentValues': js.string(namer.defaultValuesField), |
| 198 'callName': js.string(namer.callNameField)}), | 206 'callName': js.string(namer.callNameField)}), |
| 199 | 207 |
| 200 'cyclicThrow': | 208 'cyclicThrow': |
| 201 backend.emitter.staticFunctionAccess(backend.getCyclicThrowHelper()), | 209 backend.emitter.staticFunctionAccess(backend.getCyclicThrowHelper()), |
| 202 'outputContainsConstantList': program.outputContainsConstantList, | 210 'outputContainsConstantList': program.outputContainsConstantList, |
| 203 'embeddedGlobals': emitEmbeddedGlobals(program), | 211 'embeddedGlobals': emitEmbeddedGlobals(program), |
| 212 'readMetadataTypeFunction': readMetadataTypeFunction, |
| 204 'staticNonFinals': | 213 'staticNonFinals': |
| 205 emitStaticNonFinalFields(fragment.staticNonFinalFields), | 214 emitStaticNonFinalFields(fragment.staticNonFinalFields), |
| 206 'operatorIsPrefix': js.string(namer.operatorIsPrefix), | 215 'operatorIsPrefix': js.string(namer.operatorIsPrefix), |
| 207 'callName': js.string(namer.callNameField), | 216 'callName': js.string(namer.callNameField), |
| 208 'argumentCount': js.string(namer.requiredParameterField), | 217 'argumentCount': js.string(namer.requiredParameterField), |
| 209 'defaultArgumentValues': js.string(namer.defaultValuesField), | 218 'defaultArgumentValues': js.string(namer.defaultValuesField), |
| 210 'eagerClasses': emitEagerClassInitializations(fragment.libraries), | 219 'eagerClasses': emitEagerClassInitializations(fragment.libraries), |
| 211 'invokeMain': fragment.invokeMain, | 220 'invokeMain': fragment.invokeMain, |
| 212 'code': code}; | 221 'code': code}; |
| 213 | 222 |
| (...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 414 } | 423 } |
| 415 | 424 |
| 416 js.Property emitGetTypeFromName() { | 425 js.Property emitGetTypeFromName() { |
| 417 js.Expression function = | 426 js.Expression function = |
| 418 js.js( """function(name) { | 427 js.js( """function(name) { |
| 419 return holdersMap[name][name].ensureResolved(); | 428 return holdersMap[name][name].ensureResolved(); |
| 420 }"""); | 429 }"""); |
| 421 return new js.Property(js.string(GET_TYPE_FROM_NAME), function); | 430 return new js.Property(js.string(GET_TYPE_FROM_NAME), function); |
| 422 } | 431 } |
| 423 | 432 |
| 433 static final String readMetadataTypeName = "readMetadataType"; |
| 434 |
| 435 js.Statement get readMetadataTypeFunction { |
| 436 // Types are non-evaluated and must be compiled at first use. |
| 437 // Compiled strings are guaranteed not to be strings, and it's thus safe |
| 438 // to use a type-test to determine if a type has already been compiled. |
| 439 return js.js.statement('''function $readMetadataTypeName(index) { |
| 440 var type = #typesAccess[index]; |
| 441 if (typeof type == 'string') { |
| 442 type = expressionCompile(type); |
| 443 #typesAccess[index] = type; |
| 444 } |
| 445 return type; |
| 446 }''', {"typesAccess": generateEmbeddedGlobalAccess(TYPES)}); |
| 447 } |
| 448 |
| 449 js.Template get templateForReadType { |
| 450 // TODO(floitsch): make sure that no local variable shadows the access to |
| 451 // the readMetadataType function. |
| 452 return js.js.expressionTemplateFor('$readMetadataTypeName(#)'); |
| 453 } |
| 454 |
| 424 List<js.Property> emitMetadata(Program program) { | 455 List<js.Property> emitMetadata(Program program) { |
| 425 List<js.Property> metadataGlobals = <js.Property>[]; | 456 List<js.Property> metadataGlobals = <js.Property>[]; |
| 426 metadataGlobals.add(new js.Property( | 457 metadataGlobals.add(new js.Property( |
| 427 js.string(METADATA), new js.ArrayInitializer(program.metadata))); | 458 js.string(METADATA), new js.ArrayInitializer(program.metadata))); |
| 428 List<js.Expression> types = | 459 List<js.Expression> types = |
| 429 program.metadataTypes[program.fragments.first.outputUnit]; | 460 program.metadataTypes[program.fragments.first.outputUnit]; |
| 430 if (types == null) types = <js.Expression>[]; | 461 if (types == null) types = <js.Expression>[]; |
| 431 metadataGlobals.add(new js.Property( | 462 List<js.LiteralString> unparsedTypes = types |
| 432 js.string(TYPES), new js.ArrayInitializer(types))); | 463 .map((type) => unparse(compiler, type, protectForEval: false)) |
| 433 | 464 .toList(); |
| 465 js.ArrayInitializer typesArray = new js.ArrayInitializer(unparsedTypes); |
| 466 metadataGlobals.add(new js.Property(js.string(TYPES), typesArray)); |
| 434 return metadataGlobals; | 467 return metadataGlobals; |
| 435 } | 468 } |
| 436 | 469 |
| 437 js.Expression emitDeferredFragment(List<js.Expression> types, | 470 js.Expression emitDeferredFragment(List<js.Expression> types, |
| 438 DeferredFragment fragment, | 471 DeferredFragment fragment, |
| 439 List<Holder> holders) { | 472 List<Holder> holders) { |
| 440 // TODO(floitsch): initialize eager classes. | 473 // TODO(floitsch): initialize eager classes. |
| 441 // TODO(floitsch): the hash must depend on the output. | 474 // TODO(floitsch): the hash must depend on the output. |
| 442 int hash = fragment.hashCode; | 475 int hash = fragment.hashCode; |
| 443 | 476 |
| 444 List<js.Expression> deferredCode = | 477 List<js.Expression> deferredCode = |
| 445 fragment.libraries.map(emitLibrary).toList(); | 478 fragment.libraries.map(emitLibrary).toList(); |
| 446 | 479 |
| 447 deferredCode.add( | 480 deferredCode.add( |
| 448 emitLazilyInitializedStatics(fragment.staticLazilyInitializedFields)); | 481 emitLazilyInitializedStatics(fragment.staticLazilyInitializedFields)); |
| 449 | 482 |
| 450 deferredCode.add(emitConstants(fragment.constants)); | 483 deferredCode.add(emitConstants(fragment.constants)); |
| 451 | 484 |
| 452 js.ArrayInitializer deferredArray = new js.ArrayInitializer(deferredCode); | 485 js.ArrayInitializer deferredArray = new js.ArrayInitializer(deferredCode); |
| 453 | 486 |
| 454 // This is the code that must be evaluated after all deferred classes have | 487 // This is the code that must be evaluated after all deferred classes have |
| 455 // been setup. | 488 // been setup. |
| 456 js.Statement immediateCode = | 489 js.Statement immediateCode = |
| 457 emitEagerClassInitializations(fragment.libraries); | 490 emitEagerClassInitializations(fragment.libraries); |
| 458 | 491 |
| 459 js.LiteralString immediateString = unparse(compiler, immediateCode); | 492 js.LiteralString immediateString = unparse(compiler, immediateCode); |
| 460 | 493 |
| 461 js.Expression deferredTypes = types == null | 494 js.Expression deferredTypes = (types == null) |
| 462 ? js.string("[]") | 495 ? js.string("[]") |
| 463 : unparse(compiler, new js.ArrayInitializer(types)); | 496 : unparse(compiler, new js.ArrayInitializer(types)); |
| 464 | 497 |
| 465 js.ArrayInitializer hunk = | 498 js.ArrayInitializer hunk = |
| 466 new js.ArrayInitializer([deferredArray, immediateString, | 499 new js.ArrayInitializer([deferredArray, immediateString, |
| 467 deferredTypes]); | 500 deferredTypes]); |
| 468 | 501 |
| 469 return js.js("$deferredInitializersGlobal[$hash] = #", hunk); | 502 return js.js("$deferredInitializersGlobal[$hash] = #", hunk); |
| 470 } | 503 } |
| 471 | 504 |
| (...skipping 677 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1149 #nativeInfoHandler; | 1182 #nativeInfoHandler; |
| 1150 } | 1183 } |
| 1151 } | 1184 } |
| 1152 } | 1185 } |
| 1153 | 1186 |
| 1154 $setupProgramName(program, 0); | 1187 $setupProgramName(program, 0); |
| 1155 | 1188 |
| 1156 // Initialize globals. | 1189 // Initialize globals. |
| 1157 #embeddedGlobals; | 1190 #embeddedGlobals; |
| 1158 | 1191 |
| 1192 function expressionCompile(__s__) { |
| 1193 'use strict'; |
| 1194 return eval('(' + __s__ + ')'); |
| 1195 } |
| 1196 |
| 1197 #readMetadataTypeFunction; |
| 1198 |
| 1159 // TODO(floitsch): this order means that native classes may not be | 1199 // TODO(floitsch): this order means that native classes may not be |
| 1160 // referenced from constants. I'm mostly afraid of things like using them as | 1200 // referenced from constants. I'm mostly afraid of things like using them as |
| 1161 // generic arguments (which should be fine, but maybe there are other | 1201 // generic arguments (which should be fine, but maybe there are other |
| 1162 // similar things). | 1202 // similar things). |
| 1163 // Initialize natives. | 1203 // Initialize natives. |
| 1164 if (#needsNativeSupport) handleNativeClassInfos(); | 1204 if (#needsNativeSupport) handleNativeClassInfos(); |
| 1165 | 1205 |
| 1166 // Initialize static non-final fields. | 1206 // Initialize static non-final fields. |
| 1167 #staticNonFinals; | 1207 #staticNonFinals; |
| 1168 | 1208 |
| 1169 // Add native boilerplate code. | 1209 // Add native boilerplate code. |
| 1170 #nativeIsolateAffinityTagInitialization; | 1210 #nativeIsolateAffinityTagInitialization; |
| 1171 | 1211 |
| 1172 // Initialize eager classes. | 1212 // Initialize eager classes. |
| 1173 #eagerClasses; | 1213 #eagerClasses; |
| 1174 | 1214 |
| 1175 var end = Date.now(); | 1215 var end = Date.now(); |
| 1176 // print('Setup: ' + (end - start) + ' ms.'); | 1216 // print('Setup: ' + (end - start) + ' ms.'); |
| 1177 | 1217 |
| 1178 #invokeMain; // Start main. | 1218 #invokeMain; // Start main. |
| 1179 | 1219 |
| 1180 }(Date.now(), #code) | 1220 }(Date.now(), #code) |
| 1181 }"""; | 1221 }"""; |
| 1182 | 1222 |
| 1183 } | 1223 } |
| OLD | NEW |