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

Side by Side Diff: Source/bindings/dart/DartDebugHooks.js

Issue 18169002: Improve Dart Debugger performance and robustness by creating Dart wrappers using the standard SetNa… (Closed) Base URL: svn://svn.chromium.org/multivm/trunk/webkit
Patch Set: code review fixes Created 7 years, 5 months 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 /* 1 /*
2 * Copyright (C) 2012 Google Inc. All rights reserved. 2 * Copyright (C) 2012 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 14 matching lines...) Expand all
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */ 29 */
30 30
31 (function() { 31 (function() {
32 32
33 var DartDebug = {}; 33 var DartDebug = {};
34 34
35 function invokeDartCode(mirrorAPIFunction, proxy, memberName, args)
36 {
37 var unwrappedArgs = [];
38 for (var i = 0; i < args.length; ++i)
39 unwrappedArgs.push(DartDebug.unwrapValue(args[i]));
40 var result = DartDebug.nativeCallbacks.invocationTrampoline(
41 mirrorAPIFunction, [proxy, memberName, unwrappedArgs]);
42 return DartDebug.wrapValue(result);
43 }
44
45 DartDebug.ExecutionState = function(callFrames) 35 DartDebug.ExecutionState = function(callFrames)
46 { 36 {
47 this._callFrames = []; 37 this._callFrames = [];
48 for (var i = 0; i < callFrames.length; ++i) { 38 for (var i = 0; i < callFrames.length; ++i) {
49 this._callFrames.push(new DartDebug.FrameMirror(callFrames[i])); 39 this._callFrames.push(new DartDebug.FrameMirror(callFrames[i]));
50 } 40 }
51 }; 41 };
52 42
53 DartDebug.ExecutionState.prototype = { 43 DartDebug.ExecutionState.prototype = {
54 frameCount: function() 44 frameCount: function()
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
111 { 101 {
112 return this.url; 102 return this.url;
113 } 103 }
114 }; 104 };
115 105
116 DartDebug.FrameMirror = function(callFrame) 106 DartDebug.FrameMirror = function(callFrame)
117 { 107 {
118 this._functionName = callFrame.functionName; 108 this._functionName = callFrame.functionName;
119 this._scriptId = DartDebug.scriptURLToScriptId[callFrame.scriptURL]; 109 this._scriptId = DartDebug.scriptURLToScriptId[callFrame.scriptURL];
120 this._lineNumber = callFrame.lineNumber; 110 this._lineNumber = callFrame.lineNumber;
121 111 this._localScope = new DartDebug.ScopeMirror(callFrame.localScopeProxy, Scop eType.Local);
122 var localScopeObject = {} 112 this._globalScope = new DartDebug.ScopeMirror(callFrame.libraryProxy, ScopeT ype.Global);
123 localScopeObject.__proto__ = null;
124
125 for (var i = 0; i < callFrame.localVariables.length; i += 2) {
126 var name = callFrame.localVariables[i];
127 var value = callFrame.localVariables[i + 1];
128 var suffixIndex = name.indexOf('@');
129 if (suffixIndex != -1)
130 name = name.substr(0, suffixIndex);
131 localScopeObject[name] = value;
132 }
133 this._localScope = new DartDebug.ScopeMirror(localScopeObject, ScopeType.Loc al);
134
135 var libraryScopeObject = DartDebug.buildLibraryScopeObject(callFrame.library Proxy);
136 this._globalScope = new DartDebug.ScopeMirror(libraryScopeObject, ScopeType. Global);
137 113
138 this._scopes = [this._localScope, this._globalScope]; 114 this._scopes = [this._localScope, this._globalScope];
139 }; 115 };
140 116
141 DartDebug.FrameMirror.prototype = { 117 DartDebug.FrameMirror.prototype = {
142 func: function() 118 func: function()
143 { 119 {
144 var self = this; 120 var self = this;
145 return { 121 return {
146 name: function() { return self._functionName; }, 122 name: function() { return self._functionName; },
(...skipping 15 matching lines...) Expand all
162 scope: function(index) 138 scope: function(index)
163 { 139 {
164 return this._scopes[index]; 140 return this._scopes[index];
165 }, 141 },
166 142
167 evaluate: function(expression, disableBreak) 143 evaluate: function(expression, disableBreak)
168 { 144 {
169 // FIXME: Dart VM doesn't currently support evaluations. Use 145 // FIXME: Dart VM doesn't currently support evaluations. Use
170 // JavaScript eval and 'with' statement to emulate evaluation on Dart 146 // JavaScript eval and 'with' statement to emulate evaluation on Dart
171 // call frame. 147 // call frame.
172 var propertyMap = {};
173 var scopes = [this._globalScope, this._localScope];
174 for (var i = 0; i < scopes.length; ++i) {
175 var scopeObject = scopes[i]._object;
176 var propertyNames = Object.getOwnPropertyNames(scopeObject);
177 for (var j = 0; j < propertyNames.length; ++j) {
178 var name = propertyNames[j];
179 if (name !== 'this')
180 propertyMap[name] = scopeObject[name];
181 }
182 }
183 148
184 // FIXME: dartbug.com/10434 find a less fragile way to determine whether 149 // FIXME: dartbug.com/10434 find a less fragile way to determine whether
185 // we need to strip off console API support added by InjectedScript. 150 // we need to strip off console API support added by InjectedScript.
186 var CONSOLE_API_SUPPORT_HEADER = 151 var CONSOLE_API_SUPPORT_HEADER =
187 'with ((window && window.console && window.console._commandLineAPI) || {}) {\n'; 152 'with ((window && window.console && window.console._commandLineAPI) || {}) {\n';
188 if (expression.indexOf(CONSOLE_API_SUPPORT_HEADER) == 0) { 153 if (expression.indexOf(CONSOLE_API_SUPPORT_HEADER) == 0) {
189 expression = expression.substr(expression.indexOf('\n') + 1); 154 expression = expression.substr(expression.indexOf('\n') + 1);
190 expression = expression.substr(0, expression.lastIndexOf('\n')); 155 expression = expression.substr(0, expression.lastIndexOf('\n'));
191 } 156 }
192 var result = DartDebug.nativeCallbacks.evaluateInScope(expression, this. _localScope.receiver(), propertyMap); 157
158 var result = DartDebug.nativeCallbacks.evaluateInScope(expression, this. _localScope.receiver(),
159 this._globalScope._object, this._localScope._object);
193 return { value: function() { return result; } }; 160 return { value: function() { return result; } };
194 }, 161 },
195 162
196 get details_() 163 get details_()
197 { 164 {
198 var receiver = this._localScope.receiver(); 165 var receiver = this._localScope.receiver();
199 return { receiver: function() { return receiver; } }; 166 return { receiver: function() { return receiver; } };
200 } 167 }
201 }; 168 };
202 169
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
268 235
269 DartDebug.unregisterIsolate = function(isolateHandle) 236 DartDebug.unregisterIsolate = function(isolateHandle)
270 { 237 {
271 delete this.isolates[isolateHandle]; 238 delete this.isolates[isolateHandle];
272 if (Object.keys(this.isolates).length) 239 if (Object.keys(this.isolates).length)
273 return; 240 return;
274 241
275 // The page was destroyed. 242 // The page was destroyed.
276 DartDebug.scripts = {}; 243 DartDebug.scripts = {};
277 DartDebug.scriptURLToScriptId = {}; 244 DartDebug.scriptURLToScriptId = {};
278 245 DartDebug.libraryScopeCache = {};
279 DartDebug.breakpoints = {}; 246 DartDebug.breakpoints = {};
280 }; 247 };
281 248
282 DartDebug.isolateLoaded = function(isolateHandle) 249 DartDebug.isolateLoaded = function(isolateHandle)
283 { 250 {
284 var isolateScripts = DartDebug.nativeCallbacks.scriptsForIsolate(isolateHand le); 251 var isolateScripts = DartDebug.nativeCallbacks.scriptsForIsolate(isolateHand le);
285 for (var i = 0; i < isolateScripts.length; ++i) { 252 for (var i = 0; i < isolateScripts.length; ++i) {
286 var script = DartDebug.registerScript(isolateHandle, isolateScripts[i]); 253 var script = DartDebug.registerScript(isolateHandle, isolateScripts[i]);
287 if (!script) 254 if (!script)
288 continue; 255 continue;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 288
322 return script; 289 return script;
323 }; 290 };
324 291
325 DartDebug.updateExceptionPauseInfo = function() 292 DartDebug.updateExceptionPauseInfo = function()
326 { 293 {
327 for (var isolateHandle in DartDebug.isolates) 294 for (var isolateHandle in DartDebug.isolates)
328 DartDebug.nativeCallbacks.setExceptionPauseInfo(isolateHandle, Debug.isB reakOnException(), Debug.isBreakOnUncaughtException()); 295 DartDebug.nativeCallbacks.setExceptionPauseInfo(isolateHandle, Debug.isB reakOnException(), Debug.isBreakOnUncaughtException());
329 } 296 }
330 297
331 DartDebug.wrapValue = function(value)
332 {
333 if (!value || !value.isProxy)
334 return value;
335 var wrapper = DartDebug.mirrorAPI.isList(value) ? DartDebug.wrapList(value) : DartDebug.wrapObject(value);
336 DartDebug.nativeCallbacks.setHiddenValue(wrapper, 'proxy', value);
337 return wrapper;
338 }
339
340 DartDebug.unwrapValue = function(value)
341 {
342 var proxy = DartDebug.nativeCallbacks.getHiddenValue(value, 'proxy');
343 return proxy || value;
344 }
345
346 DartDebug.wrapList = function(arrayProxy)
347 {
348 function getter(index)
349 {
350 return DartDebug.wrapValue(DartDebug.mirrorAPI.listGetAt(arrayProxy, ind ex));
351 }
352
353 function setter(index, value)
354 {
355 DartDebug.mirrorAPI.listSetAt(arrayProxy, index, value);
356 }
357
358 function enumerator()
359 {
360 var indices = [];
361 var length = DartDebug.mirrorAPI.getField(arrayProxy, 'length');
362 for (var i = 0; i < length; ++i)
363 indices.push(i);
364 return indices;
365 }
366
367 var array = DartDebug.nativeCallbacks.createArrayWithIndexedPropertyHandler( getter, setter, enumerator);
368 array.length = DartDebug.mirrorAPI.getField(arrayProxy, 'length');
369 return array;
370 }
371
372 DartDebug.installProxyFieldsAndFunctions = function(proxy, getContainer, getCont ainerProxy,
373 filter, isLibrary, isClassDefinition)
374 {
375
376 function shouldInstallProperty(container, name)
377 {
378 if (!container || name in container)
379 return false;
380 return filter ? filter(name) : true;
381 }
382
383 function setAccessor(name, descriptor, hasGetter, hasSetter)
384 {
385 var container = getContainer(descriptor.isStatic);
386 if (!shouldInstallProperty(container, name))
387 return;
388 var containerProxy = getContainerProxy(descriptor.isStatic);
389 var getter;
390 if (hasGetter) {
391 getter = function()
392 {
393 return invokeDartCode(DartDebug.mirrorAPI.getField, containerPro xy, name, []);
394 };
395 }
396 var setter;
397 if (hasSetter) {
398 setter = function(value)
399 {
400 return invokeDartCode(DartDebug.mirrorAPI.setField, containerPro xy, name, [value]);
401 };
402 }
403 DartDebug.nativeCallbacks.setAccessor(container, name, getter, setter);
404 }
405
406 function setFunction(name, descriptor)
407 {
408 var container = getContainer(descriptor.isStatic);
409 if (!shouldInstallProperty(container, name))
410 return;
411 var containerProxy = getContainerProxy(descriptor.isStatic);
412 function invoke()
413 {
414 if (arguments.length < descriptor.fixedParameterCount ||
415 arguments.length > descriptor.fixedParameterCount + descriptor.o ptionalParamerterCount)
416 throw "NoSuchMethodException: incorrect number of arguments pass ed to function named '" + name + "'";
417 return invokeDartCode(DartDebug.mirrorAPI.invoke, containerProxy, na me, arguments);
418 }
419 Object.defineProperty(container, name, { value: invoke });
420 }
421
422 function setNamedConstructor(name, descriptor)
423 {
424 var container = getContainer(true);
425 var indexFirstDot = name.indexOf(".");
426 // Not a named constructor.
427 if (indexFirstDot == -1)
428 return;
429
430 var nameWithoutDot = name.substr(indexFirstDot + 1);
431 if (!shouldInstallProperty(container, nameWithoutDot))
432 return;
433 var containerProxy = getContainerProxy(descriptor.isStatic);
434 function invoke()
435 {
436 // FIXME: display the actual number of arguments and allowed range o f number of arguments.
437 if (arguments.length < descriptor.fixedParameterCount ||
438 arguments.length > descriptor.fixedParameterCount + descriptor.o ptionalParamerterCount)
439 throw "NoSuchMethodException: incorrect number of arguments pass ed to constructor '" + nameWithoutDot + "'";
440 return invokeDartCode(DartDebug.mirrorAPI.dartNew, containerProxy, n ameWithoutDot, arguments);
441 }
442 Object.defineProperty(container, nameWithoutDot, { value: invoke });
443 }
444
445 function setClass(name, descriptor)
446 {
447 var container = getContainer(true);
448 if (!shouldInstallProperty(container, name))
449 return;
450 var classProxy = DartDebug.createClassProxy(null, descriptor, name, prox y);
451 Object.defineProperty(container, name, { value: classProxy });
452 }
453
454 var variableNames = DartDebug.mirrorAPI.getVariableNames(proxy);
455 for (var i = 0; i < variableNames.length; ++i) {
456 var variableName = variableNames[i];
457 var variable = DartDebug.mirrorAPI.lookupVariable(proxy, variableName);
458 if (isClassDefinition && !variable.isStatic) continue;
459 setAccessor(variableName, variable, true, !variable.isFinal);
460 }
461
462 var functionNames = DartDebug.mirrorAPI.getFunctionNames(proxy);
463
464 var accessors = {};
465 for (var i = 0; i < functionNames.length; ++i) {
466 var functionName = functionNames[i];
467 var func = DartDebug.mirrorAPI.lookupFunction(proxy, functionName);
468 if (isClassDefinition && !func.isStatic && !func.isConstructor)
469 continue;
470
471 if (func.isAbstract)
472 continue;
473
474 if (func.isGetter) {
475 if (!accessors[functionName])
476 accessors[functionName] = {};
477 accessors[functionName].getter = func;
478 } else if (func.isSetter) {
479 // Remove trailing '='.
480 functionName = functionName.substr(0, functionName.length - 1);
481 if (!accessors[functionName])
482 accessors[functionName] = {};
483 accessors[functionName].setter = func;
484 } else if (!func.isConstructor) {
485 setFunction(functionName, func);
486 } else if (isClassDefinition && func.isConstructor){
487 setNamedConstructor(functionName, func);
488 }
489 }
490
491 if (isLibrary && !isClassDefinition) {
492 var classNames = DartDebug.mirrorAPI.getClassNames(proxy);
493 for (var i = 0; i < classNames.length; ++i) {
494 var className = classNames[i];
495 var clazz = DartDebug.mirrorAPI.lookupClass(proxy, className);
496 setClass(className, clazz);
497 }
498 }
499
500 for (var functionName in accessors) {
501 var accessor = accessors[functionName];
502 var func = accessor.getter || accessor.setter;
503 setAccessor(functionName, func, !!accessor.getter, !!accessor.setter);
504 }
505 }
506
507 DartDebug.wrapObject = function(objectProxy)
508 {
509 var classProxy = DartDebug.mirrorAPI.instanceGetClass(objectProxy);
510 var className = DartDebug.mirrorAPI.className(classProxy);
511 return DartDebug.createClassProxy(objectProxy, classProxy, className);
512 }
513
514 DartDebug.createClassProxy = function(objectProxy, classProxy, className, opt_li braryProxy)
515 {
516 // Create a fake constructor to set wrapper's class name.
517 var object;
518 if (objectProxy) {
519 // This is a class instance not a class definition object.
520 try {
521 fakeConstructor = eval('(function ' + className + '() {})');
522 object = new fakeConstructor();
523 } catch(e) {
524 object = {};
525 }
526 object.__proto__ = null;
527 } else {
528 // This is a class definition object.
529 // We need to wire up a default constructor if one exists.
530 // TODO(jacobr): there is some duplicated code here and for the named co nstructor case.
531 var myConstructor = null;
532 var functionNames = DartDebug.mirrorAPI.getFunctionNames(classProxy);
533 for (var i = 0; i < functionNames.length; ++i) {
534 var functionName = functionNames[i];
535 if (functionName != className)
536 continue;
537
538 var func = DartDebug.mirrorAPI.lookupFunction(classProxy, functionNa me);
539
540 if (func.isConstructor) {
541 myConstructor = func;
542 break;
543 }
544 }
545
546 var constructorStatement;
547 if (myConstructor != null) {
548 // FIXME: reduce duplicate code handling constructor invocation.
549 constructorStatement = '(function(invokeDartCode, DartDebug, classPr oxy, myConstructor) {' +
550 'return (function ' + className + '() {' +
551 'if (arguments.length < myConstructor.fixedParameterCount || ' +
552 'arguments.length > (myConstructor.fixedParameterCount + myConstructor.optionalParamerterCount)) ' +
553 'throw "NoSuchMethodException: incorrect number of argum ents passed to default constructor";' +
554 'return invokeDartCode(DartDebug.mirrorAPI.dartNew, classPro xy, "", arguments);' +
555 '})})';
556 } else {
557 // FIXME: throw a better error message.
558 constructorStatement = '(function() { return (function ' + className + '() { throw "' + className + ' does not have a constructor"})})';
559 }
560 try {
561 // FIXME: avoid using eval.
562 object = (eval(constructorStatement))(invokeDartCode, DartDebug, class Proxy, myConstructor);
563 } catch(e) {
564 object = {};
565 object['@ERROR'] = e;
566 object['@SOURCE'] = constructorStatement;
567 object.__proto__ = null;
568 }
569 object.toString = function() { return className + " [Dart Class]"; };
570 }
571
572 var classInfo = {};
573 classInfo.__proto__ = null;
574 classInfo['class'] = className;
575 var libraryProxy = opt_libraryProxy || DartDebug.mirrorAPI.classGetLibrary(c lassProxy);
576 classInfo['library'] = DartDebug.mirrorAPI.libraryUrl(libraryProxy);
577 Object.defineProperty(object, '@classInfo', { value: classInfo });
578
579 var staticFields = objectProxy != null ? {} : object;
580 staticFields.__proto__ = null;
581
582 function getContainer(isStatic) { return isStatic ? staticFields : object; }
583 function getContainerProxy(isStatic) { return isStatic ? classProxy : object Proxy || classProxy; }
584
585 while (classProxy) {
586 DartDebug.installProxyFieldsAndFunctions(
587 classProxy, getContainer, getContainerProxy, null, false, !objectPro xy);
588 if (!objectProxy)
589 break; // Static methods from parent classes should not be wired up to subclasses.
590 classProxy = DartDebug.mirrorAPI.getSuperclass(classProxy);
591 }
592
593 if (objectProxy != null) {
594 Object.defineProperty(object, '@staticFields', { value: staticFields });
595 }
596
597 return object;
598 }
599
600 DartDebug.buildLibraryScopeObject = function(libraryProxy)
601 {
602 var libraryScopeObject = {};
603 libraryScopeObject.__proto__ = null;
604
605 DartDebug.installProxyFieldsAndFunctions(
606 libraryProxy,
607 function() { return libraryScopeObject; },
608 function() { return libraryProxy; },
609 null,
610 true);
611
612 var imports = DartDebug.mirrorAPI.libraryImports(libraryProxy);
613 for (var i = 0; i < imports.length; i += 2) {
614 var prefix = imports[i];
615 var importedLibraryProxy = imports[i + 1];
616 var scopeObject = libraryScopeObject;
617 if (prefix) {
618 // Remove trailing '.'.
619 prefix = prefix.substr(0, prefix.length - 1);
620 // FIXME: remove the check below once dartbug.com/6131 is fixed.
621 if (!(prefix in libraryScopeObject)) {
622 scopeObject = {};
623 scopeObject.__proto__ = null;
624 Object.defineProperty(libraryScopeObject, prefix, { value: scope Object });
625 }
626 }
627 var filter = function(name) { return name[0] != '_'; };
628 var getContainer = function() { return scopeObject};
629 var getContainerProxy = function() { return importedLibraryProxy};
630 DartDebug.installProxyFieldsAndFunctions(importedLibraryProxy, getContai ner, getContainerProxy, filter, true);
631 }
632
633 return libraryScopeObject;
634 }
635
636 var originals = {}; 298 var originals = {};
637 299
638 originals.scripts = Debug.scripts; 300 originals.scripts = Debug.scripts;
639 301
640 Debug.scripts = function() 302 Debug.scripts = function()
641 { 303 {
642 var scripts = originals.scripts.apply(Debug); 304 var scripts = originals.scripts.apply(Debug);
643 for (var isolateHandle in DartDebug.isolates) { 305 for (var isolateHandle in DartDebug.isolates) {
644 var isolateScripts = DartDebug.nativeCallbacks.scriptsForIsolate(isolate Handle); 306 var isolateScripts = DartDebug.nativeCallbacks.scriptsForIsolate(isolate Handle);
645 for (var i = 0; i < isolateScripts.length; ++i) { 307 for (var i = 0; i < isolateScripts.length; ++i) {
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
735 397
736 Debug.clearBreakOnUncaughtException = function() 398 Debug.clearBreakOnUncaughtException = function()
737 { 399 {
738 originals.clearBreakOnUncaughtException.apply(Debug); 400 originals.clearBreakOnUncaughtException.apply(Debug);
739 DartDebug.updateExceptionPauseInfo(); 401 DartDebug.updateExceptionPauseInfo();
740 } 402 }
741 403
742 return DartDebug; 404 return DartDebug;
743 405
744 })() 406 })()
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698