OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "platform/v8_inspector/V8Console.h" | |
6 | |
7 #include "platform/inspector_protocol/String16.h" | |
8 #include "platform/v8_inspector/V8DebuggerImpl.h" | |
9 #include "platform/v8_inspector/V8ProfilerAgentImpl.h" | |
10 #include "platform/v8_inspector/V8StackTraceImpl.h" | |
11 #include "platform/v8_inspector/V8StringUtil.h" | |
12 #include "platform/v8_inspector/public/ConsoleAPITypes.h" | |
13 #include "platform/v8_inspector/public/ConsoleTypes.h" | |
14 #include "platform/v8_inspector/public/V8DebuggerClient.h" | |
15 | |
16 namespace blink { | |
17 | |
18 namespace { | |
19 | |
20 v8::MaybeLocal<v8::Object> consoleObjectFromInfo(const v8::FunctionCallbackInfo< v8::Value>& info) | |
21 { | |
22 if (info.Data().IsEmpty() || !info.Data()->IsObject()) | |
23 return v8::MaybeLocal<v8::Object>(); | |
24 return info.Data().As<v8::Object>(); | |
25 } | |
26 | |
27 v8::Local<v8::Private> debuggerPrivateKey(v8::Isolate* isolate) | |
28 { | |
29 return v8::Private::ForApi(isolate, toV8StringInternalized(isolate, "V8Conso le#V8DebuggerImpl")); | |
30 } | |
31 | |
32 V8DebuggerImpl* debuggerFromConsoleObject(v8::Isolate* isolate, v8::Local<v8::Ob ject> console) | |
33 { | |
34 v8::Local<v8::Value> value; | |
35 if (!console->GetPrivate(isolate->GetCurrentContext(), debuggerPrivateKey(is olate)).ToLocal(&value)) | |
36 return nullptr; | |
37 ASSERT(!value->IsExternal()); | |
38 return static_cast<V8DebuggerImpl*>(value.As<v8::External>()->Value()); | |
39 } | |
40 | |
41 V8DebuggerClient* clientFromConsoleObject(v8::Isolate* isolate, v8::Local<v8::Ob ject> console) | |
42 { | |
43 V8DebuggerImpl* debugger = debuggerFromConsoleObject(isolate, console); | |
44 return debugger ? debugger->client() : nullptr; | |
45 } | |
46 | |
47 void internalAddMessage(MessageType type, MessageLevel level, const v8::Function CallbackInfo<v8::Value>& info, bool allowEmptyArguments, int skipArgumentCount) | |
48 { | |
49 if (!allowEmptyArguments && !info.Length()) | |
50 return; | |
51 v8::Local<v8::Object> consoleObject; | |
52 if (!consoleObjectFromInfo(info).ToLocal(&consoleObject)) | |
53 return; | |
54 v8::Isolate* isolate = info.GetIsolate(); | |
55 V8DebuggerClient* client = clientFromConsoleObject(isolate, consoleObject); | |
56 if (!client) | |
57 return; | |
58 client->reportMessageToConsole(isolate->GetCurrentContext(), type, level, in fo, skipArgumentCount); | |
59 } | |
60 | |
61 void createBoundFunctionProperty(v8::Local<v8::Context> context, v8::Local<v8::O bject> obj, v8::Local<v8::Object> prototype, const char* name, v8::FunctionCallb ack callback) | |
62 { | |
63 v8::Local<v8::String> funcName = toV8StringInternalized(context->GetIsolate( ), name); | |
64 v8::Local<v8::Function> func; | |
65 if (!v8::Function::New(context, callback, obj).ToLocal(&func)) | |
66 return; | |
67 func->SetName(funcName); | |
68 if (!prototype->Set(context, funcName, func).FromMaybe(false)) | |
69 return; | |
70 } | |
71 | |
72 v8::MaybeLocal<v8::Map> privateMapFromConsoleObject(v8::Isolate* isolate, v8::Lo cal<v8::Object> console, const char* name) | |
73 { | |
74 v8::Local<v8::Context> context = isolate->GetCurrentContext(); | |
75 | |
76 v8::Local<v8::Private> privateKey = v8::Private::ForApi(isolate, toV8StringI nternalized(isolate, name)); | |
77 v8::Local<v8::Value> mapValue; | |
78 if (!console->GetPrivate(context, privateKey).ToLocal(&mapValue)) | |
79 return v8::MaybeLocal<v8::Map>(); | |
80 if (mapValue->IsUndefined()) { | |
81 v8::Local<v8::Map> map = v8::Map::New(isolate); | |
82 if (!console->SetPrivate(context, privateKey, map).FromMaybe(false)) | |
83 return v8::MaybeLocal<v8::Map>(); | |
84 return map; | |
85 } | |
86 return mapValue->IsMap() ? mapValue.As<v8::Map>() : v8::MaybeLocal<v8::Map>( ); | |
87 } | |
88 | |
89 v8::MaybeLocal<v8::Object> createObjectWithClassName(v8::Isolate* isolate, v8::L ocal<v8::Context> context, const char* className) | |
90 { | |
91 v8::Local<v8::FunctionTemplate> functionTemplate = v8::FunctionTemplate::New (isolate); | |
dgozman
2016/04/12 03:32:16
Store it per-isolate in V8DebuggerImpl instance. F
kozy
2016/04/12 21:58:32
Done.
| |
92 functionTemplate->SetClassName(toV8StringInternalized(isolate, className)); | |
93 v8::Local<v8::Function> constructor; | |
94 if (!functionTemplate->GetFunction(context).ToLocal(&constructor)) | |
95 return v8::MaybeLocal<v8::Object>(); | |
96 return constructor->NewInstance(context, 0, nullptr); | |
97 } | |
98 | |
99 } // namespace | |
100 | |
101 void V8Console::debugCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | |
102 { | |
103 internalAddMessage(LogMessageType, DebugMessageLevel, info, false, 0); | |
104 } | |
105 | |
106 void V8Console::errorCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | |
107 { | |
108 internalAddMessage(LogMessageType, ErrorMessageLevel, info, false, 0); | |
109 } | |
110 | |
111 void V8Console::infoCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | |
112 { | |
113 internalAddMessage(LogMessageType, InfoMessageLevel, info, false, 0); | |
114 } | |
115 | |
116 void V8Console::logCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | |
117 { | |
118 internalAddMessage(LogMessageType, LogMessageLevel, info, false, 0); | |
119 } | |
120 | |
121 void V8Console::warnCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | |
122 { | |
123 internalAddMessage(LogMessageType, WarningMessageLevel, info, false, 0); | |
124 } | |
125 | |
126 void V8Console::dirCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | |
127 { | |
128 internalAddMessage(DirMessageType, LogMessageLevel, info, false, 0); | |
129 } | |
130 | |
131 void V8Console::dirxmlCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | |
132 { | |
133 internalAddMessage(DirXMLMessageType, LogMessageLevel, info, false, 0); | |
134 } | |
135 | |
136 void V8Console::tableCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | |
137 { | |
138 internalAddMessage(TableMessageType, LogMessageLevel, info, false, 0); | |
139 } | |
140 | |
141 void V8Console::traceCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | |
142 { | |
143 internalAddMessage(TraceMessageType, LogMessageLevel, info, true, 0); | |
144 } | |
145 | |
146 void V8Console::groupCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | |
147 { | |
148 internalAddMessage(StartGroupMessageType, LogMessageLevel, info, true, 0); | |
149 } | |
150 | |
151 void V8Console::groupCollapsedCallback(const v8::FunctionCallbackInfo<v8::Value> & info) | |
152 { | |
153 internalAddMessage(StartGroupCollapsedMessageType, LogMessageLevel, info, tr ue, 0); | |
154 } | |
155 | |
156 void V8Console::groupEndCallback(const v8::FunctionCallbackInfo<v8::Value>& info ) | |
157 { | |
158 internalAddMessage(EndGroupMessageType, LogMessageLevel, info, true, 0); | |
159 } | |
160 | |
161 void V8Console::clearCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | |
162 { | |
163 internalAddMessage(ClearMessageType, LogMessageLevel, info, true, 0); | |
164 } | |
165 | |
166 void V8Console::countCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | |
167 { | |
168 v8::Isolate* isolate = info.GetIsolate(); | |
169 v8::Local<v8::Context> context = isolate->GetCurrentContext(); | |
170 | |
171 v8::Local<v8::Object> consoleObject; | |
172 if (!consoleObjectFromInfo(info).ToLocal(&consoleObject)) | |
173 return; | |
174 V8DebuggerClient* client = clientFromConsoleObject(isolate, consoleObject); | |
175 if (!client) | |
176 return; | |
177 | |
178 // Follow Firebug's behavior of counting with null and undefined title in | |
179 // the same bucket as no argument | |
180 String16 title; | |
181 if (info.Length() > 0 && (!info[0]->IsNull() || !info[0]->IsUndefined())) { | |
182 v8::Local<v8::String> titleValue; | |
183 if (info[0]->IsObject()) { | |
184 if (!info[0].As<v8::Object>()->ObjectProtoToString(context).ToLocal( &titleValue)) | |
185 return; | |
186 } else { | |
187 if (!info[0]->ToString(context).ToLocal(&titleValue)) | |
188 return; | |
189 } | |
190 title = toProtocolString(titleValue); | |
191 } | |
192 | |
193 String16 identifier; | |
194 if (title.isEmpty()) { | |
195 OwnPtr<V8StackTraceImpl> stackTrace = V8StackTraceImpl::capture(nullptr, 1); | |
196 if (stackTrace) | |
197 identifier = stackTrace->topSourceURL() + ":" + String16::number(sta ckTrace->topLineNumber()); | |
198 } else { | |
199 identifier = title + "@"; | |
200 } | |
201 | |
202 v8::Local<v8::Map> countMap; | |
203 if (!privateMapFromConsoleObject(info.GetIsolate(), consoleObject, "V8Consol e#countMap").ToLocal(&countMap)) | |
204 return; | |
205 | |
206 v8::Local<v8::String> key = toV8String(isolate, identifier); | |
207 int64_t count = 0; | |
208 if (countMap->Has(context, key).FromMaybe(false)) { | |
209 v8::Local<v8::Value> countValue; | |
210 if (!countMap->Get(context, key).ToLocal(&countValue)) | |
211 return; | |
212 count = countValue.As<v8::Integer>()->Value(); | |
213 } | |
214 ++count; | |
215 if (!countMap->Set(context, key, v8::Integer::New(isolate, count)).ToLocal(& countMap)) | |
216 return; | |
217 String16 message = title + ": " + String16::number(count); | |
218 client->reportMessageToConsole(context, CountMessageType, DebugMessageLevel, message); | |
dgozman
2016/04/12 03:32:15
Use internalAddMessage instead?
kozy
2016/04/12 21:58:32
Done.
| |
219 } | |
220 | |
221 void V8Console::assertCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | |
222 { | |
223 bool condition = false; | |
224 if (info.Length() > 0) { | |
225 if (info[0]->IsBoolean()) | |
226 condition = info[0].As<v8::Boolean>()->Value(); | |
227 else | |
228 condition = info[0]->BooleanValue(info.GetIsolate()->GetCurrentConte xt()).FromMaybe(false); | |
229 } | |
230 if (condition) | |
231 return; | |
232 internalAddMessage(AssertMessageType, ErrorMessageLevel, info, true, 1); | |
233 } | |
234 | |
235 void V8Console::markTimelineCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | |
236 { | |
237 if (!info.Data()->IsObject()) | |
238 return; | |
239 v8::Local<v8::Object> consoleObject = info.Data().As<v8::Object>(); | |
240 V8DebuggerClient* client = clientFromConsoleObject(info.GetIsolate(), consol eObject); | |
241 if (!client) | |
242 return; | |
243 client->reportMessageToConsole(info.GetIsolate()->GetCurrentContext(), LogMe ssageType, WarningMessageLevel, "'console.markTimeline' is deprecated. Please us e 'console.timeStamp' instead."); | |
dgozman
2016/04/12 03:32:15
Use internalAddMessage instead?
kozy
2016/04/12 21:58:32
Done.
| |
244 } | |
245 | |
246 void V8Console::profileCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | |
247 { | |
248 v8::Local<v8::Object> consoleObject; | |
249 if (!consoleObjectFromInfo(info).ToLocal(&consoleObject)) | |
250 return; | |
251 V8DebuggerImpl* debugger = debuggerFromConsoleObject(info.GetIsolate(), cons oleObject); | |
252 if (!debugger) | |
253 return; | |
254 V8ProfilerAgentImpl* profileAgent = debugger->findEnabledProfilerAgent(info. GetIsolate()->GetCurrentContext()); | |
255 if (!profileAgent) | |
256 return; | |
257 String16 title = info.Length() > 0 ? toProtocolStringWithTypeCheck(info[0]) : String16(); | |
258 profileAgent->consoleProfile(title); | |
259 } | |
260 | |
261 void V8Console::profileEndCallback(const v8::FunctionCallbackInfo<v8::Value>& in fo) | |
262 { | |
263 v8::Local<v8::Object> consoleObject; | |
264 if (!consoleObjectFromInfo(info).ToLocal(&consoleObject)) | |
265 return; | |
266 V8DebuggerImpl* debugger = debuggerFromConsoleObject(info.GetIsolate(), cons oleObject); | |
267 if (!debugger) | |
268 return; | |
269 V8ProfilerAgentImpl* profileAgent = debugger->findEnabledProfilerAgent(info. GetIsolate()->GetCurrentContext()); | |
270 if (!profileAgent) | |
271 return; | |
272 String16 title = info.Length() > 0 ? toProtocolStringWithTypeCheck(info[0]) : String16(); | |
273 profileAgent->consoleProfileEnd(title); | |
dgozman
2016/04/12 03:32:16
I'd move as much code to helper methods as possibl
kozy
2016/04/12 21:58:32
Done.
| |
274 } | |
275 | |
276 void V8Console::timelineCallback(const v8::FunctionCallbackInfo<v8::Value>& info ) | |
277 { | |
278 v8::Local<v8::Object> consoleObject; | |
279 if (!consoleObjectFromInfo(info).ToLocal(&consoleObject)) | |
280 return; | |
281 V8DebuggerClient* client = clientFromConsoleObject(info.GetIsolate(), consol eObject); | |
282 if (!client) | |
283 return; | |
284 client->reportMessageToConsole(info.GetIsolate()->GetCurrentContext(), LogMe ssageType, WarningMessageLevel, "'console.timeline' is deprecated. Please use 'c onsole.time' instead."); | |
dgozman
2016/04/12 03:32:16
Use internalAddMessage instead?
kozy
2016/04/12 21:58:32
Done.
| |
285 } | |
286 | |
287 void V8Console::timelineEndCallback(const v8::FunctionCallbackInfo<v8::Value>& i nfo) | |
288 { | |
289 v8::Local<v8::Object> consoleObject; | |
290 if (!consoleObjectFromInfo(info).ToLocal(&consoleObject)) | |
291 return; | |
292 V8DebuggerClient* client = clientFromConsoleObject(info.GetIsolate(), consol eObject); | |
293 if (!client) | |
294 return; | |
295 client->reportMessageToConsole(info.GetIsolate()->GetCurrentContext(), LogMe ssageType, WarningMessageLevel, "'console.timelineEnd' is deprecated. Please use 'console.timeEnd' instead."); | |
dgozman
2016/04/12 03:32:15
Use internalAddMessage instead?
kozy
2016/04/12 21:58:32
Done.
| |
296 } | |
297 | |
298 void V8Console::timeCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | |
dgozman
2016/04/12 03:32:15
I'd go for more helpers here as well:
v8::Local<v
kozy
2016/04/12 21:58:32
Moved partially.
| |
299 { | |
300 v8::Isolate* isolate = info.GetIsolate(); | |
301 v8::Local<v8::Context> context = isolate->GetCurrentContext(); | |
302 v8::Local<v8::Object> consoleObject; | |
303 if (!consoleObjectFromInfo(info).ToLocal(&consoleObject)) | |
304 return; | |
305 V8DebuggerClient* client = clientFromConsoleObject(isolate, consoleObject); | |
306 if (!client) | |
307 return; | |
308 String16 protocolTitle = info.Length() > 0 ? toProtocolStringWithTypeCheck(i nfo[0]) : String16(); | |
309 client->consoleTime(isolate, protocolTitle); | |
310 | |
311 v8::Local<v8::Map> timeMap; | |
312 if (!privateMapFromConsoleObject(isolate, consoleObject, "V8Console#timeMap" ).ToLocal(&timeMap)) | |
313 return; | |
314 v8::Local<v8::String> title; | |
315 if (!info[0]->ToString(context).ToLocal(&title)) | |
316 return; | |
317 if (!timeMap->Set(context, title, v8::Number::New(isolate, client->currentTi meMS())).ToLocal(&timeMap)) | |
318 return; | |
319 } | |
320 | |
321 void V8Console::timeEndCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | |
322 { | |
323 v8::Isolate* isolate = info.GetIsolate(); | |
324 v8::Local<v8::Context> context = isolate->GetCurrentContext(); | |
325 v8::Local<v8::Object> consoleObject; | |
326 if (!consoleObjectFromInfo(info).ToLocal(&consoleObject)) | |
327 return; | |
328 V8DebuggerClient* client = clientFromConsoleObject(isolate, consoleObject); | |
dgozman
2016/04/12 03:32:15
I think we can replace many places with more reada
kozy
2016/04/12 21:58:32
Done.
| |
329 if (!client) | |
330 return; | |
331 String16 protocolTitle = info.Length() > 0 ? toProtocolStringWithTypeCheck(i nfo[0]) : String16(); | |
332 client->consoleTimeEnd(isolate, protocolTitle); | |
333 | |
334 v8::Local<v8::Map> timeMap; | |
335 if (!privateMapFromConsoleObject(isolate, consoleObject, "V8Console#timeMap" ).ToLocal(&timeMap)) | |
336 return; | |
337 v8::Local<v8::String> title; | |
338 if (!info[0]->ToString(context).ToLocal(&title)) | |
339 return; | |
340 v8::Local<v8::Value> timeValue; | |
341 if (!timeMap->Get(context, title).ToLocal(&timeValue) || !timeValue->IsNumbe r()) | |
342 return; | |
343 double elapsed = client->currentTimeMS() - timeValue.As<v8::Number>()->Value (); | |
344 String16 message = toProtocolString(title) + ": " + String16::fromDoubleFixe dPrecision(elapsed, 3) + "ms"; | |
345 client->reportMessageToConsole(info.GetIsolate()->GetCurrentContext(), TimeE ndMessageType, DebugMessageLevel, message); | |
346 } | |
347 | |
348 void V8Console::timeStampCallback(const v8::FunctionCallbackInfo<v8::Value>& inf o) | |
349 { | |
350 v8::Local<v8::Object> consoleObject; | |
351 if (!consoleObjectFromInfo(info).ToLocal(&consoleObject)) | |
352 return; | |
353 V8DebuggerClient* client = clientFromConsoleObject(info.GetIsolate(), consol eObject); | |
354 if (!client) | |
355 return; | |
356 String16 title = info.Length() > 0 ? toProtocolStringWithTypeCheck(info[0]) : String16(); | |
357 client->consoleTimeStamp(info.GetIsolate(), title); | |
358 } | |
359 | |
360 void V8Console::memoryGetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | |
361 { | |
362 v8::Local<v8::Object> consoleObject; | |
363 if (!consoleObjectFromInfo(info).ToLocal(&consoleObject)) | |
364 return; | |
365 V8DebuggerClient* client = clientFromConsoleObject(info.GetIsolate(), consol eObject); | |
366 if (!client) | |
367 return; | |
368 v8::Local<v8::Value> memoryValue; | |
369 if (!client->memoryInfo(info.GetIsolate(), info.GetIsolate()->GetCurrentCont ext(), info.Holder()).ToLocal(&memoryValue)) | |
370 return; | |
371 info.GetReturnValue().Set(memoryValue); | |
372 } | |
373 | |
374 void V8Console::memorySetterCallback(const v8::FunctionCallbackInfo<v8::Value>& info) | |
375 { | |
376 // We can't make the attribute readonly as it breaks existing code that reli es on being able to assign to console.memory in strict mode. Instead, the setter just ignores the passed value. http://crbug.com/468611 | |
377 } | |
378 | |
379 v8::MaybeLocal<v8::Object> V8Console::create(v8::Local<v8::Context> context, V8D ebuggerImpl* debugger, bool hasMemoryAttribute) | |
380 { | |
381 v8::Isolate* isolate = context->GetIsolate(); | |
382 | |
383 v8::Local<v8::Object> console; | |
384 if (!createObjectWithClassName(isolate, context, "Console").ToLocal(&console )) | |
385 return v8::MaybeLocal<v8::Object>(); | |
386 | |
387 v8::Local<v8::Object> prototype; | |
388 if (!createObjectWithClassName(isolate, context, "ConsolePrototype").ToLocal (&prototype)) | |
389 return v8::MaybeLocal<v8::Object>(); | |
390 | |
391 createBoundFunctionProperty(context, console, prototype, "debug", V8Console: :debugCallback); | |
392 createBoundFunctionProperty(context, console, prototype, "error", V8Console: :errorCallback); | |
393 createBoundFunctionProperty(context, console, prototype, "info", V8Console:: infoCallback); | |
394 createBoundFunctionProperty(context, console, prototype, "log", V8Console::l ogCallback); | |
395 createBoundFunctionProperty(context, console, prototype, "warn", V8Console:: warnCallback); | |
396 createBoundFunctionProperty(context, console, prototype, "dir", V8Console::d irCallback); | |
397 createBoundFunctionProperty(context, console, prototype, "dirxml", V8Console ::dirxmlCallback); | |
398 createBoundFunctionProperty(context, console, prototype, "table", V8Console: :tableCallback); | |
399 createBoundFunctionProperty(context, console, prototype, "trace", V8Console: :traceCallback); | |
400 createBoundFunctionProperty(context, console, prototype, "group", V8Console: :groupCallback); | |
401 createBoundFunctionProperty(context, console, prototype, "groupCollapsed", V 8Console::groupCollapsedCallback); | |
402 createBoundFunctionProperty(context, console, prototype, "groupEnd", V8Conso le::groupEndCallback); | |
403 createBoundFunctionProperty(context, console, prototype, "clear", V8Console: :clearCallback); | |
404 createBoundFunctionProperty(context, console, prototype, "count", V8Console: :countCallback); | |
405 createBoundFunctionProperty(context, console, prototype, "assert", V8Console ::assertCallback); | |
406 createBoundFunctionProperty(context, console, prototype, "markTimeline", V8C onsole::markTimelineCallback); | |
407 createBoundFunctionProperty(context, console, prototype, "profile", V8Consol e::profileCallback); | |
408 createBoundFunctionProperty(context, console, prototype, "profileEnd", V8Con sole::profileEndCallback); | |
409 createBoundFunctionProperty(context, console, prototype, "timeline", V8Conso le::timelineCallback); | |
410 createBoundFunctionProperty(context, console, prototype, "timelineEnd", V8Co nsole::timelineEndCallback); | |
411 createBoundFunctionProperty(context, console, prototype, "time", V8Console:: timeCallback); | |
412 createBoundFunctionProperty(context, console, prototype, "timeEnd", V8Consol e::timeEndCallback); | |
413 createBoundFunctionProperty(context, console, prototype, "timeStamp", V8Cons ole::timeStampCallback); | |
414 | |
415 if (!console->SetPrototype(context, prototype).FromMaybe(false)) | |
416 return v8::MaybeLocal<v8::Object>(); | |
417 | |
418 if (hasMemoryAttribute) | |
419 console->SetAccessorProperty(toV8StringInternalized(isolate, "memory"), v8::Function::New(isolate, V8Console::memoryGetterCallback, console), v8::Functi on::New(isolate, V8Console::memorySetterCallback), static_cast<v8::PropertyAttri bute>(v8::None), v8::DEFAULT); | |
420 | |
421 console->SetPrivate(context, debuggerPrivateKey(isolate), v8::External::New( isolate, debugger)); | |
dgozman
2016/04/12 03:32:16
I think it's better to store InspectedContext* poi
kozy
2016/04/12 21:58:32
Done.
| |
422 return console; | |
423 } | |
424 | |
425 } // namespace blink | |
OLD | NEW |