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

Side by Side Diff: tools/dom/src/html_native_DOMImplementation.dart

Issue 680913006: Stop generating dart:blink from dart scripts (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Add dartium generated dart:blink to sdk Created 6 years, 1 month 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
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 part of html;
6
7 class _Property {
8 _Property(this.name) :
9 _hasValue = false,
10 writable = false,
11 isMethod = false,
12 isOwn = true,
13 wasThrown = false;
14
15 bool get hasValue => _hasValue;
16 get value => _value;
17 set value(v) {
18 _value = v;
19 _hasValue = true;
20 }
21
22 final String name;
23 Function setter;
24 Function getter;
25 var _value;
26 bool _hasValue;
27 bool writable;
28 bool isMethod;
29 bool isOwn;
30 bool wasThrown;
31 }
32
33 class _ConsoleVariables {
34 Map<String, Object> _data = new Map<String, Object>();
35
36 /**
37 * Forward member accesses to the backing JavaScript object.
38 */
39 noSuchMethod(Invocation invocation) {
40 String member = MirrorSystem.getName(invocation.memberName);
41 if (invocation.isGetter) {
42 return _data[member];
43 } else if (invocation.isSetter) {
44 assert(member.endsWith('='));
45 member = member.substring(0, member.length - 1);
46 _data[member] = invocation.positionalArguments[0];
47 } else {
48 return Function.apply(_data[member], invocation.positionalArguments,
49 invocation.namedArguments);
50 }
51 }
52
53 void clear() => _data.clear();
54
55 /**
56 * List all variables currently defined.
57 */
58 List variables() => _data.keys.toList();
59
60 void setVariable(String name, value) {
61 _data[name] = value;
62 }
63 }
64
65 /**
66 * Base class for invocation trampolines used to closurize methods, getters
67 * and setters.
68 */
69 abstract class _Trampoline implements Function {
70 final ObjectMirror _receiver;
71 final MethodMirror _methodMirror;
72 final Symbol _selector;
73
74 _Trampoline(this._receiver, this._methodMirror, this._selector);
75 }
76
77 class _MethodTrampoline extends _Trampoline {
78 _MethodTrampoline(ObjectMirror receiver, MethodMirror methodMirror,
79 Symbol selector) :
80 super(receiver, methodMirror, selector);
81
82 noSuchMethod(Invocation msg) {
83 if (msg.memberName != #call) return super.noSuchMethod(msg);
84 return _receiver.invoke(_selector,
85 msg.positionalArguments,
86 msg.namedArguments).reflectee;
87 }
88 }
89
90 /**
91 * Invocation trampoline class used to closurize getters.
92 */
93 class _GetterTrampoline extends _Trampoline {
94 _GetterTrampoline(ObjectMirror receiver, MethodMirror methodMirror,
95 Symbol selector) :
96 super(receiver, methodMirror, selector);
97
98 call() => _receiver.getField(_selector).reflectee;
99 }
100
101 /**
102 * Invocation trampoline class used to closurize setters.
103 */
104 class _SetterTrampoline extends _Trampoline {
105 _SetterTrampoline(ObjectMirror receiver, MethodMirror methodMirror,
106 Symbol selector) :
107 super(receiver, methodMirror, selector);
108
109 call(value) {
110 _receiver.setField(_selector, value);
111 }
112 }
113
114 class _Utils {
115 static double dateTimeToDouble(DateTime dateTime) =>
116 dateTime.millisecondsSinceEpoch.toDouble();
117 static DateTime doubleToDateTime(double dateTime) {
118 try {
119 return new DateTime.fromMillisecondsSinceEpoch(dateTime.toInt());
120 } catch(_) {
121 // TODO(antonnm): treat exceptions properly in bindings and
122 // find out how to treat NaNs.
123 return null;
124 }
125 }
126
127 static List convertToList(List list) {
128 // FIXME: [possible optimization]: do not copy the array if Dart_IsArray is fine w/ it.
129 final length = list.length;
130 List result = new List(length);
131 result.setRange(0, length, list);
132 return result;
133 }
134
135 static List convertMapToList(Map map) {
136 List result = [];
137 map.forEach((k, v) => result.addAll([k, v]));
138 return result;
139 }
140
141 static int convertCanvasElementGetContextMap(Map map) {
142 int result = 0;
143 if (map['alpha'] == true) result |= 0x01;
144 if (map['depth'] == true) result |= 0x02;
145 if (map['stencil'] == true) result |= 0x4;
146 if (map['antialias'] == true) result |= 0x08;
147 if (map['premultipliedAlpha'] == true) result |= 0x10;
148 if (map['preserveDrawingBuffer'] == true) result |= 0x20;
149
150 return result;
151 }
152
153 static void populateMap(Map result, List list) {
154 for (int i = 0; i < list.length; i += 2) {
155 result[list[i]] = list[i + 1];
156 }
157 }
158
159 static bool isMap(obj) => obj is Map;
160
161 static List toListIfIterable(obj) => obj is Iterable ? obj.toList() : null;
162
163 static Map createMap() => {};
164
165 static parseJson(String jsonSource) => const JsonDecoder().convert(jsonSource) ;
166
167 static makeUnimplementedError(String fileName, int lineNo) {
168 return new UnsupportedError('[info: $fileName:$lineNo]');
169 }
170
171 static bool isTypeSubclassOf(Type type, Type other) {
172 if (type == other) {
173 return true;
174 }
175 var superclass = reflectClass(type).superclass;
176 if (superclass != null) {
177 return isTypeSubclassOf(superclass.reflectedType, other);
178 }
179 return false;
180 }
181
182 static Element getAndValidateNativeType(Type type, String tagName) {
183 var element = new Element.tag(tagName);
184 if (!isTypeSubclassOf(type, element.runtimeType)) {
185 return null;
186 }
187 return element;
188 }
189
190 static window() => _blink.Blink_Utils.window();
191 static forwardingPrint(String message) => _blink.Blink_Utils.forwardingPrint(m essage);
192 // TODO(vsm): Make this API compatible with spawnUri. It should also
193 // return a Future<Isolate>.
194 static spawnDomUri(String uri) => _blink.Blink_Utils.spawnDomUri(uri);
195
196 // The following methods were added for debugger integration to make working
197 // with the Dart C mirrors API simpler.
198 // TODO(jacobr): consider moving them to a separate library.
199 // If Dart supported dynamic code injection, we would only inject this code
200 // when the debugger is invoked.
201
202 /**
203 * Strips the private secret prefix from member names of the form
204 * someName@hash.
205 */
206 static String stripMemberName(String name) {
207 int endIndex = name.indexOf('@');
208 return endIndex > 0 ? name.substring(0, endIndex) : name;
209 }
210
211 /**
212 * Takes a list containing variable names and corresponding values and
213 * returns a map from normalized names to values. Variable names are assumed
214 * to have list offsets 2*n values at offset 2*n+1. This method is required
215 * because Dart_GetLocalVariables returns a list instead of an object that
216 * can be queried to lookup names and values.
217 */
218 static Map<String, dynamic> createLocalVariablesMap(List localVariables) {
219 var map = {};
220 for (int i = 0; i < localVariables.length; i+=2) {
221 map[stripMemberName(localVariables[i])] = localVariables[i+1];
222 }
223 return map;
224 }
225
226 static _ConsoleVariables _consoleTempVariables = new _ConsoleVariables();
227
228 /**
229 * Takes an [expression] and a list of [local] variable and returns an
230 * expression for a closure with a body matching the original expression
231 * where locals are passed in as arguments. Returns a list containing the
232 * String expression for the closure and the list of arguments that should
233 * be passed to it. The expression should then be evaluated using
234 * Dart_EvaluateExpr which will generate a closure that should be invoked
235 * with the list of arguments passed to this method.
236 *
237 * For example:
238 * <code>
239 * _consoleTempVariables = {'a' : someValue, 'b': someOtherValue}
240 * wrapExpressionAsClosure("foo + bar + a", ["bar", 40, "foo", 2], true)
241 * </code>
242 * will return:
243 * <code>
244 * ["""(final $consoleVariables, final bar, final foo, final a, final b) =>
245 * (foo + bar + a
246 * )""",
247 * [_consoleTempVariables, 40, 2, someValue, someOtherValue]]
248 * </code>
249 */
250 static List wrapExpressionAsClosure(String expression, List locals,
251 bool includeCommandLineAPI) {
252 var args = {};
253 var sb = new StringBuffer("(");
254 addArg(arg, value) {
255 arg = stripMemberName(arg);
256 if (args.containsKey(arg)) return;
257 // We ignore arguments with the name 'this' rather than throwing an
258 // exception because Dart_GetLocalVariables includes 'this' and it
259 // is more convenient to filter it out here than from C++ code.
260 // 'this' needs to be handled by calling Dart_EvaluateExpr with
261 // 'this' as the target rather than by passing it as an argument.
262 if (arg == 'this') return;
263 if (args.isNotEmpty) {
264 sb.write(", ");
265 }
266 sb.write("final $arg");
267 args[arg] = value;
268 }
269
270 if (includeCommandLineAPI) {
271 addArg("\$consoleVariables", _consoleTempVariables);
272
273 // FIXME: use a real Dart tokenizer. The following regular expressions
274 // only allow setting variables at the immediate start of the expression
275 // to limit the number of edge cases we have to handle.
276
277 // Match expressions that start with "var x"
278 final _VARIABLE_DECLARATION = new RegExp("^(\\s*)var\\s+(\\w+)");
279 // Match expressions that start with "someExistingConsoleVar ="
280 final _SET_VARIABLE = new RegExp("^(\\s*)(\\w+)(\\s*=)");
281 // Match trailing semicolons.
282 final _ENDING_SEMICOLONS = new RegExp("(;\\s*)*\$");
283 expression = expression.replaceAllMapped(_VARIABLE_DECLARATION,
284 (match) {
285 var variableName = match[2];
286 // Set the console variable if it isn't already set.
287 if (!_consoleTempVariables._data.containsKey(variableName)) {
288 _consoleTempVariables._data[variableName] = null;
289 }
290 return "${match[1]}\$consoleVariables.${variableName}";
291 });
292
293 expression = expression.replaceAllMapped(_SET_VARIABLE,
294 (match) {
295 var variableName = match[2];
296 // Only rewrite if the name matches an existing console variable.
297 if (_consoleTempVariables._data.containsKey(variableName)) {
298 return "${match[1]}\$consoleVariables.${variableName}${match[3]}";
299 } else {
300 return match[0];
301 }
302 });
303
304 // We only allow dart expressions not Dart statements. Silently remove
305 // trailing semicolons the user might have added by accident to reduce the
306 // number of spurious compile errors.
307 expression = expression.replaceFirst(_ENDING_SEMICOLONS, "");
308 }
309
310 if (locals != null) {
311 for (int i = 0; i < locals.length; i+= 2) {
312 addArg(locals[i], locals[i+1]);
313 }
314 }
315 // Inject all the already defined console variables.
316 _consoleTempVariables._data.forEach(addArg);
317
318 // TODO(jacobr): remove the parentheses around the expresson once
319 // dartbug.com/13723 is fixed. Currently we wrap expression in parentheses
320 // to ensure only valid Dart expressions are allowed. Otherwise the DartVM
321 // quietly ignores trailing Dart statements resulting in user confusion
322 // when part of an invalid expression they entered is ignored.
323 sb..write(') => (\n$expression\n)');
324 return [sb.toString(), args.values.toList(growable: false)];
325 }
326
327 static String _getShortSymbolName(Symbol symbol,
328 DeclarationMirror declaration) {
329 var name = MirrorSystem.getName(symbol);
330 if (declaration is MethodMirror) {
331 if (declaration.isSetter && name[name.length-1] == "=") {
332 return name.substring(0, name.length-1);
333 }
334 if (declaration.isConstructor) {
335 return name.substring(name.indexOf('.') + 1);
336 }
337 }
338 return name;
339 }
340
341 /**
342 * Returns a list of completions to use if the receiver is o.
343 */
344 static List<String> getCompletions(o) {
345 MirrorSystem system = currentMirrorSystem();
346 var completions = new Set<String>();
347 addAll(Map<Symbol, dynamic> map, bool isStatic) {
348 map.forEach((symbol, mirror) {
349 if (mirror.isStatic == isStatic && !mirror.isPrivate) {
350 var name = MirrorSystem.getName(symbol);
351 if (mirror is MethodMirror && mirror.isSetter)
352 name = name.substring(0, name.length - 1);
353 completions.add(name);
354 }
355 });
356 }
357
358 addForClass(ClassMirror mirror, bool isStatic) {
359 if (mirror == null)
360 return;
361 addAll(mirror.declarations, isStatic);
362 if (mirror.superclass != null)
363 addForClass(mirror.superclass, isStatic);
364 for (var interface in mirror.superinterfaces) {
365 addForClass(interface, isStatic);
366 }
367 }
368
369 if (o is Type) {
370 addForClass(reflectClass(o), true);
371 } else {
372 addForClass(reflect(o).type, false);
373 }
374 return completions.toList(growable: false);
375 }
376
377 /**
378 * Adds all candidate String completitions from [declarations] to [output]
379 * filtering based on [staticContext] and [includePrivate].
380 */
381 static void _getCompletionsHelper(ClassMirror classMirror,
382 bool staticContext, LibraryMirror libraryMirror, Set<String> output) {
383 bool includePrivate = libraryMirror == classMirror.owner;
384 classMirror.declarations.forEach((symbol, declaration) {
385 if (!includePrivate && declaration.isPrivate) return;
386 if (declaration is VariableMirror) {
387 if (staticContext != declaration.isStatic) return;
388 } else if (declaration is MethodMirror) {
389 if (declaration.isOperator) return;
390 if (declaration.isConstructor) {
391 if (!staticContext) return;
392 var name = MirrorSystem.getName(declaration.constructorName);
393 if (name.isNotEmpty) output.add(name);
394 return;
395 }
396 if (staticContext != declaration.isStatic) return;
397 } else if (declaration is TypeMirror) {
398 return;
399 }
400 output.add(_getShortSymbolName(symbol, declaration));
401 });
402
403 if (!staticContext) {
404 for (var interface in classMirror.superinterfaces) {
405 _getCompletionsHelper(interface, staticContext,
406 libraryMirror, output);
407 }
408 if (classMirror.superclass != null) {
409 _getCompletionsHelper(classMirror.superclass, staticContext,
410 libraryMirror, output);
411 }
412 }
413 }
414
415 static void _getLibraryCompletionsHelper(
416 LibraryMirror library, bool includePrivate, Set<String> output) {
417 library.declarations.forEach((symbol, declaration) {
418 if (!includePrivate && declaration.isPrivate) return;
419 output.add(_getShortSymbolName(symbol, declaration));
420 });
421 }
422
423 static LibraryMirror getLibraryMirror(String url) =>
424 currentMirrorSystem().libraries[Uri.parse(url)];
425
426 /**
427 * Get code completions for [o] only showing privates from [libraryUrl].
428 */
429 static List<String> getObjectCompletions(o, String libraryUrl) {
430 var classMirror;
431 bool staticContext;
432 if (o is Type) {
433 classMirror = reflectClass(o);
434 staticContext = true;
435 } else {
436 classMirror = reflect(o).type;
437 staticContext = false;
438 }
439 var names = new Set<String>();
440 getClassCompletions(classMirror, names, staticContext, libraryUrl);
441 return names.toList()..sort();
442 }
443
444 static void getClassCompletions(ClassMirror classMirror, Set<String> names,
445 bool staticContext, String libraryUrl) {
446 LibraryMirror libraryMirror = getLibraryMirror(libraryUrl);
447 _getCompletionsHelper(classMirror, staticContext, libraryMirror, names);
448 }
449
450 static List<String> getLibraryCompletions(String url) {
451 var names = new Set<String>();
452 _getLibraryCompletionsHelper(getLibraryMirror(url), true, names);
453 return names.toList();
454 }
455
456 /**
457 * Get valid code completitions from within a library and all libraries
458 * imported by that library.
459 */
460 static List<String> getLibraryCompletionsIncludingImports(String url) {
461 var names = new Set<String>();
462 var libraryMirror = getLibraryMirror(url);
463 _getLibraryCompletionsHelper(libraryMirror, true, names);
464 for (var dependency in libraryMirror.libraryDependencies) {
465 if (dependency.isImport) {
466 if (dependency.prefix == null) {
467 _getLibraryCompletionsHelper(dependency.targetLibrary, false, names);
468 } else {
469 names.add(MirrorSystem.getName(dependency.prefix));
470 }
471 }
472 }
473 return names.toList();
474 }
475
476 static final SIDE_EFFECT_FREE_LIBRARIES = new Set<String>()
477 ..add('dart:html')
478 ..add('dart:indexed_db')
479 ..add('dart:svg')
480 ..add('dart:typed_data')
481 ..add('dart:web_audio')
482 ..add('dart:web_gl')
483 ..add('dart:web_sql');
484
485 static LibraryMirror _getLibrary(MethodMirror methodMirror) {
486 var owner = methodMirror.owner;
487 if (owner is ClassMirror) {
488 return owner;
489 } else if (owner is LibraryMirror) {
490 return owner;
491 }
492 return null;
493 }
494
495 /**
496 * For parity with the JavaScript debugger, we treat some getters as if
497 * they are fields so that users can see their values immediately.
498 * This matches JavaScript's behavior for getters on DOM objects.
499 * In the future we should consider adding an annotation to tag getters
500 * in user libraries as side effect free.
501 */
502 static bool _isSideEffectFreeGetter(MethodMirror methodMirror,
503 LibraryMirror libraryMirror) {
504 // This matches JavaScript behavior. We should consider displaying
505 // getters for all dart platform libraries rather than just the DOM
506 // libraries.
507 return libraryMirror.uri.scheme == 'dart' &&
508 SIDE_EFFECT_FREE_LIBRARIES.contains(libraryMirror.uri.toString());
509 }
510
511 /**
512 * Whether we should treat a property as a field for the purposes of the
513 * debugger.
514 */
515 static bool treatPropertyAsField(MethodMirror methodMirror,
516 LibraryMirror libraryMirror) {
517 return (methodMirror.isGetter || methodMirror.isSetter) &&
518 (methodMirror.isSynthetic ||
519 _isSideEffectFreeGetter(methodMirror,libraryMirror));
520 }
521
522 // TODO(jacobr): generate more concise function descriptions instead of
523 // dumping the entire function source.
524 static String describeFunction(function) {
525 if (function is _Trampoline) return function._methodMirror.source;
526 try {
527 var mirror = reflect(function);
528 return mirror.function.source;
529 } catch (e) {
530 return function.toString();
531 }
532 }
533
534 static List getInvocationTrampolineDetails(_Trampoline method) {
535 var loc = method._methodMirror.location;
536 return [loc.line, loc.column, loc.sourceUri.toString(),
537 MirrorSystem.getName(method._selector)];
538 }
539
540 static List getLibraryProperties(String libraryUrl, bool ownProperties,
541 bool accessorPropertiesOnly) {
542 var properties = new Map<String, _Property>();
543 var libraryMirror = getLibraryMirror(libraryUrl);
544 _addInstanceMirrors(libraryMirror, libraryMirror,
545 libraryMirror.declarations,
546 ownProperties, accessorPropertiesOnly, false, false,
547 properties);
548 if (!accessorPropertiesOnly) {
549 // We need to add class properties for all classes in the library.
550 libraryMirror.declarations.forEach((symbol, declarationMirror) {
551 if (declarationMirror is ClassMirror) {
552 var name = MirrorSystem.getName(symbol);
553 if (declarationMirror.hasReflectedType
554 && !properties.containsKey(name)) {
555 properties[name] = new _Property(name)
556 ..value = declarationMirror.reflectedType;
557 }
558 }
559 });
560 }
561 return packageProperties(properties);
562 }
563
564 static List getObjectProperties(o, bool ownProperties,
565 bool accessorPropertiesOnly) {
566 var properties = new Map<String, _Property>();
567 var names = new Set<String>();
568 var objectMirror = reflect(o);
569 var classMirror = objectMirror.type;
570 _addInstanceMirrors(objectMirror, classMirror.owner,
571 classMirror.instanceMembers,
572 ownProperties, accessorPropertiesOnly, false, true,
573 properties);
574 return packageProperties(properties);
575 }
576
577 static List getObjectClassProperties(o, bool ownProperties,
578 bool accessorPropertiesOnly) {
579 var properties = new Map<String, _Property>();
580 var objectMirror = reflect(o);
581 var classMirror = objectMirror.type;
582 _addInstanceMirrors(objectMirror, classMirror.owner,
583 classMirror.instanceMembers,
584 ownProperties, accessorPropertiesOnly, true, false,
585 properties);
586 _addStatics(classMirror, properties, accessorPropertiesOnly);
587 return packageProperties(properties);
588 }
589
590 static List getClassProperties(Type t, bool ownProperties,
591 bool accessorPropertiesOnly) {
592 var properties = new Map<String, _Property>();
593 var classMirror = reflectClass(t);
594 _addStatics(classMirror, properties, accessorPropertiesOnly);
595 return packageProperties(properties);
596 }
597
598 static void _addStatics(ClassMirror classMirror,
599 Map<String, _Property> properties,
600 bool accessorPropertiesOnly) {
601 var libraryMirror = classMirror.owner;
602 classMirror.declarations.forEach((symbol, declaration) {
603 var name = _getShortSymbolName(symbol, declaration);
604 if (name.isEmpty) return;
605 if (declaration is VariableMirror) {
606 if (accessorPropertiesOnly) return;
607 if (!declaration.isStatic) return;
608 properties.putIfAbsent(name, () => new _Property(name))
609 ..value = classMirror.getField(symbol).reflectee
610 ..writable = !declaration.isFinal && !declaration.isConst;
611 } else if (declaration is MethodMirror) {
612 MethodMirror methodMirror = declaration;
613 // FIXMEDART: should we display constructors?
614 if (methodMirror.isConstructor) return;
615 if (!methodMirror.isStatic) return;
616 if (accessorPropertiesOnly) {
617 if (methodMirror.isRegularMethod ||
618 treatPropertyAsField(methodMirror, libraryMirror)) {
619 return;
620 }
621 } else if (!methodMirror.isRegularMethod &&
622 !treatPropertyAsField(methodMirror, libraryMirror)) {
623 return;
624 }
625 var property = properties.putIfAbsent(name, () => new _Property(name));
626 _fillMethodMirrorProperty(libraryMirror, classMirror, methodMirror,
627 symbol, accessorPropertiesOnly, property);
628 }
629 });
630 }
631
632 static void _fillMethodMirrorProperty(LibraryMirror libraryMirror,
633 methodOwner, MethodMirror methodMirror, Symbol symbol,
634 bool accessorPropertiesOnly, _Property property) {
635 if (methodMirror.isRegularMethod) {
636 property
637 ..value = new _MethodTrampoline(methodOwner, methodMirror, symbol)
638 ..isMethod = true;
639 } else if (methodMirror.isGetter) {
640 if (treatPropertyAsField(methodMirror, libraryMirror)) {
641 try {
642 property.value = methodOwner.getField(symbol).reflectee;
643 } catch (e) {
644 property
645 ..wasThrown = true
646 ..value = e;
647 }
648 } else if (accessorPropertiesOnly) {
649 property.getter = new _GetterTrampoline(methodOwner,
650 methodMirror, symbol);
651 }
652 } else if (methodMirror.isSetter) {
653 if (accessorPropertiesOnly &&
654 !treatPropertyAsField(methodMirror, libraryMirror)) {
655 property.setter = new _SetterTrampoline(methodOwner,
656 methodMirror, MirrorSystem.getSymbol(property.name, libraryMirror));
657 }
658 property.writable = true;
659 }
660 }
661
662 /**
663 * Helper method that handles collecting up properties from classes
664 * or libraries using the filters [ownProperties], [accessorPropertiesOnly],
665 * [hideFields], and [hideMethods] to determine which properties are
666 * collected. [accessorPropertiesOnly] specifies whether all properties
667 * should be returned or just accessors. [hideFields] specifies whether
668 * fields should be hidden. hideMethods specifies whether methods should be
669 * shown or hidden. [ownProperties] is not currently used but is part of the
670 * Blink devtools API for enumerating properties.
671 */
672 static void _addInstanceMirrors(
673 ObjectMirror objectMirror,
674 LibraryMirror libraryMirror,
675 Map<Symbol, Mirror> declarations,
676 bool ownProperties, bool accessorPropertiesOnly,
677 bool hideFields, bool hideMethods,
678 Map<String, _Property> properties) {
679 declarations.forEach((symbol, declaration) {
680 if (declaration is TypedefMirror || declaration is ClassMirror) return;
681 var name = _getShortSymbolName(symbol, declaration);
682 if (name.isEmpty) return;
683 bool isField = declaration is VariableMirror ||
684 (declaration is MethodMirror &&
685 treatPropertyAsField(declaration, libraryMirror));
686 if ((isField && hideFields) || (hideMethods && !isField)) return;
687 if (accessorPropertiesOnly) {
688 if (declaration is VariableMirror || declaration.isRegularMethod ||
689 isField) {
690 return;
691 }
692 } else if (declaration is MethodMirror &&
693 (declaration.isGetter || declaration.isSetter) &&
694 !treatPropertyAsField(declaration, libraryMirror)) {
695 return;
696 }
697 var property = properties.putIfAbsent(name, () => new _Property(name));
698 if (declaration is VariableMirror) {
699 property
700 ..value = objectMirror.getField(symbol).reflectee
701 ..writable = !declaration.isFinal && !declaration.isConst;
702 return;
703 }
704 _fillMethodMirrorProperty(libraryMirror, objectMirror, declaration,
705 symbol, accessorPropertiesOnly, property);
706 });
707 }
708
709 /**
710 * Flatten down the properties data structure into a List that is easy to
711 * access from native code.
712 */
713 static List packageProperties(Map<String, _Property> properties) {
714 var ret = [];
715 for (var property in properties.values) {
716 ret.addAll([property.name,
717 property.setter,
718 property.getter,
719 property.value,
720 property.hasValue,
721 property.writable,
722 property.isMethod,
723 property.isOwn,
724 property.wasThrown]);
725 }
726 return ret;
727 }
728
729 /**
730 * Get a property, returning null if the property does not exist.
731 * For private property names, we attempt to resolve the property in the
732 * context of each library that the property name could be associated with.
733 */
734 static getObjectPropertySafe(o, String propertyName) {
735 var objectMirror = reflect(o);
736 var classMirror = objectMirror.type;
737 if (propertyName.startsWith("_")) {
738 var attemptedLibraries = new Set<LibraryMirror>();
739 while (classMirror != null) {
740 LibraryMirror library = classMirror.owner;
741 if (!attemptedLibraries.contains(library)) {
742 try {
743 return objectMirror.getField(
744 MirrorSystem.getSymbol(propertyName, library)).reflectee;
745 } catch (e) { }
746 attemptedLibraries.add(library);
747 }
748 classMirror = classMirror.superclass;
749 }
750 return null;
751 }
752 try {
753 return objectMirror.getField(
754 MirrorSystem.getSymbol(propertyName)).reflectee;
755 } catch (e) {
756 return null;
757 }
758 }
759
760 /**
761 * Helper to wrap the inspect method on InjectedScriptHost to provide the
762 * inspect method required for the
763 */
764 static List consoleApi(host) {
765 return [
766 "inspect",
767 (o) {
768 host.inspect(o, null);
769 return o;
770 },
771 "dir",
772 window().console.dir,
773 "dirxml",
774 window().console.dirxml
775 // FIXME: add copy method.
776 ];
777 }
778
779 static List getMapKeyList(Map map) => map.keys.toList();
780
781 static bool isNoSuchMethodError(obj) => obj is NoSuchMethodError;
782
783 static void register(Document document, String tag, Type type,
784 String extendsTagName) {
785 var nativeClass = _validateCustomType(type);
786
787 if (extendsTagName == null) {
788 if (nativeClass.reflectedType != HtmlElement) {
789 throw new UnsupportedError('Class must provide extendsTag if base '
790 'native class is not HTMLElement');
791 }
792 }
793
794 _register(document, tag, type, extendsTagName);
795 }
796
797 static void _register(Document document, String tag, Type customType,
798 String extendsTagName) => _blink.Blink_Utils.register(document, tag, customT ype, extendsTagName);
799
800 static Element createElement(Document document, String tagName) =>
801 _blink.Blink_Utils.createElement(document, tagName);
802
803 static void initializeCustomElement(HtmlElement element) =>
804 _blink.Blink_Utils.initializeCustomElement(element);
805
806 static Element changeElementWrapper(HtmlElement element, Type type) =>
807 _blink.Blink_Utils.changeElementWrapper(element, type);
808 }
809
810 class _DOMWindowCrossFrame extends NativeFieldWrapperClass2 implements
811 WindowBase {
812 _DOMWindowCrossFrame.internal();
813
814 // Fields.
815 HistoryBase get history => _blink.Blink_DOMWindowCrossFrame.get_history(this);
816 LocationBase get location => _blink.Blink_DOMWindowCrossFrame.get_location(thi s);
817 bool get closed => _blink.Blink_DOMWindowCrossFrame.get_closed(this);
818 WindowBase get opener => _blink.Blink_DOMWindowCrossFrame.get_opener(this);
819 WindowBase get parent => _blink.Blink_DOMWindowCrossFrame.get_parent(this);
820 WindowBase get top => _blink.Blink_DOMWindowCrossFrame.get_top(this);
821
822 // Methods.
823 void close() => _blink.Blink_DOMWindowCrossFrame.close(this);
824 void postMessage(/*SerializedScriptValue*/ message, String targetOrigin, [List messagePorts]) =>
825 _blink.Blink_DOMWindowCrossFrame.postMessage(this, message, targetOrigin, me ssagePorts);
826
827 // Implementation support.
828 String get typeName => "Window";
829
830 // TODO(efortuna): Remove this method. dartbug.com/16814
831 Events get on => throw new UnsupportedError(
832 'You can only attach EventListeners to your own window.');
833 // TODO(efortuna): Remove this method. dartbug.com/16814
834 void _addEventListener([String type, EventListener listener, bool useCapture])
835 => throw new UnsupportedError(
836 'You can only attach EventListeners to your own window.');
837 // TODO(efortuna): Remove this method. dartbug.com/16814
838 void addEventListener(String type, EventListener listener, [bool useCapture])
839 => throw new UnsupportedError(
840 'You can only attach EventListeners to your own window.');
841 // TODO(efortuna): Remove this method. dartbug.com/16814
842 bool dispatchEvent(Event event) => throw new UnsupportedError(
843 'You can only attach EventListeners to your own window.');
844 // TODO(efortuna): Remove this method. dartbug.com/16814
845 void _removeEventListener([String type, EventListener listener,
846 bool useCapture]) => throw new UnsupportedError(
847 'You can only attach EventListeners to your own window.');
848 // TODO(efortuna): Remove this method. dartbug.com/16814
849 void removeEventListener(String type, EventListener listener,
850 [bool useCapture]) => throw new UnsupportedError(
851 'You can only attach EventListeners to your own window.');
852 }
853
854 class _HistoryCrossFrame extends NativeFieldWrapperClass2 implements HistoryBase {
855 _HistoryCrossFrame.internal();
856
857 // Methods.
858 void back() => _blink.Blink_HistoryCrossFrame.back(this);
859 void forward() => _blink.Blink_HistoryCrossFrame.forward(this);
860 void go(int distance) => _blink.Blink_HistoryCrossFrame.go(this, distance);
861
862 // Implementation support.
863 String get typeName => "History";
864 }
865
866 class _LocationCrossFrame extends NativeFieldWrapperClass2 implements LocationBa se {
867 _LocationCrossFrame.internal();
868
869 // Fields.
870 void set href(String h) => _blink.Blink_LocationCrossFrame.set_href(this, h);
871
872 // Implementation support.
873 String get typeName => "Location";
874 }
875
876 class _DOMStringMap extends NativeFieldWrapperClass2 implements Map<String, Stri ng> {
877 _DOMStringMap.internal();
878
879 bool containsValue(String value) => Maps.containsValue(this, value);
880 bool containsKey(String key) => _blink.Blink_DOMStringMap.containsKey(this, ke y);
881 String operator [](String key) => _blink.Blink_DOMStringMap.item(this, key);
882 void operator []=(String key, String value) => _blink.Blink_DOMStringMap.setIt em(this, key, value);
883 String putIfAbsent(String key, String ifAbsent()) => Maps.putIfAbsent(this, ke y, ifAbsent);
884 String remove(String key) => _blink.Blink_DOMStringMap.remove(this, key);
885 void clear() => Maps.clear(this);
886 void forEach(void f(String key, String value)) => Maps.forEach(this, f);
887 Iterable<String> get keys => _blink.Blink_DOMStringMap.get_keys(this);
888 Iterable<String> get values => Maps.getValues(this);
889 int get length => Maps.length(this);
890 bool get isEmpty => Maps.isEmpty(this);
891 bool get isNotEmpty => Maps.isNotEmpty(this);
892 void addAll(Map<String, String> other) {
893 other.forEach((key, value) => this[key] = value);
894 }
895 }
896
897 final _printClosure = (s) => window.console.log(s);
898 final _pureIsolatePrintClosure = (s) {
899 throw new UnimplementedError("Printing from a background isolate "
900 "is not supported in the browser");
901 };
902
903 final _forwardingPrintClosure = _Utils.forwardingPrint;
904
905 final _uriBaseClosure = () => Uri.parse(window.location.href);
906
907 final _pureIsolateUriBaseClosure = () {
908 throw new UnimplementedError("Uri.base on a background isolate "
909 "is not supported in the browser");
910 };
911
912 class _Timer implements Timer {
913 static const int _STATE_TIMEOUT = 0;
914 static const int _STATE_INTERVAL = 1;
915 int _state;
916
917 _Timer(int milliSeconds, void callback(Timer timer), bool repeating) {
918 if (repeating) {
919 _state = (window._setInterval(() {
920 callback(this);
921 }, milliSeconds) << 1) | _STATE_INTERVAL;
922 } else {
923 _state = (window._setTimeout(() {
924 _state = null;
925 callback(this);
926 }, milliSeconds) << 1) | _STATE_TIMEOUT;
927 }
928 }
929
930 void cancel() {
931 if (_state == null) return;
932 int id = _state >> 1;
933 if ((_state & 1) == _STATE_TIMEOUT) {
934 window._clearTimeout(id);
935 } else {
936 window._clearInterval(id);
937 }
938 _state = null;
939 }
940
941 bool get isActive => _state != null;
942 }
943
944 get _timerFactoryClosure =>
945 (int milliSeconds, void callback(Timer timer), bool repeating) {
946 return new _Timer(milliSeconds, callback, repeating);
947 };
948
949 get _pureIsolateTimerFactoryClosure =>
950 ((int milliSeconds, void callback(Timer time), bool repeating) =>
951 throw new UnimplementedError("Timers on background isolates "
952 "are not supported in the browser"));
953
954 class _ScheduleImmediateHelper {
955 MutationObserver _observer;
956 final DivElement _div = new DivElement();
957 Function _callback;
958
959 _ScheduleImmediateHelper() {
960 // Run in the root-zone as the DOM callback would otherwise execute in the
961 // current zone.
962 Zone.ROOT.run(() {
963 // Mutation events get fired as soon as the current event stack is unwound
964 // so we just make a dummy event and listen for that.
965 _observer = new MutationObserver(_handleMutation);
966 _observer.observe(_div, attributes: true);
967 });
968 }
969
970 void _schedule(callback) {
971 if (_callback != null) {
972 throw new StateError(
973 'Only one immediate callback can be scheduled at once');
974 }
975 _callback = callback;
976 // Toggle it to trigger the mutation event.
977 _div.hidden = !_div.hidden;
978 }
979
980 _handleMutation(List<MutationRecord> mutations, MutationObserver observer) {
981 var tmp = _callback;
982 _callback = null;
983 tmp();
984 }
985 }
986
987 final _ScheduleImmediateHelper _scheduleImmediateHelper =
988 new _ScheduleImmediateHelper();
989
990 get _scheduleImmediateClosure => (void callback()) {
991 _scheduleImmediateHelper._schedule(callback);
992 };
993
994 get _pureIsolateScheduleImmediateClosure => ((void callback()) =>
995 throw new UnimplementedError("scheduleMicrotask in background isolates "
996 "are not supported in the browser"));
997
998 void _initializeCustomElement(Element e) {
999 _Utils.initializeCustomElement(e);
1000 }
1001
1002 // Class for unsupported native browser 'DOM' objects.
1003 class _UnsupportedBrowserObject extends NativeFieldWrapperClass2 {
1004 }
OLDNEW
« no previous file with comments | « tools/dom/src/blink_native_DOMImplementation.dart ('k') | tools/dom/src/native_DOMImplementation.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698