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 part of dart2js.js_emitter; | 5 part of dart2js.js_emitter; |
6 | 6 |
7 | 7 |
8 class OldEmitter implements Emitter { | 8 class OldEmitter implements Emitter { |
9 final Compiler compiler; | 9 final Compiler compiler; |
10 final CodeEmitterTask task; | 10 final CodeEmitterTask task; |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
245 accessors.push(property + "\$reflectable(" + fn + ");\\n"); | 245 accessors.push(property + "\$reflectable(" + fn + ");\\n"); |
246 else | 246 else |
247 accessors.push(property + fn + ";\\n"); | 247 accessors.push(property + fn + ";\\n"); |
248 } | 248 } |
249 } | 249 } |
250 | 250 |
251 return field; | 251 return field; |
252 }'''); | 252 }'''); |
253 } | 253 } |
254 | 254 |
255 List get defineClassFunction { | 255 List<jsAst.Node> get defineClassFunction { |
256 // First the class name, then the field names in an array and the members | 256 // First the class name, then the field names in an array and the members |
257 // (inside an Object literal). | 257 // (inside an Object literal). |
258 // The caller can also pass in the constructor as a function if needed. | 258 // The caller can also pass in the constructor as a function if needed. |
259 // | 259 // |
260 // Example: | 260 // Example: |
261 // defineClass("A", ["x", "y"], { | 261 // defineClass("A", ["x", "y"], { |
262 // foo$1: function(y) { | 262 // foo$1: function(y) { |
263 // print(this.x + y); | 263 // print(this.x + y); |
264 // }, | 264 // }, |
265 // bar$2: function(t, v) { | 265 // bar$2: function(t, v) { |
266 // this.x = t - v; | 266 // this.x = t - v; |
267 // }, | 267 // }, |
268 // }); | 268 // }); |
269 | 269 |
270 var defineClass = js('''function(name, fields) { | 270 bool hasIsolateSupport = compiler.hasIsolateSupport; |
| 271 String fieldNamesProperty = r"$__fields__"; |
| 272 |
| 273 jsAst.Expression defineClass = js('''function(name, fields) { |
271 var accessors = []; | 274 var accessors = []; |
272 | 275 |
273 var str = "function " + name + "("; | 276 var str = "function " + name + "("; |
274 var body = ""; | 277 var body = ""; |
| 278 if (#hasIsolateSupport) { var fieldNames = ""; } |
275 | 279 |
276 for (var i = 0; i < fields.length; i++) { | 280 for (var i = 0; i < fields.length; i++) { |
277 if(i != 0) str += ", "; | 281 if(i != 0) str += ", "; |
278 | 282 |
279 var field = generateAccessor(fields[i], accessors, name); | 283 var field = generateAccessor(fields[i], accessors, name); |
| 284 if (#hasIsolateSupport) { fieldNames += "'" + field + "',"; } |
280 var parameter = "parameter_" + field; | 285 var parameter = "parameter_" + field; |
281 str += parameter; | 286 str += parameter; |
282 body += ("this." + field + " = " + parameter + ";\\n"); | 287 body += ("this." + field + " = " + parameter + ";\\n"); |
283 } | 288 } |
284 str += ") {\\n" + body + "}\\n"; | 289 str += ") {\\n" + body + "}\\n"; |
285 str += name + ".builtin\$cls=\\"" + name + "\\";\\n"; | 290 str += name + ".builtin\$cls=\\"" + name + "\\";\\n"; |
286 str += "\$desc=\$collectedClasses." + name + ";\\n"; | 291 str += "\$desc=\$collectedClasses." + name + ";\\n"; |
287 str += "if(\$desc instanceof Array) \$desc = \$desc[1];\\n"; | 292 str += "if(\$desc instanceof Array) \$desc = \$desc[1];\\n"; |
288 str += name + ".prototype = \$desc;\\n"; | 293 str += name + ".prototype = \$desc;\\n"; |
289 if (typeof defineClass.name != "string") { | 294 if (typeof defineClass.name != "string") { |
290 str += name + ".name=\\"" + name + "\\";\\n"; | 295 str += name + ".name=\\"" + name + "\\";\\n"; |
291 } | 296 } |
| 297 if (#hasIsolateSupport) { |
| 298 str += name + ".$fieldNamesProperty=[" + fieldNames + "];\\n"; |
| 299 } |
292 str += accessors.join(""); | 300 str += accessors.join(""); |
293 | 301 |
294 return str; | 302 return str; |
295 }'''); | 303 }''', { 'hasIsolateSupport': hasIsolateSupport }); |
| 304 |
296 // Declare a function called "generateAccessor". This is used in | 305 // Declare a function called "generateAccessor". This is used in |
297 // defineClassFunction (it's a local declaration in init()). | 306 // defineClassFunction (it's a local declaration in init()). |
298 List<jsAst.Node> saveDefineClass = []; | 307 List result = <jsAst.Node>[ |
299 if (compiler.hasIncrementalSupport) { | |
300 saveDefineClass.add( | |
301 js(r'self.$dart_unsafe_eval.defineClass = defineClass')); | |
302 } | |
303 return [ | |
304 generateAccessorFunction, | 308 generateAccessorFunction, |
305 js('$generateAccessorHolder = generateAccessor'), | 309 js('$generateAccessorHolder = generateAccessor'), |
306 new jsAst.FunctionDeclaration( | 310 new jsAst.FunctionDeclaration( |
307 new jsAst.VariableDeclaration('defineClass'), defineClass) ] | 311 new jsAst.VariableDeclaration('defineClass'), defineClass) ]; |
308 ..addAll(saveDefineClass); | 312 |
| 313 if (compiler.hasIncrementalSupport) { |
| 314 result.add( |
| 315 js(r'self.$dart_unsafe_eval.defineClass = defineClass')); |
| 316 } |
| 317 |
| 318 if (hasIsolateSupport) { |
| 319 jsAst.Expression classIdExtractorAccess = |
| 320 generateEmbeddedGlobalAccess(embeddedNames.CLASS_ID_EXTRACTOR); |
| 321 var classIdExtractorAssignment = |
| 322 js('# = function(o) { return o.constructor.name; }', |
| 323 classIdExtractorAccess); |
| 324 |
| 325 jsAst.Expression classFieldsExtractorAccess = |
| 326 generateEmbeddedGlobalAccess(embeddedNames.CLASS_FIELDS_EXTRACTOR); |
| 327 var classFieldsExtractorAssignment = js(''' |
| 328 # = function(o) { |
| 329 var fieldNames = o.constructor.$fieldNamesProperty; |
| 330 if (!fieldNames) return []; // TODO(floitsch): do something else here. |
| 331 var result = []; |
| 332 result.length = fieldNames.length; |
| 333 for (var i = 0; i < fieldNames.length; i++) { |
| 334 result[i] = o[fieldNames[i]]; |
| 335 } |
| 336 return result; |
| 337 }''', classFieldsExtractorAccess); |
| 338 |
| 339 jsAst.Expression instanceFromClassIdAccess = |
| 340 generateEmbeddedGlobalAccess(embeddedNames.INSTANCE_FROM_CLASS_ID); |
| 341 jsAst.Expression allClassesAccess = |
| 342 generateEmbeddedGlobalAccess(embeddedNames.ALL_CLASSES); |
| 343 var instanceFromClassIdAssignment = |
| 344 js('# = function(name) { return new #[name](); }', |
| 345 [instanceFromClassIdAccess, allClassesAccess]); |
| 346 |
| 347 jsAst.Expression initializeEmptyInstanceAccess = |
| 348 generateEmbeddedGlobalAccess(embeddedNames.INITIALIZE_EMPTY_INSTANCE); |
| 349 var initializeEmptyInstanceAssignment = js(''' |
| 350 # = function(name, o, fields) { |
| 351 #[name].apply(o, fields); |
| 352 return o; |
| 353 }''', [ initializeEmptyInstanceAccess, allClassesAccess ]); |
| 354 |
| 355 result.addAll([classIdExtractorAssignment, |
| 356 classFieldsExtractorAssignment, |
| 357 instanceFromClassIdAssignment, |
| 358 initializeEmptyInstanceAssignment]); |
| 359 } |
| 360 |
| 361 return result; |
309 } | 362 } |
310 | 363 |
311 /** Needs defineClass to be defined. */ | 364 /** Needs defineClass to be defined. */ |
312 jsAst.Expression buildInheritFrom() { | 365 jsAst.Expression buildInheritFrom() { |
313 jsAst.Expression result = js(r''' | 366 jsAst.Expression result = js(r''' |
314 function() { | 367 function() { |
315 function tmp() {} | 368 function tmp() {} |
316 var hasOwnProperty = Object.prototype.hasOwnProperty; | 369 var hasOwnProperty = Object.prototype.hasOwnProperty; |
317 return function (constructor, superConstructor) { | 370 return function (constructor, superConstructor) { |
318 tmp.prototype = superConstructor.prototype; | 371 tmp.prototype = superConstructor.prototype; |
(...skipping 1691 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2010 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { | 2063 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { |
2011 if (element.isInstanceMember) { | 2064 if (element.isInstanceMember) { |
2012 cachedClassBuilders.remove(element.enclosingClass); | 2065 cachedClassBuilders.remove(element.enclosingClass); |
2013 | 2066 |
2014 nativeEmitter.cachedBuilders.remove(element.enclosingClass); | 2067 nativeEmitter.cachedBuilders.remove(element.enclosingClass); |
2015 | 2068 |
2016 } | 2069 } |
2017 } | 2070 } |
2018 } | 2071 } |
2019 } | 2072 } |
OLD | NEW |