react / wstein / node_modules / jest-cli / node_modules / jsdom / node_modules / contextify / src / contextify.cc
80786 views#include "node.h"1#include "node_version.h"2#include "nan.h"3#include <string>4using namespace v8;5using namespace node;67class ContextWrap;89class ContextifyContext : public ObjectWrap {10public:11Persistent<Context> context;12Persistent<Object> sandbox;13Persistent<Object> proxyGlobal;1415static Persistent<FunctionTemplate> jsTmpl;1617ContextifyContext(Local<Object> sbox) {18NanScope();19NanAssignPersistent(sandbox, sbox);20}2122~ContextifyContext() {23NanDisposePersistent(context);24NanDisposePersistent(proxyGlobal);25NanDisposePersistent(sandbox);2627// Provide a GC hint that the context has gone away. Without this call it28// does not seem that the collector will touch the context until under extreme29// stress.30NanContextDisposedNotification();31}3233// We override ObjectWrap::Wrap so that we can create our context after34// we have a reference to our "host" JavaScript object. If we try to use35// handle_ in the ContextifyContext constructor, it will be empty since it's36// set in ObjectWrap::Wrap.37void Wrap(Handle<Object> handle);3839static void Init(Handle<Object> target) {40NanScope();4142Local<FunctionTemplate> ljsTmpl = NanNew<FunctionTemplate>(New);43ljsTmpl->InstanceTemplate()->SetInternalFieldCount(1);44ljsTmpl->SetClassName(NanNew("ContextifyContext"));45NODE_SET_PROTOTYPE_METHOD(ljsTmpl, "run", ContextifyContext::Run);46NODE_SET_PROTOTYPE_METHOD(ljsTmpl, "getGlobal", ContextifyContext::GetGlobal);4748NanAssignPersistent(jsTmpl, ljsTmpl);49target->Set(NanNew("ContextifyContext"), ljsTmpl->GetFunction());50}5152static NAN_METHOD(New) {53NanScope();5455if (args.Length() < 1) {56NanThrowError("Wrong number of arguments passed to ContextifyContext constructor");57NanReturnUndefined();58}5960if (!args[0]->IsObject()) {61NanThrowTypeError("Argument to ContextifyContext constructor must be an object.");62NanReturnUndefined();63}6465ContextifyContext* ctx = new ContextifyContext(args[0]->ToObject());66ctx->Wrap(args.This());67NanReturnValue(args.This());68}6970static NAN_METHOD(Run) {71NanScope();72if (args.Length() == 0) {73NanThrowError("Must supply at least 1 argument to run");74}75if (!args[0]->IsString()) {76NanThrowTypeError("First argument to run must be a String.");77NanReturnUndefined();78}79ContextifyContext* ctx = ObjectWrap::Unwrap<ContextifyContext>(args.This());80Local<Context> lcontext = NanNew(ctx->context);81lcontext->Enter();82Local<String> code = args[0]->ToString();8384TryCatch trycatch;85Local<NanBoundScript> script;8687if (args.Length() > 1 && args[1]->IsString()) {88ScriptOrigin origin(args[1]->ToString());89script = NanCompileScript(code, origin);90} else {91script = NanCompileScript(code);92}9394if (script.IsEmpty()) {95lcontext->Exit();96NanReturnValue(trycatch.ReThrow());97}9899Handle<Value> result = NanRunScript(script);100lcontext->Exit();101102if (result.IsEmpty()) {103NanReturnValue(trycatch.ReThrow());104}105106NanReturnValue(result);107}108109static bool InstanceOf(Handle<Value> value) {110return NanHasInstance(jsTmpl, value);111}112113static NAN_METHOD(GetGlobal) {114NanScope();115ContextifyContext* ctx = ObjectWrap::Unwrap<ContextifyContext>(args.This());116NanReturnValue(NanNew(ctx->proxyGlobal));117}118};119120// This is an object that just keeps an internal pointer to this121// ContextifyContext. It's passed to the NamedPropertyHandler. If we122// pass the main JavaScript context object we're embedded in, then the123// NamedPropertyHandler will store a reference to it forever and keep it124// from getting gc'd.125class ContextWrap : public ObjectWrap {126public:127static void Init(void) {128NanScope();129Local<FunctionTemplate> tmpl = NanNew<FunctionTemplate>();130tmpl->InstanceTemplate()->SetInternalFieldCount(1);131NanAssignPersistent(functionTemplate, tmpl);132NanAssignPersistent(constructor, tmpl->GetFunction());133}134135static Local<Context> createV8Context(Handle<Object> jsContextify) {136NanEscapableScope();137Local<Object> wrapper = NanNew(constructor)->NewInstance();138139ContextWrap *contextWrapper = new ContextWrap();140contextWrapper->Wrap(wrapper);141142Local<Object> obj = NanNew(jsContextify);143NanMakeWeakPersistent(obj, contextWrapper, &weakCallback);144contextWrapper->ctx = ObjectWrap::Unwrap<ContextifyContext>(jsContextify);145146Local<FunctionTemplate> ftmpl = NanNew<FunctionTemplate>();147ftmpl->SetHiddenPrototype(true);148ftmpl->SetClassName(NanNew(contextWrapper->ctx->sandbox)->GetConstructorName());149Local<ObjectTemplate> otmpl = ftmpl->InstanceTemplate();150otmpl->SetNamedPropertyHandler(GlobalPropertyGetter,151GlobalPropertySetter,152GlobalPropertyQuery,153GlobalPropertyDeleter,154GlobalPropertyEnumerator,155wrapper);156otmpl->SetAccessCheckCallbacks(GlobalPropertyNamedAccessCheck,157GlobalPropertyIndexedAccessCheck);158return NanEscapeScope(NanNew<Context>(159static_cast<ExtensionConfiguration*>(NULL), otmpl));160}161162private:163ContextWrap() :ctx(NULL) {}164165~ContextWrap() {166}167168static bool GlobalPropertyNamedAccessCheck(Local<Object> host,169Local<Value> key,170AccessType type,171Local<Value> data) {172return true;173}174175static bool GlobalPropertyIndexedAccessCheck(Local<Object> host,176uint32_t key,177AccessType type,178Local<Value> data) {179return true;180}181182static NAN_PROPERTY_GETTER(GlobalPropertyGetter) {183NanScope();184Local<Object> data = args.Data()->ToObject();185ContextifyContext* ctx = ObjectWrap::Unwrap<ContextWrap>(data)->ctx;186if (!ctx)187NanReturnUndefined();188Local<Value> rv = NanNew(ctx->sandbox)->GetRealNamedProperty(property);189if (rv.IsEmpty()) {190rv = NanNew(ctx->proxyGlobal)->GetRealNamedProperty(property);191}192NanReturnValue(rv);193}194195static NAN_PROPERTY_SETTER(GlobalPropertySetter) {196NanScope();197Local<Object> data = args.Data()->ToObject();198ContextifyContext* ctx = ObjectWrap::Unwrap<ContextWrap>(data)->ctx;199if (!ctx)200NanReturnUndefined();201NanNew(ctx->sandbox)->Set(property, value);202NanReturnValue(value);203}204205static NAN_PROPERTY_QUERY(GlobalPropertyQuery) {206NanScope();207Local<Object> data = args.Data()->ToObject();208ContextifyContext* ctx = ObjectWrap::Unwrap<ContextWrap>(data)->ctx;209if (!ctx)210NanReturnValue(NanNew<Integer>(None));211if (!NanNew(ctx->sandbox)->GetRealNamedProperty(property).IsEmpty() ||212!NanNew(ctx->proxyGlobal)->GetRealNamedProperty(property).IsEmpty()) {213NanReturnValue(NanNew<Integer>(None));214} else {215NanReturnValue(Handle<Integer>());216}217}218219static NAN_PROPERTY_DELETER(GlobalPropertyDeleter) {220NanScope();221Local<Object> data = args.Data()->ToObject();222ContextifyContext* ctx = ObjectWrap::Unwrap<ContextWrap>(data)->ctx;223if (!ctx)224NanReturnValue(NanNew<Boolean>(false));225bool success = NanNew(ctx->sandbox)->Delete(property);226NanReturnValue(NanNew<Boolean>(success));227}228229static NAN_PROPERTY_ENUMERATOR(GlobalPropertyEnumerator) {230NanScope();231Local<Object> data = args.Data()->ToObject();232ContextifyContext* ctx = ObjectWrap::Unwrap<ContextWrap>(data)->ctx;233if (!ctx) {234Local<Array> blank = Array::New(0);235NanReturnValue(blank);236}237NanReturnValue(NanNew(ctx->sandbox)->GetPropertyNames());238}239240NAN_WEAK_CALLBACK(weakCallback) {241ContextWrap *self = data.GetParameter();242self->ctx = NULL;243}244245static Persistent<FunctionTemplate> functionTemplate;246static Persistent<Function> constructor;247ContextifyContext *ctx;248};249250Persistent<FunctionTemplate> ContextWrap::functionTemplate;251Persistent<Function> ContextWrap::constructor;252253void ContextifyContext::Wrap(Handle<Object> handle) {254ObjectWrap::Wrap(handle);255Local<Context> lcontext = ContextWrap::createV8Context(handle);256NanAssignPersistent(context, lcontext);257NanAssignPersistent(proxyGlobal, lcontext->Global());258}259260class ContextifyScript : public ObjectWrap {261public:262static Persistent<FunctionTemplate> scriptTmpl;263Persistent<NanUnboundScript> script;264265static void Init(Handle<Object> target) {266NanScope();267Local<FunctionTemplate> lscriptTmpl = NanNew<FunctionTemplate>(New);268lscriptTmpl->InstanceTemplate()->SetInternalFieldCount(1);269lscriptTmpl->SetClassName(NanNew("ContextifyScript"));270271NODE_SET_PROTOTYPE_METHOD(lscriptTmpl, "runInContext", RunInContext);272273NanAssignPersistent(scriptTmpl, lscriptTmpl);274target->Set(NanNew("ContextifyScript"),275lscriptTmpl->GetFunction());276}277static NAN_METHOD(New) {278NanScope();279ContextifyScript *contextify_script = new ContextifyScript();280contextify_script->Wrap(args.Holder());281282if (args.Length() < 1) {283NanThrowTypeError("needs at least 'code' argument.");284NanReturnUndefined();285}286287Local<String> code = args[0]->ToString();288Local<String> filename = args.Length() > 1289? args[1]->ToString()290: NanNew<String>("ContextifyScript.<anonymous>");291292Handle<Context> context = NanGetCurrentContext();293Context::Scope context_scope(context);294295// Catch errors296TryCatch trycatch;297298ScriptOrigin origin(filename);299Handle<NanUnboundScript> v8_script = NanNew<NanUnboundScript>(code, origin);300301if (v8_script.IsEmpty()) {302NanReturnValue(trycatch.ReThrow());303}304305NanAssignPersistent(contextify_script->script, v8_script);306307NanReturnValue(args.This());308}309310static NAN_METHOD(RunInContext) {311NanScope();312if (args.Length() == 0) {313NanThrowError("Must supply at least 1 argument to runInContext");314NanReturnUndefined();315}316if (!ContextifyContext::InstanceOf(args[0]->ToObject())) {317NanThrowTypeError("First argument must be a ContextifyContext.");318NanReturnUndefined();319}320321ContextifyContext* ctx = ObjectWrap::Unwrap<ContextifyContext>(args[0]->ToObject());322Local<Context> lcontext = NanNew(ctx->context);323lcontext->Enter();324ContextifyScript* wrapped_script = ObjectWrap::Unwrap<ContextifyScript>(args.This());325Local<NanUnboundScript> script = NanNew(wrapped_script->script);326TryCatch trycatch;327if (script.IsEmpty()) {328lcontext->Exit();329NanReturnValue(trycatch.ReThrow());330}331Handle<Value> result = NanRunScript(script);332lcontext->Exit();333if (result.IsEmpty()) {334NanReturnValue(trycatch.ReThrow());335}336NanReturnValue(result);337}338339~ContextifyScript() {340NanDisposePersistent(script);341}342};343344Persistent<FunctionTemplate> ContextifyContext::jsTmpl;345Persistent<FunctionTemplate> ContextifyScript::scriptTmpl;346347extern "C" {348static void init(Handle<Object> target) {349ContextifyContext::Init(target);350ContextifyScript::Init(target);351ContextWrap::Init();352}353NODE_MODULE(contextify, init)354};355356357