28 JSClassDefinition wrapper_class_def = {
30 .className =
"<pointer wrapper>",
33 JSClassRef GetWrapperClass() {
34 static JSClassRef class_ =
nullptr;
36 class_ = JSClassCreate(&wrapper_class_def);
43 bool IsInstanceOfStandardType(Handle<JsValue> value,
const std::string&
type) {
45 JSValueRef ctor =
GetMemberRaw(JSContextGetGlobalObject(cx), type);
46 return JSValueIsInstanceOfConstructor(cx, value, UnsafeJsCast<JsObject>(ctor),
55 struct RefTypeTraits<JSPropertyNameArrayRef> {
56 static constexpr
const bool AcquireWithRaw =
false;
58 static JSPropertyNameArrayRef
Duplicate(JSPropertyNameArrayRef arg) {
60 return JSPropertyNameArrayRetain(arg);
65 static void Release(JSPropertyNameArrayRef arg) {
67 JSPropertyNameArrayRelease(arg);
75 CallbackArguments::CallbackArguments(
const JSValueRef* args,
size_t count,
76 JSObjectRef callee, JSObjectRef thisv,
83 CallbackArguments::~CallbackArguments() {}
85 ReturnVal<JsValue> CallbackArguments::operator[](
size_t i)
const {
91 void CallbackArguments::SetReturn(Handle<JsValue> ret)
const {
96 void CallbackArguments::SetException(Handle<JsValue> except)
const {
102 std::vector<std::string>
GetMemberNames(Handle<JsObject>
object) {
104 util::CFRef<JSPropertyNameArrayRef> props =
105 JSObjectCopyPropertyNames(cx,
object);
106 const size_t max = JSPropertyNameArrayGetCount(props);
108 std::vector<std::string> ret;
110 for (
size_t i = 0; i < max; i++) {
111 LocalVar<JsString>
name(util::acquire_ref,
112 JSPropertyNameArrayGetNameAtIndex(props, i));
118 ReturnVal<JsValue>
GetMemberRaw(Handle<JsObject>
object,
119 const std::string&
name,
120 LocalVar<JsValue>* exception) {
121 JSValueRef raw_except =
nullptr;
125 *exception = raw_except;
131 LocalVar<JsValue>* exception) {
132 JSValueRef raw_except =
nullptr;
134 JSObjectGetPropertyAtIndex(
GetContext(),
object, index, &raw_except);
136 *exception = raw_except;
141 void SetMemberRaw(Handle<JsObject>
object,
const std::string& name,
142 Handle<JsValue> value) {
144 kJSPropertyAttributeNone,
nullptr);
148 Handle<JsValue> value) {
149 JSObjectSetPropertyAtIndex(
GetContext(),
object, i, value,
nullptr);
153 Handle<JsFunction> getter,
154 Handle<JsFunction> setter) {
158 LocalVar<JsValue> js_Object =
160 CHECK(js_Object &&
IsObject(js_Object));
161 LocalVar<JsValue> define_prop =
162 GetMemberRaw(UnsafeJsCast<JsObject>(js_Object),
"defineProperty");
170 LocalVar<JsValue> args[] = {object,
ToJsValue(name), props};
171 LocalVar<JsValue> except;
173 UnsafeJsCast<JsObject>(js_Object), 3, args, &except))
178 LocalVar<JsValue>* argv,
179 LocalVar<JsValue>* result_or_except) {
180 JSValueRef except =
nullptr;
181 std::vector<JSValueRef> args(argv, argv + argc);
182 LocalVar<JsValue> ret =
183 JSObjectCallAsConstructor(
GetContext(), ctor, argc, args.data(), &except);
185 *result_or_except = except;
188 *result_or_except = ret;
193 bool InvokeMethod(Handle<JsFunction> func, Handle<JsObject> that,
int argc,
194 LocalVar<JsValue>* argv,
195 LocalVar<JsValue>* result_or_except) {
196 JSValueRef except =
nullptr;
197 std::vector<JSValueRef> args(argv, argv + argc);
198 LocalVar<JsValue> ret = JSObjectCallAsFunction(
GetContext(), func, that, argc,
199 args.data(), &except);
201 *result_or_except = except;
204 *result_or_except = ret;
210 LocalVar<JsString> str(JSValueToStringCopy(
GetContext(), value,
nullptr));
214 const size_t max_size = JSStringGetMaximumUTF8CStringSize(str);
215 std::string ret(max_size,
'\0');
216 const size_t real_size = JSStringGetUTF8CString(str, &ret[0], ret.size());
217 ret.resize(real_size - 1);
222 return JSObjectMake(
GetContext(), GetWrapperClass(), ptr);
226 if (!JSValueIsObjectOfClass(
GetContext(), value, GetWrapperClass()))
228 return JSObjectGetPrivate(JSValueToObject(
GetContext(), value,
nullptr));
232 LocalVar<JsObject> obj(JSValueToObject(
GetContext(), value,
nullptr));
235 return reinterpret_cast<BackingObject*
>(JSObjectGetPrivate(obj));
242 bool RunScript(
const std::string& path) {
244 std::vector<uint8_t> code;
246 return RunScript(path, code.data(), code.size());
249 bool RunScript(
const std::string& path,
const uint8_t* data,
size_t size) {
253 JSValueRef except =
nullptr;
264 return JSValueMakeFromJSONString(
GetContext(), input);
268 util::CFRef<CFStringRef> cf_str(CFStringCreateWithBytes(
269 nullptr, data, size, kCFStringEncodingUTF8,
false));
270 return JSStringCreateWithCFString(cf_str);
274 util::CFRef<CFStringRef> cf_str(CFStringCreateWithBytes(
275 nullptr, reinterpret_cast<const uint8_t*>(str.data()), str.size(),
276 kCFStringEncodingUTF8,
false));
277 return JSStringCreateWithCFString(cf_str);
284 ReturnVal<JsValue>
JsNull() {
290 LocalVar<JsObject> arr(JSObjectMakeArray(cx, 0,
nullptr,
nullptr));
291 SetMemberRaw(arr,
"length", JSValueMakeNumber(cx, length));
296 return JSObjectMake(
GetContext(),
nullptr,
nullptr);
303 void SetMapValue(Handle<JsMap> map, Handle<JsValue> key,
304 Handle<JsValue> value) {
305 LocalVar<JsValue> func_value =
GetMemberRaw(map,
"set");
307 LocalVar<JsFunction> func = UnsafeJsCast<JsFunction>(func_value);
309 LocalVar<JsValue> args[] = {key, value};
310 LocalVar<JsValue> ignored;
316 return !value || JSValueIsNull(cx, value) || JSValueIsUndefined(cx, value);
319 bool IsObject(Handle<JsValue> value) {
324 LocalVar<JsValue> to_string_val =
326 {
"Object",
"prototype",
"toString"});
329 LocalVar<JsObject>
to_string = UnsafeJsCast<JsObject>(to_string_val);
330 LocalVar<JsValue> value;
331 CHECK(
InvokeMethod(to_string,
object, 0,
nullptr, &value));
337 switch (JSValueGetType(cx, value)) {
338 case kJSTypeUndefined:
351 LOG(FATAL) <<
"Unknown JavaScript value type";
355 if (JSValueIsArray(cx, value))
357 if (JSObjectIsFunction(cx, JSValueToObject(cx, value,
nullptr)))
360 switch (JSValueGetTypedArrayType(cx, value,
nullptr)) {
361 case kJSTypedArrayTypeArrayBuffer:
363 case kJSTypedArrayTypeFloat32Array:
365 case kJSTypedArrayTypeFloat64Array:
367 case kJSTypedArrayTypeInt16Array:
369 case kJSTypedArrayTypeInt32Array:
371 case kJSTypedArrayTypeInt8Array:
373 case kJSTypedArrayTypeUint16Array:
375 case kJSTypedArrayTypeUint32Array:
377 case kJSTypedArrayTypeUint8Array:
379 case kJSTypedArrayTypeUint8ClampedArray:
382 case kJSTypedArrayTypeNone:
385 LOG(FATAL) <<
"Unknown JavaScript TypedArray type";
388 if (IsInstanceOfStandardType(value,
"Boolean"))
390 if (IsInstanceOfStandardType(value,
"String"))
392 if (IsInstanceOfStandardType(value,
"Number"))
394 if (IsInstanceOfStandardType(value,
"Promise"))
402 DCHECK(JSValueIsNumber(cx, value) ||
403 IsInstanceOfStandardType(value,
"Number"));
404 return JSValueToNumber(cx, value,
nullptr);
409 if (IsInstanceOfStandardType(value,
"Boolean")) {
410 LocalVar<JsValue> func =
413 LocalVar<JsValue> except;
415 UnsafeJsCast<JsObject>(value), 0,
nullptr, &except));
418 DCHECK(JSValueIsBoolean(cx, value));
420 return JSValueToBoolean(cx, value);
void SetArrayIndexRaw(Handle< JsObject > object, size_t i, Handle< JsValue > value)
ReturnVal< JsValue > ParseJsonString(const std::string &json)
ReturnVal< JsObject > CreateObject()
ReturnVal< JsValue > JsUndefined()
bool IsObject(Handle< JsValue > value)
bool IsNullOrUndefined(Handle< JsValue > value)
std::vector< std::string > GetMemberNames(Handle< JsObject > object)
ReturnVal< JsValue > JsNull()
ReturnVal< JsValue > GetArrayIndexRaw(Handle< JsObject > object, size_t index, LocalVar< JsValue > *exception=nullptr)
ReturnVal< JsValue > GetDescendant(Handle< JsObject > root, const std::vector< std::string > &names)
bool InvokeMethod(Handle< JsFunction > method, Handle< JsObject > that, int argc, LocalVar< JsValue > *argv, LocalVar< JsValue > *result_or_except)
BackingObject * GetInternalPointer(Handle< JsValue > value)
bool BooleanFromValue(Handle< JsValue > value)
bool IsDerivedFrom(BackingObject *ptr, const std::string &name)
ReturnVal< JsObject > CreateArray(size_t length)
static void Release(JSPropertyNameArrayRef arg)
ReturnVal< JsValue > ToJsValue(T &&source)
ReturnVal< JsValue > RawToJsValue(Handle< T > source)
bool RunScript(const std::string &path)
JSValueRef CreateNativeObject(const std::string &name, JSValueRef *args, size_t argc)
proto::ValueType GetValueType(Handle< JsValue > value)
double NumberFromValue(Handle< JsValue > value)
ReturnVal< JsMap > CreateMap()
virtual MUST_USE_RESULT bool ReadFile(const std::string &path, std::vector< uint8_t > *data) const
static JSPropertyNameArrayRef Duplicate(JSPropertyNameArrayRef arg)
void SetMemberRaw(Handle< JsObject > object, const std::string &name, Handle< JsValue > value)
void SetMapValue(Handle< JsMap > map, Handle< JsValue > key, Handle< JsValue > value)
bool DerivedFrom(const std::string &base)
std::string ConvertToString(Handle< JsValue > value)
JSContextRef GetContext()
ReturnVal< JsValue > WrapPointer(void *ptr)
void OnUncaughtException(JSValueRef exception, bool in_promise)
ReturnVal< JsString > JsStringFromUtf8(const std::string &str)
bool InvokeConstructor(Handle< JsFunction > ctor, int argc, LocalVar< JsValue > *argv, LocalVar< JsValue > *result_or_except)
ReturnVal< JsValue > GetMemberRaw(Handle< JsObject > object, const std::string &name, LocalVar< JsValue > *exception=nullptr)
void * MaybeUnwrapPointer(Handle< JsValue > value)
bool IsBuiltInObject(Handle< JsObject > object)
void SetGenericPropertyRaw(Handle< JsObject > object, const std::string &name, Handle< JsFunction > getter, Handle< JsFunction > setter)