blob: c4ed731b21015745d6c25cb955921e5deb06962e [file] [log] [blame]
David Ghandehari60170302017-03-10 21:18:13 -08001// Copyright 2016 Google Inc. All Rights Reserved.
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// http://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.
David Ghandehari9fd10662017-02-01 17:59:14 -080014#include "cobalt/script/mozjs-45/wrapper_factory.h"
Andrew Topc2b40892017-01-19 14:03:49 -080015
16#include <utility>
17
18#include "base/lazy_instance.h"
David Ghandehari9fd10662017-02-01 17:59:14 -080019#include "cobalt/script/mozjs-45/mozjs_wrapper_handle.h"
20#include "cobalt/script/mozjs-45/wrapper_private.h"
21#include "third_party/mozjs-45/js/public/Proxy.h"
Andrew Topc2b40892017-01-19 14:03:49 -080022
23namespace cobalt {
24namespace script {
25namespace mozjs {
26
27void WrapperFactory::RegisterWrappableType(
28 base::TypeId wrappable_type, const CreateWrapperFunction& create_function,
29 const PrototypeClassFunction& class_function) {
30 std::pair<WrappableTypeFunctionsHashMap::iterator, bool> pib =
31 wrappable_type_functions_.insert(std::make_pair(
32 wrappable_type,
33 WrappableTypeFunctions(create_function, class_function)));
34 DCHECK(pib.second)
35 << "RegisterWrappableType registered for type more than once.";
36}
37
38JSObject* WrapperFactory::GetWrapperProxy(
39 const scoped_refptr<Wrappable>& wrappable) const {
40 if (!wrappable) {
41 return NULL;
42 }
43
44 JS::RootedObject wrapper_proxy(
45 context_,
46 MozjsWrapperHandle::GetObjectProxy(GetCachedWrapper(wrappable.get())));
47 if (!wrapper_proxy) {
48 scoped_ptr<Wrappable::WeakWrapperHandle> object_handle =
49 CreateWrapper(wrappable);
50 SetCachedWrapper(wrappable.get(), object_handle.Pass());
51 wrapper_proxy =
52 MozjsWrapperHandle::GetObjectProxy(GetCachedWrapper(wrappable.get()));
53 }
54 DCHECK(wrapper_proxy);
55 DCHECK(js::IsProxy(wrapper_proxy));
56 return wrapper_proxy;
57}
58
59bool WrapperFactory::IsWrapper(JS::HandleObject wrapper) const {
60 return JS_GetPrivate(wrapper) != NULL;
61}
62
63scoped_ptr<Wrappable::WeakWrapperHandle> WrapperFactory::CreateWrapper(
64 const scoped_refptr<Wrappable>& wrappable) const {
65 WrappableTypeFunctionsHashMap::const_iterator it =
66 wrappable_type_functions_.find(wrappable->GetWrappableType());
67 if (it == wrappable_type_functions_.end()) {
68 NOTREACHED();
69 return scoped_ptr<Wrappable::WeakWrapperHandle>();
70 }
71 JS::RootedObject new_proxy(
72 context_, it->second.create_wrapper.Run(context_, wrappable));
73 WrapperPrivate* wrapper_private =
74 WrapperPrivate::GetFromProxyObject(context_, new_proxy);
75 DCHECK(wrapper_private);
76 return make_scoped_ptr<Wrappable::WeakWrapperHandle>(
77 new MozjsWrapperHandle(wrapper_private));
78}
79
80bool WrapperFactory::DoesObjectImplementInterface(JS::HandleObject object,
81 base::TypeId type_id) const {
82 // If the object doesn't have a wrapper private which means it is not a
83 // platform object, so the object doesn't implement the interface.
84 if (!WrapperPrivate::HasWrapperPrivate(context_, object)) {
85 return false;
86 }
87
88 WrappableTypeFunctionsHashMap::const_iterator it =
89 wrappable_type_functions_.find(type_id);
90 if (it == wrappable_type_functions_.end()) {
91 NOTREACHED();
92 return false;
93 }
94 const JSClass* proto_class = it->second.prototype_class.Run(context_);
95 JS::RootedObject object_proto_object(context_);
David Ghandehari9fd10662017-02-01 17:59:14 -080096 bool success = JS_GetPrototype(context_, object, &object_proto_object);
Andrew Topc2b40892017-01-19 14:03:49 -080097 bool equality = false;
98 while (!equality && success && object_proto_object) {
99 // Get the class of the prototype.
David Ghandehari9fd10662017-02-01 17:59:14 -0800100 const JSClass* object_proto_class = JS_GetClass(object_proto_object);
Andrew Topc2b40892017-01-19 14:03:49 -0800101 equality = (object_proto_class == proto_class);
102 // Get the prototype of the previous prototype.
David Ghandehari9fd10662017-02-01 17:59:14 -0800103 success =
104 JS_GetPrototype(context_, object_proto_object, &object_proto_object);
Andrew Topc2b40892017-01-19 14:03:49 -0800105 }
106 return equality;
107}
108} // namespace mozjs
109} // namespace script
110} // namespace cobalt