From d96ad377f9fc4f82c569d29b59b38b7ec1d0d5b2 Mon Sep 17 00:00:00 2001 From: Marcin Cieslak Date: Sat, 8 Aug 2015 02:26:41 +0000 Subject: [PATCH 01/15] Update to io.js 3.0.0, use nan 2.0 The code has been updated to meet the requirements of the updated V8 engine as provided by io.js. In some cases additional EscapableHandleScope has been provided. SassValueWrapper::New has been changed: in case of instance construction via the function call "sass.types.Color(0,0,0)" instead of "new sass.types.Color(0,0,0)" the "new" part is no longer executed by falling through. This should not be necessary because the constructor is called by the NewInstance call anyway. This fixes the following error: FATAL ERROR: v8::Object::SetAlignedPointerInInternalField() Internal field out of bounds --- package.json | 2 +- src/binding.cpp | 140 ++++++++++++++-------------- src/callback_bridge.h | 77 ++++++++------- src/create_string.cpp | 12 ++- src/create_string.h | 6 +- src/custom_function_bridge.cpp | 6 +- src/custom_function_bridge.h | 8 +- src/custom_importer_bridge.cpp | 68 +++++++------- src/custom_importer_bridge.h | 11 +-- src/sass_context_wrapper.cpp | 2 +- src/sass_context_wrapper.h | 8 +- src/sass_types/boolean.cpp | 54 +++++------ src/sass_types/boolean.h | 12 +-- src/sass_types/color.cpp | 82 ++++++++-------- src/sass_types/color.h | 6 +- src/sass_types/error.cpp | 6 +- src/sass_types/error.h | 6 +- src/sass_types/factory.cpp | 31 +++--- src/sass_types/factory.h | 6 +- src/sass_types/list.cpp | 69 +++++++------- src/sass_types/list.h | 6 +- src/sass_types/map.cpp | 89 +++++++++--------- src/sass_types/map.h | 6 +- src/sass_types/null.cpp | 38 ++++---- src/sass_types/null.h | 12 +-- src/sass_types/number.cpp | 45 ++++----- src/sass_types/number.h | 5 +- src/sass_types/sass_value_wrapper.h | 98 +++++++++---------- src/sass_types/string.cpp | 25 +++-- src/sass_types/string.h | 6 +- src/sass_types/value.h | 4 +- 31 files changed, 445 insertions(+), 501 deletions(-) diff --git a/package.json b/package.json index cb5da204d..b1f528b41 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ "glob": "^5.0.13", "meow": "^3.3.0", "mkdirp": "^0.5.1", - "nan": "^1.8.4", + "nan": "^2.0.0", "npmconf": "^2.1.2", "pangyp": "^2.2.1", "request": "^2.58.0", diff --git a/src/binding.cpp b/src/binding.cpp index d482737c5..03810f0d3 100644 --- a/src/binding.cpp +++ b/src/binding.cpp @@ -37,12 +37,12 @@ union Sass_Value* sass_custom_function(const union Sass_Value* s_args, Sass_Func } } -void ExtractOptions(Local options, void* cptr, sass_context_wrapper* ctx_w, bool is_file, bool is_sync) { - NanScope(); +void ExtractOptions(v8::Local options, void* cptr, sass_context_wrapper* ctx_w, bool is_file, bool is_sync) { + Nan::HandleScope scope; struct Sass_Context* ctx; - NanAssignPersistent(ctx_w->result, options->Get(NanNew("result"))->ToObject()); + ctx_w->result.Reset(Nan::Get(options, Nan::New("result").ToLocalChecked()).ToLocalChecked()->ToObject()); if (is_file) { ctx_w->fctx = (struct Sass_File_Context*) cptr; @@ -61,52 +61,52 @@ void ExtractOptions(Local options, void* cptr, sass_context_wrapper* ctx ctx_w->request.data = ctx_w; // async (callback) style - Local success_callback = Local::Cast(options->Get(NanNew("success"))); - Local error_callback = Local::Cast(options->Get(NanNew("error"))); + v8::Local success_callback = v8::Local::Cast(Nan::Get(options, Nan::New("success").ToLocalChecked()).ToLocalChecked()); + v8::Local error_callback = v8::Local::Cast(Nan::Get(options, Nan::New("error").ToLocalChecked()).ToLocalChecked()); - ctx_w->success_callback = new NanCallback(success_callback); - ctx_w->error_callback = new NanCallback(error_callback); + ctx_w->success_callback = new Nan::Callback(success_callback); + ctx_w->error_callback = new Nan::Callback(error_callback); } if (!is_file) { - ctx_w->file = create_string(options->Get(NanNew("file"))); + ctx_w->file = create_string(Nan::Get(options, Nan::New("file").ToLocalChecked())); sass_option_set_input_path(sass_options, ctx_w->file); } - int indent_len = options->Get(NanNew("indentWidth"))->Int32Value(); + int indent_len = Nan::Get(options, Nan::New("indentWidth").ToLocalChecked()).ToLocalChecked()->Int32Value(); ctx_w->indent = (char*)malloc(indent_len + 1); strcpy(ctx_w->indent, std::string( indent_len, - options->Get(NanNew("indentType"))->Int32Value() == 1 ? '\t' : ' ' + Nan::Get(options, Nan::New("indentType").ToLocalChecked()).ToLocalChecked()->Int32Value() == 1 ? '\t' : ' ' ).c_str()); - ctx_w->linefeed = create_string(options->Get(NanNew("linefeed"))); - ctx_w->include_path = create_string(options->Get(NanNew("includePaths"))); - ctx_w->out_file = create_string(options->Get(NanNew("outFile"))); - ctx_w->source_map = create_string(options->Get(NanNew("sourceMap"))); - ctx_w->source_map_root = create_string(options->Get(NanNew("sourceMapRoot"))); + ctx_w->linefeed = create_string(Nan::Get(options, Nan::New("linefeed").ToLocalChecked())); + ctx_w->include_path = create_string(Nan::Get(options, Nan::New("includePaths").ToLocalChecked())); + ctx_w->out_file = create_string(Nan::Get(options, Nan::New("outFile").ToLocalChecked())); + ctx_w->source_map = create_string(Nan::Get(options, Nan::New("sourceMap").ToLocalChecked())); + ctx_w->source_map_root = create_string(Nan::Get(options, Nan::New("sourceMapRoot").ToLocalChecked())); sass_option_set_output_path(sass_options, ctx_w->out_file); - sass_option_set_output_style(sass_options, (Sass_Output_Style)options->Get(NanNew("style"))->Int32Value()); - sass_option_set_is_indented_syntax_src(sass_options, options->Get(NanNew("indentedSyntax"))->BooleanValue()); - sass_option_set_source_comments(sass_options, options->Get(NanNew("sourceComments"))->BooleanValue()); - sass_option_set_omit_source_map_url(sass_options, options->Get(NanNew("omitSourceMapUrl"))->BooleanValue()); - sass_option_set_source_map_embed(sass_options, options->Get(NanNew("sourceMapEmbed"))->BooleanValue()); - sass_option_set_source_map_contents(sass_options, options->Get(NanNew("sourceMapContents"))->BooleanValue()); + sass_option_set_output_style(sass_options, (Sass_Output_Style)Nan::Get(options, Nan::New("style").ToLocalChecked()).ToLocalChecked()->Int32Value()); + sass_option_set_is_indented_syntax_src(sass_options, Nan::Get(options, Nan::New("indentedSyntax").ToLocalChecked()).ToLocalChecked()->BooleanValue()); + sass_option_set_source_comments(sass_options, Nan::Get(options, Nan::New("sourceComments").ToLocalChecked()).ToLocalChecked()->BooleanValue()); + sass_option_set_omit_source_map_url(sass_options, Nan::Get(options, Nan::New("omitSourceMapUrl").ToLocalChecked()).ToLocalChecked()->BooleanValue()); + sass_option_set_source_map_embed(sass_options, Nan::Get(options, Nan::New("sourceMapEmbed").ToLocalChecked()).ToLocalChecked()->BooleanValue()); + sass_option_set_source_map_contents(sass_options, Nan::Get(options, Nan::New("sourceMapContents").ToLocalChecked()).ToLocalChecked()->BooleanValue()); sass_option_set_source_map_file(sass_options, ctx_w->source_map); sass_option_set_source_map_root(sass_options, ctx_w->source_map_root); sass_option_set_include_path(sass_options, ctx_w->include_path); - sass_option_set_precision(sass_options, options->Get(NanNew("precision"))->Int32Value()); + sass_option_set_precision(sass_options, Nan::Get(options, Nan::New("precision").ToLocalChecked()).ToLocalChecked()->Int32Value()); sass_option_set_indent(sass_options, ctx_w->indent); sass_option_set_linefeed(sass_options, ctx_w->linefeed); - Local importer_callback = options->Get(NanNew("importer")); + v8::Local importer_callback = Nan::Get(options, Nan::New("importer").ToLocalChecked()).ToLocalChecked(); if (importer_callback->IsFunction()) { - Local importer = Local::Cast(importer_callback); - auto bridge = std::make_shared(new NanCallback(importer), ctx_w->is_sync); + v8::Local importer = v8::Local::Cast(importer_callback); + auto bridge = std::make_shared(new Nan::Callback(importer), ctx_w->is_sync); ctx_w->importer_bridges.push_back(bridge); Sass_Importer_List c_importers = sass_make_importer_list(1); @@ -115,13 +115,13 @@ void ExtractOptions(Local options, void* cptr, sass_context_wrapper* ctx sass_option_set_c_importers(sass_options, c_importers); } else if (importer_callback->IsArray()) { - Handle importers = Handle::Cast(importer_callback); + v8::Local importers = v8::Local::Cast(importer_callback); Sass_Importer_List c_importers = sass_make_importer_list(importers->Length()); for (size_t i = 0; i < importers->Length(); ++i) { - Local callback = Local::Cast(importers->Get(static_cast(i))); + v8::Local callback = v8::Local::Cast(Nan::Get(importers, static_cast(i)).ToLocalChecked()); - auto bridge = std::make_shared(new NanCallback(callback), ctx_w->is_sync); + auto bridge = std::make_shared(new Nan::Callback(callback), ctx_w->is_sync); ctx_w->importer_bridges.push_back(bridge); c_importers[i] = sass_make_importer(sass_importer, importers->Length() - i - 1, bridge.get()); @@ -130,19 +130,19 @@ void ExtractOptions(Local options, void* cptr, sass_context_wrapper* ctx sass_option_set_c_importers(sass_options, c_importers); } - Local custom_functions = options->Get(NanNew("functions")); + v8::Local custom_functions = Nan::Get(options, Nan::New("functions").ToLocalChecked()).ToLocalChecked(); if (custom_functions->IsObject()) { - Local functions = Local::Cast(custom_functions); - Local signatures = functions->GetOwnPropertyNames(); + v8::Local functions = v8::Local::Cast(custom_functions); + v8::Local signatures = Nan::GetOwnPropertyNames(functions).ToLocalChecked(); unsigned num_signatures = signatures->Length(); Sass_Function_List fn_list = sass_make_function_list(num_signatures); for (unsigned i = 0; i < num_signatures; i++) { - Local signature = Local::Cast(signatures->Get(NanNew(i))); - Local callback = Local::Cast(functions->Get(signature)); + v8::Local signature = v8::Local::Cast(Nan::Get(signatures, Nan::New(i)).ToLocalChecked()); + v8::Local callback = v8::Local::Cast(Nan::Get(functions, signature).ToLocalChecked()); - auto bridge = std::make_shared(new NanCallback(callback), ctx_w->is_sync); + auto bridge = std::make_shared(new Nan::Callback(callback), ctx_w->is_sync); ctx_w->function_bridges.push_back(bridge); Sass_Function_Entry fn = sass_make_function(create_string(signature), sass_custom_function, bridge.get()); @@ -154,48 +154,51 @@ void ExtractOptions(Local options, void* cptr, sass_context_wrapper* ctx } void GetStats(sass_context_wrapper* ctx_w, Sass_Context* ctx) { - NanScope(); + Nan::HandleScope scope; char** included_files = sass_context_get_included_files(ctx); - Handle arr = NanNew(); + v8::Local arr = Nan::New(); if (included_files) { for (int i = 0; included_files[i] != nullptr; ++i) { - arr->Set(i, NanNew(included_files[i])); + Nan::Set(arr, i, Nan::New(included_files[i]).ToLocalChecked()); } } - NanNew(ctx_w->result)->Get(NanNew("stats"))->ToObject()->Set(NanNew("includedFiles"), arr); + Nan::Set(Nan::Get(Nan::New(ctx_w->result), Nan::New("stats").ToLocalChecked()).ToLocalChecked()->ToObject(), Nan::New("includedFiles").ToLocalChecked(), arr); } int GetResult(sass_context_wrapper* ctx_w, Sass_Context* ctx, bool is_sync = false) { - NanScope(); + Nan::HandleScope scope; + v8::Local result; int status = sass_context_get_error_status(ctx); + result = Nan::New(ctx_w->result); + if (status == 0) { const char* css = sass_context_get_output_string(ctx); const char* map = sass_context_get_source_map_string(ctx); - NanNew(ctx_w->result)->Set(NanNew("css"), NanNewBufferHandle(css, static_cast(strlen(css)))); + Nan::Set(result, Nan::New("css").ToLocalChecked(), Nan::CopyBuffer(css, static_cast(strlen(css))).ToLocalChecked()); GetStats(ctx_w, ctx); if (map) { - NanNew(ctx_w->result)->Set(NanNew("map"), NanNewBufferHandle(map, static_cast(strlen(map)))); + Nan::Set(result, Nan::New("map").ToLocalChecked(), Nan::CopyBuffer(map, static_cast(strlen(map))).ToLocalChecked()); } } else if (is_sync) { - NanNew(ctx_w->result)->Set(NanNew("error"), NanNew(sass_context_get_error_json(ctx))); + Nan::Set(result, Nan::New("error").ToLocalChecked(), Nan::New(sass_context_get_error_json(ctx)).ToLocalChecked()); } return status; } void MakeCallback(uv_work_t* req) { - NanScope(); + Nan::HandleScope scope; - TryCatch try_catch; + Nan::TryCatch try_catch; sass_context_wrapper* ctx_w = static_cast(req->data); struct Sass_Context* ctx; @@ -215,23 +218,22 @@ void MakeCallback(uv_work_t* req) { else if (ctx_w->error_callback) { // if error, do callback(error) const char* err = sass_context_get_error_json(ctx); - Local argv[] = { - NanNew(err) + v8::Local argv[] = { + Nan::New(err).ToLocalChecked() }; ctx_w->error_callback->Call(1, argv); } if (try_catch.HasCaught()) { - node::FatalException(try_catch); + Nan::FatalException(try_catch); } sass_free_context_wrapper(ctx_w); } NAN_METHOD(render) { - NanScope(); - Local options = args[0]->ToObject(); - char* source_string = create_string(options->Get(NanNew("data"))); + v8::Local options = info[0]->ToObject(); + char* source_string = create_string(Nan::Get(options, Nan::New("data").ToLocalChecked())); struct Sass_Data_Context* dctx = sass_make_data_context(source_string); sass_context_wrapper* ctx_w = sass_make_context_wrapper(); @@ -241,14 +243,13 @@ NAN_METHOD(render) { assert(status == 0); - NanReturnUndefined(); + return; } NAN_METHOD(render_sync) { - NanScope(); - Local options = args[0]->ToObject(); - char* source_string = create_string(options->Get(NanNew("data"))); + v8::Local options = info[0]->ToObject(); + char* source_string = create_string(Nan::Get(options, Nan::New("data").ToLocalChecked())); struct Sass_Data_Context* dctx = sass_make_data_context(source_string); struct Sass_Context* ctx = sass_data_context_get_context(dctx); sass_context_wrapper* ctx_w = sass_make_context_wrapper(); @@ -261,14 +262,13 @@ NAN_METHOD(render_sync) { sass_free_context_wrapper(ctx_w); - NanReturnValue(NanNew(result == 0)); + info.GetReturnValue().Set(Nan::New(result == 0)); } NAN_METHOD(render_file) { - NanScope(); - Local options = args[0]->ToObject(); - char* input_path = create_string(options->Get(NanNew("file"))); + v8::Local options = info[0]->ToObject(); + char* input_path = create_string(Nan::Get(options, Nan::New("file").ToLocalChecked())); struct Sass_File_Context* fctx = sass_make_file_context(input_path); sass_context_wrapper* ctx_w = sass_make_context_wrapper(); @@ -278,14 +278,13 @@ NAN_METHOD(render_file) { assert(status == 0); - NanReturnUndefined(); + return; } NAN_METHOD(render_file_sync) { - NanScope(); - Local options = args[0]->ToObject(); - char* input_path = create_string(options->Get(NanNew("file"))); + v8::Local options = info[0]->ToObject(); + char* input_path = create_string(Nan::Get(options, Nan::New("file").ToLocalChecked())); struct Sass_File_Context* fctx = sass_make_file_context(input_path); struct Sass_Context* ctx = sass_file_context_get_context(fctx); sass_context_wrapper* ctx_w = sass_make_context_wrapper(); @@ -298,20 +297,19 @@ NAN_METHOD(render_file_sync) { free(input_path); sass_free_context_wrapper(ctx_w); - NanReturnValue(NanNew(result == 0)); + info.GetReturnValue().Set(Nan::New(result == 0)); } NAN_METHOD(libsass_version) { - NanScope(); - NanReturnValue(NanNew(libsass_version())); + info.GetReturnValue().Set(Nan::New(libsass_version()).ToLocalChecked()); } -void RegisterModule(v8::Handle target) { - NODE_SET_METHOD(target, "render", render); - NODE_SET_METHOD(target, "renderSync", render_sync); - NODE_SET_METHOD(target, "renderFile", render_file); - NODE_SET_METHOD(target, "renderFileSync", render_file_sync); - NODE_SET_METHOD(target, "libsassVersion", libsass_version); +void RegisterModule(v8::Local target) { + Nan::SetMethod(target, "render", render); + Nan::SetMethod(target, "renderSync", render_sync); + Nan::SetMethod(target, "renderFile", render_file); + Nan::SetMethod(target, "renderFileSync", render_file_sync); + Nan::SetMethod(target, "libsassVersion", libsass_version); SassTypes::Factory::initExports(target); } diff --git a/src/callback_bridge.h b/src/callback_bridge.h index 2cbe8815c..7fe1366ea 100644 --- a/src/callback_bridge.h +++ b/src/callback_bridge.h @@ -8,12 +8,10 @@ #define COMMA , -using namespace v8; - template class CallbackBridge { public: - CallbackBridge(NanCallback*, bool); + CallbackBridge(Nan::Callback*, bool); virtual ~CallbackBridge(); // Executes the callback @@ -22,12 +20,12 @@ class CallbackBridge { protected: // We will expose a bridge object to the JS callback that wraps this instance so we don't loose context. // This is the V8 constructor for such objects. - static Handle get_wrapper_constructor(); + static Nan::MaybeLocal get_wrapper_constructor(); static void async_gone(uv_handle_t *handle); static NAN_METHOD(New); static NAN_METHOD(ReturnCallback); - static Persistent wrapper_constructor; - Persistent wrapper; + static Nan::Persistent wrapper_constructor; + Nan::Persistent wrapper; // The callback that will get called in the main thread after the worker thread used for the sass // compilation step makes a call to uv_async_send() @@ -36,12 +34,12 @@ class CallbackBridge { // The V8 values sent to our ReturnCallback must be read on the main thread not the sass worker thread. // This gives a chance to specialized subclasses to transform those values into whatever makes sense to // sass before we resume the worker thread. - virtual T post_process_return_value(Handle) const =0; + virtual T post_process_return_value(v8::Local) const =0; - virtual std::vector> pre_process_args(std::vector) const =0; + virtual std::vector> pre_process_args(std::vector) const =0; - NanCallback* callback; + Nan::Callback* callback; bool is_sync; std::mutex cv_mutex; @@ -53,10 +51,10 @@ class CallbackBridge { }; template -Persistent CallbackBridge::wrapper_constructor; +Nan::Persistent CallbackBridge::wrapper_constructor; template -CallbackBridge::CallbackBridge(NanCallback* callback, bool is_sync) : callback(callback), is_sync(is_sync) { +CallbackBridge::CallbackBridge(Nan::Callback* callback, bool is_sync) : callback(callback), is_sync(is_sync) { // This assumes the main thread will be the one instantiating the bridge if (!is_sync) { this->async = new uv_async_t; @@ -64,14 +62,15 @@ CallbackBridge::CallbackBridge(NanCallback* callback, bool is_sync) : call uv_async_init(uv_default_loop(), this->async, (uv_async_cb) dispatched_async_uv_callback); } - NanAssignPersistent(wrapper, NanNew(CallbackBridge::get_wrapper_constructor())->NewInstance()); - NanSetInternalFieldPointer(NanNew(wrapper), 0, this); + v8::Local func = CallbackBridge::get_wrapper_constructor().ToLocalChecked(); + wrapper.Reset(Nan::NewInstance(func).ToLocalChecked()); + Nan::SetInternalFieldPointer(Nan::New(wrapper), 0, this); } template CallbackBridge::~CallbackBridge() { delete this->callback; - NanDisposePersistent(this->wrapper); + this->wrapper.Reset(); if (!is_sync) { uv_close((uv_handle_t*)this->async, &async_gone); @@ -81,13 +80,13 @@ CallbackBridge::~CallbackBridge() { template T CallbackBridge::operator()(std::vector argv) { // argv.push_back(wrapper); - if (this->is_sync) { - std::vector> argv_v8 = pre_process_args(argv); - argv_v8.push_back(NanNew(wrapper)); + Nan::EscapableHandleScope scope; + std::vector> argv_v8 = pre_process_args(argv); + argv_v8.push_back(Nan::New(wrapper)); return this->post_process_return_value( - NanNew(this->callback->Call(argv_v8.size(), &argv_v8[0])) + scope.Escape(this->callback->Call(argv_v8.size(), &argv_v8[0])) ); } @@ -105,27 +104,26 @@ template void CallbackBridge::dispatched_async_uv_callback(uv_async_t *req) { CallbackBridge* bridge = static_cast(req->data); - NanScope(); - TryCatch try_catch; + Nan::HandleScope scope; + Nan::TryCatch try_catch; - std::vector> argv_v8 = bridge->pre_process_args(bridge->argv); - argv_v8.push_back(NanNew(bridge->wrapper)); + std::vector> argv_v8 = bridge->pre_process_args(bridge->argv); + argv_v8.push_back(Nan::New(bridge->wrapper)); - NanNew(bridge->callback->Call(argv_v8.size(), &argv_v8[0])); + bridge->callback->Call(argv_v8.size(), &argv_v8[0]); if (try_catch.HasCaught()) { - node::FatalException(try_catch); + Nan::FatalException(try_catch); } } template NAN_METHOD(CallbackBridge::ReturnCallback) { - NanScope(); - CallbackBridge* bridge = static_cast*>(NanGetInternalFieldPointer(args.This(), 0)); - TryCatch try_catch; + CallbackBridge* bridge = static_cast*>(Nan::GetInternalFieldPointer(info.This(), 0)); + Nan::TryCatch try_catch; - bridge->return_value = bridge->post_process_return_value(args[0]); + bridge->return_value = bridge->post_process_return_value(info[0]); { std::lock_guard lock(bridge->cv_mutex); @@ -135,33 +133,32 @@ NAN_METHOD(CallbackBridge::ReturnCallback) { bridge->condition_variable.notify_all(); if (try_catch.HasCaught()) { - node::FatalException(try_catch); + Nan::FatalException(try_catch); } - NanReturnUndefined(); + return; } template -Handle CallbackBridge::get_wrapper_constructor() { +Nan::MaybeLocal CallbackBridge::get_wrapper_constructor() { if (wrapper_constructor.IsEmpty()) { - Local tpl = NanNew(New); - tpl->SetClassName(NanNew("CallbackBridge")); + v8::Local tpl = Nan::New(New); + tpl->SetClassName(Nan::New("CallbackBridge").ToLocalChecked()); tpl->InstanceTemplate()->SetInternalFieldCount(1); - tpl->PrototypeTemplate()->Set( - NanNew("success"), - NanNew(ReturnCallback)->GetFunction() + + Nan::SetPrototypeTemplate(tpl, "success", + Nan::GetFunction(Nan::New(ReturnCallback)).ToLocalChecked() ); - NanAssignPersistent(wrapper_constructor, tpl->GetFunction()); + wrapper_constructor.Reset(Nan::GetFunction(tpl).ToLocalChecked()); } - return NanNew(wrapper_constructor); + return Nan::New(wrapper_constructor); } template NAN_METHOD(CallbackBridge::New) { - NanScope(); - NanReturnValue(args.This()); + info.GetReturnValue().Set(info.This()); } template diff --git a/src/create_string.cpp b/src/create_string.cpp index aa08c95b2..1b35b125f 100644 --- a/src/create_string.cpp +++ b/src/create_string.cpp @@ -3,12 +3,18 @@ #include #include "create_string.h" -char* create_string(Local value) { - if (value->IsNull() || !value->IsString()) { +char* create_string(Nan::MaybeLocal maybevalue) { + v8::Local value; + + if (maybevalue.ToLocal(&value)) { + if (value->IsNull() || !value->IsString()) { + return 0; + } + } else { return 0; } - String::Utf8Value string(value); + v8::String::Utf8Value string(value); char *str = (char *)malloc(string.length() + 1); strcpy(str, *string); return str; diff --git a/src/create_string.h b/src/create_string.h index f8df3aee1..03c7c927d 100644 --- a/src/create_string.h +++ b/src/create_string.h @@ -3,8 +3,6 @@ #include -using namespace v8; +char* create_string(Nan::MaybeLocal); -char* create_string(Local); - -#endif \ No newline at end of file +#endif diff --git a/src/custom_function_bridge.cpp b/src/custom_function_bridge.cpp index 0729f0ee7..3013650ab 100644 --- a/src/custom_function_bridge.cpp +++ b/src/custom_function_bridge.cpp @@ -2,7 +2,7 @@ #include "custom_function_bridge.h" #include "sass_types/factory.h" -Sass_Value* CustomFunctionBridge::post_process_return_value(Handle val) const { +Sass_Value* CustomFunctionBridge::post_process_return_value(v8::Local val) const { try { return SassTypes::Factory::unwrap(val)->get_sass_value(); } @@ -11,8 +11,8 @@ Sass_Value* CustomFunctionBridge::post_process_return_value(Handle val) c } } -std::vector> CustomFunctionBridge::pre_process_args(std::vector in) const { - std::vector> argv = std::vector>(); +std::vector> CustomFunctionBridge::pre_process_args(std::vector in) const { + std::vector> argv = std::vector>(); for (void* value : in) { argv.push_back(SassTypes::Factory::create(static_cast(value))->get_js_object()); diff --git a/src/custom_function_bridge.h b/src/custom_function_bridge.h index ed5bc147c..f72222931 100644 --- a/src/custom_function_bridge.h +++ b/src/custom_function_bridge.h @@ -5,15 +5,13 @@ #include #include "callback_bridge.h" -using namespace v8; - class CustomFunctionBridge : public CallbackBridge { public: - CustomFunctionBridge(NanCallback* cb, bool is_sync) : CallbackBridge(cb, is_sync) {} + CustomFunctionBridge(Nan::Callback* cb, bool is_sync) : CallbackBridge(cb, is_sync) {} private: - Sass_Value* post_process_return_value(Handle) const; - std::vector> pre_process_args(std::vector) const; + Sass_Value* post_process_return_value(v8::Local) const; + std::vector> pre_process_args(std::vector) const; }; #endif diff --git a/src/custom_importer_bridge.cpp b/src/custom_importer_bridge.cpp index db09b34ce..689bb38be 100644 --- a/src/custom_importer_bridge.cpp +++ b/src/custom_importer_bridge.cpp @@ -2,19 +2,17 @@ #include "custom_importer_bridge.h" #include "create_string.h" -SassImportList CustomImporterBridge::post_process_return_value(Handle val) const { +SassImportList CustomImporterBridge::post_process_return_value(v8::Local returned_value) const { SassImportList imports = 0; - NanScope(); - - Local returned_value = NanNew(val); + Nan::HandleScope scope; if (returned_value->IsArray()) { - Handle array = Handle::Cast(returned_value); + v8::Local array = v8::Local::Cast(returned_value); imports = sass_make_import_list(array->Length()); for (size_t i = 0; i < array->Length(); ++i) { - Local value = array->Get(static_cast(i)); + v8::Local value = Nan::Get(array, static_cast(i)).ToLocalChecked(); if (!value->IsObject()) { auto entry = sass_make_import_entry(0, 0, 0); @@ -22,10 +20,10 @@ SassImportList CustomImporterBridge::post_process_return_value(Handle val continue; } - Local object = Local::Cast(value); + v8::Local object = v8::Local::Cast(value); if (value->IsNativeError()) { - char* message = create_string(object->Get(NanNew("message"))); + char* message = create_string(Nan::Get(object, Nan::New("message").ToLocalChecked())); imports[i] = sass_make_import_entry(0, 0, 0); @@ -38,8 +36,8 @@ SassImportList CustomImporterBridge::post_process_return_value(Handle val } else if (returned_value->IsNativeError()) { imports = sass_make_import_list(1); - Local object = Local::Cast(returned_value); - char* message = create_string(object->Get(NanNew("message"))); + v8::Local object = v8::Local::Cast(returned_value); + char* message = create_string(Nan::Get(object, Nan::New("message").ToLocalChecked())); imports[0] = sass_make_import_entry(0, 0, 0); @@ -47,36 +45,42 @@ SassImportList CustomImporterBridge::post_process_return_value(Handle val } else if (returned_value->IsObject()) { imports = sass_make_import_list(1); - imports[0] = get_importer_entry(Local::Cast(returned_value)); + imports[0] = get_importer_entry(v8::Local::Cast(returned_value)); } return imports; } -Sass_Import* CustomImporterBridge::get_importer_entry(const Local& object) const { - auto returned_file = object->Get(NanNew("file")); - - if (!returned_file->IsUndefined() && !returned_file->IsString()) { +Sass_Import* CustomImporterBridge::check_returned_string(Nan::MaybeLocal value, const char *msg) const +{ + v8::Local checked; + if (value.ToLocal(&checked)) { + if (!checked->IsUndefined() && !checked->IsString()) { + goto err; + } else { + return nullptr; + } + } +err: auto entry = sass_make_import_entry(0, 0, 0); - sass_import_set_error(entry, "returned value of `file` must be a string", -1, -1); + sass_import_set_error(entry, msg, -1, -1); return entry; - } +} - auto returned_contents = object->Get(NanNew("contents")); +Sass_Import* CustomImporterBridge::get_importer_entry(const v8::Local& object) const { + auto returned_file = Nan::Get(object, Nan::New("file").ToLocalChecked()); + auto returned_contents = Nan::Get(object, Nan::New("contents").ToLocalChecked()).ToLocalChecked(); + auto returned_map = Nan::Get(object, Nan::New("map").ToLocalChecked()); + Sass_Import *err; - if (!returned_contents->IsUndefined() && !returned_contents->IsString()) { - auto entry = sass_make_import_entry(0, 0, 0); - sass_import_set_error(entry, "returned value of `contents` must be a string", -1, -1); - return entry; - } + if ((err = check_returned_string(returned_file, "returned value of `file` must be a string"))) + return err; - auto returned_map = object->Get(NanNew("map")); + if ((err = check_returned_string(returned_contents, "returned value of `contents` must be a string"))) + return err; - if (!returned_map->IsUndefined() && !returned_map->IsString()) { - auto entry = sass_make_import_entry(0, 0, 0); - sass_import_set_error(entry, "returned value of `map` must be a string", -1, -1); - return entry; - } + if ((err = check_returned_string(returned_map, "returned value of `returned_map` must be a string"))) + return err; char* path = create_string(returned_file); char* contents = create_string(returned_contents); @@ -85,11 +89,11 @@ Sass_Import* CustomImporterBridge::get_importer_entry(const Local& objec return sass_make_import_entry(path, contents, srcmap); } -std::vector> CustomImporterBridge::pre_process_args(std::vector in) const { - std::vector> out; +std::vector> CustomImporterBridge::pre_process_args(std::vector in) const { + std::vector> out; for (void* ptr : in) { - out.push_back(NanNew((char const*)ptr)); + out.push_back(Nan::New((char const*)ptr).ToLocalChecked()); } return out; diff --git a/src/custom_importer_bridge.h b/src/custom_importer_bridge.h index a906f4f4c..be24fdfe4 100644 --- a/src/custom_importer_bridge.h +++ b/src/custom_importer_bridge.h @@ -5,18 +5,17 @@ #include #include "callback_bridge.h" -using namespace v8; - typedef Sass_Import_List SassImportList; class CustomImporterBridge : public CallbackBridge { public: - CustomImporterBridge(NanCallback* cb, bool is_sync) : CallbackBridge(cb, is_sync) {} + CustomImporterBridge(Nan::Callback* cb, bool is_sync) : CallbackBridge(cb, is_sync) {} private: - SassImportList post_process_return_value(Handle) const; - Sass_Import* get_importer_entry(const Local&) const; - std::vector> pre_process_args(std::vector) const; + SassImportList post_process_return_value(v8::Local) const; + Sass_Import* check_returned_string(Nan::MaybeLocal value, const char *msg) const; + Sass_Import* get_importer_entry(const v8::Local&) const; + std::vector> pre_process_args(std::vector) const; }; #endif diff --git a/src/sass_context_wrapper.cpp b/src/sass_context_wrapper.cpp index bfa3bf943..00c0ee276 100644 --- a/src/sass_context_wrapper.cpp +++ b/src/sass_context_wrapper.cpp @@ -37,7 +37,7 @@ extern "C" { delete ctx_w->error_callback; delete ctx_w->success_callback; - NanDisposePersistent(ctx_w->result); + ctx_w->result.Reset(); free(ctx_w->include_path); free(ctx_w->linefeed); diff --git a/src/sass_context_wrapper.h b/src/sass_context_wrapper.h index 800635013..71073395b 100644 --- a/src/sass_context_wrapper.h +++ b/src/sass_context_wrapper.h @@ -14,8 +14,6 @@ extern "C" { #endif - using namespace v8; - void compile_data(struct Sass_Data_Context* dctx); void compile_file(struct Sass_File_Context* fctx); void compile_it(uv_work_t* req); @@ -41,9 +39,9 @@ extern "C" { uv_work_t request; // v8 and nan related - Persistent result; - NanCallback* error_callback; - NanCallback* success_callback; + Nan::Persistent result; + Nan::Callback* error_callback; + Nan::Callback* success_callback; std::vector> function_bridges; std::vector> importer_bridges; diff --git a/src/sass_types/boolean.cpp b/src/sass_types/boolean.cpp index a25e35f05..4dd64a679 100644 --- a/src/sass_types/boolean.cpp +++ b/src/sass_types/boolean.cpp @@ -1,11 +1,9 @@ #include #include "boolean.h" -using namespace v8; - namespace SassTypes { - Persistent Boolean::constructor; + Nan::Persistent Boolean::constructor; bool Boolean::constructor_locked = false; Boolean::Boolean(bool v) : value(v) {} @@ -15,59 +13,63 @@ namespace SassTypes return v ? instance_true : instance_false; } - Handle Boolean::get_constructor() { + v8::Local Boolean::get_constructor() { + Nan::EscapableHandleScope scope; + v8::Local conslocal; if (constructor.IsEmpty()) { - Local tpl = NanNew(New); + v8::Local tpl = Nan::New(New); - tpl->SetClassName(NanNew("SassBoolean")); + tpl->SetClassName(Nan::New("SassBoolean").ToLocalChecked()); tpl->InstanceTemplate()->SetInternalFieldCount(1); - tpl->PrototypeTemplate()->Set(NanNew("getValue"), NanNew(GetValue)->GetFunction()); + Nan::SetPrototypeTemplate(tpl, "getValue", Nan::GetFunction(Nan::New(GetValue)).ToLocalChecked()); - NanAssignPersistent(constructor, tpl->GetFunction()); + constructor.Reset(Nan::GetFunction(tpl).ToLocalChecked()); + conslocal = Nan::New(constructor); - NanAssignPersistent(get_singleton(false).js_object, NanNew(constructor)->NewInstance()); - NanSetInternalFieldPointer(NanNew(get_singleton(false).js_object), 0, &get_singleton(false)); - NanNew(constructor)->Set(NanNew("FALSE"), NanNew(get_singleton(false).js_object)); + get_singleton(false).js_object.Reset(conslocal->NewInstance()); + Nan::SetInternalFieldPointer(Nan::New(get_singleton(false).js_object), 0, &get_singleton(false)); + Nan::Set(conslocal, Nan::New("FALSE").ToLocalChecked(), Nan::New(get_singleton(false).js_object)); - NanAssignPersistent(get_singleton(true).js_object, NanNew(constructor)->NewInstance()); - NanSetInternalFieldPointer(NanNew(get_singleton(true).js_object), 0, &get_singleton(true)); - NanNew(constructor)->Set(NanNew("TRUE"), NanNew(get_singleton(true).js_object)); + get_singleton(true).js_object.Reset(conslocal->NewInstance()); + Nan::SetInternalFieldPointer(Nan::New(get_singleton(true).js_object), 0, &get_singleton(true)); + Nan::Set(conslocal, Nan::New("TRUE").ToLocalChecked(), Nan::New(get_singleton(true).js_object)); constructor_locked = true; + } else { + conslocal = Nan::New(constructor); } - return NanNew(constructor); + return scope.Escape(conslocal); } Sass_Value* Boolean::get_sass_value() { return sass_make_boolean(value); } - Local Boolean::get_js_object() { - return NanNew(this->js_object); + v8::Local Boolean::get_js_object() { + Nan::EscapableHandleScope scope; + return scope.Escape(Nan::New(this->js_object)); } NAN_METHOD(Boolean::New) { - NanScope(); - if (args.IsConstructCall()) { + if (info.IsConstructCall()) { if (constructor_locked) { - return NanThrowError(NanNew("Cannot instantiate SassBoolean")); + return Nan::ThrowError(Nan::New("Cannot instantiate SassBoolean").ToLocalChecked()); } } else { - if (args.Length() != 1 || !args[0]->IsBoolean()) { - return NanThrowError(NanNew("Expected one boolean argument")); + if (info.Length() != 1 || !info[0]->IsBoolean()) { + return Nan::ThrowError(Nan::New("Expected one boolean argument").ToLocalChecked()); } - NanReturnValue(NanNew(get_singleton(args[0]->ToBoolean()->Value()).get_js_object())); + info.GetReturnValue().Set((get_singleton(info[0]->ToBoolean()->Value()).get_js_object())); } - NanReturnUndefined(); + return; } NAN_METHOD(Boolean::GetValue) { - NanScope(); - NanReturnValue(NanNew(static_cast(Factory::unwrap(args.This()))->value)); + info.GetReturnValue().Set(Nan::New(static_cast(Factory::unwrap(info.This()))->value)); } } diff --git a/src/sass_types/boolean.h b/src/sass_types/boolean.h index 8f39745a1..ac2a254ff 100644 --- a/src/sass_types/boolean.h +++ b/src/sass_types/boolean.h @@ -7,15 +7,13 @@ namespace SassTypes { - using namespace v8; - - class Boolean : public Value { + class Boolean : public SassTypes::Value { public: static Boolean& get_singleton(bool); - static Handle get_constructor(); + static v8::Local get_constructor(); Sass_Value* get_sass_value(); - Local get_js_object(); + v8::Local get_js_object(); static NAN_METHOD(New); static NAN_METHOD(GetValue); @@ -24,9 +22,9 @@ namespace SassTypes Boolean(bool); bool value; - Persistent js_object; + Nan::Persistent js_object; - static Persistent constructor; + static Nan::Persistent constructor; static bool constructor_locked; }; } diff --git a/src/sass_types/color.cpp b/src/sass_types/color.cpp index 716f6eacb..e6d0d57a2 100644 --- a/src/sass_types/color.cpp +++ b/src/sass_types/color.cpp @@ -1,13 +1,11 @@ #include #include "color.h" -using namespace v8; - namespace SassTypes { Color::Color(Sass_Value* v) : SassValueWrapper(v) {} - Sass_Value* Color::construct(const std::vector> raw_val) { + Sass_Value* Color::construct(const std::vector> raw_val) { double a = 1.0, r = 0, g = 0, b = 0; unsigned argb; @@ -52,86 +50,82 @@ namespace SassTypes return sass_make_color(r, g, b, a); } - void Color::initPrototype(Handle proto) { - proto->Set(NanNew("getR"), NanNew(GetR)->GetFunction()); - proto->Set(NanNew("getG"), NanNew(GetG)->GetFunction()); - proto->Set(NanNew("getB"), NanNew(GetB)->GetFunction()); - proto->Set(NanNew("getA"), NanNew(GetA)->GetFunction()); - proto->Set(NanNew("setR"), NanNew(SetR)->GetFunction()); - proto->Set(NanNew("setG"), NanNew(SetG)->GetFunction()); - proto->Set(NanNew("setB"), NanNew(SetB)->GetFunction()); - proto->Set(NanNew("setA"), NanNew(SetA)->GetFunction()); + void Color::initPrototype(v8::Local proto) { + Nan::SetPrototypeMethod(proto, "getR", GetR); + Nan::SetPrototypeMethod(proto, "getG", GetG); + Nan::SetPrototypeMethod(proto, "getB", GetB); + Nan::SetPrototypeMethod(proto, "getA", GetA); + Nan::SetPrototypeMethod(proto, "setR", SetR); + Nan::SetPrototypeMethod(proto, "setG", SetG); + Nan::SetPrototypeMethod(proto, "setB", SetB); + Nan::SetPrototypeMethod(proto, "setA", SetA); } NAN_METHOD(Color::GetR) { - NanScope(); - NanReturnValue(NanNew(sass_color_get_r(unwrap(args.This())->value))); + info.GetReturnValue().Set(Nan::New(sass_color_get_r(unwrap(info.This())->value))); } NAN_METHOD(Color::GetG) { - NanScope(); - NanReturnValue(NanNew(sass_color_get_g(unwrap(args.This())->value))); + info.GetReturnValue().Set(Nan::New(sass_color_get_g(unwrap(info.This())->value))); } NAN_METHOD(Color::GetB) { - NanScope(); - NanReturnValue(NanNew(sass_color_get_b(unwrap(args.This())->value))); + info.GetReturnValue().Set(Nan::New(sass_color_get_b(unwrap(info.This())->value))); } NAN_METHOD(Color::GetA) { - NanScope(); - NanReturnValue(NanNew(sass_color_get_a(unwrap(args.This())->value))); + info.GetReturnValue().Set(Nan::New(sass_color_get_a(unwrap(info.This())->value))); } NAN_METHOD(Color::SetR) { - if (args.Length() != 1) { - return NanThrowError(NanNew("Expected just one argument")); + if (info.Length() != 1) { + return Nan::ThrowError(Nan::New("Expected just one argument").ToLocalChecked()); } - if (!args[0]->IsNumber()) { - return NanThrowError(NanNew("Supplied value should be a number")); + if (!info[0]->IsNumber()) { + return Nan::ThrowError(Nan::New("Supplied value should be a number").ToLocalChecked()); } - sass_color_set_r(unwrap(args.This())->value, args[0]->ToNumber()->Value()); - NanReturnUndefined(); + sass_color_set_r(unwrap(info.This())->value, info[0]->ToNumber()->Value()); + return; } NAN_METHOD(Color::SetG) { - if (args.Length() != 1) { - return NanThrowError(NanNew("Expected just one argument")); + if (info.Length() != 1) { + return Nan::ThrowError(Nan::New("Expected just one argument").ToLocalChecked()); } - if (!args[0]->IsNumber()) { - return NanThrowError(NanNew("Supplied value should be a number")); + if (!info[0]->IsNumber()) { + return Nan::ThrowError(Nan::New("Supplied value should be a number").ToLocalChecked()); } - sass_color_set_g(unwrap(args.This())->value, args[0]->ToNumber()->Value()); - NanReturnUndefined(); + sass_color_set_g(unwrap(info.This())->value, info[0]->ToNumber()->Value()); + return; } NAN_METHOD(Color::SetB) { - if (args.Length() != 1) { - return NanThrowError(NanNew("Expected just one argument")); + if (info.Length() != 1) { + return Nan::ThrowError(Nan::New("Expected just one argument").ToLocalChecked()); } - if (!args[0]->IsNumber()) { - return NanThrowError(NanNew("Supplied value should be a number")); + if (!info[0]->IsNumber()) { + return Nan::ThrowError(Nan::New("Supplied value should be a number").ToLocalChecked()); } - sass_color_set_b(unwrap(args.This())->value, args[0]->ToNumber()->Value()); - NanReturnUndefined(); + sass_color_set_b(unwrap(info.This())->value, info[0]->ToNumber()->Value()); + return; } NAN_METHOD(Color::SetA) { - if (args.Length() != 1) { - return NanThrowError(NanNew("Expected just one argument")); + if (info.Length() != 1) { + return Nan::ThrowError(Nan::New("Expected just one argument").ToLocalChecked()); } - if (!args[0]->IsNumber()) { - return NanThrowError(NanNew("Supplied value should be a number")); + if (!info[0]->IsNumber()) { + return Nan::ThrowError(Nan::New("Supplied value should be a number").ToLocalChecked()); } - sass_color_set_a(unwrap(args.This())->value, args[0]->ToNumber()->Value()); - NanReturnUndefined(); + sass_color_set_a(unwrap(info.This())->value, info[0]->ToNumber()->Value()); + return; } } diff --git a/src/sass_types/color.h b/src/sass_types/color.h index 441704c06..7ef10db19 100644 --- a/src/sass_types/color.h +++ b/src/sass_types/color.h @@ -6,15 +6,13 @@ namespace SassTypes { - using namespace v8; - class Color : public SassValueWrapper { public: Color(Sass_Value*); static char const* get_constructor_name() { return "SassColor"; } - static Sass_Value* construct(const std::vector>); + static Sass_Value* construct(const std::vector>); - static void initPrototype(Handle); + static void initPrototype(v8::Local); static NAN_METHOD(GetR); static NAN_METHOD(GetG); diff --git a/src/sass_types/error.cpp b/src/sass_types/error.cpp index a5ef7e426..f02dd12dc 100644 --- a/src/sass_types/error.cpp +++ b/src/sass_types/error.cpp @@ -2,13 +2,11 @@ #include "error.h" #include "../create_string.h" -using namespace v8; - namespace SassTypes { Error::Error(Sass_Value* v) : SassValueWrapper(v) {} - Sass_Value* Error::construct(const std::vector> raw_val) { + Sass_Value* Error::construct(const std::vector> raw_val) { char const* value = ""; if (raw_val.size() >= 1) { @@ -22,5 +20,5 @@ namespace SassTypes return sass_make_error(value); } - void Error::initPrototype(Handle) {} + void Error::initPrototype(v8::Local) {} } diff --git a/src/sass_types/error.h b/src/sass_types/error.h index 4163ed21b..ada3769f3 100644 --- a/src/sass_types/error.h +++ b/src/sass_types/error.h @@ -6,15 +6,13 @@ namespace SassTypes { - using namespace v8; - class Error : public SassValueWrapper { public: Error(Sass_Value*); static char const* get_constructor_name() { return "SassError"; } - static Sass_Value* construct(const std::vector>); + static Sass_Value* construct(const std::vector>); - static void initPrototype(Handle); + static void initPrototype(v8::Local); }; } diff --git a/src/sass_types/factory.cpp b/src/sass_types/factory.cpp index f119f05d7..54a2eb094 100644 --- a/src/sass_types/factory.cpp +++ b/src/sass_types/factory.cpp @@ -10,11 +10,9 @@ #include "null.h" #include "error.h" -using namespace v8; - namespace SassTypes { - Value* Factory::create(Sass_Value* v) { + SassTypes::Value* Factory::create(Sass_Value* v) { switch (sass_value_get_tag(v)) { case SASS_NUMBER: return new Number(v); @@ -45,26 +43,27 @@ namespace SassTypes } } - void Factory::initExports(Handle exports) { - Local types = NanNew(); - exports->Set(NanNew("types"), types); + void Factory::initExports(v8::Local exports) { + Nan::EscapableHandleScope scope; + v8::Local types = Nan::New(); - types->Set(NanNew("Number"), Number::get_constructor()); - types->Set(NanNew("String"), String::get_constructor()); - types->Set(NanNew("Color"), Color::get_constructor()); - types->Set(NanNew("Boolean"), Boolean::get_constructor()); - types->Set(NanNew("List"), List::get_constructor()); - types->Set(NanNew("Map"), Map::get_constructor()); - types->Set(NanNew("Null"), Null::get_constructor()); - types->Set(NanNew("Error"), Error::get_constructor()); + Nan::Set(types, Nan::New("Number").ToLocalChecked(), Number::get_constructor()); + Nan::Set(types, Nan::New("String").ToLocalChecked(), String::get_constructor()); + Nan::Set(types, Nan::New("Color").ToLocalChecked(), Color::get_constructor()); + Nan::Set(types, Nan::New("Boolean").ToLocalChecked(), Boolean::get_constructor()); + Nan::Set(types, Nan::New("List").ToLocalChecked(), List::get_constructor()); + Nan::Set(types, Nan::New("Map").ToLocalChecked(), Map::get_constructor()); + Nan::Set(types, Nan::New("Null").ToLocalChecked(), Null::get_constructor()); + Nan::Set(types, Nan::New("Error").ToLocalChecked(), Error::get_constructor()); + Nan::Set(exports, Nan::New("types").ToLocalChecked(), scope.Escape(types)); } - Value* Factory::unwrap(Handle obj) { + Value* Factory::unwrap(v8::Local obj) { // Todo: non-SassValue objects could easily fall under that condition, need to be more specific. if (!obj->IsObject() || obj->ToObject()->InternalFieldCount() != 1) { throw std::invalid_argument("A SassValue object was expected."); } - return static_cast(NanGetInternalFieldPointer(obj->ToObject(), 0)); + return static_cast(Nan::GetInternalFieldPointer(obj->ToObject(), 0)); } } diff --git a/src/sass_types/factory.h b/src/sass_types/factory.h index 25ef15219..9997312c9 100644 --- a/src/sass_types/factory.h +++ b/src/sass_types/factory.h @@ -7,15 +7,13 @@ namespace SassTypes { - using namespace v8; - // This is the guru that knows everything about instantiating the right subclass of SassTypes::Value // to wrap a given Sass_Value object. class Factory { public: - static void initExports(Handle); + static void initExports(v8::Local); static Value* create(Sass_Value*); - static Value* unwrap(Handle); + static Value* unwrap(v8::Local); }; } diff --git a/src/sass_types/list.cpp b/src/sass_types/list.cpp index b0e9b0681..0ffc228b2 100644 --- a/src/sass_types/list.cpp +++ b/src/sass_types/list.cpp @@ -1,13 +1,11 @@ #include #include "list.h" -using namespace v8; - namespace SassTypes { List::List(Sass_Value* v) : SassValueWrapper(v) {} - Sass_Value* List::construct(const std::vector> raw_val) { + Sass_Value* List::construct(const std::vector> raw_val) { size_t length = 0; bool comma = true; @@ -30,74 +28,71 @@ namespace SassTypes return sass_make_list(length, comma ? SASS_COMMA : SASS_SPACE); } - void List::initPrototype(Handle proto) { - proto->Set(NanNew("getLength"), NanNew(GetLength)->GetFunction()); - proto->Set(NanNew("getSeparator"), NanNew(GetSeparator)->GetFunction()); - proto->Set(NanNew("setSeparator"), NanNew(SetSeparator)->GetFunction()); - proto->Set(NanNew("getValue"), NanNew(GetValue)->GetFunction()); - proto->Set(NanNew("setValue"), NanNew(SetValue)->GetFunction()); + void List::initPrototype(v8::Local proto) { + Nan::SetPrototypeMethod(proto, "getLength", GetLength); + Nan::SetPrototypeMethod(proto, "getSeparator", GetSeparator); + Nan::SetPrototypeMethod(proto, "setSeparator", SetSeparator); + Nan::SetPrototypeMethod(proto, "getValue", GetValue); + Nan::SetPrototypeMethod(proto, "setValue", SetValue); } NAN_METHOD(List::GetValue) { - NanScope(); - if (args.Length() != 1) { - return NanThrowError(NanNew("Expected just one argument")); + if (info.Length() != 1) { + return Nan::ThrowError(Nan::New("Expected just one argument").ToLocalChecked()); } - if (!args[0]->IsNumber()) { - return NanThrowError(NanNew("Supplied index should be an integer")); + if (!info[0]->IsNumber()) { + return Nan::ThrowError(Nan::New("Supplied index should be an integer").ToLocalChecked()); } - Sass_Value* list = unwrap(args.This())->value; - size_t index = args[0]->ToInt32()->Value(); + Sass_Value* list = unwrap(info.This())->value; + size_t index = info[0]->ToInt32()->Value(); if (index >= sass_list_get_length(list)) { - return NanThrowError(NanNew("Out of bound index")); + return Nan::ThrowError(Nan::New("Out of bound index").ToLocalChecked()); } - NanReturnValue(Factory::create(sass_list_get_value(list, args[0]->ToInt32()->Value()))->get_js_object()); + info.GetReturnValue().Set(Factory::create(sass_list_get_value(list, info[0]->ToInt32()->Value()))->get_js_object()); } NAN_METHOD(List::SetValue) { - if (args.Length() != 2) { - return NanThrowError(NanNew("Expected two arguments")); + if (info.Length() != 2) { + return Nan::ThrowError(Nan::New("Expected two arguments").ToLocalChecked()); } - if (!args[0]->IsNumber()) { - return NanThrowError(NanNew("Supplied index should be an integer")); + if (!info[0]->IsNumber()) { + return Nan::ThrowError(Nan::New("Supplied index should be an integer").ToLocalChecked()); } - if (!args[1]->IsObject()) { - return NanThrowError(NanNew("Supplied value should be a SassValue object")); + if (!info[1]->IsObject()) { + return Nan::ThrowError(Nan::New("Supplied value should be a SassValue object").ToLocalChecked()); } - Value* sass_value = Factory::unwrap(args[1]); - sass_list_set_value(unwrap(args.This())->value, args[0]->ToInt32()->Value(), sass_value->get_sass_value()); - NanReturnUndefined(); + Value* sass_value = Factory::unwrap(info[1]); + sass_list_set_value(unwrap(info.This())->value, info[0]->ToInt32()->Value(), sass_value->get_sass_value()); + return; } NAN_METHOD(List::GetSeparator) { - NanScope(); - NanReturnValue(NanNew(sass_list_get_separator(unwrap(args.This())->value) == SASS_COMMA)); + info.GetReturnValue().Set(Nan::New(sass_list_get_separator(unwrap(info.This())->value) == SASS_COMMA)); } NAN_METHOD(List::SetSeparator) { - if (args.Length() != 1) { - return NanThrowError(NanNew("Expected just one argument")); + if (info.Length() != 1) { + return Nan::ThrowError(Nan::New("Expected just one argument").ToLocalChecked()); } - if (!args[0]->IsBoolean()) { - return NanThrowError(NanNew("Supplied value should be a boolean")); + if (!info[0]->IsBoolean()) { + return Nan::ThrowError(Nan::New("Supplied value should be a boolean").ToLocalChecked()); } - sass_list_set_separator(unwrap(args.This())->value, args[0]->ToBoolean()->Value() ? SASS_COMMA : SASS_SPACE); - NanReturnUndefined(); + sass_list_set_separator(unwrap(info.This())->value, info[0]->ToBoolean()->Value() ? SASS_COMMA : SASS_SPACE); + return; } NAN_METHOD(List::GetLength) { - NanScope(); - NanReturnValue(NanNew(sass_list_get_length(unwrap(args.This())->value))); + info.GetReturnValue().Set(Nan::New(sass_list_get_length(unwrap(info.This())->value))); } } diff --git a/src/sass_types/list.h b/src/sass_types/list.h index 8b77321c1..5f3a3aeac 100644 --- a/src/sass_types/list.h +++ b/src/sass_types/list.h @@ -6,15 +6,13 @@ namespace SassTypes { - using namespace v8; - class List : public SassValueWrapper { public: List(Sass_Value*); static char const* get_constructor_name() { return "SassList"; } - static Sass_Value* construct(const std::vector>); + static Sass_Value* construct(const std::vector>); - static void initPrototype(Handle); + static void initPrototype(v8::Local); static NAN_METHOD(GetValue); static NAN_METHOD(SetValue); diff --git a/src/sass_types/map.cpp b/src/sass_types/map.cpp index 61a01f5ee..c8683ea51 100644 --- a/src/sass_types/map.cpp +++ b/src/sass_types/map.cpp @@ -1,13 +1,11 @@ #include #include "map.h" -using namespace v8; - namespace SassTypes { Map::Map(Sass_Value* v) : SassValueWrapper(v) {} - Sass_Value* Map::construct(const std::vector> raw_val) { + Sass_Value* Map::construct(const std::vector> raw_val) { size_t length = 0; if (raw_val.size() >= 1) { @@ -21,96 +19,93 @@ namespace SassTypes return sass_make_map(length); } - void Map::initPrototype(Handle proto) { - proto->Set(NanNew("getLength"), NanNew(GetLength)->GetFunction()); - proto->Set(NanNew("getKey"), NanNew(GetKey)->GetFunction()); - proto->Set(NanNew("setKey"), NanNew(SetKey)->GetFunction()); - proto->Set(NanNew("getValue"), NanNew(GetValue)->GetFunction()); - proto->Set(NanNew("setValue"), NanNew(SetValue)->GetFunction()); + void Map::initPrototype(v8::Local proto) { + Nan::SetPrototypeMethod(proto, "getLength", GetLength); + Nan::SetPrototypeMethod(proto, "getKey", GetKey); + Nan::SetPrototypeMethod(proto, "setKey", SetKey); + Nan::SetPrototypeMethod(proto, "getValue", GetValue); + Nan::SetPrototypeMethod(proto, "setValue", SetValue); } NAN_METHOD(Map::GetValue) { - NanScope(); - if (args.Length() != 1) { - return NanThrowError(NanNew("Expected just one argument")); + if (info.Length() != 1) { + return Nan::ThrowError(Nan::New("Expected just one argument").ToLocalChecked()); } - if (!args[0]->IsNumber()) { - return NanThrowError(NanNew("Supplied index should be an integer")); + if (!info[0]->IsNumber()) { + return Nan::ThrowError(Nan::New("Supplied index should be an integer").ToLocalChecked()); } - Sass_Value* map = unwrap(args.This())->value; - size_t index = args[0]->ToInt32()->Value(); + Sass_Value* map = unwrap(info.This())->value; + size_t index = info[0]->ToInt32()->Value(); if (index >= sass_map_get_length(map)) { - return NanThrowError(NanNew("Out of bound index")); + return Nan::ThrowError(Nan::New("Out of bound index").ToLocalChecked()); } - NanReturnValue(NanNew(Factory::create(sass_map_get_value(map, args[0]->ToInt32()->Value()))->get_js_object())); + info.GetReturnValue().Set(Factory::create(sass_map_get_value(map, info[0]->ToInt32()->Value()))->get_js_object()); } NAN_METHOD(Map::SetValue) { - if (args.Length() != 2) { - return NanThrowError(NanNew("Expected two arguments")); + if (info.Length() != 2) { + return Nan::ThrowError(Nan::New("Expected two arguments").ToLocalChecked()); } - if (!args[0]->IsNumber()) { - return NanThrowError(NanNew("Supplied index should be an integer")); + if (!info[0]->IsNumber()) { + return Nan::ThrowError(Nan::New("Supplied index should be an integer").ToLocalChecked()); } - if (!args[1]->IsObject()) { - return NanThrowError(NanNew("Supplied value should be a SassValue object")); + if (!info[1]->IsObject()) { + return Nan::ThrowError(Nan::New("Supplied value should be a SassValue object").ToLocalChecked()); } - Value* sass_value = Factory::unwrap(args[1]); - sass_map_set_value(unwrap(args.This())->value, args[0]->ToInt32()->Value(), sass_value->get_sass_value()); - NanReturnUndefined(); + Value* sass_value = Factory::unwrap(info[1]); + sass_map_set_value(unwrap(info.This())->value, info[0]->ToInt32()->Value(), sass_value->get_sass_value()); + return; } NAN_METHOD(Map::GetKey) { - NanScope(); - if (args.Length() != 1) { - return NanThrowError(NanNew("Expected just one argument")); + if (info.Length() != 1) { + return Nan::ThrowError(Nan::New("Expected just one argument").ToLocalChecked()); } - if (!args[0]->IsNumber()) { - return NanThrowError(NanNew("Supplied index should be an integer")); + if (!info[0]->IsNumber()) { + return Nan::ThrowError(Nan::New("Supplied index should be an integer").ToLocalChecked()); } - Sass_Value* map = unwrap(args.This())->value; - size_t index = args[0]->ToInt32()->Value(); + Sass_Value* map = unwrap(info.This())->value; + size_t index = info[0]->ToInt32()->Value(); if (index >= sass_map_get_length(map)) { - return NanThrowError(NanNew("Out of bound index")); + return Nan::ThrowError(Nan::New("Out of bound index").ToLocalChecked()); } - NanReturnValue(Factory::create(sass_map_get_key(map, args[0]->ToInt32()->Value()))->get_js_object()); + info.GetReturnValue().Set(Factory::create(sass_map_get_key(map, info[0]->ToInt32()->Value()))->get_js_object()); } NAN_METHOD(Map::SetKey) { - if (args.Length() != 2) { - return NanThrowError(NanNew("Expected two arguments")); + if (info.Length() != 2) { + return Nan::ThrowError(Nan::New("Expected two arguments").ToLocalChecked()); } - if (!args[0]->IsNumber()) { - return NanThrowError(NanNew("Supplied index should be an integer")); + if (!info[0]->IsNumber()) { + return Nan::ThrowError(Nan::New("Supplied index should be an integer").ToLocalChecked()); } - if (!args[1]->IsObject()) { - return NanThrowError(NanNew("Supplied value should be a SassValue object")); + if (!info[1]->IsObject()) { + return Nan::ThrowError(Nan::New("Supplied value should be a SassValue object").ToLocalChecked()); } - Value* sass_value = Factory::unwrap(args[1]); - sass_map_set_key(unwrap(args.This())->value, args[0]->ToInt32()->Value(), sass_value->get_sass_value()); - NanReturnUndefined(); + Value* sass_value = Factory::unwrap(info[1]); + sass_map_set_key(unwrap(info.This())->value, info[0]->ToInt32()->Value(), sass_value->get_sass_value()); + return; } NAN_METHOD(Map::GetLength) { - NanScope(); - NanReturnValue(NanNew(sass_map_get_length(unwrap(args.This())->value))); + info.GetReturnValue().Set(Nan::New(sass_map_get_length(unwrap(info.This())->value))); } } diff --git a/src/sass_types/map.h b/src/sass_types/map.h index 3fb5c0683..26fc2286d 100644 --- a/src/sass_types/map.h +++ b/src/sass_types/map.h @@ -6,15 +6,13 @@ namespace SassTypes { - using namespace v8; - class Map : public SassValueWrapper { public: Map(Sass_Value*); static char const* get_constructor_name() { return "SassMap"; } - static Sass_Value* construct(const std::vector>); + static Sass_Value* construct(const std::vector>); - static void initPrototype(Handle); + static void initPrototype(v8::Local); static NAN_METHOD(GetValue); static NAN_METHOD(SetValue); diff --git a/src/sass_types/null.cpp b/src/sass_types/null.cpp index 8e4e21c33..4a75b8775 100644 --- a/src/sass_types/null.cpp +++ b/src/sass_types/null.cpp @@ -1,11 +1,9 @@ #include #include "null.h" -using namespace v8; - namespace SassTypes { - Persistent Null::constructor; + Nan::Persistent Null::constructor; bool Null::constructor_locked = false; Null::Null() {} @@ -15,45 +13,49 @@ namespace SassTypes return singleton_instance; } - Handle Null::get_constructor() { + v8::Local Null::get_constructor() { + Nan::EscapableHandleScope scope; + v8::Local conslocal; if (constructor.IsEmpty()) { - Local tpl = NanNew(New); + v8::Local tpl = Nan::New(New); - tpl->SetClassName(NanNew("SassNull")); + tpl->SetClassName(Nan::New("SassNull").ToLocalChecked()); tpl->InstanceTemplate()->SetInternalFieldCount(1); - NanAssignPersistent(constructor, tpl->GetFunction()); + constructor.Reset(Nan::GetFunction(tpl).ToLocalChecked()); + conslocal = Nan::New(constructor); - NanAssignPersistent(get_singleton().js_object, NanNew(constructor)->NewInstance()); - NanSetInternalFieldPointer(NanNew(get_singleton().js_object), 0, &get_singleton()); - NanNew(constructor)->Set(NanNew("NULL"), NanNew(get_singleton().js_object)); + get_singleton().js_object.Reset(conslocal->NewInstance()); + Nan::SetInternalFieldPointer(Nan::New(get_singleton().js_object), 0, &get_singleton()); + Nan::Set(conslocal, Nan::New("NULL").ToLocalChecked(), Nan::New(get_singleton().js_object)); constructor_locked = true; + } else { + conslocal = Nan::New(constructor); } - return NanNew(constructor); + return scope.Escape(conslocal); } Sass_Value* Null::get_sass_value() { return sass_make_null(); } - Local Null::get_js_object() { - return NanNew(this->js_object); + v8::Local Null::get_js_object() { + return Nan::New(this->js_object); } NAN_METHOD(Null::New) { - NanScope(); - if (args.IsConstructCall()) { + if (info.IsConstructCall()) { if (constructor_locked) { - return NanThrowError(NanNew("Cannot instantiate SassNull")); + return Nan::ThrowError(Nan::New("Cannot instantiate SassNull").ToLocalChecked()); } } else { - NanReturnValue(NanNew(get_singleton().get_js_object())); + info.GetReturnValue().Set(get_singleton().get_js_object()); } - NanReturnUndefined(); + return; } } diff --git a/src/sass_types/null.h b/src/sass_types/null.h index cb8a025b4..15b64ba09 100644 --- a/src/sass_types/null.h +++ b/src/sass_types/null.h @@ -6,24 +6,22 @@ namespace SassTypes { - using namespace v8; - - class Null : public Value { + class Null : public SassTypes::Value { public: static Null& get_singleton(); - static Handle get_constructor(); + static v8::Local get_constructor(); Sass_Value* get_sass_value(); - Local get_js_object(); + v8::Local get_js_object(); static NAN_METHOD(New); private: Null(); - Persistent js_object; + Nan::Persistent js_object; - static Persistent constructor; + static Nan::Persistent constructor; static bool constructor_locked; }; } diff --git a/src/sass_types/number.cpp b/src/sass_types/number.cpp index 268376afc..de467a2be 100644 --- a/src/sass_types/number.cpp +++ b/src/sass_types/number.cpp @@ -2,13 +2,11 @@ #include "number.h" #include "../create_string.h" -using namespace v8; - namespace SassTypes { Number::Number(Sass_Value* v) : SassValueWrapper(v) {} - Sass_Value* Number::construct(const std::vector> raw_val) { + Sass_Value* Number::construct(const std::vector> raw_val) { double value = 0; char const* unit = ""; @@ -31,48 +29,45 @@ namespace SassTypes return sass_make_number(value, unit); } - void Number::initPrototype(Handle proto) { - proto->Set(NanNew("getValue"), NanNew(GetValue)->GetFunction()); - proto->Set(NanNew("getUnit"), NanNew(GetUnit)->GetFunction()); - proto->Set(NanNew("setValue"), NanNew(SetValue)->GetFunction()); - proto->Set(NanNew("setUnit"), NanNew(SetUnit)->GetFunction()); + void Number::initPrototype(v8::Local proto) { + Nan::SetPrototypeMethod(proto, "getValue", GetValue); + Nan::SetPrototypeMethod(proto, "getUnit", GetUnit); + Nan::SetPrototypeMethod(proto, "setValue", SetValue); + Nan::SetPrototypeMethod(proto, "setUnit", SetUnit); } NAN_METHOD(Number::GetValue) { - NanScope(); - NanReturnValue(NanNew(sass_number_get_value(unwrap(args.This())->value))); + info.GetReturnValue().Set(Nan::New(sass_number_get_value(unwrap(info.This())->value))); } NAN_METHOD(Number::GetUnit) { - NanScope(); - NanReturnValue(NanNew(sass_number_get_unit(unwrap(args.This())->value))); + info.GetReturnValue().Set(Nan::New(sass_number_get_unit(unwrap(info.This())->value)).ToLocalChecked()); } NAN_METHOD(Number::SetValue) { - NanScope(); - if (args.Length() != 1) { - return NanThrowError(NanNew("Expected just one argument")); + if (info.Length() != 1) { + return Nan::ThrowError(Nan::New("Expected just one argument").ToLocalChecked()); } - if (!args[0]->IsNumber()) { - return NanThrowError(NanNew("Supplied value should be a number")); + if (!info[0]->IsNumber()) { + return Nan::ThrowError(Nan::New("Supplied value should be a number").ToLocalChecked()); } - sass_number_set_value(unwrap(args.This())->value, args[0]->ToNumber()->Value()); - NanReturnUndefined(); + sass_number_set_value(unwrap(info.This())->value, info[0]->ToNumber()->Value()); + return; } NAN_METHOD(Number::SetUnit) { - if (args.Length() != 1) { - return NanThrowError(NanNew("Expected just one argument")); + if (info.Length() != 1) { + return Nan::ThrowError(Nan::New("Expected just one argument").ToLocalChecked()); } - if (!args[0]->IsString()) { - return NanThrowError(NanNew("Supplied value should be a string")); + if (!info[0]->IsString()) { + return Nan::ThrowError(Nan::New("Supplied value should be a string").ToLocalChecked()); } - sass_number_set_unit(unwrap(args.This())->value, create_string(args[0])); - NanReturnUndefined(); + sass_number_set_unit(unwrap(info.This())->value, create_string(info[0])); + return; } } diff --git a/src/sass_types/number.h b/src/sass_types/number.h index 52bcc8bb2..b228d25fa 100644 --- a/src/sass_types/number.h +++ b/src/sass_types/number.h @@ -6,15 +6,14 @@ namespace SassTypes { - using namespace v8; class Number : public SassValueWrapper { public: Number(Sass_Value*); static char const* get_constructor_name() { return "SassNumber"; } - static Sass_Value* construct(const std::vector>); + static Sass_Value* construct(const std::vector>); - static void initPrototype(Handle); + static void initPrototype(v8::Local); static NAN_METHOD(GetValue); static NAN_METHOD(GetUnit); diff --git a/src/sass_types/sass_value_wrapper.h b/src/sass_types/sass_value_wrapper.h index edb98fdeb..69aba3e25 100644 --- a/src/sass_types/sass_value_wrapper.h +++ b/src/sass_types/sass_value_wrapper.h @@ -9,12 +9,10 @@ namespace SassTypes { - using namespace v8; - // Include this in any SassTypes::Value subclasses to handle all the heavy lifting of constructing JS // objects and wrapping sass values inside them template - class SassValueWrapper : public Value { + class SassValueWrapper : public SassTypes::Value { public: static char const* get_constructor_name() { return "SassValue"; } @@ -22,23 +20,23 @@ namespace SassTypes virtual ~SassValueWrapper(); Sass_Value* get_sass_value(); - Local get_js_object(); + v8::Local get_js_object(); - static Handle get_constructor(); - static Local get_constructor_template(); + static v8::Local get_constructor(); + static v8::Local get_constructor_template(); static NAN_METHOD(New); protected: Sass_Value* value; - static T* unwrap(Local); + static T* unwrap(v8::Local); private: - static Persistent constructor; - Persistent js_object; + static Nan::Persistent constructor; + Nan::Persistent js_object; }; template - Persistent SassValueWrapper::constructor; + Nan::Persistent SassValueWrapper::constructor; template SassValueWrapper::SassValueWrapper(Sass_Value* v) { @@ -47,7 +45,7 @@ namespace SassTypes template SassValueWrapper::~SassValueWrapper() { - NanDisposePersistent(this->js_object); + this->js_object.Reset(); sass_delete_value(this->value); } @@ -57,74 +55,64 @@ namespace SassTypes } template - Local SassValueWrapper::get_js_object() { + v8::Local SassValueWrapper::get_js_object() { if (this->js_object.IsEmpty()) { - Local wrapper = NanNew(T::get_constructor())->NewInstance(); - delete static_cast(NanGetInternalFieldPointer(wrapper, 0)); - NanSetInternalFieldPointer(wrapper, 0, this); - NanAssignPersistent(this->js_object, wrapper); + v8::Local wrapper = Nan::NewInstance(T::get_constructor()).ToLocalChecked(); + delete static_cast(Nan::GetInternalFieldPointer(wrapper, 0)); + Nan::SetInternalFieldPointer(wrapper, 0, this); + this->js_object.Reset(wrapper); } - return NanNew(this->js_object); + return Nan::New(this->js_object); } template - Local SassValueWrapper::get_constructor_template() { - Local tpl = NanNew(New); - tpl->SetClassName(NanNew(NanNew(T::get_constructor_name()))); + v8::Local SassValueWrapper::get_constructor_template() { + Nan::EscapableHandleScope scope; + v8::Local tpl = Nan::New(New); + tpl->SetClassName(Nan::New(T::get_constructor_name()).ToLocalChecked()); tpl->InstanceTemplate()->SetInternalFieldCount(1); - T::initPrototype(tpl->PrototypeTemplate()); + T::initPrototype(tpl); - return tpl; + return scope.Escape(tpl); } template - Handle SassValueWrapper::get_constructor() { + v8::Local SassValueWrapper::get_constructor() { if (constructor.IsEmpty()) { - NanAssignPersistent(constructor, T::get_constructor_template()->GetFunction()); + constructor.Reset(Nan::GetFunction(T::get_constructor_template()).ToLocalChecked()); } - return NanNew(constructor); + return Nan::New(constructor); } template NAN_METHOD(SassValueWrapper::New) { - NanScope(); - - if (!args.IsConstructCall()) { - unsigned argc = args.Length(); - std::vector> argv; - - argv.reserve(argc); - for (unsigned i = 0; i < argc; i++) { - argv.push_back(args[i]); - } + std::vector> localArgs(info.Length()); - NanReturnValue(NanNew(T::get_constructor())->NewInstance(argc, &argv[0])); + for (auto i = 0; i < info.Length(); ++i) { + localArgs[i] = info[i]; } - - std::vector> localArgs(args.Length()); - - for (auto i = 0; i < args.Length(); ++i) { - localArgs[i] = args[i]; - } - - try { - Sass_Value* value = T::construct(localArgs); - T* obj = new T(value); - sass_delete_value(value); - - NanSetInternalFieldPointer(args.This(), 0, obj); - NanAssignPersistent(obj->js_object, args.This()); - } catch (const std::exception& e) { - return NanThrowError(NanNew(e.what())); + if (info.IsConstructCall()) { + try { + Sass_Value* value = T::construct(localArgs); + T* obj = new T(value); + sass_delete_value(value); + + Nan::SetInternalFieldPointer(info.This(), 0, obj); + obj->js_object.Reset(info.This()); + } catch (const std::exception& e) { + return Nan::ThrowError(Nan::New(e.what()).ToLocalChecked()); + } + } else { + v8::Local cons = T::get_constructor(); + v8::Local inst = cons->NewInstance(info.Length(), &localArgs[0]); + info.GetReturnValue().Set(inst); } - - NanReturnUndefined(); } template - T* SassValueWrapper::unwrap(Local obj) { + T* SassValueWrapper::unwrap(v8::Local obj) { return static_cast(Factory::unwrap(obj)); } } diff --git a/src/sass_types/string.cpp b/src/sass_types/string.cpp index 267cb2a86..e9a2c452d 100644 --- a/src/sass_types/string.cpp +++ b/src/sass_types/string.cpp @@ -2,13 +2,11 @@ #include "string.h" #include "../create_string.h" -using namespace v8; - namespace SassTypes { String::String(Sass_Value* v) : SassValueWrapper(v) {} - Sass_Value* String::construct(const std::vector> raw_val) { + Sass_Value* String::construct(const std::vector> raw_val) { char const* value = ""; if (raw_val.size() >= 1) { @@ -22,26 +20,25 @@ namespace SassTypes return sass_make_string(value); } - void String::initPrototype(Handle proto) { - proto->Set(NanNew("getValue"), NanNew(GetValue)->GetFunction()); - proto->Set(NanNew("setValue"), NanNew(SetValue)->GetFunction()); + void String::initPrototype(v8::Local proto) { + Nan::SetPrototypeMethod(proto, "getValue", GetValue); + Nan::SetPrototypeMethod(proto, "setValue", SetValue); } NAN_METHOD(String::GetValue) { - NanScope(); - NanReturnValue(NanNew(sass_string_get_value(unwrap(args.This())->value))); + info.GetReturnValue().Set(Nan::New(sass_string_get_value(unwrap(info.This())->value)).ToLocalChecked()); } NAN_METHOD(String::SetValue) { - if (args.Length() != 1) { - return NanThrowError(NanNew("Expected just one argument")); + if (info.Length() != 1) { + return Nan::ThrowError(Nan::New("Expected just one argument").ToLocalChecked()); } - if (!args[0]->IsString()) { - return NanThrowError(NanNew("Supplied value should be a string")); + if (!info[0]->IsString()) { + return Nan::ThrowError(Nan::New("Supplied value should be a string").ToLocalChecked()); } - sass_string_set_value(unwrap(args.This())->value, create_string(args[0])); - NanReturnUndefined(); + sass_string_set_value(unwrap(info.This())->value, create_string(info[0])); + return; } } diff --git a/src/sass_types/string.h b/src/sass_types/string.h index 55e13f356..c7942a86d 100644 --- a/src/sass_types/string.h +++ b/src/sass_types/string.h @@ -6,15 +6,13 @@ namespace SassTypes { - using namespace v8; - class String : public SassValueWrapper { public: String(Sass_Value*); static char const* get_constructor_name() { return "SassString"; } - static Sass_Value* construct(const std::vector>); + static Sass_Value* construct(const std::vector>); - static void initPrototype(Handle); + static void initPrototype(v8::Local); static NAN_METHOD(GetValue); static NAN_METHOD(SetValue); diff --git a/src/sass_types/value.h b/src/sass_types/value.h index 86426f854..af10035d7 100644 --- a/src/sass_types/value.h +++ b/src/sass_types/value.h @@ -6,13 +6,11 @@ namespace SassTypes { - using namespace v8; - // This is the interface that all sass values must comply with class Value { public: virtual Sass_Value* get_sass_value() =0; - virtual Local get_js_object() =0; + virtual v8::Local get_js_object() =0; }; } From acd67bf4d230372fd17368aba82ff93c28e2b401 Mon Sep 17 00:00:00 2001 From: Marcin Cieslak Date: Sun, 9 Aug 2015 17:28:52 +0000 Subject: [PATCH 02/15] Nan::ReturnValue.Set() needs no Nan::New on primitive types For bool, double, [u]int32_t there is no need to wrap a returned value in Nan::New() https://github.com/nodejs/nan/blob/master/doc/methods.md#api_nan_return_value --- src/binding.cpp | 4 ++-- src/sass_types/color.cpp | 8 ++++---- src/sass_types/list.cpp | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/binding.cpp b/src/binding.cpp index 03810f0d3..51dbce010 100644 --- a/src/binding.cpp +++ b/src/binding.cpp @@ -262,7 +262,7 @@ NAN_METHOD(render_sync) { sass_free_context_wrapper(ctx_w); - info.GetReturnValue().Set(Nan::New(result == 0)); + info.GetReturnValue().Set(result == 0); } NAN_METHOD(render_file) { @@ -297,7 +297,7 @@ NAN_METHOD(render_file_sync) { free(input_path); sass_free_context_wrapper(ctx_w); - info.GetReturnValue().Set(Nan::New(result == 0)); + info.GetReturnValue().Set(result == 0); } NAN_METHOD(libsass_version) { diff --git a/src/sass_types/color.cpp b/src/sass_types/color.cpp index e6d0d57a2..c61d27636 100644 --- a/src/sass_types/color.cpp +++ b/src/sass_types/color.cpp @@ -62,19 +62,19 @@ namespace SassTypes } NAN_METHOD(Color::GetR) { - info.GetReturnValue().Set(Nan::New(sass_color_get_r(unwrap(info.This())->value))); + info.GetReturnValue().Set(sass_color_get_r(unwrap(info.This())->value)); } NAN_METHOD(Color::GetG) { - info.GetReturnValue().Set(Nan::New(sass_color_get_g(unwrap(info.This())->value))); + info.GetReturnValue().Set(sass_color_get_g(unwrap(info.This())->value)); } NAN_METHOD(Color::GetB) { - info.GetReturnValue().Set(Nan::New(sass_color_get_b(unwrap(info.This())->value))); + info.GetReturnValue().Set(sass_color_get_b(unwrap(info.This())->value)); } NAN_METHOD(Color::GetA) { - info.GetReturnValue().Set(Nan::New(sass_color_get_a(unwrap(info.This())->value))); + info.GetReturnValue().Set(sass_color_get_a(unwrap(info.This())->value)); } NAN_METHOD(Color::SetR) { diff --git a/src/sass_types/list.cpp b/src/sass_types/list.cpp index 0ffc228b2..859aa9fa4 100644 --- a/src/sass_types/list.cpp +++ b/src/sass_types/list.cpp @@ -76,7 +76,7 @@ namespace SassTypes } NAN_METHOD(List::GetSeparator) { - info.GetReturnValue().Set(Nan::New(sass_list_get_separator(unwrap(info.This())->value) == SASS_COMMA)); + info.GetReturnValue().Set(sass_list_get_separator(unwrap(info.This())->value) == SASS_COMMA); } NAN_METHOD(List::SetSeparator) { From e1191f5f3189cf29a50fa0b201e291615027c5d0 Mon Sep 17 00:00:00 2001 From: Marcin Cieslak Date: Sun, 9 Aug 2015 21:23:45 +0000 Subject: [PATCH 03/15] Use NAN_MODULE_INIT for exports, use Nan::HandleScope No need to have EscapableHandleScope, since local handle is not returned by the method - only assigned to an objects supplied by the caller. --- src/binding.cpp | 2 +- src/sass_types/factory.cpp | 6 +++--- src/sass_types/factory.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/binding.cpp b/src/binding.cpp index 51dbce010..64ce5e5fc 100644 --- a/src/binding.cpp +++ b/src/binding.cpp @@ -304,7 +304,7 @@ NAN_METHOD(libsass_version) { info.GetReturnValue().Set(Nan::New(libsass_version()).ToLocalChecked()); } -void RegisterModule(v8::Local target) { +NAN_MODULE_INIT(RegisterModule) { Nan::SetMethod(target, "render", render); Nan::SetMethod(target, "renderSync", render_sync); Nan::SetMethod(target, "renderFile", render_file); diff --git a/src/sass_types/factory.cpp b/src/sass_types/factory.cpp index 54a2eb094..aa95ebf88 100644 --- a/src/sass_types/factory.cpp +++ b/src/sass_types/factory.cpp @@ -43,8 +43,8 @@ namespace SassTypes } } - void Factory::initExports(v8::Local exports) { - Nan::EscapableHandleScope scope; + NAN_MODULE_INIT(Factory::initExports) { + Nan::HandleScope scope; v8::Local types = Nan::New(); Nan::Set(types, Nan::New("Number").ToLocalChecked(), Number::get_constructor()); @@ -55,7 +55,7 @@ namespace SassTypes Nan::Set(types, Nan::New("Map").ToLocalChecked(), Map::get_constructor()); Nan::Set(types, Nan::New("Null").ToLocalChecked(), Null::get_constructor()); Nan::Set(types, Nan::New("Error").ToLocalChecked(), Error::get_constructor()); - Nan::Set(exports, Nan::New("types").ToLocalChecked(), scope.Escape(types)); + Nan::Set(target, Nan::New("types").ToLocalChecked(), types); } Value* Factory::unwrap(v8::Local obj) { diff --git a/src/sass_types/factory.h b/src/sass_types/factory.h index 9997312c9..7a80942bd 100644 --- a/src/sass_types/factory.h +++ b/src/sass_types/factory.h @@ -11,7 +11,7 @@ namespace SassTypes // to wrap a given Sass_Value object. class Factory { public: - static void initExports(v8::Local); + static NAN_MODULE_INIT(initExports); static Value* create(Sass_Value*); static Value* unwrap(v8::Local); }; From a1395134907c6167a71487f5937869f7ca7d21b2 Mon Sep 17 00:00:00 2001 From: Marcin Cieslak Date: Sun, 9 Aug 2015 21:38:10 +0000 Subject: [PATCH 04/15] Remove unnecessary empty return; --- src/binding.cpp | 4 ---- src/callback_bridge.h | 2 -- src/sass_types/boolean.cpp | 2 -- src/sass_types/color.cpp | 4 ---- src/sass_types/list.cpp | 2 -- src/sass_types/map.cpp | 2 -- src/sass_types/null.cpp | 2 -- src/sass_types/number.cpp | 2 -- src/sass_types/string.cpp | 1 - 9 files changed, 21 deletions(-) diff --git a/src/binding.cpp b/src/binding.cpp index 64ce5e5fc..d7b725176 100644 --- a/src/binding.cpp +++ b/src/binding.cpp @@ -242,8 +242,6 @@ NAN_METHOD(render) { int status = uv_queue_work(uv_default_loop(), &ctx_w->request, compile_it, (uv_after_work_cb)MakeCallback); assert(status == 0); - - return; } NAN_METHOD(render_sync) { @@ -277,8 +275,6 @@ NAN_METHOD(render_file) { int status = uv_queue_work(uv_default_loop(), &ctx_w->request, compile_it, (uv_after_work_cb)MakeCallback); assert(status == 0); - - return; } NAN_METHOD(render_file_sync) { diff --git a/src/callback_bridge.h b/src/callback_bridge.h index 7fe1366ea..e93c99a66 100644 --- a/src/callback_bridge.h +++ b/src/callback_bridge.h @@ -135,8 +135,6 @@ NAN_METHOD(CallbackBridge::ReturnCallback) { if (try_catch.HasCaught()) { Nan::FatalException(try_catch); } - - return; } template diff --git a/src/sass_types/boolean.cpp b/src/sass_types/boolean.cpp index 4dd64a679..06009664e 100644 --- a/src/sass_types/boolean.cpp +++ b/src/sass_types/boolean.cpp @@ -65,8 +65,6 @@ namespace SassTypes info.GetReturnValue().Set((get_singleton(info[0]->ToBoolean()->Value()).get_js_object())); } - - return; } NAN_METHOD(Boolean::GetValue) { diff --git a/src/sass_types/color.cpp b/src/sass_types/color.cpp index c61d27636..1ada4af09 100644 --- a/src/sass_types/color.cpp +++ b/src/sass_types/color.cpp @@ -87,7 +87,6 @@ namespace SassTypes } sass_color_set_r(unwrap(info.This())->value, info[0]->ToNumber()->Value()); - return; } NAN_METHOD(Color::SetG) { @@ -100,7 +99,6 @@ namespace SassTypes } sass_color_set_g(unwrap(info.This())->value, info[0]->ToNumber()->Value()); - return; } NAN_METHOD(Color::SetB) { @@ -113,7 +111,6 @@ namespace SassTypes } sass_color_set_b(unwrap(info.This())->value, info[0]->ToNumber()->Value()); - return; } NAN_METHOD(Color::SetA) { @@ -126,6 +123,5 @@ namespace SassTypes } sass_color_set_a(unwrap(info.This())->value, info[0]->ToNumber()->Value()); - return; } } diff --git a/src/sass_types/list.cpp b/src/sass_types/list.cpp index 859aa9fa4..f4bf69985 100644 --- a/src/sass_types/list.cpp +++ b/src/sass_types/list.cpp @@ -72,7 +72,6 @@ namespace SassTypes Value* sass_value = Factory::unwrap(info[1]); sass_list_set_value(unwrap(info.This())->value, info[0]->ToInt32()->Value(), sass_value->get_sass_value()); - return; } NAN_METHOD(List::GetSeparator) { @@ -89,7 +88,6 @@ namespace SassTypes } sass_list_set_separator(unwrap(info.This())->value, info[0]->ToBoolean()->Value() ? SASS_COMMA : SASS_SPACE); - return; } NAN_METHOD(List::GetLength) { diff --git a/src/sass_types/map.cpp b/src/sass_types/map.cpp index c8683ea51..d7e9f381d 100644 --- a/src/sass_types/map.cpp +++ b/src/sass_types/map.cpp @@ -63,7 +63,6 @@ namespace SassTypes Value* sass_value = Factory::unwrap(info[1]); sass_map_set_value(unwrap(info.This())->value, info[0]->ToInt32()->Value(), sass_value->get_sass_value()); - return; } NAN_METHOD(Map::GetKey) { @@ -102,7 +101,6 @@ namespace SassTypes Value* sass_value = Factory::unwrap(info[1]); sass_map_set_key(unwrap(info.This())->value, info[0]->ToInt32()->Value(), sass_value->get_sass_value()); - return; } NAN_METHOD(Map::GetLength) { diff --git a/src/sass_types/null.cpp b/src/sass_types/null.cpp index 4a75b8775..7f317643e 100644 --- a/src/sass_types/null.cpp +++ b/src/sass_types/null.cpp @@ -55,7 +55,5 @@ namespace SassTypes else { info.GetReturnValue().Set(get_singleton().get_js_object()); } - - return; } } diff --git a/src/sass_types/number.cpp b/src/sass_types/number.cpp index de467a2be..55986d323 100644 --- a/src/sass_types/number.cpp +++ b/src/sass_types/number.cpp @@ -55,7 +55,6 @@ namespace SassTypes } sass_number_set_value(unwrap(info.This())->value, info[0]->ToNumber()->Value()); - return; } NAN_METHOD(Number::SetUnit) { @@ -68,6 +67,5 @@ namespace SassTypes } sass_number_set_unit(unwrap(info.This())->value, create_string(info[0])); - return; } } diff --git a/src/sass_types/string.cpp b/src/sass_types/string.cpp index e9a2c452d..5140b0561 100644 --- a/src/sass_types/string.cpp +++ b/src/sass_types/string.cpp @@ -39,6 +39,5 @@ namespace SassTypes } sass_string_set_value(unwrap(info.This())->value, create_string(info[0])); - return; } } From 7d62f6876b0192f77bb47d265a797ba06543d1f4 Mon Sep 17 00:00:00 2001 From: Marcin Cieslak Date: Sun, 9 Aug 2015 22:00:06 +0000 Subject: [PATCH 05/15] Use As<>() instead of Cast() where appropriate --- src/binding.cpp | 6 +++--- src/custom_importer_bridge.cpp | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/binding.cpp b/src/binding.cpp index d7b725176..08d6e3ca4 100644 --- a/src/binding.cpp +++ b/src/binding.cpp @@ -105,7 +105,7 @@ void ExtractOptions(v8::Local options, void* cptr, sass_context_wrap v8::Local importer_callback = Nan::Get(options, Nan::New("importer").ToLocalChecked()).ToLocalChecked(); if (importer_callback->IsFunction()) { - v8::Local importer = v8::Local::Cast(importer_callback); + v8::Local importer = importer_callback.As(); auto bridge = std::make_shared(new Nan::Callback(importer), ctx_w->is_sync); ctx_w->importer_bridges.push_back(bridge); @@ -115,7 +115,7 @@ void ExtractOptions(v8::Local options, void* cptr, sass_context_wrap sass_option_set_c_importers(sass_options, c_importers); } else if (importer_callback->IsArray()) { - v8::Local importers = v8::Local::Cast(importer_callback); + v8::Local importers = importer_callback.As(); Sass_Importer_List c_importers = sass_make_importer_list(importers->Length()); for (size_t i = 0; i < importers->Length(); ++i) { @@ -133,7 +133,7 @@ void ExtractOptions(v8::Local options, void* cptr, sass_context_wrap v8::Local custom_functions = Nan::Get(options, Nan::New("functions").ToLocalChecked()).ToLocalChecked(); if (custom_functions->IsObject()) { - v8::Local functions = v8::Local::Cast(custom_functions); + v8::Local functions = custom_functions.As(); v8::Local signatures = Nan::GetOwnPropertyNames(functions).ToLocalChecked(); unsigned num_signatures = signatures->Length(); Sass_Function_List fn_list = sass_make_function_list(num_signatures); diff --git a/src/custom_importer_bridge.cpp b/src/custom_importer_bridge.cpp index 689bb38be..a17aa6b59 100644 --- a/src/custom_importer_bridge.cpp +++ b/src/custom_importer_bridge.cpp @@ -7,7 +7,7 @@ SassImportList CustomImporterBridge::post_process_return_value(v8::LocalIsArray()) { - v8::Local array = v8::Local::Cast(returned_value); + v8::Local array = returned_value.As(); imports = sass_make_import_list(array->Length()); @@ -20,7 +20,7 @@ SassImportList CustomImporterBridge::post_process_return_value(v8::Local object = v8::Local::Cast(value); + v8::Local object = value.As(); if (value->IsNativeError()) { char* message = create_string(Nan::Get(object, Nan::New("message").ToLocalChecked())); @@ -36,7 +36,7 @@ SassImportList CustomImporterBridge::post_process_return_value(v8::LocalIsNativeError()) { imports = sass_make_import_list(1); - v8::Local object = v8::Local::Cast(returned_value); + v8::Local object = returned_value.As(); char* message = create_string(Nan::Get(object, Nan::New("message").ToLocalChecked())); imports[0] = sass_make_import_entry(0, 0, 0); @@ -45,7 +45,7 @@ SassImportList CustomImporterBridge::post_process_return_value(v8::LocalIsObject()) { imports = sass_make_import_list(1); - imports[0] = get_importer_entry(v8::Local::Cast(returned_value)); + imports[0] = get_importer_entry(returned_value.As()); } return imports; From 9cadef6ff236a6552815beacbf72fc931c08e2cd Mon Sep 17 00:00:00 2001 From: Marcin Cieslak Date: Wed, 12 Aug 2015 16:32:43 +0000 Subject: [PATCH 06/15] Robust check of provided JS options Use Nan::To instead of ->ToType() to convert caller supplied objects in renderXXX functions. Verify that provided options, options.result and options.result.stats are all valid objects provided by the caller. Throw TypeException otherwise. Introduce low-level tests that invoke C++ function directly, without additional JavaScript wrappers. --- src/binding.cpp | 75 +++++++++++++++++++++++++------------ test/api.js | 3 ++ test/lowlevel.js | 97 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 151 insertions(+), 24 deletions(-) create mode 100644 test/lowlevel.js diff --git a/src/binding.cpp b/src/binding.cpp index 08d6e3ca4..ab5fa5faa 100644 --- a/src/binding.cpp +++ b/src/binding.cpp @@ -37,12 +37,21 @@ union Sass_Value* sass_custom_function(const union Sass_Value* s_args, Sass_Func } } -void ExtractOptions(v8::Local options, void* cptr, sass_context_wrapper* ctx_w, bool is_file, bool is_sync) { +int ExtractOptions(v8::Local options, void* cptr, sass_context_wrapper* ctx_w, bool is_file, bool is_sync) { Nan::HandleScope scope; struct Sass_Context* ctx; - ctx_w->result.Reset(Nan::Get(options, Nan::New("result").ToLocalChecked()).ToLocalChecked()->ToObject()); + v8::Local result_ = Nan::Get( + options, + Nan::New("result").ToLocalChecked() + ).ToLocalChecked(); + if (!result_->IsObject()) { + Nan::ThrowTypeError("\"result\" element is not an object"); + return -1; + } + + ctx_w->result.Reset(result_.As()); if (is_file) { ctx_w->fctx = (struct Sass_File_Context*) cptr; @@ -151,6 +160,7 @@ void ExtractOptions(v8::Local options, void* cptr, sass_context_wrap sass_option_set_c_functions(sass_options, fn_list); } + return 0; } void GetStats(sass_context_wrapper* ctx_w, Sass_Context* ctx) { @@ -165,7 +175,22 @@ void GetStats(sass_context_wrapper* ctx_w, Sass_Context* ctx) { } } - Nan::Set(Nan::Get(Nan::New(ctx_w->result), Nan::New("stats").ToLocalChecked()).ToLocalChecked()->ToObject(), Nan::New("includedFiles").ToLocalChecked(), arr); + v8::Local result = Nan::New(ctx_w->result); + assert(result->IsObject()); + + v8::Local stats = Nan::Get( + result, + Nan::New("stats").ToLocalChecked() + ).ToLocalChecked(); + if (stats->IsObject()) { + Nan::Set( + stats.As(), + Nan::New("includedFiles").ToLocalChecked(), + arr + ); + } else { + Nan::ThrowTypeError("\"result.stats\" element is not an object"); + } } int GetResult(sass_context_wrapper* ctx_w, Sass_Context* ctx, bool is_sync = false) { @@ -175,6 +200,7 @@ int GetResult(sass_context_wrapper* ctx_w, Sass_Context* ctx, bool is_sync = fal int status = sass_context_get_error_status(ctx); result = Nan::New(ctx_w->result); + assert(result->IsObject()); if (status == 0) { const char* css = sass_context_get_output_string(ctx); @@ -232,63 +258,64 @@ void MakeCallback(uv_work_t* req) { NAN_METHOD(render) { - v8::Local options = info[0]->ToObject(); + v8::Local options = Nan::To(info[0]).ToLocalChecked(); char* source_string = create_string(Nan::Get(options, Nan::New("data").ToLocalChecked())); struct Sass_Data_Context* dctx = sass_make_data_context(source_string); sass_context_wrapper* ctx_w = sass_make_context_wrapper(); - ExtractOptions(options, dctx, ctx_w, false, false); + if (ExtractOptions(options, dctx, ctx_w, false, false) >= 0) { - int status = uv_queue_work(uv_default_loop(), &ctx_w->request, compile_it, (uv_after_work_cb)MakeCallback); + int status = uv_queue_work(uv_default_loop(), &ctx_w->request, compile_it, (uv_after_work_cb)MakeCallback); - assert(status == 0); + assert(status == 0); + } } NAN_METHOD(render_sync) { - v8::Local options = info[0]->ToObject(); + v8::Local options = Nan::To(info[0]).ToLocalChecked(); char* source_string = create_string(Nan::Get(options, Nan::New("data").ToLocalChecked())); struct Sass_Data_Context* dctx = sass_make_data_context(source_string); struct Sass_Context* ctx = sass_data_context_get_context(dctx); sass_context_wrapper* ctx_w = sass_make_context_wrapper(); + int result = -1; - ExtractOptions(options, dctx, ctx_w, false, true); - - compile_data(dctx); - - int result = GetResult(ctx_w, ctx, true); + if ((result = ExtractOptions(options, dctx, ctx_w, false, true)) >= 0) { + compile_data(dctx); + result = GetResult(ctx_w, ctx, true); + } sass_free_context_wrapper(ctx_w); - info.GetReturnValue().Set(result == 0); } NAN_METHOD(render_file) { - v8::Local options = info[0]->ToObject(); + v8::Local options = Nan::To(info[0]).ToLocalChecked(); char* input_path = create_string(Nan::Get(options, Nan::New("file").ToLocalChecked())); struct Sass_File_Context* fctx = sass_make_file_context(input_path); sass_context_wrapper* ctx_w = sass_make_context_wrapper(); - ExtractOptions(options, fctx, ctx_w, true, false); - - int status = uv_queue_work(uv_default_loop(), &ctx_w->request, compile_it, (uv_after_work_cb)MakeCallback); + if (ExtractOptions(options, fctx, ctx_w, true, false) >= 0) { - assert(status == 0); + int status = uv_queue_work(uv_default_loop(), &ctx_w->request, compile_it, (uv_after_work_cb)MakeCallback); + assert(status == 0); + } } NAN_METHOD(render_file_sync) { - v8::Local options = info[0]->ToObject(); + v8::Local options = Nan::To(info[0]).ToLocalChecked(); char* input_path = create_string(Nan::Get(options, Nan::New("file").ToLocalChecked())); struct Sass_File_Context* fctx = sass_make_file_context(input_path); struct Sass_Context* ctx = sass_file_context_get_context(fctx); sass_context_wrapper* ctx_w = sass_make_context_wrapper(); + int result = -1; - ExtractOptions(options, fctx, ctx_w, true, true); - compile_file(fctx); - - int result = GetResult(ctx_w, ctx, true); + if ((result = ExtractOptions(options, fctx, ctx_w, true, true)) >= 0) { + compile_file(fctx); + result = GetResult(ctx_w, ctx, true); + }; free(input_path); sass_free_context_wrapper(ctx_w); diff --git a/test/api.js b/test/api.js index 05bbc865a..11341540d 100644 --- a/test/api.js +++ b/test/api.js @@ -1031,6 +1031,9 @@ describe('api', function() { }); it('should throw error for bad input', function(done) { + assert.throws(function() { + sass.renderSync('somestring'); + }); assert.throws(function() { sass.renderSync({ data: '#navbar width 80%;' }); }); diff --git a/test/lowlevel.js b/test/lowlevel.js new file mode 100644 index 000000000..868e864d6 --- /dev/null +++ b/test/lowlevel.js @@ -0,0 +1,97 @@ +process.env.NODESASS_COV ? require('../lib-cov') : require('../lib'); + +var assert = require('assert'), + binding = require(process.sass.binaryPath); + +describe('lowlevel', function() { + it('fail with options not an object', function(done) { + var options = 2; + assert.throws(function() { + binding.renderSync(options); + }, /"result" element is not an object/); + done(); + }); + + it('fail with options.result not provided', function(done) { + var options = { data: 'div { width: 10px; } ', + sourceComments: false, + file: null, + outFile: null, + includePaths: '', + precision: 5, + sourceMap: null, + style: 0, + indentWidth: 2, + indentType: 0, + linefeed: '\n' }; + + assert.throws(function() { + binding.renderSync(options); + }, /"result" element is not an object/); + done(); + }); + + + it('fail with options.result not an object', function(done) { + var options = { data: 'div { width: 10px; } ', + sourceComments: false, + file: null, + outFile: null, + includePaths: '', + precision: 5, + sourceMap: null, + style: 0, + indentWidth: 2, + indentType: 0, + linefeed: '\n', + result: 2 }; + + assert.throws(function() { + binding.renderSync(options); + }, /"result" element is not an object/); + done(); + }); + + + it('fail with options.result.stats not provided', function(done) { + + var options = { data: 'div { width: 10px; } ', + sourceComments: false, + file: null, + outFile: null, + includePaths: '', + precision: 5, + sourceMap: null, + style: 0, + indentWidth: 2, + indentType: 0, + linefeed: '\n', + result: {} }; + + assert.throws(function() { + binding.renderSync(options); + }, /"result.stats" element is not an object/); + done(); + }); + + it('fail with options.result.stats not an object', function(done) { + + var options = { data: 'div { width: 10px; } ', + sourceComments: false, + file: null, + outFile: null, + includePaths: '', + precision: 5, + sourceMap: null, + style: 0, + indentWidth: 2, + indentType: 0, + linefeed: '\n', + result: { stats: 2 } }; + + assert.throws(function() { + binding.renderSync(options); + }, /"result.stats" element is not an object/); + done(); + }); +}); // lowlevel From 645ee72885b40cf02f75b8d9533ba223f19874e3 Mon Sep 17 00:00:00 2001 From: Marcin Cieslak Date: Tue, 18 Aug 2015 23:25:32 +0000 Subject: [PATCH 07/15] Use Nan::NewInstance() for constructors nan 2.0.1 required due to introduction of Nan::NewInstance(v8::Local, int, v8::Local) constructor: https://github.com/nodejs/nan/commit/29450ed1670051613ffea9dd3f980f8685feceb4 --- package.json | 2 +- src/sass_types/boolean.cpp | 8 ++++---- src/sass_types/null.cpp | 6 +++--- src/sass_types/sass_value_wrapper.h | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index b1f528b41..a99df8ba3 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ "glob": "^5.0.13", "meow": "^3.3.0", "mkdirp": "^0.5.1", - "nan": "^2.0.0", + "nan": "^2.0.1", "npmconf": "^2.1.2", "pangyp": "^2.2.1", "request": "^2.58.0", diff --git a/src/sass_types/boolean.cpp b/src/sass_types/boolean.cpp index 06009664e..6a8677e1c 100644 --- a/src/sass_types/boolean.cpp +++ b/src/sass_types/boolean.cpp @@ -23,14 +23,14 @@ namespace SassTypes tpl->InstanceTemplate()->SetInternalFieldCount(1); Nan::SetPrototypeTemplate(tpl, "getValue", Nan::GetFunction(Nan::New(GetValue)).ToLocalChecked()); - constructor.Reset(Nan::GetFunction(tpl).ToLocalChecked()); - conslocal = Nan::New(constructor); + conslocal = Nan::GetFunction(tpl).ToLocalChecked(); + constructor.Reset(conslocal); - get_singleton(false).js_object.Reset(conslocal->NewInstance()); + get_singleton(false).js_object.Reset(Nan::NewInstance(conslocal).ToLocalChecked()); Nan::SetInternalFieldPointer(Nan::New(get_singleton(false).js_object), 0, &get_singleton(false)); Nan::Set(conslocal, Nan::New("FALSE").ToLocalChecked(), Nan::New(get_singleton(false).js_object)); - get_singleton(true).js_object.Reset(conslocal->NewInstance()); + get_singleton(true).js_object.Reset(Nan::NewInstance(conslocal).ToLocalChecked()); Nan::SetInternalFieldPointer(Nan::New(get_singleton(true).js_object), 0, &get_singleton(true)); Nan::Set(conslocal, Nan::New("TRUE").ToLocalChecked(), Nan::New(get_singleton(true).js_object)); diff --git a/src/sass_types/null.cpp b/src/sass_types/null.cpp index 7f317643e..24430f856 100644 --- a/src/sass_types/null.cpp +++ b/src/sass_types/null.cpp @@ -22,10 +22,10 @@ namespace SassTypes tpl->SetClassName(Nan::New("SassNull").ToLocalChecked()); tpl->InstanceTemplate()->SetInternalFieldCount(1); - constructor.Reset(Nan::GetFunction(tpl).ToLocalChecked()); - conslocal = Nan::New(constructor); + conslocal = Nan::GetFunction(tpl).ToLocalChecked(); + constructor.Reset(conslocal); - get_singleton().js_object.Reset(conslocal->NewInstance()); + get_singleton().js_object.Reset(Nan::NewInstance(conslocal).ToLocalChecked()); Nan::SetInternalFieldPointer(Nan::New(get_singleton().js_object), 0, &get_singleton()); Nan::Set(conslocal, Nan::New("NULL").ToLocalChecked(), Nan::New(get_singleton().js_object)); diff --git a/src/sass_types/sass_value_wrapper.h b/src/sass_types/sass_value_wrapper.h index 69aba3e25..4e42a95db 100644 --- a/src/sass_types/sass_value_wrapper.h +++ b/src/sass_types/sass_value_wrapper.h @@ -106,7 +106,7 @@ namespace SassTypes } } else { v8::Local cons = T::get_constructor(); - v8::Local inst = cons->NewInstance(info.Length(), &localArgs[0]); + v8::Local inst = Nan::NewInstance(cons, info.Length(), &localArgs[0]).ToLocalChecked(); info.GetReturnValue().Set(inst); } } From 9a8f9056f01943f0c7120df3c7b244d242591d4a Mon Sep 17 00:00:00 2001 From: Marcin Cieslak Date: Tue, 18 Aug 2015 23:33:42 +0000 Subject: [PATCH 08/15] No need for escapable scope in Boolean::get_js_object() --- src/sass_types/boolean.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/sass_types/boolean.cpp b/src/sass_types/boolean.cpp index 6a8677e1c..a8852c5f5 100644 --- a/src/sass_types/boolean.cpp +++ b/src/sass_types/boolean.cpp @@ -47,8 +47,7 @@ namespace SassTypes } v8::Local Boolean::get_js_object() { - Nan::EscapableHandleScope scope; - return scope.Escape(Nan::New(this->js_object)); + return Nan::New(this->js_object); } NAN_METHOD(Boolean::New) { From f129ff39a51ece39c6275634ab9377b5de1d0fa9 Mon Sep 17 00:00:00 2001 From: Marcin Cieslak Date: Tue, 18 Aug 2015 23:36:25 +0000 Subject: [PATCH 09/15] bridge operator() does not need escapable scope The value is not returned, it is passed on to another funcion. --- src/callback_bridge.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/callback_bridge.h b/src/callback_bridge.h index e93c99a66..51f43d03a 100644 --- a/src/callback_bridge.h +++ b/src/callback_bridge.h @@ -81,12 +81,12 @@ template T CallbackBridge::operator()(std::vector argv) { // argv.push_back(wrapper); if (this->is_sync) { - Nan::EscapableHandleScope scope; + Nan::HandleScope scope; std::vector> argv_v8 = pre_process_args(argv); argv_v8.push_back(Nan::New(wrapper)); return this->post_process_return_value( - scope.Escape(this->callback->Call(argv_v8.size(), &argv_v8[0])) + this->callback->Call(argv_v8.size(), &argv_v8[0]) ); } From 8420fd9d8812376cc785a30b52c7cdfbe41566e8 Mon Sep 17 00:00:00 2001 From: Marcin Cieslak Date: Wed, 19 Aug 2015 00:02:08 +0000 Subject: [PATCH 10/15] Add comments to indicate V8 context --- src/callback_bridge.h | 61 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 51 insertions(+), 10 deletions(-) diff --git a/src/callback_bridge.h b/src/callback_bridge.h index 51f43d03a..b243f2e77 100644 --- a/src/callback_bridge.h +++ b/src/callback_bridge.h @@ -55,7 +55,10 @@ Nan::Persistent CallbackBridge::wrapper_constructor; template CallbackBridge::CallbackBridge(Nan::Callback* callback, bool is_sync) : callback(callback), is_sync(is_sync) { - // This assumes the main thread will be the one instantiating the bridge + /* + * This is invoked from the main JavaScript thread. + * V8 context is available. + */ if (!is_sync) { this->async = new uv_async_t; this->async->data = (void*) this; @@ -81,6 +84,14 @@ template T CallbackBridge::operator()(std::vector argv) { // argv.push_back(wrapper); if (this->is_sync) { + /* + * This is invoked from the main JavaScript thread. + * V8 context is available. + * + * Establish Local<> scope for all functions + * from types invoked by pre_process_args() and + * post_process_args(). + */ Nan::HandleScope scope; std::vector> argv_v8 = pre_process_args(argv); argv_v8.push_back(Nan::New(wrapper)); @@ -88,22 +99,45 @@ T CallbackBridge::operator()(std::vector argv) { return this->post_process_return_value( this->callback->Call(argv_v8.size(), &argv_v8[0]) ); + } else { + /* + * This is invoked from the worker thread. + * No V8 context and functions available. + * Just wait for response from asynchronously + * scheduled JavaScript code + * + * XXX Issue #1048: We block here even if the + * event loop stops and the callback + * would never be executed. + * XXX Issue #857: By waiting here we occupy + * one of the threads taken from the + * uv threadpool. Might deadlock if + * async I/O executed from JavaScript callbacks. + */ + this->argv = argv; + + std::unique_lock lock(this->cv_mutex); + this->has_returned = false; + uv_async_send(this->async); + this->condition_variable.wait(lock, [this] { return this->has_returned; }); + + return this->return_value; } - - this->argv = argv; - - std::unique_lock lock(this->cv_mutex); - this->has_returned = false; - uv_async_send(this->async); - this->condition_variable.wait(lock, [this] { return this->has_returned; }); - - return this->return_value; } template void CallbackBridge::dispatched_async_uv_callback(uv_async_t *req) { CallbackBridge* bridge = static_cast(req->data); + /* + * Function scheduled via uv_async mechanism, therefore + * it is invoked from the main JavaScript thread. + * V8 context is available. + * + * Establish Local<> scope for all functions + * from types invoked by pre_process_args() and + * post_process_args(). + */ Nan::HandleScope scope; Nan::TryCatch try_catch; @@ -120,6 +154,13 @@ void CallbackBridge::dispatched_async_uv_callback(uv_async_t *req) { template NAN_METHOD(CallbackBridge::ReturnCallback) { + /* + * Callback function invoked by the user code. + * It is invoked from the main JavaScript thread. + * V8 context is available. + * + * Implicit Local<> handle scope created by NAN_METHOD(.) + */ CallbackBridge* bridge = static_cast*>(Nan::GetInternalFieldPointer(info.This(), 0)); Nan::TryCatch try_catch; From 4ed4739de0f5fb2bf8bd43cba6d06c48727369fb Mon Sep 17 00:00:00 2001 From: Marcin Cieslak Date: Wed, 19 Aug 2015 00:17:43 +0000 Subject: [PATCH 11/15] Add explicit Local<> scope for wrapper construction --- src/callback_bridge.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/callback_bridge.h b/src/callback_bridge.h index b243f2e77..f39d261b7 100644 --- a/src/callback_bridge.h +++ b/src/callback_bridge.h @@ -59,6 +59,7 @@ CallbackBridge::CallbackBridge(Nan::Callback* callback, bool is_sync) : ca * This is invoked from the main JavaScript thread. * V8 context is available. */ + Nan::HandleScope scope; if (!is_sync) { this->async = new uv_async_t; this->async->data = (void*) this; @@ -180,6 +181,7 @@ NAN_METHOD(CallbackBridge::ReturnCallback) { template Nan::MaybeLocal CallbackBridge::get_wrapper_constructor() { + /* Uses handle scope created in the CallbackBridge constructor */ if (wrapper_constructor.IsEmpty()) { v8::Local tpl = Nan::New(New); tpl->SetClassName(Nan::New("CallbackBridge").ToLocalChecked()); From bf9f6ec2f8d214aa2685a5c2e6ed01047f0b3996 Mon Sep 17 00:00:00 2001 From: Marcin Cieslak Date: Wed, 19 Aug 2015 01:02:09 +0000 Subject: [PATCH 12/15] Change obj->XxxValue() to Nan::To() in binding.cpp --- src/binding.cpp | 26 +++++++++++++++++--------- test/lowlevel.js | 20 ++++++++++++++++++++ 2 files changed, 37 insertions(+), 9 deletions(-) diff --git a/src/binding.cpp b/src/binding.cpp index ab5fa5faa..00b0fb04a 100644 --- a/src/binding.cpp +++ b/src/binding.cpp @@ -82,13 +82,21 @@ int ExtractOptions(v8::Local options, void* cptr, sass_context_wrapp sass_option_set_input_path(sass_options, ctx_w->file); } - int indent_len = Nan::Get(options, Nan::New("indentWidth").ToLocalChecked()).ToLocalChecked()->Int32Value(); + int indent_len = Nan::To( + Nan::Get( + options, + Nan::New("indentWidth").ToLocalChecked() + ).ToLocalChecked()).FromJust(); ctx_w->indent = (char*)malloc(indent_len + 1); strcpy(ctx_w->indent, std::string( indent_len, - Nan::Get(options, Nan::New("indentType").ToLocalChecked()).ToLocalChecked()->Int32Value() == 1 ? '\t' : ' ' + Nan::To( + Nan::Get( + options, + Nan::New("indentType").ToLocalChecked() + ).ToLocalChecked()).FromJust() == 1 ? '\t' : ' ' ).c_str()); ctx_w->linefeed = create_string(Nan::Get(options, Nan::New("linefeed").ToLocalChecked())); @@ -98,16 +106,16 @@ int ExtractOptions(v8::Local options, void* cptr, sass_context_wrapp ctx_w->source_map_root = create_string(Nan::Get(options, Nan::New("sourceMapRoot").ToLocalChecked())); sass_option_set_output_path(sass_options, ctx_w->out_file); - sass_option_set_output_style(sass_options, (Sass_Output_Style)Nan::Get(options, Nan::New("style").ToLocalChecked()).ToLocalChecked()->Int32Value()); - sass_option_set_is_indented_syntax_src(sass_options, Nan::Get(options, Nan::New("indentedSyntax").ToLocalChecked()).ToLocalChecked()->BooleanValue()); - sass_option_set_source_comments(sass_options, Nan::Get(options, Nan::New("sourceComments").ToLocalChecked()).ToLocalChecked()->BooleanValue()); - sass_option_set_omit_source_map_url(sass_options, Nan::Get(options, Nan::New("omitSourceMapUrl").ToLocalChecked()).ToLocalChecked()->BooleanValue()); - sass_option_set_source_map_embed(sass_options, Nan::Get(options, Nan::New("sourceMapEmbed").ToLocalChecked()).ToLocalChecked()->BooleanValue()); - sass_option_set_source_map_contents(sass_options, Nan::Get(options, Nan::New("sourceMapContents").ToLocalChecked()).ToLocalChecked()->BooleanValue()); + sass_option_set_output_style(sass_options, (Sass_Output_Style)Nan::To(Nan::Get(options, Nan::New("style").ToLocalChecked()).ToLocalChecked()).FromJust()); + sass_option_set_is_indented_syntax_src(sass_options, Nan::To(Nan::Get(options, Nan::New("indentedSyntax").ToLocalChecked()).ToLocalChecked()).FromJust()); + sass_option_set_source_comments(sass_options, Nan::To(Nan::Get(options, Nan::New("sourceComments").ToLocalChecked()).ToLocalChecked()).FromJust()); + sass_option_set_omit_source_map_url(sass_options, Nan::To(Nan::Get(options, Nan::New("omitSourceMapUrl").ToLocalChecked()).ToLocalChecked()).FromJust()); + sass_option_set_source_map_embed(sass_options, Nan::To(Nan::Get(options, Nan::New("sourceMapEmbed").ToLocalChecked()).ToLocalChecked()).FromJust()); + sass_option_set_source_map_contents(sass_options, Nan::To(Nan::Get(options, Nan::New("sourceMapContents").ToLocalChecked()).ToLocalChecked()).FromJust()); sass_option_set_source_map_file(sass_options, ctx_w->source_map); sass_option_set_source_map_root(sass_options, ctx_w->source_map_root); sass_option_set_include_path(sass_options, ctx_w->include_path); - sass_option_set_precision(sass_options, Nan::Get(options, Nan::New("precision").ToLocalChecked()).ToLocalChecked()->Int32Value()); + sass_option_set_precision(sass_options, Nan::To(Nan::Get(options, Nan::New("precision").ToLocalChecked()).ToLocalChecked()).FromJust()); sass_option_set_indent(sass_options, ctx_w->indent); sass_option_set_linefeed(sass_options, ctx_w->linefeed); diff --git a/test/lowlevel.js b/test/lowlevel.js index 868e864d6..833f191aa 100644 --- a/test/lowlevel.js +++ b/test/lowlevel.js @@ -94,4 +94,24 @@ describe('lowlevel', function() { }, /"result.stats" element is not an object/); done(); }); + + it('options.indentWidth not provided', function(done) { + var options = { data: 'div { width: 10px; } ', + sourceComments: false, + file: null, + outFile: null, + includePaths: '', + precision: 5, + sourceMap: null, + style: 0, + /* indentWidth */ + indentType: 0, + linefeed: '\n', + result: { stats: {} } }; + + binding.renderSync(options); + done(); + }); + + }); // lowlevel From a130dae87c65373d22888fd62695231ffbb3d50a Mon Sep 17 00:00:00 2001 From: Marcin Cieslak Date: Wed, 19 Aug 2015 01:27:11 +0000 Subject: [PATCH 13/15] Cast received values to once type confirmed --- src/sass_types/factory.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sass_types/factory.cpp b/src/sass_types/factory.cpp index aa95ebf88..9bcf07005 100644 --- a/src/sass_types/factory.cpp +++ b/src/sass_types/factory.cpp @@ -60,10 +60,10 @@ namespace SassTypes Value* Factory::unwrap(v8::Local obj) { // Todo: non-SassValue objects could easily fall under that condition, need to be more specific. - if (!obj->IsObject() || obj->ToObject()->InternalFieldCount() != 1) { + if (!obj->IsObject() || obj.As()->InternalFieldCount() != 1) { throw std::invalid_argument("A SassValue object was expected."); } - return static_cast(Nan::GetInternalFieldPointer(obj->ToObject(), 0)); + return static_cast(Nan::GetInternalFieldPointer(obj.As(), 0)); } } From c94945251f315bf43581aa4f52705efc7c5785a3 Mon Sep 17 00:00:00 2001 From: Marcin Cieslak Date: Wed, 19 Aug 2015 01:02:09 +0000 Subject: [PATCH 14/15] Change obj->XxxValue() to Nan::To() in sass_types --- src/sass_types/boolean.cpp | 2 +- src/sass_types/color.cpp | 18 +++++++++--------- src/sass_types/list.cpp | 12 ++++++------ src/sass_types/map.cpp | 14 +++++++------- src/sass_types/number.cpp | 4 ++-- 5 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/sass_types/boolean.cpp b/src/sass_types/boolean.cpp index a8852c5f5..889bda300 100644 --- a/src/sass_types/boolean.cpp +++ b/src/sass_types/boolean.cpp @@ -62,7 +62,7 @@ namespace SassTypes return Nan::ThrowError(Nan::New("Expected one boolean argument").ToLocalChecked()); } - info.GetReturnValue().Set((get_singleton(info[0]->ToBoolean()->Value()).get_js_object())); + info.GetReturnValue().Set(get_singleton(Nan::To(info[0]).FromJust()).get_js_object()); } } diff --git a/src/sass_types/color.cpp b/src/sass_types/color.cpp index 1ada4af09..0cc5968ce 100644 --- a/src/sass_types/color.cpp +++ b/src/sass_types/color.cpp @@ -15,7 +15,7 @@ namespace SassTypes throw std::invalid_argument("Only argument should be an integer."); } - argb = raw_val[0]->ToInt32()->Value(); + argb = Nan::To(raw_val[0]).FromJust(); a = (double)((argb >> 030) & 0xff) / 0xff; r = (double)((argb >> 020) & 0xff); g = (double)((argb >> 010) & 0xff); @@ -27,7 +27,7 @@ namespace SassTypes throw std::invalid_argument("Constructor arguments should be numbers exclusively."); } - a = raw_val[3]->ToNumber()->Value(); + a = Nan::To(raw_val[3]).FromJust(); // fall through vvv case 3: @@ -35,9 +35,9 @@ namespace SassTypes throw std::invalid_argument("Constructor arguments should be numbers exclusively."); } - r = raw_val[0]->ToNumber()->Value(); - g = raw_val[1]->ToNumber()->Value(); - b = raw_val[2]->ToNumber()->Value(); + r = Nan::To(raw_val[0]).FromJust(); + g = Nan::To(raw_val[1]).FromJust(); + b = Nan::To(raw_val[2]).FromJust(); break; case 0: @@ -86,7 +86,7 @@ namespace SassTypes return Nan::ThrowError(Nan::New("Supplied value should be a number").ToLocalChecked()); } - sass_color_set_r(unwrap(info.This())->value, info[0]->ToNumber()->Value()); + sass_color_set_r(unwrap(info.This())->value, Nan::To(info[0]).FromJust()); } NAN_METHOD(Color::SetG) { @@ -98,7 +98,7 @@ namespace SassTypes return Nan::ThrowError(Nan::New("Supplied value should be a number").ToLocalChecked()); } - sass_color_set_g(unwrap(info.This())->value, info[0]->ToNumber()->Value()); + sass_color_set_g(unwrap(info.This())->value, Nan::To(info[0]).FromJust()); } NAN_METHOD(Color::SetB) { @@ -110,7 +110,7 @@ namespace SassTypes return Nan::ThrowError(Nan::New("Supplied value should be a number").ToLocalChecked()); } - sass_color_set_b(unwrap(info.This())->value, info[0]->ToNumber()->Value()); + sass_color_set_b(unwrap(info.This())->value, Nan::To(info[0]).FromJust()); } NAN_METHOD(Color::SetA) { @@ -122,6 +122,6 @@ namespace SassTypes return Nan::ThrowError(Nan::New("Supplied value should be a number").ToLocalChecked()); } - sass_color_set_a(unwrap(info.This())->value, info[0]->ToNumber()->Value()); + sass_color_set_a(unwrap(info.This())->value, Nan::To(info[0]).FromJust()); } } diff --git a/src/sass_types/list.cpp b/src/sass_types/list.cpp index f4bf69985..b047458e1 100644 --- a/src/sass_types/list.cpp +++ b/src/sass_types/list.cpp @@ -14,14 +14,14 @@ namespace SassTypes throw std::invalid_argument("First argument should be an integer."); } - length = raw_val[0]->ToInt32()->Value(); + length = Nan::To(raw_val[0]).FromJust(); if (raw_val.size() >= 2) { if (!raw_val[1]->IsBoolean()) { throw std::invalid_argument("Second argument should be a boolean."); } - comma = raw_val[1]->ToBoolean()->Value(); + comma = Nan::To(raw_val[1]).FromJust(); } } @@ -47,14 +47,14 @@ namespace SassTypes } Sass_Value* list = unwrap(info.This())->value; - size_t index = info[0]->ToInt32()->Value(); + size_t index = Nan::To(info[0]).FromJust(); if (index >= sass_list_get_length(list)) { return Nan::ThrowError(Nan::New("Out of bound index").ToLocalChecked()); } - info.GetReturnValue().Set(Factory::create(sass_list_get_value(list, info[0]->ToInt32()->Value()))->get_js_object()); + info.GetReturnValue().Set(Factory::create(sass_list_get_value(list, Nan::To(info[0]).FromJust()))->get_js_object()); } NAN_METHOD(List::SetValue) { @@ -71,7 +71,7 @@ namespace SassTypes } Value* sass_value = Factory::unwrap(info[1]); - sass_list_set_value(unwrap(info.This())->value, info[0]->ToInt32()->Value(), sass_value->get_sass_value()); + sass_list_set_value(unwrap(info.This())->value, Nan::To(info[0]).FromJust(), sass_value->get_sass_value()); } NAN_METHOD(List::GetSeparator) { @@ -87,7 +87,7 @@ namespace SassTypes return Nan::ThrowError(Nan::New("Supplied value should be a boolean").ToLocalChecked()); } - sass_list_set_separator(unwrap(info.This())->value, info[0]->ToBoolean()->Value() ? SASS_COMMA : SASS_SPACE); + sass_list_set_separator(unwrap(info.This())->value, Nan::To(info[0]).FromJust() ? SASS_COMMA : SASS_SPACE); } NAN_METHOD(List::GetLength) { diff --git a/src/sass_types/map.cpp b/src/sass_types/map.cpp index d7e9f381d..ac2b70308 100644 --- a/src/sass_types/map.cpp +++ b/src/sass_types/map.cpp @@ -13,7 +13,7 @@ namespace SassTypes throw std::invalid_argument("First argument should be an integer."); } - length = raw_val[0]->ToInt32()->Value(); + length = Nan::To(raw_val[0]).FromJust(); } return sass_make_map(length); @@ -38,14 +38,14 @@ namespace SassTypes } Sass_Value* map = unwrap(info.This())->value; - size_t index = info[0]->ToInt32()->Value(); + size_t index = Nan::To(info[0]).FromJust(); if (index >= sass_map_get_length(map)) { return Nan::ThrowError(Nan::New("Out of bound index").ToLocalChecked()); } - info.GetReturnValue().Set(Factory::create(sass_map_get_value(map, info[0]->ToInt32()->Value()))->get_js_object()); + info.GetReturnValue().Set(Factory::create(sass_map_get_value(map, Nan::To(info[0]).FromJust()))->get_js_object()); } NAN_METHOD(Map::SetValue) { @@ -62,7 +62,7 @@ namespace SassTypes } Value* sass_value = Factory::unwrap(info[1]); - sass_map_set_value(unwrap(info.This())->value, info[0]->ToInt32()->Value(), sass_value->get_sass_value()); + sass_map_set_value(unwrap(info.This())->value, Nan::To(info[0]).FromJust(), sass_value->get_sass_value()); } NAN_METHOD(Map::GetKey) { @@ -76,14 +76,14 @@ namespace SassTypes } Sass_Value* map = unwrap(info.This())->value; - size_t index = info[0]->ToInt32()->Value(); + size_t index = Nan::To(info[0]).FromJust(); if (index >= sass_map_get_length(map)) { return Nan::ThrowError(Nan::New("Out of bound index").ToLocalChecked()); } - info.GetReturnValue().Set(Factory::create(sass_map_get_key(map, info[0]->ToInt32()->Value()))->get_js_object()); + info.GetReturnValue().Set(Factory::create(sass_map_get_key(map, Nan::To(info[0]).FromJust()))->get_js_object()); } NAN_METHOD(Map::SetKey) { @@ -100,7 +100,7 @@ namespace SassTypes } Value* sass_value = Factory::unwrap(info[1]); - sass_map_set_key(unwrap(info.This())->value, info[0]->ToInt32()->Value(), sass_value->get_sass_value()); + sass_map_set_key(unwrap(info.This())->value, Nan::To(info[0]).FromJust(), sass_value->get_sass_value()); } NAN_METHOD(Map::GetLength) { diff --git a/src/sass_types/number.cpp b/src/sass_types/number.cpp index 55986d323..eb42e7516 100644 --- a/src/sass_types/number.cpp +++ b/src/sass_types/number.cpp @@ -15,7 +15,7 @@ namespace SassTypes throw std::invalid_argument("First argument should be a number."); } - value = raw_val[0]->ToNumber()->Value(); + value = Nan::To(raw_val[0]).FromJust(); if (raw_val.size() >= 2) { if (!raw_val[1]->IsString()) { @@ -54,7 +54,7 @@ namespace SassTypes return Nan::ThrowError(Nan::New("Supplied value should be a number").ToLocalChecked()); } - sass_number_set_value(unwrap(info.This())->value, info[0]->ToNumber()->Value()); + sass_number_set_value(unwrap(info.This())->value, Nan::To(info[0]).FromJust()); } NAN_METHOD(Number::SetUnit) { From 0604223249d1d1d836520abbcda27c8dff590443 Mon Sep 17 00:00:00 2001 From: Marcin Cieslak Date: Wed, 19 Aug 2015 01:47:12 +0000 Subject: [PATCH 15/15] Throw more specific exceptions Use TypeError whenever argument count or type do not match and RangeError if the index is out of bounds. --- src/sass_types/boolean.cpp | 4 ++-- src/sass_types/color.cpp | 16 ++++++++-------- src/sass_types/list.cpp | 16 ++++++++-------- src/sass_types/map.cpp | 24 ++++++++++++------------ src/sass_types/null.cpp | 2 +- src/sass_types/number.cpp | 8 ++++---- src/sass_types/string.cpp | 4 ++-- 7 files changed, 37 insertions(+), 37 deletions(-) diff --git a/src/sass_types/boolean.cpp b/src/sass_types/boolean.cpp index 889bda300..ebc2b2f37 100644 --- a/src/sass_types/boolean.cpp +++ b/src/sass_types/boolean.cpp @@ -54,12 +54,12 @@ namespace SassTypes if (info.IsConstructCall()) { if (constructor_locked) { - return Nan::ThrowError(Nan::New("Cannot instantiate SassBoolean").ToLocalChecked()); + return Nan::ThrowTypeError(Nan::New("Cannot instantiate SassBoolean").ToLocalChecked()); } } else { if (info.Length() != 1 || !info[0]->IsBoolean()) { - return Nan::ThrowError(Nan::New("Expected one boolean argument").ToLocalChecked()); + return Nan::ThrowTypeError(Nan::New("Expected one boolean argument").ToLocalChecked()); } info.GetReturnValue().Set(get_singleton(Nan::To(info[0]).FromJust()).get_js_object()); diff --git a/src/sass_types/color.cpp b/src/sass_types/color.cpp index 0cc5968ce..8f8efba87 100644 --- a/src/sass_types/color.cpp +++ b/src/sass_types/color.cpp @@ -79,11 +79,11 @@ namespace SassTypes NAN_METHOD(Color::SetR) { if (info.Length() != 1) { - return Nan::ThrowError(Nan::New("Expected just one argument").ToLocalChecked()); + return Nan::ThrowTypeError(Nan::New("Expected just one argument").ToLocalChecked()); } if (!info[0]->IsNumber()) { - return Nan::ThrowError(Nan::New("Supplied value should be a number").ToLocalChecked()); + return Nan::ThrowTypeError(Nan::New("Supplied value should be a number").ToLocalChecked()); } sass_color_set_r(unwrap(info.This())->value, Nan::To(info[0]).FromJust()); @@ -91,11 +91,11 @@ namespace SassTypes NAN_METHOD(Color::SetG) { if (info.Length() != 1) { - return Nan::ThrowError(Nan::New("Expected just one argument").ToLocalChecked()); + return Nan::ThrowTypeError(Nan::New("Expected just one argument").ToLocalChecked()); } if (!info[0]->IsNumber()) { - return Nan::ThrowError(Nan::New("Supplied value should be a number").ToLocalChecked()); + return Nan::ThrowTypeError(Nan::New("Supplied value should be a number").ToLocalChecked()); } sass_color_set_g(unwrap(info.This())->value, Nan::To(info[0]).FromJust()); @@ -103,11 +103,11 @@ namespace SassTypes NAN_METHOD(Color::SetB) { if (info.Length() != 1) { - return Nan::ThrowError(Nan::New("Expected just one argument").ToLocalChecked()); + return Nan::ThrowTypeError(Nan::New("Expected just one argument").ToLocalChecked()); } if (!info[0]->IsNumber()) { - return Nan::ThrowError(Nan::New("Supplied value should be a number").ToLocalChecked()); + return Nan::ThrowTypeError(Nan::New("Supplied value should be a number").ToLocalChecked()); } sass_color_set_b(unwrap(info.This())->value, Nan::To(info[0]).FromJust()); @@ -115,11 +115,11 @@ namespace SassTypes NAN_METHOD(Color::SetA) { if (info.Length() != 1) { - return Nan::ThrowError(Nan::New("Expected just one argument").ToLocalChecked()); + return Nan::ThrowTypeError(Nan::New("Expected just one argument").ToLocalChecked()); } if (!info[0]->IsNumber()) { - return Nan::ThrowError(Nan::New("Supplied value should be a number").ToLocalChecked()); + return Nan::ThrowTypeError(Nan::New("Supplied value should be a number").ToLocalChecked()); } sass_color_set_a(unwrap(info.This())->value, Nan::To(info[0]).FromJust()); diff --git a/src/sass_types/list.cpp b/src/sass_types/list.cpp index b047458e1..4e9515f95 100644 --- a/src/sass_types/list.cpp +++ b/src/sass_types/list.cpp @@ -39,11 +39,11 @@ namespace SassTypes NAN_METHOD(List::GetValue) { if (info.Length() != 1) { - return Nan::ThrowError(Nan::New("Expected just one argument").ToLocalChecked()); + return Nan::ThrowTypeError(Nan::New("Expected just one argument").ToLocalChecked()); } if (!info[0]->IsNumber()) { - return Nan::ThrowError(Nan::New("Supplied index should be an integer").ToLocalChecked()); + return Nan::ThrowTypeError(Nan::New("Supplied index should be an integer").ToLocalChecked()); } Sass_Value* list = unwrap(info.This())->value; @@ -51,7 +51,7 @@ namespace SassTypes if (index >= sass_list_get_length(list)) { - return Nan::ThrowError(Nan::New("Out of bound index").ToLocalChecked()); + return Nan::ThrowRangeError(Nan::New("Out of bound index").ToLocalChecked()); } info.GetReturnValue().Set(Factory::create(sass_list_get_value(list, Nan::To(info[0]).FromJust()))->get_js_object()); @@ -59,15 +59,15 @@ namespace SassTypes NAN_METHOD(List::SetValue) { if (info.Length() != 2) { - return Nan::ThrowError(Nan::New("Expected two arguments").ToLocalChecked()); + return Nan::ThrowTypeError(Nan::New("Expected two arguments").ToLocalChecked()); } if (!info[0]->IsNumber()) { - return Nan::ThrowError(Nan::New("Supplied index should be an integer").ToLocalChecked()); + return Nan::ThrowTypeError(Nan::New("Supplied index should be an integer").ToLocalChecked()); } if (!info[1]->IsObject()) { - return Nan::ThrowError(Nan::New("Supplied value should be a SassValue object").ToLocalChecked()); + return Nan::ThrowTypeError(Nan::New("Supplied value should be a SassValue object").ToLocalChecked()); } Value* sass_value = Factory::unwrap(info[1]); @@ -80,11 +80,11 @@ namespace SassTypes NAN_METHOD(List::SetSeparator) { if (info.Length() != 1) { - return Nan::ThrowError(Nan::New("Expected just one argument").ToLocalChecked()); + return Nan::ThrowTypeError(Nan::New("Expected just one argument").ToLocalChecked()); } if (!info[0]->IsBoolean()) { - return Nan::ThrowError(Nan::New("Supplied value should be a boolean").ToLocalChecked()); + return Nan::ThrowTypeError(Nan::New("Supplied value should be a boolean").ToLocalChecked()); } sass_list_set_separator(unwrap(info.This())->value, Nan::To(info[0]).FromJust() ? SASS_COMMA : SASS_SPACE); diff --git a/src/sass_types/map.cpp b/src/sass_types/map.cpp index ac2b70308..2be305b5a 100644 --- a/src/sass_types/map.cpp +++ b/src/sass_types/map.cpp @@ -30,11 +30,11 @@ namespace SassTypes NAN_METHOD(Map::GetValue) { if (info.Length() != 1) { - return Nan::ThrowError(Nan::New("Expected just one argument").ToLocalChecked()); + return Nan::ThrowTypeError(Nan::New("Expected just one argument").ToLocalChecked()); } if (!info[0]->IsNumber()) { - return Nan::ThrowError(Nan::New("Supplied index should be an integer").ToLocalChecked()); + return Nan::ThrowTypeError(Nan::New("Supplied index should be an integer").ToLocalChecked()); } Sass_Value* map = unwrap(info.This())->value; @@ -42,7 +42,7 @@ namespace SassTypes if (index >= sass_map_get_length(map)) { - return Nan::ThrowError(Nan::New("Out of bound index").ToLocalChecked()); + return Nan::ThrowRangeError(Nan::New("Out of bound index").ToLocalChecked()); } info.GetReturnValue().Set(Factory::create(sass_map_get_value(map, Nan::To(info[0]).FromJust()))->get_js_object()); @@ -50,15 +50,15 @@ namespace SassTypes NAN_METHOD(Map::SetValue) { if (info.Length() != 2) { - return Nan::ThrowError(Nan::New("Expected two arguments").ToLocalChecked()); + return Nan::ThrowTypeError(Nan::New("Expected two arguments").ToLocalChecked()); } if (!info[0]->IsNumber()) { - return Nan::ThrowError(Nan::New("Supplied index should be an integer").ToLocalChecked()); + return Nan::ThrowTypeError(Nan::New("Supplied index should be an integer").ToLocalChecked()); } if (!info[1]->IsObject()) { - return Nan::ThrowError(Nan::New("Supplied value should be a SassValue object").ToLocalChecked()); + return Nan::ThrowTypeError(Nan::New("Supplied value should be a SassValue object").ToLocalChecked()); } Value* sass_value = Factory::unwrap(info[1]); @@ -68,11 +68,11 @@ namespace SassTypes NAN_METHOD(Map::GetKey) { if (info.Length() != 1) { - return Nan::ThrowError(Nan::New("Expected just one argument").ToLocalChecked()); + return Nan::ThrowTypeError(Nan::New("Expected just one argument").ToLocalChecked()); } if (!info[0]->IsNumber()) { - return Nan::ThrowError(Nan::New("Supplied index should be an integer").ToLocalChecked()); + return Nan::ThrowTypeError(Nan::New("Supplied index should be an integer").ToLocalChecked()); } Sass_Value* map = unwrap(info.This())->value; @@ -80,7 +80,7 @@ namespace SassTypes if (index >= sass_map_get_length(map)) { - return Nan::ThrowError(Nan::New("Out of bound index").ToLocalChecked()); + return Nan::ThrowRangeError(Nan::New("Out of bound index").ToLocalChecked()); } info.GetReturnValue().Set(Factory::create(sass_map_get_key(map, Nan::To(info[0]).FromJust()))->get_js_object()); @@ -88,15 +88,15 @@ namespace SassTypes NAN_METHOD(Map::SetKey) { if (info.Length() != 2) { - return Nan::ThrowError(Nan::New("Expected two arguments").ToLocalChecked()); + return Nan::ThrowTypeError(Nan::New("Expected two arguments").ToLocalChecked()); } if (!info[0]->IsNumber()) { - return Nan::ThrowError(Nan::New("Supplied index should be an integer").ToLocalChecked()); + return Nan::ThrowTypeError(Nan::New("Supplied index should be an integer").ToLocalChecked()); } if (!info[1]->IsObject()) { - return Nan::ThrowError(Nan::New("Supplied value should be a SassValue object").ToLocalChecked()); + return Nan::ThrowTypeError(Nan::New("Supplied value should be a SassValue object").ToLocalChecked()); } Value* sass_value = Factory::unwrap(info[1]); diff --git a/src/sass_types/null.cpp b/src/sass_types/null.cpp index 24430f856..4e3536d6c 100644 --- a/src/sass_types/null.cpp +++ b/src/sass_types/null.cpp @@ -49,7 +49,7 @@ namespace SassTypes if (info.IsConstructCall()) { if (constructor_locked) { - return Nan::ThrowError(Nan::New("Cannot instantiate SassNull").ToLocalChecked()); + return Nan::ThrowTypeError(Nan::New("Cannot instantiate SassNull").ToLocalChecked()); } } else { diff --git a/src/sass_types/number.cpp b/src/sass_types/number.cpp index eb42e7516..b832e809b 100644 --- a/src/sass_types/number.cpp +++ b/src/sass_types/number.cpp @@ -47,11 +47,11 @@ namespace SassTypes NAN_METHOD(Number::SetValue) { if (info.Length() != 1) { - return Nan::ThrowError(Nan::New("Expected just one argument").ToLocalChecked()); + return Nan::ThrowTypeError(Nan::New("Expected just one argument").ToLocalChecked()); } if (!info[0]->IsNumber()) { - return Nan::ThrowError(Nan::New("Supplied value should be a number").ToLocalChecked()); + return Nan::ThrowTypeError(Nan::New("Supplied value should be a number").ToLocalChecked()); } sass_number_set_value(unwrap(info.This())->value, Nan::To(info[0]).FromJust()); @@ -59,11 +59,11 @@ namespace SassTypes NAN_METHOD(Number::SetUnit) { if (info.Length() != 1) { - return Nan::ThrowError(Nan::New("Expected just one argument").ToLocalChecked()); + return Nan::ThrowTypeError(Nan::New("Expected just one argument").ToLocalChecked()); } if (!info[0]->IsString()) { - return Nan::ThrowError(Nan::New("Supplied value should be a string").ToLocalChecked()); + return Nan::ThrowTypeError(Nan::New("Supplied value should be a string").ToLocalChecked()); } sass_number_set_unit(unwrap(info.This())->value, create_string(info[0])); diff --git a/src/sass_types/string.cpp b/src/sass_types/string.cpp index 5140b0561..2c2373ac6 100644 --- a/src/sass_types/string.cpp +++ b/src/sass_types/string.cpp @@ -31,11 +31,11 @@ namespace SassTypes NAN_METHOD(String::SetValue) { if (info.Length() != 1) { - return Nan::ThrowError(Nan::New("Expected just one argument").ToLocalChecked()); + return Nan::ThrowTypeError(Nan::New("Expected just one argument").ToLocalChecked()); } if (!info[0]->IsString()) { - return Nan::ThrowError(Nan::New("Supplied value should be a string").ToLocalChecked()); + return Nan::ThrowTypeError(Nan::New("Supplied value should be a string").ToLocalChecked()); } sass_string_set_value(unwrap(info.This())->value, create_string(info[0]));