[inspector] Don't use v8::Promise::Resolver for REPL mode
REPL mode always returns a promise since we basically turn the evaluated script in an async function. More-over, we stash the result as a property on a plain JS object. This prevents promise chains to resolve too far if the result of the evaluation is a promise itself. Long story short, we don't need to wrap REPL mode results in `Promise.resolve`, but can add the then/catch handlers directly. This fixes the DevTools console when working with broken promise polyfills or broken thenables. R=bmeurer@chromium.org Fixed: chromium:1371072 Change-Id: I96aa8eaf5939fdf6231712b047b50fee734efc0b Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3929037 Reviewed-by: Benedikt Meurer <bmeurer@chromium.org> Commit-Queue: Michael Achenbach <machenbach@chromium.org> Cr-Commit-Position: refs/heads/main@{#83578}
This commit is contained in:
parent
ed8953b695
commit
ad884d036f
@ -102,18 +102,6 @@ class InjectedScript::ProtocolPromiseHandler {
|
||||
Response response = scope.initialize();
|
||||
if (!response.IsSuccess()) return;
|
||||
|
||||
v8::Local<v8::Promise::Resolver> resolver;
|
||||
if (!v8::Promise::Resolver::New(context).ToLocal(&resolver)) {
|
||||
EvaluateCallback::sendFailure(callback, scope.injectedScript(),
|
||||
Response::InternalError());
|
||||
return;
|
||||
}
|
||||
if (!resolver->Resolve(context, value).FromMaybe(false)) {
|
||||
EvaluateCallback::sendFailure(callback, scope.injectedScript(),
|
||||
Response::InternalError());
|
||||
return;
|
||||
}
|
||||
|
||||
v8::MaybeLocal<v8::Promise> originalPromise =
|
||||
value->IsPromise() ? value.As<v8::Promise>()
|
||||
: v8::MaybeLocal<v8::Promise>();
|
||||
@ -130,7 +118,28 @@ class InjectedScript::ProtocolPromiseHandler {
|
||||
v8::Function::New(context, catchCallback, wrapper, 0,
|
||||
v8::ConstructorBehavior::kThrow)
|
||||
.ToLocalChecked();
|
||||
v8::Local<v8::Promise> promise = resolver->GetPromise();
|
||||
|
||||
v8::Local<v8::Promise> promise;
|
||||
v8::Local<v8::Promise::Resolver> resolver;
|
||||
if (value->IsPromise()) {
|
||||
// If value is a promise, we can chain the handlers directly onto `value`.
|
||||
promise = value.As<v8::Promise>();
|
||||
} else {
|
||||
// Otherwise we do `Promise.resolve(value)`.
|
||||
CHECK(!replMode);
|
||||
if (!v8::Promise::Resolver::New(context).ToLocal(&resolver)) {
|
||||
EvaluateCallback::sendFailure(callback, scope.injectedScript(),
|
||||
Response::InternalError());
|
||||
return;
|
||||
}
|
||||
if (!resolver->Resolve(context, value).FromMaybe(false)) {
|
||||
EvaluateCallback::sendFailure(callback, scope.injectedScript(),
|
||||
Response::InternalError());
|
||||
return;
|
||||
}
|
||||
promise = resolver->GetPromise();
|
||||
}
|
||||
|
||||
if (promise->Then(context, thenCallbackFunction, catchCallbackFunction)
|
||||
.IsEmpty()) {
|
||||
// Re-initialize after returning from JS.
|
||||
|
@ -0,0 +1,6 @@
|
||||
Tests that REPL mode still works even with a broken Promise.prototype.then
|
||||
{
|
||||
description : 42
|
||||
type : number
|
||||
value : 42
|
||||
}
|
20
test/inspector/runtime/evaluate-repl-mode-broken-thenable.js
Normal file
20
test/inspector/runtime/evaluate-repl-mode-broken-thenable.js
Normal file
@ -0,0 +1,20 @@
|
||||
// Copyright 2022 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
const {contextGroup, Protocol} = InspectorTest.start(
|
||||
"Tests that REPL mode still works even with a broken Promise.prototype.then");
|
||||
|
||||
(async function() {
|
||||
contextGroup.addScript(`
|
||||
Promise.prototype.then = () => {throw Error('you shall not evaluate')};
|
||||
`);
|
||||
|
||||
const { result: { result }} = await Protocol.Runtime.evaluate({
|
||||
expression: '42',
|
||||
replMode: true,
|
||||
});
|
||||
InspectorTest.logMessage(result);
|
||||
|
||||
InspectorTest.completeTest();
|
||||
})();
|
Loading…
Reference in New Issue
Block a user