Skip to content
This repository has been archived by the owner on Apr 22, 2023. It is now read-only.

Getters/Setters in VM's Context #1673

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
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
59 changes: 37 additions & 22 deletions src/node_script.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,11 @@ using v8::TryCatch;
using v8::String;
using v8::Exception;
using v8::Local;
using v8::Null;
using v8::Array;
using v8::Persistent;
using v8::Integer;
using v8::Function;
using v8::FunctionTemplate;


Expand Down Expand Up @@ -98,6 +100,38 @@ class WrappedScript : ObjectWrap {
};


Persistent<Function> cloneObjectMethod;

void CloneObject(Handle<Object> recv,
Handle<Value> source, Handle<Value> target) {
HandleScope scope;

Handle<Value> args[] = {source, target};

// Init
if (cloneObjectMethod.IsEmpty()) {
Local<Function> cloneObjectMethod_ = Local<Function>::Cast(
Script::Compile(String::New(
"(function(source, target) {\n\
Object.getOwnPropertyNames(source).forEach(function(key) {\n\
try {\n\
var desc = Object.getOwnPropertyDescriptor(source, key);\n\
if (desc.value === source) desc.value = target;\n\
Object.defineProperty(target, key, desc);\n\
} catch (e) {\n\
// Catch sealed properties errors\n\
}\n\
});\n\
})"
), String::New("binding:script"))->Run()
);
cloneObjectMethod = Persistent<Function>::New(cloneObjectMethod_);
}

cloneObjectMethod->Call(recv, 2, args);
}


void WrappedContext::Initialize(Handle<Object> target) {
HandleScope scope;

Expand Down Expand Up @@ -225,14 +259,8 @@ Handle<Value> WrappedScript::CreateContext(const Arguments& args) {

if (args.Length() > 0) {
Local<Object> sandbox = args[0]->ToObject();
Local<Array> keys = sandbox->GetPropertyNames();

for (uint32_t i = 0; i < keys->Length(); i++) {
Handle<String> key = keys->Get(Integer::New(i))->ToString();
Handle<Value> value = sandbox->Get(key);
if(value == sandbox) { value = context; }
context->Set(key, value);
}
CloneObject(args.This(), sandbox, context);
}


Expand Down Expand Up @@ -343,14 +371,7 @@ Handle<Value> WrappedScript::EvalMachine(const Arguments& args) {

// Copy everything from the passed in sandbox (either the persistent
// context for runInContext(), or the sandbox arg to runInNewContext()).
keys = sandbox->GetPropertyNames();

for (i = 0; i < keys->Length(); i++) {
Handle<String> key = keys->Get(Integer::New(i))->ToString();
Handle<Value> value = sandbox->Get(key);
if (value == sandbox) { value = context->Global(); }
context->Global()->Set(key, value);
}
CloneObject(args.This(), sandbox, context->Global()->GetPrototype());
}

// Catch errors
Expand Down Expand Up @@ -408,13 +429,7 @@ Handle<Value> WrappedScript::EvalMachine(const Arguments& args) {

if (context_flag == userContext || context_flag == newContext) {
// success! copy changes back onto the sandbox object.
keys = context->Global()->GetPropertyNames();
for (i = 0; i < keys->Length(); i++) {
Handle<String> key = keys->Get(Integer::New(i))->ToString();
Handle<Value> value = context->Global()->Get(key);
if (value == context->Global()) { value = sandbox; }
sandbox->Set(key, value);
}
CloneObject(args.This(), context->Global()->GetPrototype(), sandbox);
}

if (context_flag == newContext) {
Expand Down
26 changes: 26 additions & 0 deletions test/simple/test-vm-create-context-accessors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
var common = require('../common');
var assert = require('assert');
var vm = require('vm');

var ctx = {};

Object.defineProperty(ctx, 'getter', {
get: function() {
return 'ok';
}
});

var val;
Object.defineProperty(ctx, 'setter', {
set: function(_val) {
val = _val;
},
get: function() {
return 'ok=' + val;
}
});

ctx = vm.createContext(ctx);

var result = vm.runInContext('setter = "test";[getter,setter]', ctx);
assert.deepEqual(result, ['ok', 'ok=test']);