chromium/third_party/blink/renderer/platform/bindings/script_state.h

// 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_