Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(274)

Side by Side Diff: sdk/lib/_internal/compiler/implementation/lib/native_helper.dart

Issue 11553015: Add a fall-back for novel HTML Elements (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 _js_helper; 5 part of _js_helper;
6 6
7 String typeNameInChrome(obj) { 7 String typeNameInChrome(obj) {
8 String name = JS('String', "#.constructor.name", obj); 8 String name = JS('String', "#.constructor.name", obj);
9 if (name == 'Window') return 'DOMWindow'; 9 return typeNameInWebKitCommon(name);
10 if (name == 'CanvasPixelArray') return 'Uint8ClampedArray';
11 if (name == 'WebKitMutationObserver') return 'MutationObserver';
12 if (name == 'AudioChannelMerger') return 'ChannelMergerNode';
13 if (name == 'AudioChannelSplitter') return 'ChannelSplitterNode';
14 if (name == 'AudioGainNode') return 'GainNode';
15 if (name == 'AudioPannerNode') return 'PannerNode';
16 if (name == 'JavaScriptAudioNode') return 'ScriptProcessorNode';
17 if (name == 'Oscillator') return 'OscillatorNode';
18 if (name == 'RealtimeAnalyserNode') return 'AnalyserNode';
19 return name;
20 } 10 }
21 11
22 String typeNameInSafari(obj) { 12 String typeNameInSafari(obj) {
23 String name = JS('String', '#', constructorNameFallback(obj)); 13 String name = JS('String', '#', constructorNameFallback(obj));
24 // Safari is very similar to Chrome. 14 // Safari is very similar to Chrome.
15 return typeNameInWebKitCommon(name);
16 }
17
18 String typeNameInWebKitCommon(tag) {
19 String name = JS('String', '#', tag);
25 if (name == 'Window') return 'DOMWindow'; 20 if (name == 'Window') return 'DOMWindow';
26 if (name == 'CanvasPixelArray') return 'Uint8ClampedArray'; 21 if (name == 'CanvasPixelArray') return 'Uint8ClampedArray';
27 if (name == 'WebKitMutationObserver') return 'MutationObserver'; 22 if (name == 'WebKitMutationObserver') return 'MutationObserver';
28 if (name == 'AudioChannelMerger') return 'ChannelMergerNode'; 23 if (name == 'AudioChannelMerger') return 'ChannelMergerNode';
29 if (name == 'AudioChannelSplitter') return 'ChannelSplitterNode'; 24 if (name == 'AudioChannelSplitter') return 'ChannelSplitterNode';
30 if (name == 'AudioGainNode') return 'GainNode'; 25 if (name == 'AudioGainNode') return 'GainNode';
31 if (name == 'AudioPannerNode') return 'PannerNode'; 26 if (name == 'AudioPannerNode') return 'PannerNode';
32 if (name == 'JavaScriptAudioNode') return 'ScriptProcessorNode'; 27 if (name == 'JavaScriptAudioNode') return 'ScriptProcessorNode';
33 if (name == 'Oscillator') return 'OscillatorNode'; 28 if (name == 'Oscillator') return 'OscillatorNode';
34 if (name == 'RealtimeAnalyserNode') return 'AnalyserNode'; 29 if (name == 'RealtimeAnalyserNode') return 'AnalyserNode';
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
95 && !identical(name, '') 90 && !identical(name, '')
96 && !identical(name, 'Object') 91 && !identical(name, 'Object')
97 && !identical(name, 'Function.prototype')) { // Can happen in Opera. 92 && !identical(name, 'Function.prototype')) { // Can happen in Opera.
98 return name; 93 return name;
99 } 94 }
100 } 95 }
101 String string = JS('String', 'Object.prototype.toString.call(#)', object); 96 String string = JS('String', 'Object.prototype.toString.call(#)', object);
102 return JS('String', '#.substring(8, # - 1)', string, string.length); 97 return JS('String', '#.substring(8, # - 1)', string, string.length);
103 } 98 }
104 99
100 /**
101 * If a lookup on an object [object] that has [tag] fails, this function is
102 * called to provide an alternate tag. This allows us to fail gracefully if we
103 * can make a good guess, for example, when browsers add novel kinds of
104 * HTMLElement that we have never heard of.
105 */
106 String alternateTag(object, String tag) {
107 // Does it smell like some kind of HTML element?
108 if (JS('bool', r'!!/^HTML[A-Z].*Element$/.test(#)', tag)) {
109 // Check that it is not a simple JavaScript object.
110 String string = JS('String', 'Object.prototype.toString.call(#)', object);
111 if (string == '[object Object]') return null;
112 return 'HTMLElement';
113 }
114 return null;
115 }
116
105 // TODO(ngeoffray): stop using this method once our optimizers can 117 // TODO(ngeoffray): stop using this method once our optimizers can
106 // change str1.contains(str2) into str1.indexOf(str2) != -1. 118 // change str1.contains(str2) into str1.indexOf(str2) != -1.
107 bool contains(String userAgent, String name) { 119 bool contains(String userAgent, String name) {
108 return JS('int', '#.indexOf(#)', userAgent, name) != -1; 120 return JS('int', '#.indexOf(#)', userAgent, name) != -1;
109 } 121 }
110 122
111 int arrayLength(List array) { 123 int arrayLength(List array) {
112 return JS('int', '#.length', array); 124 return JS('int', '#.length', array);
113 } 125 }
114 126
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
186 String name = JS('String', '#', getTypeNameOf(obj)); 198 String name = JS('String', '#', getTypeNameOf(obj));
187 return 'Instance of $name'; 199 return 'Instance of $name';
188 } 200 }
189 201
190 int hashCodeForNativeObject(object) => Primitives.objectHashCode(object); 202 int hashCodeForNativeObject(object) => Primitives.objectHashCode(object);
191 203
192 /** 204 /**
193 * Sets a JavaScript property on an object. 205 * Sets a JavaScript property on an object.
194 */ 206 */
195 void defineProperty(var obj, String property, var value) { 207 void defineProperty(var obj, String property, var value) {
196 JS('void', """Object.defineProperty(#, #, 208 JS('void',
197 {value: #, enumerable: false, writable: true, configurable: true})""", 209 'Object.defineProperty(#, #, '
210 '{value: #, enumerable: false, writable: true, configurable: true})',
198 obj, 211 obj,
199 property, 212 property,
200 value); 213 value);
201 } 214 }
202 215
203 /** 216 /**
204 * This method looks up the type name of [obj] in [methods]. [methods] 217 * This method looks up the type name of [obj] in [methods]. [methods]
205 * is a Javascript object. If it cannot find it, it looks into the 218 * is a Javascript object. If it cannot find it, it looks into the
206 * [_dynamicMetadata] array. If the method can still not be found, it 219 * [_dynamicMetadata] array. If the method can still not be found, it
207 * creates a method that will throw a [NoSuchMethodError]. 220 * creates a method that will throw a [NoSuchMethodError].
208 * 221 *
209 * Once it has a method, the prototype of [obj] is patched with that 222 * Once it has a method, the prototype of [obj] is patched with that
210 * method, on the property [name]. The method is then invoked. 223 * method, on the property [name]. The method is then invoked.
211 * 224 *
212 * This method returns the result of invoking the found method. 225 * This method returns the result of invoking the found method.
213 */ 226 */
214 dynamicBind(var obj, 227 dynamicBind(var obj,
215 String name, 228 String name,
216 var methods, 229 var methods,
217 List arguments) { 230 List arguments) {
218 // The tag is related to the class name. E.g. the dart:html class 231 // The tag is related to the class name. E.g. the dart:html class
219 // '_ButtonElement' has the tag 'HTMLButtonElement'. TODO(erikcorry): rename 232 // '_ButtonElement' has the tag 'HTMLButtonElement'. TODO(erikcorry): rename
220 // getTypeNameOf to getTypeTag. 233 // getTypeNameOf to getTypeTag.
221 String tag = getTypeNameOf(obj); 234 String tag = getTypeNameOf(obj);
222 var hasOwnPropertyFunction = JS('var', 'Object.prototype.hasOwnProperty'); 235 var hasOwnPropertyFunction = JS('var', 'Object.prototype.hasOwnProperty');
223 var method = lookupDynamicClass(hasOwnPropertyFunction, methods, tag);
224 236
225 if (method == null && _dynamicMetadata != null) { 237 var method = dynamicBindLookup(hasOwnPropertyFunction, tag, methods);
226 // Look at the inheritance data, getting the class tags and using them 238 if (method == null) {
227 // to check the methods table for this method name. 239 String altTag = alternateTag(obj, tag);
228 for (int i = 0; i < arrayLength(_dynamicMetadata); i++) { 240 if (altTag != null) {
kasperl 2012/12/12 06:43:50 Nit: I'd try to avoid the abbreviation of alt.
229 MetaInfo entry = arrayGet(_dynamicMetadata, i); 241 method = dynamicBindLookup(hasOwnPropertyFunction, altTag, methods);
230 if (callHasOwnProperty(hasOwnPropertyFunction, entry._set, tag)) {
231 method =
232 lookupDynamicClass(hasOwnPropertyFunction, methods, entry._tag);
233 // Stop if we found it in the methods array.
234 if (method != null) break;
235 }
236 } 242 }
237 } 243 }
238 244
239 // If we didn't find the method then look up in the Dart Object class, using 245 // If we didn't find the method then look up in the Dart Object class, using
240 // getTypeNameOf in case the minifier has renamed Object. 246 // getTypeNameOf in case the minifier has renamed Object.
241 if (method == null) { 247 if (method == null) {
242 String nameOfObjectClass = getTypeNameOf(const Object()); 248 String nameOfObjectClass = getTypeNameOf(const Object());
243 method = 249 method =
244 lookupDynamicClass(hasOwnPropertyFunction, methods, nameOfObjectClass); 250 lookupDynamicClass(hasOwnPropertyFunction, methods, nameOfObjectClass);
245 } 251 }
(...skipping 15 matching lines...) Expand all
261 proto, name, name); 267 proto, name, name);
262 } 268 }
263 269
264 if (!callHasOwnProperty(hasOwnPropertyFunction, proto, name)) { 270 if (!callHasOwnProperty(hasOwnPropertyFunction, proto, name)) {
265 defineProperty(proto, name, method); 271 defineProperty(proto, name, method);
266 } 272 }
267 273
268 return JS('var', '#.apply(#, #)', method, obj, arguments); 274 return JS('var', '#.apply(#, #)', method, obj, arguments);
269 } 275 }
270 276
277 dynamicBindLookup(var hasOwnPropertyFunction, String tag, var methods) {
278 var method = lookupDynamicClass(hasOwnPropertyFunction, methods, tag);
279 // Look at the inheritance data, getting the class tags and using them
280 // to check the methods table for this method name.
281 if (method == null && _dynamicMetadata != null) {
282 for (int i = 0; i < arrayLength(_dynamicMetadata); i++) {
283 MetaInfo entry = arrayGet(_dynamicMetadata, i);
284 if (callHasOwnProperty(hasOwnPropertyFunction, entry._set, tag)) {
285 method =
286 lookupDynamicClass(hasOwnPropertyFunction, methods, entry._tag);
287 // Stop if we found it in the methods array.
288 if (method != null) break;
289 }
290 }
291 }
292 return method;
293 }
294
271 // For each method name and class inheritance subtree, we use an ordinary JS 295 // For each method name and class inheritance subtree, we use an ordinary JS
272 // object as a hash map to store the method for each class. Entries are added 296 // object as a hash map to store the method for each class. Entries are added
273 // in native_emitter.dart (see dynamicName). In order to avoid the class names 297 // in native_emitter.dart (see dynamicName). In order to avoid the class names
274 // clashing with the method names on Object.prototype (needed for native 298 // clashing with the method names on Object.prototype (needed for native
275 // objects) we must always use hasOwnProperty. 299 // objects) we must always use hasOwnProperty.
276 var lookupDynamicClass(var hasOwnPropertyFunction, 300 var lookupDynamicClass(var hasOwnPropertyFunction,
277 var methods, 301 var methods,
278 String className) { 302 String className) {
279 return callHasOwnProperty(hasOwnPropertyFunction, methods, className) ? 303 return callHasOwnProperty(hasOwnPropertyFunction, methods, className) ?
280 propertyGet(methods, className) : 304 propertyGet(methods, className) :
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
389 } 413 }
390 return result; 414 return result;
391 } 415 }
392 416
393 /** 417 /**
394 * Called by the compiler to setup [_dynamicMetadata]. 418 * Called by the compiler to setup [_dynamicMetadata].
395 */ 419 */
396 void dynamicSetMetadata(List<List<String>> inputTable) { 420 void dynamicSetMetadata(List<List<String>> inputTable) {
397 _dynamicMetadata = buildDynamicMetadata(inputTable); 421 _dynamicMetadata = buildDynamicMetadata(inputTable);
398 } 422 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698