WebKit Bugzilla
New
Browse
Search+
Log In
×
Sign in with GitHub
or
Remember my login
Create Account
·
Forgot Password
Forgotten password account recovery
[patch]
Patch
bug-192171-20181130123201.patch (text/plain), 52.09 KB, created by
Devin Rousso
on 2018-11-30 12:32:02 PST
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
Devin Rousso
Created:
2018-11-30 12:32:02 PST
Size:
52.09 KB
patch
obsolete
>diff --git a/Source/JavaScriptCore/ChangeLog b/Source/JavaScriptCore/ChangeLog >index 676d21b7016b1699ab8d3f187cef6c068160a2e0..59e610d4d5f5a26e77c49d174e98ac96088b17d2 100644 >--- a/Source/JavaScriptCore/ChangeLog >+++ b/Source/JavaScriptCore/ChangeLog >@@ -1,3 +1,42 @@ >+2018-11-30 Devin Rousso <drousso@apple.com> >+ >+ Web Inspector: Audit: tests should support async operations >+ https://bugs.webkit.org/show_bug.cgi?id=192171 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Add `awaitPromise` command for executing a callback when a Promise gets settled. >+ >+ Drive-by: allow `wasThrown` to be optional, instead of expecting it to always have a value. >+ >+ * inspector/protocol/Runtime.json: >+ >+ * inspector/InjectedScriptSource.js: >+ (InjectedScript.prototype.awaitPromise): Added. >+ >+ * inspector/InjectedScript.h: >+ * inspector/InjectedScript.cpp: >+ (Inspector::InjectedScript::evaluate): >+ (Inspector::InjectedScript::awaitPromise): Added. >+ (Inspector::InjectedScript::callFunctionOn): >+ (Inspector::InjectedScript::evaluateOnCallFrame): >+ >+ * inspector/InjectedScriptBase.h: >+ * inspector/InjectedScriptBase.cpp: >+ (Inspector::InjectedScriptBase::makeEvalCall): >+ (Inspector::InjectedScriptBase::makeAsyncCall): Added. >+ (Inspector::InjcetedScriptBase::checkCallResult): Added. >+ (Inspector::InjcetedScriptBase::checkAsyncCallResult): Added. >+ >+ * inspector/agents/InspectorRuntimeAgent.h: >+ * inspector/agents/InspectorRuntimeAgent.cpp: >+ (Inspector::InspectorRuntimeAgent::evaluate): >+ (Inspector::InspectorRuntimeAgent::awaitPromise): >+ (Inspector::InspectorRuntimeAgent::callFunctionOn): >+ >+ * inspector/agents/InspectorDebuggerAgent.cpp: >+ (Inspector::InspectorDebuggerAgent::evaluateOnCallFrame): >+ > 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/WebInspectorUI/ChangeLog b/Source/WebInspectorUI/ChangeLog >index a8e1de9a0cfd0c5e34ea4a1df1dcb17fe8067135..a3913906414796b947e8694048f4b4c8f86da035 100644 >--- a/Source/WebInspectorUI/ChangeLog >+++ b/Source/WebInspectorUI/ChangeLog >@@ -1,3 +1,26 @@ >+2018-11-30 Devin Rousso <drousso@apple.com> >+ >+ Web Inspector: Audit: tests should support async operations >+ https://bugs.webkit.org/show_bug.cgi?id=192171 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * UserInterface/Controllers/RuntimeManager.js: >+ (WI.RuntimeManager.supportsAwaitPromise): Added. >+ >+ * UserInterface/Models/AuditTestCase.js: >+ (WI.AuditTestCase.prototype.async run.async parseResponse.checkResultProperty.addErrorForValueType): Deleted. >+ (WI.AuditTestCase.prototype.async run.async parseResponse.checkResultProperty): Deleted. >+ (WI.AuditTestCase.prototype.async run.async parseResponse.async resultArrayForEach): Deleted. >+ (WI.AuditTestCase.prototype.async run.async parseResponse): Added. >+ (WI.AuditTestCase.prototype.async run): >+ (WI.AuditTestCase.prototype.async run.checkResultProperty.addErrorForValueType): Deleted. >+ (WI.AuditTestCase.prototype.async run.checkResultProperty): Deleted. >+ (WI.AuditTestCase.prototype.async run.async resultArrayForEach): Deleted. >+ >+ * UserInterface/Views/AuditTestCaseContentView.js: >+ (WI.AuditTestCaseContentView.prototype.layout): >+ > 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/InjectedScript.cpp b/Source/JavaScriptCore/inspector/InjectedScript.cpp >index 2c9a4b2f4c31f8d2ca82eda8a6588fc63e619016..c03ffeb2e4484f75d9b8fc4cc33a6a00865a2b0e 100644 >--- a/Source/JavaScriptCore/inspector/InjectedScript.cpp >+++ b/Source/JavaScriptCore/inspector/InjectedScript.cpp >@@ -54,7 +54,7 @@ InjectedScript::~InjectedScript() > { > } > >-void InjectedScript::evaluate(ErrorString& errorString, const String& expression, const String& objectGroup, bool includeCommandLineAPI, bool returnByValue, bool generatePreview, bool saveResult, RefPtr<Protocol::Runtime::RemoteObject>& result, bool& wasThrown, std::optional<int>& savedResultIndex) >+void InjectedScript::evaluate(ErrorString& errorString, const String& expression, const String& objectGroup, bool includeCommandLineAPI, bool returnByValue, bool generatePreview, bool saveResult, RefPtr<Protocol::Runtime::RemoteObject>& result, std::optional<bool>& wasThrown, std::optional<int>& savedResultIndex) > { > Deprecated::ScriptFunctionCall function(injectedScriptObject(), "evaluate"_s, inspectorEnvironment()->functionCallHandler()); > function.appendArgument(expression); >@@ -66,7 +66,17 @@ void InjectedScript::evaluate(ErrorString& errorString, const String& expression > makeEvalCall(errorString, function, result, wasThrown, savedResultIndex); > } > >-void InjectedScript::callFunctionOn(ErrorString& errorString, const String& objectId, const String& expression, const String& arguments, bool returnByValue, bool generatePreview, RefPtr<Protocol::Runtime::RemoteObject>& result, bool& wasThrown) >+void InjectedScript::awaitPromise(const String& promiseObjectId, bool returnByValue, bool generatePreview, bool saveResult, AsyncCallCallback&& callback) >+{ >+ Deprecated::ScriptFunctionCall function(injectedScriptObject(), "awaitPromise"_s, inspectorEnvironment()->functionCallHandler()); >+ function.appendArgument(promiseObjectId); >+ function.appendArgument(returnByValue); >+ function.appendArgument(generatePreview); >+ function.appendArgument(saveResult); >+ makeAsyncCall(function, WTFMove(callback)); >+} >+ >+void InjectedScript::callFunctionOn(ErrorString& errorString, const String& objectId, const String& expression, const String& arguments, bool returnByValue, bool generatePreview, RefPtr<Protocol::Runtime::RemoteObject>& result, std::optional<bool>& wasThrown) > { > Deprecated::ScriptFunctionCall function(injectedScriptObject(), "callFunctionOn"_s, inspectorEnvironment()->functionCallHandler()); > function.appendArgument(objectId); >@@ -74,12 +84,13 @@ void InjectedScript::callFunctionOn(ErrorString& errorString, const String& obje > function.appendArgument(arguments); > function.appendArgument(returnByValue); > function.appendArgument(generatePreview); >- >- std::optional<int> unused; >- makeEvalCall(errorString, function, result, wasThrown, unused); >+ >+ std::optional<int> savedResultIndex; >+ makeEvalCall(errorString, function, result, wasThrown, savedResultIndex); >+ ASSERT(!savedResultIndex); > } > >-void InjectedScript::evaluateOnCallFrame(ErrorString& errorString, JSC::JSValue callFrames, const String& callFrameId, const String& expression, const String& objectGroup, bool includeCommandLineAPI, bool returnByValue, bool generatePreview, bool saveResult, RefPtr<Protocol::Runtime::RemoteObject>& result, bool& wasThrown, std::optional<int>& savedResultIndex) >+void InjectedScript::evaluateOnCallFrame(ErrorString& errorString, JSC::JSValue callFrames, const String& callFrameId, const String& expression, const String& objectGroup, bool includeCommandLineAPI, bool returnByValue, bool generatePreview, bool saveResult, RefPtr<Protocol::Runtime::RemoteObject>& result, std::optional<bool>& wasThrown, std::optional<int>& savedResultIndex) > { > Deprecated::ScriptFunctionCall function(injectedScriptObject(), "evaluateOnCallFrame"_s, inspectorEnvironment()->functionCallHandler()); > function.appendArgument(callFrames); >diff --git a/Source/JavaScriptCore/inspector/InjectedScript.h b/Source/JavaScriptCore/inspector/InjectedScript.h >index 6d32b97cbfe1c66875a399a8ea9785bf03cbab95..4de9d745dce5b3dcf59bc1c53aeb6c3f8cc0a34f 100644 >--- a/Source/JavaScriptCore/inspector/InjectedScript.h >+++ b/Source/JavaScriptCore/inspector/InjectedScript.h >@@ -33,6 +33,7 @@ > > #include "InjectedScriptBase.h" > #include <wtf/Forward.h> >+#include <wtf/Function.h> > #include <wtf/RefPtr.h> > > namespace Deprecated { >@@ -50,9 +51,10 @@ public: > InjectedScript(Deprecated::ScriptObject, InspectorEnvironment*); > virtual ~InjectedScript(); > >- void evaluate(ErrorString&, const String& expression, const String& objectGroup, bool includeCommandLineAPI, bool returnByValue, bool generatePreview, bool saveResult, RefPtr<Protocol::Runtime::RemoteObject>& result, bool& wasThrown, std::optional<int>& savedResultIndex); >- void evaluateOnCallFrame(ErrorString&, JSC::JSValue callFrames, const String& callFrameId, const String& expression, const String& objectGroup, bool includeCommandLineAPI, bool returnByValue, bool generatePreview, bool saveResult, RefPtr<Protocol::Runtime::RemoteObject>& result, bool& wasThrown, std::optional<int>& savedResultIndex); >- void callFunctionOn(ErrorString&, const String& objectId, const String& expression, const String& arguments, bool returnByValue, bool generatePreview, RefPtr<Protocol::Runtime::RemoteObject>& result, bool& wasThrown); >+ void evaluate(ErrorString&, const String& expression, const String& objectGroup, bool includeCommandLineAPI, bool returnByValue, bool generatePreview, bool saveResult, RefPtr<Protocol::Runtime::RemoteObject>& result, std::optional<bool>& wasThrown, std::optional<int>& savedResultIndex); >+ void awaitPromise(const String& promiseObjectId, bool returnByValue, bool generatePreview, bool saveResult, AsyncCallCallback&&); >+ void evaluateOnCallFrame(ErrorString&, JSC::JSValue callFrames, const String& callFrameId, const String& expression, const String& objectGroup, bool includeCommandLineAPI, bool returnByValue, bool generatePreview, bool saveResult, RefPtr<Protocol::Runtime::RemoteObject>& result, std::optional<bool>& wasThrown, std::optional<int>& savedResultIndex); >+ void callFunctionOn(ErrorString&, const String& objectId, const String& expression, const String& arguments, bool returnByValue, bool generatePreview, RefPtr<Protocol::Runtime::RemoteObject>& result, std::optional<bool>& wasThrown); > void getFunctionDetails(ErrorString&, const String& functionId, RefPtr<Protocol::Debugger::FunctionDetails>& result); > void functionDetails(ErrorString&, JSC::JSValue, RefPtr<Protocol::Debugger::FunctionDetails>& result); > void getPreview(ErrorString&, const String& objectId, RefPtr<Protocol::Runtime::ObjectPreview>& result); >diff --git a/Source/JavaScriptCore/inspector/InjectedScriptBase.cpp b/Source/JavaScriptCore/inspector/InjectedScriptBase.cpp >index c5dbc73237891efe9c87351ac7213e96e744889a..02d31f92eb995d6768602c1283f7c78332ee58a5 100644 >--- a/Source/JavaScriptCore/inspector/InjectedScriptBase.cpp >+++ b/Source/JavaScriptCore/inspector/InjectedScriptBase.cpp >@@ -35,6 +35,9 @@ > #include "DebuggerEvalEnabler.h" > #include "JSCInlines.h" > #include "JSGlobalObject.h" >+#include "JSLock.h" >+#include "JSNativeStdFunction.h" >+#include "NativeStdFunctionCell.h" > #include "ScriptFunctionCall.h" > #include <wtf/JSONValues.h> > #include <wtf/text/WTFString.h> >@@ -93,9 +96,53 @@ Ref<JSON::Value> InjectedScriptBase::makeCall(Deprecated::ScriptFunctionCall& fu > return resultJSONValue.releaseNonNull(); > } > >-void InjectedScriptBase::makeEvalCall(ErrorString& errorString, Deprecated::ScriptFunctionCall& function, RefPtr<Protocol::Runtime::RemoteObject>& out_resultObject, bool& out_wasThrown, std::optional<int>& out_savedResultIndex) >+void InjectedScriptBase::makeEvalCall(ErrorString& errorString, Deprecated::ScriptFunctionCall& function, RefPtr<Protocol::Runtime::RemoteObject>& out_resultObject, std::optional<bool>& out_wasThrown, std::optional<int>& out_savedResultIndex) >+{ >+ checkCallResult(errorString, makeCall(function), out_resultObject, out_wasThrown, out_savedResultIndex); >+} >+ >+void InjectedScriptBase::makeAsyncCall(Deprecated::ScriptFunctionCall& function, AsyncCallCallback&& callback) >+{ >+ if (hasNoValue() || !hasAccessToInspectedScriptState()) { >+ checkAsyncCallResult(JSON::Value::null(), callback); >+ return; >+ } >+ >+ auto* scriptState = m_injectedScriptObject.scriptState(); >+ JSC::VM& vm = scriptState->vm(); >+ >+ JSC::JSNativeStdFunction* jsFunction; >+ >+ { >+ JSC::JSLockHolder locker(vm); >+ >+ jsFunction = JSC::JSNativeStdFunction::create(vm, scriptState->lexicalGlobalObject(), 1, String(), [&, callback = WTFMove(callback)] (JSC::ExecState* exec) { >+ if (!exec) >+ checkAsyncCallResult(JSON::Value::create("Exception while making a call."), callback); >+ if (auto resultJSONValue = toInspectorValue(*exec, exec->argument(0))) >+ checkAsyncCallResult(resultJSONValue, callback); >+ else >+ checkAsyncCallResult(JSON::Value::create(String::format("Object has too long reference chain (must not be longer than %d)", JSON::Value::maxDepth)), callback); >+ return JSC::JSValue::encode(JSC::jsUndefined()); >+ }); >+ } >+ >+ function.appendArgument(JSC::JSValue(jsFunction)); >+ >+ bool hadException = false; >+ auto resultJSValue = callFunctionWithEvalEnabled(function, hadException); >+ ASSERT_UNUSED(resultJSValue, resultJSValue.isUndefined()); >+ >+ ASSERT(!hadException); >+ if (hadException) { >+ // Since `callback` is moved above, we can't call it if there's an execption while trying to >+ // execute the `JSNativeStdFunction` inside InjectedScriptSource.js. >+ jsFunction->nativeStdFunctionCell()->function()(nullptr); >+ } >+} >+ >+void InjectedScriptBase::checkCallResult(ErrorString& errorString, RefPtr<JSON::Value> result, RefPtr<Protocol::Runtime::RemoteObject>& out_resultObject, std::optional<bool>& out_wasThrown, std::optional<int>& out_savedResultIndex) > { >- RefPtr<JSON::Value> result = makeCall(function); > if (!result) { > errorString = "Internal error: result value is empty"_s; > return; >@@ -126,12 +173,26 @@ void InjectedScriptBase::makeEvalCall(ErrorString& errorString, Deprecated::Scri > } > > out_resultObject = BindingTraits<Protocol::Runtime::RemoteObject>::runtimeCast(resultObject); >- out_wasThrown = wasThrown; >+ >+ if (wasThrown) >+ out_wasThrown = wasThrown; > > int savedResultIndex; > if (resultTuple->getInteger("savedResultIndex"_s, savedResultIndex)) > out_savedResultIndex = savedResultIndex; > } > >+void InjectedScriptBase::checkAsyncCallResult(RefPtr<JSON::Value> result, const AsyncCallCallback& callback) >+{ >+ ErrorString errorString; >+ RefPtr<Protocol::Runtime::RemoteObject> resultObject; >+ std::optional<bool> wasThrown; >+ std::optional<int> savedResultIndex; >+ >+ checkCallResult(errorString, result, resultObject, wasThrown, savedResultIndex); >+ >+ callback(errorString, WTFMove(resultObject), wasThrown, savedResultIndex); >+} >+ > } // namespace Inspector > >diff --git a/Source/JavaScriptCore/inspector/InjectedScriptBase.h b/Source/JavaScriptCore/inspector/InjectedScriptBase.h >index 3e7e7a3009eba81760e3b16d948150aa9d2fa730..447a4288f9977cf2cb20aefdefe2cb52b02c3a78 100644 >--- a/Source/JavaScriptCore/inspector/InjectedScriptBase.h >+++ b/Source/JavaScriptCore/inspector/InjectedScriptBase.h >@@ -35,6 +35,7 @@ > #include "InspectorProtocolObjects.h" > #include "ScriptObject.h" > #include <wtf/Forward.h> >+#include <wtf/Function.h> > #include <wtf/RefPtr.h> > > namespace Deprecated { >@@ -44,6 +45,7 @@ class ScriptFunctionCall; > namespace Inspector { > > typedef String ErrorString; >+typedef WTF::Function<void(ErrorString&, RefPtr<Protocol::Runtime::RemoteObject>&&, std::optional<bool>&, std::optional<int>&)> AsyncCallCallback; > > class JS_EXPORT_PRIVATE InjectedScriptBase { > public: >@@ -64,9 +66,13 @@ protected: > const Deprecated::ScriptObject& injectedScriptObject() const; > JSC::JSValue callFunctionWithEvalEnabled(Deprecated::ScriptFunctionCall&, bool& hadException) const; > Ref<JSON::Value> makeCall(Deprecated::ScriptFunctionCall&); >- void makeEvalCall(ErrorString&, Deprecated::ScriptFunctionCall&, RefPtr<Protocol::Runtime::RemoteObject>& resultObject, bool& wasThrown, std::optional<int>& savedResultIndex); >+ void makeEvalCall(ErrorString&, Deprecated::ScriptFunctionCall&, RefPtr<Protocol::Runtime::RemoteObject>& resultObject, std::optional<bool>& wasThrown, std::optional<int>& savedResultIndex); >+ void makeAsyncCall(Deprecated::ScriptFunctionCall&, AsyncCallCallback&&); > > private: >+ void checkCallResult(ErrorString&, RefPtr<JSON::Value> result, RefPtr<Protocol::Runtime::RemoteObject>& resultObject, std::optional<bool>& wasThrown, std::optional<int>& savedResultIndex); >+ void checkAsyncCallResult(RefPtr<JSON::Value> result, const AsyncCallCallback&); >+ > String m_name; > Deprecated::ScriptObject m_injectedScriptObject; > InspectorEnvironment* m_environment { nullptr }; >diff --git a/Source/JavaScriptCore/inspector/InjectedScriptSource.js b/Source/JavaScriptCore/inspector/InjectedScriptSource.js >index d6b75f1fecd79af702f9ed58000423238343668a..b5adc6f99b3f2d887b735ebd8ee45e111e3bf6c0 100644 >--- a/Source/JavaScriptCore/inspector/InjectedScriptSource.js >+++ b/Source/JavaScriptCore/inspector/InjectedScriptSource.js >@@ -108,6 +108,43 @@ let InjectedScript = class InjectedScript > return this._evaluateAndWrap(InjectedScriptHost.evaluateWithScopeExtension, InjectedScriptHost, expression, objectGroup, false, injectCommandLineAPI, returnByValue, generatePreview, saveResult); > } > >+ awaitPromise(promiseObjectId, returnByValue, generatePreview, saveResult, callback) >+ { >+ let parsedPromiseObjectId = this._parseObjectId(promiseObjectId); >+ let promiseObject = this._objectForId(parsedPromiseObjectId); >+ let promiseObjectGroupName = this._idToObjectGroupName[parsedPromiseObjectId.id]; >+ >+ if (!isDefined(promiseObject)) { >+ callback("Could not find object with given id"); >+ return; >+ } >+ >+ if (!(promiseObject instanceof Promise)) { >+ callback("Object with given id is not a Promise"); >+ return; >+ } >+ >+ let resolve = (value) => { >+ let returnObject = { >+ wasThrown: false, >+ result: RemoteObject.create(value, promiseObjectGroupName, returnByValue, generatePreview), >+ }; >+ >+ if (saveResult) { >+ this._savedResultIndex = 0; >+ this._saveResult(returnObject.result); >+ if (this._savedResultIndex) >+ returnObject.savedResultIndex = this._savedResultIndex; >+ } >+ >+ callback(returnObject); >+ }; >+ let reject = (reason) => { >+ callback(this._createThrownValue(reason, promiseObjectGroupName)); >+ }; >+ promiseObject.then(resolve, reject); >+ } >+ > evaluateOnCallFrame(topCallFrame, callFrameId, expression, objectGroup, injectCommandLineAPI, returnByValue, generatePreview, saveResult) > { > let callFrame = this._callFrameForId(topCallFrame, callFrameId); >diff --git a/Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.cpp b/Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.cpp >index b487a22010ec51f290501aa9336c9dfc1f315c90..f9910071742281e6b1dfe5df8a7b321996c4467b 100644 >--- a/Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.cpp >+++ b/Source/JavaScriptCore/inspector/agents/InspectorDebuggerAgent.cpp >@@ -827,7 +827,7 @@ void InspectorDebuggerAgent::setPauseOnAssertions(ErrorString&, bool enabled) > m_pauseOnAssertionFailures = enabled; > } > >-void InspectorDebuggerAgent::evaluateOnCallFrame(ErrorString& errorString, const String& callFrameId, const String& expression, const String* objectGroup, const bool* includeCommandLineAPI, const bool* doNotPauseOnExceptionsAndMuteConsole, const bool* returnByValue, const bool* generatePreview, const bool* saveResult, RefPtr<Protocol::Runtime::RemoteObject>& result, std::optional<bool>& outWasThrown, std::optional<int>& savedResultIndex) >+void InspectorDebuggerAgent::evaluateOnCallFrame(ErrorString& errorString, const String& callFrameId, const String& expression, const String* objectGroup, const bool* includeCommandLineAPI, const bool* doNotPauseOnExceptionsAndMuteConsole, const bool* returnByValue, const bool* generatePreview, const bool* saveResult, RefPtr<Protocol::Runtime::RemoteObject>& result, std::optional<bool>& wasThrown, std::optional<int>& savedResultIndex) > { > if (!m_currentCallStack) { > errorString = "Not paused"_s; >@@ -848,11 +848,9 @@ void InspectorDebuggerAgent::evaluateOnCallFrame(ErrorString& errorString, const > muteConsole(); > } > >- bool wasThrown; > injectedScript.evaluateOnCallFrame(errorString, m_currentCallStack.get(), callFrameId, expression, > objectGroup ? *objectGroup : emptyString(), includeCommandLineAPI && *includeCommandLineAPI, returnByValue && *returnByValue, generatePreview && *generatePreview, saveResult && *saveResult, > result, wasThrown, savedResultIndex); >- outWasThrown = wasThrown; > > if (pauseAndMute) { > unmuteConsole(); >diff --git a/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp b/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp >index e869a6172d3677ff2992ef0e478593225c354cb0..627975b71339c559369205ceed8a903320bebe61 100644 >--- a/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp >+++ b/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp >@@ -111,7 +111,7 @@ void InspectorRuntimeAgent::parse(ErrorString&, const String& expression, Protoc > } > } > >-void InspectorRuntimeAgent::evaluate(ErrorString& errorString, const String& expression, const String* objectGroup, const bool* includeCommandLineAPI, const bool* doNotPauseOnExceptionsAndMuteConsole, const int* executionContextId, const bool* returnByValue, const bool* generatePreview, const bool* saveResult, RefPtr<Protocol::Runtime::RemoteObject>& result, std::optional<bool>& outWasThrown, std::optional<int>& savedResultIndex) >+void InspectorRuntimeAgent::evaluate(ErrorString& errorString, const String& expression, const String* objectGroup, const bool* includeCommandLineAPI, const bool* doNotPauseOnExceptionsAndMuteConsole, const int* executionContextId, const bool* returnByValue, const bool* generatePreview, const bool* saveResult, RefPtr<Protocol::Runtime::RemoteObject>& result, std::optional<bool>& wasThrown, std::optional<int>& savedResultIndex) > { > InjectedScript injectedScript = injectedScriptForEval(errorString, executionContextId); > if (injectedScript.hasNoValue()) >@@ -123,9 +123,7 @@ void InspectorRuntimeAgent::evaluate(ErrorString& errorString, const String& exp > if (asBool(doNotPauseOnExceptionsAndMuteConsole)) > muteConsole(); > >- bool wasThrown; > injectedScript.evaluate(errorString, expression, objectGroup ? *objectGroup : String(), asBool(includeCommandLineAPI), asBool(returnByValue), asBool(generatePreview), asBool(saveResult), result, wasThrown, savedResultIndex); >- outWasThrown = wasThrown; > > if (asBool(doNotPauseOnExceptionsAndMuteConsole)) { > unmuteConsole(); >@@ -133,7 +131,23 @@ void InspectorRuntimeAgent::evaluate(ErrorString& errorString, const String& exp > } > } > >-void InspectorRuntimeAgent::callFunctionOn(ErrorString& errorString, const String& objectId, const String& expression, const JSON::Array* optionalArguments, const bool* doNotPauseOnExceptionsAndMuteConsole, const bool* returnByValue, const bool* generatePreview, RefPtr<Protocol::Runtime::RemoteObject>& result, std::optional<bool>& outWasThrown) >+void InspectorRuntimeAgent::awaitPromise(const String& promiseObjectId, const bool* returnByValue, const bool* generatePreview, const bool* saveResult, Ref<AwaitPromiseCallback>&& callback) >+{ >+ InjectedScript injectedScript = m_injectedScriptManager.injectedScriptForObjectId(promiseObjectId); >+ if (injectedScript.hasNoValue()) { >+ callback->sendFailure("Could not find InjectedScript for promiseObjectId"_s); >+ return; >+ } >+ >+ injectedScript.awaitPromise(promiseObjectId, asBool(returnByValue), asBool(generatePreview), asBool(saveResult), [callback = WTFMove(callback)] (ErrorString& errorString, RefPtr<Protocol::Runtime::RemoteObject>&& result, std::optional<bool>& wasThrown, std::optional<int>& savedResultIndex) { >+ if (!errorString.isEmpty()) >+ callback->sendFailure(errorString); >+ else >+ callback->sendSuccess(WTFMove(result), wasThrown, savedResultIndex); >+ }); >+} >+ >+void InspectorRuntimeAgent::callFunctionOn(ErrorString& errorString, const String& objectId, const String& expression, const JSON::Array* optionalArguments, const bool* doNotPauseOnExceptionsAndMuteConsole, const bool* returnByValue, const bool* generatePreview, RefPtr<Protocol::Runtime::RemoteObject>& result, std::optional<bool>& wasThrown) > { > InjectedScript injectedScript = m_injectedScriptManager.injectedScriptForObjectId(objectId); > if (injectedScript.hasNoValue()) { >@@ -151,12 +165,8 @@ void InspectorRuntimeAgent::callFunctionOn(ErrorString& errorString, const Strin > if (asBool(doNotPauseOnExceptionsAndMuteConsole)) > muteConsole(); > >- bool wasThrown; >- > injectedScript.callFunctionOn(errorString, objectId, expression, arguments, asBool(returnByValue), asBool(generatePreview), result, wasThrown); > >- outWasThrown = wasThrown; >- > if (asBool(doNotPauseOnExceptionsAndMuteConsole)) { > unmuteConsole(); > setPauseOnExceptionsState(m_scriptDebugServer, previousPauseOnExceptionsState); >diff --git a/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.h b/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.h >index 29927b1f4971dfb510041c35a727af220fde01f3..ab6d7fc856bbf8f62250243cfd5c2e8231884b0c 100644 >--- a/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.h >+++ b/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.h >@@ -59,6 +59,7 @@ public: > void disable(ErrorString&) override { m_enabled = false; } > void parse(ErrorString&, const String& expression, Protocol::Runtime::SyntaxErrorType* result, std::optional<String>& message, RefPtr<Protocol::Runtime::ErrorRange>&) final; > void evaluate(ErrorString&, const String& expression, const String* objectGroup, const bool* includeCommandLineAPI, const bool* doNotPauseOnExceptionsAndMuteConsole, const int* executionContextId, const bool* returnByValue, const bool* generatePreview, const bool* saveResult, RefPtr<Protocol::Runtime::RemoteObject>& result, std::optional<bool>& wasThrown, std::optional<int>& savedResultIndex) final; >+ void awaitPromise(const String& promiseObjectId, const bool* returnByValue, const bool* generatePreview, const bool* saveResult, Ref<AwaitPromiseCallback>&&) final; > void callFunctionOn(ErrorString&, const String& objectId, const String& expression, const JSON::Array* optionalArguments, const bool* doNotPauseOnExceptionsAndMuteConsole, const bool* returnByValue, const bool* generatePreview, RefPtr<Protocol::Runtime::RemoteObject>& result, std::optional<bool>& wasThrown) final; > void releaseObject(ErrorString&, const ErrorString& objectId) final; > void getPreview(ErrorString&, const String& objectId, RefPtr<Protocol::Runtime::ObjectPreview>&) final; >diff --git a/Source/JavaScriptCore/inspector/protocol/Runtime.json b/Source/JavaScriptCore/inspector/protocol/Runtime.json >index 33d59a44c6f2f40850e1c0a589bd4bda444c1528..a7ed961cc8a1c592f47d6bc6584fafb39aae01b7 100644 >--- a/Source/JavaScriptCore/inspector/protocol/Runtime.json >+++ b/Source/JavaScriptCore/inspector/protocol/Runtime.json >@@ -225,6 +225,22 @@ > { "name": "savedResultIndex", "type": "integer", "optional": true, "description": "If the result was saved, this is the $n index that can be used to access the value." } > ] > }, >+ { >+ "name": "awaitPromise", >+ "description": "Evaluates promise on global object.", >+ "parameters": [ >+ { "name": "promiseObjectId", "$ref": "RemoteObjectId", "description": "Identifier of the promise." }, >+ { "name": "returnByValue", "type": "boolean", "optional": true, "description": "Whether the result is expected to be a JSON object that should be sent by value." }, >+ { "name": "generatePreview", "type": "boolean", "optional": true, "description": "Whether preview should be generated for the result." }, >+ { "name": "saveResult", "type": "boolean", "optional": true, "description": "Whether the resulting value should be considered for saving in the $n history." } >+ ], >+ "returns": [ >+ { "name": "result", "$ref": "RemoteObject", "description": "Evaluation result." }, >+ { "name": "wasThrown", "type": "boolean", "optional": true, "description": "True if the result was thrown during the evaluation." }, >+ { "name": "savedResultIndex", "type": "integer", "optional": true, "description": "If the result was saved, this is the $n index that can be used to access the value." } >+ ], >+ "async": true >+ }, > { > "name": "callFunctionOn", > "description": "Calls function with given declaration on the given object. Object group of the result is inherited from the target object.", >diff --git a/Source/WebInspectorUI/UserInterface/Controllers/RuntimeManager.js b/Source/WebInspectorUI/UserInterface/Controllers/RuntimeManager.js >index 5a14542aee9b9f4eb8727370eeb720a5140653fb..a71beeced20727d700dcf6913602d7be70c9f446 100644 >--- a/Source/WebInspectorUI/UserInterface/Controllers/RuntimeManager.js >+++ b/Source/WebInspectorUI/UserInterface/Controllers/RuntimeManager.js >@@ -34,6 +34,14 @@ WI.RuntimeManager = class RuntimeManager extends WI.Object > WI.Frame.addEventListener(WI.Frame.Event.ExecutionContextsCleared, this._frameExecutionContextsCleared, this); > } > >+ // Static >+ >+ static supportsAwaitPromise() >+ { >+ // COMPATIBILITY (iOS 12): Runtime.awaitPromise did not exist >+ return !!InspectorBackend.domains.Runtime.awaitPromise; >+ } >+ > // Target > > initializeTarget(target) >diff --git a/Source/WebInspectorUI/UserInterface/Models/AuditTestCase.js b/Source/WebInspectorUI/UserInterface/Models/AuditTestCase.js >index 7b365859b749e17df602b383c1ca8e8aadc6e95b..ee3ea5f0651995d93b34fd1eb5167ad4e12b54ab 100644 >--- a/Source/WebInspectorUI/UserInterface/Models/AuditTestCase.js >+++ b/Source/WebInspectorUI/UserInterface/Models/AuditTestCase.js >@@ -112,13 +112,9 @@ WI.AuditTestCase = class AuditTestCase extends WI.AuditTestBase > doNotPauseOnExceptionsAndMuteConsole: true, > }; > >- try { >- metadata.startTimestamp = new Date; >- let evaluateResponse = await RuntimeAgent.evaluate.invoke(evaluateArguments); >- metadata.endTimestamp = new Date; >- >- let remoteObject = WI.RemoteObject.fromPayload(evaluateResponse.result, WI.mainTarget); >- if (evaluateResponse.wasThrown || (remoteObject.type === "object" && remoteObject.subtype === "error")) >+ async function parseResponse(response) { >+ let remoteObject = WI.RemoteObject.fromPayload(response.result, WI.mainTarget); >+ if (response.wasThrown || (remoteObject.type === "object" && remoteObject.subtype === "error")) > addError(remoteObject.description); > else if (remoteObject.type === "boolean") > setLevel(remoteObject.value ? WI.AuditTestCaseResult.Level.Pass : WI.AuditTestCaseResult.Level.Fail); >@@ -234,6 +230,29 @@ WI.AuditTestCase = class AuditTestCase extends WI.AuditTestBase > }); > } else > addError(WI.UIString("Return value is not an object, string, or boolean")); >+ } >+ >+ try { >+ let response = null; >+ >+ metadata.startTimestamp = new Date; >+ response = await RuntimeAgent.evaluate.invoke(evaluateArguments); >+ metadata.endTimestamp = new Date; >+ >+ if (response.result.type === "object" && response.result.className === "Promise") { >+ if (WI.RuntimeManager.supportsAwaitPromise()) { >+ metadata.asyncTimestamp = metadata.endTimestamp; >+ response = await RuntimeAgent.awaitPromise(response.result.objectId); >+ metadata.endTimestamp = new Date; >+ } else { >+ response = null; >+ addError(WI.UIString("Async audits are not supported on this device.")); >+ setLevel(WI.AuditTestCaseResult.Level.Unsupported); >+ } >+ } >+ >+ if (response) >+ await parseResponse(response); > } catch (error) { > metadata.endTimestamp = new Date; > addError(error.message); >diff --git a/Source/WebInspectorUI/UserInterface/Views/AuditTestCaseContentView.js b/Source/WebInspectorUI/UserInterface/Views/AuditTestCaseContentView.js >index 1fcb53b7ca2df738621eeaeeb824cf70025f4873..156612c5985a6ed2e943b1d40132d9db9cdeffc0 100644 >--- a/Source/WebInspectorUI/UserInterface/Views/AuditTestCaseContentView.js >+++ b/Source/WebInspectorUI/UserInterface/Views/AuditTestCaseContentView.js >@@ -104,9 +104,19 @@ WI.AuditTestCaseContentView = class AuditTestCaseContentView extends WI.AuditTes > timeElement.textContent = metadata.startTimestamp.toLocaleString(); > > if (metadata.endTimestamp) { >+ let totalDuration = Number.secondsToString((metadata.endTimestamp - metadata.startTimestamp) / 1000); >+ > let durationElement = this._metadataElement.appendChild(document.createElement("span")); > durationElement.classList.add("duration"); >- durationElement.textContent = Number.secondsToString((metadata.endTimestamp - metadata.startTimestamp) / 1000); >+ durationElement.textContent = totalDuration; >+ >+ if (metadata.asyncTimestamp) { >+ let evalDuration = Number.secondsToString((metadata.asyncTimestamp - metadata.startTimestamp) / 1000); >+ let asyncDuration = Number.secondsToString((metadata.endTimestamp - metadata.asyncTimestamp) / 1000); >+ >+ durationElement.classList.add("async"); >+ durationElement.title = WI.UIString("%s eval\n%s async").format(evalDuration, asyncDuration); >+ } > } > } > >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index 8a41c60d2ded46a9440ff52ee78036448d75bf9f..e6daed2b316673bfe586a549cb95ab10c593456c 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,21 @@ >+2018-11-30 Devin Rousso <drousso@apple.com> >+ >+ Web Inspector: Audit: tests should support async operations >+ https://bugs.webkit.org/show_bug.cgi?id=192171 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * inspector/audit/resources/audit-utilities.js: >+ (TestPage.registerInitializer.InspectorTest.Audit.addFunctionlessTest): >+ (TestPage.registerInitializer.InspectorTest.Audit.addStringTest): >+ (TestPage.registerInitializer.InspectorTest.Audit.addObjectTest): >+ (TestPage.registerInitializer.InspectorTest.Audit.addPromiseTest): Added. >+ * inspector/audit/basic-expected.txt: >+ * inspector/audit/basic.html: >+ >+ * inspector/runtime/awaitPromise-expected.txt: Added. >+ * inspector/runtime/awaitPromise.html: Added. >+ > 2018-11-29 Frederic Wang <fwang@igalia.com> > > Separate paint and scroll offsets for RenderLayerBacking::m_scrollingContentsLayer >diff --git a/LayoutTests/inspector/audit/basic-expected.txt b/LayoutTests/inspector/audit/basic-expected.txt >index 4246c2982c5361dd192389f0669d071554f259f4..c1a9a393f51d3f3b16e91b236d3ff5dc6624bd88 100644 >--- a/LayoutTests/inspector/audit/basic-expected.txt >+++ b/LayoutTests/inspector/audit/basic-expected.txt >@@ -50,23 +50,51 @@ PASS: Result should be "error". > Testing value `{"level":"unsupported"}`... > PASS: Result should be "unsupported". > >+-- Running test case: Audit.Basic.Promise.Boolean.True >+Testing value `new Promise((resolve, reject) => resolve(true))`... >+PASS: Result should be "pass". >+ >+-- Running test case: Audit.Basic.Promise.String.Pass >+Testing value `new Promise((resolve, reject) => resolve("pass"))`... >+PASS: Result should be "pass". >+ >+-- Running test case: Audit.Basic.Promise.Object.Pass >+Testing value `new Promise((resolve, reject) => resolve({level: "pass"}))`... >+PASS: Result should be "pass". >+ >+-- Running test case: Audit.Basic.Async.Boolean.True >+Testing value `true`... >+PASS: Result should be "pass". >+ >+-- Running test case: Audit.Basic.Async.String.Pass >+Testing value `"pass"`... >+PASS: Result should be "pass". >+ >+-- Running test case: Audit.Basic.Async.Object.Pass >+Testing value `{"level":"pass"}`... >+PASS: Result should be "pass". >+ >+-- Running test case: Audit.Basic.Timeout.Pass >+Testing value `new Promise((resolve, reject) => setTimeout(resolve, 10, "pass"))`... >+PASS: Result should be "pass". >+ > -- Running test case: Audit.Basic.Error.Undefined >-Testing... >+Testing value `undefined`... > PASS: Result should be "error". > errors: >- - TypeError: eval(undefined) is not a function. (In 'eval(undefined)()', 'eval(undefined)' is undefined) >+ - Return value is not an object, string, or boolean > > -- Running test case: Audit.Basic.Error.Null >-Testing... >+Testing value `null`... > PASS: Result should be "error". > errors: >- - TypeError: eval(null) is not a function. (In 'eval(null)()', 'eval(null)' is null) >+ - Return value is not an object, string, or boolean > > -- Running test case: Audit.Basic.Error.Number >-Testing... >+Testing value `42`... > PASS: Result should be "error". > errors: >- - TypeError: eval(42) is not a function. (In 'eval(42)()', 'eval(42)' is 42) >+ - Return value is not an object, string, or boolean > > -- Running test case: Audit.Basic.Error.String > Testing value `"foo"`... >@@ -81,8 +109,20 @@ PASS: Result should be "error". > - Missing result level > > -- Running test case: Audit.Basic.Error.Variable >-Testing... >+Testing value `INVALID`... > PASS: Result should be "error". > errors: > - ReferenceError: Can't find variable: INVALID > >+-- Running test case: Audit.Basic.Error.Promise.Resolved >+Testing value `new Promise((resolve, reject) => setTimeout(resolve, 10))`... >+PASS: Result should be "error". >+ errors: >+ - Return value is not an object, string, or boolean >+ >+-- Running test case: Audit.Basic.Error.Promise.Rejected >+Testing value `new Promise((resolve, reject) => setTimeout(reject, 10, "rejected"))`... >+PASS: Result should be "error". >+ errors: >+ - rejected >+ >diff --git a/LayoutTests/inspector/audit/basic.html b/LayoutTests/inspector/audit/basic.html >index 085a04adc6ae5736e82c373906c4cd5a9fe82362..9fff45597aaf11643d26fdb75c07da37e11a31ca 100644 >--- a/LayoutTests/inspector/audit/basic.html >+++ b/LayoutTests/inspector/audit/basic.html >@@ -23,12 +23,24 @@ function test() > InspectorTest.Audit.addObjectTest("Audit.Basic.Object.Error", {level: WI.AuditTestCaseResult.Level.Error}, WI.AuditTestCaseResult.Level.Error); > InspectorTest.Audit.addObjectTest("Audit.Basic.Object.Unsupported", {level: WI.AuditTestCaseResult.Level.Unsupported}, WI.AuditTestCaseResult.Level.Unsupported); > >- InspectorTest.Audit.addTest("Audit.Basic.Error.Undefined", undefined, WI.AuditTestCaseResult.Level.Error); >- InspectorTest.Audit.addTest("Audit.Basic.Error.Null", null, WI.AuditTestCaseResult.Level.Error); >- InspectorTest.Audit.addTest("Audit.Basic.Error.Number", 42, WI.AuditTestCaseResult.Level.Error); >+ InspectorTest.Audit.addPromiseTest("Audit.Basic.Promise.Boolean.True", `resolve(true)`, WI.AuditTestCaseResult.Level.Pass); >+ InspectorTest.Audit.addPromiseTest("Audit.Basic.Promise.String.Pass", `resolve("${WI.AuditTestCaseResult.Level.Pass}")`, WI.AuditTestCaseResult.Level.Pass); >+ InspectorTest.Audit.addPromiseTest("Audit.Basic.Promise.Object.Pass", `resolve({level: "${WI.AuditTestCaseResult.Level.Pass}"})`, WI.AuditTestCaseResult.Level.Pass); >+ >+ InspectorTest.Audit.addFunctionlessTest("Audit.Basic.Async.Boolean.True", true, WI.AuditTestCaseResult.Level.Pass, {async: true}); >+ InspectorTest.Audit.addStringTest("Audit.Basic.Async.String.Pass", WI.AuditTestCaseResult.Level.Pass, WI.AuditTestCaseResult.Level.Pass, {async: true}); >+ InspectorTest.Audit.addObjectTest("Audit.Basic.Async.Object.Pass", {level: WI.AuditTestCaseResult.Level.Pass}, WI.AuditTestCaseResult.Level.Pass, {async: true}); >+ >+ InspectorTest.Audit.addPromiseTest("Audit.Basic.Timeout.Pass", `setTimeout(resolve, 100, "${WI.AuditTestCaseResult.Level.Pass}")`, WI.AuditTestCaseResult.Level.Pass); >+ >+ InspectorTest.Audit.addFunctionlessTest("Audit.Basic.Error.Undefined", undefined, WI.AuditTestCaseResult.Level.Error); >+ InspectorTest.Audit.addFunctionlessTest("Audit.Basic.Error.Null", null, WI.AuditTestCaseResult.Level.Error); >+ InspectorTest.Audit.addFunctionlessTest("Audit.Basic.Error.Number", 42, WI.AuditTestCaseResult.Level.Error); > InspectorTest.Audit.addStringTest("Audit.Basic.Error.String", "foo", WI.AuditTestCaseResult.Level.Error); > InspectorTest.Audit.addObjectTest("Audit.Basic.Error.Object", {}, WI.AuditTestCaseResult.Level.Error); >- InspectorTest.Audit.addTest("Audit.Basic.Error.Variable", "INVALID", WI.AuditTestCaseResult.Level.Error); >+ InspectorTest.Audit.addFunctionlessTest("Audit.Basic.Error.Variable", "INVALID", WI.AuditTestCaseResult.Level.Error); >+ InspectorTest.Audit.addPromiseTest("Audit.Basic.Error.Promise.Resolved", `setTimeout(resolve, 100)`, WI.AuditTestCaseResult.Level.Error); >+ InspectorTest.Audit.addPromiseTest("Audit.Basic.Error.Promise.Rejected", `setTimeout(reject, 100, "rejected")`, WI.AuditTestCaseResult.Level.Error); > > suite.runTestCasesAndFinish(); > } >diff --git a/LayoutTests/inspector/audit/resources/audit-utilities.js b/LayoutTests/inspector/audit/resources/audit-utilities.js >index 136b59d5559f34b8c5029c0300782dc145b1cc8d..10f114c82e00597205a57cfb5e5bffe4ad218fdd 100644 >--- a/LayoutTests/inspector/audit/resources/audit-utilities.js >+++ b/LayoutTests/inspector/audit/resources/audit-utilities.js >@@ -69,18 +69,22 @@ TestPage.registerInitializer(() => { > }); > }; > >- InspectorTest.Audit.addFunctionlessTest = function(name, test, level) { >- InspectorTest.Audit.addTest(name, `function() { return ${test} }`, level, { >+ InspectorTest.Audit.addFunctionlessTest = function(name, test, level, options = {}) { >+ InspectorTest.Audit.addTest(name, (options.async ? "async " : "") + `function() { return ${test} }`, level, { > beforeStart: ` value \`${test}\``, > }); > }; > >- InspectorTest.Audit.addStringTest = function(name, test, level) { >- InspectorTest.Audit.addFunctionlessTest(name, `"${test}"`, level); >+ InspectorTest.Audit.addStringTest = function(name, test, level, options = {}) { >+ InspectorTest.Audit.addFunctionlessTest(name, `"${test}"`, level, options); > }; > >- InspectorTest.Audit.addObjectTest = function(name, test, level) { >- InspectorTest.Audit.addFunctionlessTest(name, JSON.stringify(test), level); >+ InspectorTest.Audit.addObjectTest = function(name, test, level, options = {}) { >+ InspectorTest.Audit.addFunctionlessTest(name, JSON.stringify(test), level, options); >+ }; >+ >+ InspectorTest.Audit.addPromiseTest = function(name, test, level, options = {}) { >+ InspectorTest.Audit.addFunctionlessTest(name, `new Promise((resolve, reject) => ${test})`, level, options); > }; > > InspectorTest.Audit.addDOMSelectorTest = function(name, test, level) { >diff --git a/LayoutTests/inspector/runtime/awaitPromise-expected.txt b/LayoutTests/inspector/runtime/awaitPromise-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..d915638b527d91141945b95ed50d277538945abe >--- /dev/null >+++ b/LayoutTests/inspector/runtime/awaitPromise-expected.txt >@@ -0,0 +1,68 @@ >+Tests functionality of Runtime.awaitPromise. >+ >+ >+== Running test suite: Runtime.awaitPromise >+-- Running test case: Runtime.awaitPromise.Resolve.Undefined >+{"type":"undefined"} >+PASS: The resolved value should be undefined >+ >+-- Running test case: Runtime.awaitPromise.Resolve.Null >+{"type":"object","value":null,"subtype":"null"} >+PASS: The resolved value should be null >+ >+-- Running test case: Runtime.awaitPromise.Resolve.Boolean >+{"type":"boolean","value":true} >+PASS: The resolved value should be true >+ >+-- Running test case: Runtime.awaitPromise.Resolve.Number >+{"type":"number","value":42,"description":"42"} >+PASS: The resolved value should be 42 >+ >+-- Running test case: Runtime.awaitPromise.Resolve.String >+{"type":"string","value":"foo"} >+PASS: The resolved value should be "foo" >+ >+-- Running test case: Runtime.awaitPromise.Resolve.Array >+{"type":"object","value":[0,1]} >+PASS: The resolved value should be [0,1] >+ >+-- Running test case: Runtime.awaitPromise.Resolve.Object >+{"type":"object","value":{"a":1,"b":2}} >+PASS: The resolved value should be {"a":1,"b":2} >+ >+-- Running test case: Runtime.awaitPromise.Reject.Undefined >+{"type":"undefined","description":"undefined"} >+PASS: The rejected value should be undefined >+ >+-- Running test case: Runtime.awaitPromise.Reject.Null >+{"type":"object","value":null,"subtype":"null","description":"null"} >+PASS: The rejected value should be null >+ >+-- Running test case: Runtime.awaitPromise.Reject.Boolean >+{"type":"boolean","value":true,"description":"true"} >+PASS: The rejected value should be true >+ >+-- Running test case: Runtime.awaitPromise.Reject.Number >+{"type":"number","value":42,"description":"42"} >+PASS: The rejected value should be 42 >+ >+-- Running test case: Runtime.awaitPromise.Reject.String >+{"type":"string","value":"foo","description":"foo"} >+PASS: The rejected value should be "foo" >+ >+-- Running test case: Runtime.awaitPromise.Reject.Array >+{"type":"object","objectId":"{\"injectedScriptId\":1,\"id\":14}","subtype":"array","className":"Array","description":"0,1","size":2} >+PASS: The rejected value should be [0,1] >+ >+-- Running test case: Runtime.awaitPromise.Reject.Object >+{"type":"object","objectId":"{\"injectedScriptId\":1,\"id\":61}","className":"Object","description":"[object Object]"} >+PASS: The rejected value should be {"a":1,"b":2} >+ >+-- Running test case: Runtime.awaitPromise.Error.NonPromiseObjectId >+PASS: Should produce an error. >+Error: Error: Object with given id is not a Promise >+ >+-- Running test case: Runtime.awaitPromise.Error.InvalidPromiseObjectId >+PASS: Should produce an error. >+Error: Could not find InjectedScript for promiseObjectId >+ >diff --git a/LayoutTests/inspector/runtime/awaitPromise.html b/LayoutTests/inspector/runtime/awaitPromise.html >new file mode 100644 >index 0000000000000000000000000000000000000000..fae5fb4aec20d04525e6ecf2372b176253774a70 >--- /dev/null >+++ b/LayoutTests/inspector/runtime/awaitPromise.html >@@ -0,0 +1,116 @@ >+<!DOCTYPE html> >+<html> >+<head> >+<script src="../../http/tests/inspector/resources/inspector-test.js"></script> >+<script src="resources/audit-utilities.js"></script> >+<script> >+function test() >+{ >+ let savedResultCount = 0; >+ >+ let suite = InspectorTest.createAsyncSuite("Runtime.awaitPromise"); >+ >+ function addTest(name, expression, options = {}, callback) { >+ suite.addTestCase({ >+ name, >+ async test() { >+ let evaluateResponse = await RuntimeAgent.evaluate(expression); >+ InspectorTest.assert(evaluateResponse.result.type === "object"); >+ InspectorTest.assert(evaluateResponse.result.className === "Promise"); >+ >+ let awaitPromiseResponse = await RuntimeAgent.awaitPromise(evaluateResponse.result.objectId, options.returnByValue, options.generatePreview, options.saveResult); >+ >+ if (!awaitPromiseResponse.wasThrown && options.saveResult) >+ InspectorTest.assert(++savedResultCount === awaitPromiseResponse.savedResultIndex, "savedResultIndex should match."); >+ >+ InspectorTest.log(awaitPromiseResponse.result); >+ await callback(WI.RemoteObject.fromPayload(awaitPromiseResponse.result), awaitPromiseResponse.wasThrown, awaitPromiseResponse.savedResultIndex); >+ }, >+ }); >+ } >+ >+ function addResolveTest(name, value, options = {}) { >+ let expression = `new Promise((resolve, reject) => setTimeout(resolve, 100, ${JSON.stringify(value)}))`; >+ addTest(name, expression, options, async (remoteObject, wasThrown) => { >+ InspectorTest.assert(!wasThrown, "There should be no error."); >+ if (options.returnByValue) { >+ if (value && typeof value === "object") >+ InspectorTest.expectShallowEqual(remoteObject.value, value, "The resolved value should be " + JSON.stringify(value)); >+ else >+ InspectorTest.expectEqual(remoteObject.value, value, "The resolved value should be " + JSON.stringify(value)); >+ } else { >+ InspectorTest.expectEqual(remoteObject.type, value.type, "The type should be " + value.type); >+ InspectorTest.expectEqual(remoteObject.subtype, value.subtype, "The subtype should be " + value.subtype); >+ InspectorTest.expectEqual(remoteObject.description, value.description, "The description should be " + value.description); >+ } >+ }); >+ } >+ >+ function addRejectTest(name, value, options = {}) { >+ let expression = `new Promise((resolve, reject) => setTimeout(reject, 100, ${JSON.stringify(value)}))`; >+ addTest(name, expression, options, async (remoteObject, wasThrown) => { >+ InspectorTest.assert(wasThrown, "There should be an error."); >+ if (value && typeof value === "object") { >+ let propertyDescriptors = await new Promise((resolve) => remoteObject.getPropertyDescriptorsAsObject(resolve)); >+ let properties = Array.isArray(value) ? [] : {}; >+ for (let key in value) >+ properties[key] = propertyDescriptors[key].value.value; >+ InspectorTest.expectShallowEqual(properties, value, "The rejected value should be " + JSON.stringify(value)); >+ } else >+ InspectorTest.expectEqual(remoteObject.value, value, "The rejected value should be " + JSON.stringify(value)); >+ }); >+ } >+ >+ addResolveTest("Runtime.awaitPromise.Resolve.Undefined", undefined, {returnByValue: true, saveResult: true}); >+ addResolveTest("Runtime.awaitPromise.Resolve.Null", null, {returnByValue: true, saveResult: true}); >+ addResolveTest("Runtime.awaitPromise.Resolve.Boolean", true, {returnByValue: true, saveResult: true}); >+ addResolveTest("Runtime.awaitPromise.Resolve.Number", 42, {returnByValue: true, saveResult: true}); >+ addResolveTest("Runtime.awaitPromise.Resolve.String", "foo", {returnByValue: true, saveResult: true}); >+ addResolveTest("Runtime.awaitPromise.Resolve.Array", [0, 1], {returnByValue: true, saveResult: true}); >+ addResolveTest("Runtime.awaitPromise.Resolve.Object", {a: 1, b: 2}, {returnByValue: true, saveResult: true}); >+ >+ addRejectTest("Runtime.awaitPromise.Reject.Undefined", undefined); >+ addRejectTest("Runtime.awaitPromise.Reject.Null", null); >+ addRejectTest("Runtime.awaitPromise.Reject.Boolean", true); >+ addRejectTest("Runtime.awaitPromise.Reject.Number", 42); >+ addRejectTest("Runtime.awaitPromise.Reject.String", "foo"); >+ addRejectTest("Runtime.awaitPromise.Reject.Array", [0, 1]); >+ addRejectTest("Runtime.awaitPromise.Reject.Object", {a: 1, b: 2}); >+ >+ suite.addTestCase({ >+ name: "Runtime.awaitPromise.Error.NonPromiseObjectId", >+ test(resolve, reject) { >+ RuntimeAgent.evaluate("window") >+ .then((response) => RuntimeAgent.awaitPromise(response.result.objectId)) >+ .then((response) => { >+ InspectorTest.fail("Should not be able to call awaitPromise for a non-Promise object."); >+ resolve(); >+ }) >+ .catch((error) => { >+ InspectorTest.expectThat(error, "Should produce an error."); >+ InspectorTest.log("Error: " + error); >+ resolve(); >+ }); >+ }, >+ }); >+ >+ suite.addTestCase({ >+ name: "Runtime.awaitPromise.Error.InvalidPromiseObjectId", >+ test(resolve, reject) { >+ const promiseObjectId = "DOES_NOT_EXIST"; >+ RuntimeAgent.awaitPromise(promiseObjectId, (error) => { >+ InspectorTest.expectThat(error, "Should produce an error."); >+ InspectorTest.log("Error: " + error); >+ resolve(); >+ }); >+ }, >+ }); >+ >+ suite.runTestCasesAndFinish(); >+} >+</script> >+</head> >+<body onload="runTest()"> >+ <p>Tests functionality of Runtime.awaitPromise.</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
Flags:
ews-watchlist
:
commit-queue-
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 192171
:
356034
|
356045
|
356051
|
356056
|
356073
|
356077
|
356096
|
356160
|
356164
|
356166
|
356183
|
356200
|
356218
|
356220
|
356228
|
356229
|
356286
|
356453
|
356457
|
356470
|
356471