Commit 2be20513 authored by Rika Fujimaki's avatar Rika Fujimaki Committed by Commit Bot

Replace ScriptValue's value with Member<WorldSafeV8ReferenceWrapper>

Since we can't trace WorldSafeV8Reference on stack,
we use Member<WorldSafeV8ReferenceWrapper>.
WorldSafeV8ReferenceWrapper class wraps WorldSafeV8Reference.

Note that we remove ScriptValue::ToWorldSafeV8Reference() for now,
but revive this once we ensure that TraceWrapperV8Reference's copy assignment
is not buggy.

Bug: 1007881, 1008258, 1008215, 1007881, 1007868
Bug: 1007865, 1007341
Change-Id: Ief22c6138394a512df9454d3c5bfad0bf35f8425
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1828783
Commit-Queue: Rika Fujimaki <rikaf@google.com>
Reviewed-by: default avatarYuki Shiino <yukishiino@chromium.org>
Reviewed-by: default avatarKeishi Hattori <keishi@chromium.org>
Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
Cr-Commit-Position: refs/heads/master@{#701030}
parent d78367f9
...@@ -41,7 +41,7 @@ v8::Local<v8::Value> ScriptValue::V8Value() const { ...@@ -41,7 +41,7 @@ v8::Local<v8::Value> ScriptValue::V8Value() const {
return v8::Local<v8::Value>(); return v8::Local<v8::Value>();
DCHECK(GetIsolate()->InContext()); DCHECK(GetIsolate()->InContext());
return value_.Get(ScriptState::From(isolate_->GetCurrentContext())); return value_->Get(ScriptState::From(isolate_->GetCurrentContext()));
} }
v8::Local<v8::Value> ScriptValue::V8ValueFor( v8::Local<v8::Value> ScriptValue::V8ValueFor(
...@@ -49,7 +49,7 @@ v8::Local<v8::Value> ScriptValue::V8ValueFor( ...@@ -49,7 +49,7 @@ v8::Local<v8::Value> ScriptValue::V8ValueFor(
if (IsEmpty()) if (IsEmpty())
return v8::Local<v8::Value>(); return v8::Local<v8::Value>();
return value_.GetAcrossWorld(target_script_state); return value_->GetAcrossWorld(target_script_state);
} }
bool ScriptValue::ToString(String& result) const { bool ScriptValue::ToString(String& result) const {
......
...@@ -73,12 +73,12 @@ class CORE_EXPORT ScriptValue final { ...@@ -73,12 +73,12 @@ class CORE_EXPORT ScriptValue final {
// TODO(rikaf): Forbid passing empty v8::Local<v8::Value> to ScriptValue's // TODO(rikaf): Forbid passing empty v8::Local<v8::Value> to ScriptValue's
// ctor. // ctor.
ScriptValue(v8::Isolate* isolate, v8::Local<v8::Value> value) ScriptValue(v8::Isolate* isolate, v8::Local<v8::Value> value)
: isolate_(isolate), : isolate_(isolate),
value_(value.IsEmpty() value_(value.IsEmpty()
? WorldSafeV8Reference<v8::Value>() ? MakeGarbageCollected<WorldSafeV8ReferenceWrapper>()
: WorldSafeV8Reference<v8::Value>(isolate, value)) { : MakeGarbageCollected<WorldSafeV8ReferenceWrapper>(isolate,
value)) {
DCHECK(isolate_); DCHECK(isolate_);
} }
...@@ -86,30 +86,17 @@ class CORE_EXPORT ScriptValue final { ...@@ -86,30 +86,17 @@ class CORE_EXPORT ScriptValue final {
ScriptValue(v8::Isolate* isolate, v8::MaybeLocal<T> value) ScriptValue(v8::Isolate* isolate, v8::MaybeLocal<T> value)
: isolate_(isolate), : isolate_(isolate),
value_(value.IsEmpty() value_(value.IsEmpty()
? WorldSafeV8Reference<v8::Value>() ? MakeGarbageCollected<WorldSafeV8ReferenceWrapper>()
: WorldSafeV8Reference<v8::Value>(isolate, : MakeGarbageCollected<WorldSafeV8ReferenceWrapper>(
value.ToLocalChecked())) { isolate,
DCHECK(isolate_); value.ToLocalChecked())) {
}
ScriptValue(v8::Isolate* isolate, WorldSafeV8Reference<v8::Value> value)
: isolate_(isolate), value_(value) {
DCHECK(isolate_); DCHECK(isolate_);
} }
ScriptValue(const ScriptValue& value) { ScriptValue(const ScriptValue& value) = default;
// TODO(crbug.com/v8/9773): Deal with null value at the side of v8.
if (value.IsEmpty()) {
isolate_ = nullptr;
value_.Reset();
} else {
isolate_ = value.isolate_;
value_ = value.value_;
DCHECK(isolate_);
}
}
// Use this GetIsolate() to do DCHECK inside ScriptValue. // TODO(riakf): Use this GetIsolate() only when doing DCHECK inside
// ScriptValue.
v8::Isolate* GetIsolate() const { v8::Isolate* GetIsolate() const {
DCHECK(isolate_); DCHECK(isolate_);
return isolate_; return isolate_;
...@@ -118,7 +105,11 @@ class CORE_EXPORT ScriptValue final { ...@@ -118,7 +105,11 @@ class CORE_EXPORT ScriptValue final {
ScriptValue& operator=(const ScriptValue& value) = default; ScriptValue& operator=(const ScriptValue& value) = default;
bool operator==(const ScriptValue& value) const { bool operator==(const ScriptValue& value) const {
return value_ == value.value_; if (IsEmpty())
return value.IsEmpty();
if (value.IsEmpty())
return false;
return *value_ == *value.value_;
} }
bool operator!=(const ScriptValue& value) const { return !operator==(value); } bool operator!=(const ScriptValue& value) const { return !operator==(value); }
...@@ -155,11 +146,11 @@ class CORE_EXPORT ScriptValue final { ...@@ -155,11 +146,11 @@ class CORE_EXPORT ScriptValue final {
return !value.IsEmpty() && value->IsObject(); return !value.IsEmpty() && value->IsObject();
} }
bool IsEmpty() const { return value_.IsEmpty(); } bool IsEmpty() const { return !value_ || value_->IsEmpty(); }
void Clear() { void Clear() {
isolate_ = nullptr; isolate_ = nullptr;
value_.Reset(); value_.Clear();
} }
v8::Local<v8::Value> V8Value() const; v8::Local<v8::Value> V8Value() const;
...@@ -168,10 +159,6 @@ class CORE_EXPORT ScriptValue final { ...@@ -168,10 +159,6 @@ class CORE_EXPORT ScriptValue final {
// this "clones" the v8 value and returns it. // this "clones" the v8 value and returns it.
v8::Local<v8::Value> V8ValueFor(ScriptState*) const; v8::Local<v8::Value> V8ValueFor(ScriptState*) const;
const WorldSafeV8Reference<v8::Value>& ToWorldSafeV8Reference() const {
return value_;
}
bool ToString(String&) const; bool ToString(String&) const;
static ScriptValue CreateNull(v8::Isolate*); static ScriptValue CreateNull(v8::Isolate*);
...@@ -179,8 +166,41 @@ class CORE_EXPORT ScriptValue final { ...@@ -179,8 +166,41 @@ class CORE_EXPORT ScriptValue final {
void Trace(Visitor* visitor) { visitor->Trace(value_); } void Trace(Visitor* visitor) { visitor->Trace(value_); }
private: private:
// WorldSafeV8ReferenceWrapper wraps a WorldSafeV8Reference so that it can be
// used on both the stack and heaps. WorldSafeV8Reference cannot be used on
// the stack because the conservative scanning does not know how to trace
// TraceWrapperV8Reference.
class CORE_EXPORT WorldSafeV8ReferenceWrapper
: public GarbageCollected<WorldSafeV8ReferenceWrapper> {
public:
WorldSafeV8ReferenceWrapper() = default;
WorldSafeV8ReferenceWrapper(v8::Isolate* isolate,
v8::Local<v8::Value> value)
: value_(isolate, value) {}
virtual ~WorldSafeV8ReferenceWrapper() = default;
void Trace(blink::Visitor* visitor) { visitor->Trace(value_); }
v8::Local<v8::Value> Get(ScriptState* script_state) const {
return value_.Get(script_state);
}
v8::Local<v8::Value> GetAcrossWorld(ScriptState* script_state) const {
return value_.GetAcrossWorld(script_state);
}
bool IsEmpty() const { return value_.IsEmpty(); }
bool operator==(const WorldSafeV8ReferenceWrapper& other) const {
return value_ == other.value_;
}
private:
WorldSafeV8Reference<v8::Value> value_;
};
v8::Isolate* isolate_ = nullptr; v8::Isolate* isolate_ = nullptr;
WorldSafeV8Reference<v8::Value> value_; Member<WorldSafeV8ReferenceWrapper> value_;
}; };
template <> template <>
......
...@@ -66,7 +66,7 @@ ErrorEvent::ErrorEvent(ScriptState* script_state, ...@@ -66,7 +66,7 @@ ErrorEvent::ErrorEvent(ScriptState* script_state,
initializer->hasLineno() ? initializer->lineno() : 0, initializer->hasLineno() ? initializer->lineno() : 0,
initializer->hasColno() ? initializer->colno() : 0, nullptr); initializer->hasColno() ? initializer->colno() : 0, nullptr);
if (initializer->hasError()) { if (initializer->hasError()) {
error_ = initializer->error().ToWorldSafeV8Reference(); error_.Set(script_state->GetIsolate(), initializer->error().V8Value());
} }
} }
...@@ -79,7 +79,7 @@ ErrorEvent::ErrorEvent(const String& message, ...@@ -79,7 +79,7 @@ ErrorEvent::ErrorEvent(const String& message,
location_(std::move(location)), location_(std::move(location)),
world_(world) { world_(world) {
if (!error.IsEmpty()) if (!error.IsEmpty())
error_ = error.ToWorldSafeV8Reference(); error_.Set(error.GetIsolate(), error.V8Value());
} }
void ErrorEvent::SetUnsanitizedMessage(const String& message) { void ErrorEvent::SetUnsanitizedMessage(const String& message) {
......
...@@ -73,7 +73,8 @@ MessageEvent::MessageEvent(const AtomicString& type, ...@@ -73,7 +73,8 @@ MessageEvent::MessageEvent(const AtomicString& type,
data_type_(kDataTypeScriptValue), data_type_(kDataTypeScriptValue),
source_(nullptr) { source_(nullptr) {
if (initializer->hasData()) { if (initializer->hasData()) {
data_as_v8_value_ = initializer->data().ToWorldSafeV8Reference(); data_as_v8_value_.Set(initializer->data().GetIsolate(),
initializer->data().V8Value());
} }
if (initializer->hasOrigin()) if (initializer->hasOrigin())
origin_ = initializer->origin(); origin_ = initializer->origin();
...@@ -194,7 +195,7 @@ void MessageEvent::initMessageEvent(const AtomicString& type, ...@@ -194,7 +195,7 @@ void MessageEvent::initMessageEvent(const AtomicString& type,
initEvent(type, bubbles, cancelable); initEvent(type, bubbles, cancelable);
data_type_ = kDataTypeScriptValue; data_type_ = kDataTypeScriptValue;
data_as_v8_value_ = data.ToWorldSafeV8Reference(); data_as_v8_value_.Set(data.GetIsolate(), data.V8Value());
is_data_dirty_ = true; is_data_dirty_ = true;
origin_ = origin; origin_ = origin;
last_event_id_ = last_event_id; last_event_id_ = last_event_id;
......
...@@ -50,23 +50,29 @@ void ModuleScript::SetParseErrorAndClearRecord(ScriptValue error) { ...@@ -50,23 +50,29 @@ void ModuleScript::SetParseErrorAndClearRecord(ScriptValue error) {
DCHECK(!error.IsEmpty()); DCHECK(!error.IsEmpty());
record_.Clear(); record_.Clear();
parse_error_ = error.ToWorldSafeV8Reference(); parse_error_.Set(settings_object_->GetScriptState()->GetIsolate(),
error.V8Value());
} }
ScriptValue ModuleScript::CreateParseError() const { ScriptValue ModuleScript::CreateParseError() const {
v8::Isolate* isolate = settings_object_->GetScriptState()->GetIsolate(); ScriptState* script_state = settings_object_->GetScriptState();
ScriptValue error(isolate, parse_error_); ScriptState::Scope scope(script_state);
ScriptValue error(script_state->GetIsolate(), parse_error_.Get(script_state));
DCHECK(!error.IsEmpty()); DCHECK(!error.IsEmpty());
return error; return error;
} }
void ModuleScript::SetErrorToRethrow(ScriptValue error) { void ModuleScript::SetErrorToRethrow(ScriptValue error) {
error_to_rethrow_ = error.ToWorldSafeV8Reference(); ScriptState* script_state = settings_object_->GetScriptState();
ScriptState::Scope scope(script_state);
error_to_rethrow_.Set(script_state->GetIsolate(), error.V8Value());
} }
ScriptValue ModuleScript::CreateErrorToRethrow() const { ScriptValue ModuleScript::CreateErrorToRethrow() const {
v8::Isolate* isolate = settings_object_->GetScriptState()->GetIsolate(); ScriptState* script_state = settings_object_->GetScriptState();
ScriptValue error(isolate, error_to_rethrow_); ScriptState::Scope scope(script_state);
ScriptValue error(script_state->GetIsolate(),
error_to_rethrow_.Get(script_state));
DCHECK(!error.IsEmpty()); DCHECK(!error.IsEmpty());
return error; return error;
} }
......
...@@ -18,18 +18,20 @@ PendingImportMap* PendingImportMap::CreateInline(ScriptElementBase& element, ...@@ -18,18 +18,20 @@ PendingImportMap* PendingImportMap::CreateInline(ScriptElementBase& element,
const KURL& base_url) { const KURL& base_url) {
Document& element_document = element.GetDocument(); Document& element_document = element.GetDocument();
Document* context_document = element_document.ContextDocument(); Document* context_document = element_document.ContextDocument();
Modulator* modulator = ScriptState* script_state =
Modulator::From(ToScriptStateForMainWorld(context_document->GetFrame())); ToScriptStateForMainWorld(context_document->GetFrame());
Modulator* modulator = Modulator::From(script_state);
ScriptValue error_to_rethrow; ScriptValue error_to_rethrow;
ImportMap* import_map = ImportMap* import_map =
ImportMap::Parse(*modulator, import_map_text, base_url, *context_document, ImportMap::Parse(*modulator, import_map_text, base_url, *context_document,
&error_to_rethrow); &error_to_rethrow);
return MakeGarbageCollected<PendingImportMap>( return MakeGarbageCollected<PendingImportMap>(
element, import_map, error_to_rethrow, *context_document); script_state, element, import_map, error_to_rethrow, *context_document);
} }
PendingImportMap::PendingImportMap(ScriptElementBase& element, PendingImportMap::PendingImportMap(ScriptState* script_state,
ScriptElementBase& element,
ImportMap* import_map, ImportMap* import_map,
ScriptValue error_to_rethrow, ScriptValue error_to_rethrow,
const Document& original_context_document) const Document& original_context_document)
...@@ -37,7 +39,9 @@ PendingImportMap::PendingImportMap(ScriptElementBase& element, ...@@ -37,7 +39,9 @@ PendingImportMap::PendingImportMap(ScriptElementBase& element,
import_map_(import_map), import_map_(import_map),
original_context_document_(&original_context_document) { original_context_document_(&original_context_document) {
if (!error_to_rethrow.IsEmpty()) { if (!error_to_rethrow.IsEmpty()) {
error_to_rethrow_ = error_to_rethrow.ToWorldSafeV8Reference(); ScriptState::Scope scope(script_state);
error_to_rethrow_.Set(script_state->GetIsolate(),
error_to_rethrow.V8Value());
} }
} }
...@@ -81,8 +85,13 @@ void PendingImportMap::RegisterImportMap() const { ...@@ -81,8 +85,13 @@ void PendingImportMap::RegisterImportMap() const {
Modulator* modulator = Modulator::From(ToScriptStateForMainWorld(frame)); Modulator* modulator = Modulator::From(ToScriptStateForMainWorld(frame));
v8::Isolate* isolate = modulator->GetScriptState()->GetIsolate(); ScriptState* script_state = modulator->GetScriptState();
ScriptValue error(isolate, error_to_rethrow_); ScriptState::Scope scope(script_state);
ScriptValue error;
if (!error_to_rethrow_.IsEmpty()) {
error = ScriptValue(script_state->GetIsolate(),
error_to_rethrow_.Get(script_state));
}
modulator->RegisterImportMap(import_map_, error); modulator->RegisterImportMap(import_map_, error);
// <spec step="9">If element is from an external file, then fire an event // <spec step="9">If element is from an external file, then fire an event
......
...@@ -40,7 +40,8 @@ class CORE_EXPORT PendingImportMap final ...@@ -40,7 +40,8 @@ class CORE_EXPORT PendingImportMap final
const String& import_map_text, const String& import_map_text,
const KURL& base_url); const KURL& base_url);
PendingImportMap(ScriptElementBase&, PendingImportMap(ScriptState* script_state,
ScriptElementBase&,
ImportMap*, ImportMap*,
ScriptValue error_to_rethrow, ScriptValue error_to_rethrow,
const Document& original_context_document); const Document& original_context_document);
......
...@@ -276,13 +276,13 @@ TEST(WakeLockControllerTest, LossOfDocumentActivity) { ...@@ -276,13 +276,13 @@ TEST(WakeLockControllerTest, LossOfDocumentActivity) {
// First, acquire a handful of locks of different types. // First, acquire a handful of locks of different types.
auto* screen_resolver1 = auto* screen_resolver1 =
MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState()); MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
ScriptPromise screen_promise1 = screen_resolver1->Promise(); screen_resolver1->Promise();
auto* screen_resolver2 = auto* screen_resolver2 =
MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState()); MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
ScriptPromise screen_promise2 = screen_resolver2->Promise(); screen_resolver2->Promise();
auto* system_resolver1 = auto* system_resolver1 =
MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState()); MakeGarbageCollected<ScriptPromiseResolver>(context.GetScriptState());
ScriptPromise system_promise1 = system_resolver1->Promise(); system_resolver1->Promise();
controller.RequestWakeLock(WakeLockType::kScreen, screen_resolver1, controller.RequestWakeLock(WakeLockType::kScreen, screen_resolver1,
/*signal=*/nullptr); /*signal=*/nullptr);
controller.RequestWakeLock(WakeLockType::kScreen, screen_resolver2, controller.RequestWakeLock(WakeLockType::kScreen, screen_resolver2,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment