WebKit Bugzilla
Attachment 358232 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-20190102185533.patch (text/plain), 44.04 KB, created by
Devin Rousso
on 2019-01-02 17:55:34 PST
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Devin Rousso
Created:
2019-01-02 17:55:34 PST
Size:
44.04 KB
patch
obsolete
>diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog >index 7ec6d60e0a9949835e4c55cf51e89377970469cf..7cad47879af2a3c79e03686ba1fa1a5f7fb90058 100644 >--- a/Source/JavaScriptCore/ChangeLog >+++ b/Source/JavaScriptCore/ChangeLog >@@ -1,3 +1,48 @@ >+2019-01-02 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 Joseph Pecoraro. >+ >+ 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): Added. >+ (Inspector::JSInjectedScriptHost::queryObjects): Added. >+ 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): Added. >+ >+ * inspector/InjectedScriptSource.js: >+ (queryObjects): Added. >+ >+ * runtime/JSGlobalObject.h: >+ (JSC::JSGlobalObject::promisePrototype): Added. >+ > 2018-12-30 Ross Kirsling <ross.kirsling@sony.com> > > [JSC] Identifier validity should be based on ID_Start / ID_Continue properties >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index a4196c06d8b677975364d3509669eb26f151a7f6..06286f5b49096f442a519970e7271d04c20cbe63 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,17 @@ >+2019-01-02 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 Joseph Pecoraro. >+ >+ Test: inspector/console/queryObjects.html >+ >+ * inspector/CommandLineAPIModuleSource.js: >+ (CommandLineAPI): >+ (CommandLineAPIImpl.prototype.queryObjects): Added. >+ > 2018-12-30 David Kilzer <ddkilzer@apple.com> > > clang-tidy: Save 8 padding bytes on WebCore::BorderEdge >diff --git a/Source/WebInspectorUI/ChangeLog b/Source/WebInspectorUI/ChangeLog >index d0d8c6c2cb99a6a96941aac00f7af2287933ae7c..044b0d5f17a08400aa5bb48fe6a5760d789fe17e 100644 >--- a/Source/WebInspectorUI/ChangeLog >+++ b/Source/WebInspectorUI/ChangeLog >@@ -1,3 +1,15 @@ >+2019-01-02 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 Joseph Pecoraro. >+ >+ * UserInterface/Controllers/JavaScriptRuntimeCompletionProvider.js: >+ (WI.JavaScriptRuntimeCompletionProvider.completionControllerCompletionsNeeded.receivedPropertyNames): >+ Add `queryObjects` to the list of command line functions. >+ > 2018-12-21 Devin Rousso <drousso@apple.com> > > Web Inspector: Styles Redesign: remove unused CSS style icons >diff --git a/Source/JavaScriptCore/inspector/InjectedScriptSource.js b/Source/JavaScriptCore/inspector/InjectedScriptSource.js >index b5adc6f99b3f2d887b735ebd8ee45e111e3bf6c0..01c1abeb3e540b91af5e3b3ddbf19b3d8e5acd9a 100644 >--- a/Source/JavaScriptCore/inspector/InjectedScriptSource.js >+++ b/Source/JavaScriptCore/inspector/InjectedScriptSource.js >@@ -1447,6 +1447,10 @@ BasicCommandLineAPI.methods = [ > result.push(object[key]); > return result; > }, >+ >+ function queryObjects() { >+ return InjectedScriptHost.queryObjects(...arguments); >+ }, > ]; > > 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..241f5db37d41440065b532c8bbd3b1362721a6e3 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" >@@ -44,6 +47,7 @@ > #include "JSInjectedScriptHostPrototype.h" > #include "JSMap.h" > #include "JSPromise.h" >+#include "JSPromisePrototype.h" > #include "JSSet.h" > #include "JSStringIterator.h" > #include "JSTypedArrays.h" >@@ -51,11 +55,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 +629,87 @@ 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; >+ >+ PropertySlot prototypeSlot(object, PropertySlot::InternalMethodType::VMInquiry); >+ if (object->getPropertySlot(exec, vm.propertyNames->prototype, prototypeSlot)) { >+ RETURN_IF_EXCEPTION(scope, { }); >+ if (prototypeSlot.isValue()) { >+ JSValue prototypeValue = prototypeSlot.getValue(exec, vm.propertyNames->prototype); >+ if (prototypeValue.isObject()) { >+ prototype = prototypeValue; >+ 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); >+ if (checkForbiddenPrototype(exec, object, lexicalGlobalObject->promisePrototype())) >+ return throwTypeError(exec, scope, "queryObjects cannot be called with Promise."_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 (!isJSCellKind(kind)) >+ return IterationStatus::Continue; >+ >+ JSValue value(static_cast<JSCell*>(cell)); >+ if (value.inherits<ProxyObject>(vm)) >+ return IterationStatus::Continue; >+ >+ 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/JavaScriptCore/runtime/JSGlobalObject.h b/Source/JavaScriptCore/runtime/JSGlobalObject.h >index 2cf557d89be5c840cc908280627c0595eaf5affc..357ca8bf62ff7c8f5fbb0374816b44027f653251 100644 >--- a/Source/JavaScriptCore/runtime/JSGlobalObject.h >+++ b/Source/JavaScriptCore/runtime/JSGlobalObject.h >@@ -616,6 +616,7 @@ public: > MapPrototype* mapPrototype() const { return m_mapPrototype.get(); } > // Workaround for the name conflict between JSCell::setPrototype. > SetPrototype* jsSetPrototype() const { return m_setPrototype.get(); } >+ JSPromisePrototype* promisePrototype() const { return m_promisePrototype.get(); } > AsyncGeneratorPrototype* asyncGeneratorPrototype() const { return m_asyncGeneratorPrototype.get(); } > AsyncGeneratorFunctionPrototype* asyncGeneratorFunctionPrototype() const { return m_asyncGeneratorFunctionPrototype.get(); } > >diff --git a/Source/WebCore/inspector/CommandLineAPIModuleSource.js b/Source/WebCore/inspector/CommandLineAPIModuleSource.js >index 7cf4fcdaaaa2ef4d964d9f7ee6b9423a64706d0b..92254f588a0b33b58a3ed7244226b0a30d473976 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() >+ { >+ return InjectedScriptHost.queryObjects(...arguments); >+ }, >+ > 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 4a85e5fbb6bcc0a74bb554f3d975fd9fe6ea9fc8..f1aad78540d35384cbbccea18ba85934ff3c717f 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,16 @@ >+2019-01-02 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 Joseph Pecoraro. >+ >+ * inspector/console/queryObjects-expected.html: Added. >+ * inspector/console/queryObjects.html: Added. >+ >+ * http/tests/inspector/console/cross-domain-inspected-node-access-expected.txt: >+ > 2018-12-31 Carlos Garcia Campos <cgarcia@igalia.com> > > Unreviewed. Support PHP 7.3 in Debian. >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..c093f186865559d72073362f0d646e06e567adb9 >--- /dev/null >+++ b/LayoutTests/inspector/console/queryObjects-expected.txt >@@ -0,0 +1,342 @@ >+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.objectWithDisallowedPrototypeGetter >+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.objectWithErrorPrototypeGetter >+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.undefined >+PASS: Calling "queryObjects" with "undefined" should throw an exception. >+TypeError: queryObjects first argument must be an object. >+ >+-- Running test case: CommandLineAPI.queryObjects.null >+PASS: Calling "queryObjects" with "null" should throw an exception. >+TypeError: queryObjects first argument must be an object. >+ >+-- Running test case: CommandLineAPI.queryObjects.Infinity >+PASS: Calling "queryObjects" with "Infinity" should throw an exception. >+TypeError: queryObjects first argument must be an object. >+ >+-- Running test case: CommandLineAPI.queryObjects.NaN >+PASS: Calling "queryObjects" with "NaN" should throw an exception. >+TypeError: queryObjects first argument must be an object. >+ >+-- Running test case: CommandLineAPI.queryObjects.1 >+PASS: Calling "queryObjects" with "1" should throw an exception. >+TypeError: queryObjects first argument must be an object. >+ >+-- Running test case: CommandLineAPI.queryObjects.true >+PASS: Calling "queryObjects" with "true" should throw an exception. >+TypeError: queryObjects first argument must be an object. >+ >+-- Running test case: CommandLineAPI.queryObjects."test" >+PASS: Calling "queryObjects" with ""test"" should throw an exception. >+TypeError: queryObjects first argument must be an object. >+ >+-- Running test case: CommandLineAPI.queryObjects.Instances.Symbol >+PASS: Calling "queryObjects" with "Instances.Symbol" should throw an exception. >+TypeError: queryObjects first argument must be an object. >+ >+-- 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.Proxies.constructor >+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.Proxies.basic >+PASS: Calling "queryObjects" with "Proxies.basic" should throw an exception. >+TypeError: queryObjects cannot be called with a Proxy. >+ >+-- Running test case: CommandLineAPI.queryObjects.Proxies.object >+PASS: Calling "queryObjects" with "Proxies.object" should throw an exception. >+TypeError: queryObjects cannot be called with a Proxy. >+ >+-- Running test case: CommandLineAPI.queryObjects.Proxies.tricky >+PASS: Calling "queryObjects" with "Proxies.tricky" should throw an exception. >+TypeError: queryObjects cannot be called with a Proxy. >+ >+-- 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. >+TypeError: queryObjects cannot be called with Object. >+ >+-- Running test case: CommandLineAPI.queryObjects.Object.prototype >+PASS: Calling "queryObjects" with "Object.prototype" should throw an exception. >+TypeError: queryObjects cannot be called with Object. >+ >+-- 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. >+TypeError: queryObjects cannot be called with Function. >+ >+-- Running test case: CommandLineAPI.queryObjects.Function.prototype >+PASS: Calling "queryObjects" with "Function.prototype" should throw an exception. >+TypeError: queryObjects cannot be called with Function. >+ >+-- 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. >+TypeError: queryObjects cannot be called with Array. >+ >+-- Running test case: CommandLineAPI.queryObjects.Array.prototype >+PASS: Calling "queryObjects" with "Array.prototype" should throw an exception. >+TypeError: queryObjects cannot be called with Array. >+ >+-- 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. >+TypeError: queryObjects cannot be called with Map. >+ >+-- Running test case: CommandLineAPI.queryObjects.Map.prototype >+PASS: Calling "queryObjects" with "Map.prototype" should throw an exception. >+TypeError: queryObjects cannot be called with Map. >+ >+-- 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. >+TypeError: queryObjects cannot be called with Set. >+ >+-- Running test case: CommandLineAPI.queryObjects.Set.prototype >+PASS: Calling "queryObjects" with "Set.prototype" should throw an exception. >+TypeError: queryObjects cannot be called with Set. >+ >+-- 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: Calling "queryObjects" with "Promise" should throw an exception. >+TypeError: queryObjects cannot be called with Promise. >+ >+-- Running test case: CommandLineAPI.queryObjects.Promise.prototype >+PASS: Calling "queryObjects" with "Promise.prototype" should throw an exception. >+TypeError: queryObjects cannot be called with Promise. >+ >+-- Running test case: CommandLineAPI.queryObjects.FunctionPrototypeReplacement >+PASS: Calling "queryObjects" with "FunctionPrototypeReplacement" should throw an exception. >+TypeError: queryObjects cannot be called with Function. >+ >+-- Running test case: CommandLineAPI.queryObjects.FunctionPrototypeReplacement.prototype >+PASS: Calling "queryObjects" with "FunctionPrototypeReplacement.prototype" should throw an exception. >+TypeError: queryObjects cannot be called with Function. >+ >+-- Running test case: CommandLineAPI.queryObjects.ArrayPrototypeReplacement >+PASS: Calling "queryObjects" with "ArrayPrototypeReplacement" should throw an exception. >+TypeError: queryObjects cannot be called with Array. >+ >+-- Running test case: CommandLineAPI.queryObjects.ArrayPrototypeReplacement.prototype >+PASS: Calling "queryObjects" with "ArrayPrototypeReplacement.prototype" should throw an exception. >+TypeError: queryObjects cannot be called with Array. >+ >+-- Running test case: CommandLineAPI.queryObjects.MapPrototypeReplacement >+PASS: Calling "queryObjects" with "MapPrototypeReplacement" should throw an exception. >+TypeError: queryObjects cannot be called with Map. >+ >+-- Running test case: CommandLineAPI.queryObjects.MapPrototypeReplacement.prototype >+PASS: Calling "queryObjects" with "MapPrototypeReplacement.prototype" should throw an exception. >+TypeError: queryObjects cannot be called with Map. >+ >+-- Running test case: CommandLineAPI.queryObjects.SetPrototypeReplacement >+PASS: Calling "queryObjects" with "SetPrototypeReplacement" should throw an exception. >+TypeError: queryObjects cannot be called with Set. >+ >+-- Running test case: CommandLineAPI.queryObjects.SetPrototypeReplacement.prototype >+PASS: Calling "queryObjects" with "SetPrototypeReplacement.prototype" should throw an exception. >+TypeError: queryObjects cannot be called with Set. >+ >+-- Running test case: CommandLineAPI.queryObjects.PromisePrototypeReplacement >+PASS: Calling "queryObjects" with "PromisePrototypeReplacement" should throw an exception. >+TypeError: queryObjects cannot be called with Promise. >+ >+-- Running test case: CommandLineAPI.queryObjects.PromisePrototypeReplacement.prototype >+PASS: Calling "queryObjects" with "PromisePrototypeReplacement.prototype" should throw an exception. >+TypeError: queryObjects cannot be called with Promise. >+ >+-- 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.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..03ba6c23b25260888e7dac74423b785331903bb4 >--- /dev/null >+++ b/LayoutTests/inspector/console/queryObjects.html >@@ -0,0 +1,215 @@ >+<!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 Proxies = { >+ constructor: Proxy, >+ basic: new Proxy({}, {}), >+ object: new Proxy({}, { get() { return Object.prototype; } }), >+ tricky: new Proxy({}, { get() { return this.count++ === 0 ? ClassA : Object.prototype; } }), >+}; >+ >+var objectWithDisallowedPrototypeGetter = { >+ get prototype() { return Object.prototype; }, >+}; >+ >+var objectWithErrorPrototypeGetter = { >+ 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; >+ >+class PromisePrototypeReplacement { }; >+Promise.prototype.__proto__ = PromisePrototypeReplacement.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: `objectWithDisallowedPrototypeGetter`, resultCount: 0}, >+ {prototypeOrConstructor: `objectWithErrorPrototypeGetter`, resultCount: 0}, >+ >+ {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}, >+ >+ {prototypeOrConstructor: `Proxies.constructor`, resultCount: 0}, >+ {prototypeOrConstructor: `Proxies.basic`, shouldThrow: true}, >+ {prototypeOrConstructor: `Proxies.object`, shouldThrow: true}, >+ {prototypeOrConstructor: `Proxies.tricky`, shouldThrow: true}, >+ ]; >+ >+ for (let type of ["Object", "Function", "Array", "Map", "Set", "Promise"]) { >+ 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", "PromisePrototypeReplacement"]) { >+ cases.push({prototypeOrConstructor: type, shouldThrow: true}); >+ cases.push({prototypeOrConstructor: `${type}.prototype`, shouldThrow: true}); >+ } >+ >+ for (let type of ["Boolean", "String", "Number", "Date", "RegExp"]) { >+ 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.`); >+ InspectorTest.log(remoteObject.description); >+ if (wasThrown) { >+ resolve(); >+ return; >+ } >+ } else if (wasThrown) { >+ InspectorTest.fail("An exception was thrown."); >+ InspectorTest.log(remoteObject.description); >+ 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.assert(!wasThrown); >+ if (wasThrown) >+ InspectorTest.log(remoteObject.description); >+ >+ 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.assert(!wasThrown); >+ if (wasThrown) >+ InspectorTest.log(remoteObject.description); >+ >+ 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."); >+ InspectorTest.log(remoteObject.description); >+ 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