Chromium Code Reviews| Index: sdk/lib/_internal/compiler/implementation/lib/native_helper.dart |
| diff --git a/sdk/lib/_internal/compiler/implementation/lib/native_helper.dart b/sdk/lib/_internal/compiler/implementation/lib/native_helper.dart |
| index bd9348d1892e16bfc65e3ee21280f1383fc127f3..353652d9bc9c04686ed56f67097bd78ebe5c51af 100644 |
| --- a/sdk/lib/_internal/compiler/implementation/lib/native_helper.dart |
| +++ b/sdk/lib/_internal/compiler/implementation/lib/native_helper.dart |
| @@ -6,22 +6,17 @@ part of _js_helper; |
| String typeNameInChrome(obj) { |
| String name = JS('String', "#.constructor.name", obj); |
| - if (name == 'Window') return 'DOMWindow'; |
| - if (name == 'CanvasPixelArray') return 'Uint8ClampedArray'; |
| - if (name == 'WebKitMutationObserver') return 'MutationObserver'; |
| - if (name == 'AudioChannelMerger') return 'ChannelMergerNode'; |
| - if (name == 'AudioChannelSplitter') return 'ChannelSplitterNode'; |
| - if (name == 'AudioGainNode') return 'GainNode'; |
| - if (name == 'AudioPannerNode') return 'PannerNode'; |
| - if (name == 'JavaScriptAudioNode') return 'ScriptProcessorNode'; |
| - if (name == 'Oscillator') return 'OscillatorNode'; |
| - if (name == 'RealtimeAnalyserNode') return 'AnalyserNode'; |
| - return name; |
| + return typeNameInWebKitCommon(name); |
| } |
| String typeNameInSafari(obj) { |
| String name = JS('String', '#', constructorNameFallback(obj)); |
| // Safari is very similar to Chrome. |
| + return typeNameInWebKitCommon(name); |
| +} |
| + |
| +String typeNameInWebKitCommon(tag) { |
| + String name = JS('String', '#', tag); |
| if (name == 'Window') return 'DOMWindow'; |
| if (name == 'CanvasPixelArray') return 'Uint8ClampedArray'; |
| if (name == 'WebKitMutationObserver') return 'MutationObserver'; |
| @@ -102,6 +97,23 @@ String constructorNameFallback(object) { |
| return JS('String', '#.substring(8, # - 1)', string, string.length); |
| } |
| +/** |
| + * If a lookup 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. |
| + */ |
| +String alternateTag(object, String tag) { |
| + // Does it smell like some kind of HTML element? |
| + if (JS('bool', r'!!/^HTML[A-Z].*Element$/.test(#)', tag)) { |
| + // Check that it is not a simple JavaScript object. |
| + String string = JS('String', 'Object.prototype.toString.call(#)', object); |
| + if (string == '[object Object]') return null; |
| + return 'HTMLElement'; |
| + } |
| + return null; |
| +} |
| + |
| // 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) { |
| @@ -193,8 +205,9 @@ 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})""", |
| + JS('void', |
| + 'Object.defineProperty(#, #, ' |
| + '{value: #, enumerable: false, writable: true, configurable: true})', |
| obj, |
| property, |
| value); |
| @@ -220,19 +233,12 @@ dynamicBind(var obj, |
| // getTypeNameOf to getTypeTag. |
| String tag = getTypeNameOf(obj); |
| var hasOwnPropertyFunction = JS('var', 'Object.prototype.hasOwnProperty'); |
| - var method = lookupDynamicClass(hasOwnPropertyFunction, methods, tag); |
| - if (method == null && _dynamicMetadata != null) { |
| - // Look at the inheritance data, getting the class tags and using them |
| - // to check the methods table for this method name. |
| - for (int i = 0; i < arrayLength(_dynamicMetadata); i++) { |
| - MetaInfo entry = arrayGet(_dynamicMetadata, i); |
| - if (callHasOwnProperty(hasOwnPropertyFunction, entry._set, tag)) { |
| - method = |
| - lookupDynamicClass(hasOwnPropertyFunction, methods, entry._tag); |
| - // Stop if we found it in the methods array. |
| - if (method != null) break; |
| - } |
| + var method = dynamicBindLookup(hasOwnPropertyFunction, tag, methods); |
| + if (method == null) { |
| + String altTag = alternateTag(obj, tag); |
| + if (altTag != null) { |
|
kasperl
2012/12/12 06:43:50
Nit: I'd try to avoid the abbreviation of alt.
|
| + method = dynamicBindLookup(hasOwnPropertyFunction, altTag, methods); |
| } |
| } |
| @@ -268,6 +274,24 @@ dynamicBind(var obj, |
| return JS('var', '#.apply(#, #)', method, obj, arguments); |
| } |
| +dynamicBindLookup(var hasOwnPropertyFunction, String tag, var methods) { |
| + var method = lookupDynamicClass(hasOwnPropertyFunction, methods, tag); |
| + // Look at the inheritance data, getting the class tags and using them |
| + // to check the methods table for this method name. |
| + if (method == null && _dynamicMetadata != null) { |
| + for (int i = 0; i < arrayLength(_dynamicMetadata); i++) { |
| + MetaInfo entry = arrayGet(_dynamicMetadata, i); |
| + if (callHasOwnProperty(hasOwnPropertyFunction, entry._set, tag)) { |
| + method = |
| + lookupDynamicClass(hasOwnPropertyFunction, methods, entry._tag); |
| + // Stop if we found it in the methods array. |
| + if (method != null) break; |
| + } |
| + } |
| + } |
| + return method; |
| +} |
| + |
| // For each method name and class inheritance subtree, we use an ordinary JS |
| // object as a hash map to store the method for each class. Entries are added |
| // in native_emitter.dart (see dynamicName). In order to avoid the class names |