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

Side by Side Diff: src/JsValue.cpp

Issue 29361562: Issue 3594 - remove circular references JsEngine-JsValue-JsEngine (Closed)
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:
View unified diff | Download patch
« no previous file with comments | « src/JsContext.cpp ('k') | src/Notification.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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(AdblockPlus::JsEnginePtr jsEngine, 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 : jsEngine(jsEngine), 27 : jsEngine(jsEngine)
28 value(new v8::Persistent<v8::Value>(jsEngine->GetIsolate(), 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 : jsEngine(src.jsEngine), 33 : jsEngine(std::move(src.jsEngine)),
34 value(std::move(src.value)) 34 value(std::move(src.value))
35 { 35 {
36 } 36 }
37 37
38 AdblockPlus::JsValue::~JsValue() 38 AdblockPlus::JsValue::~JsValue()
39 { 39 {
40 if (value) 40 try
41 { 41 {
42 value->Dispose(); 42 JsContext context(jsEngine);
sergei 2016/12/01 22:24:37 Although I have not seen a crash on practice there
43 value.reset(); 43 if (value)
44 {
45 value->Dispose();
46 value.reset();
47 }
48 }
49 catch (const JsEngine::JsEngineNotAvailableException&)
50 {
44 } 51 }
45 } 52 }
46 53
47 bool AdblockPlus::JsValue::IsUndefined() const 54 bool AdblockPlus::JsValue::IsUndefined() const
48 { 55 {
49 const JsContext context(jsEngine); 56 JsContext context(jsEngine);
50 return UnwrapValue()->IsUndefined(); 57 return UnwrapValue(context.GetJsEngine())->IsUndefined();
51 } 58 }
52 59
53 bool AdblockPlus::JsValue::IsNull() const 60 bool AdblockPlus::JsValue::IsNull() const
54 { 61 {
55 const JsContext context(jsEngine); 62 JsContext context(jsEngine);
56 return UnwrapValue()->IsNull(); 63 return UnwrapValue(context.GetJsEngine())->IsNull();
57 } 64 }
58 65
59 bool AdblockPlus::JsValue::IsString() const 66 bool AdblockPlus::JsValue::IsString() const
60 { 67 {
61 const JsContext context(jsEngine); 68 JsContext context(jsEngine);
62 v8::Local<v8::Value> value = UnwrapValue(); 69 v8::Local<v8::Value> value = UnwrapValue(context.GetJsEngine());
63 return value->IsString() || value->IsStringObject(); 70 return value->IsString() || value->IsStringObject();
64 } 71 }
65 72
66 bool AdblockPlus::JsValue::IsNumber() const 73 bool AdblockPlus::JsValue::IsNumber() const
67 { 74 {
68 const JsContext context(jsEngine); 75 JsContext context(jsEngine);
69 v8::Local<v8::Value> value = UnwrapValue(); 76 v8::Local<v8::Value> value = UnwrapValue(context.GetJsEngine());
70 return value->IsNumber() || value->IsNumberObject(); 77 return value->IsNumber() || value->IsNumberObject();
71 } 78 }
72 79
73 bool AdblockPlus::JsValue::IsBool() const 80 bool AdblockPlus::JsValue::IsBool() const
74 { 81 {
75 const JsContext context(jsEngine); 82 JsContext context(jsEngine);
76 v8::Local<v8::Value> value = UnwrapValue(); 83 v8::Local<v8::Value> value = UnwrapValue(context.GetJsEngine());
77 return value->IsBoolean() || value->IsBooleanObject(); 84 return value->IsBoolean() || value->IsBooleanObject();
78 } 85 }
79 86
80 bool AdblockPlus::JsValue::IsObject() const 87 bool AdblockPlus::JsValue::IsObject() const
81 { 88 {
82 const JsContext context(jsEngine); 89 JsContext context(jsEngine);
83 return UnwrapValue()->IsObject(); 90 return UnwrapValue(context.GetJsEngine())->IsObject();
84 } 91 }
85 92
86 bool AdblockPlus::JsValue::IsArray() const 93 bool AdblockPlus::JsValue::IsArray() const
87 { 94 {
88 const JsContext context(jsEngine); 95 JsContext context(jsEngine);
89 return UnwrapValue()->IsArray(); 96 return UnwrapValue(context.GetJsEngine())->IsArray();
90 } 97 }
91 98
92 bool AdblockPlus::JsValue::IsFunction() const 99 bool AdblockPlus::JsValue::IsFunction() const
93 { 100 {
94 const JsContext context(jsEngine); 101 JsContext context(jsEngine);
95 return UnwrapValue()->IsFunction(); 102 return UnwrapValue(context.GetJsEngine())->IsFunction();
96 } 103 }
97 104
98 std::string AdblockPlus::JsValue::AsString() const 105 std::string AdblockPlus::JsValue::AsString() const
99 { 106 {
100 const JsContext context(jsEngine); 107 JsContext context(jsEngine);
101 return Utils::FromV8String(UnwrapValue()); 108 return Utils::FromV8String(UnwrapValue(context.GetJsEngine()));
102 } 109 }
103 110
104 int64_t AdblockPlus::JsValue::AsInt() const 111 int64_t AdblockPlus::JsValue::AsInt() const
105 { 112 {
106 const JsContext context(jsEngine); 113 JsContext context(jsEngine);
107 return UnwrapValue()->IntegerValue(); 114 return UnwrapValue(context.GetJsEngine())->IntegerValue();
108 } 115 }
109 116
110 bool AdblockPlus::JsValue::AsBool() const 117 bool AdblockPlus::JsValue::AsBool() const
111 { 118 {
112 const JsContext context(jsEngine); 119 JsContext context(jsEngine);
113 return UnwrapValue()->BooleanValue(); 120 return UnwrapValue(context.GetJsEngine())->BooleanValue();
114 } 121 }
115 122
116 AdblockPlus::JsValueList AdblockPlus::JsValue::AsList() const 123 AdblockPlus::JsValueList AdblockPlus::JsValue::AsList() const
117 { 124 {
125 JsContext context(jsEngine);
118 if (!IsArray()) 126 if (!IsArray())
119 throw std::runtime_error("Cannot convert a non-array to list"); 127 throw std::runtime_error("Cannot convert a non-array to list");
120 128
121 const JsContext context(jsEngine);
122 JsValueList result; 129 JsValueList result;
123 v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(UnwrapValue()); 130 v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(UnwrapValue(context.Ge tJsEngine()));
124 uint32_t length = array->Length(); 131 uint32_t length = array->Length();
125 for (uint32_t i = 0; i < length; i++) 132 for (uint32_t i = 0; i < length; i++)
126 { 133 {
127 v8::Local<v8::Value> item = array->Get(i); 134 v8::Local<v8::Value> item = array->Get(i);
128 result.push_back(JsValuePtr(new JsValue(jsEngine, item))); 135 result.push_back(JsValuePtr(new JsValue(jsEngine, item)));
129 } 136 }
130 return result; 137 return result;
131 } 138 }
132 139
133 std::vector<std::string> AdblockPlus::JsValue::GetOwnPropertyNames() const 140 std::vector<std::string> AdblockPlus::JsValue::GetOwnPropertyNames() const
134 { 141 {
142 JsContext context(jsEngine);
135 if (!IsObject()) 143 if (!IsObject())
136 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");
137 145
138 const JsContext context(jsEngine); 146 v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(UnwrapValue(context .GetJsEngine()));
139 v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(UnwrapValue());
140 JsValueList properties = JsValuePtr(new JsValue(jsEngine, object->GetOwnProper tyNames()))->AsList(); 147 JsValueList properties = JsValuePtr(new JsValue(jsEngine, object->GetOwnProper tyNames()))->AsList();
141 std::vector<std::string> result; 148 std::vector<std::string> result;
142 for (JsValueList::iterator it = properties.begin(); it != properties.end(); ++ it) 149 for (JsValueList::iterator it = properties.begin(); it != properties.end(); ++ it)
143 result.push_back((*it)->AsString()); 150 result.push_back((*it)->AsString());
144 return result; 151 return result;
145 } 152 }
146 153
147 154
148 AdblockPlus::JsValuePtr AdblockPlus::JsValue::GetProperty(const std::string& nam e) const 155 AdblockPlus::JsValuePtr AdblockPlus::JsValue::GetProperty(const std::string& nam e) const
149 { 156 {
157 JsContext context(jsEngine);
150 if (!IsObject()) 158 if (!IsObject())
151 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");
152 160
153 const JsContext context(jsEngine); 161 v8::Local<v8::String> property = Utils::ToV8String(context.GetJsEngine().GetIs olate(), name);
154 v8::Local<v8::String> property = Utils::ToV8String(jsEngine->GetIsolate(), nam e); 162 v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(UnwrapValue(context.Ge tJsEngine()));
155 v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(UnwrapValue());
156 return JsValuePtr(new JsValue(jsEngine, obj->Get(property))); 163 return JsValuePtr(new JsValue(jsEngine, obj->Get(property)));
157 } 164 }
158 165
159 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)
160 { 167 {
168 JsContext context(jsEngine);
161 if (!IsObject()) 169 if (!IsObject())
162 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");
163 171
164 v8::Local<v8::String> property = Utils::ToV8String(jsEngine->GetIsolate(), nam e); 172 v8::Local<v8::String> property = Utils::ToV8String(context.GetJsEngine().GetIs olate(), name);
165 v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(UnwrapValue()); 173 v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(UnwrapValue(context.Ge tJsEngine()));
166 obj->Set(property, val); 174 obj->Set(property, val);
167 } 175 }
168 176
169 v8::Local<v8::Value> AdblockPlus::JsValue::UnwrapValue() const 177 v8::Local<v8::Value> AdblockPlus::JsValue::UnwrapValue(JsEngine& jsEngine) const
170 { 178 {
171 return v8::Local<v8::Value>::New(jsEngine->GetIsolate(), *value); 179 return v8::Local<v8::Value>::New(jsEngine.GetIsolate(), *value);
172 } 180 }
173 181
174 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)
175 { 183 {
176 const JsContext context(jsEngine); 184 JsContext context(jsEngine);
177 SetProperty(name, Utils::ToV8String(jsEngine->GetIsolate(), val)); 185 SetProperty(name, Utils::ToV8String(context.GetJsEngine().GetIsolate(), val));
178 } 186 }
179 187
180 void AdblockPlus::JsValue::SetProperty(const std::string& name, int64_t val) 188 void AdblockPlus::JsValue::SetProperty(const std::string& name, int64_t val)
181 { 189 {
182 const JsContext context(jsEngine); 190 JsContext context(jsEngine);
183 SetProperty(name, v8::Number::New(jsEngine->GetIsolate(), val)); 191 SetProperty(name, v8::Number::New(context.GetJsEngine().GetIsolate(), val));
184 } 192 }
185 193
186 void AdblockPlus::JsValue::SetProperty(const std::string& name, const JsValuePtr & val) 194 void AdblockPlus::JsValue::SetProperty(const std::string& name, const JsValuePtr & val)
187 { 195 {
188 const JsContext context(jsEngine); 196 JsContext context(jsEngine);
189 SetProperty(name, val->UnwrapValue()); 197 SetProperty(name, val->UnwrapValue(context.GetJsEngine()));
190 } 198 }
191 199
192 void AdblockPlus::JsValue::SetProperty(const std::string& name, bool val) 200 void AdblockPlus::JsValue::SetProperty(const std::string& name, bool val)
193 { 201 {
194 const JsContext context(jsEngine); 202 JsContext context(jsEngine);
195 SetProperty(name, v8::Boolean::New(val)); 203 SetProperty(name, v8::Boolean::New(val));
196 } 204 }
197 205
198 std::string AdblockPlus::JsValue::GetClass() const 206 std::string AdblockPlus::JsValue::GetClass() const
199 { 207 {
208 JsContext context(jsEngine);
200 if (!IsObject()) 209 if (!IsObject())
201 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");
202 211
203 const JsContext context(jsEngine); 212 v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(UnwrapValue(context.Ge tJsEngine()));
204 v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(UnwrapValue());
205 return Utils::FromV8String(obj->GetConstructorName()); 213 return Utils::FromV8String(obj->GetConstructorName());
206 } 214 }
207 215
208 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
209 { 217 {
218 JsContext context(jsEngine);
210 if (!IsFunction()) 219 if (!IsFunction())
211 throw new std::runtime_error("Attempting to call a non-function"); 220 throw new std::runtime_error("Attempting to call a non-function");
212 221
213 const JsContext context(jsEngine);
214 if (!thisPtr) 222 if (!thisPtr)
215 { 223 {
216 v8::Local<v8::Context> localContext = v8::Local<v8::Context>::New( 224 v8::Local<v8::Context> localContext = v8::Local<v8::Context>::New(
217 jsEngine->GetIsolate(), *jsEngine->context); 225 context.GetJsEngine().GetIsolate(), *context.GetJsEngine().context);
218 thisPtr = JsValuePtr(new JsValue(jsEngine, localContext->Global())); 226 thisPtr = JsValuePtr(new JsValue(jsEngine, localContext->Global()));
219 } 227 }
220 if (!thisPtr->IsObject()) 228 if (!thisPtr->IsObject())
221 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");
222 v8::Local<v8::Object> thisObj = v8::Local<v8::Object>::Cast(thisPtr->UnwrapVal ue()); 230 v8::Local<v8::Object> thisObj = v8::Local<v8::Object>::Cast(thisPtr->UnwrapVal ue(context.GetJsEngine()));
223 231
224 std::vector<v8::Handle<v8::Value>> argv; 232 std::vector<v8::Handle<v8::Value>> argv;
225 for (JsValueList::const_iterator it = params.begin(); it != params.end(); ++it ) 233 for (JsValueList::const_iterator it = params.begin(); it != params.end(); ++it )
226 argv.push_back((*it)->UnwrapValue()); 234 argv.push_back((*it)->UnwrapValue(context.GetJsEngine()));
227 235
228 const v8::TryCatch tryCatch; 236 const v8::TryCatch tryCatch;
229 v8::Local<v8::Function> func = v8::Local<v8::Function>::Cast(UnwrapValue()); 237 v8::Local<v8::Function> func = v8::Local<v8::Function>::Cast(UnwrapValue(conte xt.GetJsEngine()));
230 v8::Local<v8::Value> result = func->Call(thisObj, argv.size(), 238 v8::Local<v8::Value> result = func->Call(thisObj, argv.size(),
231 argv.size() ? &argv.front() : 0); 239 argv.size() ? &argv.front() : 0);
232 240
233 if (tryCatch.HasCaught()) 241 if (tryCatch.HasCaught())
234 throw JsError(tryCatch.Exception(), tryCatch.Message()); 242 throw JsError(tryCatch.Exception(), tryCatch.Message());
235 243
236 return JsValuePtr(new JsValue(jsEngine, result)); 244 return JsValuePtr(new JsValue(jsEngine, result));
237 } 245 }
238 246
239 AdblockPlus::JsValuePtr AdblockPlus::JsValue::Call(const JsValue& arg) const 247 AdblockPlus::JsValuePtr AdblockPlus::JsValue::Call(const JsValue& arg) const
240 { 248 {
241 const JsContext context(jsEngine); 249 JsContext context(jsEngine);
242 JsValueList params; 250 JsValueList params;
243 params.push_back(JsValuePtr(new JsValue(arg.jsEngine, arg.UnwrapValue()))); 251 params.push_back(JsValuePtr(new JsValue(arg.jsEngine, arg.UnwrapValue(context. GetJsEngine()))));
244 return Call(params); 252 return Call(params);
245 } 253 }
OLDNEW
« no previous file with comments | « src/JsContext.cpp ('k') | src/Notification.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld