Commit 8d499724 by Michael Mifsud

Merge pull request #1054 from saper/iojs45

Update bindings for io.js 3.0.0
parents 435a956d 06042232
...@@ -55,7 +55,7 @@ ...@@ -55,7 +55,7 @@
"glob": "^5.0.13", "glob": "^5.0.13",
"meow": "^3.3.0", "meow": "^3.3.0",
"mkdirp": "^0.5.1", "mkdirp": "^0.5.1",
"nan": "^1.8.4", "nan": "^2.0.1",
"npmconf": "^2.1.2", "npmconf": "^2.1.2",
"pangyp": "^2.2.1", "pangyp": "^2.2.1",
"request": "^2.58.0", "request": "^2.58.0",
......
...@@ -37,12 +37,21 @@ union Sass_Value* sass_custom_function(const union Sass_Value* s_args, Sass_Func ...@@ -37,12 +37,21 @@ union Sass_Value* sass_custom_function(const union Sass_Value* s_args, Sass_Func
} }
} }
void ExtractOptions(Local<Object> options, void* cptr, sass_context_wrapper* ctx_w, bool is_file, bool is_sync) { int ExtractOptions(v8::Local<v8::Object> options, void* cptr, sass_context_wrapper* ctx_w, bool is_file, bool is_sync) {
NanScope(); Nan::HandleScope scope;
struct Sass_Context* ctx; struct Sass_Context* ctx;
NanAssignPersistent(ctx_w->result, options->Get(NanNew("result"))->ToObject()); v8::Local<v8::Value> 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<v8::Object>());
if (is_file) { if (is_file) {
ctx_w->fctx = (struct Sass_File_Context*) cptr; ctx_w->fctx = (struct Sass_File_Context*) cptr;
...@@ -61,52 +70,60 @@ void ExtractOptions(Local<Object> options, void* cptr, sass_context_wrapper* ctx ...@@ -61,52 +70,60 @@ void ExtractOptions(Local<Object> options, void* cptr, sass_context_wrapper* ctx
ctx_w->request.data = ctx_w; ctx_w->request.data = ctx_w;
// async (callback) style // async (callback) style
Local<Function> success_callback = Local<Function>::Cast(options->Get(NanNew("success"))); v8::Local<v8::Function> success_callback = v8::Local<v8::Function>::Cast(Nan::Get(options, Nan::New("success").ToLocalChecked()).ToLocalChecked());
Local<Function> error_callback = Local<Function>::Cast(options->Get(NanNew("error"))); v8::Local<v8::Function> error_callback = v8::Local<v8::Function>::Cast(Nan::Get(options, Nan::New("error").ToLocalChecked()).ToLocalChecked());
ctx_w->success_callback = new NanCallback(success_callback); ctx_w->success_callback = new Nan::Callback(success_callback);
ctx_w->error_callback = new NanCallback(error_callback); ctx_w->error_callback = new Nan::Callback(error_callback);
} }
if (!is_file) { 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); sass_option_set_input_path(sass_options, ctx_w->file);
} }
int indent_len = options->Get(NanNew("indentWidth"))->Int32Value(); int indent_len = Nan::To<int32_t>(
Nan::Get(
options,
Nan::New("indentWidth").ToLocalChecked()
).ToLocalChecked()).FromJust();
ctx_w->indent = (char*)malloc(indent_len + 1); ctx_w->indent = (char*)malloc(indent_len + 1);
strcpy(ctx_w->indent, std::string( strcpy(ctx_w->indent, std::string(
indent_len, indent_len,
options->Get(NanNew("indentType"))->Int32Value() == 1 ? '\t' : ' ' Nan::To<int32_t>(
Nan::Get(
options,
Nan::New("indentType").ToLocalChecked()
).ToLocalChecked()).FromJust() == 1 ? '\t' : ' '
).c_str()); ).c_str());
ctx_w->linefeed = create_string(options->Get(NanNew("linefeed"))); ctx_w->linefeed = create_string(Nan::Get(options, Nan::New("linefeed").ToLocalChecked()));
ctx_w->include_path = create_string(options->Get(NanNew("includePaths"))); ctx_w->include_path = create_string(Nan::Get(options, Nan::New("includePaths").ToLocalChecked()));
ctx_w->out_file = create_string(options->Get(NanNew("outFile"))); ctx_w->out_file = create_string(Nan::Get(options, Nan::New("outFile").ToLocalChecked()));
ctx_w->source_map = create_string(options->Get(NanNew("sourceMap"))); ctx_w->source_map = create_string(Nan::Get(options, Nan::New("sourceMap").ToLocalChecked()));
ctx_w->source_map_root = create_string(options->Get(NanNew("sourceMapRoot"))); 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_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_output_style(sass_options, (Sass_Output_Style)Nan::To<int32_t>(Nan::Get(options, Nan::New("style").ToLocalChecked()).ToLocalChecked()).FromJust());
sass_option_set_is_indented_syntax_src(sass_options, options->Get(NanNew("indentedSyntax"))->BooleanValue()); sass_option_set_is_indented_syntax_src(sass_options, Nan::To<bool>(Nan::Get(options, Nan::New("indentedSyntax").ToLocalChecked()).ToLocalChecked()).FromJust());
sass_option_set_source_comments(sass_options, options->Get(NanNew("sourceComments"))->BooleanValue()); sass_option_set_source_comments(sass_options, Nan::To<bool>(Nan::Get(options, Nan::New("sourceComments").ToLocalChecked()).ToLocalChecked()).FromJust());
sass_option_set_omit_source_map_url(sass_options, options->Get(NanNew("omitSourceMapUrl"))->BooleanValue()); sass_option_set_omit_source_map_url(sass_options, Nan::To<bool>(Nan::Get(options, Nan::New("omitSourceMapUrl").ToLocalChecked()).ToLocalChecked()).FromJust());
sass_option_set_source_map_embed(sass_options, options->Get(NanNew("sourceMapEmbed"))->BooleanValue()); sass_option_set_source_map_embed(sass_options, Nan::To<bool>(Nan::Get(options, Nan::New("sourceMapEmbed").ToLocalChecked()).ToLocalChecked()).FromJust());
sass_option_set_source_map_contents(sass_options, options->Get(NanNew("sourceMapContents"))->BooleanValue()); sass_option_set_source_map_contents(sass_options, Nan::To<bool>(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_file(sass_options, ctx_w->source_map);
sass_option_set_source_map_root(sass_options, ctx_w->source_map_root); 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_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::To<int32_t>(Nan::Get(options, Nan::New("precision").ToLocalChecked()).ToLocalChecked()).FromJust());
sass_option_set_indent(sass_options, ctx_w->indent); sass_option_set_indent(sass_options, ctx_w->indent);
sass_option_set_linefeed(sass_options, ctx_w->linefeed); sass_option_set_linefeed(sass_options, ctx_w->linefeed);
Local<Value> importer_callback = options->Get(NanNew("importer")); v8::Local<v8::Value> importer_callback = Nan::Get(options, Nan::New("importer").ToLocalChecked()).ToLocalChecked();
if (importer_callback->IsFunction()) { if (importer_callback->IsFunction()) {
Local<Function> importer = Local<Function>::Cast(importer_callback); v8::Local<v8::Function> importer = importer_callback.As<v8::Function>();
auto bridge = std::make_shared<CustomImporterBridge>(new NanCallback(importer), ctx_w->is_sync); auto bridge = std::make_shared<CustomImporterBridge>(new Nan::Callback(importer), ctx_w->is_sync);
ctx_w->importer_bridges.push_back(bridge); ctx_w->importer_bridges.push_back(bridge);
Sass_Importer_List c_importers = sass_make_importer_list(1); Sass_Importer_List c_importers = sass_make_importer_list(1);
...@@ -115,13 +132,13 @@ void ExtractOptions(Local<Object> options, void* cptr, sass_context_wrapper* ctx ...@@ -115,13 +132,13 @@ void ExtractOptions(Local<Object> options, void* cptr, sass_context_wrapper* ctx
sass_option_set_c_importers(sass_options, c_importers); sass_option_set_c_importers(sass_options, c_importers);
} }
else if (importer_callback->IsArray()) { else if (importer_callback->IsArray()) {
Handle<Array> importers = Handle<Array>::Cast(importer_callback); v8::Local<v8::Array> importers = importer_callback.As<v8::Array>();
Sass_Importer_List c_importers = sass_make_importer_list(importers->Length()); Sass_Importer_List c_importers = sass_make_importer_list(importers->Length());
for (size_t i = 0; i < importers->Length(); ++i) { for (size_t i = 0; i < importers->Length(); ++i) {
Local<Function> callback = Local<Function>::Cast(importers->Get(static_cast<uint32_t>(i))); v8::Local<v8::Function> callback = v8::Local<v8::Function>::Cast(Nan::Get(importers, static_cast<uint32_t>(i)).ToLocalChecked());
auto bridge = std::make_shared<CustomImporterBridge>(new NanCallback(callback), ctx_w->is_sync); auto bridge = std::make_shared<CustomImporterBridge>(new Nan::Callback(callback), ctx_w->is_sync);
ctx_w->importer_bridges.push_back(bridge); ctx_w->importer_bridges.push_back(bridge);
c_importers[i] = sass_make_importer(sass_importer, importers->Length() - i - 1, bridge.get()); c_importers[i] = sass_make_importer(sass_importer, importers->Length() - i - 1, bridge.get());
...@@ -130,19 +147,19 @@ void ExtractOptions(Local<Object> options, void* cptr, sass_context_wrapper* ctx ...@@ -130,19 +147,19 @@ void ExtractOptions(Local<Object> options, void* cptr, sass_context_wrapper* ctx
sass_option_set_c_importers(sass_options, c_importers); sass_option_set_c_importers(sass_options, c_importers);
} }
Local<Value> custom_functions = options->Get(NanNew("functions")); v8::Local<v8::Value> custom_functions = Nan::Get(options, Nan::New("functions").ToLocalChecked()).ToLocalChecked();
if (custom_functions->IsObject()) { if (custom_functions->IsObject()) {
Local<Object> functions = Local<Object>::Cast(custom_functions); v8::Local<v8::Object> functions = custom_functions.As<v8::Object>();
Local<Array> signatures = functions->GetOwnPropertyNames(); v8::Local<v8::Array> signatures = Nan::GetOwnPropertyNames(functions).ToLocalChecked();
unsigned num_signatures = signatures->Length(); unsigned num_signatures = signatures->Length();
Sass_Function_List fn_list = sass_make_function_list(num_signatures); Sass_Function_List fn_list = sass_make_function_list(num_signatures);
for (unsigned i = 0; i < num_signatures; i++) { for (unsigned i = 0; i < num_signatures; i++) {
Local<String> signature = Local<String>::Cast(signatures->Get(NanNew(i))); v8::Local<v8::String> signature = v8::Local<v8::String>::Cast(Nan::Get(signatures, Nan::New(i)).ToLocalChecked());
Local<Function> callback = Local<Function>::Cast(functions->Get(signature)); v8::Local<v8::Function> callback = v8::Local<v8::Function>::Cast(Nan::Get(functions, signature).ToLocalChecked());
auto bridge = std::make_shared<CustomFunctionBridge>(new NanCallback(callback), ctx_w->is_sync); auto bridge = std::make_shared<CustomFunctionBridge>(new Nan::Callback(callback), ctx_w->is_sync);
ctx_w->function_bridges.push_back(bridge); ctx_w->function_bridges.push_back(bridge);
Sass_Function_Entry fn = sass_make_function(create_string(signature), sass_custom_function, bridge.get()); Sass_Function_Entry fn = sass_make_function(create_string(signature), sass_custom_function, bridge.get());
...@@ -151,51 +168,71 @@ void ExtractOptions(Local<Object> options, void* cptr, sass_context_wrapper* ctx ...@@ -151,51 +168,71 @@ void ExtractOptions(Local<Object> options, void* cptr, sass_context_wrapper* ctx
sass_option_set_c_functions(sass_options, fn_list); sass_option_set_c_functions(sass_options, fn_list);
} }
return 0;
} }
void GetStats(sass_context_wrapper* ctx_w, Sass_Context* ctx) { void GetStats(sass_context_wrapper* ctx_w, Sass_Context* ctx) {
NanScope(); Nan::HandleScope scope;
char** included_files = sass_context_get_included_files(ctx); char** included_files = sass_context_get_included_files(ctx);
Handle<Array> arr = NanNew<Array>(); v8::Local<v8::Array> arr = Nan::New<v8::Array>();
if (included_files) { if (included_files) {
for (int i = 0; included_files[i] != nullptr; ++i) { for (int i = 0; included_files[i] != nullptr; ++i) {
arr->Set(i, NanNew<String>(included_files[i])); Nan::Set(arr, i, Nan::New<v8::String>(included_files[i]).ToLocalChecked());
} }
} }
NanNew(ctx_w->result)->Get(NanNew("stats"))->ToObject()->Set(NanNew("includedFiles"), arr); v8::Local<v8::Object> result = Nan::New(ctx_w->result);
assert(result->IsObject());
v8::Local<v8::Value> stats = Nan::Get(
result,
Nan::New("stats").ToLocalChecked()
).ToLocalChecked();
if (stats->IsObject()) {
Nan::Set(
stats.As<v8::Object>(),
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) { int GetResult(sass_context_wrapper* ctx_w, Sass_Context* ctx, bool is_sync = false) {
NanScope(); Nan::HandleScope scope;
v8::Local<v8::Object> result;
int status = sass_context_get_error_status(ctx); int status = sass_context_get_error_status(ctx);
result = Nan::New(ctx_w->result);
assert(result->IsObject());
if (status == 0) { if (status == 0) {
const char* css = sass_context_get_output_string(ctx); const char* css = sass_context_get_output_string(ctx);
const char* map = sass_context_get_source_map_string(ctx); const char* map = sass_context_get_source_map_string(ctx);
NanNew(ctx_w->result)->Set(NanNew("css"), NanNewBufferHandle(css, static_cast<uint32_t>(strlen(css)))); Nan::Set(result, Nan::New("css").ToLocalChecked(), Nan::CopyBuffer(css, static_cast<uint32_t>(strlen(css))).ToLocalChecked());
GetStats(ctx_w, ctx); GetStats(ctx_w, ctx);
if (map) { if (map) {
NanNew(ctx_w->result)->Set(NanNew("map"), NanNewBufferHandle(map, static_cast<uint32_t>(strlen(map)))); Nan::Set(result, Nan::New("map").ToLocalChecked(), Nan::CopyBuffer(map, static_cast<uint32_t>(strlen(map))).ToLocalChecked());
} }
} }
else if (is_sync) { else if (is_sync) {
NanNew(ctx_w->result)->Set(NanNew("error"), NanNew<String>(sass_context_get_error_json(ctx))); Nan::Set(result, Nan::New("error").ToLocalChecked(), Nan::New<v8::String>(sass_context_get_error_json(ctx)).ToLocalChecked());
} }
return status; return status;
} }
void MakeCallback(uv_work_t* req) { void MakeCallback(uv_work_t* req) {
NanScope(); Nan::HandleScope scope;
TryCatch try_catch; Nan::TryCatch try_catch;
sass_context_wrapper* ctx_w = static_cast<sass_context_wrapper*>(req->data); sass_context_wrapper* ctx_w = static_cast<sass_context_wrapper*>(req->data);
struct Sass_Context* ctx; struct Sass_Context* ctx;
...@@ -215,103 +252,95 @@ void MakeCallback(uv_work_t* req) { ...@@ -215,103 +252,95 @@ void MakeCallback(uv_work_t* req) {
else if (ctx_w->error_callback) { else if (ctx_w->error_callback) {
// if error, do callback(error) // if error, do callback(error)
const char* err = sass_context_get_error_json(ctx); const char* err = sass_context_get_error_json(ctx);
Local<Value> argv[] = { v8::Local<v8::Value> argv[] = {
NanNew<String>(err) Nan::New<v8::String>(err).ToLocalChecked()
}; };
ctx_w->error_callback->Call(1, argv); ctx_w->error_callback->Call(1, argv);
} }
if (try_catch.HasCaught()) { if (try_catch.HasCaught()) {
node::FatalException(try_catch); Nan::FatalException(try_catch);
} }
sass_free_context_wrapper(ctx_w); sass_free_context_wrapper(ctx_w);
} }
NAN_METHOD(render) { NAN_METHOD(render) {
NanScope();
Local<Object> options = args[0]->ToObject(); v8::Local<v8::Object> options = Nan::To<v8::Object>(info[0]).ToLocalChecked();
char* source_string = create_string(options->Get(NanNew("data"))); 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_Data_Context* dctx = sass_make_data_context(source_string);
sass_context_wrapper* ctx_w = sass_make_context_wrapper(); 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);
}
NanReturnUndefined();
} }
NAN_METHOD(render_sync) { NAN_METHOD(render_sync) {
NanScope();
Local<Object> options = args[0]->ToObject(); v8::Local<v8::Object> options = Nan::To<v8::Object>(info[0]).ToLocalChecked();
char* source_string = create_string(options->Get(NanNew("data"))); 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_Data_Context* dctx = sass_make_data_context(source_string);
struct Sass_Context* ctx = sass_data_context_get_context(dctx); struct Sass_Context* ctx = sass_data_context_get_context(dctx);
sass_context_wrapper* ctx_w = sass_make_context_wrapper(); sass_context_wrapper* ctx_w = sass_make_context_wrapper();
int result = -1;
ExtractOptions(options, dctx, ctx_w, false, true); if ((result = ExtractOptions(options, dctx, ctx_w, false, true)) >= 0) {
compile_data(dctx);
compile_data(dctx); result = GetResult(ctx_w, ctx, true);
}
int result = GetResult(ctx_w, ctx, true);
sass_free_context_wrapper(ctx_w); sass_free_context_wrapper(ctx_w);
info.GetReturnValue().Set(result == 0);
NanReturnValue(NanNew<Boolean>(result == 0));
} }
NAN_METHOD(render_file) { NAN_METHOD(render_file) {
NanScope();
Local<Object> options = args[0]->ToObject(); v8::Local<v8::Object> options = Nan::To<v8::Object>(info[0]).ToLocalChecked();
char* input_path = create_string(options->Get(NanNew("file"))); 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_File_Context* fctx = sass_make_file_context(input_path);
sass_context_wrapper* ctx_w = sass_make_context_wrapper(); sass_context_wrapper* ctx_w = sass_make_context_wrapper();
ExtractOptions(options, fctx, ctx_w, true, false); if (ExtractOptions(options, fctx, ctx_w, true, false) >= 0) {
int status = uv_queue_work(uv_default_loop(), &ctx_w->request, compile_it, (uv_after_work_cb)MakeCallback);
assert(status == 0); int status = uv_queue_work(uv_default_loop(), &ctx_w->request, compile_it, (uv_after_work_cb)MakeCallback);
assert(status == 0);
NanReturnUndefined(); }
} }
NAN_METHOD(render_file_sync) { NAN_METHOD(render_file_sync) {
NanScope();
Local<Object> options = args[0]->ToObject(); v8::Local<v8::Object> options = Nan::To<v8::Object>(info[0]).ToLocalChecked();
char* input_path = create_string(options->Get(NanNew("file"))); 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_File_Context* fctx = sass_make_file_context(input_path);
struct Sass_Context* ctx = sass_file_context_get_context(fctx); struct Sass_Context* ctx = sass_file_context_get_context(fctx);
sass_context_wrapper* ctx_w = sass_make_context_wrapper(); sass_context_wrapper* ctx_w = sass_make_context_wrapper();
int result = -1;
ExtractOptions(options, fctx, ctx_w, true, true); if ((result = ExtractOptions(options, fctx, ctx_w, true, true)) >= 0) {
compile_file(fctx); compile_file(fctx);
result = GetResult(ctx_w, ctx, true);
int result = GetResult(ctx_w, ctx, true); };
free(input_path); free(input_path);
sass_free_context_wrapper(ctx_w); sass_free_context_wrapper(ctx_w);
NanReturnValue(NanNew<Boolean>(result == 0)); info.GetReturnValue().Set(result == 0);
} }
NAN_METHOD(libsass_version) { NAN_METHOD(libsass_version) {
NanScope(); info.GetReturnValue().Set(Nan::New<v8::String>(libsass_version()).ToLocalChecked());
NanReturnValue(NanNew<String>(libsass_version()));
} }
void RegisterModule(v8::Handle<v8::Object> target) { NAN_MODULE_INIT(RegisterModule) {
NODE_SET_METHOD(target, "render", render); Nan::SetMethod(target, "render", render);
NODE_SET_METHOD(target, "renderSync", render_sync); Nan::SetMethod(target, "renderSync", render_sync);
NODE_SET_METHOD(target, "renderFile", render_file); Nan::SetMethod(target, "renderFile", render_file);
NODE_SET_METHOD(target, "renderFileSync", render_file_sync); Nan::SetMethod(target, "renderFileSync", render_file_sync);
NODE_SET_METHOD(target, "libsassVersion", libsass_version); Nan::SetMethod(target, "libsassVersion", libsass_version);
SassTypes::Factory::initExports(target); SassTypes::Factory::initExports(target);
} }
......
...@@ -8,12 +8,10 @@ ...@@ -8,12 +8,10 @@
#define COMMA , #define COMMA ,
using namespace v8;
template <typename T, typename L = void*> template <typename T, typename L = void*>
class CallbackBridge { class CallbackBridge {
public: public:
CallbackBridge(NanCallback*, bool); CallbackBridge(Nan::Callback*, bool);
virtual ~CallbackBridge(); virtual ~CallbackBridge();
// Executes the callback // Executes the callback
...@@ -22,12 +20,12 @@ class CallbackBridge { ...@@ -22,12 +20,12 @@ class CallbackBridge {
protected: protected:
// We will expose a bridge object to the JS callback that wraps this instance so we don't loose context. // 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. // This is the V8 constructor for such objects.
static Handle<Function> get_wrapper_constructor(); static Nan::MaybeLocal<v8::Function> get_wrapper_constructor();
static void async_gone(uv_handle_t *handle); static void async_gone(uv_handle_t *handle);
static NAN_METHOD(New); static NAN_METHOD(New);
static NAN_METHOD(ReturnCallback); static NAN_METHOD(ReturnCallback);
static Persistent<Function> wrapper_constructor; static Nan::Persistent<v8::Function> wrapper_constructor;
Persistent<Object> wrapper; Nan::Persistent<v8::Object> wrapper;
// The callback that will get called in the main thread after the worker thread used for the sass // 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() // compilation step makes a call to uv_async_send()
...@@ -36,12 +34,12 @@ class CallbackBridge { ...@@ -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. // 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 // This gives a chance to specialized subclasses to transform those values into whatever makes sense to
// sass before we resume the worker thread. // sass before we resume the worker thread.
virtual T post_process_return_value(Handle<Value>) const =0; virtual T post_process_return_value(v8::Local<v8::Value>) const =0;
virtual std::vector<Handle<Value>> pre_process_args(std::vector<L>) const =0; virtual std::vector<v8::Local<v8::Value>> pre_process_args(std::vector<L>) const =0;
NanCallback* callback; Nan::Callback* callback;
bool is_sync; bool is_sync;
std::mutex cv_mutex; std::mutex cv_mutex;
...@@ -53,25 +51,30 @@ class CallbackBridge { ...@@ -53,25 +51,30 @@ class CallbackBridge {
}; };
template <typename T, typename L> template <typename T, typename L>
Persistent<Function> CallbackBridge<T, L>::wrapper_constructor; Nan::Persistent<v8::Function> CallbackBridge<T, L>::wrapper_constructor;
template <typename T, typename L> template <typename T, typename L>
CallbackBridge<T, L>::CallbackBridge(NanCallback* callback, bool is_sync) : callback(callback), is_sync(is_sync) { CallbackBridge<T, L>::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.
*/
Nan::HandleScope scope;
if (!is_sync) { if (!is_sync) {
this->async = new uv_async_t; this->async = new uv_async_t;
this->async->data = (void*) this; this->async->data = (void*) this;
uv_async_init(uv_default_loop(), this->async, (uv_async_cb) dispatched_async_uv_callback); uv_async_init(uv_default_loop(), this->async, (uv_async_cb) dispatched_async_uv_callback);
} }
NanAssignPersistent(wrapper, NanNew(CallbackBridge<T, L>::get_wrapper_constructor())->NewInstance()); v8::Local<v8::Function> func = CallbackBridge<T, L>::get_wrapper_constructor().ToLocalChecked();
NanSetInternalFieldPointer(NanNew(wrapper), 0, this); wrapper.Reset(Nan::NewInstance(func).ToLocalChecked());
Nan::SetInternalFieldPointer(Nan::New(wrapper), 0, this);
} }
template <typename T, typename L> template <typename T, typename L>
CallbackBridge<T, L>::~CallbackBridge() { CallbackBridge<T, L>::~CallbackBridge() {
delete this->callback; delete this->callback;
NanDisposePersistent(this->wrapper); this->wrapper.Reset();
if (!is_sync) { if (!is_sync) {
uv_close((uv_handle_t*)this->async, &async_gone); uv_close((uv_handle_t*)this->async, &async_gone);
...@@ -81,51 +84,88 @@ CallbackBridge<T, L>::~CallbackBridge() { ...@@ -81,51 +84,88 @@ CallbackBridge<T, L>::~CallbackBridge() {
template <typename T, typename L> template <typename T, typename L>
T CallbackBridge<T, L>::operator()(std::vector<void*> argv) { T CallbackBridge<T, L>::operator()(std::vector<void*> argv) {
// argv.push_back(wrapper); // argv.push_back(wrapper);
if (this->is_sync) { if (this->is_sync) {
std::vector<Handle<Value>> argv_v8 = pre_process_args(argv); /*
argv_v8.push_back(NanNew(wrapper)); * 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<v8::Local<v8::Value>> argv_v8 = pre_process_args(argv);
argv_v8.push_back(Nan::New(wrapper));
return this->post_process_return_value( return this->post_process_return_value(
NanNew<Value>(this->callback->Call(argv_v8.size(), &argv_v8[0])) 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<std::mutex> 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<std::mutex> 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 <typename T, typename L> template <typename T, typename L>
void CallbackBridge<T, L>::dispatched_async_uv_callback(uv_async_t *req) { void CallbackBridge<T, L>::dispatched_async_uv_callback(uv_async_t *req) {
CallbackBridge* bridge = static_cast<CallbackBridge*>(req->data); CallbackBridge* bridge = static_cast<CallbackBridge*>(req->data);
NanScope(); /*
TryCatch try_catch; * 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;
std::vector<Handle<Value>> argv_v8 = bridge->pre_process_args(bridge->argv); std::vector<v8::Local<v8::Value>> argv_v8 = bridge->pre_process_args(bridge->argv);
argv_v8.push_back(NanNew(bridge->wrapper)); argv_v8.push_back(Nan::New(bridge->wrapper));
NanNew<Value>(bridge->callback->Call(argv_v8.size(), &argv_v8[0])); bridge->callback->Call(argv_v8.size(), &argv_v8[0]);
if (try_catch.HasCaught()) { if (try_catch.HasCaught()) {
node::FatalException(try_catch); Nan::FatalException(try_catch);
} }
} }
template <typename T, typename L> template <typename T, typename L>
NAN_METHOD(CallbackBridge<T COMMA L>::ReturnCallback) { NAN_METHOD(CallbackBridge<T COMMA L>::ReturnCallback) {
NanScope();
CallbackBridge<T, L>* bridge = static_cast<CallbackBridge<T, L>*>(NanGetInternalFieldPointer(args.This(), 0)); /*
TryCatch try_catch; * 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<T, L>* bridge = static_cast<CallbackBridge<T, L>*>(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<std::mutex> lock(bridge->cv_mutex); std::lock_guard<std::mutex> lock(bridge->cv_mutex);
...@@ -135,33 +175,31 @@ NAN_METHOD(CallbackBridge<T COMMA L>::ReturnCallback) { ...@@ -135,33 +175,31 @@ NAN_METHOD(CallbackBridge<T COMMA L>::ReturnCallback) {
bridge->condition_variable.notify_all(); bridge->condition_variable.notify_all();
if (try_catch.HasCaught()) { if (try_catch.HasCaught()) {
node::FatalException(try_catch); Nan::FatalException(try_catch);
} }
NanReturnUndefined();
} }
template <typename T, typename L> template <typename T, typename L>
Handle<Function> CallbackBridge<T, L>::get_wrapper_constructor() { Nan::MaybeLocal<v8::Function> CallbackBridge<T, L>::get_wrapper_constructor() {
/* Uses handle scope created in the CallbackBridge<T, L> constructor */
if (wrapper_constructor.IsEmpty()) { if (wrapper_constructor.IsEmpty()) {
Local<FunctionTemplate> tpl = NanNew<FunctionTemplate>(New); v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
tpl->SetClassName(NanNew("CallbackBridge")); tpl->SetClassName(Nan::New("CallbackBridge").ToLocalChecked());
tpl->InstanceTemplate()->SetInternalFieldCount(1); tpl->InstanceTemplate()->SetInternalFieldCount(1);
tpl->PrototypeTemplate()->Set(
NanNew("success"), Nan::SetPrototypeTemplate(tpl, "success",
NanNew<FunctionTemplate>(ReturnCallback)->GetFunction() Nan::GetFunction(Nan::New<v8::FunctionTemplate>(ReturnCallback)).ToLocalChecked()
); );
NanAssignPersistent(wrapper_constructor, tpl->GetFunction()); wrapper_constructor.Reset(Nan::GetFunction(tpl).ToLocalChecked());
} }
return NanNew(wrapper_constructor); return Nan::New(wrapper_constructor);
} }
template <typename T, typename L> template <typename T, typename L>
NAN_METHOD(CallbackBridge<T COMMA L>::New) { NAN_METHOD(CallbackBridge<T COMMA L>::New) {
NanScope(); info.GetReturnValue().Set(info.This());
NanReturnValue(args.This());
} }
template <typename T, typename L> template <typename T, typename L>
......
...@@ -3,12 +3,18 @@ ...@@ -3,12 +3,18 @@
#include <string.h> #include <string.h>
#include "create_string.h" #include "create_string.h"
char* create_string(Local<Value> value) { char* create_string(Nan::MaybeLocal<v8::Value> maybevalue) {
if (value->IsNull() || !value->IsString()) { v8::Local<v8::Value> value;
if (maybevalue.ToLocal(&value)) {
if (value->IsNull() || !value->IsString()) {
return 0;
}
} else {
return 0; return 0;
} }
String::Utf8Value string(value); v8::String::Utf8Value string(value);
char *str = (char *)malloc(string.length() + 1); char *str = (char *)malloc(string.length() + 1);
strcpy(str, *string); strcpy(str, *string);
return str; return str;
......
...@@ -3,8 +3,6 @@ ...@@ -3,8 +3,6 @@
#include <nan.h> #include <nan.h>
using namespace v8; char* create_string(Nan::MaybeLocal<v8::Value>);
char* create_string(Local<Value>); #endif
#endif
\ No newline at end of file
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
#include "custom_function_bridge.h" #include "custom_function_bridge.h"
#include "sass_types/factory.h" #include "sass_types/factory.h"
Sass_Value* CustomFunctionBridge::post_process_return_value(Handle<Value> val) const { Sass_Value* CustomFunctionBridge::post_process_return_value(v8::Local<v8::Value> val) const {
try { try {
return SassTypes::Factory::unwrap(val)->get_sass_value(); return SassTypes::Factory::unwrap(val)->get_sass_value();
} }
...@@ -11,8 +11,8 @@ Sass_Value* CustomFunctionBridge::post_process_return_value(Handle<Value> val) c ...@@ -11,8 +11,8 @@ Sass_Value* CustomFunctionBridge::post_process_return_value(Handle<Value> val) c
} }
} }
std::vector<Handle<Value>> CustomFunctionBridge::pre_process_args(std::vector<void*> in) const { std::vector<v8::Local<v8::Value>> CustomFunctionBridge::pre_process_args(std::vector<void*> in) const {
std::vector<Handle<Value>> argv = std::vector<Handle<Value>>(); std::vector<v8::Local<v8::Value>> argv = std::vector<v8::Local<v8::Value>>();
for (void* value : in) { for (void* value : in) {
argv.push_back(SassTypes::Factory::create(static_cast<Sass_Value*>(value))->get_js_object()); argv.push_back(SassTypes::Factory::create(static_cast<Sass_Value*>(value))->get_js_object());
......
...@@ -5,15 +5,13 @@ ...@@ -5,15 +5,13 @@
#include <sass_context.h> #include <sass_context.h>
#include "callback_bridge.h" #include "callback_bridge.h"
using namespace v8;
class CustomFunctionBridge : public CallbackBridge<Sass_Value*> { class CustomFunctionBridge : public CallbackBridge<Sass_Value*> {
public: public:
CustomFunctionBridge(NanCallback* cb, bool is_sync) : CallbackBridge<Sass_Value*>(cb, is_sync) {} CustomFunctionBridge(Nan::Callback* cb, bool is_sync) : CallbackBridge<Sass_Value*>(cb, is_sync) {}
private: private:
Sass_Value* post_process_return_value(Handle<Value>) const; Sass_Value* post_process_return_value(v8::Local<v8::Value>) const;
std::vector<Handle<Value>> pre_process_args(std::vector<void*>) const; std::vector<v8::Local<v8::Value>> pre_process_args(std::vector<void*>) const;
}; };
#endif #endif
...@@ -2,19 +2,17 @@ ...@@ -2,19 +2,17 @@
#include "custom_importer_bridge.h" #include "custom_importer_bridge.h"
#include "create_string.h" #include "create_string.h"
SassImportList CustomImporterBridge::post_process_return_value(Handle<Value> val) const { SassImportList CustomImporterBridge::post_process_return_value(v8::Local<v8::Value> returned_value) const {
SassImportList imports = 0; SassImportList imports = 0;
NanScope(); Nan::HandleScope scope;
Local<Value> returned_value = NanNew(val);
if (returned_value->IsArray()) { if (returned_value->IsArray()) {
Handle<Array> array = Handle<Array>::Cast(returned_value); v8::Local<v8::Array> array = returned_value.As<v8::Array>();
imports = sass_make_import_list(array->Length()); imports = sass_make_import_list(array->Length());
for (size_t i = 0; i < array->Length(); ++i) { for (size_t i = 0; i < array->Length(); ++i) {
Local<Value> value = array->Get(static_cast<uint32_t>(i)); v8::Local<v8::Value> value = Nan::Get(array, static_cast<uint32_t>(i)).ToLocalChecked();
if (!value->IsObject()) { if (!value->IsObject()) {
auto entry = sass_make_import_entry(0, 0, 0); auto entry = sass_make_import_entry(0, 0, 0);
...@@ -22,10 +20,10 @@ SassImportList CustomImporterBridge::post_process_return_value(Handle<Value> val ...@@ -22,10 +20,10 @@ SassImportList CustomImporterBridge::post_process_return_value(Handle<Value> val
continue; continue;
} }
Local<Object> object = Local<Object>::Cast(value); v8::Local<v8::Object> object = value.As<v8::Object>();
if (value->IsNativeError()) { if (value->IsNativeError()) {
char* message = create_string(object->Get(NanNew<String>("message"))); char* message = create_string(Nan::Get(object, Nan::New<v8::String>("message").ToLocalChecked()));
imports[i] = sass_make_import_entry(0, 0, 0); imports[i] = sass_make_import_entry(0, 0, 0);
...@@ -38,8 +36,8 @@ SassImportList CustomImporterBridge::post_process_return_value(Handle<Value> val ...@@ -38,8 +36,8 @@ SassImportList CustomImporterBridge::post_process_return_value(Handle<Value> val
} }
else if (returned_value->IsNativeError()) { else if (returned_value->IsNativeError()) {
imports = sass_make_import_list(1); imports = sass_make_import_list(1);
Local<Object> object = Local<Object>::Cast(returned_value); v8::Local<v8::Object> object = returned_value.As<v8::Object>();
char* message = create_string(object->Get(NanNew<String>("message"))); char* message = create_string(Nan::Get(object, Nan::New<v8::String>("message").ToLocalChecked()));
imports[0] = sass_make_import_entry(0, 0, 0); imports[0] = sass_make_import_entry(0, 0, 0);
...@@ -47,36 +45,42 @@ SassImportList CustomImporterBridge::post_process_return_value(Handle<Value> val ...@@ -47,36 +45,42 @@ SassImportList CustomImporterBridge::post_process_return_value(Handle<Value> val
} }
else if (returned_value->IsObject()) { else if (returned_value->IsObject()) {
imports = sass_make_import_list(1); imports = sass_make_import_list(1);
imports[0] = get_importer_entry(Local<Object>::Cast(returned_value)); imports[0] = get_importer_entry(returned_value.As<v8::Object>());
} }
return imports; return imports;
} }
Sass_Import* CustomImporterBridge::get_importer_entry(const Local<Object>& object) const { Sass_Import* CustomImporterBridge::check_returned_string(Nan::MaybeLocal<v8::Value> value, const char *msg) const
auto returned_file = object->Get(NanNew<String>("file")); {
v8::Local<v8::Value> checked;
if (!returned_file->IsUndefined() && !returned_file->IsString()) { if (value.ToLocal(&checked)) {
if (!checked->IsUndefined() && !checked->IsString()) {
goto err;
} else {
return nullptr;
}
}
err:
auto entry = sass_make_import_entry(0, 0, 0); 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; return entry;
} }
auto returned_contents = object->Get(NanNew<String>("contents")); Sass_Import* CustomImporterBridge::get_importer_entry(const v8::Local<v8::Object>& object) const {
auto returned_file = Nan::Get(object, Nan::New<v8::String>("file").ToLocalChecked());
auto returned_contents = Nan::Get(object, Nan::New<v8::String>("contents").ToLocalChecked()).ToLocalChecked();
auto returned_map = Nan::Get(object, Nan::New<v8::String>("map").ToLocalChecked());
Sass_Import *err;
if (!returned_contents->IsUndefined() && !returned_contents->IsString()) { if ((err = check_returned_string(returned_file, "returned value of `file` must be a string")))
auto entry = sass_make_import_entry(0, 0, 0); return err;
sass_import_set_error(entry, "returned value of `contents` must be a string", -1, -1);
return entry;
}
auto returned_map = object->Get(NanNew<String>("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()) { if ((err = check_returned_string(returned_map, "returned value of `returned_map` must be a string")))
auto entry = sass_make_import_entry(0, 0, 0); return err;
sass_import_set_error(entry, "returned value of `map` must be a string", -1, -1);
return entry;
}
char* path = create_string(returned_file); char* path = create_string(returned_file);
char* contents = create_string(returned_contents); char* contents = create_string(returned_contents);
...@@ -85,11 +89,11 @@ Sass_Import* CustomImporterBridge::get_importer_entry(const Local<Object>& objec ...@@ -85,11 +89,11 @@ Sass_Import* CustomImporterBridge::get_importer_entry(const Local<Object>& objec
return sass_make_import_entry(path, contents, srcmap); return sass_make_import_entry(path, contents, srcmap);
} }
std::vector<Handle<Value>> CustomImporterBridge::pre_process_args(std::vector<void*> in) const { std::vector<v8::Local<v8::Value>> CustomImporterBridge::pre_process_args(std::vector<void*> in) const {
std::vector<Handle<Value>> out; std::vector<v8::Local<v8::Value>> out;
for (void* ptr : in) { for (void* ptr : in) {
out.push_back(NanNew<String>((char const*)ptr)); out.push_back(Nan::New<v8::String>((char const*)ptr).ToLocalChecked());
} }
return out; return out;
......
...@@ -5,18 +5,17 @@ ...@@ -5,18 +5,17 @@
#include <sass_context.h> #include <sass_context.h>
#include "callback_bridge.h" #include "callback_bridge.h"
using namespace v8;
typedef Sass_Import_List SassImportList; typedef Sass_Import_List SassImportList;
class CustomImporterBridge : public CallbackBridge<SassImportList> { class CustomImporterBridge : public CallbackBridge<SassImportList> {
public: public:
CustomImporterBridge(NanCallback* cb, bool is_sync) : CallbackBridge<SassImportList>(cb, is_sync) {} CustomImporterBridge(Nan::Callback* cb, bool is_sync) : CallbackBridge<SassImportList>(cb, is_sync) {}
private: private:
SassImportList post_process_return_value(Handle<Value>) const; SassImportList post_process_return_value(v8::Local<v8::Value>) const;
Sass_Import* get_importer_entry(const Local<Object>&) const; Sass_Import* check_returned_string(Nan::MaybeLocal<v8::Value> value, const char *msg) const;
std::vector<Handle<Value>> pre_process_args(std::vector<void*>) const; Sass_Import* get_importer_entry(const v8::Local<v8::Object>&) const;
std::vector<v8::Local<v8::Value>> pre_process_args(std::vector<void*>) const;
}; };
#endif #endif
...@@ -37,7 +37,7 @@ extern "C" { ...@@ -37,7 +37,7 @@ extern "C" {
delete ctx_w->error_callback; delete ctx_w->error_callback;
delete ctx_w->success_callback; delete ctx_w->success_callback;
NanDisposePersistent(ctx_w->result); ctx_w->result.Reset();
free(ctx_w->include_path); free(ctx_w->include_path);
free(ctx_w->linefeed); free(ctx_w->linefeed);
......
...@@ -14,8 +14,6 @@ ...@@ -14,8 +14,6 @@
extern "C" { extern "C" {
#endif #endif
using namespace v8;
void compile_data(struct Sass_Data_Context* dctx); void compile_data(struct Sass_Data_Context* dctx);
void compile_file(struct Sass_File_Context* fctx); void compile_file(struct Sass_File_Context* fctx);
void compile_it(uv_work_t* req); void compile_it(uv_work_t* req);
...@@ -41,9 +39,9 @@ extern "C" { ...@@ -41,9 +39,9 @@ extern "C" {
uv_work_t request; uv_work_t request;
// v8 and nan related // v8 and nan related
Persistent<Object> result; Nan::Persistent<v8::Object> result;
NanCallback* error_callback; Nan::Callback* error_callback;
NanCallback* success_callback; Nan::Callback* success_callback;
std::vector<std::shared_ptr<CustomFunctionBridge>> function_bridges; std::vector<std::shared_ptr<CustomFunctionBridge>> function_bridges;
std::vector<std::shared_ptr<CustomImporterBridge>> importer_bridges; std::vector<std::shared_ptr<CustomImporterBridge>> importer_bridges;
......
#include <nan.h> #include <nan.h>
#include "boolean.h" #include "boolean.h"
using namespace v8;
namespace SassTypes namespace SassTypes
{ {
Persistent<Function> Boolean::constructor; Nan::Persistent<v8::Function> Boolean::constructor;
bool Boolean::constructor_locked = false; bool Boolean::constructor_locked = false;
Boolean::Boolean(bool v) : value(v) {} Boolean::Boolean(bool v) : value(v) {}
...@@ -15,59 +13,60 @@ namespace SassTypes ...@@ -15,59 +13,60 @@ namespace SassTypes
return v ? instance_true : instance_false; return v ? instance_true : instance_false;
} }
Handle<Function> Boolean::get_constructor() { v8::Local<v8::Function> Boolean::get_constructor() {
Nan::EscapableHandleScope scope;
v8::Local<v8::Function> conslocal;
if (constructor.IsEmpty()) { if (constructor.IsEmpty()) {
Local<FunctionTemplate> tpl = NanNew<FunctionTemplate>(New); v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
tpl->SetClassName(NanNew("SassBoolean")); tpl->SetClassName(Nan::New("SassBoolean").ToLocalChecked());
tpl->InstanceTemplate()->SetInternalFieldCount(1); tpl->InstanceTemplate()->SetInternalFieldCount(1);
tpl->PrototypeTemplate()->Set(NanNew("getValue"), NanNew<FunctionTemplate>(GetValue)->GetFunction()); Nan::SetPrototypeTemplate(tpl, "getValue", Nan::GetFunction(Nan::New<v8::FunctionTemplate>(GetValue)).ToLocalChecked());
NanAssignPersistent(constructor, tpl->GetFunction()); conslocal = Nan::GetFunction(tpl).ToLocalChecked();
constructor.Reset(conslocal);
NanAssignPersistent(get_singleton(false).js_object, NanNew(constructor)->NewInstance()); get_singleton(false).js_object.Reset(Nan::NewInstance(conslocal).ToLocalChecked());
NanSetInternalFieldPointer(NanNew(get_singleton(false).js_object), 0, &get_singleton(false)); Nan::SetInternalFieldPointer(Nan::New(get_singleton(false).js_object), 0, &get_singleton(false));
NanNew(constructor)->Set(NanNew("FALSE"), NanNew(get_singleton(false).js_object)); Nan::Set(conslocal, Nan::New("FALSE").ToLocalChecked(), Nan::New(get_singleton(false).js_object));
NanAssignPersistent(get_singleton(true).js_object, NanNew(constructor)->NewInstance()); get_singleton(true).js_object.Reset(Nan::NewInstance(conslocal).ToLocalChecked());
NanSetInternalFieldPointer(NanNew(get_singleton(true).js_object), 0, &get_singleton(true)); Nan::SetInternalFieldPointer(Nan::New(get_singleton(true).js_object), 0, &get_singleton(true));
NanNew(constructor)->Set(NanNew("TRUE"), NanNew(get_singleton(true).js_object)); Nan::Set(conslocal, Nan::New("TRUE").ToLocalChecked(), Nan::New(get_singleton(true).js_object));
constructor_locked = true; constructor_locked = true;
} else {
conslocal = Nan::New(constructor);
} }
return NanNew(constructor); return scope.Escape(conslocal);
} }
Sass_Value* Boolean::get_sass_value() { Sass_Value* Boolean::get_sass_value() {
return sass_make_boolean(value); return sass_make_boolean(value);
} }
Local<Object> Boolean::get_js_object() { v8::Local<v8::Object> Boolean::get_js_object() {
return NanNew(this->js_object); return Nan::New(this->js_object);
} }
NAN_METHOD(Boolean::New) { NAN_METHOD(Boolean::New) {
NanScope();
if (args.IsConstructCall()) { if (info.IsConstructCall()) {
if (constructor_locked) { if (constructor_locked) {
return NanThrowError(NanNew("Cannot instantiate SassBoolean")); return Nan::ThrowTypeError(Nan::New("Cannot instantiate SassBoolean").ToLocalChecked());
} }
} }
else { else {
if (args.Length() != 1 || !args[0]->IsBoolean()) { if (info.Length() != 1 || !info[0]->IsBoolean()) {
return NanThrowError(NanNew("Expected one boolean argument")); return Nan::ThrowTypeError(Nan::New("Expected one boolean argument").ToLocalChecked());
} }
NanReturnValue(NanNew(get_singleton(args[0]->ToBoolean()->Value()).get_js_object())); info.GetReturnValue().Set(get_singleton(Nan::To<bool>(info[0]).FromJust()).get_js_object());
} }
NanReturnUndefined();
} }
NAN_METHOD(Boolean::GetValue) { NAN_METHOD(Boolean::GetValue) {
NanScope(); info.GetReturnValue().Set(Nan::New(static_cast<Boolean*>(Factory::unwrap(info.This()))->value));
NanReturnValue(NanNew(static_cast<Boolean*>(Factory::unwrap(args.This()))->value));
} }
} }
...@@ -7,15 +7,13 @@ ...@@ -7,15 +7,13 @@
namespace SassTypes namespace SassTypes
{ {
using namespace v8; class Boolean : public SassTypes::Value {
class Boolean : public Value {
public: public:
static Boolean& get_singleton(bool); static Boolean& get_singleton(bool);
static Handle<Function> get_constructor(); static v8::Local<v8::Function> get_constructor();
Sass_Value* get_sass_value(); Sass_Value* get_sass_value();
Local<Object> get_js_object(); v8::Local<v8::Object> get_js_object();
static NAN_METHOD(New); static NAN_METHOD(New);
static NAN_METHOD(GetValue); static NAN_METHOD(GetValue);
...@@ -24,9 +22,9 @@ namespace SassTypes ...@@ -24,9 +22,9 @@ namespace SassTypes
Boolean(bool); Boolean(bool);
bool value; bool value;
Persistent<Object> js_object; Nan::Persistent<v8::Object> js_object;
static Persistent<Function> constructor; static Nan::Persistent<v8::Function> constructor;
static bool constructor_locked; static bool constructor_locked;
}; };
} }
......
#include <nan.h> #include <nan.h>
#include "color.h" #include "color.h"
using namespace v8;
namespace SassTypes namespace SassTypes
{ {
Color::Color(Sass_Value* v) : SassValueWrapper(v) {} Color::Color(Sass_Value* v) : SassValueWrapper(v) {}
Sass_Value* Color::construct(const std::vector<Local<v8::Value>> raw_val) { Sass_Value* Color::construct(const std::vector<v8::Local<v8::Value>> raw_val) {
double a = 1.0, r = 0, g = 0, b = 0; double a = 1.0, r = 0, g = 0, b = 0;
unsigned argb; unsigned argb;
...@@ -17,7 +15,7 @@ namespace SassTypes ...@@ -17,7 +15,7 @@ namespace SassTypes
throw std::invalid_argument("Only argument should be an integer."); throw std::invalid_argument("Only argument should be an integer.");
} }
argb = raw_val[0]->ToInt32()->Value(); argb = Nan::To<int32_t>(raw_val[0]).FromJust();
a = (double)((argb >> 030) & 0xff) / 0xff; a = (double)((argb >> 030) & 0xff) / 0xff;
r = (double)((argb >> 020) & 0xff); r = (double)((argb >> 020) & 0xff);
g = (double)((argb >> 010) & 0xff); g = (double)((argb >> 010) & 0xff);
...@@ -29,7 +27,7 @@ namespace SassTypes ...@@ -29,7 +27,7 @@ namespace SassTypes
throw std::invalid_argument("Constructor arguments should be numbers exclusively."); throw std::invalid_argument("Constructor arguments should be numbers exclusively.");
} }
a = raw_val[3]->ToNumber()->Value(); a = Nan::To<double>(raw_val[3]).FromJust();
// fall through vvv // fall through vvv
case 3: case 3:
...@@ -37,9 +35,9 @@ namespace SassTypes ...@@ -37,9 +35,9 @@ namespace SassTypes
throw std::invalid_argument("Constructor arguments should be numbers exclusively."); throw std::invalid_argument("Constructor arguments should be numbers exclusively.");
} }
r = raw_val[0]->ToNumber()->Value(); r = Nan::To<double>(raw_val[0]).FromJust();
g = raw_val[1]->ToNumber()->Value(); g = Nan::To<double>(raw_val[1]).FromJust();
b = raw_val[2]->ToNumber()->Value(); b = Nan::To<double>(raw_val[2]).FromJust();
break; break;
case 0: case 0:
...@@ -52,86 +50,78 @@ namespace SassTypes ...@@ -52,86 +50,78 @@ namespace SassTypes
return sass_make_color(r, g, b, a); return sass_make_color(r, g, b, a);
} }
void Color::initPrototype(Handle<ObjectTemplate> proto) { void Color::initPrototype(v8::Local<v8::FunctionTemplate> proto) {
proto->Set(NanNew("getR"), NanNew<FunctionTemplate>(GetR)->GetFunction()); Nan::SetPrototypeMethod(proto, "getR", GetR);
proto->Set(NanNew("getG"), NanNew<FunctionTemplate>(GetG)->GetFunction()); Nan::SetPrototypeMethod(proto, "getG", GetG);
proto->Set(NanNew("getB"), NanNew<FunctionTemplate>(GetB)->GetFunction()); Nan::SetPrototypeMethod(proto, "getB", GetB);
proto->Set(NanNew("getA"), NanNew<FunctionTemplate>(GetA)->GetFunction()); Nan::SetPrototypeMethod(proto, "getA", GetA);
proto->Set(NanNew("setR"), NanNew<FunctionTemplate>(SetR)->GetFunction()); Nan::SetPrototypeMethod(proto, "setR", SetR);
proto->Set(NanNew("setG"), NanNew<FunctionTemplate>(SetG)->GetFunction()); Nan::SetPrototypeMethod(proto, "setG", SetG);
proto->Set(NanNew("setB"), NanNew<FunctionTemplate>(SetB)->GetFunction()); Nan::SetPrototypeMethod(proto, "setB", SetB);
proto->Set(NanNew("setA"), NanNew<FunctionTemplate>(SetA)->GetFunction()); Nan::SetPrototypeMethod(proto, "setA", SetA);
} }
NAN_METHOD(Color::GetR) { NAN_METHOD(Color::GetR) {
NanScope(); info.GetReturnValue().Set(sass_color_get_r(unwrap(info.This())->value));
NanReturnValue(NanNew(sass_color_get_r(unwrap(args.This())->value)));
} }
NAN_METHOD(Color::GetG) { NAN_METHOD(Color::GetG) {
NanScope(); info.GetReturnValue().Set(sass_color_get_g(unwrap(info.This())->value));
NanReturnValue(NanNew(sass_color_get_g(unwrap(args.This())->value)));
} }
NAN_METHOD(Color::GetB) { NAN_METHOD(Color::GetB) {
NanScope(); info.GetReturnValue().Set(sass_color_get_b(unwrap(info.This())->value));
NanReturnValue(NanNew(sass_color_get_b(unwrap(args.This())->value)));
} }
NAN_METHOD(Color::GetA) { NAN_METHOD(Color::GetA) {
NanScope(); info.GetReturnValue().Set(sass_color_get_a(unwrap(info.This())->value));
NanReturnValue(NanNew(sass_color_get_a(unwrap(args.This())->value)));
} }
NAN_METHOD(Color::SetR) { NAN_METHOD(Color::SetR) {
if (args.Length() != 1) { if (info.Length() != 1) {
return NanThrowError(NanNew("Expected just one argument")); return Nan::ThrowTypeError(Nan::New("Expected just one argument").ToLocalChecked());
} }
if (!args[0]->IsNumber()) { if (!info[0]->IsNumber()) {
return NanThrowError(NanNew("Supplied value should be a number")); return Nan::ThrowTypeError(Nan::New("Supplied value should be a number").ToLocalChecked());
} }
sass_color_set_r(unwrap(args.This())->value, args[0]->ToNumber()->Value()); sass_color_set_r(unwrap(info.This())->value, Nan::To<double>(info[0]).FromJust());
NanReturnUndefined();
} }
NAN_METHOD(Color::SetG) { NAN_METHOD(Color::SetG) {
if (args.Length() != 1) { if (info.Length() != 1) {
return NanThrowError(NanNew("Expected just one argument")); return Nan::ThrowTypeError(Nan::New("Expected just one argument").ToLocalChecked());
} }
if (!args[0]->IsNumber()) { if (!info[0]->IsNumber()) {
return NanThrowError(NanNew("Supplied value should be a number")); return Nan::ThrowTypeError(Nan::New("Supplied value should be a number").ToLocalChecked());
} }
sass_color_set_g(unwrap(args.This())->value, args[0]->ToNumber()->Value()); sass_color_set_g(unwrap(info.This())->value, Nan::To<double>(info[0]).FromJust());
NanReturnUndefined();
} }
NAN_METHOD(Color::SetB) { NAN_METHOD(Color::SetB) {
if (args.Length() != 1) { if (info.Length() != 1) {
return NanThrowError(NanNew("Expected just one argument")); return Nan::ThrowTypeError(Nan::New("Expected just one argument").ToLocalChecked());
} }
if (!args[0]->IsNumber()) { if (!info[0]->IsNumber()) {
return NanThrowError(NanNew("Supplied value should be a number")); return Nan::ThrowTypeError(Nan::New("Supplied value should be a number").ToLocalChecked());
} }
sass_color_set_b(unwrap(args.This())->value, args[0]->ToNumber()->Value()); sass_color_set_b(unwrap(info.This())->value, Nan::To<double>(info[0]).FromJust());
NanReturnUndefined();
} }
NAN_METHOD(Color::SetA) { NAN_METHOD(Color::SetA) {
if (args.Length() != 1) { if (info.Length() != 1) {
return NanThrowError(NanNew("Expected just one argument")); return Nan::ThrowTypeError(Nan::New("Expected just one argument").ToLocalChecked());
} }
if (!args[0]->IsNumber()) { if (!info[0]->IsNumber()) {
return NanThrowError(NanNew("Supplied value should be a number")); return Nan::ThrowTypeError(Nan::New("Supplied value should be a number").ToLocalChecked());
} }
sass_color_set_a(unwrap(args.This())->value, args[0]->ToNumber()->Value()); sass_color_set_a(unwrap(info.This())->value, Nan::To<double>(info[0]).FromJust());
NanReturnUndefined();
} }
} }
...@@ -6,15 +6,13 @@ ...@@ -6,15 +6,13 @@
namespace SassTypes namespace SassTypes
{ {
using namespace v8;
class Color : public SassValueWrapper<Color> { class Color : public SassValueWrapper<Color> {
public: public:
Color(Sass_Value*); Color(Sass_Value*);
static char const* get_constructor_name() { return "SassColor"; } static char const* get_constructor_name() { return "SassColor"; }
static Sass_Value* construct(const std::vector<Local<v8::Value>>); static Sass_Value* construct(const std::vector<v8::Local<v8::Value>>);
static void initPrototype(Handle<ObjectTemplate>); static void initPrototype(v8::Local<v8::FunctionTemplate>);
static NAN_METHOD(GetR); static NAN_METHOD(GetR);
static NAN_METHOD(GetG); static NAN_METHOD(GetG);
......
...@@ -2,13 +2,11 @@ ...@@ -2,13 +2,11 @@
#include "error.h" #include "error.h"
#include "../create_string.h" #include "../create_string.h"
using namespace v8;
namespace SassTypes namespace SassTypes
{ {
Error::Error(Sass_Value* v) : SassValueWrapper(v) {} Error::Error(Sass_Value* v) : SassValueWrapper(v) {}
Sass_Value* Error::construct(const std::vector<Local<v8::Value>> raw_val) { Sass_Value* Error::construct(const std::vector<v8::Local<v8::Value>> raw_val) {
char const* value = ""; char const* value = "";
if (raw_val.size() >= 1) { if (raw_val.size() >= 1) {
...@@ -22,5 +20,5 @@ namespace SassTypes ...@@ -22,5 +20,5 @@ namespace SassTypes
return sass_make_error(value); return sass_make_error(value);
} }
void Error::initPrototype(Handle<ObjectTemplate>) {} void Error::initPrototype(v8::Local<v8::FunctionTemplate>) {}
} }
...@@ -6,15 +6,13 @@ ...@@ -6,15 +6,13 @@
namespace SassTypes namespace SassTypes
{ {
using namespace v8;
class Error : public SassValueWrapper<Error> { class Error : public SassValueWrapper<Error> {
public: public:
Error(Sass_Value*); Error(Sass_Value*);
static char const* get_constructor_name() { return "SassError"; } static char const* get_constructor_name() { return "SassError"; }
static Sass_Value* construct(const std::vector<Local<v8::Value>>); static Sass_Value* construct(const std::vector<v8::Local<v8::Value>>);
static void initPrototype(Handle<ObjectTemplate>); static void initPrototype(v8::Local<v8::FunctionTemplate>);
}; };
} }
......
...@@ -10,11 +10,9 @@ ...@@ -10,11 +10,9 @@
#include "null.h" #include "null.h"
#include "error.h" #include "error.h"
using namespace v8;
namespace SassTypes namespace SassTypes
{ {
Value* Factory::create(Sass_Value* v) { SassTypes::Value* Factory::create(Sass_Value* v) {
switch (sass_value_get_tag(v)) { switch (sass_value_get_tag(v)) {
case SASS_NUMBER: case SASS_NUMBER:
return new Number(v); return new Number(v);
...@@ -45,26 +43,27 @@ namespace SassTypes ...@@ -45,26 +43,27 @@ namespace SassTypes
} }
} }
void Factory::initExports(Handle<Object> exports) { NAN_MODULE_INIT(Factory::initExports) {
Local<Object> types = NanNew<Object>(); Nan::HandleScope scope;
exports->Set(NanNew("types"), types); v8::Local<v8::Object> types = Nan::New<v8::Object>();
types->Set(NanNew("Number"), Number::get_constructor()); Nan::Set(types, Nan::New("Number").ToLocalChecked(), Number::get_constructor());
types->Set(NanNew("String"), String::get_constructor()); Nan::Set(types, Nan::New("String").ToLocalChecked(), String::get_constructor());
types->Set(NanNew("Color"), Color::get_constructor()); Nan::Set(types, Nan::New("Color").ToLocalChecked(), Color::get_constructor());
types->Set(NanNew("Boolean"), Boolean::get_constructor()); Nan::Set(types, Nan::New("Boolean").ToLocalChecked(), Boolean::get_constructor());
types->Set(NanNew("List"), List::get_constructor()); Nan::Set(types, Nan::New("List").ToLocalChecked(), List::get_constructor());
types->Set(NanNew("Map"), Map::get_constructor()); Nan::Set(types, Nan::New("Map").ToLocalChecked(), Map::get_constructor());
types->Set(NanNew("Null"), Null::get_constructor()); Nan::Set(types, Nan::New("Null").ToLocalChecked(), Null::get_constructor());
types->Set(NanNew("Error"), Error::get_constructor()); Nan::Set(types, Nan::New("Error").ToLocalChecked(), Error::get_constructor());
Nan::Set(target, Nan::New<v8::String>("types").ToLocalChecked(), types);
} }
Value* Factory::unwrap(Handle<v8::Value> obj) { Value* Factory::unwrap(v8::Local<v8::Value> obj) {
// Todo: non-SassValue objects could easily fall under that condition, need to be more specific. // 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<v8::Object>()->InternalFieldCount() != 1) {
throw std::invalid_argument("A SassValue object was expected."); throw std::invalid_argument("A SassValue object was expected.");
} }
return static_cast<Value*>(NanGetInternalFieldPointer(obj->ToObject(), 0)); return static_cast<Value*>(Nan::GetInternalFieldPointer(obj.As<v8::Object>(), 0));
} }
} }
...@@ -7,15 +7,13 @@ ...@@ -7,15 +7,13 @@
namespace SassTypes namespace SassTypes
{ {
using namespace v8;
// This is the guru that knows everything about instantiating the right subclass of SassTypes::Value // This is the guru that knows everything about instantiating the right subclass of SassTypes::Value
// to wrap a given Sass_Value object. // to wrap a given Sass_Value object.
class Factory { class Factory {
public: public:
static void initExports(Handle<Object>); static NAN_MODULE_INIT(initExports);
static Value* create(Sass_Value*); static Value* create(Sass_Value*);
static Value* unwrap(Handle<v8::Value>); static Value* unwrap(v8::Local<v8::Value>);
}; };
} }
......
#include <nan.h> #include <nan.h>
#include "list.h" #include "list.h"
using namespace v8;
namespace SassTypes namespace SassTypes
{ {
List::List(Sass_Value* v) : SassValueWrapper(v) {} List::List(Sass_Value* v) : SassValueWrapper(v) {}
Sass_Value* List::construct(const std::vector<Local<v8::Value>> raw_val) { Sass_Value* List::construct(const std::vector<v8::Local<v8::Value>> raw_val) {
size_t length = 0; size_t length = 0;
bool comma = true; bool comma = true;
...@@ -16,88 +14,83 @@ namespace SassTypes ...@@ -16,88 +14,83 @@ namespace SassTypes
throw std::invalid_argument("First argument should be an integer."); throw std::invalid_argument("First argument should be an integer.");
} }
length = raw_val[0]->ToInt32()->Value(); length = Nan::To<uint32_t>(raw_val[0]).FromJust();
if (raw_val.size() >= 2) { if (raw_val.size() >= 2) {
if (!raw_val[1]->IsBoolean()) { if (!raw_val[1]->IsBoolean()) {
throw std::invalid_argument("Second argument should be a boolean."); throw std::invalid_argument("Second argument should be a boolean.");
} }
comma = raw_val[1]->ToBoolean()->Value(); comma = Nan::To<bool>(raw_val[1]).FromJust();
} }
} }
return sass_make_list(length, comma ? SASS_COMMA : SASS_SPACE); return sass_make_list(length, comma ? SASS_COMMA : SASS_SPACE);
} }
void List::initPrototype(Handle<ObjectTemplate> proto) { void List::initPrototype(v8::Local<v8::FunctionTemplate> proto) {
proto->Set(NanNew("getLength"), NanNew<FunctionTemplate>(GetLength)->GetFunction()); Nan::SetPrototypeMethod(proto, "getLength", GetLength);
proto->Set(NanNew("getSeparator"), NanNew<FunctionTemplate>(GetSeparator)->GetFunction()); Nan::SetPrototypeMethod(proto, "getSeparator", GetSeparator);
proto->Set(NanNew("setSeparator"), NanNew<FunctionTemplate>(SetSeparator)->GetFunction()); Nan::SetPrototypeMethod(proto, "setSeparator", SetSeparator);
proto->Set(NanNew("getValue"), NanNew<FunctionTemplate>(GetValue)->GetFunction()); Nan::SetPrototypeMethod(proto, "getValue", GetValue);
proto->Set(NanNew("setValue"), NanNew<FunctionTemplate>(SetValue)->GetFunction()); Nan::SetPrototypeMethod(proto, "setValue", SetValue);
} }
NAN_METHOD(List::GetValue) { NAN_METHOD(List::GetValue) {
NanScope();
if (args.Length() != 1) { if (info.Length() != 1) {
return NanThrowError(NanNew("Expected just one argument")); return Nan::ThrowTypeError(Nan::New("Expected just one argument").ToLocalChecked());
} }
if (!args[0]->IsNumber()) { if (!info[0]->IsNumber()) {
return NanThrowError(NanNew("Supplied index should be an integer")); return Nan::ThrowTypeError(Nan::New("Supplied index should be an integer").ToLocalChecked());
} }
Sass_Value* list = unwrap(args.This())->value; Sass_Value* list = unwrap(info.This())->value;
size_t index = args[0]->ToInt32()->Value(); size_t index = Nan::To<uint32_t>(info[0]).FromJust();
if (index >= sass_list_get_length(list)) { if (index >= sass_list_get_length(list)) {
return NanThrowError(NanNew("Out of bound index")); return Nan::ThrowRangeError(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, Nan::To<uint32_t>(info[0]).FromJust()))->get_js_object());
} }
NAN_METHOD(List::SetValue) { NAN_METHOD(List::SetValue) {
if (args.Length() != 2) { if (info.Length() != 2) {
return NanThrowError(NanNew("Expected two arguments")); return Nan::ThrowTypeError(Nan::New("Expected two arguments").ToLocalChecked());
} }
if (!args[0]->IsNumber()) { if (!info[0]->IsNumber()) {
return NanThrowError(NanNew("Supplied index should be an integer")); return Nan::ThrowTypeError(Nan::New("Supplied index should be an integer").ToLocalChecked());
} }
if (!args[1]->IsObject()) { if (!info[1]->IsObject()) {
return NanThrowError(NanNew("Supplied value should be a SassValue object")); return Nan::ThrowTypeError(Nan::New("Supplied value should be a SassValue object").ToLocalChecked());
} }
Value* sass_value = Factory::unwrap(args[1]); Value* sass_value = Factory::unwrap(info[1]);
sass_list_set_value(unwrap(args.This())->value, args[0]->ToInt32()->Value(), sass_value->get_sass_value()); sass_list_set_value(unwrap(info.This())->value, Nan::To<uint32_t>(info[0]).FromJust(), sass_value->get_sass_value());
NanReturnUndefined();
} }
NAN_METHOD(List::GetSeparator) { NAN_METHOD(List::GetSeparator) {
NanScope(); info.GetReturnValue().Set(sass_list_get_separator(unwrap(info.This())->value) == SASS_COMMA);
NanReturnValue(NanNew(sass_list_get_separator(unwrap(args.This())->value) == SASS_COMMA));
} }
NAN_METHOD(List::SetSeparator) { NAN_METHOD(List::SetSeparator) {
if (args.Length() != 1) { if (info.Length() != 1) {
return NanThrowError(NanNew("Expected just one argument")); return Nan::ThrowTypeError(Nan::New("Expected just one argument").ToLocalChecked());
} }
if (!args[0]->IsBoolean()) { if (!info[0]->IsBoolean()) {
return NanThrowError(NanNew("Supplied value should be a boolean")); return Nan::ThrowTypeError(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); sass_list_set_separator(unwrap(info.This())->value, Nan::To<bool>(info[0]).FromJust() ? SASS_COMMA : SASS_SPACE);
NanReturnUndefined();
} }
NAN_METHOD(List::GetLength) { NAN_METHOD(List::GetLength) {
NanScope(); info.GetReturnValue().Set(Nan::New<v8::Number>(sass_list_get_length(unwrap(info.This())->value)));
NanReturnValue(NanNew<v8::Number>(sass_list_get_length(unwrap(args.This())->value)));
} }
} }
...@@ -6,15 +6,13 @@ ...@@ -6,15 +6,13 @@
namespace SassTypes namespace SassTypes
{ {
using namespace v8;
class List : public SassValueWrapper<List> { class List : public SassValueWrapper<List> {
public: public:
List(Sass_Value*); List(Sass_Value*);
static char const* get_constructor_name() { return "SassList"; } static char const* get_constructor_name() { return "SassList"; }
static Sass_Value* construct(const std::vector<Local<v8::Value>>); static Sass_Value* construct(const std::vector<v8::Local<v8::Value>>);
static void initPrototype(Handle<ObjectTemplate>); static void initPrototype(v8::Local<v8::FunctionTemplate>);
static NAN_METHOD(GetValue); static NAN_METHOD(GetValue);
static NAN_METHOD(SetValue); static NAN_METHOD(SetValue);
......
#include <nan.h> #include <nan.h>
#include "map.h" #include "map.h"
using namespace v8;
namespace SassTypes namespace SassTypes
{ {
Map::Map(Sass_Value* v) : SassValueWrapper(v) {} Map::Map(Sass_Value* v) : SassValueWrapper(v) {}
Sass_Value* Map::construct(const std::vector<Local<v8::Value>> raw_val) { Sass_Value* Map::construct(const std::vector<v8::Local<v8::Value>> raw_val) {
size_t length = 0; size_t length = 0;
if (raw_val.size() >= 1) { if (raw_val.size() >= 1) {
...@@ -15,102 +13,97 @@ namespace SassTypes ...@@ -15,102 +13,97 @@ namespace SassTypes
throw std::invalid_argument("First argument should be an integer."); throw std::invalid_argument("First argument should be an integer.");
} }
length = raw_val[0]->ToInt32()->Value(); length = Nan::To<uint32_t>(raw_val[0]).FromJust();
} }
return sass_make_map(length); return sass_make_map(length);
} }
void Map::initPrototype(Handle<ObjectTemplate> proto) { void Map::initPrototype(v8::Local<v8::FunctionTemplate> proto) {
proto->Set(NanNew("getLength"), NanNew<FunctionTemplate>(GetLength)->GetFunction()); Nan::SetPrototypeMethod(proto, "getLength", GetLength);
proto->Set(NanNew("getKey"), NanNew<FunctionTemplate>(GetKey)->GetFunction()); Nan::SetPrototypeMethod(proto, "getKey", GetKey);
proto->Set(NanNew("setKey"), NanNew<FunctionTemplate>(SetKey)->GetFunction()); Nan::SetPrototypeMethod(proto, "setKey", SetKey);
proto->Set(NanNew("getValue"), NanNew<FunctionTemplate>(GetValue)->GetFunction()); Nan::SetPrototypeMethod(proto, "getValue", GetValue);
proto->Set(NanNew("setValue"), NanNew<FunctionTemplate>(SetValue)->GetFunction()); Nan::SetPrototypeMethod(proto, "setValue", SetValue);
} }
NAN_METHOD(Map::GetValue) { NAN_METHOD(Map::GetValue) {
NanScope();
if (args.Length() != 1) { if (info.Length() != 1) {
return NanThrowError(NanNew("Expected just one argument")); return Nan::ThrowTypeError(Nan::New("Expected just one argument").ToLocalChecked());
} }
if (!args[0]->IsNumber()) { if (!info[0]->IsNumber()) {
return NanThrowError(NanNew("Supplied index should be an integer")); return Nan::ThrowTypeError(Nan::New("Supplied index should be an integer").ToLocalChecked());
} }
Sass_Value* map = unwrap(args.This())->value; Sass_Value* map = unwrap(info.This())->value;
size_t index = args[0]->ToInt32()->Value(); size_t index = Nan::To<uint32_t>(info[0]).FromJust();
if (index >= sass_map_get_length(map)) { if (index >= sass_map_get_length(map)) {
return NanThrowError(NanNew("Out of bound index")); return Nan::ThrowRangeError(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, Nan::To<uint32_t>(info[0]).FromJust()))->get_js_object());
} }
NAN_METHOD(Map::SetValue) { NAN_METHOD(Map::SetValue) {
if (args.Length() != 2) { if (info.Length() != 2) {
return NanThrowError(NanNew("Expected two arguments")); return Nan::ThrowTypeError(Nan::New("Expected two arguments").ToLocalChecked());
} }
if (!args[0]->IsNumber()) { if (!info[0]->IsNumber()) {
return NanThrowError(NanNew("Supplied index should be an integer")); return Nan::ThrowTypeError(Nan::New("Supplied index should be an integer").ToLocalChecked());
} }
if (!args[1]->IsObject()) { if (!info[1]->IsObject()) {
return NanThrowError(NanNew("Supplied value should be a SassValue object")); return Nan::ThrowTypeError(Nan::New("Supplied value should be a SassValue object").ToLocalChecked());
} }
Value* sass_value = Factory::unwrap(args[1]); Value* sass_value = Factory::unwrap(info[1]);
sass_map_set_value(unwrap(args.This())->value, args[0]->ToInt32()->Value(), sass_value->get_sass_value()); sass_map_set_value(unwrap(info.This())->value, Nan::To<uint32_t>(info[0]).FromJust(), sass_value->get_sass_value());
NanReturnUndefined();
} }
NAN_METHOD(Map::GetKey) { NAN_METHOD(Map::GetKey) {
NanScope();
if (args.Length() != 1) { if (info.Length() != 1) {
return NanThrowError(NanNew("Expected just one argument")); return Nan::ThrowTypeError(Nan::New("Expected just one argument").ToLocalChecked());
} }
if (!args[0]->IsNumber()) { if (!info[0]->IsNumber()) {
return NanThrowError(NanNew("Supplied index should be an integer")); return Nan::ThrowTypeError(Nan::New("Supplied index should be an integer").ToLocalChecked());
} }
Sass_Value* map = unwrap(args.This())->value; Sass_Value* map = unwrap(info.This())->value;
size_t index = args[0]->ToInt32()->Value(); size_t index = Nan::To<uint32_t>(info[0]).FromJust();
if (index >= sass_map_get_length(map)) { if (index >= sass_map_get_length(map)) {
return NanThrowError(NanNew("Out of bound index")); return Nan::ThrowRangeError(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, Nan::To<uint32_t>(info[0]).FromJust()))->get_js_object());
} }
NAN_METHOD(Map::SetKey) { NAN_METHOD(Map::SetKey) {
if (args.Length() != 2) { if (info.Length() != 2) {
return NanThrowError(NanNew("Expected two arguments")); return Nan::ThrowTypeError(Nan::New("Expected two arguments").ToLocalChecked());
} }
if (!args[0]->IsNumber()) { if (!info[0]->IsNumber()) {
return NanThrowError(NanNew("Supplied index should be an integer")); return Nan::ThrowTypeError(Nan::New("Supplied index should be an integer").ToLocalChecked());
} }
if (!args[1]->IsObject()) { if (!info[1]->IsObject()) {
return NanThrowError(NanNew("Supplied value should be a SassValue object")); return Nan::ThrowTypeError(Nan::New("Supplied value should be a SassValue object").ToLocalChecked());
} }
Value* sass_value = Factory::unwrap(args[1]); Value* sass_value = Factory::unwrap(info[1]);
sass_map_set_key(unwrap(args.This())->value, args[0]->ToInt32()->Value(), sass_value->get_sass_value()); sass_map_set_key(unwrap(info.This())->value, Nan::To<uint32_t>(info[0]).FromJust(), sass_value->get_sass_value());
NanReturnUndefined();
} }
NAN_METHOD(Map::GetLength) { NAN_METHOD(Map::GetLength) {
NanScope(); info.GetReturnValue().Set(Nan::New<v8::Number>(sass_map_get_length(unwrap(info.This())->value)));
NanReturnValue(NanNew<v8::Number>(sass_map_get_length(unwrap(args.This())->value)));
} }
} }
...@@ -6,15 +6,13 @@ ...@@ -6,15 +6,13 @@
namespace SassTypes namespace SassTypes
{ {
using namespace v8;
class Map : public SassValueWrapper<Map> { class Map : public SassValueWrapper<Map> {
public: public:
Map(Sass_Value*); Map(Sass_Value*);
static char const* get_constructor_name() { return "SassMap"; } static char const* get_constructor_name() { return "SassMap"; }
static Sass_Value* construct(const std::vector<Local<v8::Value>>); static Sass_Value* construct(const std::vector<v8::Local<v8::Value>>);
static void initPrototype(Handle<ObjectTemplate>); static void initPrototype(v8::Local<v8::FunctionTemplate>);
static NAN_METHOD(GetValue); static NAN_METHOD(GetValue);
static NAN_METHOD(SetValue); static NAN_METHOD(SetValue);
......
#include <nan.h> #include <nan.h>
#include "null.h" #include "null.h"
using namespace v8;
namespace SassTypes namespace SassTypes
{ {
Persistent<Function> Null::constructor; Nan::Persistent<v8::Function> Null::constructor;
bool Null::constructor_locked = false; bool Null::constructor_locked = false;
Null::Null() {} Null::Null() {}
...@@ -15,45 +13,47 @@ namespace SassTypes ...@@ -15,45 +13,47 @@ namespace SassTypes
return singleton_instance; return singleton_instance;
} }
Handle<Function> Null::get_constructor() { v8::Local<v8::Function> Null::get_constructor() {
Nan::EscapableHandleScope scope;
v8::Local<v8::Function> conslocal;
if (constructor.IsEmpty()) { if (constructor.IsEmpty()) {
Local<FunctionTemplate> tpl = NanNew<FunctionTemplate>(New); v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
tpl->SetClassName(NanNew("SassNull")); tpl->SetClassName(Nan::New("SassNull").ToLocalChecked());
tpl->InstanceTemplate()->SetInternalFieldCount(1); tpl->InstanceTemplate()->SetInternalFieldCount(1);
NanAssignPersistent(constructor, tpl->GetFunction()); conslocal = Nan::GetFunction(tpl).ToLocalChecked();
constructor.Reset(conslocal);
NanAssignPersistent(get_singleton().js_object, NanNew(constructor)->NewInstance()); get_singleton().js_object.Reset(Nan::NewInstance(conslocal).ToLocalChecked());
NanSetInternalFieldPointer(NanNew(get_singleton().js_object), 0, &get_singleton()); Nan::SetInternalFieldPointer(Nan::New(get_singleton().js_object), 0, &get_singleton());
NanNew(constructor)->Set(NanNew("NULL"), NanNew(get_singleton().js_object)); Nan::Set(conslocal, Nan::New("NULL").ToLocalChecked(), Nan::New(get_singleton().js_object));
constructor_locked = true; constructor_locked = true;
} else {
conslocal = Nan::New(constructor);
} }
return NanNew(constructor); return scope.Escape(conslocal);
} }
Sass_Value* Null::get_sass_value() { Sass_Value* Null::get_sass_value() {
return sass_make_null(); return sass_make_null();
} }
Local<Object> Null::get_js_object() { v8::Local<v8::Object> Null::get_js_object() {
return NanNew(this->js_object); return Nan::New(this->js_object);
} }
NAN_METHOD(Null::New) { NAN_METHOD(Null::New) {
NanScope();
if (args.IsConstructCall()) { if (info.IsConstructCall()) {
if (constructor_locked) { if (constructor_locked) {
return NanThrowError(NanNew("Cannot instantiate SassNull")); return Nan::ThrowTypeError(Nan::New("Cannot instantiate SassNull").ToLocalChecked());
} }
} }
else { else {
NanReturnValue(NanNew(get_singleton().get_js_object())); info.GetReturnValue().Set(get_singleton().get_js_object());
} }
NanReturnUndefined();
} }
} }
...@@ -6,24 +6,22 @@ ...@@ -6,24 +6,22 @@
namespace SassTypes namespace SassTypes
{ {
using namespace v8; class Null : public SassTypes::Value {
class Null : public Value {
public: public:
static Null& get_singleton(); static Null& get_singleton();
static Handle<Function> get_constructor(); static v8::Local<v8::Function> get_constructor();
Sass_Value* get_sass_value(); Sass_Value* get_sass_value();
Local<Object> get_js_object(); v8::Local<v8::Object> get_js_object();
static NAN_METHOD(New); static NAN_METHOD(New);
private: private:
Null(); Null();
Persistent<Object> js_object; Nan::Persistent<v8::Object> js_object;
static Persistent<Function> constructor; static Nan::Persistent<v8::Function> constructor;
static bool constructor_locked; static bool constructor_locked;
}; };
} }
......
...@@ -2,13 +2,11 @@ ...@@ -2,13 +2,11 @@
#include "number.h" #include "number.h"
#include "../create_string.h" #include "../create_string.h"
using namespace v8;
namespace SassTypes namespace SassTypes
{ {
Number::Number(Sass_Value* v) : SassValueWrapper(v) {} Number::Number(Sass_Value* v) : SassValueWrapper(v) {}
Sass_Value* Number::construct(const std::vector<Local<v8::Value>> raw_val) { Sass_Value* Number::construct(const std::vector<v8::Local<v8::Value>> raw_val) {
double value = 0; double value = 0;
char const* unit = ""; char const* unit = "";
...@@ -17,7 +15,7 @@ namespace SassTypes ...@@ -17,7 +15,7 @@ namespace SassTypes
throw std::invalid_argument("First argument should be a number."); throw std::invalid_argument("First argument should be a number.");
} }
value = raw_val[0]->ToNumber()->Value(); value = Nan::To<double>(raw_val[0]).FromJust();
if (raw_val.size() >= 2) { if (raw_val.size() >= 2) {
if (!raw_val[1]->IsString()) { if (!raw_val[1]->IsString()) {
...@@ -31,48 +29,43 @@ namespace SassTypes ...@@ -31,48 +29,43 @@ namespace SassTypes
return sass_make_number(value, unit); return sass_make_number(value, unit);
} }
void Number::initPrototype(Handle<ObjectTemplate> proto) { void Number::initPrototype(v8::Local<v8::FunctionTemplate> proto) {
proto->Set(NanNew("getValue"), NanNew<FunctionTemplate>(GetValue)->GetFunction()); Nan::SetPrototypeMethod(proto, "getValue", GetValue);
proto->Set(NanNew("getUnit"), NanNew<FunctionTemplate>(GetUnit)->GetFunction()); Nan::SetPrototypeMethod(proto, "getUnit", GetUnit);
proto->Set(NanNew("setValue"), NanNew<FunctionTemplate>(SetValue)->GetFunction()); Nan::SetPrototypeMethod(proto, "setValue", SetValue);
proto->Set(NanNew("setUnit"), NanNew<FunctionTemplate>(SetUnit)->GetFunction()); Nan::SetPrototypeMethod(proto, "setUnit", SetUnit);
} }
NAN_METHOD(Number::GetValue) { NAN_METHOD(Number::GetValue) {
NanScope(); info.GetReturnValue().Set(Nan::New<v8::Number>(sass_number_get_value(unwrap(info.This())->value)));
NanReturnValue(NanNew(sass_number_get_value(unwrap(args.This())->value)));
} }
NAN_METHOD(Number::GetUnit) { NAN_METHOD(Number::GetUnit) {
NanScope(); info.GetReturnValue().Set(Nan::New<v8::String>(sass_number_get_unit(unwrap(info.This())->value)).ToLocalChecked());
NanReturnValue(NanNew(sass_number_get_unit(unwrap(args.This())->value)));
} }
NAN_METHOD(Number::SetValue) { NAN_METHOD(Number::SetValue) {
NanScope();
if (args.Length() != 1) { if (info.Length() != 1) {
return NanThrowError(NanNew("Expected just one argument")); return Nan::ThrowTypeError(Nan::New("Expected just one argument").ToLocalChecked());
} }
if (!args[0]->IsNumber()) { if (!info[0]->IsNumber()) {
return NanThrowError(NanNew("Supplied value should be a number")); return Nan::ThrowTypeError(Nan::New("Supplied value should be a number").ToLocalChecked());
} }
sass_number_set_value(unwrap(args.This())->value, args[0]->ToNumber()->Value()); sass_number_set_value(unwrap(info.This())->value, Nan::To<double>(info[0]).FromJust());
NanReturnUndefined();
} }
NAN_METHOD(Number::SetUnit) { NAN_METHOD(Number::SetUnit) {
if (args.Length() != 1) { if (info.Length() != 1) {
return NanThrowError(NanNew("Expected just one argument")); return Nan::ThrowTypeError(Nan::New("Expected just one argument").ToLocalChecked());
} }
if (!args[0]->IsString()) { if (!info[0]->IsString()) {
return NanThrowError(NanNew("Supplied value should be a string")); return Nan::ThrowTypeError(Nan::New("Supplied value should be a string").ToLocalChecked());
} }
sass_number_set_unit(unwrap(args.This())->value, create_string(args[0])); sass_number_set_unit(unwrap(info.This())->value, create_string(info[0]));
NanReturnUndefined();
} }
} }
...@@ -6,15 +6,14 @@ ...@@ -6,15 +6,14 @@
namespace SassTypes namespace SassTypes
{ {
using namespace v8;
class Number : public SassValueWrapper<Number> { class Number : public SassValueWrapper<Number> {
public: public:
Number(Sass_Value*); Number(Sass_Value*);
static char const* get_constructor_name() { return "SassNumber"; } static char const* get_constructor_name() { return "SassNumber"; }
static Sass_Value* construct(const std::vector<Local<v8::Value>>); static Sass_Value* construct(const std::vector<v8::Local<v8::Value>>);
static void initPrototype(Handle<ObjectTemplate>); static void initPrototype(v8::Local<v8::FunctionTemplate>);
static NAN_METHOD(GetValue); static NAN_METHOD(GetValue);
static NAN_METHOD(GetUnit); static NAN_METHOD(GetUnit);
......
...@@ -9,12 +9,10 @@ ...@@ -9,12 +9,10 @@
namespace SassTypes namespace SassTypes
{ {
using namespace v8;
// Include this in any SassTypes::Value subclasses to handle all the heavy lifting of constructing JS // Include this in any SassTypes::Value subclasses to handle all the heavy lifting of constructing JS
// objects and wrapping sass values inside them // objects and wrapping sass values inside them
template <class T> template <class T>
class SassValueWrapper : public Value { class SassValueWrapper : public SassTypes::Value {
public: public:
static char const* get_constructor_name() { return "SassValue"; } static char const* get_constructor_name() { return "SassValue"; }
...@@ -22,23 +20,23 @@ namespace SassTypes ...@@ -22,23 +20,23 @@ namespace SassTypes
virtual ~SassValueWrapper(); virtual ~SassValueWrapper();
Sass_Value* get_sass_value(); Sass_Value* get_sass_value();
Local<Object> get_js_object(); v8::Local<v8::Object> get_js_object();
static Handle<Function> get_constructor(); static v8::Local<v8::Function> get_constructor();
static Local<FunctionTemplate> get_constructor_template(); static v8::Local<v8::FunctionTemplate> get_constructor_template();
static NAN_METHOD(New); static NAN_METHOD(New);
protected: protected:
Sass_Value* value; Sass_Value* value;
static T* unwrap(Local<Object>); static T* unwrap(v8::Local<v8::Object>);
private: private:
static Persistent<Function> constructor; static Nan::Persistent<v8::Function> constructor;
Persistent<Object> js_object; Nan::Persistent<v8::Object> js_object;
}; };
template <class T> template <class T>
Persistent<Function> SassValueWrapper<T>::constructor; Nan::Persistent<v8::Function> SassValueWrapper<T>::constructor;
template <class T> template <class T>
SassValueWrapper<T>::SassValueWrapper(Sass_Value* v) { SassValueWrapper<T>::SassValueWrapper(Sass_Value* v) {
...@@ -47,7 +45,7 @@ namespace SassTypes ...@@ -47,7 +45,7 @@ namespace SassTypes
template <class T> template <class T>
SassValueWrapper<T>::~SassValueWrapper() { SassValueWrapper<T>::~SassValueWrapper() {
NanDisposePersistent(this->js_object); this->js_object.Reset();
sass_delete_value(this->value); sass_delete_value(this->value);
} }
...@@ -57,74 +55,64 @@ namespace SassTypes ...@@ -57,74 +55,64 @@ namespace SassTypes
} }
template <class T> template <class T>
Local<Object> SassValueWrapper<T>::get_js_object() { v8::Local<v8::Object> SassValueWrapper<T>::get_js_object() {
if (this->js_object.IsEmpty()) { if (this->js_object.IsEmpty()) {
Local<Object> wrapper = NanNew(T::get_constructor())->NewInstance(); v8::Local<v8::Object> wrapper = Nan::NewInstance(T::get_constructor()).ToLocalChecked();
delete static_cast<T*>(NanGetInternalFieldPointer(wrapper, 0)); delete static_cast<T*>(Nan::GetInternalFieldPointer(wrapper, 0));
NanSetInternalFieldPointer(wrapper, 0, this); Nan::SetInternalFieldPointer(wrapper, 0, this);
NanAssignPersistent(this->js_object, wrapper); this->js_object.Reset(wrapper);
} }
return NanNew(this->js_object); return Nan::New(this->js_object);
} }
template <class T> template <class T>
Local<FunctionTemplate> SassValueWrapper<T>::get_constructor_template() { v8::Local<v8::FunctionTemplate> SassValueWrapper<T>::get_constructor_template() {
Local<FunctionTemplate> tpl = NanNew<FunctionTemplate>(New); Nan::EscapableHandleScope scope;
tpl->SetClassName(NanNew(NanNew(T::get_constructor_name()))); v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
tpl->SetClassName(Nan::New<v8::String>(T::get_constructor_name()).ToLocalChecked());
tpl->InstanceTemplate()->SetInternalFieldCount(1); tpl->InstanceTemplate()->SetInternalFieldCount(1);
T::initPrototype(tpl->PrototypeTemplate()); T::initPrototype(tpl);
return tpl; return scope.Escape(tpl);
} }
template <class T> template <class T>
Handle<Function> SassValueWrapper<T>::get_constructor() { v8::Local<v8::Function> SassValueWrapper<T>::get_constructor() {
if (constructor.IsEmpty()) { 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 <class T> template <class T>
NAN_METHOD(SassValueWrapper<T>::New) { NAN_METHOD(SassValueWrapper<T>::New) {
NanScope(); std::vector<v8::Local<v8::Value>> localArgs(info.Length());
if (!args.IsConstructCall()) {
unsigned argc = args.Length();
std::vector<Handle<v8::Value>> argv;
argv.reserve(argc);
for (unsigned i = 0; i < argc; i++) {
argv.push_back(args[i]);
}
NanReturnValue(NanNew(T::get_constructor())->NewInstance(argc, &argv[0])); for (auto i = 0; i < info.Length(); ++i) {
localArgs[i] = info[i];
} }
if (info.IsConstructCall()) {
std::vector<Local<v8::Value>> localArgs(args.Length()); try {
Sass_Value* value = T::construct(localArgs);
for (auto i = 0; i < args.Length(); ++i) { T* obj = new T(value);
localArgs[i] = args[i]; sass_delete_value(value);
}
Nan::SetInternalFieldPointer(info.This(), 0, obj);
try { obj->js_object.Reset(info.This());
Sass_Value* value = T::construct(localArgs); } catch (const std::exception& e) {
T* obj = new T(value); return Nan::ThrowError(Nan::New<v8::String>(e.what()).ToLocalChecked());
sass_delete_value(value); }
} else {
NanSetInternalFieldPointer(args.This(), 0, obj); v8::Local<v8::Function> cons = T::get_constructor();
NanAssignPersistent(obj->js_object, args.This()); v8::Local<v8::Object> inst = Nan::NewInstance(cons, info.Length(), &localArgs[0]).ToLocalChecked();
} catch (const std::exception& e) { info.GetReturnValue().Set(inst);
return NanThrowError(NanNew(e.what()));
} }
NanReturnUndefined();
} }
template <class T> template <class T>
T* SassValueWrapper<T>::unwrap(Local<Object> obj) { T* SassValueWrapper<T>::unwrap(v8::Local<v8::Object> obj) {
return static_cast<T*>(Factory::unwrap(obj)); return static_cast<T*>(Factory::unwrap(obj));
} }
} }
......
...@@ -2,13 +2,11 @@ ...@@ -2,13 +2,11 @@
#include "string.h" #include "string.h"
#include "../create_string.h" #include "../create_string.h"
using namespace v8;
namespace SassTypes namespace SassTypes
{ {
String::String(Sass_Value* v) : SassValueWrapper(v) {} String::String(Sass_Value* v) : SassValueWrapper(v) {}
Sass_Value* String::construct(const std::vector<Local<v8::Value>> raw_val) { Sass_Value* String::construct(const std::vector<v8::Local<v8::Value>> raw_val) {
char const* value = ""; char const* value = "";
if (raw_val.size() >= 1) { if (raw_val.size() >= 1) {
...@@ -22,26 +20,24 @@ namespace SassTypes ...@@ -22,26 +20,24 @@ namespace SassTypes
return sass_make_string(value); return sass_make_string(value);
} }
void String::initPrototype(Handle<ObjectTemplate> proto) { void String::initPrototype(v8::Local<v8::FunctionTemplate> proto) {
proto->Set(NanNew("getValue"), NanNew<FunctionTemplate>(GetValue)->GetFunction()); Nan::SetPrototypeMethod(proto, "getValue", GetValue);
proto->Set(NanNew("setValue"), NanNew<FunctionTemplate>(SetValue)->GetFunction()); Nan::SetPrototypeMethod(proto, "setValue", SetValue);
} }
NAN_METHOD(String::GetValue) { NAN_METHOD(String::GetValue) {
NanScope(); info.GetReturnValue().Set(Nan::New<v8::String>(sass_string_get_value(unwrap(info.This())->value)).ToLocalChecked());
NanReturnValue(NanNew(sass_string_get_value(unwrap(args.This())->value)));
} }
NAN_METHOD(String::SetValue) { NAN_METHOD(String::SetValue) {
if (args.Length() != 1) { if (info.Length() != 1) {
return NanThrowError(NanNew("Expected just one argument")); return Nan::ThrowTypeError(Nan::New("Expected just one argument").ToLocalChecked());
} }
if (!args[0]->IsString()) { if (!info[0]->IsString()) {
return NanThrowError(NanNew("Supplied value should be a string")); return Nan::ThrowTypeError(Nan::New("Supplied value should be a string").ToLocalChecked());
} }
sass_string_set_value(unwrap(args.This())->value, create_string(args[0])); sass_string_set_value(unwrap(info.This())->value, create_string(info[0]));
NanReturnUndefined();
} }
} }
...@@ -6,15 +6,13 @@ ...@@ -6,15 +6,13 @@
namespace SassTypes namespace SassTypes
{ {
using namespace v8;
class String : public SassValueWrapper<String> { class String : public SassValueWrapper<String> {
public: public:
String(Sass_Value*); String(Sass_Value*);
static char const* get_constructor_name() { return "SassString"; } static char const* get_constructor_name() { return "SassString"; }
static Sass_Value* construct(const std::vector<Local<v8::Value>>); static Sass_Value* construct(const std::vector<v8::Local<v8::Value>>);
static void initPrototype(Handle<ObjectTemplate>); static void initPrototype(v8::Local<v8::FunctionTemplate>);
static NAN_METHOD(GetValue); static NAN_METHOD(GetValue);
static NAN_METHOD(SetValue); static NAN_METHOD(SetValue);
......
...@@ -6,13 +6,11 @@ ...@@ -6,13 +6,11 @@
namespace SassTypes namespace SassTypes
{ {
using namespace v8;
// This is the interface that all sass values must comply with // This is the interface that all sass values must comply with
class Value { class Value {
public: public:
virtual Sass_Value* get_sass_value() =0; virtual Sass_Value* get_sass_value() =0;
virtual Local<Object> get_js_object() =0; virtual v8::Local<v8::Object> get_js_object() =0;
}; };
} }
......
...@@ -1032,6 +1032,9 @@ describe('api', function() { ...@@ -1032,6 +1032,9 @@ describe('api', function() {
it('should throw error for bad input', function(done) { it('should throw error for bad input', function(done) {
assert.throws(function() { assert.throws(function() {
sass.renderSync('somestring');
});
assert.throws(function() {
sass.renderSync({ data: '#navbar width 80%;' }); sass.renderSync({ data: '#navbar width 80%;' });
}); });
......
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();
});
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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment