Skip to content

Commit

Permalink
src: migrate to new V8 interceptors API
Browse files Browse the repository at this point in the history
Refs: v8#180
PR-URL: nodejs#52745
Reviewed-By: Yagiz Nizipli <yagiz.nizipli@sentry.io>
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
  • Loading branch information
targos authored and sophonieb committed Jun 20, 2024
1 parent 5168f49 commit b1a3dd9
Show file tree
Hide file tree
Showing 4 changed files with 152 additions and 103 deletions.
145 changes: 91 additions & 54 deletions src/node_contextify.cc
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ using v8::FunctionTemplate;
using v8::HandleScope;
using v8::IndexedPropertyHandlerConfiguration;
using v8::Int32;
using v8::Intercepted;
using v8::Isolate;
using v8::Just;
using v8::Local;
Expand Down Expand Up @@ -458,14 +459,15 @@ bool ContextifyContext::IsStillInitializing(const ContextifyContext* ctx) {
}

// static
void ContextifyContext::PropertyGetterCallback(
Local<Name> property,
const PropertyCallbackInfo<Value>& args) {
Intercepted ContextifyContext::PropertyGetterCallback(
Local<Name> property, const PropertyCallbackInfo<Value>& args) {
Environment* env = Environment::GetCurrent(args);
ContextifyContext* ctx = ContextifyContext::Get(args);

// Still initializing
if (IsStillInitializing(ctx)) return;
if (IsStillInitializing(ctx)) {
return Intercepted::kNo;
}

Local<Context> context = ctx->context();
Local<Object> sandbox = ctx->sandbox();
Expand All @@ -487,18 +489,22 @@ void ContextifyContext::PropertyGetterCallback(
rv = ctx->global_proxy();

args.GetReturnValue().Set(rv);
return Intercepted::kYes;
}
return Intercepted::kNo;
}

// static
void ContextifyContext::PropertySetterCallback(
Intercepted ContextifyContext::PropertySetterCallback(
Local<Name> property,
Local<Value> value,
const PropertyCallbackInfo<Value>& args) {
const PropertyCallbackInfo<void>& args) {
ContextifyContext* ctx = ContextifyContext::Get(args);

// Still initializing
if (IsStillInitializing(ctx)) return;
if (IsStillInitializing(ctx)) {
return Intercepted::kNo;
}

Local<Context> context = ctx->context();
PropertyAttribute attributes = PropertyAttribute::None;
Expand All @@ -516,8 +522,9 @@ void ContextifyContext::PropertySetterCallback(
(static_cast<int>(attributes) &
static_cast<int>(PropertyAttribute::ReadOnly));

if (read_only)
return;
if (read_only) {
return Intercepted::kNo;
}

// true for x = 5
// false for this.x = 5
Expand All @@ -536,11 +543,16 @@ void ContextifyContext::PropertySetterCallback(

bool is_declared = is_declared_on_global_proxy || is_declared_on_sandbox;
if (!is_declared && args.ShouldThrowOnError() && is_contextual_store &&
!is_function)
return;
!is_function) {
return Intercepted::kNo;
}

if (!is_declared && property->IsSymbol()) return;
if (ctx->sandbox()->Set(context, property, value).IsNothing()) return;
if (!is_declared && property->IsSymbol()) {
return Intercepted::kNo;
}
if (ctx->sandbox()->Set(context, property, value).IsNothing()) {
return Intercepted::kNo;
}

Local<Value> desc;
if (is_declared_on_sandbox &&
Expand All @@ -554,19 +566,23 @@ void ContextifyContext::PropertySetterCallback(
// We have to specify the return value for any contextual or get/set
// property
if (desc_obj->HasOwnProperty(context, env->get_string()).FromMaybe(false) ||
desc_obj->HasOwnProperty(context, env->set_string()).FromMaybe(false))
desc_obj->HasOwnProperty(context, env->set_string()).FromMaybe(false)) {
args.GetReturnValue().Set(value);
return Intercepted::kYes;
}
}
return Intercepted::kNo;
}

// static
void ContextifyContext::PropertyDescriptorCallback(
Local<Name> property,
const PropertyCallbackInfo<Value>& args) {
Intercepted ContextifyContext::PropertyDescriptorCallback(
Local<Name> property, const PropertyCallbackInfo<Value>& args) {
ContextifyContext* ctx = ContextifyContext::Get(args);

// Still initializing
if (IsStillInitializing(ctx)) return;
if (IsStillInitializing(ctx)) {
return Intercepted::kNo;
}

Local<Context> context = ctx->context();

Expand All @@ -576,19 +592,23 @@ void ContextifyContext::PropertyDescriptorCallback(
Local<Value> desc;
if (sandbox->GetOwnPropertyDescriptor(context, property).ToLocal(&desc)) {
args.GetReturnValue().Set(desc);
return Intercepted::kYes;
}
}
return Intercepted::kNo;
}

// static
void ContextifyContext::PropertyDefinerCallback(
Intercepted ContextifyContext::PropertyDefinerCallback(
Local<Name> property,
const PropertyDescriptor& desc,
const PropertyCallbackInfo<Value>& args) {
const PropertyCallbackInfo<void>& args) {
ContextifyContext* ctx = ContextifyContext::Get(args);

// Still initializing
if (IsStillInitializing(ctx)) return;
if (IsStillInitializing(ctx)) {
return Intercepted::kNo;
}

Local<Context> context = ctx->context();
Isolate* isolate = context->GetIsolate();
Expand All @@ -607,7 +627,7 @@ void ContextifyContext::PropertyDefinerCallback(
// If the property is set on the global as neither writable nor
// configurable, don't change it on the global or sandbox.
if (is_declared && read_only && dont_delete) {
return;
return Intercepted::kNo;
}

Local<Object> sandbox = ctx->sandbox();
Expand All @@ -630,6 +650,9 @@ void ContextifyContext::PropertyDefinerCallback(
desc.has_set() ? desc.set() : Undefined(isolate).As<Value>());

define_prop_on_sandbox(&desc_for_sandbox);
// TODO(https://github.com/nodejs/node/issues/52634): this should return
// kYes to behave according to the expected semantics.
return Intercepted::kNo;
} else {
Local<Value> value =
desc.has_value() ? desc.value() : Undefined(isolate).As<Value>();
Expand All @@ -641,26 +664,33 @@ void ContextifyContext::PropertyDefinerCallback(
PropertyDescriptor desc_for_sandbox(value);
define_prop_on_sandbox(&desc_for_sandbox);
}
// TODO(https://github.com/nodejs/node/issues/52634): this should return
// kYes to behave according to the expected semantics.
return Intercepted::kNo;
}
return Intercepted::kNo;
}

// static
void ContextifyContext::PropertyDeleterCallback(
Local<Name> property,
const PropertyCallbackInfo<Boolean>& args) {
Intercepted ContextifyContext::PropertyDeleterCallback(
Local<Name> property, const PropertyCallbackInfo<Boolean>& args) {
ContextifyContext* ctx = ContextifyContext::Get(args);

// Still initializing
if (IsStillInitializing(ctx)) return;
if (IsStillInitializing(ctx)) {
return Intercepted::kNo;
}

Maybe<bool> success = ctx->sandbox()->Delete(ctx->context(), property);

if (success.FromMaybe(false))
return;
if (success.FromMaybe(false)) {
return Intercepted::kNo;
}

// Delete failed on the sandbox, intercept and do not delete on
// the global object.
args.GetReturnValue().Set(false);
return Intercepted::kYes;
}

// static
Expand All @@ -680,76 +710,83 @@ void ContextifyContext::PropertyEnumeratorCallback(
}

// static
void ContextifyContext::IndexedPropertyGetterCallback(
uint32_t index,
const PropertyCallbackInfo<Value>& args) {
Intercepted ContextifyContext::IndexedPropertyGetterCallback(
uint32_t index, const PropertyCallbackInfo<Value>& args) {
ContextifyContext* ctx = ContextifyContext::Get(args);

// Still initializing
if (IsStillInitializing(ctx)) return;
if (IsStillInitializing(ctx)) {
return Intercepted::kNo;
}

ContextifyContext::PropertyGetterCallback(
return ContextifyContext::PropertyGetterCallback(
Uint32ToName(ctx->context(), index), args);
}


void ContextifyContext::IndexedPropertySetterCallback(
Intercepted ContextifyContext::IndexedPropertySetterCallback(
uint32_t index,
Local<Value> value,
const PropertyCallbackInfo<Value>& args) {
const PropertyCallbackInfo<void>& args) {
ContextifyContext* ctx = ContextifyContext::Get(args);

// Still initializing
if (IsStillInitializing(ctx)) return;
if (IsStillInitializing(ctx)) {
return Intercepted::kNo;
}

ContextifyContext::PropertySetterCallback(
return ContextifyContext::PropertySetterCallback(
Uint32ToName(ctx->context(), index), value, args);
}

// static
void ContextifyContext::IndexedPropertyDescriptorCallback(
uint32_t index,
const PropertyCallbackInfo<Value>& args) {
Intercepted ContextifyContext::IndexedPropertyDescriptorCallback(
uint32_t index, const PropertyCallbackInfo<Value>& args) {
ContextifyContext* ctx = ContextifyContext::Get(args);

// Still initializing
if (IsStillInitializing(ctx)) return;
if (IsStillInitializing(ctx)) {
return Intercepted::kNo;
}

ContextifyContext::PropertyDescriptorCallback(
return ContextifyContext::PropertyDescriptorCallback(
Uint32ToName(ctx->context(), index), args);
}


void ContextifyContext::IndexedPropertyDefinerCallback(
Intercepted ContextifyContext::IndexedPropertyDefinerCallback(
uint32_t index,
const PropertyDescriptor& desc,
const PropertyCallbackInfo<Value>& args) {
const PropertyCallbackInfo<void>& args) {
ContextifyContext* ctx = ContextifyContext::Get(args);

// Still initializing
if (IsStillInitializing(ctx)) return;
if (IsStillInitializing(ctx)) {
return Intercepted::kNo;
}

ContextifyContext::PropertyDefinerCallback(
return ContextifyContext::PropertyDefinerCallback(
Uint32ToName(ctx->context(), index), desc, args);
}

// static
void ContextifyContext::IndexedPropertyDeleterCallback(
uint32_t index,
const PropertyCallbackInfo<Boolean>& args) {
Intercepted ContextifyContext::IndexedPropertyDeleterCallback(
uint32_t index, const PropertyCallbackInfo<Boolean>& args) {
ContextifyContext* ctx = ContextifyContext::Get(args);

// Still initializing
if (IsStillInitializing(ctx)) return;
if (IsStillInitializing(ctx)) {
return Intercepted::kNo;
}

Maybe<bool> success = ctx->sandbox()->Delete(ctx->context(), index);

if (success.FromMaybe(false))
return;
if (success.FromMaybe(false)) {
return Intercepted::kNo;
}

// Delete failed on the sandbox, intercept and do not delete on
// the global object.
args.GetReturnValue().Set(false);
return Intercepted::kYes;
}

void ContextifyScript::CreatePerIsolateProperties(
Expand Down
37 changes: 17 additions & 20 deletions src/node_contextify.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,42 +96,39 @@ class ContextifyContext : public BaseObject {
const errors::TryCatchScope& try_catch);
static void WeakCallback(
const v8::WeakCallbackInfo<ContextifyContext>& data);
static void PropertyGetterCallback(
static v8::Intercepted PropertyGetterCallback(
v8::Local<v8::Name> property,
const v8::PropertyCallbackInfo<v8::Value>& args);
static void PropertySetterCallback(
static v8::Intercepted PropertySetterCallback(
v8::Local<v8::Name> property,
v8::Local<v8::Value> value,
const v8::PropertyCallbackInfo<v8::Value>& args);
static void PropertyDescriptorCallback(
const v8::PropertyCallbackInfo<void>& args);
static v8::Intercepted PropertyDescriptorCallback(
v8::Local<v8::Name> property,
const v8::PropertyCallbackInfo<v8::Value>& args);
static void PropertyDefinerCallback(
static v8::Intercepted PropertyDefinerCallback(
v8::Local<v8::Name> property,
const v8::PropertyDescriptor& desc,
const v8::PropertyCallbackInfo<v8::Value>& args);
static void PropertyDeleterCallback(
const v8::PropertyCallbackInfo<void>& args);
static v8::Intercepted 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(
static v8::Intercepted IndexedPropertyGetterCallback(
uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& args);
static v8::Intercepted 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(
const v8::PropertyCallbackInfo<void>& args);
static v8::Intercepted IndexedPropertyDescriptorCallback(
uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& args);
static v8::Intercepted 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);
const v8::PropertyCallbackInfo<void>& args);
static v8::Intercepted IndexedPropertyDeleterCallback(
uint32_t index, const v8::PropertyCallbackInfo<v8::Boolean>& args);

v8::Global<v8::Context> context_;
std::unique_ptr<v8::MicrotaskQueue> microtask_queue_;
Expand Down
Loading

0 comments on commit b1a3dd9

Please sign in to comment.