102 lines
3.2 KiB
C++
102 lines
3.2 KiB
C++
#ifndef SASS_TYPES_SASS_VALUE_WRAPPER_H
|
|
#define SASS_TYPES_SASS_VALUE_WRAPPER_H
|
|
|
|
#include <stdexcept>
|
|
#include <vector>
|
|
#include <nan.h>
|
|
#include "value.h"
|
|
#include "factory.h"
|
|
|
|
namespace SassTypes
|
|
{
|
|
// 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 SassTypes::Value { */
|
|
class SassValueWrapper : public SassTypes::Value {
|
|
public:
|
|
static char const* get_constructor_name() { return "SassValue"; }
|
|
|
|
SassValueWrapper(Sass_Value* v) : Value(v) { }
|
|
v8::Local<v8::Object> get_js_object();
|
|
|
|
static v8::Local<v8::Function> get_constructor();
|
|
static v8::Local<v8::FunctionTemplate> get_constructor_template();
|
|
static NAN_METHOD(New);
|
|
static Sass_Value *fail(const char *, Sass_Value **);
|
|
|
|
/* private: */
|
|
static Nan::Persistent<v8::Function> constructor;
|
|
};
|
|
|
|
template <class T>
|
|
Nan::Persistent<v8::Function> SassValueWrapper<T>::constructor;
|
|
|
|
template <class T>
|
|
v8::Local<v8::Object> SassValueWrapper<T>::get_js_object() {
|
|
if (this->persistent().IsEmpty()) {
|
|
v8::Local<v8::Object> wrapper = Nan::NewInstance(T::get_constructor()).ToLocalChecked();
|
|
this->Wrap(wrapper);
|
|
}
|
|
|
|
return this->handle();
|
|
}
|
|
|
|
template <class T>
|
|
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);
|
|
|
|
return scope.Escape(tpl);
|
|
}
|
|
|
|
template <class T>
|
|
v8::Local<v8::Function> SassValueWrapper<T>::get_constructor() {
|
|
if (constructor.IsEmpty()) {
|
|
constructor.Reset(Nan::GetFunction(T::get_constructor_template()).ToLocalChecked());
|
|
}
|
|
|
|
return Nan::New(constructor);
|
|
}
|
|
|
|
template <class T>
|
|
NAN_METHOD(SassValueWrapper<T>::New) {
|
|
std::vector<v8::Local<v8::Value>> localArgs(info.Length());
|
|
|
|
for (auto i = 0; i < info.Length(); ++i) {
|
|
localArgs[i] = info[i];
|
|
}
|
|
if (info.IsConstructCall()) {
|
|
Sass_Value* value;
|
|
if (T::construct(localArgs, &value) != NULL) {
|
|
T* obj = new T(value);
|
|
sass_delete_value(value);
|
|
|
|
obj->Wrap(info.This());
|
|
info.GetReturnValue().Set(info.This());
|
|
} else {
|
|
return Nan::ThrowError(Nan::New<v8::String>(sass_error_get_message(value)).ToLocalChecked());
|
|
}
|
|
} else {
|
|
v8::Local<v8::Function> cons = T::get_constructor();
|
|
v8::Local<v8::Object> inst;
|
|
if (Nan::NewInstance(cons, info.Length(), &localArgs[0]).ToLocal(&inst)) {
|
|
info.GetReturnValue().Set(inst);
|
|
} else {
|
|
info.GetReturnValue().Set(Nan::Undefined());
|
|
}
|
|
}
|
|
}
|
|
|
|
template <class T>
|
|
Sass_Value *SassValueWrapper<T>::fail(const char *reason, Sass_Value **out) {
|
|
*out = sass_make_error(reason);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
#endif
|