// Copyright 2014 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_SCRIPT_STATE_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_SCRIPT_STATE_H_ #include "base/memory/raw_ptr.h" #include "gin/public/context_holder.h" #include "gin/public/gin_embedders.h" #include "third_party/blink/public/common/tokens/tokens.h" #include "third_party/blink/renderer/platform/bindings/scoped_persistent.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" #include "third_party/blink/renderer/platform/heap/member.h" #include "third_party/blink/renderer/platform/heap/self_keep_alive.h" #include "third_party/blink/renderer/platform/platform_export.h" #include "third_party/blink/renderer/platform/wtf/assertions.h" #include "v8/include/v8.h" namespace blink { class DOMWrapperWorld; class ExecutionContext; class ScriptValue; class V8PerContextData; // ScriptState is an abstraction class that holds all information about script // execution (e.g., v8::Isolate, v8::Context, DOMWrapperWorld, ExecutionContext // etc). If you need any info about the script execution, you're expected to // pass around ScriptState in the code base. ScriptState is in a 1:1 // relationship with v8::Context. // // When you need ScriptState, you can add [CallWith=ScriptState] to IDL files // and pass around ScriptState into a place where you need ScriptState. // // In some cases, you need ScriptState in code that doesn't have any JavaScript // on the stack. Then you can store ScriptState on a C++ object using // Member<ScriptState> or Persistent<ScriptState>. // // class SomeObject : public GarbageCollected<SomeObject> { // void someMethod(ScriptState* scriptState) { // script_state_ = scriptState; // Record the ScriptState. // ...; // } // // void asynchronousMethod() { // if (!script_state_->contextIsValid()) { // // It's possible that the context is already gone. // return; // } // // Enter the ScriptState. // ScriptState::Scope scope(script_state_); // // Do V8 related things. // ToV8(...); // } // // virtual void Trace(Visitor* visitor) const { // visitor->Trace(script_state_); // ScriptState also needs to be traced. // } // // Member<ScriptState> script_state_; // }; // // You should not store ScriptState on a C++ object that can be accessed // by multiple worlds. For example, you can store ScriptState on // ScriptPromiseResolverBase, ScriptValue etc because they can be accessed from // one world. However, you cannot store ScriptState on a DOM object that has an // IDL interface because the DOM object can be accessed from multiple worlds. If // ScriptState of one world "leak"s to another world, you will end up with // leaking any JavaScript objects from one Chrome extension to another Chrome // extension, which is a severe security bug. // // Lifetime: // ScriptState is created when v8::Context is created. // ScriptState is destroyed when v8::Context is garbage-collected and // all V8 proxy objects that have references to the ScriptState are destructed. class PLATFORM_EXPORT ScriptState : public GarbageCollected<ScriptState> { … }; // ScriptStateProtectingContext keeps the context associated with the // ScriptState alive. You need to call Clear() once you no longer need the // context. Otherwise, the context will leak. class ScriptStateProtectingContext final : public GarbageCollected<ScriptStateProtectingContext> { … }; } // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_SCRIPT_STATE_H_