Shaka Player Embedded
js_wrappers.h
Go to the documentation of this file.
1 // Copyright 2016 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef SHAKA_EMBEDDED_MAPPING_JS_WRAPPERS_H_
16 #define SHAKA_EMBEDDED_MAPPING_JS_WRAPPERS_H_
17 
18 #include <glog/logging.h>
19 
20 #include <string>
21 #include <vector>
22 
23 #include "src/util/macros.h"
24 // Use the IndexedDB protobuf for ValueType so we don't have to duplicate
25 // the enum here and for IndexedDB storage.
26 #include "src/js/idb/database.pb.h"
27 
28 #if defined(USING_V8)
29 # include <v8.h>
30 # include "src/mapping/v8/v8_utils.h"
31 #elif defined(USING_JSC)
32 # include <JavaScriptCore/JavaScriptCore.h>
34 # include "src/util/cfref.h"
35 #endif
36 
37 namespace shaka {
38 
39 class BackingObject;
40 
41 namespace util {
42 
43 #ifdef USING_JSC
44 template <>
45 struct RefTypeTraits<JSStringRef> {
46  static constexpr const bool AcquireWithRaw = false;
47 
48  static JSStringRef Duplicate(JSStringRef arg) {
49  if (arg)
50  JSStringRetain(arg);
51  return arg;
52  }
53 
54  static void Release(JSStringRef arg) {
55  if (arg)
56  JSStringRelease(arg);
57  }
58 };
59 template <>
60 struct RefTypeTraits<JSValueRef> {
61  static constexpr const bool AcquireWithRaw = true;
62 
63  static JSValueRef Duplicate(JSValueRef arg) {
64  if (arg)
65  JSValueProtect(GetContext(), arg);
66  return arg;
67  }
68 
69  static void Release(JSValueRef arg) {
70  if (arg)
71  JSValueUnprotect(GetContext(), arg);
72  }
73 };
74 template <>
75 struct RefTypeTraits<JSObjectRef> : RefTypeTraits<JSValueRef> {
76  static JSObjectRef Duplicate(JSObjectRef arg) {
77  if (arg)
78  JSValueProtect(GetContext(), arg);
79  return arg;
80  }
81 };
82 
83 #endif
84 
85 } // namespace util
86 
101 #if defined(USING_V8)
102 template <typename T>
103 using Handle = v8::Local<T>;
104 template <typename T>
105 using LocalVar = v8::Local<T>;
106 template <typename T>
107 using ReturnVal = v8::Local<T>;
108 template <typename T>
109 struct Global {
110  Global() {}
111  template <typename U = T>
112  explicit Global(v8::Local<U> val) : val_(GetIsolate(), val) {}
113 
114  template <typename U = T>
115  operator v8::Local<U>() const {
116  return val_.Get(GetIsolate());
117  }
118  operator bool() const {
119  return !val_.IsEmpty();
120  }
121 
122  template <typename U = T>
123  Global& operator=(v8::Local<U> other) {
124  val_.Reset(GetIsolate(), other);
125  return *this;
126  }
127  Global& operator=(std::nullptr_t) {
128  val_.Reset();
129  return *this;
130  }
131 
132  template <typename U = T>
133  bool operator==(v8::Local<U> other) {
134  return val_ == other;
135  }
136 
137  private:
138  v8::Global<T> val_;
139 };
140 
141 using JsValue = v8::Value;
142 using JsObject = v8::Object;
143 using JsString = v8::String;
144 using JsFunction = v8::Function;
145 using JsPromise = v8::Promise;
146 using JsMap = v8::Map;
147 
153 using CallbackArguments = v8::FunctionCallbackInfo<v8::Value>;
154 #elif defined(USING_JSC)
155 template <typename T>
156 using Handle = util::CFRef<T>;
157 template <typename T>
158 using LocalVar = Handle<T>;
159 template <typename T>
160 using ReturnVal = Handle<T>;
161 template <typename T>
162 using Global = Handle<T>;
163 
164 using JsValue = JSValueRef;
165 using JsObject = JSObjectRef;
166 using JsString = JSStringRef;
167 using JsFunction = JSObjectRef;
168 using JsPromise = JSObjectRef;
169 using JsMap = JSObjectRef;
170 
171 class CallbackArguments {
172  public:
173  CallbackArguments(const JSValueRef* args, size_t count, JSObjectRef callee,
174  JSObjectRef thisv, JSValueRef* except);
175  ~CallbackArguments();
176 
177  size_t length() const {
178  return count_;
179  }
180  JSObjectRef callee() const {
181  return callee_;
182  }
183  JSObjectRef thisv() const {
184  return this_;
185  }
186  ReturnVal<JSValueRef> ret() const {
187  return ret_;
188  }
189 
190  ReturnVal<JsValue> operator[](size_t i) const;
191 
192  void SetReturn(Handle<JsValue> ret) const;
193  void SetException(Handle<JsValue> except) const;
194 
195  private:
196  // These need to be modifiable within const methods since in V8
197  // we can modify the return value when the arguments are const.
198  mutable JSValueRef* except_;
199  mutable Handle<JsValue> ret_;
200  const JSObjectRef callee_;
201  const JSObjectRef this_;
202  const JSValueRef* args_;
203  const size_t count_;
204 };
205 #endif
206 
207 
209 inline size_t ArgumentCount(const CallbackArguments& arguments) {
210 #if defined(USING_V8)
211  return arguments.Length();
212 #elif defined(USING_JSC)
213  return arguments.length();
214 #endif
215 }
216 
224 std::vector<std::string> GetMemberNames(Handle<JsObject> object);
225 
227 ReturnVal<JsValue> GetMemberRaw(Handle<JsObject> object,
228  const std::string& name,
229  LocalVar<JsValue>* exception = nullptr);
230 
232 ReturnVal<JsValue> GetArrayIndexRaw(Handle<JsObject> object, size_t index,
233  LocalVar<JsValue>* exception = nullptr);
234 
236 void SetMemberRaw(Handle<JsObject> object, const std::string& name,
237  Handle<JsValue> value);
238 
240 void SetArrayIndexRaw(Handle<JsObject> object, size_t i, Handle<JsValue> value);
241 
243 void SetGenericPropertyRaw(Handle<JsObject> object, const std::string& name,
244  Handle<JsFunction> getter,
245  Handle<JsFunction> setter);
246 
247 
259 bool InvokeConstructor(Handle<JsFunction> ctor, int argc,
260  LocalVar<JsValue>* argv,
261  LocalVar<JsValue>* result_or_except);
262 
275 bool InvokeMethod(Handle<JsFunction> method, Handle<JsObject> that, int argc,
276  LocalVar<JsValue>* argv, LocalVar<JsValue>* result_or_except);
277 
278 
280 std::string ConvertToString(Handle<JsValue> value);
281 
283 ReturnVal<JsValue> WrapPointer(void* ptr);
284 
289 void* MaybeUnwrapPointer(Handle<JsValue> value);
290 
295 BackingObject* GetInternalPointer(Handle<JsValue> value);
296 
301 bool IsDerivedFrom(BackingObject* ptr, const std::string& name);
302 
309 bool RunScript(const std::string& path);
310 
319 bool RunScript(const std::string& path, const uint8_t* data, size_t data_size);
320 
326 ReturnVal<JsValue> ParseJsonString(const std::string& json);
327 
329 ReturnVal<JsString> JsStringFromUtf8(const std::string& str);
330 
332 ReturnVal<JsString> JsStringFromUtf8(const uint8_t* data, size_t size);
333 
335 ReturnVal<JsValue> JsUndefined();
336 
338 ReturnVal<JsValue> JsNull();
339 
341 ReturnVal<JsObject> CreateArray(size_t length);
342 
344 ReturnVal<JsObject> CreateObject();
345 
347 ReturnVal<JsMap> CreateMap();
348 
353 void SetMapValue(Handle<JsMap> map, Handle<JsValue> key, Handle<JsValue> value);
354 
356 bool IsNullOrUndefined(Handle<JsValue> value);
357 
362 bool IsObject(Handle<JsValue> value);
363 
369 bool IsBuiltInObject(Handle<JsObject> object);
370 
372 proto::ValueType GetValueType(Handle<JsValue> value);
373 
374 
376 
381 template <typename Dest>
382 ReturnVal<Dest> UnsafeJsCast(Handle<JsValue> source) {
383 #ifdef USING_V8
384  return source.As<Dest>();
385 #else
386  static_assert(std::is_same<Dest, JsValue>::value,
387  "Should use other specializations");
388  return source;
389 #endif
390 }
391 
392 #ifdef USING_JSC
393 template <>
394 inline ReturnVal<JsObject> UnsafeJsCast<JsObject>(Handle<JsValue> source) {
395  DCHECK(IsObject(source));
396  return JSValueToObject(GetContext(), source, nullptr);
397 }
398 #endif
399 
401 
403 
404 template <typename T>
405 ReturnVal<JsValue> RawToJsValue(Handle<T> source) {
406  return source;
407 }
408 
409 #if defined(USING_JSC)
410 template <>
411 inline ReturnVal<JsValue> RawToJsValue<JsString>(Handle<JsString> source) {
412  return JSValueMakeString(GetContext(), source);
413 }
414 #endif
415 
417 
418 inline size_t ArrayLength(Handle<JsObject> value) {
419 #if defined(USING_V8)
420  DCHECK(GetValueType(value) == proto::ValueType::Array);
421  return value.As<v8::Array>()->Length();
422 #elif defined(USING_JSC)
423  auto* ctx = GetContext();
424  LocalVar<JsValue> length(GetMemberRaw(value, "length"));
425  CHECK(length && JSValueIsNumber(ctx, length));
426  return static_cast<size_t>(JSValueToNumber(ctx, length, nullptr));
427 #endif
428 }
429 
434 double NumberFromValue(Handle<JsValue> value);
435 
440 bool BooleanFromValue(Handle<JsValue> value);
441 
442 } // namespace shaka
443 
444 #endif // SHAKA_EMBEDDED_MAPPING_JS_WRAPPERS_H_
void SetArrayIndexRaw(Handle< JsObject > object, size_t i, Handle< JsValue > value)
Definition: js_wrappers.cc:152
ReturnVal< JsValue > ParseJsonString(const std::string &json)
Definition: js_wrappers.cc:256
ReturnVal< JsObject > CreateObject()
Definition: js_wrappers.cc:296
ReturnVal< JsValue > JsUndefined()
Definition: js_wrappers.cc:284
bool IsObject(Handle< JsValue > value)
Definition: js_wrappers.cc:315
bool IsNullOrUndefined(Handle< JsValue > value)
Definition: js_wrappers.cc:311
std::vector< std::string > GetMemberNames(Handle< JsObject > object)
Definition: js_wrappers.cc:118
ReturnVal< JsValue > JsNull()
Definition: js_wrappers.cc:288
ReturnVal< JsValue > GetArrayIndexRaw(Handle< JsObject > object, size_t index, LocalVar< JsValue > *exception=nullptr)
Definition: js_wrappers.cc:142
size_t ArgumentCount(const CallbackArguments &arguments)
Definition: js_wrappers.h:209
bool InvokeMethod(Handle< JsFunction > method, Handle< JsObject > that, int argc, LocalVar< JsValue > *argv, LocalVar< JsValue > *result_or_except)
Definition: js_wrappers.cc:182
bool operator==(const optional< A > &lhs, const optional< B > &rhs)
Definition: optional.h:207
BackingObject * GetInternalPointer(Handle< JsValue > value)
Definition: js_wrappers.cc:223
const char * name
ReturnVal< Dest > UnsafeJsCast(Handle< JsValue > source)
Definition: js_wrappers.h:382
bool BooleanFromValue(Handle< JsValue > value)
Definition: js_wrappers.cc:394
bool IsDerivedFrom(BackingObject *ptr, const std::string &name)
Definition: js_wrappers.cc:235
ReturnVal< JsObject > CreateArray(size_t length)
Definition: js_wrappers.cc:292
const char * source
Definition: media_utils.cc:30
ReturnVal< JsValue > RawToJsValue(Handle< T > source)
Definition: js_wrappers.h:405
bool RunScript(const std::string &path)
Definition: js_wrappers.cc:239
proto::ValueType GetValueType(Handle< JsValue > value)
Definition: js_wrappers.cc:329
double NumberFromValue(Handle< JsValue > value)
Definition: js_wrappers.cc:385
ReturnVal< JsMap > CreateMap()
Definition: js_wrappers.cc:300
void SetMemberRaw(Handle< JsObject > object, const std::string &name, Handle< JsValue > value)
Definition: js_wrappers.cc:147
void SetMapValue(Handle< JsMap > map, Handle< JsValue > key, Handle< JsValue > value)
Definition: js_wrappers.cc:304
std::string ConvertToString(Handle< JsValue > value)
Definition: js_wrappers.cc:203
JSContextRef GetContext()
Definition: jsc_utils.cc:24
ReturnVal< JsValue > WrapPointer(void *ptr)
Definition: js_wrappers.cc:213
size_t ArrayLength(Handle< JsObject > value)
Definition: js_wrappers.h:418
ReturnVal< JsString > JsStringFromUtf8(const std::string &str)
Definition: js_wrappers.cc:266
bool InvokeConstructor(Handle< JsFunction > ctor, int argc, LocalVar< JsValue > *argv, LocalVar< JsValue > *result_or_except)
Definition: js_wrappers.cc:165
v8::Isolate * GetIsolate()
Definition: v8_utils.cc:27
ReturnVal< JsValue > GetMemberRaw(Handle< JsObject > object, const std::string &name, LocalVar< JsValue > *exception=nullptr)
Definition: js_wrappers.cc:136
void * MaybeUnwrapPointer(Handle< JsValue > value)
Definition: js_wrappers.cc:217
bool IsBuiltInObject(Handle< JsObject > object)
Definition: js_wrappers.cc:319
void SetGenericPropertyRaw(Handle< JsObject > object, const std::string &name, Handle< JsFunction > getter, Handle< JsFunction > setter)
Definition: js_wrappers.cc:158