Skip to content
Closed
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Revert "contextify: cleanup weak ref for sandbox"
This reverts commit f7224ca.
  • Loading branch information
cjihrig committed Mar 18, 2016
commit 7bb52161ed3777e51ddc808cb2f20456937add3f
80 changes: 52 additions & 28 deletions src/node_contextify.cc
Original file line number Diff line number Diff line change
Expand Up @@ -50,29 +50,40 @@ using v8::WeakCallbackData;

class ContextifyContext {
protected:
// V8 reserves the first field in context objects for the debugger. We use the
// second field to hold a reference to the sandbox object.
enum { kSandboxObjectIndex = 1 };
enum Kind {
kSandbox,
kContext
};

Environment* const env_;
Persistent<Object> sandbox_;
Persistent<Context> context_;
int references_;

public:
explicit ContextifyContext(Environment* env, Local<Object> sandbox_obj)
: env_(env) {
Local<Context> v8_context = CreateV8Context(env, sandbox_obj);
context_.Reset(env->isolate(), v8_context);
explicit ContextifyContext(Environment* env, Local<Object> sandbox)
: env_(env),
sandbox_(env->isolate(), sandbox),
// Wait for sandbox_ and context_ to die
references_(0) {
context_.Reset(env->isolate(), CreateV8Context(env));

sandbox_.SetWeak(this, WeakCallback<Object, kSandbox>);
sandbox_.MarkIndependent();
references_++;

// Allocation failure or maximum call stack size reached
if (context_.IsEmpty())
return;
context_.SetWeak(this, WeakCallback<Context>);
context_.SetWeak(this, WeakCallback<Context, kContext>);
context_.MarkIndependent();
references_++;
}


~ContextifyContext() {
context_.Reset();
sandbox_.Reset();
}


Expand All @@ -90,11 +101,6 @@ class ContextifyContext {
return context()->Global();
}


inline Local<Object> sandbox() const {
return Local<Object>::Cast(context()->GetEmbedderData(kSandboxObjectIndex));
}

// XXX(isaacs): This function only exists because of a shortcoming of
// the V8 SetNamedPropertyHandler function.
//
Expand Down Expand Up @@ -122,14 +128,15 @@ class ContextifyContext {
Local<Context> context = PersistentToLocal(env()->isolate(), context_);
Local<Object> global =
context->Global()->GetPrototype()->ToObject(env()->isolate());
Local<Object> sandbox = PersistentToLocal(env()->isolate(), sandbox_);

Local<Function> clone_property_method;

Local<Array> names = global->GetOwnPropertyNames();
int length = names->Length();
for (int i = 0; i < length; i++) {
Local<String> key = names->Get(i)->ToString(env()->isolate());
bool has = sandbox()->HasOwnProperty(context, key).FromJust();
bool has = sandbox->HasOwnProperty(context, key).FromJust();
if (!has) {
// Could also do this like so:
//
Expand Down Expand Up @@ -161,7 +168,7 @@ class ContextifyContext {
clone_property_method = Local<Function>::Cast(script->Run());
CHECK(clone_property_method->IsFunction());
}
Local<Value> args[] = { global, key, sandbox() };
Local<Value> args[] = { global, key, sandbox };
clone_property_method->Call(global, ARRAY_SIZE(args), args);
}
}
Expand All @@ -186,13 +193,14 @@ class ContextifyContext {
}


Local<Context> CreateV8Context(Environment* env, Local<Object> sandbox_obj) {
Local<Context> CreateV8Context(Environment* env) {
EscapableHandleScope scope(env->isolate());
Local<FunctionTemplate> function_template =
FunctionTemplate::New(env->isolate());
function_template->SetHiddenPrototype(true);

function_template->SetClassName(sandbox_obj->GetConstructorName());
Local<Object> sandbox = PersistentToLocal(env->isolate(), sandbox_);
function_template->SetClassName(sandbox->GetConstructorName());

Local<ObjectTemplate> object_template =
function_template->InstanceTemplate();
Expand All @@ -209,7 +217,6 @@ class ContextifyContext {

CHECK(!ctx.IsEmpty());
ctx->SetSecurityToken(env->context()->GetSecurityToken());
ctx->SetEmbedderData(kSandboxObjectIndex, sandbox_obj);

env->AssignToContext(ctx);

Expand Down Expand Up @@ -305,11 +312,16 @@ class ContextifyContext {
}


template <class T>
template <class T, Kind kind>
static void WeakCallback(const WeakCallbackData<T, ContextifyContext>& data) {
ContextifyContext* context = data.GetParameter();
context->context_.ClearWeak();
delete context;
if (kind == kSandbox)
context->sandbox_.ClearWeak();
else
context->context_.ClearWeak();

if (--context->references_ == 0)
delete context;
}


Expand All @@ -331,23 +343,26 @@ class ContextifyContext {
static void GlobalPropertyGetterCallback(
Local<Name> property,
const PropertyCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();

ContextifyContext* ctx =
Unwrap<ContextifyContext>(args.Data().As<Object>());

// Stil initializing
if (ctx->context_.IsEmpty())
return;

Local<Object> sandbox = PersistentToLocal(isolate, ctx->sandbox_);
MaybeLocal<Value> maybe_rv =
ctx->sandbox()->GetRealNamedProperty(ctx->context(), property);
sandbox->GetRealNamedProperty(ctx->context(), property);
if (maybe_rv.IsEmpty()) {
maybe_rv =
ctx->global_proxy()->GetRealNamedProperty(ctx->context(), property);
}

Local<Value> rv;
if (maybe_rv.ToLocal(&rv)) {
if (rv == ctx->sandbox())
if (rv == ctx->sandbox_)
rv = ctx->global_proxy();

args.GetReturnValue().Set(rv);
Expand All @@ -359,30 +374,34 @@ class ContextifyContext {
Local<Name> property,
Local<Value> value,
const PropertyCallbackInfo<Value>& args) {
Isolate* isolate = args.GetIsolate();

ContextifyContext* ctx =
Unwrap<ContextifyContext>(args.Data().As<Object>());

// Stil initializing
if (ctx->context_.IsEmpty())
return;

ctx->sandbox()->Set(property, value);
PersistentToLocal(isolate, ctx->sandbox_)->Set(property, value);
}


static void GlobalPropertyQueryCallback(
Local<Name> property,
const PropertyCallbackInfo<Integer>& args) {
Isolate* isolate = args.GetIsolate();

ContextifyContext* ctx =
Unwrap<ContextifyContext>(args.Data().As<Object>());

// Stil initializing
if (ctx->context_.IsEmpty())
return;

Local<Object> sandbox = PersistentToLocal(isolate, ctx->sandbox_);
Maybe<PropertyAttribute> maybe_prop_attr =
ctx->sandbox()->GetRealNamedPropertyAttributes(ctx->context(),
property);
sandbox->GetRealNamedPropertyAttributes(ctx->context(), property);

if (maybe_prop_attr.IsNothing()) {
maybe_prop_attr =
Expand All @@ -400,14 +419,18 @@ class ContextifyContext {
static void GlobalPropertyDeleterCallback(
Local<Name> property,
const PropertyCallbackInfo<Boolean>& args) {
Isolate* isolate = args.GetIsolate();

ContextifyContext* ctx =
Unwrap<ContextifyContext>(args.Data().As<Object>());

// Stil initializing
if (ctx->context_.IsEmpty())
return;

Maybe<bool> success = ctx->sandbox()->Delete(ctx->context(), property);
Local<Object> sandbox = PersistentToLocal(isolate, ctx->sandbox_);

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

if (success.IsJust())
args.GetReturnValue().Set(success.FromJust());
Expand All @@ -423,7 +446,8 @@ class ContextifyContext {
if (ctx->context_.IsEmpty())
return;

args.GetReturnValue().Set(ctx->sandbox()->GetPropertyNames());
Local<Object> sandbox = PersistentToLocal(args.GetIsolate(), ctx->sandbox_);
args.GetReturnValue().Set(sandbox->GetPropertyNames());
}
};

Expand Down