1 #ifndef SASS_TYPES_SASS_VALUE_WRAPPER_H
2 #define SASS_TYPES_SASS_VALUE_WRAPPER_H
12 // Include this in any SassTypes::Value subclasses to handle all the heavy lifting of constructing JS
13 // objects and wrapping sass values inside them
15 class SassValueWrapper : public SassTypes::Value {
17 static char const* get_constructor_name() { return "SassValue"; }
19 SassValueWrapper(Sass_Value*);
20 virtual ~SassValueWrapper();
22 Sass_Value* get_sass_value();
23 v8::Local<v8::Object> get_js_object();
25 static v8::Local<v8::Function> get_constructor();
26 static v8::Local<v8::FunctionTemplate> get_constructor_template();
27 static NAN_METHOD(New);
28 static Sass_Value *fail(const char *, Sass_Value **);
32 static T* unwrap(v8::Local<v8::Object>);
35 static Nan::Persistent<v8::Function> constructor;
36 Nan::Persistent<v8::Object> js_object;
40 Nan::Persistent<v8::Function> SassValueWrapper<T>::constructor;
43 SassValueWrapper<T>::SassValueWrapper(Sass_Value* v) {
44 this->value = sass_clone_value(v);
48 SassValueWrapper<T>::~SassValueWrapper() {
49 this->js_object.Reset();
50 sass_delete_value(this->value);
54 Sass_Value* SassValueWrapper<T>::get_sass_value() {
55 return sass_clone_value(this->value);
59 v8::Local<v8::Object> SassValueWrapper<T>::get_js_object() {
60 if (this->js_object.IsEmpty()) {
61 v8::Local<v8::Object> wrapper = Nan::NewInstance(T::get_constructor()).ToLocalChecked();
62 delete static_cast<T*>(Nan::GetInternalFieldPointer(wrapper, 0));
63 Nan::SetInternalFieldPointer(wrapper, 0, this);
64 this->js_object.Reset(wrapper);
67 return Nan::New(this->js_object);
71 v8::Local<v8::FunctionTemplate> SassValueWrapper<T>::get_constructor_template() {
72 Nan::EscapableHandleScope scope;
73 v8::Local<v8::FunctionTemplate> tpl = Nan::New<v8::FunctionTemplate>(New);
74 tpl->SetClassName(Nan::New<v8::String>(T::get_constructor_name()).ToLocalChecked());
75 tpl->InstanceTemplate()->SetInternalFieldCount(1);
76 T::initPrototype(tpl);
78 return scope.Escape(tpl);
82 v8::Local<v8::Function> SassValueWrapper<T>::get_constructor() {
83 if (constructor.IsEmpty()) {
84 constructor.Reset(Nan::GetFunction(T::get_constructor_template()).ToLocalChecked());
87 return Nan::New(constructor);
91 NAN_METHOD(SassValueWrapper<T>::New) {
92 std::vector<v8::Local<v8::Value>> localArgs(info.Length());
94 for (auto i = 0; i < info.Length(); ++i) {
95 localArgs[i] = info[i];
97 if (info.IsConstructCall()) {
99 if (T::construct(localArgs, &value) != NULL) {
100 T* obj = new T(value);
101 sass_delete_value(value);
103 Nan::SetInternalFieldPointer(info.This(), 0, obj);
104 obj->js_object.Reset(info.This());
106 return Nan::ThrowError(Nan::New<v8::String>(sass_error_get_message(value)).ToLocalChecked());
109 v8::Local<v8::Function> cons = T::get_constructor();
110 v8::Local<v8::Object> inst;
111 if (Nan::NewInstance(cons, info.Length(), &localArgs[0]).ToLocal(&inst)) {
112 info.GetReturnValue().Set(inst);
114 info.GetReturnValue().Set(Nan::Undefined());
120 T* SassValueWrapper<T>::unwrap(v8::Local<v8::Object> obj) {
121 /* This maybe NULL */
122 return static_cast<T*>(Factory::unwrap(obj));
126 Sass_Value *SassValueWrapper<T>::fail(const char *reason, Sass_Value **out) {
127 *out = sass_make_error(reason);