OLD | NEW |
---|---|
1 part of html_common; | 1 part of html_common; |
2 | 2 |
3 convertDartToNative_PrepareForStructuredClone(value) => | 3 convertDartToNative_PrepareForStructuredClone(value) => |
4 new _StructuredCloneDartium().convertDartToNative_PrepareForStructuredClone( value); | 4 new _StructuredCloneDartium().convertDartToNative_PrepareForStructuredClone( value); |
5 | 5 |
6 convertNativeToDart_AcceptStructuredClone(object, {mustCopy: false}) => | 6 convertNativeToDart_AcceptStructuredClone(object, {mustCopy: false}) => |
7 new _AcceptStructuredCloneDartium().convertNativeToDart_AcceptStructuredClon e(object, mustCopy: mustCopy); | 7 new _AcceptStructuredCloneDartium().convertNativeToDart_AcceptStructuredClon e(object, mustCopy: mustCopy); |
8 | 8 |
9 class _StructuredCloneDartium extends _StructuredClone { | 9 class _StructuredCloneDartium extends _StructuredClone { |
10 newJsMap() => new js.JsObject(js.context["Object"]); | 10 newJsMap() => new js.JsObject(js.context["Object"]); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
68 } | 68 } |
69 | 69 |
70 /// Creates a Dart Rectangle from a Javascript object with properties | 70 /// Creates a Dart Rectangle from a Javascript object with properties |
71 /// left, top, width and height. Used internally in Dartium. | 71 /// left, top, width and height. Used internally in Dartium. |
72 Rectangle make_dart_rectangle(r) => | 72 Rectangle make_dart_rectangle(r) => |
73 r == null ? null : new Rectangle( | 73 r == null ? null : new Rectangle( |
74 js.JsNative.getProperty(r, 'left'), | 74 js.JsNative.getProperty(r, 'left'), |
75 js.JsNative.getProperty(r, 'top'), | 75 js.JsNative.getProperty(r, 'top'), |
76 js.JsNative.getProperty(r, 'width'), | 76 js.JsNative.getProperty(r, 'width'), |
77 js.JsNative.getProperty(r, 'height')); | 77 js.JsNative.getProperty(r, 'height')); |
78 | |
79 // Converts a flat Dart map into a JavaScript object with properties this is | |
80 // is the Dartium only version it uses dart:js. | |
81 // TODO(alanknight): This could probably be unified with the dart2js conversions | |
82 // code in html_common and be more general. | |
83 convertDartToNative_Dictionary(Map dict) { | |
84 if (dict == null) return null; | |
85 var jsObject = new js.JsObject(js.JsNative.getProperty(js.context, 'Object')); | |
86 dict.forEach((String key, value) { | |
87 if (value is List) { | |
88 var jsArray = new js.JsArray(); | |
89 value.forEach((elem) { | |
90 jsArray.add(elem is Map ? convertDartToNative_Dictionary(elem): elem); | |
91 }); | |
92 jsObject[key] = jsArray; | |
93 } else { | |
94 jsObject[key] = value; | |
95 } | |
96 }); | |
97 return jsObject; | |
98 } | |
99 | |
100 // Conversion function place holder (currently not used in dart2js or dartium). | |
101 List convertDartToNative_StringArray(List<String> input) => input; | |
102 | |
103 // Converts a Dart list into a JsArray. For the Dartium version only. | |
104 convertDartToNative_List(List input) => new js.JsArray()..addAll(input); | |
105 | |
106 /// Find the underlying JS object for a dart:html Dart object. | |
107 unwrap_jso(dartClass_instance) => js.unwrap_jso(dartClass_instance); | |
108 | |
109 // Flag to disable JS interop asserts. Setting to false will speed up the | |
110 // wrap_jso calls. | |
111 bool __interop_checks = false; | |
terry
2015/10/19 17:11:25
Should this be hidden? Looks like we're not hidin
Alan Knight
2015/10/19 18:28:02
Done.
| |
112 | |
113 /// Wrap a JS object with an instance of the matching dart:html class. Used only in Dartium. | |
114 wrap_jso(jsObject) { | |
115 try { | |
116 if (jsObject is! js.JsObject || jsObject == null) { | |
117 // JS Interop converted the object to a Dart class e.g., Uint8ClampedList. | |
118 // or it's a simple type. | |
119 return jsObject; | |
120 } | |
121 | |
122 var wrapper = js.getDartHtmlWrapperFor(jsObject); | |
123 // if we have a wrapper return the Dart instance. | |
124 if (wrapper != null) { | |
125 var customElementClass = getCustomElementType(wrapper.blink_jsObject); | |
126 if (wrapper.runtimeType != customElementClass && customElementClass != nul l) { | |
127 if (wrapper.runtimeType == HtmlElement && !wrapper.isBadUpgrade) { | |
128 // We're a Dart instance if it's HtmlElement and we have a customEleme nt | |
129 // class then we need to upgrade. | |
130 if (customElementClass != null) { | |
131 var dartClass_instance; | |
132 try { | |
133 dartClass_instance = _blink.Blink_Utils.constructElement(customEle mentClass, jsObject); | |
134 } finally { | |
135 dartClass_instance.blink_jsObject = jsObject; | |
136 return dartClass_instance; | |
137 } | |
138 } | |
139 } | |
140 } | |
141 | |
142 return wrapper; | |
143 } | |
144 | |
145 if (jsObject is js.JsArray) { | |
146 var wrappingList = new _DartHtmlWrappingList(jsObject); | |
147 js.setDartHtmlWrapperFor(jsObject, wrappingList); | |
148 return wrappingList; | |
149 } | |
150 | |
151 // Try the most general type conversions on it. | |
152 // TODO(alanknight): We may be able to do better. This maintains identity, | |
153 // which is useful, but expensive. And if we nest something that only | |
154 // this conversion handles, how does that work? e.g. a list of maps of eleme nts. | |
155 var converted = convertNativeToDart_SerializedScriptValue(jsObject); | |
156 if (!identical(converted, jsObject)) { | |
157 return converted; | |
158 } | |
159 | |
160 var constructor = js.JsNative.getProperty(jsObject, 'constructor'); | |
161 if (constructor == null) { | |
162 // Perfectly valid case for JavaScript objects where __proto__ has | |
163 // intentionally been set to null. | |
164 js.setDartHtmlWrapperFor(jsObject, jsObject); | |
165 return jsObject; | |
166 } | |
167 var jsTypeName = js.JsNative.getProperty(constructor, 'name'); | |
168 if (jsTypeName is! String || jsTypeName.length == 0) { | |
169 // Not an html type. | |
170 js.setDartHtmlWrapperFor(jsObject, jsObject); | |
171 return jsObject; | |
172 } | |
173 | |
174 var dartClass_instance; | |
175 var customElementClass = null; | |
176 var extendsTag = ""; | |
177 var custom = getCustomElementEntry(jsObject); | |
178 if (custom != null) { | |
179 customElementClass = custom['type']; | |
180 extendsTag = custom['extends']; | |
181 } | |
182 | |
183 // Custom Element to upgrade. | |
184 // Only allow custome elements to be created in the html or svg default | |
185 // namespace. | |
186 var defaultNS = jsObject['namespaceURI'] == 'http://www.w3.org/1999/xhtml' | | | |
187 jsObject['namespaceURI'] == 'http://www.w3.org/2000/svg'; | |
188 if (customElementClass != null && extendsTag == "" && defaultNS) { | |
189 try { | |
190 dartClass_instance = _blink.Blink_Utils.constructElement(customElementCl ass, jsObject); | |
191 } finally { | |
192 dartClass_instance.blink_jsObject = jsObject; | |
193 js.setDartHtmlWrapperFor(jsObject, dartClass_instance); | |
194 } | |
195 } else { | |
196 var func = getHtmlCreateFunction(jsTypeName); | |
197 if (func == null) { | |
198 if (jsTypeName == 'auto-binding') { | |
199 func = getHtmlCreateFunction("HTMLTemplateElement"); | |
200 } else if (jsObject.toString() == "[object HTMLElement]") { | |
201 // One last ditch effort could be a JS custom element. | |
202 func = getHtmlCreateFunction("HTMLElement"); | |
203 } | |
204 } | |
205 if (func != null) { | |
206 dartClass_instance = func(); | |
207 dartClass_instance.blink_jsObject = jsObject; | |
208 js.setDartHtmlWrapperFor(jsObject, dartClass_instance); | |
209 } | |
210 } | |
211 | |
212 // TODO(jacobr): cache that this is not a dart:html JS class. | |
213 return dartClass_instance; | |
214 } catch(e, stacktrace){ | |
215 if (__interop_checks) { | |
216 if (e is DebugAssertException) | |
217 window.console.log("${e.message}\n ${stacktrace}"); | |
218 else | |
219 window.console.log("${stacktrace}"); | |
220 } | |
221 } | |
222 | |
223 return null; | |
224 } | |
225 | |
226 /** | |
227 * Create Dart class that maps to the JS Type, add the JsObject as an expando | |
228 * on the Dart class and return the created Dart class. | |
229 */ | |
230 wrap_jso_no_SerializedScriptvalue(jsObject) { | |
231 try { | |
232 if (jsObject is! js.JsObject || jsObject == null) { | |
233 // JS Interop converted the object to a Dart class e.g., Uint8ClampedList. | |
234 // or it's a simple type. | |
235 return jsObject; | |
236 } | |
237 | |
238 // TODO(alanknight): With upgraded custom elements this causes a failure bec ause | |
239 // we need a new wrapper after the type changes. We could possibly invalidat e this | |
240 // if the constructor name didn't match? | |
241 var wrapper = js.getDartHtmlWrapperFor(jsObject); | |
242 if (wrapper != null) { | |
243 return wrapper; | |
244 } | |
245 | |
246 if (jsObject is js.JsArray) { | |
247 var wrappingList = new _DartHtmlWrappingList(jsObject); | |
248 js.setDartHtmlWrapperFor(jsObject, wrappingList); | |
249 return wrappingList; | |
250 } | |
251 | |
252 var constructor = js.JsNative.getProperty(jsObject, 'constructor'); | |
253 if (constructor == null) { | |
254 // Perfectly valid case for JavaScript objects where __proto__ has | |
255 // intentionally been set to null. | |
256 js.setDartHtmlWrapperFor(jsObject, jsObject); | |
257 return jsObject; | |
258 } | |
259 var jsTypeName = js.JsNative.getProperty(constructor, 'name'); | |
260 if (jsTypeName is! String || jsTypeName.length == 0) { | |
261 // Not an html type. | |
262 js.setDartHtmlWrapperFor(jsObject, jsObject); | |
263 return jsObject; | |
264 } | |
265 | |
266 var func = getHtmlCreateFunction(jsTypeName); | |
267 if (func != null) { | |
268 var dartClass_instance = func(); | |
269 dartClass_instance.blink_jsObject = jsObject; | |
270 js.setDartHtmlWrapperFor(jsObject, dartClass_instance); | |
271 return dartClass_instance; | |
272 } | |
273 return jsObject; | |
274 } catch(e, stacktrace){ | |
275 if (__interop_checks) { | |
276 if (e is DebugAssertException) | |
277 window.console.log("${e.message}\n ${stacktrace}"); | |
278 else | |
279 window.console.log("${stacktrace}"); | |
280 } | |
281 } | |
282 | |
283 return null; | |
284 } | |
285 | |
286 /** | |
287 * Create Dart class that maps to the JS Type that is the JS type being | |
288 * extended using JS interop createCallback (we need the base type of the | |
289 * custom element) not the Dart created constructor. | |
290 */ | |
291 wrap_jso_custom_element(jsObject) { | |
292 try { | |
293 if (jsObject is! js.JsObject) { | |
294 // JS Interop converted the object to a Dart class e.g., Uint8ClampedList. | |
295 return jsObject; | |
296 } | |
297 | |
298 // Find out what object we're extending. | |
299 var objectName = jsObject.toString(); | |
300 // Expect to see something like '[object HTMLElement]'. | |
301 if (!objectName.startsWith('[object ')) { | |
302 return jsObject; | |
303 } | |
304 | |
305 var extendsClass = objectName.substring(8, objectName.length - 1); | |
306 var func = getHtmlCreateFunction(extendsClass); | |
307 if (__interop_checks) | |
308 debug_or_assert("func != null name = ${extendsClass}", func != null); | |
309 var dartClass_instance = func(); | |
310 dartClass_instance.blink_jsObject = jsObject; | |
311 return dartClass_instance; | |
312 } catch(e, stacktrace){ | |
313 if (__interop_checks) { | |
314 if (e is DebugAssertException) | |
315 window.console.log("${e.message}\n ${stacktrace}"); | |
316 else | |
317 window.console.log("${stacktrace}"); | |
318 } | |
319 | |
320 // Problem? | |
321 return null; | |
322 } | |
323 } | |
324 | |
325 getCustomElementEntry(element) { | |
326 var hasAttribute = false; | |
327 | |
328 var jsObject; | |
329 var tag = ""; | |
330 var runtimeType = element.runtimeType; | |
331 if (runtimeType == HtmlElement) { | |
332 tag = element.localName; | |
333 } else if (runtimeType == TemplateElement) { | |
334 // Data binding with a Dart class. | |
335 tag = element.attributes['is']; | |
336 } else if (runtimeType == js.JsObjectImpl) { | |
337 // It's a Polymer core element (written in JS). | |
338 // Make sure it's an element anything else we can ignore. | |
339 if (element.hasProperty('nodeType') && element['nodeType'] == 1) { | |
340 if (js.JsNative.callMethod(element, 'hasAttribute', ['is'])) { | |
341 hasAttribute = true; | |
342 // It's data binding use the is attribute. | |
343 tag = js.JsNative.callMethod(element, 'getAttribute', ['is']); | |
344 } else { | |
345 // It's a custom element we want the local name. | |
346 tag = element['localName']; | |
347 } | |
348 } | |
349 } else { | |
350 throw new UnsupportedError('Element is incorrect type. Got ${runtimeType}, e xpected HtmlElement/HtmlTemplate/JsObjectImpl.'); | |
351 } | |
352 | |
353 var entry = knownCustomElements[tag]; | |
354 if (entry != null) { | |
355 // If there's an 'is' attribute then check if the extends tag registered | |
356 // matches the tag if so then return the entry that's registered for this | |
357 // extendsTag or if there's no 'is' tag then return the entry found. | |
358 if ((hasAttribute && entry['extends'] == tag) || !hasAttribute) { | |
359 return entry; | |
360 } | |
361 } | |
362 | |
363 return null; | |
364 } | |
365 | |
366 // List of known tagName to DartClass for custom elements, used for upgrade. | |
367 var knownCustomElements = new Map<String, Map<Type, String>>(); | |
terry
2015/10/19 17:11:25
We don't want anyone really accessing knownCustomE
Alan Knight
2015/10/19 18:28:02
Done.
| |
368 | |
369 void addCustomElementType(String tagName, Type dartClass, [String extendTag]) { | |
370 knownCustomElements[tagName] = | |
371 {'type': dartClass, 'extends': extendTag != null ? extendTag : "" }; | |
372 } | |
373 | |
374 Type getCustomElementType(object) { | |
375 var entry = getCustomElementEntry(object); | |
376 if (entry != null) { | |
377 return entry['type']; | |
378 } | |
379 return null; | |
380 } | |
381 | |
382 /** | |
383 * Wraps a JsArray and will call wrap_jso on its entries. | |
384 */ | |
385 class _DartHtmlWrappingList extends ListBase implements NativeFieldWrapperClass2 { | |
terry
2015/10/19 17:11:25
Doesn't need to be hidden?
Alan Knight
2015/10/19 18:28:02
Done.
| |
386 _DartHtmlWrappingList(this.blink_jsObject); | |
387 | |
388 final js.JsArray blink_jsObject; | |
389 | |
390 operator [](int index) => wrap_jso(js.JsNative.getArrayIndex(blink_jsObject, i ndex)); | |
391 | |
392 operator []=(int index, value) => blink_jsObject[index] = value; | |
393 | |
394 int get length => blink_jsObject.length; | |
395 int set length(int newLength) => blink_jsObject.length = newLength; | |
396 } | |
OLD | NEW |