Index: sdk/lib/_internal/compiler/js_lib/native_helper.dart |
diff --git a/sdk/lib/_internal/compiler/js_lib/native_helper.dart b/sdk/lib/_internal/compiler/js_lib/native_helper.dart |
deleted file mode 100644 |
index e87ace9432b98bbb18bb548c36ef3a807e262783..0000000000000000000000000000000000000000 |
--- a/sdk/lib/_internal/compiler/js_lib/native_helper.dart |
+++ /dev/null |
@@ -1,655 +0,0 @@ |
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
-// for details. All rights reserved. Use of this source code is governed by a |
-// BSD-style license that can be found in the LICENSE file. |
- |
-part of _js_helper; |
- |
- |
-// TODO(ngeoffray): stop using this method once our optimizers can |
-// change str1.contains(str2) into str1.indexOf(str2) != -1. |
-bool contains(String userAgent, String name) { |
- return JS('int', '#.indexOf(#)', userAgent, name) != -1; |
-} |
- |
-int arrayLength(List array) { |
- return JS('int', '#.length', array); |
-} |
- |
-arrayGet(List array, int index) { |
- return JS('var', '#[#]', array, index); |
-} |
- |
-void arraySet(List array, int index, var value) { |
- JS('var', '#[#] = #', array, index, value); |
-} |
- |
-propertyGet(var object, String property) { |
- return JS('var', '#[#]', object, property); |
-} |
- |
-bool callHasOwnProperty(var function, var object, String property) { |
- return JS('bool', '#.call(#, #)', function, object, property); |
-} |
- |
-void propertySet(var object, String property, var value) { |
- JS('var', '#[#] = #', object, property, value); |
-} |
- |
-getPropertyFromPrototype(var object, String name) { |
- return JS('var', 'Object.getPrototypeOf(#)[#]', object, name); |
-} |
- |
-/** |
- * Returns a String tag identifying the type of the native object, or `null`. |
- * The tag is not the name of the type, but usually the name of the JavaScript |
- * constructor function. Initialized by [initHooks]. |
- */ |
-Function getTagFunction; |
- |
-/** |
- * If a lookup via [getTagFunction] on an object [object] that has [tag] fails, |
- * this function is called to provide an alternate tag. This allows us to fail |
- * gracefully if we can make a good guess, for example, when browsers add novel |
- * kinds of HTMLElement that we have never heard of. Initialized by |
- * [initHooks]. |
- */ |
-Function alternateTagFunction; |
- |
-/** |
- * Returns the prototype for the JavaScript constructor named by an input tag. |
- * Returns `null` if there is no such constructor, or if pre-patching of the |
- * constructor is to be avoided. Initialized by [initHooks]. |
- */ |
-Function prototypeForTagFunction; |
- |
- |
-String toStringForNativeObject(var obj) { |
- // TODO(sra): Is this code dead? |
- // [getTagFunction] might be uninitialized, but in usual usage, toString has |
- // been called via an interceptor and initialized it. |
- String name = getTagFunction == null |
- ? '<Unknown>' |
- : JS('String', '#', getTagFunction(obj)); |
- return 'Instance of $name'; |
-} |
- |
-int hashCodeForNativeObject(object) => Primitives.objectHashCode(object); |
- |
-/** |
- * Sets a JavaScript property on an object. |
- */ |
-void defineProperty(var obj, String property, var value) { |
- JS('void', |
- 'Object.defineProperty(#, #, ' |
- '{value: #, enumerable: false, writable: true, configurable: true})', |
- obj, |
- property, |
- value); |
-} |
- |
- |
-// Is [obj] an instance of a Dart-defined class? |
-bool isDartObject(obj) { |
- // Some of the extra parens here are necessary. |
- return JS('bool', '((#) instanceof (#))', |
- obj, |
- JS_BUILTIN('depends:none;effects:none;', |
- JsBuiltin.dartObjectConstructor)); |
-} |
- |
-/** |
- * A JavaScript object mapping tags to the constructors of interceptors. |
- * This is a JavaScript object with no prototype. |
- * |
- * Example: 'HTMLImageElement' maps to the ImageElement class constructor. |
- */ |
-get interceptorsByTag => JS_EMBEDDED_GLOBAL('=Object', INTERCEPTORS_BY_TAG); |
- |
-/** |
- * A JavaScript object mapping tags to `true` or `false`. |
- * |
- * Example: 'HTMLImageElement' maps to `true` since, as there are no subclasses |
- * of ImageElement, it is a leaf class in the native class hierarchy. |
- */ |
-get leafTags => JS_EMBEDDED_GLOBAL('=Object', LEAF_TAGS); |
- |
-String findDispatchTagForInterceptorClass(interceptorClassConstructor) { |
- return JS('', r'#.#', |
- interceptorClassConstructor, NATIVE_SUPERCLASS_TAG_NAME); |
-} |
- |
-/** |
- * Cache of dispatch records for instances. This is a JavaScript object used as |
- * a map. Keys are instance tags, e.g. "!SomeThing". The cache permits the |
- * sharing of one dispatch record between multiple instances. |
- */ |
-var dispatchRecordsForInstanceTags; |
- |
-/** |
- * Cache of interceptors indexed by uncacheable tags, e.g. "~SomeThing". |
- * This is a JavaScript object used as a map. |
- */ |
-var interceptorsForUncacheableTags; |
- |
- |
-lookupInterceptor(String tag) { |
- return propertyGet(interceptorsByTag, tag); |
-} |
- |
- |
-// Dispatch tag marks are optional prefixes for a dispatch tag that direct how |
-// the interceptor for the tag may be cached. |
- |
-/// No caching permitted. |
-const UNCACHED_MARK = '~'; |
- |
-/// Dispatch record must be cached per instance |
-const INSTANCE_CACHED_MARK = '!'; |
- |
-/// Dispatch record is cached on immediate prototype. |
-const LEAF_MARK = '-'; |
- |
-/// Dispatch record is cached on immediate prototype with a prototype |
-/// verification to prevent the interceptor being associated with a subclass |
-/// before a dispatch record is cached on the subclass. |
-const INTERIOR_MARK = '+'; |
- |
-/// A 'discriminator' function is to be used. TBD. |
-const DISCRIMINATED_MARK = '*'; |
- |
- |
-/** |
- * Returns the interceptor for a native object, or returns `null` if not found. |
- * |
- * A dispatch record is cached according to the specification of the dispatch |
- * tag for [obj]. |
- */ |
-lookupAndCacheInterceptor(obj) { |
- assert(!isDartObject(obj)); |
- String tag = getTagFunction(obj); |
- |
- // Fast path for instance (and uncached) tags because the lookup is repeated |
- // for each instance (or getInterceptor call). |
- var record = propertyGet(dispatchRecordsForInstanceTags, tag); |
- if (record != null) return patchInstance(obj, record); |
- var interceptor = propertyGet(interceptorsForUncacheableTags, tag); |
- if (interceptor != null) return interceptor; |
- |
- // This lookup works for derived dispatch tags because we add them all in |
- // [initNativeDispatch]. |
- var interceptorClass = lookupInterceptor(tag); |
- if (interceptorClass == null) { |
- tag = alternateTagFunction(obj, tag); |
- if (tag != null) { |
- // Fast path for instance and uncached tags again. |
- record = propertyGet(dispatchRecordsForInstanceTags, tag); |
- if (record != null) return patchInstance(obj, record); |
- interceptor = propertyGet(interceptorsForUncacheableTags, tag); |
- if (interceptor != null) return interceptor; |
- |
- interceptorClass = lookupInterceptor(tag); |
- } |
- } |
- |
- if (interceptorClass == null) { |
- // This object is not known to Dart. There could be several reasons for |
- // that, including (but not limited to): |
- // |
- // * A bug in native code (hopefully this is caught during development). |
- // * An unknown DOM object encountered. |
- // * JavaScript code running in an unexpected context. For example, on |
- // node.js. |
- return null; |
- } |
- |
- interceptor = JS('', '#.prototype', interceptorClass); |
- |
- var mark = JS('String|Null', '#[0]', tag); |
- |
- if (mark == INSTANCE_CACHED_MARK) { |
- record = makeLeafDispatchRecord(interceptor); |
- propertySet(dispatchRecordsForInstanceTags, tag, record); |
- return patchInstance(obj, record); |
- } |
- |
- if (mark == UNCACHED_MARK) { |
- propertySet(interceptorsForUncacheableTags, tag, interceptor); |
- return interceptor; |
- } |
- |
- if (mark == LEAF_MARK) { |
- return patchProto(obj, makeLeafDispatchRecord(interceptor)); |
- } |
- |
- if (mark == INTERIOR_MARK) { |
- return patchInteriorProto(obj, interceptor); |
- } |
- |
- if (mark == DISCRIMINATED_MARK) { |
- // TODO(sra): Use discriminator of tag. |
- throw new UnimplementedError(tag); |
- } |
- |
- // [tag] was not explicitly an interior or leaf tag, so |
- var isLeaf = JS('bool', '(#[#]) === true', leafTags, tag); |
- if (isLeaf) { |
- return patchProto(obj, makeLeafDispatchRecord(interceptor)); |
- } else { |
- return patchInteriorProto(obj, interceptor); |
- } |
-} |
- |
-patchInstance(obj, record) { |
- setDispatchProperty(obj, record); |
- return dispatchRecordInterceptor(record); |
-} |
- |
-patchProto(obj, record) { |
- setDispatchProperty(JS('', 'Object.getPrototypeOf(#)', obj), record); |
- return dispatchRecordInterceptor(record); |
-} |
- |
-patchInteriorProto(obj, interceptor) { |
- var proto = JS('', 'Object.getPrototypeOf(#)', obj); |
- var record = makeDispatchRecord(interceptor, proto, null, null); |
- setDispatchProperty(proto, record); |
- return interceptor; |
-} |
- |
- |
-makeLeafDispatchRecord(interceptor) { |
- var fieldName = JS_GET_NAME(JsGetName.IS_INDEXABLE_FIELD_NAME); |
- bool indexability = JS('bool', r'!!#[#]', interceptor, fieldName); |
- return makeDispatchRecord(interceptor, false, null, indexability); |
-} |
- |
-makeDefaultDispatchRecord(tag, interceptorClass, proto) { |
- var interceptor = JS('', '#.prototype', interceptorClass); |
- var isLeaf = JS('bool', '(#[#]) === true', leafTags, tag); |
- if (isLeaf) { |
- return makeLeafDispatchRecord(interceptor); |
- } else { |
- return makeDispatchRecord(interceptor, proto, null, null); |
- } |
-} |
- |
-/** |
- * [proto] should have no shadowing prototypes that are not also assigned a |
- * dispatch rescord. |
- */ |
-setNativeSubclassDispatchRecord(proto, interceptor) { |
- setDispatchProperty(proto, makeLeafDispatchRecord(interceptor)); |
-} |
- |
-String constructorNameFallback(object) { |
- return JS('String', '#(#)', _constructorNameFallback, object); |
-} |
- |
- |
-var initNativeDispatchFlag; // null or true |
- |
-void initNativeDispatch() { |
- if (true == initNativeDispatchFlag) return; |
- initNativeDispatchFlag = true; |
- initNativeDispatchContinue(); |
-} |
- |
-void initNativeDispatchContinue() { |
- |
- dispatchRecordsForInstanceTags = JS('', 'Object.create(null)'); |
- interceptorsForUncacheableTags = JS('', 'Object.create(null)'); |
- |
- initHooks(); |
- |
- // Try to pro-actively patch prototypes of DOM objects. For each of our known |
- // tags `TAG`, if `window.TAG` is a (constructor) function, set the dispatch |
- // property if the function's prototype to a dispatch record. |
- var map = interceptorsByTag; |
- var tags = JS('JSMutableArray', 'Object.getOwnPropertyNames(#)', map); |
- |
- if (JS('bool', 'typeof window != "undefined"')) { |
- var context = JS('=Object', 'window'); |
- var fun = JS('=Object', 'function () {}'); |
- for (int i = 0; i < tags.length; i++) { |
- var tag = tags[i]; |
- var proto = prototypeForTagFunction(tag); |
- if (proto != null) { |
- var interceptorClass = JS('', '#[#]', map, tag); |
- var record = makeDefaultDispatchRecord(tag, interceptorClass, proto); |
- if (record != null) { |
- setDispatchProperty(proto, record); |
- // Ensure the modified prototype is still fast by assigning it to |
- // the prototype property of a function object. |
- JS('', '#.prototype = #', fun, proto); |
- } |
- } |
- } |
- } |
- |
- // [interceptorsByTag] maps 'plain' dispatch tags. Add all the derived |
- // dispatch tags to simplify lookup of derived tags. |
- for (int i = 0; i < tags.length; i++) { |
- var tag = JS('String', '#[#]', tags, i); |
- if (JS('bool', '/^[A-Za-z_]/.test(#)', tag)) { |
- var interceptorClass = propertyGet(map, tag); |
- propertySet(map, INSTANCE_CACHED_MARK + tag, interceptorClass); |
- propertySet(map, UNCACHED_MARK + tag, interceptorClass); |
- propertySet(map, LEAF_MARK + tag, interceptorClass); |
- propertySet(map, INTERIOR_MARK + tag, interceptorClass); |
- propertySet(map, DISCRIMINATED_MARK + tag, interceptorClass); |
- } |
- } |
-} |
- |
- |
-/** |
- * Initializes [getTagFunction] and [alternateTagFunction]. |
- * |
- * These functions are 'hook functions', collectively 'hooks'. They initialized |
- * by applying a series of hooks transformers. Built-in hooks transformers deal |
- * with various known browser behaviours. |
- * |
- * Each hook tranformer takes a 'hooks' input which is a JavaScript object |
- * containing the hook functions, and returns the same or a new object with |
- * replacements. The replacements can wrap the originals to provide alternate |
- * or modified behaviour. |
- * |
- * { getTag: function(obj) {...}, |
- * getUnknownTag: function(obj, tag) {...}, |
- * prototypeForTag: function(tag) {...}, |
- * discriminator: function(tag) {...}, |
- * } |
- * |
- * * getTag(obj) returns the dispatch tag, or `null`. |
- * * getUnknownTag(obj, tag) returns a tag when [getTag] fails. |
- * * prototypeForTag(tag) returns the prototype of the constructor for tag, |
- * or `null` if not available or prepatching is undesirable. |
- * * discriminator(tag) returns a function TBD. |
- * |
- * The web site can adapt a dart2js application by loading code ahead of the |
- * dart2js application that defines hook transformers to be after the built in |
- * ones. Code defining a transformer HT should use the following pattern to |
- * ensure multiple transformers can be composed: |
- * |
- * (dartNativeDispatchHooksTransformer = |
- * window.dartNativeDispatchHooksTransformer || []).push(HT); |
- * |
- * |
- * TODO: Implement and describe dispatch tags and their caching methods. |
- */ |
-void initHooks() { |
- // The initial simple hooks: |
- var hooks = JS('', '#()', _baseHooks); |
- |
- // Customize for browsers where `object.constructor.name` fails: |
- var _fallbackConstructorHooksTransformer = |
- JS('', '#(#)', _fallbackConstructorHooksTransformerGenerator, |
- _constructorNameFallback); |
- hooks = applyHooksTransformer(_fallbackConstructorHooksTransformer, hooks); |
- |
- // Customize for browsers: |
- hooks = applyHooksTransformer(_firefoxHooksTransformer, hooks); |
- hooks = applyHooksTransformer(_ieHooksTransformer, hooks); |
- hooks = applyHooksTransformer(_operaHooksTransformer, hooks); |
- hooks = applyHooksTransformer(_safariHooksTransformer, hooks); |
- |
- hooks = applyHooksTransformer(_fixDocumentHooksTransformer, hooks); |
- |
- // TODO(sra): Update ShadowDOM polyfil to use |
- // [dartNativeDispatchHooksTransformer] and remove this hook. |
- hooks = applyHooksTransformer(_dartExperimentalFixupGetTagHooksTransformer, |
- hooks); |
- |
- // Apply global hooks. |
- // |
- // If defined, dartNativeDispatchHookdTransformer should be a single function |
- // of a JavaScript Array of functions. |
- |
- if (JS('bool', 'typeof dartNativeDispatchHooksTransformer != "undefined"')) { |
- var transformers = JS('', 'dartNativeDispatchHooksTransformer'); |
- if (JS('bool', 'typeof # == "function"', transformers)) { |
- transformers = [transformers]; |
- } |
- if (JS('bool', '#.constructor == Array', transformers)) { |
- for (int i = 0; i < JS('int', '#.length', transformers); i++) { |
- var transformer = JS('', '#[#]', transformers, i); |
- if (JS('bool', 'typeof # == "function"', transformer)) { |
- hooks = applyHooksTransformer(transformer, hooks); |
- } |
- } |
- } |
- } |
- |
- var getTag = JS('', '#.getTag', hooks); |
- var getUnknownTag = JS('', '#.getUnknownTag', hooks); |
- var prototypeForTag = JS('', '#.prototypeForTag', hooks); |
- |
- getTagFunction = (o) => JS('String|Null', '#(#)', getTag, o); |
- alternateTagFunction = |
- (o, String tag) => JS('String|Null', '#(#, #)', getUnknownTag, o, tag); |
- prototypeForTagFunction = |
- (String tag) => JS('', '#(#)', prototypeForTag, tag); |
-} |
- |
-applyHooksTransformer(transformer, hooks) { |
- var newHooks = JS('=Object|Null', '#(#)', transformer, hooks); |
- return JS('', '# || #', newHooks, hooks); |
-} |
- |
-// JavaScript code fragments. |
-// |
-// This is a temporary place for the JavaScript code. |
-// |
-// TODO(sra): These code fragments are not minified. They could be generated by |
-// the code emitter, or JS_CONST could be improved to parse entire functions and |
-// take care of the minification. |
- |
-const _baseHooks = const JS_CONST(r''' |
-function() { |
- function typeNameInChrome(o) { |
- var constructor = o.constructor; |
- if (constructor) { |
- var name = constructor.name; |
- if (name) return name; |
- } |
- var s = Object.prototype.toString.call(o); |
- return s.substring(8, s.length - 1); |
- } |
- function getUnknownTag(object, tag) { |
- // This code really belongs in [getUnknownTagGenericBrowser] but having it |
- // here allows [getUnknownTag] to be tested on d8. |
- if (/^HTML[A-Z].*Element$/.test(tag)) { |
- // Check that it is not a simple JavaScript object. |
- var name = Object.prototype.toString.call(object); |
- if (name == "[object Object]") return null; |
- return "HTMLElement"; |
- } |
- } |
- function getUnknownTagGenericBrowser(object, tag) { |
- if (self.HTMLElement && object instanceof HTMLElement) return "HTMLElement"; |
- return getUnknownTag(object, tag); |
- } |
- function prototypeForTag(tag) { |
- if (typeof window == "undefined") return null; |
- if (typeof window[tag] == "undefined") return null; |
- var constructor = window[tag]; |
- if (typeof constructor != "function") return null; |
- return constructor.prototype; |
- } |
- function discriminator(tag) { return null; } |
- |
- var isBrowser = typeof navigator == "object"; |
- |
- return { |
- getTag: typeNameInChrome, |
- getUnknownTag: isBrowser ? getUnknownTagGenericBrowser : getUnknownTag, |
- prototypeForTag: prototypeForTag, |
- discriminator: discriminator }; |
-}'''); |
- |
- |
-/** |
- * Returns the name of the constructor function for browsers where |
- * `object.constructor.name` is not reliable. |
- * |
- * This function is split out of [_fallbackConstructorHooksTransformerGenerator] |
- * as it is called from both the dispatch hooks and via |
- * [constructorNameFallback] from objectToString. |
- */ |
-const _constructorNameFallback = const JS_CONST(r''' |
-function getTagFallback(o) { |
- var constructor = o.constructor; |
- if (typeof constructor == "function") { |
- var name = constructor.name; |
- // If the name is a non-empty string, we use that as the type name of this |
- // object. There are various cases where that does not work, so we have to |
- // detect them and fall through to the toString() based implementation. |
- |
- if (typeof name == "string" && |
- |
- // Sometimes the string is empty. This test also catches minified |
- // shadow dom polyfil wrapper for Window on Firefox where the faked |
- // constructor name does not 'stick'. The shortest real DOM object |
- // names have three characters (e.g. URL, CSS). |
- name.length > 2 && |
- |
- // On Firefox we often get "Object" as the constructor name, even for |
- // more specialized DOM objects. |
- name !== "Object" && |
- |
- // This can happen in Opera. |
- name !== "Function.prototype") { |
- return name; |
- } |
- } |
- var s = Object.prototype.toString.call(o); |
- return s.substring(8, s.length - 1); |
-}'''); |
- |
- |
-const _fallbackConstructorHooksTransformerGenerator = const JS_CONST(r''' |
-function(getTagFallback) { |
- return function(hooks) { |
- // If we are not in a browser, assume we are in d8. |
- // TODO(sra): Recognize jsshell. |
- if (typeof navigator != "object") return hooks; |
- |
- var ua = navigator.userAgent; |
- // TODO(antonm): remove a reference to DumpRenderTree. |
- if (ua.indexOf("DumpRenderTree") >= 0) return hooks; |
- if (ua.indexOf("Chrome") >= 0) { |
- // Confirm constructor name is usable for dispatch. |
- function confirm(p) { |
- return typeof window == "object" && window[p] && window[p].name == p; |
- } |
- if (confirm("Window") && confirm("HTMLElement")) return hooks; |
- } |
- |
- hooks.getTag = getTagFallback; |
- }; |
-}'''); |
- |
- |
-const _ieHooksTransformer = const JS_CONST(r''' |
-function(hooks) { |
- var userAgent = typeof navigator == "object" ? navigator.userAgent : ""; |
- if (userAgent.indexOf("Trident/") == -1) return hooks; |
- |
- var getTag = hooks.getTag; |
- |
- var quickMap = { |
- "BeforeUnloadEvent": "Event", |
- "DataTransfer": "Clipboard", |
- "HTMLDDElement": "HTMLElement", |
- "HTMLDTElement": "HTMLElement", |
- "HTMLPhraseElement": "HTMLElement", |
- "Position": "Geoposition" |
- }; |
- |
- function getTagIE(o) { |
- var tag = getTag(o); |
- var newTag = quickMap[tag]; |
- if (newTag) return newTag; |
- // Patches for types which report themselves as Objects. |
- if (tag == "Object") { |
- if (window.DataView && (o instanceof window.DataView)) return "DataView"; |
- } |
- return tag; |
- } |
- |
- function prototypeForTagIE(tag) { |
- var constructor = window[tag]; |
- if (constructor == null) return null; |
- return constructor.prototype; |
- } |
- |
- hooks.getTag = getTagIE; |
- hooks.prototypeForTag = prototypeForTagIE; |
-}'''); |
- |
-const _fixDocumentHooksTransformer = const JS_CONST(r''' |
-function(hooks) { |
- var getTag = hooks.getTag; |
- var prototypeForTag = hooks.prototypeForTag; |
- function getTagFixed(o) { |
- var tag = getTag(o); |
- if (tag == "Document") { |
- // Some browsers and the polymer polyfill call both HTML and XML documents |
- // "Document", so we check for the xmlVersion property, which is the empty |
- // string on HTML documents. Since both dart:html classes Document and |
- // HtmlDocument share the same type, we must patch the instances and not |
- // the prototype. |
- if (!!o.xmlVersion) return "!Document"; |
- return "!HTMLDocument"; |
- } |
- return tag; |
- } |
- |
- function prototypeForTagFixed(tag) { |
- if (tag == "Document") return null; // Do not pre-patch Document. |
- return prototypeForTag(tag); |
- } |
- |
- hooks.getTag = getTagFixed; |
- hooks.prototypeForTag = prototypeForTagFixed; |
-}'''); |
- |
-const _firefoxHooksTransformer = const JS_CONST(r''' |
-function(hooks) { |
- var userAgent = typeof navigator == "object" ? navigator.userAgent : ""; |
- if (userAgent.indexOf("Firefox") == -1) return hooks; |
- |
- var getTag = hooks.getTag; |
- |
- var quickMap = { |
- "BeforeUnloadEvent": "Event", |
- "DataTransfer": "Clipboard", |
- "GeoGeolocation": "Geolocation", |
- "Location": "!Location", // Fixes issue 18151 |
- "WorkerMessageEvent": "MessageEvent", |
- "XMLDocument": "!Document"}; |
- |
- function getTagFirefox(o) { |
- var tag = getTag(o); |
- return quickMap[tag] || tag; |
- } |
- |
- hooks.getTag = getTagFirefox; |
-}'''); |
- |
- |
-const _operaHooksTransformer = const JS_CONST(r''' |
-function(hooks) { return hooks; } |
-'''); |
- |
- |
-const _safariHooksTransformer = const JS_CONST(r''' |
-function(hooks) { return hooks; } |
-'''); |
- |
- |
-const _dartExperimentalFixupGetTagHooksTransformer = const JS_CONST(r''' |
-function(hooks) { |
- if (typeof dartExperimentalFixupGetTag != "function") return hooks; |
- hooks.getTag = dartExperimentalFixupGetTag(hooks.getTag); |
-}'''); |