Expose V8 C++ type checking to JS
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

174 lines
5.5 KiB

#include <node.h>
#include <v8.h>
using namespace v8;
#define ARRAY String::NewSymbol("array")
#define BOOLEAN String::NewSymbol("boolean")
#define BOOLEAN_OBJECT String::NewSymbol("boolean_object")
#define DATE String::NewSymbol("date")
#define FUNCTION String::NewSymbol("function")
#define NUMBER String::NewSymbol("number")
#define NUMBER_OBJECT String::NewSymbol("number_object")
#define REGEXP String::NewSymbol("regexp")
#define STRING String::NewSymbol("string")
#define STRING_OBJECT String::NewSymbol("string_object")
#define OBJECT String::NewSymbol("object")
#define UNDEFINED String::NewSymbol("undefined")
#define NULL_TYPE String::NewSymbol("null")
#define PRIMITIVE String::NewSymbol("primitive")
Handle<Value> v8type_of(const Arguments& args){
HandleScope scope;
if(args.Length() < 1){
ThrowException(Exception::TypeError(String::New("v8type.of function requires at least 1 argument")));
return scope.Close(Undefined());
}
if(args[0]->IsArray()){
return scope.Close(ARRAY);
} else if(args[0]->IsBoolean()){
return scope.Close(BOOLEAN);
} else if(args[0]->IsBooleanObject()){
return scope.Close(BOOLEAN_OBJECT);
} else if(args[0]->IsDate()){
return scope.Close(DATE);
} else if(args[0]->IsFunction()){
return scope.Close(FUNCTION);
} else if(args[0]->IsNumber()){
return scope.Close(NUMBER);
} else if(args[0]->IsNumberObject()){
return scope.Close(NUMBER_OBJECT);
} else if(args[0]->IsString()){
return scope.Close(STRING);
} else if(args[0]->IsStringObject()){
return scope.Close(STRING_OBJECT);
} else if(args[0]->IsRegExp()){
return scope.Close(REGEXP);
} else if(args[0]->IsUndefined()){
return scope.Close(UNDEFINED);
} else if(args[0]->IsNull()){
return scope.Close(NULL_TYPE);
} else if(args[0]->IsObject()){
return scope.Close(OBJECT);
}
return scope.Close(Undefined());
}
Handle<Value> v8type_is(const Arguments& args){
HandleScope scope;
if(args.Length() < 2){
ThrowException(Exception::TypeError(String::New("v8type.is function requires at least 2 arguments")));
return scope.Close(Undefined());
}
if(!args[1]->IsString()){
ThrowException(Exception::TypeError(String::New("v8type.is second argument must be a string")));
return scope.Close(Undefined());
}
Handle<Context> context = Context::New();
Context::Scope context_scope(context);
Handle<Value> arguments[] = { args[0] };
Handle<Value> type = FunctionTemplate::New(v8type_of)->GetFunction()->Call(context->Global(), 1, arguments);
return scope.Close(Boolean::New(args[1] == type));
}
Handle<Value> v8type_instance(const Arguments& args){
HandleScope scope;
if(args.Length() < 2){
ThrowException(Exception::TypeError(String::New("v8type.instance function requires at least 2 arguments")));
return scope.Close(Undefined());
}
if(!args[1]->IsString()){
ThrowException(Exception::TypeError(String::New("v8type.instance second argument must be a string")));
return scope.Close(Undefined());
}
Handle<Context> context = Context::New();
Context::Scope context_scope(context);
Handle<Value> arguments[] = { args[0] };
Handle<Value> type = FunctionTemplate::New(v8type_of)->GetFunction()->Call(context->Global(), 1, arguments);
if(args[1] == type){
return scope.Close(Boolean::New(true));
}
if(args[1]->ToString() == OBJECT){
if(type == ARRAY or type == FUNCTION or type == DATE or type == REGEXP or type == STRING_OBJECT
or type == BOOLEAN_OBJECT or type == NUMBER_OBJECT){
return scope.Close(Boolean::New(true));
}
} else if(args[1]->ToString() == PRIMITIVE){
if(type == NUMBER or type == BOOLEAN or type == STRING){
return scope.Close(Boolean::New(true));
}
} else if(args[1]->ToString() == NUMBER and type == NUMBER_OBJECT){
return scope.Close(Boolean::New(true));
} else if(args[1]->ToString() == STRING and type == STRING_OBJECT){
return scope.Close(Boolean::New(true));
} else if(args[1]->ToString() == BOOLEAN and type == BOOLEAN_OBJECT){
return scope.Close(Boolean::New(true));
}
return scope.Close(Boolean::New(false));
}
void init_constants(Handle<Object> target){
target->Set(String::NewSymbol("ARRAY"), ARRAY);
target->Set(String::NewSymbol("BOOLEAN"), BOOLEAN);
target->Set(String::NewSymbol("BOOLEAN_OBJECT"), BOOLEAN_OBJECT);
target->Set(String::NewSymbol("DATE"), DATE);
target->Set(String::NewSymbol("FUNCTION"), FUNCTION);
target->Set(String::NewSymbol("NUMBER"), NUMBER);
target->Set(String::NewSymbol("NUMBER_OBJECT"), NUMBER_OBJECT);
target->Set(String::NewSymbol("REGEXP"), REGEXP);
target->Set(String::NewSymbol("STRING"), STRING);
target->Set(String::NewSymbol("STRING_OBJECT"), STRING_OBJECT);
target->Set(String::NewSymbol("OBJECT"), OBJECT);
target->Set(String::NewSymbol("UNDEFINED"), UNDEFINED);
target->Set(String::NewSymbol("NULL"), NULL_TYPE);
target->Set(String::NewSymbol("PRIMITIVE"), PRIMITIVE);
}
void init_v8type_of(Handle<Object> target){
target->Set(String::NewSymbol("of"), FunctionTemplate::New(v8type_of)->GetFunction());
}
void init_v8type_is(Handle<Object> target){
target->Set(String::NewSymbol("is"), FunctionTemplate::New(v8type_is)->GetFunction());
}
void init_v8type_instance(Handle<Object> target){
target->Set(String::NewSymbol("instance"), FunctionTemplate::New(v8type_instance)->GetFunction());
}
void init(Handle<Object> target){
init_constants(target);
init_v8type_of(target);
init_v8type_is(target);
init_v8type_instance(target);
}
NODE_MODULE(v8type, init);