| 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 class NativeEmitter { | 7 class NativeEmitter { |
| 8 | 8 |
| 9 final Map<Element, ClassBuilder> cachedBuilders; | 9 final Map<Element, ClassBuilder> cachedBuilders; |
| 10 | 10 |
| (...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 415 if (emitterTask.compiler.enableMinification) { | 415 if (emitterTask.compiler.enableMinification) { |
| 416 targetOutput.add(';'); | 416 targetOutput.add(';'); |
| 417 } | 417 } |
| 418 targetOutput.addBuffer(jsAst.prettyPrint( | 418 targetOutput.addBuffer(jsAst.prettyPrint( |
| 419 new jsAst.ExpressionStatement(init), compiler)); | 419 new jsAst.ExpressionStatement(init), compiler)); |
| 420 targetOutput.add('\n'); | 420 targetOutput.add('\n'); |
| 421 } | 421 } |
| 422 | 422 |
| 423 targetOutput.add('\n'); | 423 targetOutput.add('\n'); |
| 424 } | 424 } |
| 425 |
| 426 /// Returns a JavaScript template that fills the embedded globals referenced |
| 427 /// by [interceptorsByTagAccess] and [leafTagsAccess]. |
| 428 /// |
| 429 /// This code must be invoked for every class that has a native info before |
| 430 /// the program starts. |
| 431 /// |
| 432 /// The [infoAccess] parameter must evaluate to an expression that contains |
| 433 /// the info (as a JavaScript string). |
| 434 /// |
| 435 /// The [constructorAccess] parameter must evaluate to an expression that |
| 436 /// contains the constructor of the class. The constructor's prototype must |
| 437 /// be set up. |
| 438 /// |
| 439 /// The [subclassReadGenerator] function must evaluate to a JS expression |
| 440 /// that returns a reference to the constructor (with evaluated prototype) |
| 441 /// of the given JS expression. |
| 442 /// |
| 443 /// The [interceptorsByTagAccess] must point to the embedded global |
| 444 /// [embeddedNames.INTERCEPTORS_BY_TAG] and must be initialized with an empty |
| 445 /// JS Object (used as a map). |
| 446 /// |
| 447 /// Similarly, the [leafTagsAccess] must point to the embedded global |
| 448 /// [embeddedNames.LEAF_TAGS] and must be initialized with an empty JS Object |
| 449 /// (used as a map). |
| 450 /// |
| 451 /// Both variables are passed in (instead of creating the access here) to |
| 452 /// make sure the caller is aware of these globals. |
| 453 jsAst.Statement buildNativeInfoHandler( |
| 454 jsAst.Expression infoAccess, |
| 455 jsAst.Expression constructorAccess, |
| 456 jsAst.Expression subclassReadGenerator(jsAst.Expression subclass), |
| 457 jsAst.Expression interceptorsByTagAccess, |
| 458 jsAst.Expression leafTagsAccess) { |
| 459 jsAst.Expression subclassRead = |
| 460 subclassReadGenerator(js('subclasses[i]', [])); |
| 461 return js.statement(''' |
| 462 // The native info looks like this: |
| 463 // |
| 464 // HtmlElement: { |
| 465 // "%": "HTMLDivElement|HTMLAnchorElement;HTMLElement;FancyButton" |
| 466 // |
| 467 // The first two semicolon-separated parts contain dispatch tags, the |
| 468 // third contains the JavaScript names for classes. |
| 469 // |
| 470 // The tags indicate that JavaScript objects with the dispatch tags |
| 471 // (usually constructor names) HTMLDivElement, HTMLAnchorElement and |
| 472 // HTMLElement all map to the Dart native class named HtmlElement. |
| 473 // The first set is for effective leaf nodes in the hierarchy, the |
| 474 // second set is non-leaf nodes. |
| 475 // |
| 476 // The third part contains the JavaScript names of Dart classes that |
| 477 // extend the native class. Here, FancyButton extends HtmlElement, so |
| 478 // the runtime needs to know that window.HTMLElement.prototype is the |
| 479 // prototype that needs to be extended in creating the custom element. |
| 480 // |
| 481 // The information is used to build tables referenced by |
| 482 // getNativeInterceptor and custom element support. |
| 483 { |
| 484 var nativeSpec = #info.split(";"); |
| 485 if (nativeSpec[0]) { |
| 486 var tags = nativeSpec[0].split("|"); |
| 487 for (var i = 0; i < tags.length; i++) { |
| 488 #interceptorsByTagAccess[tags[i]] = #constructor; |
| 489 #leafTagsAccess[tags[i]] = true; |
| 490 } |
| 491 } |
| 492 if (nativeSpec[1]) { |
| 493 tags = nativeSpec[1].split("|"); |
| 494 if (#allowNativesSubclassing) { |
| 495 if (nativeSpec[2]) { |
| 496 var subclasses = nativeSpec[2].split("|"); |
| 497 for (var i = 0; i < subclasses.length; i++) { |
| 498 var subclass = #subclassRead; |
| 499 subclass.#nativeSuperclassTagName = tags[0]; |
| 500 } |
| 501 } |
| 502 for (i = 0; i < tags.length; i++) { |
| 503 #interceptorsByTagAccess[tags[i]] = #constructor; |
| 504 #leafTagsAccess[tags[i]] = false; |
| 505 } |
| 506 } |
| 507 } |
| 508 } |
| 509 ''', {'info': infoAccess, |
| 510 'constructor': constructorAccess, |
| 511 'subclassRead': subclassRead, |
| 512 'interceptorsByTagAccess': interceptorsByTagAccess, |
| 513 'leafTagsAccess': leafTagsAccess, |
| 514 'nativeSuperclassTagName': embeddedNames.NATIVE_SUPERCLASS_TAG_NAME, |
| 515 'allowNativesSubclassing': true}); |
| 516 } |
| 425 } | 517 } |
| OLD | NEW |