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 46d81be95f1a8aa1b16726b6975e4b54f19daff0..66eee7570a0da301f17ed8cc513e4fbeb2272457 100644 |
| --- a/sdk/lib/_internal/compiler/implementation/lib/native_helper.dart |
| +++ b/sdk/lib/_internal/compiler/implementation/lib/native_helper.dart |
| @@ -122,10 +122,18 @@ 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); |
| +} |
| + |
| newJsObject() { |
| return JS('var', '{}'); |
| } |
| @@ -205,21 +213,33 @@ dynamicBind(var obj, |
| String name, |
| var methods, |
| List arguments) { |
| + // The tag is related to the class name. E.g. the dart:html class |
| + // '_ButtonElement' has the tag 'HTMLButtonElement'. TODO(erikcorry): rename |
| + // getTypeNameOf to getTypeTag. |
|
ngeoffray
2012/12/10 08:55:42
What's making it difficult today to have it in thi
erikcorry
2012/12/10 12:37:40
I don't like to mix renaming changes with real cha
|
| String tag = getTypeNameOf(obj); |
| - var method = JS('var', '#[#]', methods, tag); |
| + 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 (JS('bool', '#', propertyGet(entry._set, tag))) { |
| - method = propertyGet(methods, entry._tag); |
| + 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; |
| } |
| } |
| } |
| + // If we didn't find the method then look up in the Dart Object class, using |
| + // getTypeNameOf in case the minifier has renamed Object. |
| if (method == null) { |
| - method = propertyGet(methods, 'Object'); |
| + String nameOfObjectClass = getTypeNameOf(const Object()); |
| + method = |
| + lookupDynamicClass(hasOwnPropertyFunction, methods, nameOfObjectClass); |
| } |
| var proto = JS('var', 'Object.getPrototypeOf(#)', obj); |
| @@ -239,13 +259,26 @@ dynamicBind(var obj, |
| proto, name, name); |
| } |
| - if (JS('bool', '!#.hasOwnProperty(#)', proto, name)) { |
| + if (callHasOwnProperty(hasOwnPropertyFunction, proto, name)) { |
| defineProperty(proto, name, method); |
| } |
| return JS('var', '#.apply(#, #)', method, obj, arguments); |
| } |
| +// 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 |
| +// clashing with the method names on Object.prototype (needed for native |
| +// objects) we must always use hasOwnProperty. |
| +var lookupDynamicClass(var hasOwnPropertyFunction, |
| + var methods, |
| + String className) { |
| + return callHasOwnProperty(hasOwnPropertyFunction, methods, className) ? |
| + propertyGet(methods, className) : |
| + null; |
| +} |
| + |
| /** |
| * Code for doing the dynamic dispatch on JavaScript prototypes that are not |
| * available at compile-time. Each property of a native Dart class |
| @@ -273,7 +306,9 @@ dynamicFunction(name) { |
| var methods = JS('var', '{}'); |
| // If there is a method attached to the Dart Object class, use it as |
| // the method to call in case no method is registered for that type. |
| - var dartMethod = JS('var', 'Object.getPrototypeOf(#)[#]', const Object(), name); |
| + var dartMethod = getPropertyFromPrototype(const Object(), name); |
| + // Take the method from the Dart Object class if we didn't find it yet and it |
| + // is there. |
| if (dartMethod != null) propertySet(methods, 'Object', dartMethod); |
| var bind = JS('var', |