Initial commit
[yaffs-website] / node_modules / node-sass / src / sass_types / sass_value_wrapper.h
1 #ifndef SASS_TYPES_SASS_VALUE_WRAPPER_H
2 #define SASS_TYPES_SASS_VALUE_WRAPPER_H
3
4 #include <stdexcept>
5 #include <vector>
6 #include <nan.h>
7 #include "value.h"
8 #include "factory.h"
9
10 namespace SassTypes
11 {
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
14   template <class T>
15   class SassValueWrapper : public SassTypes::Value {
16     public:
17       static char const* get_constructor_name() { return "SassValue"; }
18
19       SassValueWrapper(Sass_Value*);
20       virtual ~SassValueWrapper();
21
22       Sass_Value* get_sass_value();
23       v8::Local<v8::Object> get_js_object();
24
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 **);
29
30     protected:
31       Sass_Value* value;
32       static T* unwrap(v8::Local<v8::Object>);
33
34     private:
35       static Nan::Persistent<v8::Function> constructor;
36       Nan::Persistent<v8::Object> js_object;
37   };
38
39   template <class T>
40   Nan::Persistent<v8::Function> SassValueWrapper<T>::constructor;
41
42   template <class T>
43   SassValueWrapper<T>::SassValueWrapper(Sass_Value* v) {
44     this->value = sass_clone_value(v);
45   }
46
47   template <class T>
48   SassValueWrapper<T>::~SassValueWrapper() {
49     this->js_object.Reset();
50     sass_delete_value(this->value);
51   }
52
53   template <class T>
54   Sass_Value* SassValueWrapper<T>::get_sass_value() {
55     return sass_clone_value(this->value);
56   }
57
58   template <class T>
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);
65     }
66
67     return Nan::New(this->js_object);
68   }
69
70   template <class T>
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);
77
78     return scope.Escape(tpl);
79   }
80
81   template <class T>
82   v8::Local<v8::Function> SassValueWrapper<T>::get_constructor() {
83     if (constructor.IsEmpty()) {
84       constructor.Reset(Nan::GetFunction(T::get_constructor_template()).ToLocalChecked());
85     }
86
87     return Nan::New(constructor);
88   }
89
90   template <class T>
91   NAN_METHOD(SassValueWrapper<T>::New) {
92     std::vector<v8::Local<v8::Value>> localArgs(info.Length());
93
94     for (auto i = 0; i < info.Length(); ++i) {
95       localArgs[i] = info[i];
96     }
97     if (info.IsConstructCall()) {
98       Sass_Value* value;
99       if (T::construct(localArgs, &value) != NULL) {
100         T* obj = new T(value);
101         sass_delete_value(value);
102
103         Nan::SetInternalFieldPointer(info.This(), 0, obj);
104         obj->js_object.Reset(info.This());
105       } else {
106         return Nan::ThrowError(Nan::New<v8::String>(sass_error_get_message(value)).ToLocalChecked());
107       }
108     } else {
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);
113       } else {
114         info.GetReturnValue().Set(Nan::Undefined());
115       }
116     }
117   }
118
119   template <class T>
120   T* SassValueWrapper<T>::unwrap(v8::Local<v8::Object> obj) {
121     /* This maybe NULL */
122     return static_cast<T*>(Factory::unwrap(obj));
123   }
124
125   template <class T>
126   Sass_Value *SassValueWrapper<T>::fail(const char *reason, Sass_Value **out) {
127     *out = sass_make_error(reason);
128     return NULL;
129   }
130 }
131
132
133 #endif