Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Delta Between Two Patch Sets: src/JsValue.cpp

Issue 29361562: Issue 3594 - remove circular references JsEngine-JsValue-JsEngine (Closed)
Left Patch Set: Created Nov. 3, 2016, 11:26 a.m.
Right Patch Set: temporary workaround for race condition Created Dec. 1, 2016, 10:26 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « src/JsContext.cpp ('k') | src/Notification.cpp » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 /* 1 /*
2 * This file is part of Adblock Plus <https://adblockplus.org/>, 2 * This file is part of Adblock Plus <https://adblockplus.org/>,
3 * Copyright (C) 2006-2016 Eyeo GmbH 3 * Copyright (C) 2006-2016 Eyeo GmbH
4 * 4 *
5 * Adblock Plus is free software: you can redistribute it and/or modify 5 * Adblock Plus is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as 6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
8 * 8 *
9 * Adblock Plus is distributed in the hope that it will be useful, 9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details. 12 * GNU General Public License for more details.
13 * 13 *
14 * You should have received a copy of the GNU General Public License 14 * You should have received a copy of the GNU General Public License
15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. 15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
16 */ 16 */
17 17
18 #include <vector> 18 #include <vector>
19 #include <AdblockPlus.h> 19 #include <AdblockPlus.h>
20 20
21 #include "JsContext.h" 21 #include "JsContext.h"
22 #include "JsError.h" 22 #include "JsError.h"
23 #include "Utils.h" 23 #include "Utils.h"
24 24
25 AdblockPlus::JsValue::JsValue(const std::weak_ptr<AdblockPlus::JsEngine>& jsEngi ne, 25 AdblockPlus::JsValue::JsValue(const std::weak_ptr<AdblockPlus::JsEngine>& jsEngi ne,
26 v8::Handle<v8::Value> value) 26 v8::Handle<v8::Value> value)
27 : m_jsEngine(jsEngine) 27 : jsEngine(jsEngine)
28 , m_value(new v8::Persistent<v8::Value>(Utils::lockJsEngine(jsEngine)->GetIsol ate(), value)) 28 , value(new v8::Persistent<v8::Value>(Utils::lockJsEngine(jsEngine)->GetIsolat e(), value))
29 { 29 {
30 } 30 }
31 31
32 AdblockPlus::JsValue::JsValue(AdblockPlus::JsValue&& src) 32 AdblockPlus::JsValue::JsValue(AdblockPlus::JsValue&& src)
33 : m_jsEngine(move(src.m_jsEngine)), 33 : jsEngine(std::move(src.jsEngine)),
34 m_value(std::move(src.m_value)) 34 value(std::move(src.value))
35 { 35 {
36 } 36 }
37 37
38 AdblockPlus::JsValue::~JsValue() 38 AdblockPlus::JsValue::~JsValue()
39 { 39 {
40 try 40 try
41 { 41 {
42 JsContext context(m_jsEngine); 42 JsContext context(jsEngine);
sergei 2016/12/01 22:24:37 Although I have not seen a crash on practice there
43 if (m_value) 43 if (value)
44 { 44 {
45 m_value->Dispose(); 45 value->Dispose();
46 m_value.reset(); 46 value.reset();
47 } 47 }
48 } 48 }
49 catch (const JsEngine::JsEngineNotAvailableException&) 49 catch (const JsEngine::JsEngineNotAvailableException&)
50 { 50 {
51 } 51 }
52 } 52 }
53 53
54 bool AdblockPlus::JsValue::IsUndefined() const 54 bool AdblockPlus::JsValue::IsUndefined() const
55 { 55 {
56 JsContext context(m_jsEngine); 56 JsContext context(jsEngine);
57 return UnwrapValue(context.jsEngine())->IsUndefined(); 57 return UnwrapValue(context.GetJsEngine())->IsUndefined();
58 } 58 }
59 59
60 bool AdblockPlus::JsValue::IsNull() const 60 bool AdblockPlus::JsValue::IsNull() const
61 { 61 {
62 JsContext context(m_jsEngine); 62 JsContext context(jsEngine);
63 return UnwrapValue(context.jsEngine())->IsNull(); 63 return UnwrapValue(context.GetJsEngine())->IsNull();
64 } 64 }
65 65
66 bool AdblockPlus::JsValue::IsString() const 66 bool AdblockPlus::JsValue::IsString() const
67 { 67 {
68 JsContext context(m_jsEngine); 68 JsContext context(jsEngine);
69 v8::Local<v8::Value> value = UnwrapValue(context.jsEngine()); 69 v8::Local<v8::Value> value = UnwrapValue(context.GetJsEngine());
70 return value->IsString() || value->IsStringObject(); 70 return value->IsString() || value->IsStringObject();
71 } 71 }
72 72
73 bool AdblockPlus::JsValue::IsNumber() const 73 bool AdblockPlus::JsValue::IsNumber() const
74 { 74 {
75 JsContext context(m_jsEngine); 75 JsContext context(jsEngine);
76 v8::Local<v8::Value> value = UnwrapValue(context.jsEngine()); 76 v8::Local<v8::Value> value = UnwrapValue(context.GetJsEngine());
77 return value->IsNumber() || value->IsNumberObject(); 77 return value->IsNumber() || value->IsNumberObject();
78 } 78 }
79 79
80 bool AdblockPlus::JsValue::IsBool() const 80 bool AdblockPlus::JsValue::IsBool() const
81 { 81 {
82 JsContext context(m_jsEngine); 82 JsContext context(jsEngine);
83 v8::Local<v8::Value> value = UnwrapValue(context.jsEngine()); 83 v8::Local<v8::Value> value = UnwrapValue(context.GetJsEngine());
84 return value->IsBoolean() || value->IsBooleanObject(); 84 return value->IsBoolean() || value->IsBooleanObject();
85 } 85 }
86 86
87 bool AdblockPlus::JsValue::IsObject() const 87 bool AdblockPlus::JsValue::IsObject() const
88 { 88 {
89 JsContext context(m_jsEngine); 89 JsContext context(jsEngine);
90 return UnwrapValue(context.jsEngine())->IsObject(); 90 return UnwrapValue(context.GetJsEngine())->IsObject();
91 } 91 }
92 92
93 bool AdblockPlus::JsValue::IsArray() const 93 bool AdblockPlus::JsValue::IsArray() const
94 { 94 {
95 JsContext context(m_jsEngine); 95 JsContext context(jsEngine);
96 return UnwrapValue(context.jsEngine())->IsArray(); 96 return UnwrapValue(context.GetJsEngine())->IsArray();
97 } 97 }
98 98
99 bool AdblockPlus::JsValue::IsFunction() const 99 bool AdblockPlus::JsValue::IsFunction() const
100 { 100 {
101 JsContext context(m_jsEngine); 101 JsContext context(jsEngine);
102 return UnwrapValue(context.jsEngine())->IsFunction(); 102 return UnwrapValue(context.GetJsEngine())->IsFunction();
103 } 103 }
104 104
105 std::string AdblockPlus::JsValue::AsString() const 105 std::string AdblockPlus::JsValue::AsString() const
106 { 106 {
107 JsContext context(m_jsEngine); 107 JsContext context(jsEngine);
108 return Utils::FromV8String(UnwrapValue(context.jsEngine())); 108 return Utils::FromV8String(UnwrapValue(context.GetJsEngine()));
109 } 109 }
110 110
111 int64_t AdblockPlus::JsValue::AsInt() const 111 int64_t AdblockPlus::JsValue::AsInt() const
112 { 112 {
113 JsContext context(m_jsEngine); 113 JsContext context(jsEngine);
114 return UnwrapValue(context.jsEngine())->IntegerValue(); 114 return UnwrapValue(context.GetJsEngine())->IntegerValue();
115 } 115 }
116 116
117 bool AdblockPlus::JsValue::AsBool() const 117 bool AdblockPlus::JsValue::AsBool() const
118 { 118 {
119 JsContext context(m_jsEngine); 119 JsContext context(jsEngine);
120 return UnwrapValue(context.jsEngine())->BooleanValue(); 120 return UnwrapValue(context.GetJsEngine())->BooleanValue();
121 } 121 }
122 122
123 AdblockPlus::JsValueList AdblockPlus::JsValue::AsList() const 123 AdblockPlus::JsValueList AdblockPlus::JsValue::AsList() const
124 { 124 {
125 JsContext context(m_jsEngine); 125 JsContext context(jsEngine);
126 if (!IsArray()) 126 if (!IsArray())
127 throw std::runtime_error("Cannot convert a non-array to list"); 127 throw std::runtime_error("Cannot convert a non-array to list");
128 128
129 JsValueList result; 129 JsValueList result;
130 v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(UnwrapValue(context.js Engine())); 130 v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(UnwrapValue(context.Ge tJsEngine()));
131 uint32_t length = array->Length(); 131 uint32_t length = array->Length();
132 for (uint32_t i = 0; i < length; i++) 132 for (uint32_t i = 0; i < length; i++)
133 { 133 {
134 v8::Local<v8::Value> item = array->Get(i); 134 v8::Local<v8::Value> item = array->Get(i);
135 result.push_back(JsValuePtr(new JsValue(m_jsEngine, item))); 135 result.push_back(JsValuePtr(new JsValue(jsEngine, item)));
136 } 136 }
137 return result; 137 return result;
138 } 138 }
139 139
140 std::vector<std::string> AdblockPlus::JsValue::GetOwnPropertyNames() const 140 std::vector<std::string> AdblockPlus::JsValue::GetOwnPropertyNames() const
141 { 141 {
142 JsContext context(m_jsEngine); 142 JsContext context(jsEngine);
143 if (!IsObject()) 143 if (!IsObject())
144 throw new std::runtime_error("Attempting to get propert list for a non-objec t"); 144 throw new std::runtime_error("Attempting to get propert list for a non-objec t");
145 145
146 v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(UnwrapValue(context .jsEngine())); 146 v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(UnwrapValue(context .GetJsEngine()));
147 JsValueList properties = JsValuePtr(new JsValue(m_jsEngine, object->GetOwnProp ertyNames()))->AsList(); 147 JsValueList properties = JsValuePtr(new JsValue(jsEngine, object->GetOwnProper tyNames()))->AsList();
148 std::vector<std::string> result; 148 std::vector<std::string> result;
149 for (JsValueList::iterator it = properties.begin(); it != properties.end(); ++ it) 149 for (JsValueList::iterator it = properties.begin(); it != properties.end(); ++ it)
150 result.push_back((*it)->AsString()); 150 result.push_back((*it)->AsString());
151 return result; 151 return result;
152 } 152 }
153 153
154 154
155 AdblockPlus::JsValuePtr AdblockPlus::JsValue::GetProperty(const std::string& nam e) const 155 AdblockPlus::JsValuePtr AdblockPlus::JsValue::GetProperty(const std::string& nam e) const
156 { 156 {
157 JsContext context(m_jsEngine); 157 JsContext context(jsEngine);
158 if (!IsObject()) 158 if (!IsObject())
159 throw new std::runtime_error("Attempting to get property of a non-object"); 159 throw new std::runtime_error("Attempting to get property of a non-object");
160 160
161 v8::Local<v8::String> property = Utils::ToV8String(context.jsEngine().GetIsola te(), name); 161 v8::Local<v8::String> property = Utils::ToV8String(context.GetJsEngine().GetIs olate(), name);
162 v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(UnwrapValue(context.js Engine())); 162 v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(UnwrapValue(context.Ge tJsEngine()));
163 return JsValuePtr(new JsValue(m_jsEngine, obj->Get(property))); 163 return JsValuePtr(new JsValue(jsEngine, obj->Get(property)));
164 } 164 }
165 165
166 void AdblockPlus::JsValue::SetProperty(const std::string& name, v8::Handle<v8::V alue> val) 166 void AdblockPlus::JsValue::SetProperty(const std::string& name, v8::Handle<v8::V alue> val)
167 { 167 {
168 JsContext context(m_jsEngine); 168 JsContext context(jsEngine);
169 if (!IsObject()) 169 if (!IsObject())
170 throw new std::runtime_error("Attempting to set property on a non-object"); 170 throw new std::runtime_error("Attempting to set property on a non-object");
171 171
172 v8::Local<v8::String> property = Utils::ToV8String(context.jsEngine().GetIsola te(), name); 172 v8::Local<v8::String> property = Utils::ToV8String(context.GetJsEngine().GetIs olate(), name);
173 v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(UnwrapValue(context.js Engine())); 173 v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(UnwrapValue(context.Ge tJsEngine()));
174 obj->Set(property, val); 174 obj->Set(property, val);
175 } 175 }
176 176
177 v8::Local<v8::Value> AdblockPlus::JsValue::UnwrapValue(JsEngine& jsEngine) const 177 v8::Local<v8::Value> AdblockPlus::JsValue::UnwrapValue(JsEngine& jsEngine) const
178 { 178 {
179 return v8::Local<v8::Value>::New(jsEngine.GetIsolate(), *m_value); 179 return v8::Local<v8::Value>::New(jsEngine.GetIsolate(), *value);
180 } 180 }
181 181
182 void AdblockPlus::JsValue::SetProperty(const std::string& name, const std::strin g& val) 182 void AdblockPlus::JsValue::SetProperty(const std::string& name, const std::strin g& val)
183 { 183 {
184 JsContext context(m_jsEngine); 184 JsContext context(jsEngine);
185 SetProperty(name, Utils::ToV8String(context.jsEngine().GetIsolate(), val)); 185 SetProperty(name, Utils::ToV8String(context.GetJsEngine().GetIsolate(), val));
186 } 186 }
187 187
188 void AdblockPlus::JsValue::SetProperty(const std::string& name, int64_t val) 188 void AdblockPlus::JsValue::SetProperty(const std::string& name, int64_t val)
189 { 189 {
190 JsContext context(m_jsEngine); 190 JsContext context(jsEngine);
191 SetProperty(name, v8::Number::New(context.jsEngine().GetIsolate(), val)); 191 SetProperty(name, v8::Number::New(context.GetJsEngine().GetIsolate(), val));
192 } 192 }
193 193
194 void AdblockPlus::JsValue::SetProperty(const std::string& name, const JsValuePtr & val) 194 void AdblockPlus::JsValue::SetProperty(const std::string& name, const JsValuePtr & val)
195 { 195 {
196 JsContext context(m_jsEngine); 196 JsContext context(jsEngine);
197 SetProperty(name, val->UnwrapValue(context.jsEngine())); 197 SetProperty(name, val->UnwrapValue(context.GetJsEngine()));
198 } 198 }
199 199
200 void AdblockPlus::JsValue::SetProperty(const std::string& name, bool val) 200 void AdblockPlus::JsValue::SetProperty(const std::string& name, bool val)
201 { 201 {
202 JsContext context(m_jsEngine); 202 JsContext context(jsEngine);
203 SetProperty(name, v8::Boolean::New(val)); 203 SetProperty(name, v8::Boolean::New(val));
204 } 204 }
205 205
206 std::string AdblockPlus::JsValue::GetClass() const 206 std::string AdblockPlus::JsValue::GetClass() const
207 { 207 {
208 JsContext context(m_jsEngine); 208 JsContext context(jsEngine);
209 if (!IsObject()) 209 if (!IsObject())
210 throw new std::runtime_error("Cannot get constructor of a non-object"); 210 throw new std::runtime_error("Cannot get constructor of a non-object");
211 211
212 v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(UnwrapValue(context.js Engine())); 212 v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(UnwrapValue(context.Ge tJsEngine()));
213 return Utils::FromV8String(obj->GetConstructorName()); 213 return Utils::FromV8String(obj->GetConstructorName());
214 } 214 }
215 215
216 AdblockPlus::JsValuePtr AdblockPlus::JsValue::Call(const JsValueList& params, Js ValuePtr thisPtr) const 216 AdblockPlus::JsValuePtr AdblockPlus::JsValue::Call(const JsValueList& params, Js ValuePtr thisPtr) const
217 { 217 {
218 JsContext context(m_jsEngine); 218 JsContext context(jsEngine);
219 if (!IsFunction()) 219 if (!IsFunction())
220 throw new std::runtime_error("Attempting to call a non-function"); 220 throw new std::runtime_error("Attempting to call a non-function");
221 221
222 if (!thisPtr) 222 if (!thisPtr)
223 { 223 {
224 v8::Local<v8::Context> localContext = v8::Local<v8::Context>::New( 224 v8::Local<v8::Context> localContext = v8::Local<v8::Context>::New(
225 context.jsEngine().GetIsolate(), *context.jsEngine().context); 225 context.GetJsEngine().GetIsolate(), *context.GetJsEngine().context);
226 thisPtr = JsValuePtr(new JsValue(m_jsEngine, localContext->Global())); 226 thisPtr = JsValuePtr(new JsValue(jsEngine, localContext->Global()));
227 } 227 }
228 if (!thisPtr->IsObject()) 228 if (!thisPtr->IsObject())
229 throw new std::runtime_error("`this` pointer has to be an object"); 229 throw new std::runtime_error("`this` pointer has to be an object");
230 v8::Local<v8::Object> thisObj = v8::Local<v8::Object>::Cast(thisPtr->UnwrapVal ue(context.jsEngine())); 230 v8::Local<v8::Object> thisObj = v8::Local<v8::Object>::Cast(thisPtr->UnwrapVal ue(context.GetJsEngine()));
231 231
232 std::vector<v8::Handle<v8::Value>> argv; 232 std::vector<v8::Handle<v8::Value>> argv;
233 for (JsValueList::const_iterator it = params.begin(); it != params.end(); ++it ) 233 for (JsValueList::const_iterator it = params.begin(); it != params.end(); ++it )
234 argv.push_back((*it)->UnwrapValue(context.jsEngine())); 234 argv.push_back((*it)->UnwrapValue(context.GetJsEngine()));
235 235
236 const v8::TryCatch tryCatch; 236 const v8::TryCatch tryCatch;
237 v8::Local<v8::Function> func = v8::Local<v8::Function>::Cast(UnwrapValue(conte xt.jsEngine())); 237 v8::Local<v8::Function> func = v8::Local<v8::Function>::Cast(UnwrapValue(conte xt.GetJsEngine()));
238 v8::Local<v8::Value> result = func->Call(thisObj, argv.size(), 238 v8::Local<v8::Value> result = func->Call(thisObj, argv.size(),
239 argv.size() ? &argv.front() : 0); 239 argv.size() ? &argv.front() : 0);
240 240
241 if (tryCatch.HasCaught()) 241 if (tryCatch.HasCaught())
242 throw JsError(tryCatch.Exception(), tryCatch.Message()); 242 throw JsError(tryCatch.Exception(), tryCatch.Message());
243 243
244 return JsValuePtr(new JsValue(m_jsEngine, result)); 244 return JsValuePtr(new JsValue(jsEngine, result));
245 } 245 }
246 246
247 AdblockPlus::JsValuePtr AdblockPlus::JsValue::Call(const JsValue& arg) const 247 AdblockPlus::JsValuePtr AdblockPlus::JsValue::Call(const JsValue& arg) const
248 { 248 {
249 JsContext context(m_jsEngine); 249 JsContext context(jsEngine);
250 JsValueList params; 250 JsValueList params;
251 params.push_back(JsValuePtr(new JsValue(arg.m_jsEngine, arg.UnwrapValue(contex t.jsEngine())))); 251 params.push_back(JsValuePtr(new JsValue(arg.jsEngine, arg.UnwrapValue(context. GetJsEngine()))));
252 return Call(params); 252 return Call(params);
253 } 253 }
LEFTRIGHT

Powered by Google App Engine
This is Rietveld