Shaka Player Embedded
idb_utils.cc
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 #include "src/js/idb/idb_utils.h"
16 
17 #include <glog/logging.h>
18 
19 #include <vector>
20 
21 #include "src/js/js_error.h"
23 #include "src/mapping/convert_js.h"
25 #include "src/util/utils.h"
26 
27 namespace shaka {
28 namespace js {
29 namespace idb {
30 
31 namespace {
32 
33 ReturnVal<JsValue> ToJsObject(bool value) {
34 #ifdef USING_V8
35  return v8::BooleanObject::New(GetIsolate(), value);
36 #elif defined(USING_JSC)
37  LocalVar<JsValue> value_js = ToJsValue(value);
38  JSValueRef arg = value_js;
39  return CreateNativeObject("Boolean", &arg, 1);
40 #endif
41 }
42 
43 ReturnVal<JsValue> ToJsObject(double value) {
44 #ifdef USING_V8
45  return v8::NumberObject::New(GetIsolate(), value);
46 #elif defined(USING_JSC)
47  LocalVar<JsValue> value_js = ToJsValue(value);
48  JSValueRef arg = value_js;
49  return CreateNativeObject("Number", &arg, 1);
50 #endif
51 }
52 
53 ReturnVal<JsValue> ToJsObject(const std::string& value) {
54 #ifdef USING_V8
55  return v8::StringObject::New(GetIsolate(), JsStringFromUtf8(value));
56 #elif defined(USING_JSC)
57  LocalVar<JsValue> value_js = ToJsValue(value);
58  JSValueRef arg = value_js;
59  return CreateNativeObject("String", &arg, 1);
60 #endif
61 }
62 
63 
64 ExceptionOr<void> StoreValue(Handle<JsValue> input, proto::Value* output,
65  std::vector<ReturnVal<JsValue>>* memory);
66 ReturnVal<JsValue> InternalFromStored(const proto::Value& item);
67 
68 ExceptionOr<void> StoreObject(proto::ValueType kind, Handle<JsObject> object,
69  proto::Object* output,
70  std::vector<Handle<JsValue>>* memory) {
71  if (kind == proto::Array)
72  output->set_array_length(ArrayLength(object));
73  else
74  output->clear_array_length();
75 
76  output->clear_entries();
77  for (const std::string& property : GetMemberNames(object)) {
78  proto::Object::Entry* child = output->add_entries();
79 
80  // Call [[Get]], rethrowing any exception thrown.
81  LocalVar<JsValue> except;
82  LocalVar<JsValue> value = GetMemberRaw(object, property, &except);
83  if (!IsNullOrUndefined(except))
84  return JsError::Rethrow(except);
85 
86  child->set_key(property);
87  RETURN_IF_ERROR(StoreValue(value, child->mutable_value(), memory));
88  }
89  return {};
90 }
91 
92 ExceptionOr<void> StoreValue(Handle<JsValue> input, proto::Value* output,
93  std::vector<ReturnVal<JsValue>>* memory) {
94  const proto::ValueType kind = GetValueType(input);
95 
96  // Store objects we have seen and throw error if we see duplicates.
97  if (IsObject(input)) {
98  if (util::contains(*memory, input)) {
99  return JsError::DOMException(
101  "Duplicate copies of the same object are not supported.");
102  }
103  memory->push_back(input);
104  }
105 
106  output->Clear();
107  output->set_kind(kind);
108  switch (kind) {
109  case proto::Undefined:
110  case proto::Null:
111  break;
112  case proto::Boolean:
114  output->set_value_bool(BooleanFromValue(input));
115  break;
116  case proto::Number:
117  case proto::NumberObject:
118  output->set_value_number(NumberFromValue(input));
119  break;
120  case proto::String:
121  case proto::StringObject: {
122  std::string str = ConvertToString(input);
123  output->set_value_string(str.data(), str.size());
124  break;
125  }
126 
127  case proto::ArrayBuffer:
128  case proto::Int8Array:
129  case proto::Uint8Array:
131  case proto::Int16Array:
132  case proto::Uint16Array:
133  case proto::Int32Array:
134  case proto::Uint32Array:
135  case proto::Float32Array:
136  case proto::Float64Array:
137  case proto::DataView: {
138  ByteBuffer buffer;
139  CHECK(buffer.TryConvert(input));
140  output->set_value_bytes(buffer.data(), buffer.size());
141  break;
142  }
143 
144  case proto::Array:
145  case proto::OtherObject: {
146  // This must be either an anonymous object, an array, or a wrapper object.
147  LocalVar<JsObject> object = UnsafeJsCast<JsObject>(input);
148  if (kind != proto::Array && IsBuiltInObject(object)) {
150  }
151 
152  // Arrays and objects are treated the same.
153  proto::Object* output_object = output->mutable_value_object();
154  return StoreObject(kind, object, output_object, memory);
155  }
156  case proto::Function:
157  default:
159  }
160 
161  return {};
162 }
163 
164 
165 ReturnVal<JsValue> FromStoredObject(const proto::Object& object) {
166  LocalVar<JsObject> ret;
167  if (object.has_array_length())
168  ret = CreateArray(object.array_length());
169  else
170  ret = CreateObject();
171 
172  for (const proto::Object::Entry& entry : object.entries()) {
173  LocalVar<JsValue> value = InternalFromStored(entry.value());
174  SetMemberRaw(ret, entry.key(), value);
175  }
176 
177  return RawToJsValue(ret);
178 }
179 
180 ReturnVal<JsValue> InternalFromStored(const proto::Value& item) {
181  DCHECK(item.IsInitialized());
182  switch (item.kind()) {
183  case proto::Undefined:
184  return JsUndefined();
185  case proto::Null:
186  return JsNull();
187  case proto::Boolean:
188  DCHECK(item.has_value_bool());
189  return ToJsValue(item.value_bool());
190  case proto::Number:
191  DCHECK(item.has_value_number());
192  return ToJsValue(item.value_number());
193  case proto::String:
194  DCHECK(item.has_value_string());
195  return ToJsValue(item.value_string());
196 
198  DCHECK(item.has_value_bool());
199  return ToJsObject(item.value_bool());
200  case proto::NumberObject:
201  DCHECK(item.has_value_number());
202  return ToJsObject(item.value_number());
203  case proto::StringObject:
204  DCHECK(item.has_value_string());
205  return ToJsObject(item.value_string());
206 
207  case proto::ArrayBuffer:
208  case proto::Int8Array:
209  case proto::Uint8Array:
211  case proto::Int16Array:
212  case proto::Uint16Array:
213  case proto::Int32Array:
214  case proto::Uint32Array:
215  case proto::Float32Array:
216  case proto::Float64Array:
217  case proto::DataView: {
218  DCHECK(item.has_value_bytes());
219  const std::string& str = item.value_bytes();
220  ByteBuffer temp(reinterpret_cast<const uint8_t*>(&str[0]), str.size());
221  return temp.ToJsValue(item.kind());
222  }
223  case proto::Array:
224  case proto::OtherObject:
225  return FromStoredObject(item.value_object());
226  default:
227  LOG(FATAL) << "Invalid stored value " << item.kind();
228  }
229 }
230 
231 } // namespace
232 
234  std::vector<ReturnVal<JsValue>> seen;
235  return StoreValue(input.ToJsValue(), result, &seen);
236 }
237 
239  Any ret;
240  CHECK(ret.TryConvert(InternalFromStored(value)));
241  return ret;
242 }
243 
244 } // namespace idb
245 } // namespace js
246 } // namespace shaka
Any LoadFromProto(const proto::Value &value)
Definition: idb_utils.cc:238
Definition: any.h:31
ExceptionOr< void > StoreInProto(Any input, proto::Value *result)
Definition: idb_utils.cc:233
ReturnVal< JsObject > CreateObject()
Definition: js_wrappers.cc:296
ReturnVal< JsValue > JsUndefined()
Definition: js_wrappers.cc:284
bool contains(const std::vector< T > &vec, U &&elem)
Definition: utils.h:87
bool IsObject(Handle< JsValue > value)
Definition: js_wrappers.cc:315
static JsError Rethrow(Handle< JsValue > error)
Definition: js_error.cc:105
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
bool BooleanFromValue(Handle< JsValue > value)
Definition: js_wrappers.cc:394
ReturnVal< JsObject > CreateArray(size_t length)
Definition: js_wrappers.cc:292
ReturnVal< JsValue > ToJsValue(T &&source)
Definition: convert_js.h:381
ReturnVal< JsValue > RawToJsValue(Handle< T > source)
Definition: js_wrappers.h:405
JSValueRef CreateNativeObject(const std::string &name, JSValueRef *args, size_t argc)
Definition: jsc_utils.cc:40
#define RETURN_IF_ERROR(code)
Definition: sqlite.cc:31
proto::ValueType GetValueType(Handle< JsValue > value)
Definition: js_wrappers.cc:329
double NumberFromValue(Handle< JsValue > value)
Definition: js_wrappers.cc:385
Object_Entry Entry
Definition: database.pb.h:362
void SetMemberRaw(Handle< JsObject > object, const std::string &name, Handle< JsValue > value)
Definition: js_wrappers.cc:147
std::string ConvertToString(Handle< JsValue > value)
Definition: js_wrappers.cc:203
static JsError DOMException(ExceptionCode code)
Definition: js_error.cc:115
ReturnVal< JsValue > ToJsValue() const override
Definition: any.cc:56
size_t ArrayLength(Handle< JsObject > value)
Definition: js_wrappers.h:418
ReturnVal< JsString > JsStringFromUtf8(const std::string &str)
Definition: js_wrappers.cc:266
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
bool TryConvert(Handle< JsValue > value) override
Definition: any.cc:50
bool IsBuiltInObject(Handle< JsObject > object)
Definition: js_wrappers.cc:319