WebKit Bugzilla
Attachment 356288 Details for
Bug 176766
: Web Inspector: Implement `queryObjects` Command Line API
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-176766-20181130203431.patch (text/plain), 38.18 KB, created by
Devin Rousso
on 2018-11-30 20:34:32 PST
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Devin Rousso
Created:
2018-11-30 20:34:32 PST
Size:
38.18 KB
patch
obsolete
>diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog >index 676d21b7016b1699ab8d3f187cef6c068160a2e0..8309e76c954a78deb25036c063184a0f1e9e87ea 100644 >--- a/Source/JavaScriptCore/ChangeLog >+++ b/Source/JavaScriptCore/ChangeLog >@@ -1,3 +1,45 @@ >+2018-11-30 Devin Rousso <webkit@devinrousso.com> >+ >+ Web Inspector: Implement `queryObjects` Command Line API >+ https://bugs.webkit.org/show_bug.cgi?id=176766 >+ <rdar://problem/34890689> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Introduces a new Command Line function called `queryObjects` that will return an array of >+ object that have the given constructor/prototype argument in their prototype chain. >+ - `queryObjects(Promise)` will return an array of all Promises. >+ - `queryObjects(Foo)` will return all objects created with the constructor `Foo`. >+ >+ Currently, an error is thrown if the first argument is one of the following: >+ - Object >+ - Object.prototype >+ - Function >+ - Function.prototype >+ - Array >+ - Array.prototype >+ - Map >+ - Map.prototype >+ - Set >+ - Set.prototype >+ - Proxy >+ >+ The reason for this is that we don't want to expose any internal/builtin objects, as some of >+ them are highly sensitive and undefined behaviour can occur if they are modified. >+ >+ * inspector/JSInjectedScriptHost.h: >+ * inspector/JSInjectedScriptHost.cpp: >+ (Inspector::checkForbiddenPrototype): >+ (Inspector::JSInjectedScriptHost::queryObjects): >+ Does a GC and then iterates over all live JSCell in the heap to find these objects. >+ >+ * inspector/JSInjectedScriptHostPrototype.cpp: >+ (Inspector::JSInjectedScriptHostPrototype::finishCreation): >+ (Inspector::jsInjectedScriptHostPrototypeFunctionQueryObjects): >+ >+ * inspector/InjectedScriptSource.js: >+ (queryObjects): >+ > 2018-11-29 Justin Michaud <justin_michaud@apple.com> > > CSS Painting API should pass 'this' correctly to paint callback, and repaint when properties change. >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index f3ca220be3f930eac7f9a58912684a33db482b2f..7c85de160f3972f7b69cc25ae2b80e0344905ae6 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,17 @@ >+2018-11-30 Devin Rousso <webkit@devinrousso.com> >+ >+ Web Inspector: Implement `queryObjects` Command Line API >+ https://bugs.webkit.org/show_bug.cgi?id=176766 >+ <rdar://problem/34890689> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Test: inspector/console/queryObjects.html >+ >+ * inspector/CommandLineAPIModuleSource.js: >+ (CommandLineAPI): >+ (CommandLineAPIImpl.prototype.queryObjects): >+ > 2018-11-29 Frederic Wang <fwang@igalia.com> > > Separate paint and scroll offsets for RenderLayerBacking::m_scrollingContentsLayer >diff --git a/Source/WebInspectorUI/ChangeLog b/Source/WebInspectorUI/ChangeLog >index a8e1de9a0cfd0c5e34ea4a1df1dcb17fe8067135..cc0bf02ce83dca18eff86e1cbc7e16e089d04959 100644 >--- a/Source/WebInspectorUI/ChangeLog >+++ b/Source/WebInspectorUI/ChangeLog >@@ -1,3 +1,15 @@ >+2018-11-30 Devin Rousso <webkit@devinrousso.com> >+ >+ Web Inspector: Implement `queryObjects` Command Line API >+ https://bugs.webkit.org/show_bug.cgi?id=176766 >+ <rdar://problem/34890689> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * UserInterface/Controllers/JavaScriptRuntimeCompletionProvider.js: >+ (WI.JavaScriptRuntimeCompletionProvider.completionControllerCompletionsNeeded.receivedPropertyNames): >+ Add `queryObjects` to the list of command line functions. >+ > 2018-11-29 Matt Baker <mattbaker@apple.com> > > Web Inspector: RTL: disclosure triangles should be flipped and aligned right >diff --git a/Source/JavaScriptCore/inspector/InjectedScriptSource.js b/Source/JavaScriptCore/inspector/InjectedScriptSource.js >index d6b75f1fecd79af702f9ed58000423238343668a..e8646d8754b2d5465d7e902b1fcae8646dcb6cf7 100644 >--- a/Source/JavaScriptCore/inspector/InjectedScriptSource.js >+++ b/Source/JavaScriptCore/inspector/InjectedScriptSource.js >@@ -1410,6 +1410,10 @@ BasicCommandLineAPI.methods = [ > result.push(object[key]); > return result; > }, >+ >+ function queryObjects(prototypeOrConstructor) { >+ return InjectedScriptHost.queryObjects(prototypeOrConstructor); >+ }, > ]; > > for (let i = 0; i < BasicCommandLineAPI.methods.length; ++i) { >diff --git a/Source/JavaScriptCore/inspector/JSInjectedScriptHost.cpp b/Source/JavaScriptCore/inspector/JSInjectedScriptHost.cpp >index 71d7c406550db7c99f67c78e9fe33a3cc99b1870..6acb93f8a3cd97ab8df858b91e051fc23cb1822c 100644 >--- a/Source/JavaScriptCore/inspector/JSInjectedScriptHost.cpp >+++ b/Source/JavaScriptCore/inspector/JSInjectedScriptHost.cpp >@@ -27,11 +27,14 @@ > #include "JSInjectedScriptHost.h" > > #include "ArrayIteratorPrototype.h" >+#include "ArrayPrototype.h" > #include "BuiltinNames.h" > #include "Completion.h" > #include "DateInstance.h" > #include "DirectArguments.h" > #include "Error.h" >+#include "FunctionPrototype.h" >+#include "HeapIterationScope.h" > #include "InjectedScriptHost.h" > #include "IterationKind.h" > #include "IteratorOperations.h" >@@ -51,11 +54,15 @@ > #include "JSWeakSet.h" > #include "JSWithScope.h" > #include "MapIteratorPrototype.h" >+#include "MapPrototype.h" >+#include "MarkedSpaceInlines.h" > #include "ObjectConstructor.h" >+#include "ObjectPrototype.h" > #include "ProxyObject.h" > #include "RegExpObject.h" > #include "ScopedArguments.h" > #include "SetIteratorPrototype.h" >+#include "SetPrototype.h" > #include "SourceCode.h" > #include "TypedArrayInlines.h" > >@@ -621,4 +628,77 @@ JSValue JSInjectedScriptHost::iteratorEntries(ExecState* exec) > return array; > } > >+static bool checkForbiddenPrototype(ExecState* exec, JSValue value, JSValue proto) >+{ >+ if (value == proto) >+ return true; >+ >+ // Check that the prototype chain of proto hasn't been modified to include value. >+ return JSObject::defaultHasInstance(exec, proto, value); >+} >+ >+JSValue JSInjectedScriptHost::queryObjects(ExecState* exec) >+{ >+ if (exec->argumentCount() < 1) >+ return jsUndefined(); >+ >+ VM& vm = exec->vm(); >+ auto scope = DECLARE_THROW_SCOPE(vm); >+ >+ JSValue prototypeOrConstructor = exec->uncheckedArgument(0); >+ if (!prototypeOrConstructor.isObject()) >+ return throwTypeError(exec, scope, "queryObjects first argument must be an object."_s); >+ >+ JSObject* object = asObject(prototypeOrConstructor); >+ if (object->inherits<ProxyObject>(vm)) >+ return throwTypeError(exec, scope, "queryObjects cannot be called with a Proxy."_s); >+ >+ JSValue prototype = object; >+ >+ JSValue constructorPrototype = object->get(exec, vm.propertyNames->prototype); >+ RETURN_IF_EXCEPTION(scope, { }); >+ if (constructorPrototype.isObject()) { >+ prototype = constructorPrototype; >+ object = asObject(prototype); >+ } >+ >+ if (object->inherits<ProxyObject>(vm) || prototype.inherits<ProxyObject>(vm)) >+ return throwTypeError(exec, scope, "queryObjects cannot be called with a Proxy."_s); >+ >+ // FIXME: implement a way of distinguishing between internal and user-created objects. >+ JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject(); >+ if (checkForbiddenPrototype(exec, object, lexicalGlobalObject->objectPrototype())) >+ return throwTypeError(exec, scope, "queryObjects cannot be called with Object."_s); >+ if (checkForbiddenPrototype(exec, object, lexicalGlobalObject->functionPrototype())) >+ return throwTypeError(exec, scope, "queryObjects cannot be called with Function."_s); >+ if (checkForbiddenPrototype(exec, object, lexicalGlobalObject->arrayPrototype())) >+ return throwTypeError(exec, scope, "queryObjects cannot be called with Array."_s); >+ if (checkForbiddenPrototype(exec, object, lexicalGlobalObject->mapPrototype())) >+ return throwTypeError(exec, scope, "queryObjects cannot be called with Map."_s); >+ if (checkForbiddenPrototype(exec, object, lexicalGlobalObject->jsSetPrototype())) >+ return throwTypeError(exec, scope, "queryObjects cannot be called with Set."_s); >+ >+ sanitizeStackForVM(&vm); >+ vm.heap.collectNow(Sync, CollectionScope::Full); >+ >+ JSArray* array = constructEmptyArray(exec, nullptr); >+ RETURN_IF_EXCEPTION(scope, { }); >+ >+ { >+ HeapIterationScope iterationScope(vm.heap); >+ vm.heap.objectSpace().forEachLiveCell(iterationScope, [&] (HeapCell* cell, HeapCell::Kind kind) { >+ if (kind != HeapCell::JSCell) >+ return IterationStatus::Continue; >+ >+ JSValue value(static_cast<JSCell*>(cell)); >+ if (JSObject::defaultHasInstance(exec, value, prototype)) >+ array->putDirectIndex(exec, array->length(), value); >+ >+ return IterationStatus::Continue; >+ }); >+ } >+ >+ return array; >+} >+ > } // namespace Inspector >diff --git a/Source/JavaScriptCore/inspector/JSInjectedScriptHost.h b/Source/JavaScriptCore/inspector/JSInjectedScriptHost.h >index 4035a69f466547ac3eb4385337f2efaffe7ff0f2..bacc37aab17308d6f21891e79c7090a5979f7643 100644 >--- a/Source/JavaScriptCore/inspector/JSInjectedScriptHost.h >+++ b/Source/JavaScriptCore/inspector/JSInjectedScriptHost.h >@@ -71,6 +71,7 @@ public: > JSC::JSValue weakSetSize(JSC::ExecState*); > JSC::JSValue weakSetEntries(JSC::ExecState*); > JSC::JSValue iteratorEntries(JSC::ExecState*); >+ JSC::JSValue queryObjects(JSC::ExecState*); > > protected: > void finishCreation(JSC::VM&); >diff --git a/Source/JavaScriptCore/inspector/JSInjectedScriptHostPrototype.cpp b/Source/JavaScriptCore/inspector/JSInjectedScriptHostPrototype.cpp >index 549332962b794de867d8a026a514418def3ae9ec..f3960de9673a12c3c36e0c7fdc17e97f3065a237 100644 >--- a/Source/JavaScriptCore/inspector/JSInjectedScriptHostPrototype.cpp >+++ b/Source/JavaScriptCore/inspector/JSInjectedScriptHostPrototype.cpp >@@ -49,6 +49,7 @@ static EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionWeakMap > static EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionWeakSetSize(ExecState*); > static EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionWeakSetEntries(ExecState*); > static EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionIteratorEntries(ExecState*); >+static EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionQueryObjects(ExecState*); > static EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionEvaluateWithScopeExtension(ExecState*); > > static EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeAttributeEvaluate(ExecState*); >@@ -72,6 +73,7 @@ void JSInjectedScriptHostPrototype::finishCreation(VM& vm, JSGlobalObject* globa > JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("weakSetSize", jsInjectedScriptHostPrototypeFunctionWeakSetSize, static_cast<unsigned>(PropertyAttribute::DontEnum), 1); > JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("weakSetEntries", jsInjectedScriptHostPrototypeFunctionWeakSetEntries, static_cast<unsigned>(PropertyAttribute::DontEnum), 1); > JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("iteratorEntries", jsInjectedScriptHostPrototypeFunctionIteratorEntries, static_cast<unsigned>(PropertyAttribute::DontEnum), 1); >+ JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("queryObjects", jsInjectedScriptHostPrototypeFunctionQueryObjects, static_cast<unsigned>(PropertyAttribute::DontEnum), 1); > JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION("evaluateWithScopeExtension", jsInjectedScriptHostPrototypeFunctionEvaluateWithScopeExtension, static_cast<unsigned>(PropertyAttribute::DontEnum), 1); > > JSC_NATIVE_GETTER("evaluate", jsInjectedScriptHostPrototypeAttributeEvaluate, PropertyAttribute::DontEnum | PropertyAttribute::Accessor); >@@ -194,6 +196,19 @@ EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionIteratorEntrie > return JSValue::encode(castedThis->iteratorEntries(exec)); > } > >+EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionQueryObjects(ExecState* exec) >+{ >+ VM& vm = exec->vm(); >+ auto scope = DECLARE_THROW_SCOPE(vm); >+ >+ JSValue thisValue = exec->thisValue(); >+ JSInjectedScriptHost* castedThis = jsDynamicCast<JSInjectedScriptHost*>(vm, thisValue); >+ if (!castedThis) >+ return throwVMTypeError(exec, scope); >+ >+ return JSValue::encode(castedThis->queryObjects(exec)); >+} >+ > EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionEvaluateWithScopeExtension(ExecState* exec) > { > VM& vm = exec->vm(); >diff --git a/Source/WebCore/inspector/CommandLineAPIModuleSource.js b/Source/WebCore/inspector/CommandLineAPIModuleSource.js >index 7cf4fcdaaaa2ef4d964d9f7ee6b9423a64706d0b..a59efef890da236730937d7474cb935244b88dc9 100644 >--- a/Source/WebCore/inspector/CommandLineAPIModuleSource.js >+++ b/Source/WebCore/inspector/CommandLineAPIModuleSource.js >@@ -57,9 +57,10 @@ function CommandLineAPI(commandLineAPIImpl, callFrame) > this.__defineGetter__("$" + i, bind(injectedScript._savedResult, injectedScript, i)); > > // Command Line API methods. >- for (let member of CommandLineAPI.members_) { >- this[member] = bind(commandLineAPIImpl[member], commandLineAPIImpl); >- this[member].toString = function() { return "function " + member + "() { [Command Line API] }" }; >+ for (let i = 0; i < CommandLineAPI.methods.length; ++i) { >+ let method = CommandLineAPI.methods[i]; >+ this[method] = bind(commandLineAPIImpl[method], commandLineAPIImpl); >+ this[method].toString = function() { return "function " + method + "() { [Command Line API] }" }; > } > } > >@@ -67,9 +68,24 @@ function CommandLineAPI(commandLineAPIImpl, callFrame) > * @type {Array.<string>} > * @const > */ >-CommandLineAPI.members_ = [ >- "$", "$$", "$x", "dir", "dirxml", "keys", "values", "profile", "profileEnd", "table", >- "monitorEvents", "unmonitorEvents", "inspect", "copy", "clear", "getEventListeners" >+CommandLineAPI.methods = [ >+ "$", >+ "$$", >+ "$x", >+ "clear", >+ "copy", >+ "dir", >+ "dirxml", >+ "getEventListeners", >+ "inspect", >+ "keys", >+ "monitorEvents", >+ "profile", >+ "profileEnd", >+ "queryObjects", >+ "table", >+ "unmonitorEvents", >+ "values", > ]; > > /** >@@ -221,6 +237,11 @@ CommandLineAPIImpl.prototype = { > return this._inspect(object); > }, > >+ queryObjects(prototypeOrConstructor) >+ { >+ return InjectedScriptHost.queryObjects(prototypeOrConstructor); >+ }, >+ > copy: function(object) > { > var string; >diff --git a/Source/WebInspectorUI/UserInterface/Controllers/JavaScriptRuntimeCompletionProvider.js b/Source/WebInspectorUI/UserInterface/Controllers/JavaScriptRuntimeCompletionProvider.js >index aebd456ca068290aa4bef51e0ceac753350065da..f23df46b130b4707a157bb1ce182996f9c40510f 100644 >--- a/Source/WebInspectorUI/UserInterface/Controllers/JavaScriptRuntimeCompletionProvider.js >+++ b/Source/WebInspectorUI/UserInterface/Controllers/JavaScriptRuntimeCompletionProvider.js >@@ -218,14 +218,14 @@ WI.JavaScriptRuntimeCompletionProvider = class JavaScriptRuntimeCompletionProvid > WI.runtimeManager.activeExecutionContext.target.RuntimeAgent.releaseObjectGroup("completion"); > > if (!base) { >- var commandLineAPI = ["$", "$$", "$x", "dir", "dirxml", "keys", "values", "profile", "profileEnd", "monitorEvents", "unmonitorEvents", "inspect", "copy", "clear", "getEventListeners", "$0", "$_"]; >+ let commandLineAPI = WI.JavaScriptRuntimeCompletionProvider._commandLineAPI.slice(0); > if (WI.debuggerManager.paused) { > let targetData = WI.debuggerManager.dataForTarget(WI.runtimeManager.activeExecutionContext.target); > if (targetData.pauseReason === WI.DebuggerManager.PauseReason.Exception) > commandLineAPI.push("$exception"); > } >- for (var i = 0; i < commandLineAPI.length; ++i) >- propertyNames[commandLineAPI[i]] = true; >+ for (let name of commandLineAPI) >+ propertyNames[name] = true; > > // FIXME: Due to caching, sometimes old $n values show up as completion results even though they are not available. We should clear that proactively. > for (var i = 1; i <= WI.ConsoleCommandResultMessage.maximumSavedResultIndex; ++i) >@@ -301,3 +301,25 @@ WI.JavaScriptRuntimeCompletionProvider = class JavaScriptRuntimeCompletionProvid > this._lastPropertyNames = null; > } > }; >+ >+WI.JavaScriptRuntimeCompletionProvider._commandLineAPI = [ >+ "$", >+ "$$", >+ "$0", >+ "$_", >+ "$x", >+ "clear", >+ "copy", >+ "dir", >+ "dirxml", >+ "getEventListeners", >+ "inspect", >+ "keys", >+ "monitorEvents", >+ "profile", >+ "profileEnd", >+ "queryObjects", >+ "table", >+ "unmonitorEvents", >+ "values", >+]; >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index 8a41c60d2ded46a9440ff52ee78036448d75bf9f..68917681df34d8a0692cbaf2b5af7142adeed06f 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,16 @@ >+2018-11-30 Devin Rousso <webkit@devinrousso.com> >+ >+ Web Inspector: Implement `queryObjects` Command Line API >+ https://bugs.webkit.org/show_bug.cgi?id=176766 >+ <rdar://problem/34890689> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * inspector/console/queryObjects-expected.html: Added. >+ * inspector/console/queryObjects.html: Added. >+ >+ * http/tests/inspector/console/cross-domain-inspected-node-access-expected.txt: >+ > 2018-11-29 Frederic Wang <fwang@igalia.com> > > Separate paint and scroll offsets for RenderLayerBacking::m_scrollingContentsLayer >diff --git a/LayoutTests/http/tests/inspector/dom/cross-domain-inspected-node-access-expected.txt b/LayoutTests/http/tests/inspector/dom/cross-domain-inspected-node-access-expected.txt >index d638f6bd85a72f6abd708d778f09887a1af62410..89c9c538cfc3ef860aacd4072eeec187a9596006 100644 >--- a/LayoutTests/http/tests/inspector/dom/cross-domain-inspected-node-access-expected.txt >+++ b/LayoutTests/http/tests/inspector/dom/cross-domain-inspected-node-access-expected.txt >@@ -1,5 +1,5 @@ >-CONSOLE MESSAGE: line 42: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match. >-CONSOLE MESSAGE: line 42: Blocked a frame with origin "http://localhost:8000" from accessing a frame with origin "http://127.0.0.1:8000". Protocols, domains, and ports must match. >+CONSOLE MESSAGE: line 43: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match. >+CONSOLE MESSAGE: line 43: Blocked a frame with origin "http://localhost:8000" from accessing a frame with origin "http://127.0.0.1:8000". Protocols, domains, and ports must match. > Test that code evaluated in the main frame cannot access $0 that resolves to a node in a frame from a different domain. Bug 105423. > > >diff --git a/LayoutTests/inspector/console/queryObjects-expected.txt b/LayoutTests/inspector/console/queryObjects-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..d30b050af82f1f8226b2330d815acd5dcb9f18e0 >--- /dev/null >+++ b/LayoutTests/inspector/console/queryObjects-expected.txt >@@ -0,0 +1,285 @@ >+Tests for the `queryObjects` function in the Command Line API. >+ >+ >+== Running test suite: CommandLineAPI.queryObjects >+-- Running test case: CommandLineAPI.queryObjects.Instances.ClassA >+PASS: The result should be an object. >+PASS: The result should be an array object. >+PASS: The result should have 0 items. >+ >+-- Running test case: CommandLineAPI.queryObjects.ClassA >+PASS: The result should be an object. >+PASS: The result should be an array object. >+PASS: The result should have 5 items. >+[ClassA, ClassB, ClassB, ClassC, ClassC] >+ >+-- Running test case: CommandLineAPI.queryObjects.ClassA.prototype >+PASS: The result should be an object. >+PASS: The result should be an array object. >+PASS: The result should have 5 items. >+[ClassA, ClassB, ClassB, ClassC, ClassC] >+ >+-- Running test case: CommandLineAPI.queryObjects.Instances.ClassB >+PASS: The result should be an object. >+PASS: The result should be an array object. >+PASS: The result should have 0 items. >+ >+-- Running test case: CommandLineAPI.queryObjects.ClassB >+PASS: The result should be an object. >+PASS: The result should be an array object. >+PASS: The result should have 3 items. >+[ClassB, ClassC, ClassC] >+ >+-- Running test case: CommandLineAPI.queryObjects.ClassB.prototype >+PASS: The result should be an object. >+PASS: The result should be an array object. >+PASS: The result should have 3 items. >+[ClassB, ClassC, ClassC] >+ >+-- Running test case: CommandLineAPI.queryObjects.Instances.ClassC >+PASS: The result should be an object. >+PASS: The result should be an array object. >+PASS: The result should have 0 items. >+ >+-- Running test case: CommandLineAPI.queryObjects.ClassC >+PASS: The result should be an object. >+PASS: The result should be an array object. >+PASS: The result should have 1 items. >+[ClassC] >+ >+-- Running test case: CommandLineAPI.queryObjects.ClassC.prototype >+PASS: The result should be an object. >+PASS: The result should be an array object. >+PASS: The result should have 1 items. >+[ClassC] >+ >+-- Running test case: CommandLineAPI.queryObjects.HTMLDocument >+PASS: The result should be an object. >+PASS: The result should be an array object. >+PASS: The result should have 1 items. >+[#document] >+ >+-- Running test case: CommandLineAPI.queryObjects.HTMLBodyElement >+PASS: The result should be an object. >+PASS: The result should be an array object. >+PASS: The result should have 1 items. >+[<body>] >+ >+-- Running test case: CommandLineAPI.queryObjects.HTMLImageElement >+PASS: The result should be an object. >+PASS: The result should be an array object. >+PASS: The result should have 0 items. >+ >+-- Running test case: CommandLineAPI.queryObjects.objectWithErrorPrototype >+PASS: Calling "queryObjects" with "objectWithErrorPrototype" should throw an exception. >+ >+-- Running test case: CommandLineAPI.queryObjects.undefined >+PASS: Calling "queryObjects" with "undefined" should throw an exception. >+ >+-- Running test case: CommandLineAPI.queryObjects.null >+PASS: Calling "queryObjects" with "null" should throw an exception. >+ >+-- Running test case: CommandLineAPI.queryObjects.Infinity >+PASS: Calling "queryObjects" with "Infinity" should throw an exception. >+ >+-- Running test case: CommandLineAPI.queryObjects.NaN >+PASS: Calling "queryObjects" with "NaN" should throw an exception. >+ >+-- Running test case: CommandLineAPI.queryObjects.1 >+PASS: Calling "queryObjects" with "1" should throw an exception. >+ >+-- Running test case: CommandLineAPI.queryObjects.true >+PASS: Calling "queryObjects" with "true" should throw an exception. >+ >+-- Running test case: CommandLineAPI.queryObjects."test" >+PASS: Calling "queryObjects" with ""test"" should throw an exception. >+ >+-- Running test case: CommandLineAPI.queryObjects.Instances.Symbol >+PASS: Calling "queryObjects" with "Instances.Symbol" should throw an exception. >+ >+-- Running test case: CommandLineAPI.queryObjects.Symbol >+PASS: The result should be an object. >+PASS: The result should be an array object. >+PASS: The result should have 0 items. >+ >+-- Running test case: CommandLineAPI.queryObjects.Symbol.prototype >+PASS: The result should be an object. >+PASS: The result should be an array object. >+PASS: The result should have 0 items. >+ >+-- Running test case: CommandLineAPI.queryObjects.Instances.Object >+PASS: The result should be an object. >+PASS: The result should be an array object. >+PASS: The result should have 0 items. >+ >+-- Running test case: CommandLineAPI.queryObjects.Object >+PASS: Calling "queryObjects" with "Object" should throw an exception. >+ >+-- Running test case: CommandLineAPI.queryObjects.Object.prototype >+PASS: Calling "queryObjects" with "Object.prototype" should throw an exception. >+ >+-- Running test case: CommandLineAPI.queryObjects.Instances.Function >+PASS: The result should be an object. >+PASS: The result should be an array object. >+PASS: The result should have 0 items. >+ >+-- Running test case: CommandLineAPI.queryObjects.Function >+PASS: Calling "queryObjects" with "Function" should throw an exception. >+ >+-- Running test case: CommandLineAPI.queryObjects.Function.prototype >+PASS: Calling "queryObjects" with "Function.prototype" should throw an exception. >+ >+-- Running test case: CommandLineAPI.queryObjects.Instances.Array >+PASS: The result should be an object. >+PASS: The result should be an array object. >+PASS: The result should have 0 items. >+ >+-- Running test case: CommandLineAPI.queryObjects.Array >+PASS: Calling "queryObjects" with "Array" should throw an exception. >+ >+-- Running test case: CommandLineAPI.queryObjects.Array.prototype >+PASS: Calling "queryObjects" with "Array.prototype" should throw an exception. >+ >+-- Running test case: CommandLineAPI.queryObjects.Instances.Map >+PASS: The result should be an object. >+PASS: The result should be an array object. >+PASS: The result should have 0 items. >+ >+-- Running test case: CommandLineAPI.queryObjects.Map >+PASS: Calling "queryObjects" with "Map" should throw an exception. >+ >+-- Running test case: CommandLineAPI.queryObjects.Map.prototype >+PASS: Calling "queryObjects" with "Map.prototype" should throw an exception. >+ >+-- Running test case: CommandLineAPI.queryObjects.Instances.Set >+PASS: The result should be an object. >+PASS: The result should be an array object. >+PASS: The result should have 0 items. >+ >+-- Running test case: CommandLineAPI.queryObjects.Set >+PASS: Calling "queryObjects" with "Set" should throw an exception. >+ >+-- Running test case: CommandLineAPI.queryObjects.Set.prototype >+PASS: Calling "queryObjects" with "Set.prototype" should throw an exception. >+ >+-- Running test case: CommandLineAPI.queryObjects.FunctionPrototypeReplacement >+PASS: Calling "queryObjects" with "FunctionPrototypeReplacement" should throw an exception. >+ >+-- Running test case: CommandLineAPI.queryObjects.FunctionPrototypeReplacement.prototype >+PASS: Calling "queryObjects" with "FunctionPrototypeReplacement.prototype" should throw an exception. >+ >+-- Running test case: CommandLineAPI.queryObjects.ArrayPrototypeReplacement >+PASS: Calling "queryObjects" with "ArrayPrototypeReplacement" should throw an exception. >+ >+-- Running test case: CommandLineAPI.queryObjects.ArrayPrototypeReplacement.prototype >+PASS: Calling "queryObjects" with "ArrayPrototypeReplacement.prototype" should throw an exception. >+ >+-- Running test case: CommandLineAPI.queryObjects.MapPrototypeReplacement >+PASS: Calling "queryObjects" with "MapPrototypeReplacement" should throw an exception. >+ >+-- Running test case: CommandLineAPI.queryObjects.MapPrototypeReplacement.prototype >+PASS: Calling "queryObjects" with "MapPrototypeReplacement.prototype" should throw an exception. >+ >+-- Running test case: CommandLineAPI.queryObjects.SetPrototypeReplacement >+PASS: Calling "queryObjects" with "SetPrototypeReplacement" should throw an exception. >+ >+-- Running test case: CommandLineAPI.queryObjects.SetPrototypeReplacement.prototype >+PASS: Calling "queryObjects" with "SetPrototypeReplacement.prototype" should throw an exception. >+ >+-- Running test case: CommandLineAPI.queryObjects.Instances.Boolean >+PASS: The result should be an object. >+PASS: The result should be an array object. >+PASS: The result should have 0 items. >+ >+-- Running test case: CommandLineAPI.queryObjects.Boolean >+PASS: The result should be an object. >+PASS: The result should be an array object. >+PASS: The result should have at least 1 item. >+ >+-- Running test case: CommandLineAPI.queryObjects.Boolean.prototype >+PASS: The result should be an object. >+PASS: The result should be an array object. >+PASS: The result should have at least 1 item. >+ >+-- Running test case: CommandLineAPI.queryObjects.Instances.String >+PASS: The result should be an object. >+PASS: The result should be an array object. >+PASS: The result should have 0 items. >+ >+-- Running test case: CommandLineAPI.queryObjects.String >+PASS: The result should be an object. >+PASS: The result should be an array object. >+PASS: The result should have at least 1 item. >+ >+-- Running test case: CommandLineAPI.queryObjects.String.prototype >+PASS: The result should be an object. >+PASS: The result should be an array object. >+PASS: The result should have at least 1 item. >+ >+-- Running test case: CommandLineAPI.queryObjects.Instances.Number >+PASS: The result should be an object. >+PASS: The result should be an array object. >+PASS: The result should have 0 items. >+ >+-- Running test case: CommandLineAPI.queryObjects.Number >+PASS: The result should be an object. >+PASS: The result should be an array object. >+PASS: The result should have at least 1 item. >+ >+-- Running test case: CommandLineAPI.queryObjects.Number.prototype >+PASS: The result should be an object. >+PASS: The result should be an array object. >+PASS: The result should have at least 1 item. >+ >+-- Running test case: CommandLineAPI.queryObjects.Instances.Date >+PASS: The result should be an object. >+PASS: The result should be an array object. >+PASS: The result should have 0 items. >+ >+-- Running test case: CommandLineAPI.queryObjects.Date >+PASS: The result should be an object. >+PASS: The result should be an array object. >+PASS: The result should have at least 1 item. >+ >+-- Running test case: CommandLineAPI.queryObjects.Date.prototype >+PASS: The result should be an object. >+PASS: The result should be an array object. >+PASS: The result should have at least 1 item. >+ >+-- Running test case: CommandLineAPI.queryObjects.Instances.RegExp >+PASS: The result should be an object. >+PASS: The result should be an array object. >+PASS: The result should have 0 items. >+ >+-- Running test case: CommandLineAPI.queryObjects.RegExp >+PASS: The result should be an object. >+PASS: The result should be an array object. >+PASS: The result should have at least 1 item. >+ >+-- Running test case: CommandLineAPI.queryObjects.RegExp.prototype >+PASS: The result should be an object. >+PASS: The result should be an array object. >+PASS: The result should have at least 1 item. >+ >+-- Running test case: CommandLineAPI.queryObjects.Instances.Promise >+PASS: The result should be an object. >+PASS: The result should be an array object. >+PASS: The result should have 0 items. >+ >+-- Running test case: CommandLineAPI.queryObjects.Promise >+PASS: The result should be an object. >+PASS: The result should be an array object. >+PASS: The result should have at least 1 item. >+ >+-- Running test case: CommandLineAPI.queryObjects.Promise.prototype >+PASS: The result should be an object. >+PASS: The result should be an array object. >+PASS: The result should have at least 1 item. >+ >+-- Running test case: CommandLineAPI.queryObjects.GC >+PASS: Should be 1 ClassC instance. >+Clearing instances... >+PASS: Should now be 0 ClassC instances. >+ >+-- Running test case: CommandLineAPI.queryObjects.NoParameter >+PASS: The result should be undefined. >diff --git a/LayoutTests/inspector/console/queryObjects.html b/LayoutTests/inspector/console/queryObjects.html >new file mode 100644 >index 0000000000000000000000000000000000000000..e6e6ed7ce045a1ea60b0f6b9c3fb84004ba4b6f0 >--- /dev/null >+++ b/LayoutTests/inspector/console/queryObjects.html >@@ -0,0 +1,184 @@ >+<!doctype html> >+<html> >+<head> >+<script src="../../http/tests/inspector/resources/inspector-test.js"></script> >+<script> >+class ClassA { } >+class ClassB extends ClassA { } >+class ClassC extends ClassB { } >+ >+var Instances = { >+ ClassA: new ClassA, >+ ClassB: new ClassB, >+ ClassC: new ClassC, >+ Object: new Object, >+ Function: new Function, >+ Array: new Array, >+ Boolean: new Boolean, >+ String: new String, >+ Symbol: Symbol(), >+ Number: new Number, >+ Date: new Date, >+ RegExp: new RegExp, >+ Map: new Map, >+ Set: new Set, >+ Promise: new Promise(function() {}), >+}; >+ >+var objectWithErrorPrototype = { >+ get prototype() { throw 42; }, >+}; >+ >+class FunctionPrototypeReplacement { }; >+Function.prototype.__proto__ = FunctionPrototypeReplacement.prototype; >+ >+class ArrayPrototypeReplacement { }; >+Array.prototype.__proto__ = ArrayPrototypeReplacement.prototype; >+ >+class MapPrototypeReplacement { }; >+Map.prototype.__proto__ = MapPrototypeReplacement.prototype; >+ >+class SetPrototypeReplacement { }; >+Set.prototype.__proto__ = SetPrototypeReplacement.prototype; >+ >+function clearInstances() { >+ Instances = {}; >+} >+ >+function test() { >+ function queryObjects(prototypeOrConstructor, callback) { >+ WI.runtimeManager.evaluateInInspectedWindow(`queryObjects(${prototypeOrConstructor})`, {objectGroup: "test", includeCommandLineAPI: true, generatePreview: true}, callback); >+ } >+ >+ let suite = InspectorTest.createAsyncSuite("CommandLineAPI.queryObjects"); >+ >+ let cases = [ >+ {prototypeOrConstructor: `Instances.ClassA`, resultCount: 0}, >+ {prototypeOrConstructor: `ClassA`, resultCount: 5}, >+ {prototypeOrConstructor: `ClassA.prototype`, resultCount: 5}, >+ >+ {prototypeOrConstructor: `Instances.ClassB`, resultCount: 0}, >+ {prototypeOrConstructor: `ClassB`, resultCount: 3}, >+ {prototypeOrConstructor: `ClassB.prototype`, resultCount: 3}, >+ >+ {prototypeOrConstructor: `Instances.ClassC`, resultCount: 0}, >+ {prototypeOrConstructor: `ClassC`, resultCount: 1}, >+ {prototypeOrConstructor: `ClassC.prototype`, resultCount: 1}, >+ >+ {prototypeOrConstructor: `HTMLDocument`, resultCount: 1}, >+ {prototypeOrConstructor: `HTMLBodyElement`, resultCount: 1}, >+ {prototypeOrConstructor: `HTMLImageElement`, resultCount: 0}, >+ >+ {prototypeOrConstructor: `objectWithErrorPrototype`, shouldThrow: true}, >+ >+ {prototypeOrConstructor: `undefined`, shouldThrow: true}, >+ {prototypeOrConstructor: `null`, shouldThrow: true}, >+ {prototypeOrConstructor: `Infinity`, shouldThrow: true}, >+ {prototypeOrConstructor: `NaN`, shouldThrow: true}, >+ {prototypeOrConstructor: `1`, shouldThrow: true}, >+ {prototypeOrConstructor: `true`, shouldThrow: true}, >+ {prototypeOrConstructor: `"test"`, shouldThrow: true}, >+ >+ {prototypeOrConstructor: `Instances.Symbol`, shouldThrow: true}, >+ {prototypeOrConstructor: `Symbol`, resultCount: 0}, >+ {prototypeOrConstructor: `Symbol.prototype`, resultCount: 0}, >+ ]; >+ >+ for (let type of ["Object", "Function", "Array", "Map", "Set"]) { >+ cases.push({prototypeOrConstructor: `Instances.${type}`, resultCount: 0}); >+ cases.push({prototypeOrConstructor: type, shouldThrow: true}); >+ cases.push({prototypeOrConstructor: `${type}.prototype`, shouldThrow: true}); >+ } >+ >+ for (let type of ["FunctionPrototypeReplacement", "ArrayPrototypeReplacement", "MapPrototypeReplacement", "SetPrototypeReplacement"]) { >+ cases.push({prototypeOrConstructor: type, shouldThrow: true}); >+ cases.push({prototypeOrConstructor: `${type}.prototype`, shouldThrow: true}); >+ } >+ >+ for (let type of ["Boolean", "String", "Number", "Date", "RegExp", "Promise"]) { >+ cases.push({prototypeOrConstructor: `Instances.${type}`, resultCount: 0}); >+ cases.push({prototypeOrConstructor: type}); >+ cases.push({prototypeOrConstructor: `${type}.prototype`}); >+ } >+ >+ for (let {prototypeOrConstructor, resultCount, shouldThrow} of cases) { >+ suite.addTestCase({ >+ name: `CommandLineAPI.queryObjects.${prototypeOrConstructor}`, >+ test(resolve, reject) { >+ queryObjects(prototypeOrConstructor, (remoteObject, wasThrown, savedResultIndex) => { >+ if (shouldThrow) { >+ InspectorTest.expectThat(wasThrown, `Calling "queryObjects" with "${prototypeOrConstructor}" should throw an exception.`); >+ if (wasThrown) { >+ resolve(); >+ return; >+ } >+ } else if (wasThrown) { >+ InspectorTest.fail("An exception was thrown."); >+ resolve(); >+ return; >+ } >+ >+ InspectorTest.expectEqual(remoteObject.type, "object", "The result should be an object."); >+ InspectorTest.expectEqual(remoteObject.subtype, "array", "The result should be an array object."); >+ >+ if (resultCount === undefined) >+ InspectorTest.expectGreaterThan(remoteObject.size, 0, `The result should have at least 1 item.`); >+ else { >+ InspectorTest.expectEqual(remoteObject.size, resultCount, `The result should have ${resultCount} items.`); >+ if (remoteObject.size) { >+ let propertyPreviews = remoteObject.preview.propertyPreviews.map((preview) => preview.value); >+ propertyPreviews.sort(); >+ InspectorTest.log("[" + propertyPreviews.join(", ") + "]"); >+ } >+ } >+ >+ resolve(); >+ }); >+ } >+ }); >+ } >+ >+ suite.addTestCase({ >+ name: "CommandLineAPI.queryObjects.GC", >+ test(resolve, reject) { >+ queryObjects(`ClassC`, (remoteObject, wasThrown, savedResultIndex) => { >+ InspectorTest.expectEqual(remoteObject.size, 1, `Should be 1 ClassC instance.`); >+ >+ InspectorTest.log("Clearing instances..."); >+ >+ RuntimeAgent.releaseObjectGroup("test"); >+ InspectorTest.evaluateInPage(`clearInstances()`); >+ >+ queryObjects(`ClassC`, (remoteObject, wasThrown, savedResultIndex) => { >+ InspectorTest.expectEqual(remoteObject.size, 0, `Should now be 0 ClassC instances.`); >+ resolve(); >+ }); >+ }); >+ } >+ }); >+ >+ suite.addTestCase({ >+ name: "CommandLineAPI.queryObjects.NoParameter", >+ test(resolve, reject) { >+ const prototypeOrConstructor = ""; >+ queryObjects(prototypeOrConstructor, (remoteObject, wasThrown, savedResultIndex) => { >+ if (wasThrown) { >+ InspectorTest.fail("An exception was thrown."); >+ reject(); >+ return; >+ } >+ >+ InspectorTest.expectEqual(remoteObject.type, "undefined", "The result should be undefined."); >+ resolve(); >+ }); >+ } >+ }); >+ >+ suite.runTestCasesAndFinish(); >+} >+</script> >+</head> >+<body onload="runTest()"> >+ <p>Tests for the `queryObjects` function in the Command Line API.</p> >+</body> >+</html>
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 176766
:
321026
|
321032
|
321034
|
321037
|
321185
|
321187
|
321223
|
321372
|
321519
|
321618
|
321621
|
321623
|
322029
|
356241
|
356288
|
356290
|
356295
|
356300
|
358232