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 @@
"glob": "^5.0.13",
"meow": "^3.3.0",
"mkdirp": "^0.5.1",
"nan": "^1.8.4",
"nan": "^2.0.1",
"npmconf": "^2.1.2",
"pangyp": "^2.2.1",
"request": "^2.58.0",
......
......@@ -8,12 +8,10 @@
#define COMMA ,
using namespace v8;
template <typename T, typename L = void*>
class CallbackBridge {
public:
CallbackBridge(NanCallback*, bool);
CallbackBridge(Nan::Callback*, bool);
virtual ~CallbackBridge();
// Executes the callback
......@@ -22,12 +20,12 @@ class CallbackBridge {
protected:
// We will expose a bridge object to the JS callback that wraps this instance so we don't loose context.
// This is the V8 constructor for such objects.
static Handle<Function> get_wrapper_constructor();
static Nan::MaybeLocal<v8::Function> get_wrapper_constructor();
static void async_gone(uv_handle_t *handle);
static NAN_METHOD(New);
static NAN_METHOD(ReturnCallback);
static Persistent<Function> wrapper_constructor;
Persistent<Object> wrapper;
static Nan::Persistent<v8::Function> wrapper_constructor;
Nan::Persistent<v8::Object> wrapper;
// The callback that will get called in the main thread after the worker thread used for the sass
// compilation step makes a call to uv_async_send()
......@@ -36,12 +34,12 @@ class CallbackBridge {
// The V8 values sent to our ReturnCallback must be read on the main thread not the sass worker thread.
// This gives a chance to specialized subclasses to transform those values into whatever makes sense to
// sass before we resume the worker thread.
virtual T post_process_return_value(Handle<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;
std::mutex cv_mutex;
......@@ -53,25 +51,30 @@ class CallbackBridge {
};
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>
CallbackBridge<T, L>::CallbackBridge(NanCallback* callback, bool is_sync) : callback(callback), is_sync(is_sync) {
// This assumes the main thread will be the one instantiating the bridge
CallbackBridge<T, L>::CallbackBridge(Nan::Callback* callback, bool is_sync) : callback(callback), is_sync(is_sync) {
/*
* This is invoked from the main JavaScript thread.
* V8 context is available.
*/
Nan::HandleScope scope;
if (!is_sync) {
this->async = new uv_async_t;
this->async->data = (void*) this;
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());
NanSetInternalFieldPointer(NanNew(wrapper), 0, this);
v8::Local<v8::Function> func = CallbackBridge<T, L>::get_wrapper_constructor().ToLocalChecked();
wrapper.Reset(Nan::NewInstance(func).ToLocalChecked());
Nan::SetInternalFieldPointer(Nan::New(wrapper), 0, this);
}
template <typename T, typename L>
CallbackBridge<T, L>::~CallbackBridge() {
delete this->callback;
NanDisposePersistent(this->wrapper);
this->wrapper.Reset();
if (!is_sync) {
uv_close((uv_handle_t*)this->async, &async_gone);
......@@ -81,51 +84,88 @@ CallbackBridge<T, L>::~CallbackBridge() {
template <typename T, typename L>
T CallbackBridge<T, L>::operator()(std::vector<void*> argv) {
// argv.push_back(wrapper);
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(
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>
void CallbackBridge<T, L>::dispatched_async_uv_callback(uv_async_t *req) {
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);
argv_v8.push_back(NanNew(bridge->wrapper));
std::vector<v8::Local<v8::Value>> argv_v8 = bridge->pre_process_args(bridge->argv);
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()) {
node::FatalException(try_catch);
Nan::FatalException(try_catch);
}
}
template <typename T, typename L>
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);
......@@ -135,33 +175,31 @@ NAN_METHOD(CallbackBridge<T COMMA L>::ReturnCallback) {
bridge->condition_variable.notify_all();
if (try_catch.HasCaught()) {
node::FatalException(try_catch);
Nan::FatalException(try_catch);
}
NanReturnUndefined();
}
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()) {
Local<FunctionTemplate> tpl = NanNew<FunctionTemplate>(New);
tpl->SetClassName(NanNew("CallbackBridge"));
v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
tpl->SetClassName(Nan::New("CallbackBridge").ToLocalChecked());
tpl->InstanceTemplate()->SetInternalFieldCount(1);
tpl->PrototypeTemplate()->Set(
NanNew("success"),
NanNew<FunctionTemplate>(ReturnCallback)->GetFunction()
Nan::SetPrototypeTemplate(tpl, "success",
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>
NAN_METHOD(CallbackBridge<T COMMA L>::New) {
NanScope();
NanReturnValue(args.This());
info.GetReturnValue().Set(info.This());
}
template <typename T, typename L>
......
......@@ -3,12 +3,18 @@
#include <string.h>
#include "create_string.h"
char* create_string(Local<Value> value) {
if (value->IsNull() || !value->IsString()) {
char* create_string(Nan::MaybeLocal<v8::Value> maybevalue) {
v8::Local<v8::Value> value;
if (maybevalue.ToLocal(&value)) {
if (value->IsNull() || !value->IsString()) {
return 0;
}
} else {
return 0;
}
String::Utf8Value string(value);
v8::String::Utf8Value string(value);
char *str = (char *)malloc(string.length() + 1);
strcpy(str, *string);
return str;
......
......@@ -3,8 +3,6 @@
#include <nan.h>
using namespace v8;
char* create_string(Nan::MaybeLocal<v8::Value>);
char* create_string(Local<Value>);
#endif
\ No newline at end of file
#endif
......@@ -2,7 +2,7 @@
#include "custom_function_bridge.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 {
return SassTypes::Factory::unwrap(val)->get_sass_value();
}
......@@ -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<Handle<Value>> argv = std::vector<Handle<Value>>();
std::vector<v8::Local<v8::Value>> CustomFunctionBridge::pre_process_args(std::vector<void*> in) const {
std::vector<v8::Local<v8::Value>> argv = std::vector<v8::Local<v8::Value>>();
for (void* value : in) {
argv.push_back(SassTypes::Factory::create(static_cast<Sass_Value*>(value))->get_js_object());
......
......@@ -5,15 +5,13 @@
#include <sass_context.h>
#include "callback_bridge.h"
using namespace v8;
class CustomFunctionBridge : public CallbackBridge<Sass_Value*> {
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:
Sass_Value* post_process_return_value(Handle<Value>) const;
std::vector<Handle<Value>> pre_process_args(std::vector<void*>) const;
Sass_Value* post_process_return_value(v8::Local<v8::Value>) const;
std::vector<v8::Local<v8::Value>> pre_process_args(std::vector<void*>) const;
};
#endif
......@@ -2,19 +2,17 @@
#include "custom_importer_bridge.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;
NanScope();
Local<Value> returned_value = NanNew(val);
Nan::HandleScope scope;
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());
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()) {
auto entry = sass_make_import_entry(0, 0, 0);
......@@ -22,10 +20,10 @@ SassImportList CustomImporterBridge::post_process_return_value(Handle<Value> val
continue;
}
Local<Object> object = Local<Object>::Cast(value);
v8::Local<v8::Object> object = value.As<v8::Object>();
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);
......@@ -38,8 +36,8 @@ SassImportList CustomImporterBridge::post_process_return_value(Handle<Value> val
}
else if (returned_value->IsNativeError()) {
imports = sass_make_import_list(1);
Local<Object> object = Local<Object>::Cast(returned_value);
char* message = create_string(object->Get(NanNew<String>("message")));
v8::Local<v8::Object> object = returned_value.As<v8::Object>();
char* message = create_string(Nan::Get(object, Nan::New<v8::String>("message").ToLocalChecked()));
imports[0] = sass_make_import_entry(0, 0, 0);
......@@ -47,36 +45,42 @@ SassImportList CustomImporterBridge::post_process_return_value(Handle<Value> val
}
else if (returned_value->IsObject()) {
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;
}
Sass_Import* CustomImporterBridge::get_importer_entry(const Local<Object>& object) const {
auto returned_file = object->Get(NanNew<String>("file"));
if (!returned_file->IsUndefined() && !returned_file->IsString()) {
Sass_Import* CustomImporterBridge::check_returned_string(Nan::MaybeLocal<v8::Value> value, const char *msg) const
{
v8::Local<v8::Value> checked;
if (value.ToLocal(&checked)) {
if (!checked->IsUndefined() && !checked->IsString()) {
goto err;
} else {
return nullptr;
}
}
err:
auto entry = sass_make_import_entry(0, 0, 0);
sass_import_set_error(entry, "returned value of `file` must be a string", -1, -1);
sass_import_set_error(entry, msg, -1, -1);
return entry;
}
}
auto returned_contents = object->Get(NanNew<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()) {
auto entry = sass_make_import_entry(0, 0, 0);
sass_import_set_error(entry, "returned value of `contents` must be a string", -1, -1);
return entry;
}
if ((err = check_returned_string(returned_file, "returned value of `file` must be a string")))
return err;
auto returned_map = object->Get(NanNew<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()) {
auto entry = sass_make_import_entry(0, 0, 0);
sass_import_set_error(entry, "returned value of `map` must be a string", -1, -1);
return entry;
}
if ((err = check_returned_string(returned_map, "returned value of `returned_map` must be a string")))
return err;
char* path = create_string(returned_file);
char* contents = create_string(returned_contents);
......@@ -85,11 +89,11 @@ Sass_Import* CustomImporterBridge::get_importer_entry(const Local<Object>& objec
return sass_make_import_entry(path, contents, srcmap);
}
std::vector<Handle<Value>> CustomImporterBridge::pre_process_args(std::vector<void*> in) const {
std::vector<Handle<Value>> out;
std::vector<v8::Local<v8::Value>> CustomImporterBridge::pre_process_args(std::vector<void*> in) const {
std::vector<v8::Local<v8::Value>> out;
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;
......
......@@ -5,18 +5,17 @@
#include <sass_context.h>
#include "callback_bridge.h"
using namespace v8;
typedef Sass_Import_List SassImportList;
class CustomImporterBridge : public CallbackBridge<SassImportList> {
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:
SassImportList post_process_return_value(Handle<Value>) const;
Sass_Import* get_importer_entry(const Local<Object>&) const;
std::vector<Handle<Value>> pre_process_args(std::vector<void*>) const;
SassImportList post_process_return_value(v8::Local<v8::Value>) const;
Sass_Import* check_returned_string(Nan::MaybeLocal<v8::Value> value, const char *msg) 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
......@@ -37,7 +37,7 @@ extern "C" {
delete ctx_w->error_callback;
delete ctx_w->success_callback;
NanDisposePersistent(ctx_w->result);
ctx_w->result.Reset();
free(ctx_w->include_path);
free(ctx_w->linefeed);
......
......@@ -14,8 +14,6 @@
extern "C" {
#endif
using namespace v8;
void compile_data(struct Sass_Data_Context* dctx);
void compile_file(struct Sass_File_Context* fctx);
void compile_it(uv_work_t* req);
......@@ -41,9 +39,9 @@ extern "C" {
uv_work_t request;
// v8 and nan related
Persistent<Object> result;
NanCallback* error_callback;
NanCallback* success_callback;
Nan::Persistent<v8::Object> result;
Nan::Callback* error_callback;
Nan::Callback* success_callback;
std::vector<std::shared_ptr<CustomFunctionBridge>> function_bridges;
std::vector<std::shared_ptr<CustomImporterBridge>> importer_bridges;
......
#include <nan.h>
#include "boolean.h"
using namespace v8;
namespace SassTypes
{
Persistent<Function> Boolean::constructor;
Nan::Persistent<v8::Function> Boolean::constructor;
bool Boolean::constructor_locked = false;
Boolean::Boolean(bool v) : value(v) {}
......@@ -15,59 +13,60 @@ namespace SassTypes
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()) {
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->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());
NanSetInternalFieldPointer(NanNew(get_singleton(false).js_object), 0, &get_singleton(false));
NanNew(constructor)->Set(NanNew("FALSE"), NanNew(get_singleton(false).js_object));
get_singleton(false).js_object.Reset(Nan::NewInstance(conslocal).ToLocalChecked());
Nan::SetInternalFieldPointer(Nan::New(get_singleton(false).js_object), 0, &get_singleton(false));
Nan::Set(conslocal, Nan::New("FALSE").ToLocalChecked(), Nan::New(get_singleton(false).js_object));
NanAssignPersistent(get_singleton(true).js_object, NanNew(constructor)->NewInstance());
NanSetInternalFieldPointer(NanNew(get_singleton(true).js_object), 0, &get_singleton(true));
NanNew(constructor)->Set(NanNew("TRUE"), NanNew(get_singleton(true).js_object));
get_singleton(true).js_object.Reset(Nan::NewInstance(conslocal).ToLocalChecked());
Nan::SetInternalFieldPointer(Nan::New(get_singleton(true).js_object), 0, &get_singleton(true));
Nan::Set(conslocal, Nan::New("TRUE").ToLocalChecked(), Nan::New(get_singleton(true).js_object));
constructor_locked = true;
} else {
conslocal = Nan::New(constructor);
}
return NanNew(constructor);
return scope.Escape(conslocal);
}
Sass_Value* Boolean::get_sass_value() {
return sass_make_boolean(value);
}
Local<Object> Boolean::get_js_object() {
return NanNew(this->js_object);
v8::Local<v8::Object> Boolean::get_js_object() {
return Nan::New(this->js_object);
}
NAN_METHOD(Boolean::New) {
NanScope();
if (args.IsConstructCall()) {
if (info.IsConstructCall()) {
if (constructor_locked) {
return NanThrowError(NanNew("Cannot instantiate SassBoolean"));
return Nan::ThrowTypeError(Nan::New("Cannot instantiate SassBoolean").ToLocalChecked());
}
}
else {
if (args.Length() != 1 || !args[0]->IsBoolean()) {
return NanThrowError(NanNew("Expected one boolean argument"));
if (info.Length() != 1 || !info[0]->IsBoolean()) {
return Nan::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) {
NanScope();
NanReturnValue(NanNew(static_cast<Boolean*>(Factory::unwrap(args.This()))->value));
info.GetReturnValue().Set(Nan::New(static_cast<Boolean*>(Factory::unwrap(info.This()))->value));
}
}
......@@ -7,15 +7,13 @@
namespace SassTypes
{
using namespace v8;
class Boolean : public Value {
class Boolean : public SassTypes::Value {
public:
static Boolean& get_singleton(bool);
static Handle<Function> get_constructor();
static v8::Local<v8::Function> get_constructor();
Sass_Value* get_sass_value();
Local<Object> get_js_object();
v8::Local<v8::Object> get_js_object();
static NAN_METHOD(New);
static NAN_METHOD(GetValue);
......@@ -24,9 +22,9 @@ namespace SassTypes
Boolean(bool);
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;
};
}
......
#include <nan.h>
#include "color.h"
using namespace v8;
namespace SassTypes
{
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;
unsigned argb;
......@@ -17,7 +15,7 @@ namespace SassTypes
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;
r = (double)((argb >> 020) & 0xff);
g = (double)((argb >> 010) & 0xff);
......@@ -29,7 +27,7 @@ namespace SassTypes
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
case 3:
......@@ -37,9 +35,9 @@ namespace SassTypes
throw std::invalid_argument("Constructor arguments should be numbers exclusively.");
}
r = raw_val[0]->ToNumber()->Value();
g = raw_val[1]->ToNumber()->Value();
b = raw_val[2]->ToNumber()->Value();
r = Nan::To<double>(raw_val[0]).FromJust();
g = Nan::To<double>(raw_val[1]).FromJust();
b = Nan::To<double>(raw_val[2]).FromJust();
break;
case 0:
......@@ -52,86 +50,78 @@ namespace SassTypes
return sass_make_color(r, g, b, a);
}
void Color::initPrototype(Handle<ObjectTemplate> proto) {
proto->Set(NanNew("getR"), NanNew<FunctionTemplate>(GetR)->GetFunction());
proto->Set(NanNew("getG"), NanNew<FunctionTemplate>(GetG)->GetFunction());
proto->Set(NanNew("getB"), NanNew<FunctionTemplate>(GetB)->GetFunction());
proto->Set(NanNew("getA"), NanNew<FunctionTemplate>(GetA)->GetFunction());
proto->Set(NanNew("setR"), NanNew<FunctionTemplate>(SetR)->GetFunction());
proto->Set(NanNew("setG"), NanNew<FunctionTemplate>(SetG)->GetFunction());
proto->Set(NanNew("setB"), NanNew<FunctionTemplate>(SetB)->GetFunction());
proto->Set(NanNew("setA"), NanNew<FunctionTemplate>(SetA)->GetFunction());
void Color::initPrototype(v8::Local<v8::FunctionTemplate> proto) {
Nan::SetPrototypeMethod(proto, "getR", GetR);
Nan::SetPrototypeMethod(proto, "getG", GetG);
Nan::SetPrototypeMethod(proto, "getB", GetB);
Nan::SetPrototypeMethod(proto, "getA", GetA);
Nan::SetPrototypeMethod(proto, "setR", SetR);
Nan::SetPrototypeMethod(proto, "setG", SetG);
Nan::SetPrototypeMethod(proto, "setB", SetB);
Nan::SetPrototypeMethod(proto, "setA", SetA);
}
NAN_METHOD(Color::GetR) {
NanScope();
NanReturnValue(NanNew(sass_color_get_r(unwrap(args.This())->value)));
info.GetReturnValue().Set(sass_color_get_r(unwrap(info.This())->value));
}
NAN_METHOD(Color::GetG) {
NanScope();
NanReturnValue(NanNew(sass_color_get_g(unwrap(args.This())->value)));
info.GetReturnValue().Set(sass_color_get_g(unwrap(info.This())->value));
}
NAN_METHOD(Color::GetB) {
NanScope();
NanReturnValue(NanNew(sass_color_get_b(unwrap(args.This())->value)));
info.GetReturnValue().Set(sass_color_get_b(unwrap(info.This())->value));
}
NAN_METHOD(Color::GetA) {
NanScope();
NanReturnValue(NanNew(sass_color_get_a(unwrap(args.This())->value)));
info.GetReturnValue().Set(sass_color_get_a(unwrap(info.This())->value));
}
NAN_METHOD(Color::SetR) {
if (args.Length() != 1) {
return NanThrowError(NanNew("Expected just one argument"));
if (info.Length() != 1) {
return Nan::ThrowTypeError(Nan::New("Expected just one argument").ToLocalChecked());
}
if (!args[0]->IsNumber()) {
return NanThrowError(NanNew("Supplied value should be a number"));
if (!info[0]->IsNumber()) {
return Nan::ThrowTypeError(Nan::New("Supplied value should be a number").ToLocalChecked());
}
sass_color_set_r(unwrap(args.This())->value, args[0]->ToNumber()->Value());
NanReturnUndefined();
sass_color_set_r(unwrap(info.This())->value, Nan::To<double>(info[0]).FromJust());
}
NAN_METHOD(Color::SetG) {
if (args.Length() != 1) {
return NanThrowError(NanNew("Expected just one argument"));
if (info.Length() != 1) {
return Nan::ThrowTypeError(Nan::New("Expected just one argument").ToLocalChecked());
}
if (!args[0]->IsNumber()) {
return NanThrowError(NanNew("Supplied value should be a number"));
if (!info[0]->IsNumber()) {
return Nan::ThrowTypeError(Nan::New("Supplied value should be a number").ToLocalChecked());
}
sass_color_set_g(unwrap(args.This())->value, args[0]->ToNumber()->Value());
NanReturnUndefined();
sass_color_set_g(unwrap(info.This())->value, Nan::To<double>(info[0]).FromJust());
}
NAN_METHOD(Color::SetB) {
if (args.Length() != 1) {
return NanThrowError(NanNew("Expected just one argument"));
if (info.Length() != 1) {
return Nan::ThrowTypeError(Nan::New("Expected just one argument").ToLocalChecked());
}
if (!args[0]->IsNumber()) {
return NanThrowError(NanNew("Supplied value should be a number"));
if (!info[0]->IsNumber()) {
return Nan::ThrowTypeError(Nan::New("Supplied value should be a number").ToLocalChecked());
}
sass_color_set_b(unwrap(args.This())->value, args[0]->ToNumber()->Value());
NanReturnUndefined();
sass_color_set_b(unwrap(info.This())->value, Nan::To<double>(info[0]).FromJust());
}
NAN_METHOD(Color::SetA) {
if (args.Length() != 1) {
return NanThrowError(NanNew("Expected just one argument"));
if (info.Length() != 1) {
return Nan::ThrowTypeError(Nan::New("Expected just one argument").ToLocalChecked());
}
if (!args[0]->IsNumber()) {
return NanThrowError(NanNew("Supplied value should be a number"));
if (!info[0]->IsNumber()) {
return Nan::ThrowTypeError(Nan::New("Supplied value should be a number").ToLocalChecked());
}
sass_color_set_a(unwrap(args.This())->value, args[0]->ToNumber()->Value());
NanReturnUndefined();
sass_color_set_a(unwrap(info.This())->value, Nan::To<double>(info[0]).FromJust());
}
}
......@@ -6,15 +6,13 @@
namespace SassTypes
{
using namespace v8;
class Color : public SassValueWrapper<Color> {
public:
Color(Sass_Value*);
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(GetG);
......
......@@ -2,13 +2,11 @@
#include "error.h"
#include "../create_string.h"
using namespace v8;
namespace SassTypes
{
Error::Error(Sass_Value* v) : SassValueWrapper(v) {}
Sass_Value* Error::construct(const std::vector<Local<v8::Value>> raw_val) {
Sass_Value* Error::construct(const std::vector<v8::Local<v8::Value>> raw_val) {
char const* value = "";
if (raw_val.size() >= 1) {
......@@ -22,5 +20,5 @@ namespace SassTypes
return sass_make_error(value);
}
void Error::initPrototype(Handle<ObjectTemplate>) {}
void Error::initPrototype(v8::Local<v8::FunctionTemplate>) {}
}
......@@ -6,15 +6,13 @@
namespace SassTypes
{
using namespace v8;
class Error : public SassValueWrapper<Error> {
public:
Error(Sass_Value*);
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 @@
#include "null.h"
#include "error.h"
using namespace v8;
namespace SassTypes
{
Value* Factory::create(Sass_Value* v) {
SassTypes::Value* Factory::create(Sass_Value* v) {
switch (sass_value_get_tag(v)) {
case SASS_NUMBER:
return new Number(v);
......@@ -45,26 +43,27 @@ namespace SassTypes
}
}
void Factory::initExports(Handle<Object> exports) {
Local<Object> types = NanNew<Object>();
exports->Set(NanNew("types"), types);
NAN_MODULE_INIT(Factory::initExports) {
Nan::HandleScope scope;
v8::Local<v8::Object> types = Nan::New<v8::Object>();
types->Set(NanNew("Number"), Number::get_constructor());
types->Set(NanNew("String"), String::get_constructor());
types->Set(NanNew("Color"), Color::get_constructor());
types->Set(NanNew("Boolean"), Boolean::get_constructor());
types->Set(NanNew("List"), List::get_constructor());
types->Set(NanNew("Map"), Map::get_constructor());
types->Set(NanNew("Null"), Null::get_constructor());
types->Set(NanNew("Error"), Error::get_constructor());
Nan::Set(types, Nan::New("Number").ToLocalChecked(), Number::get_constructor());
Nan::Set(types, Nan::New("String").ToLocalChecked(), String::get_constructor());
Nan::Set(types, Nan::New("Color").ToLocalChecked(), Color::get_constructor());
Nan::Set(types, Nan::New("Boolean").ToLocalChecked(), Boolean::get_constructor());
Nan::Set(types, Nan::New("List").ToLocalChecked(), List::get_constructor());
Nan::Set(types, Nan::New("Map").ToLocalChecked(), Map::get_constructor());
Nan::Set(types, Nan::New("Null").ToLocalChecked(), Null::get_constructor());
Nan::Set(types, Nan::New("Error").ToLocalChecked(), Error::get_constructor());
Nan::Set(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.
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.");
}
return static_cast<Value*>(NanGetInternalFieldPointer(obj->ToObject(), 0));
return static_cast<Value*>(Nan::GetInternalFieldPointer(obj.As<v8::Object>(), 0));
}
}
......@@ -7,15 +7,13 @@
namespace SassTypes
{
using namespace v8;
// This is the guru that knows everything about instantiating the right subclass of SassTypes::Value
// to wrap a given Sass_Value object.
class Factory {
public:
static void initExports(Handle<Object>);
static NAN_MODULE_INIT(initExports);
static Value* create(Sass_Value*);
static Value* unwrap(Handle<v8::Value>);
static Value* unwrap(v8::Local<v8::Value>);
};
}
......
#include <nan.h>
#include "list.h"
using namespace v8;
namespace SassTypes
{
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;
bool comma = true;
......@@ -16,88 +14,83 @@ namespace SassTypes
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[1]->IsBoolean()) {
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);
}
void List::initPrototype(Handle<ObjectTemplate> proto) {
proto->Set(NanNew("getLength"), NanNew<FunctionTemplate>(GetLength)->GetFunction());
proto->Set(NanNew("getSeparator"), NanNew<FunctionTemplate>(GetSeparator)->GetFunction());
proto->Set(NanNew("setSeparator"), NanNew<FunctionTemplate>(SetSeparator)->GetFunction());
proto->Set(NanNew("getValue"), NanNew<FunctionTemplate>(GetValue)->GetFunction());
proto->Set(NanNew("setValue"), NanNew<FunctionTemplate>(SetValue)->GetFunction());
void List::initPrototype(v8::Local<v8::FunctionTemplate> proto) {
Nan::SetPrototypeMethod(proto, "getLength", GetLength);
Nan::SetPrototypeMethod(proto, "getSeparator", GetSeparator);
Nan::SetPrototypeMethod(proto, "setSeparator", SetSeparator);
Nan::SetPrototypeMethod(proto, "getValue", GetValue);
Nan::SetPrototypeMethod(proto, "setValue", SetValue);
}
NAN_METHOD(List::GetValue) {
NanScope();
if (args.Length() != 1) {
return NanThrowError(NanNew("Expected just one argument"));
if (info.Length() != 1) {
return Nan::ThrowTypeError(Nan::New("Expected just one argument").ToLocalChecked());
}
if (!args[0]->IsNumber()) {
return NanThrowError(NanNew("Supplied index should be an integer"));
if (!info[0]->IsNumber()) {
return Nan::ThrowTypeError(Nan::New("Supplied index should be an integer").ToLocalChecked());
}
Sass_Value* list = unwrap(args.This())->value;
size_t index = args[0]->ToInt32()->Value();
Sass_Value* list = unwrap(info.This())->value;
size_t index = Nan::To<uint32_t>(info[0]).FromJust();
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) {
if (args.Length() != 2) {
return NanThrowError(NanNew("Expected two arguments"));
if (info.Length() != 2) {
return Nan::ThrowTypeError(Nan::New("Expected two arguments").ToLocalChecked());
}
if (!args[0]->IsNumber()) {
return NanThrowError(NanNew("Supplied index should be an integer"));
if (!info[0]->IsNumber()) {
return Nan::ThrowTypeError(Nan::New("Supplied index should be an integer").ToLocalChecked());
}
if (!args[1]->IsObject()) {
return NanThrowError(NanNew("Supplied value should be a SassValue object"));
if (!info[1]->IsObject()) {
return Nan::ThrowTypeError(Nan::New("Supplied value should be a SassValue object").ToLocalChecked());
}
Value* sass_value = Factory::unwrap(args[1]);
sass_list_set_value(unwrap(args.This())->value, args[0]->ToInt32()->Value(), sass_value->get_sass_value());
NanReturnUndefined();
Value* sass_value = Factory::unwrap(info[1]);
sass_list_set_value(unwrap(info.This())->value, Nan::To<uint32_t>(info[0]).FromJust(), sass_value->get_sass_value());
}
NAN_METHOD(List::GetSeparator) {
NanScope();
NanReturnValue(NanNew(sass_list_get_separator(unwrap(args.This())->value) == SASS_COMMA));
info.GetReturnValue().Set(sass_list_get_separator(unwrap(info.This())->value) == SASS_COMMA);
}
NAN_METHOD(List::SetSeparator) {
if (args.Length() != 1) {
return NanThrowError(NanNew("Expected just one argument"));
if (info.Length() != 1) {
return Nan::ThrowTypeError(Nan::New("Expected just one argument").ToLocalChecked());
}
if (!args[0]->IsBoolean()) {
return NanThrowError(NanNew("Supplied value should be a boolean"));
if (!info[0]->IsBoolean()) {
return Nan::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);
NanReturnUndefined();
sass_list_set_separator(unwrap(info.This())->value, Nan::To<bool>(info[0]).FromJust() ? SASS_COMMA : SASS_SPACE);
}
NAN_METHOD(List::GetLength) {
NanScope();
NanReturnValue(NanNew<v8::Number>(sass_list_get_length(unwrap(args.This())->value)));
info.GetReturnValue().Set(Nan::New<v8::Number>(sass_list_get_length(unwrap(info.This())->value)));
}
}
......@@ -6,15 +6,13 @@
namespace SassTypes
{
using namespace v8;
class List : public SassValueWrapper<List> {
public:
List(Sass_Value*);
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(SetValue);
......
#include <nan.h>
#include "map.h"
using namespace v8;
namespace SassTypes
{
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;
if (raw_val.size() >= 1) {
......@@ -15,102 +13,97 @@ namespace SassTypes
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);
}
void Map::initPrototype(Handle<ObjectTemplate> proto) {
proto->Set(NanNew("getLength"), NanNew<FunctionTemplate>(GetLength)->GetFunction());
proto->Set(NanNew("getKey"), NanNew<FunctionTemplate>(GetKey)->GetFunction());
proto->Set(NanNew("setKey"), NanNew<FunctionTemplate>(SetKey)->GetFunction());
proto->Set(NanNew("getValue"), NanNew<FunctionTemplate>(GetValue)->GetFunction());
proto->Set(NanNew("setValue"), NanNew<FunctionTemplate>(SetValue)->GetFunction());
void Map::initPrototype(v8::Local<v8::FunctionTemplate> proto) {
Nan::SetPrototypeMethod(proto, "getLength", GetLength);
Nan::SetPrototypeMethod(proto, "getKey", GetKey);
Nan::SetPrototypeMethod(proto, "setKey", SetKey);
Nan::SetPrototypeMethod(proto, "getValue", GetValue);
Nan::SetPrototypeMethod(proto, "setValue", SetValue);
}
NAN_METHOD(Map::GetValue) {
NanScope();
if (args.Length() != 1) {
return NanThrowError(NanNew("Expected just one argument"));
if (info.Length() != 1) {
return Nan::ThrowTypeError(Nan::New("Expected just one argument").ToLocalChecked());
}
if (!args[0]->IsNumber()) {
return NanThrowError(NanNew("Supplied index should be an integer"));
if (!info[0]->IsNumber()) {
return Nan::ThrowTypeError(Nan::New("Supplied index should be an integer").ToLocalChecked());
}
Sass_Value* map = unwrap(args.This())->value;
size_t index = args[0]->ToInt32()->Value();
Sass_Value* map = unwrap(info.This())->value;
size_t index = Nan::To<uint32_t>(info[0]).FromJust();
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) {
if (args.Length() != 2) {
return NanThrowError(NanNew("Expected two arguments"));
if (info.Length() != 2) {
return Nan::ThrowTypeError(Nan::New("Expected two arguments").ToLocalChecked());
}
if (!args[0]->IsNumber()) {
return NanThrowError(NanNew("Supplied index should be an integer"));
if (!info[0]->IsNumber()) {
return Nan::ThrowTypeError(Nan::New("Supplied index should be an integer").ToLocalChecked());
}
if (!args[1]->IsObject()) {
return NanThrowError(NanNew("Supplied value should be a SassValue object"));
if (!info[1]->IsObject()) {
return Nan::ThrowTypeError(Nan::New("Supplied value should be a SassValue object").ToLocalChecked());
}
Value* sass_value = Factory::unwrap(args[1]);
sass_map_set_value(unwrap(args.This())->value, args[0]->ToInt32()->Value(), sass_value->get_sass_value());
NanReturnUndefined();
Value* sass_value = Factory::unwrap(info[1]);
sass_map_set_value(unwrap(info.This())->value, Nan::To<uint32_t>(info[0]).FromJust(), sass_value->get_sass_value());
}
NAN_METHOD(Map::GetKey) {
NanScope();
if (args.Length() != 1) {
return NanThrowError(NanNew("Expected just one argument"));
if (info.Length() != 1) {
return Nan::ThrowTypeError(Nan::New("Expected just one argument").ToLocalChecked());
}
if (!args[0]->IsNumber()) {
return NanThrowError(NanNew("Supplied index should be an integer"));
if (!info[0]->IsNumber()) {
return Nan::ThrowTypeError(Nan::New("Supplied index should be an integer").ToLocalChecked());
}
Sass_Value* map = unwrap(args.This())->value;
size_t index = args[0]->ToInt32()->Value();
Sass_Value* map = unwrap(info.This())->value;
size_t index = Nan::To<uint32_t>(info[0]).FromJust();
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) {
if (args.Length() != 2) {
return NanThrowError(NanNew("Expected two arguments"));
if (info.Length() != 2) {
return Nan::ThrowTypeError(Nan::New("Expected two arguments").ToLocalChecked());
}
if (!args[0]->IsNumber()) {
return NanThrowError(NanNew("Supplied index should be an integer"));
if (!info[0]->IsNumber()) {
return Nan::ThrowTypeError(Nan::New("Supplied index should be an integer").ToLocalChecked());
}
if (!args[1]->IsObject()) {
return NanThrowError(NanNew("Supplied value should be a SassValue object"));
if (!info[1]->IsObject()) {
return Nan::ThrowTypeError(Nan::New("Supplied value should be a SassValue object").ToLocalChecked());
}
Value* sass_value = Factory::unwrap(args[1]);
sass_map_set_key(unwrap(args.This())->value, args[0]->ToInt32()->Value(), sass_value->get_sass_value());
NanReturnUndefined();
Value* sass_value = Factory::unwrap(info[1]);
sass_map_set_key(unwrap(info.This())->value, Nan::To<uint32_t>(info[0]).FromJust(), sass_value->get_sass_value());
}
NAN_METHOD(Map::GetLength) {
NanScope();
NanReturnValue(NanNew<v8::Number>(sass_map_get_length(unwrap(args.This())->value)));
info.GetReturnValue().Set(Nan::New<v8::Number>(sass_map_get_length(unwrap(info.This())->value)));
}
}
......@@ -6,15 +6,13 @@
namespace SassTypes
{
using namespace v8;
class Map : public SassValueWrapper<Map> {
public:
Map(Sass_Value*);
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(SetValue);
......
#include <nan.h>
#include "null.h"
using namespace v8;
namespace SassTypes
{
Persistent<Function> Null::constructor;
Nan::Persistent<v8::Function> Null::constructor;
bool Null::constructor_locked = false;
Null::Null() {}
......@@ -15,45 +13,47 @@ namespace SassTypes
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()) {
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);
NanAssignPersistent(constructor, tpl->GetFunction());
conslocal = Nan::GetFunction(tpl).ToLocalChecked();
constructor.Reset(conslocal);
NanAssignPersistent(get_singleton().js_object, NanNew(constructor)->NewInstance());
NanSetInternalFieldPointer(NanNew(get_singleton().js_object), 0, &get_singleton());
NanNew(constructor)->Set(NanNew("NULL"), NanNew(get_singleton().js_object));
get_singleton().js_object.Reset(Nan::NewInstance(conslocal).ToLocalChecked());
Nan::SetInternalFieldPointer(Nan::New(get_singleton().js_object), 0, &get_singleton());
Nan::Set(conslocal, Nan::New("NULL").ToLocalChecked(), Nan::New(get_singleton().js_object));
constructor_locked = true;
} else {
conslocal = Nan::New(constructor);
}
return NanNew(constructor);
return scope.Escape(conslocal);
}
Sass_Value* Null::get_sass_value() {
return sass_make_null();
}
Local<Object> Null::get_js_object() {
return NanNew(this->js_object);
v8::Local<v8::Object> Null::get_js_object() {
return Nan::New(this->js_object);
}
NAN_METHOD(Null::New) {
NanScope();
if (args.IsConstructCall()) {
if (info.IsConstructCall()) {
if (constructor_locked) {
return NanThrowError(NanNew("Cannot instantiate SassNull"));
return Nan::ThrowTypeError(Nan::New("Cannot instantiate SassNull").ToLocalChecked());
}
}
else {
NanReturnValue(NanNew(get_singleton().get_js_object()));
info.GetReturnValue().Set(get_singleton().get_js_object());
}
NanReturnUndefined();
}
}
......@@ -6,24 +6,22 @@
namespace SassTypes
{
using namespace v8;
class Null : public Value {
class Null : public SassTypes::Value {
public:
static Null& get_singleton();
static Handle<Function> get_constructor();
static v8::Local<v8::Function> get_constructor();
Sass_Value* get_sass_value();
Local<Object> get_js_object();
v8::Local<v8::Object> get_js_object();
static NAN_METHOD(New);
private:
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;
};
}
......
......@@ -2,13 +2,11 @@
#include "number.h"
#include "../create_string.h"
using namespace v8;
namespace SassTypes
{
Number::Number(Sass_Value* v) : SassValueWrapper(v) {}
Sass_Value* Number::construct(const std::vector<Local<v8::Value>> raw_val) {
Sass_Value* Number::construct(const std::vector<v8::Local<v8::Value>> raw_val) {
double value = 0;
char const* unit = "";
......@@ -17,7 +15,7 @@ namespace SassTypes
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[1]->IsString()) {
......@@ -31,48 +29,43 @@ namespace SassTypes
return sass_make_number(value, unit);
}
void Number::initPrototype(Handle<ObjectTemplate> proto) {
proto->Set(NanNew("getValue"), NanNew<FunctionTemplate>(GetValue)->GetFunction());
proto->Set(NanNew("getUnit"), NanNew<FunctionTemplate>(GetUnit)->GetFunction());
proto->Set(NanNew("setValue"), NanNew<FunctionTemplate>(SetValue)->GetFunction());
proto->Set(NanNew("setUnit"), NanNew<FunctionTemplate>(SetUnit)->GetFunction());
void Number::initPrototype(v8::Local<v8::FunctionTemplate> proto) {
Nan::SetPrototypeMethod(proto, "getValue", GetValue);
Nan::SetPrototypeMethod(proto, "getUnit", GetUnit);
Nan::SetPrototypeMethod(proto, "setValue", SetValue);
Nan::SetPrototypeMethod(proto, "setUnit", SetUnit);
}
NAN_METHOD(Number::GetValue) {
NanScope();
NanReturnValue(NanNew(sass_number_get_value(unwrap(args.This())->value)));
info.GetReturnValue().Set(Nan::New<v8::Number>(sass_number_get_value(unwrap(info.This())->value)));
}
NAN_METHOD(Number::GetUnit) {
NanScope();
NanReturnValue(NanNew(sass_number_get_unit(unwrap(args.This())->value)));
info.GetReturnValue().Set(Nan::New<v8::String>(sass_number_get_unit(unwrap(info.This())->value)).ToLocalChecked());
}
NAN_METHOD(Number::SetValue) {
NanScope();
if (args.Length() != 1) {
return NanThrowError(NanNew("Expected just one argument"));
if (info.Length() != 1) {
return Nan::ThrowTypeError(Nan::New("Expected just one argument").ToLocalChecked());
}
if (!args[0]->IsNumber()) {
return NanThrowError(NanNew("Supplied value should be a number"));
if (!info[0]->IsNumber()) {
return Nan::ThrowTypeError(Nan::New("Supplied value should be a number").ToLocalChecked());
}
sass_number_set_value(unwrap(args.This())->value, args[0]->ToNumber()->Value());
NanReturnUndefined();
sass_number_set_value(unwrap(info.This())->value, Nan::To<double>(info[0]).FromJust());
}
NAN_METHOD(Number::SetUnit) {
if (args.Length() != 1) {
return NanThrowError(NanNew("Expected just one argument"));
if (info.Length() != 1) {
return Nan::ThrowTypeError(Nan::New("Expected just one argument").ToLocalChecked());
}
if (!args[0]->IsString()) {
return NanThrowError(NanNew("Supplied value should be a string"));
if (!info[0]->IsString()) {
return Nan::ThrowTypeError(Nan::New("Supplied value should be a string").ToLocalChecked());
}
sass_number_set_unit(unwrap(args.This())->value, create_string(args[0]));
NanReturnUndefined();
sass_number_set_unit(unwrap(info.This())->value, create_string(info[0]));
}
}
......@@ -6,15 +6,14 @@
namespace SassTypes
{
using namespace v8;
class Number : public SassValueWrapper<Number> {
public:
Number(Sass_Value*);
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(GetUnit);
......
......@@ -9,12 +9,10 @@
namespace SassTypes
{
using namespace v8;
// Include this in any SassTypes::Value subclasses to handle all the heavy lifting of constructing JS
// objects and wrapping sass values inside them
template <class T>
class SassValueWrapper : public Value {
class SassValueWrapper : public SassTypes::Value {
public:
static char const* get_constructor_name() { return "SassValue"; }
......@@ -22,23 +20,23 @@ namespace SassTypes
virtual ~SassValueWrapper();
Sass_Value* get_sass_value();
Local<Object> get_js_object();
v8::Local<v8::Object> get_js_object();
static Handle<Function> get_constructor();
static Local<FunctionTemplate> get_constructor_template();
static v8::Local<v8::Function> get_constructor();
static v8::Local<v8::FunctionTemplate> get_constructor_template();
static NAN_METHOD(New);
protected:
Sass_Value* value;
static T* unwrap(Local<Object>);
static T* unwrap(v8::Local<v8::Object>);
private:
static Persistent<Function> constructor;
Persistent<Object> js_object;
static Nan::Persistent<v8::Function> constructor;
Nan::Persistent<v8::Object> js_object;
};
template <class T>
Persistent<Function> SassValueWrapper<T>::constructor;
Nan::Persistent<v8::Function> SassValueWrapper<T>::constructor;
template <class T>
SassValueWrapper<T>::SassValueWrapper(Sass_Value* v) {
......@@ -47,7 +45,7 @@ namespace SassTypes
template <class T>
SassValueWrapper<T>::~SassValueWrapper() {
NanDisposePersistent(this->js_object);
this->js_object.Reset();
sass_delete_value(this->value);
}
......@@ -57,74 +55,64 @@ namespace SassTypes
}
template <class T>
Local<Object> SassValueWrapper<T>::get_js_object() {
v8::Local<v8::Object> SassValueWrapper<T>::get_js_object() {
if (this->js_object.IsEmpty()) {
Local<Object> wrapper = NanNew(T::get_constructor())->NewInstance();
delete static_cast<T*>(NanGetInternalFieldPointer(wrapper, 0));
NanSetInternalFieldPointer(wrapper, 0, this);
NanAssignPersistent(this->js_object, wrapper);
v8::Local<v8::Object> wrapper = Nan::NewInstance(T::get_constructor()).ToLocalChecked();
delete static_cast<T*>(Nan::GetInternalFieldPointer(wrapper, 0));
Nan::SetInternalFieldPointer(wrapper, 0, this);
this->js_object.Reset(wrapper);
}
return NanNew(this->js_object);
return Nan::New(this->js_object);
}
template <class T>
Local<FunctionTemplate> SassValueWrapper<T>::get_constructor_template() {
Local<FunctionTemplate> tpl = NanNew<FunctionTemplate>(New);
tpl->SetClassName(NanNew(NanNew(T::get_constructor_name())));
v8::Local<v8::FunctionTemplate> SassValueWrapper<T>::get_constructor_template() {
Nan::EscapableHandleScope scope;
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);
T::initPrototype(tpl->PrototypeTemplate());
T::initPrototype(tpl);
return tpl;
return scope.Escape(tpl);
}
template <class T>
Handle<Function> SassValueWrapper<T>::get_constructor() {
v8::Local<v8::Function> SassValueWrapper<T>::get_constructor() {
if (constructor.IsEmpty()) {
NanAssignPersistent(constructor, T::get_constructor_template()->GetFunction());
constructor.Reset(Nan::GetFunction(T::get_constructor_template()).ToLocalChecked());
}
return NanNew(constructor);
return Nan::New(constructor);
}
template <class T>
NAN_METHOD(SassValueWrapper<T>::New) {
NanScope();
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]);
}
std::vector<v8::Local<v8::Value>> localArgs(info.Length());
NanReturnValue(NanNew(T::get_constructor())->NewInstance(argc, &argv[0]));
for (auto i = 0; i < info.Length(); ++i) {
localArgs[i] = info[i];
}
std::vector<Local<v8::Value>> localArgs(args.Length());
for (auto i = 0; i < args.Length(); ++i) {
localArgs[i] = args[i];
}
try {
Sass_Value* value = T::construct(localArgs);
T* obj = new T(value);
sass_delete_value(value);
NanSetInternalFieldPointer(args.This(), 0, obj);
NanAssignPersistent(obj->js_object, args.This());
} catch (const std::exception& e) {
return NanThrowError(NanNew(e.what()));
if (info.IsConstructCall()) {
try {
Sass_Value* value = T::construct(localArgs);
T* obj = new T(value);
sass_delete_value(value);
Nan::SetInternalFieldPointer(info.This(), 0, obj);
obj->js_object.Reset(info.This());
} catch (const std::exception& e) {
return Nan::ThrowError(Nan::New<v8::String>(e.what()).ToLocalChecked());
}
} else {
v8::Local<v8::Function> cons = T::get_constructor();
v8::Local<v8::Object> inst = Nan::NewInstance(cons, info.Length(), &localArgs[0]).ToLocalChecked();
info.GetReturnValue().Set(inst);
}
NanReturnUndefined();
}
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));
}
}
......
......@@ -2,13 +2,11 @@
#include "string.h"
#include "../create_string.h"
using namespace v8;
namespace SassTypes
{
String::String(Sass_Value* v) : SassValueWrapper(v) {}
Sass_Value* String::construct(const std::vector<Local<v8::Value>> raw_val) {
Sass_Value* String::construct(const std::vector<v8::Local<v8::Value>> raw_val) {
char const* value = "";
if (raw_val.size() >= 1) {
......@@ -22,26 +20,24 @@ namespace SassTypes
return sass_make_string(value);
}
void String::initPrototype(Handle<ObjectTemplate> proto) {
proto->Set(NanNew("getValue"), NanNew<FunctionTemplate>(GetValue)->GetFunction());
proto->Set(NanNew("setValue"), NanNew<FunctionTemplate>(SetValue)->GetFunction());
void String::initPrototype(v8::Local<v8::FunctionTemplate> proto) {
Nan::SetPrototypeMethod(proto, "getValue", GetValue);
Nan::SetPrototypeMethod(proto, "setValue", SetValue);
}
NAN_METHOD(String::GetValue) {
NanScope();
NanReturnValue(NanNew(sass_string_get_value(unwrap(args.This())->value)));
info.GetReturnValue().Set(Nan::New<v8::String>(sass_string_get_value(unwrap(info.This())->value)).ToLocalChecked());
}
NAN_METHOD(String::SetValue) {
if (args.Length() != 1) {
return NanThrowError(NanNew("Expected just one argument"));
if (info.Length() != 1) {
return Nan::ThrowTypeError(Nan::New("Expected just one argument").ToLocalChecked());
}
if (!args[0]->IsString()) {
return NanThrowError(NanNew("Supplied value should be a string"));
if (!info[0]->IsString()) {
return Nan::ThrowTypeError(Nan::New("Supplied value should be a string").ToLocalChecked());
}
sass_string_set_value(unwrap(args.This())->value, create_string(args[0]));
NanReturnUndefined();
sass_string_set_value(unwrap(info.This())->value, create_string(info[0]));
}
}
......@@ -6,15 +6,13 @@
namespace SassTypes
{
using namespace v8;
class String : public SassValueWrapper<String> {
public:
String(Sass_Value*);
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(SetValue);
......
......@@ -6,13 +6,11 @@
namespace SassTypes
{
using namespace v8;
// This is the interface that all sass values must comply with
class Value {
public:
virtual Sass_Value* get_sass_value() =0;
virtual Local<Object> get_js_object() =0;
virtual v8::Local<v8::Object> get_js_object() =0;
};
}
......
......@@ -1032,6 +1032,9 @@ describe('api', function() {
it('should throw error for bad input', function(done) {
assert.throws(function() {
sass.renderSync('somestring');
});
assert.throws(function() {
sass.renderSync({ data: '#navbar width 80%;' });
});
......
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