diff --git a/Changes b/Changes index 0ec1b8bb..7d64c792 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,11 @@ Revision history for plv8 +x.x.x 2015-xx-xx + - Adaptions for current V8 version, e.g. 4.1.0.x + (see http://strongloop.com/strongblog/node-js-v0-12-c-apis-breaking/ + for an overview of the V8 changes which break existing code bases) + - GUC plv8.v8_flags for V8 engine initialization flags + 1.4.4 2015-05-26 - Add jsonb type coercion in function boundary. - Fix crash related to FLEXIBLE_ARRAY_MEMBER changes. diff --git a/Makefile b/Makefile index 4db8669c..2d80c8b8 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ # Makefile for plv8 # # @param DISABLE_DIALECT if defined, not build dialects (i.e. plcoffee, etc) -# @param ENABLE_DEBUGGER_SUPPORT enables v8 deubbger agent +# @param ENABLE_DEBUGGER_SUPPORT enables v8 debugger agent # # There are two ways to build plv8. # 1. Dynamic link to v8 (default) @@ -37,7 +37,7 @@ DATA += plcoffee.control plcoffee--$(PLV8_VERSION).sql \ endif DATA_built = plv8.sql REGRESS = init-extension plv8 inline json startup_pre startup varparam json_conv \ - jsonb_conv window + jsonb_conv window guc es6 ifndef DISABLE_DIALECT REGRESS += dialect endif @@ -52,11 +52,16 @@ endif ifdef ENABLE_DEBUGGER_SUPPORT OPT_ENABLE_DEBUGGER_SUPPORT = -DENABLE_DEBUGGER_SUPPORT endif -OPTFLAGS = -O2 -DV8_USE_UNSAFE_HANDLES + +# for older g++ (e.g. 4.6.x), which do not support c++11 +#OPTFLAGS = -O2 -std=gnu++0x -fno-rtti + +OPTFLAGS = -O2 -std=c++11 -fno-rtti + CCFLAGS = -Wall $(OPTFLAGS) $(OPT_ENABLE_DEBUGGER_SUPPORT) ifdef V8_SRCDIR -override CPPFLAGS += -I$(V8_SRCDIR)/include +override CPPFLAGS += -I$(V8_SRCDIR) -I$(V8_SRCDIR)/include endif all: diff --git a/Makefile.v8 b/Makefile.v8 index 5744c111..44d5035c 100644 --- a/Makefile.v8 +++ b/Makefile.v8 @@ -7,11 +7,14 @@ # structure in v8 which may be different from version to another, but user # can specify the v8 version by AUTOV8_VERSION, too. #-----------------------------------------------------------------------------# -AUTOV8_VERSION = 3.14.5 -AUTOV8_DIR = build/v8-$(AUTOV8_VERSION) -AUTOV8_OUT = build/v8-$(AUTOV8_VERSION)/out/native +AUTOV8_VERSION = 4.3.66 +AUTOV8_DIR = build/v8-git-mirror-$(AUTOV8_VERSION) +AUTOV8_OUT = build/v8-git-mirror-$(AUTOV8_VERSION)/out/native +AUTOV8_DEPOT_TOOLS = build/depot_tools AUTOV8_LIB = $(AUTOV8_OUT)/libv8_snapshot.a -AUTOV8_STATIC_LIBS = libv8_base.a libv8_snapshot.a +AUTOV8_STATIC_LIBS = libv8_base.a libv8_snapshot.a libv8_libplatform.a libv8_libbase.a libicui18n.a libicuuc.a libicudata.a + +export PATH := $(abspath $(AUTOV8_DEPOT_TOOLS)):$(PATH) SHLIB_LINK += $(addprefix $(AUTOV8_OUT)/, $(AUTOV8_STATIC_LIBS)) @@ -20,23 +23,40 @@ all: $(AUTOV8_LIB) # For some reason, this solves parallel make dependency. plv8_config.h: $(AUTOV8_LIB) -$(AUTOV8_DIR): +$(AUTOV8_DEPOT_TOOLS): mkdir -p build - curl -L 'https://github.com/v8/v8/archive/$(AUTOV8_VERSION).tar.gz' \ - | tar zxf - -C build + cd build; git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git + +$(AUTOV8_DIR): $(AUTOV8_DEPOT_TOOLS) + cd build; fetch v8; cd v8; git checkout $(AUTOV8_VERSION); gclient sync + mv build/v8 $(AUTOV8_DIR) $(AUTOV8_LIB): $(AUTOV8_DIR) - env CXXFLAGS=-fPIC $(MAKE) -C build/v8-$(AUTOV8_VERSION) dependencies - env CXXFLAGS=-fPIC $(MAKE) -C build/v8-$(AUTOV8_VERSION) native + env CXXFLAGS=-fPIC CFLAGS=-fPIC $(MAKE) -C build/v8-git-mirror-$(AUTOV8_VERSION) native test -f $(AUTOV8_OUT)/libv8_base.a || \ ln -s $(abspath $(AUTOV8_OUT)/obj.target/tools/gyp/libv8_base.a) \ $(AUTOV8_OUT)/libv8_base.a test -f $(AUTOV8_OUT)/libv8_snapshot.a || \ ln -s $(abspath $(AUTOV8_OUT)/obj.target/tools/gyp/libv8_snapshot.a) \ $(AUTOV8_OUT)/libv8_snapshot.a + test -f $(AUTOV8_OUT)/libv8_libbase.a || \ + ln -s $(abspath $(AUTOV8_OUT)/obj.target/tools/gyp/libv8_libbase.a) \ + $(AUTOV8_OUT)/libv8_libbase.a + test -f $(AUTOV8_OUT)/libv8_libplatform.a || \ + ln -s $(abspath $(AUTOV8_OUT)/obj.target/tools/gyp/libv8_libplatform.a) \ + $(AUTOV8_OUT)/libv8_libplatform.a + test -f $(AUTOV8_OUT)/libicui18n.a || \ + ln -s $(abspath $(AUTOV8_OUT)/obj.target/third_party/icu/libicui18n.a) \ + $(AUTOV8_OUT)/libicui18n.a + test -f $(AUTOV8_OUT)/libicuuc.a || \ + ln -s $(abspath $(AUTOV8_OUT)/obj.target/third_party/icu/libicuuc.a) \ + $(AUTOV8_OUT)/libicuuc.a + test -f $(AUTOV8_OUT)/libicudata.a || \ + ln -s $(abspath $(AUTOV8_OUT)/obj.target/third_party/icu/libicudata.a) \ + $(AUTOV8_OUT)/libicudata.a include Makefile -CCFLAGS += -I$(AUTOV8_DIR)/include +CCFLAGS += -I$(AUTOV8_DIR)/include -I$(AUTOV8_DIR) # We're gonna build static link. Rip it out after include Makefile SHLIB_LINK := $(filter-out -lv8, $(SHLIB_LINK)) diff --git a/README.md b/README.md index 79b38f59..a81f076b 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,9 @@ REQUIREMENT plv8 is tested with: -- PG: version 8.4, 9.0, 9.1, 9.2 and 9.3dev (maybe older are allowed) -- V8: version 3.14.5 -- g++: version 4.5.1 +- PG: version 9.4 (maybe older are allowed) +- V8: version 4.3.66 +- g++: version 4.8.2 It is also known to work with some older versions of gcc and v8. diff --git a/doc/plv8.md b/doc/plv8.md index 90d16ec4..ba4ee225 100644 --- a/doc/plv8.md +++ b/doc/plv8.md @@ -413,6 +413,22 @@ and return the value. An example for these types are as follows. 15 (1 row) +ES6 Language Features +--------------------- + +PL/v8 enables all shipping feature of the used V8 version. So with V8 4.1+ +many ES6 features, like block scoping, collections, generators and string +templates, are enabled by default. + +Additional features can be enabled by setting the GUC plv8.v8_flags +(e.g. "SET plv8.v8_flags = '--es_staging';"). + +These flags are honoured once per user session when the V8 runtime is +initialized. Compared to dialects (see below), which can be set on a +per function base, the V8 flags cannot be changed once the runtime is +initialized. So normally this setting should rather be set per database, +and not per session. + Remote debugger --------------- @@ -471,5 +487,5 @@ are supported. - CoffeeScript (plcoffee) - LiveScript (plls) -With PostgreSQL 9.1 or above, you are able to load tohse dialects via CREATE +With PostgreSQL 9.1 or above, you are able to load those dialects via CREATE EXTENSION command. diff --git a/expected/es6.out b/expected/es6.out new file mode 100644 index 00000000..9d99abd5 --- /dev/null +++ b/expected/es6.out @@ -0,0 +1,64 @@ +-- ES6 / harmony features +CREATE TABLE rectangle ( + id INTEGER, + data JSON +); +INSERT INTO rectangle (id, data) VALUES +(1, '{"width": 20.3, "height": 1.5}'), +(2, '{"width": 10.2, "height": 9.5}'), +(3, '{"width": 3.5, "height": 5.2}'), +(4, '{"width": 8.2, "height": 8.2}'), +(5, '{"width": 9.4, "height": 0.2}'), +(6, '{"width": 1.2, "height": 1.5}'); +-- for..of loop over result array with break +CREATE OR REPLACE FUNCTION get_rectangles_area(min_area NUMERIC) + RETURNS json AS $$ + var rectangles = plv8.execute('SELECT id, data FROM rectangle ORDER BY id'); + var result = []; + var area = 0.0; + for (var rectangle of rectangles) { + area += rectangle.data.width * rectangle.data.height; + result.push({id: rectangle.id, data: rectangle.data}); + if (area >= min_area) { + break; + } + } + return result; + $$ LANGUAGE plv8 STABLE STRICT; +SELECT get_rectangles_area(130.0); + get_rectangles_area +-------------------------------------------------------------------------------------------------------------------------------------- + [{"id":1,"data":{"width":20.3,"height":1.5}},{"id":2,"data":{"width":10.2,"height":9.5}},{"id":3,"data":{"width":3.5,"height":5.2}}] +(1 row) + +-- same for..of loop, this time using a cursor within a generator +CREATE OR REPLACE FUNCTION get_rectangles_area(min_area NUMERIC) + RETURNS json AS $$ + var plan = plv8.prepare('SELECT id, data FROM rectangle ORDER BY id'); + var cursor = plan.cursor(); + var generator = function* () { + var row; + while (row = cursor.fetch()) { + yield row; + } + }; + var rectangles = generator(); + var result = []; + var area = 0.0; + for (var rectangle of rectangles) { + area += rectangle.data.width * rectangle.data.height; + result.push({id: rectangle.id, data: rectangle.data}); + if (area >= min_area) { + break; + } + } + cursor.close(); + plan.free(); + return result; + $$ LANGUAGE plv8 STABLE STRICT; +SELECT get_rectangles_area(130.0); + get_rectangles_area +-------------------------------------------------------------------------------------------------------------------------------------- + [{"id":1,"data":{"width":20.3,"height":1.5}},{"id":2,"data":{"width":10.2,"height":9.5}},{"id":3,"data":{"width":3.5,"height":5.2}}] +(1 row) + diff --git a/expected/guc.out b/expected/guc.out new file mode 100644 index 00000000..c50f00e8 --- /dev/null +++ b/expected/guc.out @@ -0,0 +1,14 @@ +-- enable strict mode with GUC, which allows usage of ES6 let and const keywords +SET plv8.v8_flags = '--use_strict'; +CREATE OR REPLACE FUNCTION let_test() + RETURNS json AS $$ + let result = ['Hello, World!']; + return result; + $$ LANGUAGE plv8 STABLE STRICT; +SELECT let_test(); + let_test +------------------- + ["Hello, World!"] +(1 row) + +DROP FUNCTION let_test(); diff --git a/plv8.cc b/plv8.cc index 8e2be808..a1dfd53f 100644 --- a/plv8.cc +++ b/plv8.cc @@ -6,6 +6,8 @@ *------------------------------------------------------------------------- */ #include "plv8.h" +#include "libplatform/libplatform.h" + #include extern "C" { @@ -86,6 +88,8 @@ typedef struct plv8_proc_cache Oid argtypes[FUNC_MAX_ARGS]; } plv8_proc_cache; +Isolate* plv8_isolate = NULL; + /* * The function and context are created at the first invocation. Their * lifetime is same as plv8_proc, but they are not palloc'ed memory, @@ -95,6 +99,7 @@ typedef struct plv8_exec_env { Persistent recv; Persistent context; + Local localContext() { return Local::New(plv8_isolate, context) ; } struct plv8_exec_env *next; } plv8_exec_env; @@ -118,6 +123,7 @@ typedef struct plv8_proc typedef struct plv8_context { Persistent context; + Local localContext() { return Local::New(plv8_isolate, context) ; } Oid user_id; } plv8_context; @@ -141,9 +147,10 @@ static void plv8_xact_cb(XactEvent event, void *arg); * They could raise errors with C++ throw statements, or never throw exceptions. */ static plv8_exec_env *CreateExecEnv(Handle script); +static plv8_exec_env *CreateExecEnv(Persistent& script); static plv8_proc *Compile(Oid fn_oid, FunctionCallInfo fcinfo, bool validate, bool is_trigger, Dialect dialect); -static Local CompileFunction(Handle global_context, +static Local CompileFunction(Persistent& global_context, const char *proname, int proarglen, const char *proargs[], const char *prosrc, bool is_trigger, bool retset, Dialect dialect); @@ -152,12 +159,15 @@ static Datum CallFunction(PG_FUNCTION_ARGS, plv8_exec_env *xenv, static Datum CallSRFunction(PG_FUNCTION_ARGS, plv8_exec_env *xenv, int nargs, plv8_type argtypes[], plv8_type *rettype); static Datum CallTrigger(PG_FUNCTION_ARGS, plv8_exec_env *xenv); -static Persistent GetGlobalContext(); -static Persistent GetGlobalObjectTemplate(); +static void GetGlobalContext(Persistent& global_context); +static Local GetGlobalObjectTemplate(); /* A GUC to specify a custom start up function to call */ static char *plv8_start_proc = NULL; +/* A GUC to specify V8 flags (e.g. --es_staging) */ +static char *plv8_v8_flags = NULL; + /* A GUC to specify the remote debugger port */ static int plv8_debugger_port; /* @@ -210,6 +220,18 @@ _PG_init(void) NULL, NULL); + DefineCustomStringVariable("plv8.v8_flags", + gettext_noop("V8 engine initialization flags (e.g. --es_staging for additional ES6 features)."), + NULL, + &plv8_v8_flags, + NULL, + PGC_USERSET, 0, +#if PG_VERSION_NUM >= 90100 + NULL, +#endif + NULL, + NULL); + DefineCustomIntVariable("plv8.debugger_port", gettext_noop("V8 remote debug port."), gettext_noop("The default value is 35432. " @@ -226,6 +248,17 @@ _PG_init(void) RegisterXactCallback(plv8_xact_cb, NULL); EmitWarningsOnPlaceholders("plv8"); + + + V8::InitializeICU(); + Platform* platform = platform::CreateDefaultPlatform(); + V8::InitializePlatform(platform); + V8::Initialize(); + if (plv8_v8_flags != NULL) { + V8::SetFlagsFromString(plv8_v8_flags, strlen(plv8_v8_flags)); + } + plv8_isolate = Isolate::New(); + plv8_isolate->Enter(); } static void @@ -237,8 +270,7 @@ plv8_xact_cb(XactEvent event, void *arg) { if (!env->recv.IsEmpty()) { - env->recv.Dispose(); - env->recv.Clear(); + env->recv.Reset(); } env = env->next; /* @@ -278,7 +310,7 @@ common_pl_call_handler(PG_FUNCTION_ARGS, Dialect dialect) throw() #ifdef ENABLE_DEBUGGER_SUPPORT Locker lock; #endif // ENABLE_DEBUGGER_SUPPORT - HandleScope handle_scope; + HandleScope handle_scope(plv8_isolate); if (!fcinfo->flinfo->fn_extra) { @@ -337,11 +369,12 @@ common_pl_inline_handler(PG_FUNCTION_ARGS, Dialect dialect) throw() #ifdef ENABLE_DEBUGGER_SUPPORT Locker lock; #endif // ENABLE_DEBUGGER_SUPPORT - HandleScope handle_scope; + HandleScope handle_scope(plv8_isolate); char *source_text = codeblock->source_text; - Handle global_context = GetGlobalContext(); - Handle function = CompileFunction(global_context, + Persistent global_context; + GetGlobalContext(global_context); + Local function = CompileFunction(global_context, NULL, 0, NULL, source_text, false, false, dialect); plv8_exec_env *xenv = CreateExecEnv(function); @@ -401,7 +434,7 @@ static Datum CallFunction(PG_FUNCTION_ARGS, plv8_exec_env *xenv, int nargs, plv8_type argtypes[], plv8_type *rettype) { - Handle context = xenv->context; + Local context = xenv->localContext(); Context::Scope context_scope(context); Handle args[FUNC_MAX_ARGS]; Handle plv8obj; @@ -428,10 +461,11 @@ CallFunction(PG_FUNCTION_ARGS, plv8_exec_env *xenv, args[i] = ToValue(fcinfo->arg[i], fcinfo->argnull[i], &argtypes[i]); } + Local recv = Local::New(plv8_isolate, xenv->recv); Local fn = - Local::Cast(xenv->recv->GetInternalField(0)); + Local::Cast(recv->GetInternalField(0)); Local result = - DoCall(fn, xenv->recv, nargs, args); + DoCall(fn, recv, nargs, args); if (rettype) return ToDatum(result, &fcinfo->isnull, rettype); @@ -509,7 +543,7 @@ CallSRFunction(PG_FUNCTION_ARGS, plv8_exec_env *xenv, tupstore = CreateTupleStore(fcinfo, &tupdesc); - Handle context = xenv->context; + Handle context = xenv->localContext(); Context::Scope context_scope(context); Converter conv(tupdesc, proc->functypclass == TYPEFUNC_SCALAR); Handle args[FUNC_MAX_ARGS + 1]; @@ -523,10 +557,11 @@ CallSRFunction(PG_FUNCTION_ARGS, plv8_exec_env *xenv, for (int i = 0; i < nargs; i++) args[i] = ToValue(fcinfo->arg[i], fcinfo->argnull[i], &argtypes[i]); + Local recv = Local::New(plv8_isolate, xenv->recv); Local fn = - Local::Cast(xenv->recv->GetInternalField(0)); + Local::Cast(recv->GetInternalField(0)); - Handle result = DoCall(fn, xenv->recv, nargs, args); + Handle result = DoCall(fn, recv, nargs, args); if (result->IsUndefined()) { @@ -572,7 +607,7 @@ CallTrigger(PG_FUNCTION_ARGS, plv8_exec_env *xenv) Handle args[10]; Datum result = (Datum) 0; - Handle context = xenv->context; + Handle context = xenv->localContext(); Context::Scope context_scope(context); if (TRIGGER_FIRED_FOR_ROW(event)) @@ -586,13 +621,13 @@ CallTrigger(PG_FUNCTION_ARGS, plv8_exec_env *xenv) // NEW args[0] = conv.ToValue(trig->tg_trigtuple); // OLD - args[1] = Undefined(); + args[1] = Undefined(plv8_isolate); } else if (TRIGGER_FIRED_BY_DELETE(event)) { result = PointerGetDatum(trig->tg_trigtuple); // NEW - args[0] = Undefined(); + args[0] = Undefined(plv8_isolate); // OLD args[1] = conv.ToValue(trig->tg_trigtuple); } @@ -607,7 +642,7 @@ CallTrigger(PG_FUNCTION_ARGS, plv8_exec_env *xenv) } else { - args[0] = args[1] = Undefined(); + args[0] = args[1] = Undefined(plv8_isolate); } // 2: TG_NAME @@ -615,32 +650,32 @@ CallTrigger(PG_FUNCTION_ARGS, plv8_exec_env *xenv) // 3: TG_WHEN if (TRIGGER_FIRED_BEFORE(event)) - args[3] = String::New("BEFORE"); + args[3] = String::NewFromUtf8(plv8_isolate, "BEFORE"); else - args[3] = String::New("AFTER"); + args[3] = String::NewFromUtf8(plv8_isolate, "AFTER"); // 4: TG_LEVEL if (TRIGGER_FIRED_FOR_ROW(event)) - args[4] = String::New("ROW"); + args[4] = String::NewFromUtf8(plv8_isolate, "ROW"); else - args[4] = String::New("STATEMENT"); + args[4] = String::NewFromUtf8(plv8_isolate, "STATEMENT"); // 5: TG_OP if (TRIGGER_FIRED_BY_INSERT(event)) - args[5] = String::New("INSERT"); + args[5] = String::NewFromUtf8(plv8_isolate, "INSERT"); else if (TRIGGER_FIRED_BY_DELETE(event)) - args[5] = String::New("DELETE"); + args[5] = String::NewFromUtf8(plv8_isolate, "DELETE"); else if (TRIGGER_FIRED_BY_UPDATE(event)) - args[5] = String::New("UPDATE"); + args[5] = String::NewFromUtf8(plv8_isolate, "UPDATE"); #ifdef TRIGGER_FIRED_BY_TRUNCATE else if (TRIGGER_FIRED_BY_TRUNCATE(event)) - args[5] = String::New("TRUNCATE"); + args[5] = String::NewFromUtf8(plv8_isolate, "TRUNCATE"); #endif else - args[5] = String::New("?"); + args[5] = String::NewFromUtf8(plv8_isolate, "?"); // 6: TG_RELID - args[6] = Uint32::New(RelationGetRelid(rel)); + args[6] = Uint32::New(plv8_isolate, RelationGetRelid(rel)); // 7: TG_TABLE_NAME args[7] = ToString(RelationGetRelationName(rel)); @@ -649,16 +684,17 @@ CallTrigger(PG_FUNCTION_ARGS, plv8_exec_env *xenv) args[8] = ToString(get_namespace_name(RelationGetNamespace(rel))); // 9: TG_ARGV - Handle tgargs = Array::New(trig->tg_trigger->tgnargs); + Handle tgargs = Array::New(plv8_isolate, trig->tg_trigger->tgnargs); for (int i = 0; i < trig->tg_trigger->tgnargs; i++) tgargs->Set(i, ToString(trig->tg_trigger->tgargs[i])); args[9] = tgargs; TryCatch try_catch; + Local recv = Local::New(plv8_isolate, xenv->recv); Local fn = - Local::Cast(xenv->recv->GetInternalField(0)); + Local::Cast(recv->GetInternalField(0)); Handle newtup = - DoCall(fn, xenv->recv, lengthof(args), args); + DoCall(fn, recv, lengthof(args), args); if (newtup.IsEmpty()) throw js_error(try_catch); @@ -804,8 +840,7 @@ plv8_get_proc(Oid fn_oid, FunctionCallInfo fcinfo, bool validate, char ***argnam pfree(cache->prosrc); cache->prosrc = NULL; } - cache->function.Dispose(); - cache->function.Clear(); + cache->function.Reset(); } else { @@ -913,11 +948,47 @@ plv8_get_proc(Oid fn_oid, FunctionCallInfo fcinfo, bool validate, char ***argnam return proc; } +static plv8_exec_env * +CreateExecEnv(Persistent& function) +{ + plv8_exec_env *xenv; + HandleScope handle_scope(plv8_isolate); + + PG_TRY(); + { + xenv = plv8_new_exec_env(); + } + PG_CATCH(); + { + throw pg_error(); + } + PG_END_TRY(); + + GetGlobalContext(xenv->context); + Context::Scope scope(xenv->localContext()); + + static Persistent recv_templ; + if (recv_templ.IsEmpty()) + { + Local templ = ObjectTemplate::New(plv8_isolate); + templ->SetInternalFieldCount(1); + recv_templ.Reset(plv8_isolate, templ); + } + Local templ = Local::New(plv8_isolate, recv_templ); + Local obj = templ->NewInstance(); + Local f = Local::New(plv8_isolate, function); + obj->SetInternalField(0, f); + xenv->recv.Reset(plv8_isolate, obj); + + + return xenv; +} + static plv8_exec_env * CreateExecEnv(Handle function) { plv8_exec_env *xenv; - HandleScope handle_scope; + HandleScope handle_scope(plv8_isolate); PG_TRY(); { @@ -929,18 +1000,22 @@ CreateExecEnv(Handle function) } PG_END_TRY(); - xenv->context = GetGlobalContext(); - Context::Scope scope(xenv->context); + GetGlobalContext(xenv->context); + Context::Scope scope(xenv->localContext()); static Persistent recv_templ; if (recv_templ.IsEmpty()) { - recv_templ = Persistent::New(ObjectTemplate::New()); - recv_templ->SetInternalFieldCount(1); + Local templ = ObjectTemplate::New(plv8_isolate); + templ->SetInternalFieldCount(1); + recv_templ.Reset(plv8_isolate, templ); } - xenv->recv = Persistent::New(recv_templ->NewInstance()); + Local templ = Local::New(plv8_isolate, recv_templ); + Local obj = templ->NewInstance(); + Local f = Local::New(plv8_isolate, function); + obj->SetInternalField(0, f); + xenv->recv.Reset(plv8_isolate, obj); - xenv->recv->SetInternalField(0, function); return xenv; } @@ -949,9 +1024,14 @@ CreateExecEnv(Handle function) static char * CompileDialect(const char *src, Dialect dialect) { - HandleScope handle_scope; - static Persistent context = Context::New((ExtensionConfiguration*)NULL); - Context::Scope context_scope(context); + HandleScope handle_scope(plv8_isolate); + static Persistent context; + if (context.IsEmpty()) { + Local ctx = Context::New(plv8_isolate, (ExtensionConfiguration*)NULL); + context.Reset(plv8_isolate, ctx); + } + Local ctx = Local::New(plv8_isolate, context); + Context::Scope context_scope(ctx); TryCatch try_catch; Local key; char *cresult; @@ -962,24 +1042,24 @@ CompileDialect(const char *src, Dialect dialect) case PLV8_DIALECT_COFFEE: if (coffee_script_binary_data[0] == '\0') throw js_error("CoffeeScript is not enabled"); - key = String::NewSymbol("CoffeeScript"); + key = String::NewFromUtf8(plv8_isolate, "CoffeeScript", String::kInternalizedString); dialect_binary_data = (const char *) coffee_script_binary_data; break; case PLV8_DIALECT_LIVESCRIPT: if (livescript_binary_data[0] == '\0') throw js_error("LiveScript is not enabled"); - key = String::NewSymbol("LiveScript"); + key = String::NewFromUtf8(plv8_isolate, "LiveScript", String::kInternalizedString); dialect_binary_data = (const char *) livescript_binary_data; break; default: throw js_error("Unknown Dialect"); } - if (context->Global()->Get(key)->IsUndefined()) + if (ctx->Global()->Get(key)->IsUndefined()) { - HandleScope handle_scope; + HandleScope handle_scope(plv8_isolate); Local