mirror of
https://github.com/zebrajr/node.git
synced 2026-01-15 12:15:26 +00:00
This allows timeouts to apply to e.g. `Promise`s and `async function`s from code running inside of `vm.Context`s, by giving the Context its own microtasks queue. Fixes: https://github.com/nodejs/node/issues/3020 PR-URL: https://github.com/nodejs/node/pull/34023 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Denys Otrishko <shishugi@gmail.com>
190 lines
6.4 KiB
C++
190 lines
6.4 KiB
C++
#ifndef SRC_NODE_CONTEXTIFY_H_
|
|
#define SRC_NODE_CONTEXTIFY_H_
|
|
|
|
#if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
|
|
|
|
#include "base_object-inl.h"
|
|
#include "node_context_data.h"
|
|
#include "node_errors.h"
|
|
|
|
namespace node {
|
|
namespace contextify {
|
|
|
|
class MicrotaskQueueWrap : public BaseObject {
|
|
public:
|
|
MicrotaskQueueWrap(Environment* env, v8::Local<v8::Object> obj);
|
|
|
|
const std::shared_ptr<v8::MicrotaskQueue>& microtask_queue() const;
|
|
|
|
static void Init(Environment* env, v8::Local<v8::Object> target);
|
|
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
|
|
|
|
// This could have methods for running the microtask queue, if we ever decide
|
|
// to make that fully customizable from userland.
|
|
|
|
SET_NO_MEMORY_INFO()
|
|
SET_MEMORY_INFO_NAME(MicrotaskQueueWrap)
|
|
SET_SELF_SIZE(MicrotaskQueueWrap)
|
|
|
|
private:
|
|
std::shared_ptr<v8::MicrotaskQueue> microtask_queue_;
|
|
};
|
|
|
|
struct ContextOptions {
|
|
v8::Local<v8::String> name;
|
|
v8::Local<v8::String> origin;
|
|
v8::Local<v8::Boolean> allow_code_gen_strings;
|
|
v8::Local<v8::Boolean> allow_code_gen_wasm;
|
|
BaseObjectPtr<MicrotaskQueueWrap> microtask_queue_wrap;
|
|
};
|
|
|
|
class ContextifyContext {
|
|
public:
|
|
enum InternalFields { kSlot, kInternalFieldCount };
|
|
ContextifyContext(Environment* env,
|
|
v8::Local<v8::Object> sandbox_obj,
|
|
const ContextOptions& options);
|
|
~ContextifyContext();
|
|
static void CleanupHook(void* arg);
|
|
|
|
v8::MaybeLocal<v8::Object> CreateDataWrapper(Environment* env);
|
|
v8::MaybeLocal<v8::Context> CreateV8Context(Environment* env,
|
|
v8::Local<v8::Object> sandbox_obj,
|
|
const ContextOptions& options);
|
|
static void Init(Environment* env, v8::Local<v8::Object> target);
|
|
|
|
static ContextifyContext* ContextFromContextifiedSandbox(
|
|
Environment* env,
|
|
const v8::Local<v8::Object>& sandbox);
|
|
|
|
inline Environment* env() const {
|
|
return env_;
|
|
}
|
|
|
|
inline v8::Local<v8::Context> context() const {
|
|
return PersistentToLocal::Default(env()->isolate(), context_);
|
|
}
|
|
|
|
inline v8::Local<v8::Object> global_proxy() const {
|
|
return context()->Global();
|
|
}
|
|
|
|
inline v8::Local<v8::Object> sandbox() const {
|
|
return v8::Local<v8::Object>::Cast(
|
|
context()->GetEmbedderData(ContextEmbedderIndex::kSandboxObject));
|
|
}
|
|
|
|
inline std::shared_ptr<v8::MicrotaskQueue> microtask_queue() const {
|
|
if (!microtask_queue_wrap_) return {};
|
|
return microtask_queue_wrap_->microtask_queue();
|
|
}
|
|
|
|
|
|
template <typename T>
|
|
static ContextifyContext* Get(const v8::PropertyCallbackInfo<T>& args);
|
|
|
|
private:
|
|
static void MakeContext(const v8::FunctionCallbackInfo<v8::Value>& args);
|
|
static void IsContext(const v8::FunctionCallbackInfo<v8::Value>& args);
|
|
static void CompileFunction(
|
|
const v8::FunctionCallbackInfo<v8::Value>& args);
|
|
static void WeakCallback(
|
|
const v8::WeakCallbackInfo<ContextifyContext>& data);
|
|
static void PropertyGetterCallback(
|
|
v8::Local<v8::Name> property,
|
|
const v8::PropertyCallbackInfo<v8::Value>& args);
|
|
static void PropertySetterCallback(
|
|
v8::Local<v8::Name> property,
|
|
v8::Local<v8::Value> value,
|
|
const v8::PropertyCallbackInfo<v8::Value>& args);
|
|
static void PropertyDescriptorCallback(
|
|
v8::Local<v8::Name> property,
|
|
const v8::PropertyCallbackInfo<v8::Value>& args);
|
|
static void PropertyDefinerCallback(
|
|
v8::Local<v8::Name> property,
|
|
const v8::PropertyDescriptor& desc,
|
|
const v8::PropertyCallbackInfo<v8::Value>& args);
|
|
static void PropertyDeleterCallback(
|
|
v8::Local<v8::Name> property,
|
|
const v8::PropertyCallbackInfo<v8::Boolean>& args);
|
|
static void PropertyEnumeratorCallback(
|
|
const v8::PropertyCallbackInfo<v8::Array>& args);
|
|
static void IndexedPropertyGetterCallback(
|
|
uint32_t index,
|
|
const v8::PropertyCallbackInfo<v8::Value>& args);
|
|
static void IndexedPropertySetterCallback(
|
|
uint32_t index,
|
|
v8::Local<v8::Value> value,
|
|
const v8::PropertyCallbackInfo<v8::Value>& args);
|
|
static void IndexedPropertyDescriptorCallback(
|
|
uint32_t index,
|
|
const v8::PropertyCallbackInfo<v8::Value>& args);
|
|
static void IndexedPropertyDefinerCallback(
|
|
uint32_t index,
|
|
const v8::PropertyDescriptor& desc,
|
|
const v8::PropertyCallbackInfo<v8::Value>& args);
|
|
static void IndexedPropertyDeleterCallback(
|
|
uint32_t index,
|
|
const v8::PropertyCallbackInfo<v8::Boolean>& args);
|
|
Environment* const env_;
|
|
v8::Global<v8::Context> context_;
|
|
BaseObjectPtr<MicrotaskQueueWrap> microtask_queue_wrap_;
|
|
};
|
|
|
|
class ContextifyScript : public BaseObject {
|
|
public:
|
|
SET_NO_MEMORY_INFO()
|
|
SET_MEMORY_INFO_NAME(ContextifyScript)
|
|
SET_SELF_SIZE(ContextifyScript)
|
|
|
|
ContextifyScript(Environment* env, v8::Local<v8::Object> object);
|
|
~ContextifyScript() override;
|
|
|
|
static void Init(Environment* env, v8::Local<v8::Object> target);
|
|
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
|
|
static bool InstanceOf(Environment* env, const v8::Local<v8::Value>& args);
|
|
static void CreateCachedData(
|
|
const v8::FunctionCallbackInfo<v8::Value>& args);
|
|
static void RunInThisContext(const v8::FunctionCallbackInfo<v8::Value>& args);
|
|
static void RunInContext(const v8::FunctionCallbackInfo<v8::Value>& args);
|
|
static bool EvalMachine(Environment* env,
|
|
const int64_t timeout,
|
|
const bool display_errors,
|
|
const bool break_on_sigint,
|
|
const bool break_on_first_line,
|
|
std::shared_ptr<v8::MicrotaskQueue> microtask_queue,
|
|
const v8::FunctionCallbackInfo<v8::Value>& args);
|
|
|
|
inline uint32_t id() { return id_; }
|
|
|
|
private:
|
|
v8::Global<v8::UnboundScript> script_;
|
|
uint32_t id_;
|
|
};
|
|
|
|
class CompiledFnEntry final : public BaseObject {
|
|
public:
|
|
SET_NO_MEMORY_INFO()
|
|
SET_MEMORY_INFO_NAME(CompiledFnEntry)
|
|
SET_SELF_SIZE(CompiledFnEntry)
|
|
|
|
CompiledFnEntry(Environment* env,
|
|
v8::Local<v8::Object> object,
|
|
uint32_t id,
|
|
v8::Local<v8::ScriptOrModule> script);
|
|
~CompiledFnEntry();
|
|
|
|
private:
|
|
uint32_t id_;
|
|
v8::Global<v8::ScriptOrModule> script_;
|
|
|
|
static void WeakCallback(const v8::WeakCallbackInfo<CompiledFnEntry>& data);
|
|
};
|
|
|
|
} // namespace contextify
|
|
} // namespace node
|
|
|
|
#endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS
|
|
|
|
#endif // SRC_NODE_CONTEXTIFY_H_
|