#ifndef THE_RUBY_RACER #define THE_RUBY_RACER #include #include #include namespace rr { #define Void(expr) expr; return Qnil; VALUE not_implemented(const char* message); class Equiv { public: Equiv(VALUE val) : value(val) {} inline operator VALUE() {return value;} protected: VALUE value; }; class Bool : public Equiv { public: Bool(VALUE val) : Equiv(val) {} Bool(bool b) : Equiv(b ? Qtrue : Qfalse) {} inline operator bool() {return RTEST(value);} }; class UInt32 : public Equiv { public: UInt32(VALUE val) : Equiv(val) {} UInt32(uint32_t ui) : Equiv(UINT2NUM(ui)) {} inline operator uint32_t() {return RTEST(value) ? NUM2UINT(value) : 0;} }; class GC { public: class Queue { public: Queue(); void Enqueue(void* phantom); void* Dequeue(); private: struct Node { Node(void* val ) : value(val), next(NULL) { } void* value; Node* next; }; Node* first; // for producer only Node* divider; Node* last; }; static void Finalize(void* phantom); static void Drain(v8::GCType type, v8::GCCallbackFlags flags); static void Init(); }; /** * A V8 Enum */ template class Enum : public Equiv { public: Enum(VALUE value, T defaultValue = 0) : Equiv(value) { this->defaultValue = defaultValue; } inline operator T() { return (T)(RTEST(value) ? NUM2INT(value) : defaultValue); } private: T defaultValue; }; /** * A Reference to a V8 managed object */ template class Ref { public: Ref(VALUE value) { this->value = value; } Ref(v8::Handle handle) { this->handle = handle; } virtual operator VALUE() const { return handle.IsEmpty() ? Qnil : (new Holder(handle, Class))->value; } virtual operator v8::Handle() const { if (RTEST(this->value)) { Holder* holder = NULL; Data_Get_Struct(this->value, class Holder, holder); return holder->handle; } else { return v8::Handle(); } } inline v8::Handle operator->() const { return *this;} inline v8::Handle GetHandle() const { return *this;} inline v8::Handle operator*() const {return *this;} static v8::Handle * array(VALUE argv, std::vector< v8::Handle >& v) { for (uint32_t i = 0; i < v.size(); i++) { v[i] = Ref(rb_ary_entry(argv, i)); } return &v[0]; } class Holder { friend class Ref; public: Holder(v8::Handle handle, VALUE klass) { this->handle = v8::Persistent::New(handle); this->value = Data_Wrap_Struct(klass, 0, &Holder::enqueue, this); } virtual ~Holder() { handle.Dispose(); } protected: VALUE value; v8::Persistent handle; static void enqueue(Holder* holder) { holder->value = Qnil; GC::Finalize(holder); } }; VALUE value; v8::Handle handle; static VALUE Class; }; template VALUE Ref::Class; class Handles { public: static void Init(); static VALUE HandleScope(int argc, VALUE* argv, VALUE self); private: static VALUE SetupAndCall(int* state, VALUE code); static VALUE DoCall(VALUE code); }; class Phantom { public: inline Phantom(void* reference) : holder((Ref::Holder*)reference) {} inline bool NotNull() { return this->holder != NULL; } inline void destroy() { delete holder; } Ref::Holder* holder; }; class Context : public Ref { public: static void Init(); static VALUE New(VALUE self); static VALUE Enter(VALUE self); static VALUE Exit(VALUE self); static VALUE Global(VALUE self); static VALUE DetachGlobal(VALUE self); static VALUE ReattachGlobal(VALUE self, VALUE global); static VALUE GetEntered(VALUE self); static VALUE GetCurrent(VALUE self); static VALUE GetCalling(VALUE self); static VALUE SetSecurityToken(VALUE self, VALUE token); static VALUE UseDefaultSecurityToken(VALUE self); static VALUE GetSecurityToken(VALUE self); static VALUE HasOutOfMemoryException(VALUE self); static VALUE InContext(VALUE self); static VALUE SetData(VALUE self, VALUE data); static VALUE GetData(VALUE self); static VALUE AllowCodeGenerationFromStrings(VALUE self, VALUE allow); static VALUE IsCodeGenerationFromStringsAllowed(VALUE self); inline Context(VALUE value) : Ref(value) {} inline Context(v8::Handle cxt) : Ref(cxt) {} }; class External: public Ref { public: static void Init(); static VALUE New(VALUE self, VALUE data); static VALUE Value(VALUE self); inline External(VALUE value) : Ref(value) {} inline External(v8::Handle ext) : Ref(ext) {} static v8::Handle wrap(VALUE data); static VALUE unwrap(v8::Handle external); private: static void release(v8::Persistent object, void* parameter); struct Data { Data(VALUE data); ~Data(); VALUE value; }; }; class Script : public Ref { public: static void Init(); static VALUE New(VALUE klass, VALUE source, VALUE filename); static VALUE Run(VALUE self); inline Script(VALUE value) : Ref(value) {} inline Script(v8::Handle script) : Ref(script) {} }; class Value : public Ref { public: static void Init(); static VALUE IsUndefined(VALUE self); static VALUE IsNull(VALUE self); static VALUE IsTrue(VALUE self); static VALUE IsFalse(VALUE self); static VALUE IsString(VALUE self); static VALUE IsFunction(VALUE self); static VALUE IsArray(VALUE self); static VALUE IsObject(VALUE self); static VALUE IsBoolean(VALUE self); static VALUE IsNumber(VALUE self); static VALUE IsExternal(VALUE self); static VALUE IsInt32(VALUE self); static VALUE IsUint32(VALUE self); static VALUE IsDate(VALUE self); static VALUE IsBooleanObject(VALUE self); static VALUE IsNumberObject(VALUE self); static VALUE IsStringObject(VALUE self); static VALUE IsNativeError(VALUE self); static VALUE IsRegExp(VALUE self); // VALUE ToBoolean(VALUE self); // VALUE ToNumber(VALUE self); static VALUE ToString(VALUE self); static VALUE ToDetailString(VALUE self); static VALUE ToObject(VALUE self); // static VALUE ToInteger(VALUE self); // static VALUE ToUint32(VALUE self); // static VALUE ToInt32(VALUE self); // static VALUE ToArrayIndex(VALUE self); static VALUE BooleanValue(VALUE self); static VALUE NumberValue(VALUE self); static VALUE IntegerValue(VALUE self); static VALUE Uint32Value(VALUE self); static VALUE Int32Value(VALUE self); static VALUE Equals(VALUE self, VALUE other); static VALUE StrictEquals(VALUE self, VALUE other); inline Value(VALUE value) : Ref(value) {} inline Value(v8::Handle value) : Ref(value) {} virtual operator VALUE(); }; class String: public Ref { public: static void Init(); static VALUE New(VALUE self, VALUE value); static VALUE Utf8Value(VALUE self); static VALUE Concat(VALUE self, VALUE left, VALUE right); inline String(VALUE value) : Ref(value) {} inline String(v8::Handle string) : Ref(string) {} }; class PropertyAttribute: public Enum { public: inline PropertyAttribute(VALUE value) : Enum(value, v8::None) {} }; class AccessControl: public Enum { public: inline AccessControl(VALUE value) : Enum(value, v8::DEFAULT) {} }; class Accessor { public: static void Init(); Accessor(VALUE get, VALUE set, VALUE data); Accessor(VALUE get, VALUE set, VALUE query, VALUE deleter, VALUE enumerator, VALUE data); Accessor(v8::Handle value); inline v8::AccessorGetter accessorGetter() {return &AccessorGetter;} inline v8::AccessorSetter accessorSetter() {return RTEST(set) ? &AccessorSetter : 0;} inline v8::NamedPropertyGetter namedPropertyGetter() {return &NamedPropertyGetter;} inline v8::NamedPropertySetter namedPropertySetter() {return RTEST(set) ? &NamedPropertySetter : 0;} inline v8::NamedPropertyQuery namedPropertyQuery() {return RTEST(query) ? &NamedPropertyQuery : 0;} inline v8::NamedPropertyDeleter namedPropertyDeleter() {return RTEST(deleter) ? &NamedPropertyDeleter : 0;} inline v8::NamedPropertyEnumerator namedPropertyEnumerator() {return RTEST(enumerator) ? &NamedPropertyEnumerator : 0;} inline v8::IndexedPropertyGetter indexedPropertyGetter() {return &IndexedPropertyGetter;} inline v8::IndexedPropertySetter indexedPropertySetter() {return RTEST(set) ? &IndexedPropertySetter : 0;} inline v8::IndexedPropertyQuery indexedPropertyQuery() {return RTEST(query) ? &IndexedPropertyQuery : 0;} inline v8::IndexedPropertyDeleter indexedPropertyDeleter() {return RTEST(deleter) ? &IndexedPropertyDeleter : 0;} inline v8::IndexedPropertyEnumerator indexedPropertyEnumerator() {return RTEST(enumerator) ? &IndexedPropertyEnumerator : 0;} operator v8::Handle(); class Info { public: Info(const v8::AccessorInfo& info); Info(VALUE value); static VALUE This(VALUE self); static VALUE Holder(VALUE self); static VALUE Data(VALUE self); operator VALUE(); inline const v8::AccessorInfo* operator->() {return this->info;} v8::Handle get(v8::Local property); v8::Handle set(v8::Local property, v8::Local value); v8::Handle query(v8::Local property); v8::Handle remove(v8::Local property); v8::Handle enumerateNames(); v8::Handle get(uint32_t index); v8::Handle set(uint32_t index, v8::Local value); v8::Handle query(uint32_t index); v8::Handle remove(uint32_t index); v8::Handle enumerateIndices(); static VALUE Class; private: const v8::AccessorInfo* info; }; friend class Info; private: static v8::Handle AccessorGetter(v8::Local property, const v8::AccessorInfo& info); static void AccessorSetter(v8::Local property, v8::Local value, const v8::AccessorInfo& info); static v8::Handle NamedPropertyGetter(v8::Local property, const v8::AccessorInfo& info); static v8::Handle NamedPropertySetter(v8::Local property, v8::Local value, const v8::AccessorInfo& info); static v8::Handle NamedPropertyQuery(v8::Local property, const v8::AccessorInfo& info); static v8::Handle NamedPropertyDeleter(v8::Local property, const v8::AccessorInfo& info); static v8::Handle NamedPropertyEnumerator(const v8::AccessorInfo& info); static v8::Handle IndexedPropertyGetter(uint32_t index, const v8::AccessorInfo& info); static v8::Handle IndexedPropertySetter(uint32_t index, v8::Local value, const v8::AccessorInfo& info); static v8::Handle IndexedPropertyQuery(uint32_t index, const v8::AccessorInfo& info); static v8::Handle IndexedPropertyDeleter(uint32_t index, const v8::AccessorInfo& info); static v8::Handle IndexedPropertyEnumerator(const v8::AccessorInfo& info); void wrap(v8::Handle wrapper, int index, VALUE value); VALUE unwrap(v8::Handle wrapper, int index); VALUE get; VALUE set; VALUE query; VALUE deleter; VALUE enumerator; VALUE data; }; class Invocation { public: static void Init(); Invocation(VALUE code, VALUE data); Invocation(v8::Handle wrapper); operator v8::InvocationCallback(); operator v8::Handle(); static v8::Handle Callback(const v8::Arguments& args); class Arguments { public: static void Init(); Arguments(const v8::Arguments& args); Arguments(VALUE value); inline const v8::Arguments* operator->() {return this->args;} inline const v8::Arguments operator*() {return *this->args;} v8::Handle Call(); static VALUE Length(VALUE self); static VALUE Get(VALUE self, VALUE index); static VALUE Callee(VALUE self); static VALUE This(VALUE self); static VALUE Holder(VALUE self); static VALUE IsConstructCall(VALUE self); static VALUE Data(VALUE self); private: const v8::Arguments* args; static VALUE Class; }; private: VALUE code; VALUE data; friend class Arguments; }; class Object : public Ref { public: static void Init(); static VALUE New(VALUE self); static VALUE Set(VALUE self, VALUE key, VALUE value); static VALUE ForceSet(VALUE self, VALUE key, VALUE value); static VALUE Get(VALUE self, VALUE key); static VALUE GetPropertyAttributes(VALUE self, VALUE key); static VALUE Has(VALUE self, VALUE key); static VALUE Delete(VALUE self, VALUE key); static VALUE ForceDelete(VALUE self, VALUE key); static VALUE SetAccessor(int argc, VALUE* argv, VALUE self); static VALUE GetPropertyNames(VALUE self); static VALUE GetOwnPropertyNames(VALUE self); static VALUE GetPrototype(VALUE self); static VALUE SetPrototype(VALUE self, VALUE prototype); static VALUE FindInstanceInPrototypeChain(VALUE self, VALUE impl); static VALUE ObjectProtoToString(VALUE self); static VALUE GetConstructorName(VALUE self); static VALUE InternalFieldCount(VALUE self); static VALUE GetInternalField(VALUE self, VALUE idx); static VALUE SetInternalField(VALUE self, VALUE idx, VALUE value); static VALUE HasOwnProperty(VALUE self, VALUE key); static VALUE HasRealNamedProperty(VALUE self, VALUE key); static VALUE HasRealIndexedProperty(VALUE self, VALUE idx); static VALUE HasRealNamedCallbackProperty(VALUE self, VALUE key); static VALUE GetRealNamedPropertyInPrototypeChain(VALUE self, VALUE key); static VALUE GetRealNamedProperty(VALUE self, VALUE key); static VALUE HasNamedLookupInterceptor(VALUE self); static VALUE HasIndexedLookupInterceptor(VALUE self); static VALUE TurnOnAccessCheck(VALUE self); static VALUE GetIdentityHash(VALUE self); static VALUE SetHiddenValue(VALUE self, VALUE key, VALUE value); static VALUE GetHiddenValue(VALUE self, VALUE key); static VALUE DeleteHiddenValue(VALUE self, VALUE key); static VALUE IsDirty(VALUE self); static VALUE Clone(VALUE self); static VALUE CreationContext(VALUE self); static VALUE SetIndexedPropertiesToPixelData(VALUE self, VALUE data, VALUE length); static VALUE GetIndexedPropertiesPixelData(VALUE self); static VALUE HasIndexedPropertiesInPixelData(VALUE self); static VALUE GetIndexedPropertiesPixelDataLength(VALUE self); static VALUE SetIndexedPropertiesToExternalArrayData(VALUE self); static VALUE HasIndexedPropertiesInExternalArrayData(VALUE self); static VALUE GetIndexedPropertiesExternalArrayData(VALUE self); static VALUE GetIndexedPropertiesExternalArrayDataType(VALUE self); static VALUE GetIndexedPropertiesExternalArrayDataLength(VALUE self); static VALUE IsCallable(VALUE self); static VALUE CallAsFunction(VALUE self, VALUE recv, VALUE argc, VALUE argv); static VALUE CallAsConstructor(VALUE self, VALUE argc, VALUE argv); inline Object(VALUE value) : Ref(value) {} inline Object(v8::Handle object) : Ref(object) {} virtual operator VALUE(); }; class Array : public Ref { public: static void Init(); static VALUE New(int argc, VALUE argv[], VALUE self); static VALUE Length(VALUE self); static VALUE CloneElementAt(VALUE self, VALUE index); inline Array(v8::Handle array) : Ref(array) {} inline Array(VALUE value) : Ref(value) {} }; class Function : public Ref { public: static void Init(); static VALUE NewInstance(int i, VALUE v[], VALUE self); static VALUE Call(VALUE self, VALUE receiver, VALUE argc, VALUE argv); static VALUE SetName(VALUE self, VALUE name); static VALUE GetName(VALUE self); static VALUE GetInferredName(VALUE self); static VALUE GetScriptLineNumber(VALUE self); static VALUE GetScriptColumnNumber(VALUE self); static VALUE GetScriptId(VALUE self); static VALUE GetScriptOrigin(VALUE self); inline Function(VALUE value) : Ref(value) {} inline Function(v8::Handle function) : Ref(function) {} }; class Signature : public Ref { public: static void Init(); static VALUE New(int argc, VALUE argv[], VALUE self); inline Signature(v8::Handle sig) : Ref(sig) {} inline Signature(VALUE value) : Ref(value) {} }; class Template { public: static void Init(); }; class ObjectTemplate : public Ref { public: static void Init(); static VALUE New(VALUE self); static VALUE NewInstance(VALUE self); static VALUE SetAccessor(int argc, VALUE argv[], VALUE self); static VALUE SetNamedPropertyHandler(int argc, VALUE argv[], VALUE self); static VALUE SetIndexedPropertyHandler(int argc, VALUE argv[], VALUE self); static VALUE SetCallAsFunctionHandler(int argc, VALUE argv[], VALUE self); static VALUE MarkAsUndetectable(VALUE self); static VALUE SetAccessCheckCallbacks(int argc, VALUE argv[], VALUE self); static VALUE InternalFieldCount(VALUE self); static VALUE SetInternalFieldCount(VALUE self, VALUE count); inline ObjectTemplate(VALUE value) : Ref(value) {} inline ObjectTemplate(v8::Handle t) : Ref(t) {} }; class FunctionTemplate : public Ref { public: static void Init(); static VALUE New(int argc, VALUE argv[], VALUE self); static VALUE GetFunction(VALUE self); static VALUE SetCallHandler(int argc, VALUE argv[], VALUE self); static VALUE InstanceTemplate(VALUE self); static VALUE Inherit(VALUE self, VALUE parent); static VALUE PrototypeTemplate(VALUE self); static VALUE SetClassName(VALUE self, VALUE name); static VALUE SetHiddenPrototype(VALUE self, VALUE value); static VALUE ReadOnlyPrototype(VALUE self); static VALUE HasInstance(VALUE self, VALUE object); inline FunctionTemplate(VALUE value) : Ref(value) {} inline FunctionTemplate(v8::Handle t) : Ref(t) {} }; class Message : public Ref { public: static void Init(); inline Message(v8::Handle message) : Ref(message) {} inline Message(VALUE value) : Ref(value) {} static VALUE Get(VALUE self); static VALUE GetSourceLine(VALUE self); static VALUE GetScriptResourceName(VALUE self); static VALUE GetScriptData(VALUE self); static VALUE GetStackTrace(VALUE self); static VALUE GetLineNumber(VALUE self); static VALUE GetStartPosition(VALUE self); static VALUE GetEndPosition(VALUE self); static VALUE GetStartColumn(VALUE self); static VALUE GetEndColumn(VALUE self); static inline VALUE kNoLineNumberInfo(VALUE self) {return INT2FIX(v8::Message::kNoLineNumberInfo);} static inline VALUE kNoColumnInfo(VALUE self) {return INT2FIX(v8::Message::kNoColumnInfo);} }; class Stack { public: static void Init(); class Trace : public Ref { public: class StackTraceOptions : public Enum { public: inline StackTraceOptions(VALUE value) : Enum(value, v8::StackTrace::kOverview) {} }; public: inline Trace(v8::Handle trace) : Ref(trace) {} inline Trace(VALUE value) : Ref(value) {} static inline VALUE kLineNumber(VALUE self) {return INT2FIX(v8::StackTrace::kLineNumber);} static inline VALUE kColumnOffset(VALUE self) {return INT2FIX(v8::StackTrace::kColumnOffset);} static inline VALUE kScriptName(VALUE self) {return INT2FIX(v8::StackTrace::kScriptName);} static inline VALUE kFunctionName(VALUE self) {return INT2FIX(v8::StackTrace::kFunctionName);} static inline VALUE kIsEval(VALUE self) {return INT2FIX(v8::StackTrace::kIsEval);} static inline VALUE kIsConstructor(VALUE self) {return INT2FIX(v8::StackTrace::kIsConstructor);} static inline VALUE kScriptNameOrSourceURL(VALUE self) {return INT2FIX(v8::StackTrace::kScriptNameOrSourceURL);} static inline VALUE kOverview(VALUE self) {return INT2FIX(v8::StackTrace::kOverview);} static inline VALUE kDetailed(VALUE self) {return INT2FIX(v8::StackTrace::kDetailed);} static VALUE GetFrame(VALUE self, VALUE index); static VALUE GetFrameCount(VALUE self); static VALUE AsArray(VALUE self); static VALUE CurrentStackTrace(int argc, VALUE argv[], VALUE self); }; class Frame : public Ref { public: inline Frame(v8::Handle frame) : Ref(frame) {} inline Frame(VALUE value) : Ref(value) {} static VALUE GetLineNumber(VALUE self); static VALUE GetColumn(VALUE self); static VALUE GetScriptName(VALUE self); static VALUE GetScriptNameOrSourceURL(VALUE self); static VALUE GetFunctionName(VALUE self); static VALUE IsEval(VALUE self); static VALUE IsConstructor(VALUE self); }; }; class TryCatch { public: static void Init(); TryCatch(); TryCatch(VALUE value); ~TryCatch(); operator VALUE(); inline v8::TryCatch* operator->() {return this->impl;} static VALUE HasCaught(VALUE self); static VALUE CanContinue(VALUE self); static VALUE ReThrow(VALUE self); static VALUE Exception(VALUE self); static VALUE StackTrace(VALUE self); static VALUE Message(VALUE self); static VALUE Reset(VALUE self); static VALUE SetVerbose(VALUE self, VALUE value); static VALUE SetCaptureMessage(VALUE self, VALUE value); private: static VALUE doTryCatch(int argc, VALUE argv[], VALUE self); static VALUE setupAndCall(int* state, VALUE code); static VALUE doCall(VALUE code); static VALUE Class; v8::TryCatch* impl; bool allocated; }; class Locker { public: static void Init(); static VALUE StartPreemption(VALUE self, VALUE every_n_ms); static VALUE StopPreemption(VALUE self); static VALUE IsLocked(VALUE self); static VALUE IsActive(VALUE self); static VALUE doLock(int argc, VALUE* argv, VALUE self); static VALUE setupLockAndCall(int* state, VALUE code); static VALUE doLockCall(VALUE code); static VALUE doUnlock(int argc, VALUE* argv, VALUE self); static VALUE setupUnlockAndCall(int* state, VALUE code); static VALUE doUnlockCall(VALUE code); }; class V8 { public: static void Init(); static VALUE IdleNotification(VALUE self); static VALUE SetCaptureStackTraceForUncaughtExceptions(int argc, VALUE argv[], VALUE self); }; class ClassBuilder { public: ClassBuilder(const char* name, VALUE superclass = rb_cObject); ClassBuilder(const char* name, const char* supername); ClassBuilder& defineMethod(const char* name, VALUE (*impl)(int, VALUE*, VALUE)); ClassBuilder& defineMethod(const char* name, VALUE (*impl)(VALUE)); ClassBuilder& defineMethod(const char* name, VALUE (*impl)(VALUE, VALUE)); ClassBuilder& defineMethod(const char* name, VALUE (*impl)(VALUE, VALUE, VALUE)); ClassBuilder& defineMethod(const char* name, VALUE (*impl)(VALUE, VALUE, VALUE, VALUE)); ClassBuilder& defineSingletonMethod(const char* name, VALUE (*impl)(int, VALUE*, VALUE)); ClassBuilder& defineSingletonMethod(const char* name, VALUE (*impl)(VALUE)); ClassBuilder& defineSingletonMethod(const char* name, VALUE (*impl)(VALUE, VALUE)); ClassBuilder& defineSingletonMethod(const char* name, VALUE (*impl)(VALUE, VALUE, VALUE)); ClassBuilder& defineSingletonMethod(const char* name, VALUE (*impl)(VALUE, VALUE, VALUE, VALUE)); ClassBuilder& defineEnumConst(const char* name, int value); ClassBuilder& store(VALUE* storage); inline operator VALUE() {return this->value;} private: VALUE value; }; } #endif