OLD | NEW |
---|---|
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 part of dart2js.js_emitter; | 5 part of dart2js.js_emitter; |
6 | 6 |
7 /** | 7 /** |
8 * Generates the code for all used classes in the program. Static fields (even | 8 * Generates the code for all used classes in the program. Static fields (even |
9 * in classes) are ignored, since they can be treated as non-class elements. | 9 * in classes) are ignored, since they can be treated as non-class elements. |
10 * | 10 * |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
141 const RANGE2_SIZE = RANGE2_LAST - RANGE2_FIRST + 1; | 141 const RANGE2_SIZE = RANGE2_LAST - RANGE2_FIRST + 1; |
142 const RANGE1_ADJUST = - (FIRST_FIELD_CODE - RANGE1_FIRST); | 142 const RANGE1_ADJUST = - (FIRST_FIELD_CODE - RANGE1_FIRST); |
143 const RANGE2_ADJUST = - (FIRST_FIELD_CODE + RANGE1_SIZE - RANGE2_FIRST); | 143 const RANGE2_ADJUST = - (FIRST_FIELD_CODE + RANGE1_SIZE - RANGE2_FIRST); |
144 const RANGE3_ADJUST = | 144 const RANGE3_ADJUST = |
145 - (FIRST_FIELD_CODE + RANGE1_SIZE + RANGE2_SIZE - RANGE3_FIRST); | 145 - (FIRST_FIELD_CODE + RANGE1_SIZE + RANGE2_SIZE - RANGE3_FIRST); |
146 | 146 |
147 String receiverParamName = compiler.enableMinification ? "r" : "receiver"; | 147 String receiverParamName = compiler.enableMinification ? "r" : "receiver"; |
148 String valueParamName = compiler.enableMinification ? "v" : "value"; | 148 String valueParamName = compiler.enableMinification ? "v" : "value"; |
149 String reflectableField = namer.reflectableField; | 149 String reflectableField = namer.reflectableField; |
150 | 150 |
151 // function generateAccessor(field, prototype, cls) { | 151 return js.statement(''' |
152 jsAst.Fun fun = js.fun(['fieldDescriptor', 'accessors', 'cls'], [ | 152 function generateAccessor(fieldDescriptor, accessors, cls) { |
153 js('var fieldInformation = fieldDescriptor.split("-")'), | 153 var fieldInformation = fieldDescriptor.split("-"); |
154 js('var field = fieldInformation[0]'), | 154 var field = fieldInformation[0]; |
155 js('var len = field.length'), | 155 var len = field.length; |
156 js('var code = field.charCodeAt(len - 1)'), | 156 var code = field.charCodeAt(len - 1); |
157 js('var reflectable'), | 157 var reflectable; |
158 js.if_('fieldInformation.length > 1', js('reflectable = true'), | 158 if (fieldInformation.length > 1) reflectable = true; |
floitsch
2014/04/22 16:11:18
var reflectable = fieldInformation.length > 1;
sra1
2014/04/23 02:33:50
I agree, but the process for this change it to cha
| |
159 js('reflectable = false')), | 159 else reflectable = false; |
160 js('code = ((code >= $RANGE1_FIRST) && (code <= $RANGE1_LAST))' | 160 code = ((code >= $RANGE1_FIRST) && (code <= $RANGE1_LAST)) |
161 ' ? code - $RANGE1_ADJUST' | 161 ? code - $RANGE1_ADJUST |
162 ' : ((code >= $RANGE2_FIRST) && (code <= $RANGE2_LAST))' | 162 : ((code >= $RANGE2_FIRST) && (code <= $RANGE2_LAST)) |
163 ' ? code - $RANGE2_ADJUST' | 163 ? code - $RANGE2_ADJUST |
164 ' : ((code >= $RANGE3_FIRST) && (code <= $RANGE3_LAST))' | 164 : ((code >= $RANGE3_FIRST) && (code <= $RANGE3_LAST)) |
165 ' ? code - $RANGE3_ADJUST' | 165 ? code - $RANGE3_ADJUST |
166 ' : $NO_FIELD_CODE'), | 166 : $NO_FIELD_CODE; |
167 | 167 |
168 // if (needsAccessor) { | 168 if (code) { // needsAccessor |
169 js.if_('code', [ | 169 var getterCode = code & 3; |
170 js('var getterCode = code & 3'), | 170 var setterCode = code >> 2; |
171 js('var setterCode = code >> 2'), | 171 var accessorName = field = field.substring(0, len - 1); |
172 js('var accessorName = field = field.substring(0, len - 1)'), | |
173 | 172 |
174 js('var divider = field.indexOf(":")'), | 173 var divider = field.indexOf(":"); |
175 js.if_('divider > 0', [ // Colon never in first position. | 174 if (divider > 0) { // Colon never in first position. |
176 js('accessorName = field.substring(0, divider)'), | 175 accessorName = field.substring(0, divider); |
177 js('field = field.substring(divider + 1)') | 176 field = field.substring(divider + 1); |
178 ]), | 177 } |
179 | 178 |
180 // if (needsGetter) { | 179 if (getterCode) { // needsGetter |
181 js.if_('getterCode', [ | 180 var args = (getterCode & 2) ? "$receiverParamName" : ""; |
182 js('var args = (getterCode & 2) ? "$receiverParamName" : ""'), | 181 var receiver = (getterCode & 1) ? "this" : "$receiverParamName"; |
183 js('var receiver = (getterCode & 1) ? "this" : "$receiverParamName"'), | 182 var body = "return " + receiver + "." + field; |
184 js('var body = "return " + receiver + "." + field'), | 183 var property = |
185 js('var property =' | 184 cls + ".prototype.${namer.getterPrefix}" + accessorName + "="; |
186 ' cls + ".prototype.${namer.getterPrefix}" + accessorName + "="'), | 185 var fn = "function(" + args + "){" + body + "}"; |
187 js('var fn = "function(" + args + "){" + body + "}"'), | 186 if (reflectable) |
188 js.if_( | 187 accessors.push(property + "\$reflectable(" + fn + ");\\n"); |
189 'reflectable', | 188 else |
190 js('accessors.push(property + "\$reflectable(" + fn + ");\\n")'), | 189 accessors.push(property + fn + ";\\n"); |
191 js('accessors.push(property + fn + ";\\n")')), | 190 } |
192 ]), | |
193 | 191 |
194 // if (needsSetter) { | 192 if (setterCode) { // needsSetter |
195 js.if_('setterCode', [ | 193 var args = (setterCode & 2) |
196 js('var args = (setterCode & 2)' | 194 ? "$receiverParamName,${_}$valueParamName" |
197 ' ? "$receiverParamName,${_}$valueParamName"' | 195 : "$valueParamName"; |
198 ' : "$valueParamName"'), | 196 var receiver = (setterCode & 1) ? "this" : "$receiverParamName"; |
199 js('var receiver = (setterCode & 1) ? "this" : "$receiverParamName"'), | 197 var body = receiver + "." + field + "$_=$_$valueParamName"; |
200 js('var body = receiver + "." + field + "$_=$_$valueParamName"'), | 198 var property = |
201 js('var property =' | 199 cls + ".prototype.${namer.setterPrefix}" + accessorName + "="; |
202 ' cls + ".prototype.${namer.setterPrefix}" + accessorName + "="'), | 200 var fn = "function(" + args + "){" + body + "}"; |
203 js('var fn = "function(" + args + "){" + body + "}"'), | 201 if (reflectable) |
204 js.if_( | 202 accessors.push(property + "\$reflectable(" + fn + ");\\n"); |
205 'reflectable', | 203 else |
206 js('accessors.push(property + "\$reflectable(" + fn + ");\\n")'), | 204 accessors.push(property + fn + ";\\n"); |
207 js('accessors.push(property + fn + ";\\n")')), | 205 } |
208 ]), | 206 } |
209 | 207 |
210 ]), | 208 return field; |
211 | 209 }'''); |
212 // return field; | |
213 js.return_('field') | |
214 ]); | |
215 | |
216 return new jsAst.FunctionDeclaration( | |
217 new jsAst.VariableDeclaration('generateAccessor'), | |
218 fun); | |
219 } | 210 } |
220 | 211 |
221 List get defineClassFunction { | 212 List get defineClassFunction { |
222 // First the class name, then the field names in an array and the members | 213 // First the class name, then the field names in an array and the members |
223 // (inside an Object literal). | 214 // (inside an Object literal). |
224 // The caller can also pass in the constructor as a function if needed. | 215 // The caller can also pass in the constructor as a function if needed. |
225 // | 216 // |
226 // Example: | 217 // Example: |
227 // defineClass("A", ["x", "y"], { | 218 // defineClass("A", ["x", "y"], { |
228 // foo$1: function(y) { | 219 // foo$1: function(y) { |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
297 // - it contains all (local) members. | 288 // - it contains all (local) members. |
298 // - its internal prototype (__proto__) points to the superclass' | 289 // - its internal prototype (__proto__) points to the superclass' |
299 // prototype field. | 290 // prototype field. |
300 // - the prototype's constructor field points to the JavaScript | 291 // - the prototype's constructor field points to the JavaScript |
301 // constructor. | 292 // constructor. |
302 // For engines where we have access to the '__proto__' we can manipulate | 293 // For engines where we have access to the '__proto__' we can manipulate |
303 // the object literal directly. For other engines we have to create a new | 294 // the object literal directly. For other engines we have to create a new |
304 // object and copy over the members. | 295 // object and copy over the members. |
305 | 296 |
306 String reflectableField = namer.reflectableField; | 297 String reflectableField = namer.reflectableField; |
307 List<jsAst.Node> statements = [ | |
308 js('var pendingClasses = {}'), | |
309 js.if_('!init.allClasses', js('init.allClasses = {}')), | |
310 js('var allClasses = init.allClasses'), | |
311 | 298 |
312 optional( | 299 return js(''' |
313 DEBUG_FAST_OBJECTS, | 300 function(collectedClasses, isolateProperties, existingIsolateProperties) { |
314 js('print("Number of classes: "' | 301 var pendingClasses = {}; |
315 r' + Object.getOwnPropertyNames($$).length)')), | 302 if (!init.allClasses) init.allClasses = {}; |
303 var allClasses = init.allClasses; | |
316 | 304 |
317 js('var hasOwnProperty = Object.prototype.hasOwnProperty'), | 305 if (#) // DEBUG_FAST_OBJECTS |
306 print("Number of classes: " + | |
307 Object.getOwnPropertyNames(\$\$).length); | |
318 | 308 |
319 js.if_('typeof dart_precompiled == "function"', | 309 var hasOwnProperty = Object.prototype.hasOwnProperty; |
320 [js('var constructors = dart_precompiled(collectedClasses)')], | |
321 | 310 |
322 [js('var combinedConstructorFunction = "function \$reflectable(fn){' | 311 if (typeof dart_precompiled == "function") { |
floitsch
2014/04/22 16:11:18
Not this CL, but I think this is a compile-time co
sra1
2014/04/23 02:33:50
I'm not sure because the csp stuff is appended.
It
| |
323 'fn.$reflectableField=1;return fn};\\n"+ "var \$desc;\\n"'), | 312 var constructors = dart_precompiled(collectedClasses); |
324 js('var constructorsList = []')]), | 313 } else { |
325 js.forIn('cls', 'collectedClasses', [ | 314 var combinedConstructorFunction = |
326 js.if_('hasOwnProperty.call(collectedClasses, cls)', [ | 315 "function \$reflectable(fn){fn.$reflectableField=1;return fn};\\n"+ |
327 js('var desc = collectedClasses[cls]'), | 316 "var \$desc;\\n"; |
328 js.if_('desc instanceof Array', js('desc = desc[1]')), | 317 var constructorsList = []; |
318 } | |
329 | 319 |
330 /* The 'fields' are either a constructor function or a | 320 for (var cls in collectedClasses) { |
331 * string encoding fields, constructor and superclass. Get | 321 if (hasOwnProperty.call(collectedClasses, cls)) { |
332 * the superclass and the fields in the format | 322 var desc = collectedClasses[cls]; |
333 * '[name/]Super;field1,field2' | 323 if (desc instanceof Array) desc = desc[1]; |
334 * from the CLASS_DESCRIPTOR_PROPERTY property on the descriptor. | |
335 * The 'name/' is optional and contains the name that should be used | |
336 * when printing the runtime type string. It is used, for example, to | |
337 * print the runtime type JSInt as 'int'. | |
338 */ | |
339 js('var classData = desc["${namer.classDescriptorProperty}"], ' | |
340 'supr, name = cls, fields = classData'), | |
341 optional( | |
342 backend.hasRetainedMetadata, | |
343 js.if_('typeof classData == "object" && ' | |
344 'classData instanceof Array', | |
345 [js('classData = fields = classData[0]')])), | |
346 | 324 |
347 js.if_('typeof classData == "string"', [ | 325 /* The 'fields' are either a constructor function or a |
348 js('var split = classData.split("/")'), | 326 * string encoding fields, constructor and superclass. Get |
349 js.if_('split.length == 2', [ | 327 * the superclass and the fields in the format |
350 js('name = split[0]'), | 328 * '[name/]Super;field1,field2' |
351 js('fields = split[1]') | 329 * from the CLASS_DESCRIPTOR_PROPERTY property on the descriptor. |
352 ]) | 330 * The 'name/' is optional and contains the name that should be used |
353 ]), | 331 * when printing the runtime type string. It is used, for example, |
332 * to print the runtime type JSInt as 'int'. | |
333 */ | |
334 var classData = desc["${namer.classDescriptorProperty}"], | |
335 supr, name = cls, fields = classData; | |
336 if (#) // backend.hasRetainedMetadata | |
337 if (typeof classData == "object" && | |
338 classData instanceof Array) { | |
339 classData = fields = classData[0]; | |
340 } | |
341 if (typeof classData == "string") { | |
342 var split = classData.split("/"); | |
343 if (split.length == 2) { | |
344 name = split[0]; | |
345 fields = split[1]; | |
346 } | |
347 } | |
354 | 348 |
355 js('var s = fields.split(";")'), | 349 var s = fields.split(";"); |
356 js('fields = s[1] == "" ? [] : s[1].split(",")'), | 350 fields = s[1] == "" ? [] : s[1].split(","); |
357 js('supr = s[0]'), | 351 supr = s[0]; |
358 js('split = supr.split(":")'), | 352 split = supr.split(":"); |
359 js.if_('split.length == 2', [ | 353 if (split.length == 2) { |
360 js('supr = split[0]'), | 354 supr = split[0]; |
361 js('var functionSignature = split[1]'), | 355 var functionSignature = split[1]; |
362 js.if_('functionSignature', | 356 if (functionSignature) |
363 js('desc.\$signature = #', | 357 desc.\$signature = (function(s) { |
364 js.fun('s', | 358 return function(){ return init.metadata[s]; }; |
365 js.return_(js.fun([], js.return_('init.metadata[s]'))))( | 359 })(functionSignature); |
366 js('functionSignature')))) | 360 } |
367 ]), | |
368 | 361 |
369 optional(needsMixinSupport, js.if_('supr && supr.indexOf("+") > 0', [ | 362 if (#) // needsMixinSupport |
370 js('s = supr.split("+")'), | 363 if (supr && supr.indexOf("+") > 0) { |
371 js('supr = s[0]'), | 364 s = supr.split("+"); |
372 js('var mixin = collectedClasses[s[1]]'), | 365 supr = s[0]; |
373 js.if_('mixin instanceof Array', js('mixin = mixin[1]')), | 366 var mixin = collectedClasses[s[1]]; |
374 js.forIn('d', 'mixin', [ | 367 if (mixin instanceof Array) mixin = mixin[1]; |
375 js.if_('hasOwnProperty.call(mixin, d)' | 368 for(var d in mixin) { |
376 '&& !hasOwnProperty.call(desc, d)', | 369 if (hasOwnProperty.call(mixin, d) && |
377 js('desc[d] = mixin[d]')) | 370 !hasOwnProperty.call(desc, d)) |
378 ]), | 371 desc[d] = mixin[d]; |
379 ])), | 372 } |
373 } | |
380 | 374 |
381 js.if_('typeof dart_precompiled != "function"', | 375 if (typeof dart_precompiled != "function") { |
382 [js('combinedConstructorFunction +=' | 376 combinedConstructorFunction += defineClass(name, cls, fields); |
383 ' defineClass(name, cls, fields)'), | 377 constructorsList.push(cls); |
384 js('constructorsList.push(cls)')]), | 378 } |
385 js.if_('supr', js('pendingClasses[cls] = supr')) | 379 if (supr) pendingClasses[cls] = supr; |
386 ]) | 380 } |
387 ]), | 381 } |
388 js.statement(''' | |
389 if (typeof dart_precompiled != "function") { | |
390 combinedConstructorFunction += | |
391 "return [\\n " + constructorsList.join(",\\n ") + "\\n]"; | |
392 var constructors = | |
393 new Function("\$collectedClasses", combinedConstructorFunction) | |
394 (collectedClasses); | |
395 combinedConstructorFunction = null; | |
396 }'''), | |
397 js.for_('var i = 0', 'i < constructors.length', 'i++', [ | |
398 js('var constructor = constructors[i]'), | |
399 js('var cls = constructor.name'), | |
400 js('var desc = collectedClasses[cls]'), | |
401 js('var globalObject = isolateProperties'), | |
402 js.if_('desc instanceof Array', [ | |
403 js('globalObject = desc[0] || isolateProperties'), | |
404 js('desc = desc[1]') | |
405 ]), | |
406 optional(backend.isTreeShakingDisabled, | |
407 js('constructor["${namer.metadataField}"] = desc')), | |
408 js('allClasses[cls] = constructor'), | |
409 js('globalObject[cls] = constructor'), | |
410 ]), | |
411 js('constructors = null'), | |
412 | 382 |
413 js('var finishedClasses = {}'), | 383 if (typeof dart_precompiled != "function") { |
414 js('init.interceptorsByTag = Object.create(null)'), | 384 combinedConstructorFunction += |
415 js('init.leafTags = {}'), | 385 "return [\\n " + constructorsList.join(",\\n ") + "\\n]"; |
386 var constructors = | |
387 new Function("\$collectedClasses", combinedConstructorFunction) | |
388 (collectedClasses); | |
389 combinedConstructorFunction = null; | |
390 } | |
416 | 391 |
417 buildFinishClass(), | 392 for (var i = 0; i < constructors.length; i++) { |
418 ]; | 393 var constructor = constructors[i]; |
394 var cls = constructor.name; | |
395 var desc = collectedClasses[cls]; | |
396 var globalObject = isolateProperties; | |
397 if (desc instanceof Array) { | |
398 globalObject = desc[0] || isolateProperties; | |
399 desc = desc[1]; | |
400 } | |
401 if (#) //backend.isTreeShakingDisabled, | |
402 constructor["${namer.metadataField}"] = desc; | |
403 allClasses[cls] = constructor; | |
404 globalObject[cls] = constructor; | |
405 } | |
419 | 406 |
420 nsmEmitter.addTrivialNsmHandlers(statements); | 407 constructors = null; |
421 | 408 |
422 statements.add( | 409 var finishedClasses = {}; |
423 js.statement('for (var cls in pendingClasses) finishClass(cls);') | 410 init.interceptorsByTag = Object.create(null); |
424 ); | 411 init.leafTags = {}; |
425 | 412 |
426 // function(collectedClasses, | 413 #; // buildFinishClass(), |
427 // isolateProperties, | 414 |
428 // existingIsolateProperties) | 415 #; // buildTrivialNsmHandlers() |
429 return js.fun(['collectedClasses', 'isolateProperties', | 416 |
430 'existingIsolateProperties'], statements); | 417 for (var cls in pendingClasses) finishClass(cls); |
418 }''', [ | |
419 DEBUG_FAST_OBJECTS, | |
420 backend.hasRetainedMetadata, | |
421 needsMixinSupport, | |
422 backend.isTreeShakingDisabled, | |
423 buildFinishClass(), | |
424 nsmEmitter.buildTrivialNsmHandlers()]); | |
425 | |
431 } | 426 } |
432 | 427 |
433 jsAst.Node optional(bool condition, jsAst.Node node) { | 428 jsAst.Node optional(bool condition, jsAst.Node node) { |
434 return condition ? node : new jsAst.EmptyStatement(); | 429 return condition ? node : new jsAst.EmptyStatement(); |
435 } | 430 } |
436 | 431 |
437 jsAst.FunctionDeclaration buildFinishClass() { | 432 jsAst.FunctionDeclaration buildFinishClass() { |
438 String specProperty = '"${namer.nativeSpecProperty}"'; // "%" | 433 String specProperty = '"${namer.nativeSpecProperty}"'; // "%" |
439 | 434 |
440 // function finishClass(cls) { | 435 return js.statement(''' |
441 jsAst.Fun fun = js.fun(['cls'], [ | 436 function finishClass(cls) { |
442 | 437 |
443 // TODO(8540): Remove this work around. | 438 // TODO(8540): Remove this work around. |
444 /* Opera does not support 'getOwnPropertyNames'. Therefore we use | 439 // Opera does not support 'getOwnPropertyNames'. Therefore we use |
445 hasOwnProperty instead. */ | 440 // hasOwnProperty instead. |
446 js('var hasOwnProperty = Object.prototype.hasOwnProperty'), | 441 var hasOwnProperty = Object.prototype.hasOwnProperty; |
447 | 442 |
448 // if (hasOwnProperty.call(finishedClasses, cls)) return; | 443 if (hasOwnProperty.call(finishedClasses, cls)) return; |
449 js.if_('hasOwnProperty.call(finishedClasses, cls)', | |
450 js.return_()), | |
451 | 444 |
452 js('finishedClasses[cls] = true'), | 445 finishedClasses[cls] = true; |
453 | 446 |
454 js('var superclass = pendingClasses[cls]'), | 447 var superclass = pendingClasses[cls]; |
455 | 448 |
456 // The superclass is only false (empty string) for Dart's Object class. | 449 // The superclass is only false (empty string) for the Dart Object |
457 // The minifier together with noSuchMethod can put methods on the | 450 // class. The minifier together with noSuchMethod can put methods on |
458 // Object.prototype object, and they show through here, so we check that | 451 // the Object.prototype object, and they show through here, so we check |
459 // we have a string. | 452 // that we have a string. |
460 js.if_('!superclass || typeof superclass != "string"', js.return_()), | 453 if (!superclass || typeof superclass != "string") return; |
461 js('finishClass(superclass)'), | 454 finishClass(superclass); |
462 js('var constructor = allClasses[cls]'), | 455 var constructor = allClasses[cls]; |
463 js('var superConstructor = allClasses[superclass]'), | 456 var superConstructor = allClasses[superclass]; |
464 | 457 |
465 js.if_(js('!superConstructor'), | 458 if (!superConstructor) |
466 js('superConstructor =' | 459 superConstructor = existingIsolateProperties[superclass]; |
467 'existingIsolateProperties[superclass]')), | |
468 | 460 |
469 js('var prototype = inheritFrom(constructor, superConstructor)'), | 461 var prototype = inheritFrom(constructor, superConstructor); |
470 | 462 |
471 optional(!nativeClasses.isEmpty, | 463 if (#) { // !nativeClasses.isEmpty, |
472 // The property looks like this: | 464 // The property looks like this: |
473 // | 465 // |
474 // HtmlElement: { | 466 // HtmlElement: { |
475 // "%": "HTMLDivElement|HTMLAnchorElement;HTMLElement;FancyButton" | 467 // "%": "HTMLDivElement|HTMLAnchorElement;HTMLElement;FancyButton" |
476 // | 468 // |
477 // The first two semicolon-separated parts contain dispatch tags, the | 469 // The first two semicolon-separated parts contain dispatch tags, the |
478 // third contains the JavaScript names for classes. | 470 // third contains the JavaScript names for classes. |
479 // | 471 // |
480 // The tags indicate that JavaScript objects with the dispatch tags | 472 // The tags indicate that JavaScript objects with the dispatch tags |
481 // (usually constructor names) HTMLDivElement, HTMLAnchorElement and | 473 // (usually constructor names) HTMLDivElement, HTMLAnchorElement and |
482 // HTMLElement all map to the Dart native class named HtmlElement. | 474 // HTMLElement all map to the Dart native class named HtmlElement. |
483 // The first set is for effective leaf nodes in the hierarchy, the | 475 // The first set is for effective leaf nodes in the hierarchy, the |
484 // second set is non-leaf nodes. | 476 // second set is non-leaf nodes. |
485 // | 477 // |
486 // The third part contains the JavaScript names of Dart classes that | 478 // The third part contains the JavaScript names of Dart classes that |
487 // extend the native class. Here, FancyButton extends HtmlElement, so | 479 // extend the native class. Here, FancyButton extends HtmlElement, so |
488 // the runtime needs to know that window.HTMLElement.prototype is the | 480 // the runtime needs to know that window.HTMLElement.prototype is the |
489 // prototype that needs to be extended in creating the custom element. | 481 // prototype that needs to be extended in creating the custom element. |
490 // | 482 // |
491 // The information is used to build tables referenced by | 483 // The information is used to build tables referenced by |
492 // getNativeInterceptor and custom element support. | 484 // getNativeInterceptor and custom element support. |
493 js.if_('hasOwnProperty.call(prototype, $specProperty)', [ | 485 if (hasOwnProperty.call(prototype, $specProperty)) { |
494 js('var nativeSpec = prototype[$specProperty].split(";")'), | 486 var nativeSpec = prototype[$specProperty].split(";"); |
495 js.if_('nativeSpec[0]', [ | 487 if (nativeSpec[0]) { |
496 js('var tags = nativeSpec[0].split("|")'), | 488 var tags = nativeSpec[0].split("|"); |
497 js.for_('var i = 0', 'i < tags.length', 'i++', [ | 489 for (var i = 0; i < tags.length; i++) { |
498 js('init.interceptorsByTag[tags[i]] = constructor'), | 490 init.interceptorsByTag[tags[i]] = constructor; |
499 js('init.leafTags[tags[i]] = true')])]), | 491 init.leafTags[tags[i]] = true; |
500 js.if_('nativeSpec[1]', [ | 492 } |
501 js('tags = nativeSpec[1].split("|")'), | 493 } |
502 optional(true, // User subclassing of native classes? | 494 if (nativeSpec[1]) { |
503 js.if_('nativeSpec[2]', [ | 495 tags = nativeSpec[1].split("|"); |
504 js('var subclasses = nativeSpec[2].split("|")'), | 496 if (#) { // User subclassing of native classes? |
505 js.for_('var i = 0', 'i < subclasses.length', 'i++', [ | 497 if (nativeSpec[2]) { |
506 js('var subclass = allClasses[subclasses[i]]'), | 498 var subclasses = nativeSpec[2].split("|"); |
507 js('subclass.\$nativeSuperclassTag = ' | 499 for (var i = 0; i < subclasses.length; i++) { |
508 'tags[0]')])])), | 500 var subclass = allClasses[subclasses[i]]; |
509 js.for_('i = 0', 'i < tags.length', 'i++', [ | 501 subclass.\$nativeSuperclassTag = tags[0]; |
510 js('init.interceptorsByTag[tags[i]] = constructor'), | 502 } |
511 js('init.leafTags[tags[i]] = false')])])])) | 503 } |
512 ]); | 504 for (i = 0; i < tags.length; i++) { |
513 | 505 init.interceptorsByTag[tags[i]] = constructor; |
514 return new jsAst.FunctionDeclaration( | 506 init.leafTags[tags[i]] = false; |
515 new jsAst.VariableDeclaration('finishClass'), | 507 } |
516 fun); | 508 } |
509 } | |
510 } | |
511 } | |
512 }''', [!nativeClasses.isEmpty, true]); | |
517 } | 513 } |
518 | 514 |
519 jsAst.Fun get finishIsolateConstructorFunction { | 515 jsAst.Fun get finishIsolateConstructorFunction { |
520 // We replace the old Isolate function with a new one that initializes | 516 // We replace the old Isolate function with a new one that initializes |
521 // all its fields with the initial (and often final) value of all globals. | 517 // all its fields with the initial (and often final) value of all globals. |
522 // | 518 // |
523 // We also copy over old values like the prototype, and the | 519 // We also copy over old values like the prototype, and the |
524 // isolateProperties themselves. | 520 // isolateProperties themselves. |
525 return js(''' | 521 return js(''' |
526 function (oldIsolate) { | 522 function (oldIsolate) { |
527 var isolateProperties = oldIsolate.${namer.isolatePropertiesName}; | 523 var isolateProperties = oldIsolate.${namer.isolatePropertiesName}; |
528 function Isolate() { | 524 function Isolate() { |
529 var hasOwnProperty = Object.prototype.hasOwnProperty; | 525 var hasOwnProperty = Object.prototype.hasOwnProperty; |
530 for (var staticName in isolateProperties) | 526 for (var staticName in isolateProperties) |
531 if (hasOwnProperty.call(isolateProperties, staticName)) | 527 if (hasOwnProperty.call(isolateProperties, staticName)) |
532 this[staticName] = isolateProperties[staticName]; | 528 this[staticName] = isolateProperties[staticName]; |
533 // Use the newly created object as prototype. In Chrome, | 529 // Use the newly created object as prototype. In Chrome, |
534 // this creates a hidden class for the object and makes | 530 // this creates a hidden class for the object and makes |
535 // sure it is fast to access. | 531 // sure it is fast to access. |
536 function ForceEfficientMap() {} | 532 function ForceEfficientMap() {} |
537 ForceEfficientMap.prototype = this; | 533 ForceEfficientMap.prototype = this; |
538 new ForceEfficientMap(); | 534 new ForceEfficientMap(); |
539 } | 535 } |
540 Isolate.prototype = oldIsolate.prototype; | 536 Isolate.prototype = oldIsolate.prototype; |
541 Isolate.prototype.constructor = Isolate; | 537 Isolate.prototype.constructor = Isolate; |
542 Isolate.${namer.isolatePropertiesName} = isolateProperties; | 538 Isolate.${namer.isolatePropertiesName} = isolateProperties; |
543 # | 539 if (#) |
544 # | 540 Isolate.$finishClassesProperty = oldIsolate.$finishClassesProperty; |
541 if (#) | |
542 Isolate.makeConstantList = oldIsolate.makeConstantList; | |
545 return Isolate; | 543 return Isolate; |
546 }''', | 544 }''', |
547 [ optional(needsDefineClass, | 545 [ needsDefineClass, hasMakeConstantList ]); |
548 js('Isolate.$finishClassesProperty =' | |
549 ' oldIsolate.$finishClassesProperty')), | |
550 optional(hasMakeConstantList, | |
551 js('Isolate.makeConstantList = oldIsolate.makeConstantList')) | |
552 ]); | |
553 } | 546 } |
554 | 547 |
555 jsAst.Fun get lazyInitializerFunction { | 548 jsAst.Fun get lazyInitializerFunction { |
556 // function(prototype, staticName, fieldName, getterName, lazyValue) { | |
557 var parameters = <String>['prototype', 'staticName', 'fieldName', | |
558 'getterName', 'lazyValue']; | |
559 return js.fun(parameters, addLazyInitializerLogic()); | |
560 } | |
561 | |
562 List addLazyInitializerLogic() { | |
563 String isolate = namer.currentIsolate; | 549 String isolate = namer.currentIsolate; |
564 String cyclicThrow = namer.isolateAccess(backend.getCyclicThrowHelper()); | 550 String cyclicThrow = namer.isolateAccess(backend.getCyclicThrowHelper()); |
565 var lazies = []; | |
566 if (backend.rememberLazies) { | |
567 lazies = [ | |
568 js.if_('!init.lazies', js('init.lazies = {}')), | |
569 js('init.lazies[fieldName] = getterName')]; | |
570 } | |
571 | 551 |
572 return lazies..addAll([ | 552 return js(''' |
573 js('var sentinelUndefined = {}'), | 553 function (prototype, staticName, fieldName, getterName, lazyValue) { |
574 js('var sentinelInProgress = {}'), | 554 if (#) { |
575 js('prototype[fieldName] = sentinelUndefined'), | 555 if (!init.lazies) init.lazies = {}; |
556 init.lazies[fieldName] = getterName; | |
557 } | |
576 | 558 |
577 // prototype[getterName] = function() | 559 var sentinelUndefined = {}; |
578 js('prototype[getterName] = #', js.fun([], [ | 560 var sentinelInProgress = {}; |
579 js('var result = $isolate[fieldName]'), | 561 prototype[fieldName] = sentinelUndefined; |
580 | 562 |
581 // try | 563 prototype[getterName] = function () { |
582 js.try_([ | 564 var result = $isolate[fieldName]; |
583 js.if_('result === sentinelUndefined', [ | 565 try { |
584 js('$isolate[fieldName] = sentinelInProgress'), | 566 if (result === sentinelUndefined) { |
567 $isolate[fieldName] = sentinelInProgress; | |
585 | 568 |
586 // try | 569 try { |
587 js.try_([ | 570 result = $isolate[fieldName] = lazyValue(); |
588 js('result = $isolate[fieldName] = lazyValue()'), | 571 } finally { |
572 // Use try-finally, not try-catch/throw as it destroys the | |
573 // stack trace. | |
574 if (result === sentinelUndefined) | |
575 if ($isolate[fieldName] === sentinelInProgress) | |
576 $isolate[fieldName] = null; | |
577 } | |
578 } else { | |
579 if (result === sentinelInProgress) | |
580 $cyclicThrow(staticName); | |
581 } | |
589 | 582 |
590 ], finallyPart: [ | 583 return result; |
591 // Use try-finally, not try-catch/throw as it destroys the | 584 } finally { |
592 // stack trace. | 585 $isolate[getterName] = function() { return this[fieldName]; }; |
593 | 586 } |
594 // if (result === sentinelUndefined) | 587 } |
595 js.if_('result === sentinelUndefined', [ | 588 } |
596 // if ($isolate[fieldName] === sentinelInProgress) | 589 ''', [backend.rememberLazies]); |
597 js.if_('$isolate[fieldName] === sentinelInProgress', [ | |
598 js('$isolate[fieldName] = null'), | |
599 ]) | |
600 ]) | |
601 ]) | |
602 ], /* else */ [ | |
603 js.if_('result === sentinelInProgress', | |
604 js('$cyclicThrow(staticName)') | |
605 ) | |
606 ]), | |
607 | |
608 // return result; | |
609 js.return_('result') | |
610 | |
611 ], finallyPart: [ | |
612 js('$isolate[getterName] = #', | |
613 js.fun([], [js.return_('this[fieldName]')])) | |
614 ]) | |
615 ])) | |
616 ]); | |
617 } | 590 } |
618 | 591 |
619 List buildDefineClassAndFinishClassFunctionsIfNecessary() { | 592 List buildDefineClassAndFinishClassFunctionsIfNecessary() { |
620 if (!needsDefineClass) return []; | 593 if (!needsDefineClass) return []; |
621 return defineClassFunction | 594 return defineClassFunction |
622 ..addAll(buildInheritFrom()) | 595 ..addAll(buildInheritFrom()) |
623 ..addAll([ | 596 ..addAll([ |
624 js('$finishClassesName = #', finishClassesFunction) | 597 js('$finishClassesName = #', finishClassesFunction) |
625 ]); | 598 ]); |
626 } | 599 } |
627 | 600 |
628 List buildLazyInitializerFunctionIfNecessary() { | 601 List buildLazyInitializerFunctionIfNecessary() { |
629 if (!needsLazyInitializer) return []; | 602 if (!needsLazyInitializer) return []; |
630 | 603 |
631 return [js('$lazyInitializerName = #', lazyInitializerFunction)]; | 604 return [js('# = #', [js(lazyInitializerName), lazyInitializerFunction])]; |
floitsch
2014/04/22 16:11:18
lazyInitializerName is a string. Do you have to ru
sra1
2014/04/23 02:33:50
It is a String, but it is not an identifier: "Isol
| |
632 } | 605 } |
633 | 606 |
634 List buildFinishIsolateConstructor() { | 607 List buildFinishIsolateConstructor() { |
635 return [ | 608 return [ |
636 js('$finishIsolateConstructorName = #', finishIsolateConstructorFunction) | 609 js('$finishIsolateConstructorName = #', finishIsolateConstructorFunction) |
637 ]; | 610 ]; |
638 } | 611 } |
639 | 612 |
640 void emitFinishIsolateConstructorInvocation(CodeBuffer buffer) { | 613 void emitFinishIsolateConstructorInvocation(CodeBuffer buffer) { |
641 String isolate = namer.isolateName; | 614 String isolate = namer.isolateName; |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
753 | 726 |
754 String namedParametersAsReflectionNames(Selector selector) { | 727 String namedParametersAsReflectionNames(Selector selector) { |
755 if (selector.getOrderedNamedArguments().isEmpty) return ''; | 728 if (selector.getOrderedNamedArguments().isEmpty) return ''; |
756 String names = selector.getOrderedNamedArguments().join(':'); | 729 String names = selector.getOrderedNamedArguments().join(':'); |
757 return ':$names'; | 730 return ':$names'; |
758 } | 731 } |
759 | 732 |
760 jsAst.FunctionDeclaration buildPrecompiledFunction() { | 733 jsAst.FunctionDeclaration buildPrecompiledFunction() { |
761 // TODO(ahe): Compute a hash code. | 734 // TODO(ahe): Compute a hash code. |
762 String name = 'dart_precompiled'; | 735 String name = 'dart_precompiled'; |
763 | 736 return js.statement(''' |
floitsch
2014/04/22 16:11:18
This should not be cached.
Write TODO, that this s
sra1
2014/04/23 02:33:50
The name is dart_precompiled, from the previous li
| |
764 precompiledFunction.add( | 737 function $name(\$collectedClasses) { |
765 js.return_( | 738 var \$desc; |
766 new jsAst.ArrayInitializer.from(precompiledConstructorNames))); | 739 #; |
767 precompiledFunction.insert(0, js(r'var $desc')); | 740 return #; |
768 return new jsAst.FunctionDeclaration( | 741 }''', [ |
769 new jsAst.VariableDeclaration(name), | 742 precompiledFunction, |
770 js.fun([r'$collectedClasses'], precompiledFunction)); | 743 new jsAst.ArrayInitializer.from(precompiledConstructorNames)]); |
771 } | 744 } |
772 | 745 |
773 void generateClass(ClassElement classElement, ClassBuilder properties) { | 746 void generateClass(ClassElement classElement, ClassBuilder properties) { |
774 compiler.withCurrentElement(classElement, () { | 747 compiler.withCurrentElement(classElement, () { |
775 classEmitter.generateClass( | 748 classEmitter.generateClass( |
776 classElement, properties, additionalProperties[classElement]); | 749 classElement, properties, additionalProperties[classElement]); |
777 }); | 750 }); |
778 } | 751 } |
779 | 752 |
780 /** | 753 /** |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
851 Iterable<VariableElement> staticNonFinalFields = | 824 Iterable<VariableElement> staticNonFinalFields = |
852 handler.getStaticNonFinalFieldsForEmission(); | 825 handler.getStaticNonFinalFieldsForEmission(); |
853 for (Element element in Elements.sortedByPosition(staticNonFinalFields)) { | 826 for (Element element in Elements.sortedByPosition(staticNonFinalFields)) { |
854 // [:interceptedNames:] is handled in [emitInterceptedNames]. | 827 // [:interceptedNames:] is handled in [emitInterceptedNames]. |
855 if (element == backend.interceptedNames) continue; | 828 if (element == backend.interceptedNames) continue; |
856 // `mapTypeToInterceptor` is handled in [emitMapTypeToInterceptor]. | 829 // `mapTypeToInterceptor` is handled in [emitMapTypeToInterceptor]. |
857 if (element == backend.mapTypeToInterceptor) continue; | 830 if (element == backend.mapTypeToInterceptor) continue; |
858 compiler.withCurrentElement(element, () { | 831 compiler.withCurrentElement(element, () { |
859 Constant initialValue = handler.getInitialValueFor(element); | 832 Constant initialValue = handler.getInitialValueFor(element); |
860 jsAst.Expression init = | 833 jsAst.Expression init = |
861 js('$isolateProperties.${namer.getNameOfGlobalField(element)} = #', | 834 js('$isolateProperties.# = #', |
862 constantEmitter.referenceInInitializationContext(initialValue)); | 835 [namer.getNameOfGlobalField(element), |
836 constantEmitter.referenceInInitializationContext(initialValue)]); | |
863 buffer.write(jsAst.prettyPrint(init, compiler)); | 837 buffer.write(jsAst.prettyPrint(init, compiler)); |
864 buffer.write('$N'); | 838 buffer.write('$N'); |
865 }); | 839 }); |
866 } | 840 } |
867 } | 841 } |
868 | 842 |
869 void emitLazilyInitializedStaticFields(CodeBuffer buffer) { | 843 void emitLazilyInitializedStaticFields(CodeBuffer buffer) { |
870 JavaScriptConstantCompiler handler = backend.constants; | 844 JavaScriptConstantCompiler handler = backend.constants; |
871 List<VariableElement> lazyFields = | 845 List<VariableElement> lazyFields = |
872 handler.getLazilyInitializedFieldsForEmission(); | 846 handler.getLazilyInitializedFieldsForEmission(); |
873 if (!lazyFields.isEmpty) { | 847 if (!lazyFields.isEmpty) { |
874 needsLazyInitializer = true; | 848 needsLazyInitializer = true; |
875 for (VariableElement element in Elements.sortedByPosition(lazyFields)) { | 849 for (VariableElement element in Elements.sortedByPosition(lazyFields)) { |
876 jsAst.Expression code = backend.generatedCode[element]; | 850 jsAst.Expression code = backend.generatedCode[element]; |
877 // The code is null if we ended up not needing the lazily | 851 // The code is null if we ended up not needing the lazily |
878 // initialized field after all because of constant folding | 852 // initialized field after all because of constant folding |
879 // before code generation. | 853 // before code generation. |
880 if (code == null) continue; | 854 if (code == null) continue; |
881 // The code only computes the initial value. We build the lazy-check | 855 // The code only computes the initial value. We build the lazy-check |
882 // here: | 856 // here: |
883 // lazyInitializer(prototype, 'name', fieldName, getterName, initial); | 857 // lazyInitializer(prototype, 'name', fieldName, getterName, initial); |
884 // The name is used for error reporting. The 'initial' must be a | 858 // The name is used for error reporting. The 'initial' must be a |
885 // closure that constructs the initial value. | 859 // closure that constructs the initial value. |
886 List<jsAst.Expression> arguments = <jsAst.Expression>[]; | |
887 arguments.add(js(isolateProperties)); | |
888 arguments.add(js.string(element.name)); | |
889 arguments.add(js.string(namer.getNameX(element))); | |
890 arguments.add(js.string(namer.getLazyInitializerName(element))); | |
891 arguments.add(code); | |
892 jsAst.Expression getter = buildLazyInitializedGetter(element); | 860 jsAst.Expression getter = buildLazyInitializedGetter(element); |
893 if (getter != null) { | 861 jsAst.Expression init = js('#(#,#,#,#,#,#)', |
894 arguments.add(getter); | 862 [js(lazyInitializerName), |
floitsch
2014/04/22 16:11:18
lazyInitializerName is a String. Why do we need to
sra1
2014/04/23 02:33:50
It is "Isolate.$lazy"
Only strings in the form of
| |
895 } | 863 js(isolateProperties), |
896 jsAst.Expression init = js(lazyInitializerName)(arguments); | 864 js.string(element.name), |
865 js.string(namer.getNameX(element)), | |
866 js.string(namer.getLazyInitializerName(element)), | |
867 code, | |
868 getter == null ? [] : [getter]]); | |
897 buffer.write(jsAst.prettyPrint(init, compiler)); | 869 buffer.write(jsAst.prettyPrint(init, compiler)); |
898 buffer.write("$N"); | 870 buffer.write("$N"); |
899 } | 871 } |
900 } | 872 } |
901 } | 873 } |
902 | 874 |
903 jsAst.Expression buildLazyInitializedGetter(VariableElement element) { | 875 jsAst.Expression buildLazyInitializedGetter(VariableElement element) { |
904 // Nothing to do, the 'lazy' function will create the getter. | 876 // Nothing to do, the 'lazy' function will create the getter. |
905 return null; | 877 return null; |
906 } | 878 } |
(...skipping 14 matching lines...) Expand all Loading... | |
921 && constantUnit == null) { | 893 && constantUnit == null) { |
922 // The back-end introduces some constants, like "InterceptorConstant" or | 894 // The back-end introduces some constants, like "InterceptorConstant" or |
923 // some list constants. They are emitted in the main output-unit, and | 895 // some list constants. They are emitted in the main output-unit, and |
924 // ignored otherwise. | 896 // ignored otherwise. |
925 // TODO(sigurdm): We should track those constants. | 897 // TODO(sigurdm): We should track those constants. |
926 continue; | 898 continue; |
927 } | 899 } |
928 | 900 |
929 String name = namer.constantName(constant); | 901 String name = namer.constantName(constant); |
930 if (constant.isList) emitMakeConstantListIfNotEmitted(buffer); | 902 if (constant.isList) emitMakeConstantListIfNotEmitted(buffer); |
931 jsAst.Expression init = js( | 903 jsAst.Expression init = js('#.# = #', |
932 '${namer.globalObjectForConstant(constant)}.$name = #', | 904 [namer.globalObjectForConstant(constant), name, |
933 constantInitializerExpression(constant)); | 905 constantInitializerExpression(constant)]); |
934 buffer.write(jsAst.prettyPrint(init, compiler)); | 906 buffer.write(jsAst.prettyPrint(init, compiler)); |
935 buffer.write('$N'); | 907 buffer.write('$N'); |
936 } | 908 } |
937 } | 909 } |
938 | 910 |
939 bool isConstantInlinedOrAlreadyEmitted(Constant constant) { | 911 bool isConstantInlinedOrAlreadyEmitted(Constant constant) { |
940 if (constant.isFunction) return true; // Already emitted. | 912 if (constant.isFunction) return true; // Already emitted. |
941 if (constant.isPrimitive) return true; // Inlined. | 913 if (constant.isPrimitive) return true; // Inlined. |
942 if (constant.isDummy) return true; // Inlined. | 914 if (constant.isDummy) return true; // Inlined. |
943 // The name is null when the constant is already a JS constant. | 915 // The name is null when the constant is already a JS constant. |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1187 } else { | 1159 } else { |
1188 outputClassLists.putIfAbsent( | 1160 outputClassLists.putIfAbsent( |
1189 compiler.deferredLoadTask.outputUnitForElement(element), | 1161 compiler.deferredLoadTask.outputUnitForElement(element), |
1190 () => new List<ClassElement>()) | 1162 () => new List<ClassElement>()) |
1191 .add(element); | 1163 .add(element); |
1192 } | 1164 } |
1193 } | 1165 } |
1194 } | 1166 } |
1195 | 1167 |
1196 void emitInitFunction(CodeBuffer buffer) { | 1168 void emitInitFunction(CodeBuffer buffer) { |
1197 jsAst.Fun fun = js.fun([], [ | 1169 jsAst.FunctionDeclaration decl = js.statement(''' |
1198 js('$isolateProperties = {}'), | 1170 function init() { |
1199 ] | 1171 $isolateProperties = {}; |
1200 ..addAll(buildDefineClassAndFinishClassFunctionsIfNecessary()) | 1172 #; #; #; |
1201 ..addAll(buildLazyInitializerFunctionIfNecessary()) | 1173 }''', [ |
1202 ..addAll(buildFinishIsolateConstructor()) | 1174 buildDefineClassAndFinishClassFunctionsIfNecessary(), |
1203 ); | 1175 buildLazyInitializerFunctionIfNecessary(), |
1204 jsAst.FunctionDeclaration decl = new jsAst.FunctionDeclaration( | 1176 buildFinishIsolateConstructor()]); |
1205 new jsAst.VariableDeclaration('init'), fun); | 1177 |
1206 buffer.write(jsAst.prettyPrint(decl, compiler).getText()); | 1178 buffer.write(jsAst.prettyPrint(decl, compiler).getText()); |
1207 if (compiler.enableMinification) buffer.write('\n'); | 1179 if (compiler.enableMinification) buffer.write('\n'); |
1208 } | 1180 } |
1209 | 1181 |
1210 void emitConvertToFastObjectFunction() { | 1182 void emitConvertToFastObjectFunction() { |
1211 // Create an instance that uses 'properties' as prototype. This should make | 1183 // Create an instance that uses 'properties' as prototype. This should make |
1212 // 'properties' a fast object. | 1184 // 'properties' a fast object. |
1213 mainBuffer.add(r'''function convertToFastObject(properties) { | 1185 mainBuffer.add(r'''function convertToFastObject(properties) { |
1214 function MyClass() {}; | 1186 function MyClass() {}; |
1215 MyClass.prototype = properties; | 1187 MyClass.prototype = properties; |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1382 var keys = mangledFieldNames.keys.toList(); | 1354 var keys = mangledFieldNames.keys.toList(); |
1383 keys.sort(); | 1355 keys.sort(); |
1384 var properties = []; | 1356 var properties = []; |
1385 for (String key in keys) { | 1357 for (String key in keys) { |
1386 var value = js.string('${mangledFieldNames[key]}'); | 1358 var value = js.string('${mangledFieldNames[key]}'); |
1387 properties.add(new jsAst.Property(js.string(key), value)); | 1359 properties.add(new jsAst.Property(js.string(key), value)); |
1388 } | 1360 } |
1389 var map = new jsAst.ObjectInitializer(properties); | 1361 var map = new jsAst.ObjectInitializer(properties); |
1390 mainBuffer.write( | 1362 mainBuffer.write( |
1391 jsAst.prettyPrint( | 1363 jsAst.prettyPrint( |
1392 js('init.mangledNames = #', map).toStatement(), compiler)); | 1364 js.statement('init.mangledNames = #', map), compiler)); |
1393 if (compiler.enableMinification) { | 1365 if (compiler.enableMinification) { |
1394 mainBuffer.write(';'); | 1366 mainBuffer.write(';'); |
1395 } | 1367 } |
1396 } | 1368 } |
1397 if (!mangledGlobalFieldNames.isEmpty) { | 1369 if (!mangledGlobalFieldNames.isEmpty) { |
1398 var keys = mangledGlobalFieldNames.keys.toList(); | 1370 var keys = mangledGlobalFieldNames.keys.toList(); |
1399 keys.sort(); | 1371 keys.sort(); |
1400 var properties = []; | 1372 var properties = []; |
1401 for (String key in keys) { | 1373 for (String key in keys) { |
1402 var value = js.string('${mangledGlobalFieldNames[key]}'); | 1374 var value = js.string('${mangledGlobalFieldNames[key]}'); |
1403 properties.add(new jsAst.Property(js.string(key), value)); | 1375 properties.add(new jsAst.Property(js.string(key), value)); |
1404 } | 1376 } |
1405 var map = new jsAst.ObjectInitializer(properties); | 1377 var map = new jsAst.ObjectInitializer(properties); |
1406 mainBuffer.write( | 1378 mainBuffer.write( |
1407 jsAst.prettyPrint( | 1379 jsAst.prettyPrint( |
1408 js('init.mangledGlobalNames = #', map).toStatement(), | 1380 js.statement('init.mangledGlobalNames = #', map), |
1409 compiler)); | 1381 compiler)); |
1410 if (compiler.enableMinification) { | 1382 if (compiler.enableMinification) { |
1411 mainBuffer.write(';'); | 1383 mainBuffer.write(';'); |
1412 } | 1384 } |
1413 } | 1385 } |
1414 mainBuffer | 1386 mainBuffer |
1415 ..write('(') | 1387 ..write('(') |
1416 ..write( | 1388 ..write( |
1417 jsAst.prettyPrint( | 1389 jsAst.prettyPrint( |
1418 getReflectionDataParser(classesCollector, backend), | 1390 getReflectionDataParser(classesCollector, backend), |
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1729 String sourceMap = sourceMapBuilder.build(); | 1701 String sourceMap = sourceMapBuilder.build(); |
1730 compiler.outputProvider(name, 'js.map') | 1702 compiler.outputProvider(name, 'js.map') |
1731 ..add(sourceMap) | 1703 ..add(sourceMap) |
1732 ..close(); | 1704 ..close(); |
1733 } | 1705 } |
1734 | 1706 |
1735 void registerReadTypeVariable(TypeVariableElement element) { | 1707 void registerReadTypeVariable(TypeVariableElement element) { |
1736 readTypeVariables.add(element); | 1708 readTypeVariables.add(element); |
1737 } | 1709 } |
1738 } | 1710 } |
OLD | NEW |