| Index: pkg/compiler/lib/src/js_emitter/native_emitter.dart
|
| diff --git a/pkg/compiler/lib/src/js_emitter/native_emitter.dart b/pkg/compiler/lib/src/js_emitter/native_emitter.dart
|
| index b53c911a279667f15c954da266b59b361c3e8657..54d58e1fffd9feaf74a003611c7c3b4a27787b68 100644
|
| --- a/pkg/compiler/lib/src/js_emitter/native_emitter.dart
|
| +++ b/pkg/compiler/lib/src/js_emitter/native_emitter.dart
|
| @@ -422,4 +422,96 @@ class NativeEmitter {
|
|
|
| targetOutput.add('\n');
|
| }
|
| +
|
| + /// Returns a JavaScript template that fills the embedded globals referenced
|
| + /// by [interceptorsByTagAccess] and [leafTagsAccess].
|
| + ///
|
| + /// This code must be invoked for every class that has a native info before
|
| + /// the program starts.
|
| + ///
|
| + /// The [infoAccess] parameter must evaluate to an expression that contains
|
| + /// the info (as a JavaScript string).
|
| + ///
|
| + /// The [constructorAccess] parameter must evaluate to an expression that
|
| + /// contains the constructor of the class. The constructor's prototype must
|
| + /// be set up.
|
| + ///
|
| + /// The [subclassReadGenerator] function must evaluate to a JS expression
|
| + /// that returns a reference to the constructor (with evaluated prototype)
|
| + /// of the given JS expression.
|
| + ///
|
| + /// The [interceptorsByTagAccess] must point to the embedded global
|
| + /// [embeddedNames.INTERCEPTORS_BY_TAG] and must be initialized with an empty
|
| + /// JS Object (used as a map).
|
| + ///
|
| + /// Similarly, the [leafTagsAccess] must point to the embedded global
|
| + /// [embeddedNames.LEAF_TAGS] and must be initialized with an empty JS Object
|
| + /// (used as a map).
|
| + ///
|
| + /// Both variables are passed in (instead of creating the access here) to
|
| + /// make sure the caller is aware of these globals.
|
| + jsAst.Statement buildNativeInfoHandler(
|
| + jsAst.Expression infoAccess,
|
| + jsAst.Expression constructorAccess,
|
| + jsAst.Expression subclassReadGenerator(jsAst.Expression subclass),
|
| + jsAst.Expression interceptorsByTagAccess,
|
| + jsAst.Expression leafTagsAccess) {
|
| + jsAst.Expression subclassRead =
|
| + subclassReadGenerator(js('subclasses[i]', []));
|
| + return js.statement('''
|
| + // The native info looks like this:
|
| + //
|
| + // HtmlElement: {
|
| + // "%": "HTMLDivElement|HTMLAnchorElement;HTMLElement;FancyButton"
|
| + //
|
| + // The first two semicolon-separated parts contain dispatch tags, the
|
| + // third contains the JavaScript names for classes.
|
| + //
|
| + // The tags indicate that JavaScript objects with the dispatch tags
|
| + // (usually constructor names) HTMLDivElement, HTMLAnchorElement and
|
| + // HTMLElement all map to the Dart native class named HtmlElement.
|
| + // The first set is for effective leaf nodes in the hierarchy, the
|
| + // second set is non-leaf nodes.
|
| + //
|
| + // The third part contains the JavaScript names of Dart classes that
|
| + // extend the native class. Here, FancyButton extends HtmlElement, so
|
| + // the runtime needs to know that window.HTMLElement.prototype is the
|
| + // prototype that needs to be extended in creating the custom element.
|
| + //
|
| + // The information is used to build tables referenced by
|
| + // getNativeInterceptor and custom element support.
|
| + {
|
| + var nativeSpec = #info.split(";");
|
| + if (nativeSpec[0]) {
|
| + var tags = nativeSpec[0].split("|");
|
| + for (var i = 0; i < tags.length; i++) {
|
| + #interceptorsByTagAccess[tags[i]] = #constructor;
|
| + #leafTagsAccess[tags[i]] = true;
|
| + }
|
| + }
|
| + if (nativeSpec[1]) {
|
| + tags = nativeSpec[1].split("|");
|
| + if (#allowNativesSubclassing) {
|
| + if (nativeSpec[2]) {
|
| + var subclasses = nativeSpec[2].split("|");
|
| + for (var i = 0; i < subclasses.length; i++) {
|
| + var subclass = #subclassRead;
|
| + subclass.#nativeSuperclassTagName = tags[0];
|
| + }
|
| + }
|
| + for (i = 0; i < tags.length; i++) {
|
| + #interceptorsByTagAccess[tags[i]] = #constructor;
|
| + #leafTagsAccess[tags[i]] = false;
|
| + }
|
| + }
|
| + }
|
| + }
|
| + ''', {'info': infoAccess,
|
| + 'constructor': constructorAccess,
|
| + 'subclassRead': subclassRead,
|
| + 'interceptorsByTagAccess': interceptorsByTagAccess,
|
| + 'leafTagsAccess': leafTagsAccess,
|
| + 'nativeSuperclassTagName': embeddedNames.NATIVE_SUPERCLASS_TAG_NAME,
|
| + 'allowNativesSubclassing': true});
|
| + }
|
| }
|
|
|