Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(266)

Side by Side Diff: Source/bindings/core/dart/DartHandleProxy.cpp

Issue 1532413002: Added Dartium changes onto 45.0.2454.104 (Closed) Base URL: http://src.chromium.org/blink/branches/chromium/2454
Patch Set: Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 2012 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30 #include "config.h"
31 #include "bindings/core/dart/DartHandleProxy.h"
32
33 #include "bindings/core/dart/DartJsInterop.h"
34 #include "bindings/core/dart/DartPersistentValue.h"
35 #include "bindings/core/dart/V8Converter.h"
36 #include "bindings/core/v8/PageScriptDebugServer.h"
37 #include "bindings/core/v8/ScriptController.h"
38 #include "bindings/core/v8/V8Binding.h"
39 #include "bindings/core/v8/V8ScriptRunner.h"
40 #include "bindings/core/v8/V8ThrowException.h"
41
42 #include "wtf/StdLibExtras.h"
43
44 namespace blink {
45
46 struct DartHandleProxy::CallbackData {
47 ScopedPersistent<v8::Object> handle;
48 DartPersistentValue* value;
49 };
50
51 typedef HashMap<String, v8::Persistent<v8::FunctionTemplate>* > FunctionTemplate Map;
52
53 static v8::Local<v8::FunctionTemplate> objectProxyTemplate(Dart_Handle instance) ;
54 static v8::Local<v8::FunctionTemplate> functionProxyTemplate();
55 static v8::Local<v8::FunctionTemplate> libraryProxyTemplate(v8::Handle<v8::Strin g> libraryNameV8);
56 static v8::Local<v8::FunctionTemplate> typeProxyTemplate(Dart_Handle type);
57 static v8::Local<v8::FunctionTemplate> frameProxyTemplate();
58
59 DartPersistentValue* DartHandleProxy::readPointerFromProxy(v8::Handle<v8::Value> proxy)
60 {
61 void* pointer = proxy.As<v8::Object>()->GetAlignedPointerFromInternalField(0 );
62 return static_cast<DartPersistentValue*>(pointer);
63 }
64
65 bool DartHandleProxy::isDartProxy(v8::Handle<v8::Value> value)
66 {
67 if (!value.IsEmpty() && value->IsObject()) {
68 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
69 v8::Local<v8::Value> hiddenValue = value.As<v8::Object>()->GetHiddenValu e(v8::String::NewFromUtf8(v8Isolate, "dartProxy"));
70 return *hiddenValue && hiddenValue->IsBoolean();
71 }
72 return false;
73 }
74
75 bool isGlobalObjectProxy(v8::Handle<v8::Object> value)
76 {
77 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
78 v8::Local<v8::Value> hiddenValue = value.As<v8::Object>()->GetHiddenValue(v8 ::String::NewFromUtf8(v8Isolate, "asGlobal"));
79 return *hiddenValue && hiddenValue->IsBoolean();
80 }
81
82 DartScopes::DartScopes(v8::Local<v8::Object> v8Handle, bool disableBreak) :
83 scriptValue(DartHandleProxy::readPointerFromProxy(v8Handle)),
84 scope(scriptValue->isolate()),
85 disableBreak(disableBreak)
86 {
87 ASSERT(scriptValue->isIsolateAlive());
88 handle = scriptValue->value();
89 if (disableBreak) {
90 previousPauseInfo = Dart_GetExceptionPauseInfo();
91 Dart_SetExceptionPauseInfo(kNoPauseOnExceptions);
92 }
93 }
94
95 DartScopes::~DartScopes()
96 {
97 if (disableBreak) {
98 Dart_SetExceptionPauseInfo(previousPauseInfo);
99 }
100 }
101
102 static void weakCallback(const v8::WeakCallbackData<v8::Object, DartHandleProxy: :CallbackData >& data)
103 {
104 DartHandleProxy::CallbackData* callbackData = data.GetParameter();
105 callbackData->handle.clear();
106 delete callbackData->value;
107 delete callbackData;
108 }
109
110 Dart_Handle DartHandleProxy::unwrapValue(v8::Handle<v8::Value> value)
111 {
112 if (DartHandleProxy::isDartProxy(value))
113 return readPointerFromProxy(value)->value();
114
115 Dart_Handle exception = 0;
116 Dart_Handle handle = V8Converter::toDart(value, exception);
117 ASSERT(!exception);
118 return handle;
119 }
120
121 bool libraryHasMember(Dart_Handle library, Dart_Handle name)
122 {
123 return !Dart_IsError(Dart_GetField(library, name))
124 || !Dart_IsError(Dart_GetType(library, name, 0, 0))
125 || Dart_IsFunction(Dart_LookupFunction(library, name));
126 }
127
128 bool typeHasMember(Dart_Handle type, Dart_Handle name)
129 {
130 return !Dart_IsError(Dart_GetField(type, name)) || Dart_IsFunction(Dart_Look upFunction(type, name));
131 }
132
133 Dart_Handle getEncodedMapKeyList(Dart_Handle object)
134 {
135 return DartUtilities::invokeUtilsMethod("getEncodedMapKeyList", 1, &object);
136 }
137
138 Dart_Handle stripTrailingDot(Dart_Handle str)
139 {
140 return DartUtilities::invokeUtilsMethod("stripTrailingDot", 1, &str);
141 }
142
143 Dart_Handle addTrailingDot(Dart_Handle str)
144 {
145 return DartUtilities::invokeUtilsMethod("addTrailingDot", 1, &str);
146 }
147
148 Dart_Handle demangle(Dart_Handle str)
149 {
150 return DartUtilities::invokeUtilsMethod("demangle", 1, &str);
151 }
152
153 Dart_Handle lookupValueForEncodedMapKey(Dart_Handle object, Dart_Handle key)
154 {
155 Dart_Handle args[] = {object, key};
156 return DartUtilities::invokeUtilsMethod("lookupValueForEncodedMapKey", 2, ar gs);
157 }
158
159 Dart_Handle buildConstructorName(Dart_Handle typeName, Dart_Handle constructorNa me)
160 {
161 Dart_Handle args[] = {typeName, constructorName};
162 return DartUtilities::invokeUtilsMethod("buildConstructorName", 2, args);
163 }
164
165 Dart_Handle stripClassName(Dart_Handle str, Dart_Handle typeName)
166 {
167 Dart_Handle args[] = {str, typeName};
168 return DartUtilities::invokeUtilsMethod("stripClassName", 2, args);
169 }
170
171 bool isNoSuchMethodError(Dart_Handle type)
172 {
173 Dart_Handle exception = 0;
174 bool ret = DartUtilities::dartToBool(DartUtilities::invokeUtilsMethod("isNoS uchMethodError", 1, &type), exception);
175 ASSERT(!exception);
176 return ret;
177 }
178
179 Dart_Handle createLocalVariablesMap(Dart_Handle localVariablesList)
180 {
181 return DartUtilities::invokeUtilsMethod("createLocalVariablesMap", 1, &local VariablesList);
182 }
183
184 Dart_Handle getMapKeyList(Dart_Handle localVariablesMap)
185 {
186 return DartUtilities::invokeUtilsMethod("getMapKeyList", 1, &localVariablesM ap);
187 }
188
189 bool mapContainsKey(Dart_Handle map, Dart_Handle key)
190 {
191 Dart_Handle exception = 0;
192 return DartUtilities::dartToBool(Dart_Invoke(map, Dart_NewStringFromCString( "containsKey"), 1, &key), exception);
193 }
194
195 void addFunctionNames(Dart_Handle handle, v8::Local<v8::Array>& properties, intp tr_t* count, bool isInstance, bool noMethods)
196 {
197 intptr_t length = 0;
198 Dart_Handle functionNames = Dart_GetFunctionNames(handle);
199 ASSERT(!Dart_IsError(functionNames));
200 bool isLibrary = Dart_IsLibrary(handle);
201 Dart_ListLength(functionNames, &length);
202 for (intptr_t i = 0; i < length; i++) {
203 Dart_Handle functionName = Dart_ListGetAt(functionNames, i);
204 Dart_Handle function = Dart_LookupFunction(handle, functionName);
205
206 // FIXME: the DartVM doesn't correctly handle invoking properties with
207 // private names. For now, skip private function names.
208 intptr_t functionNameLength = 0;
209 uint8_t* functionNameData;
210 Dart_StringToUTF8(functionName, &functionNameData, &functionNameLength);
211 if (functionNameLength > 0 && functionNameData[0] == '_')
212 continue;
213
214 bool isStatic = false;
215 Dart_FunctionIsStatic(function, &isStatic);
216
217 bool isConstructor = false;
218 Dart_FunctionIsConstructor(function, &isConstructor);
219
220 if (!isLibrary) {
221 if (isInstance == (isStatic || isConstructor))
222 continue;
223
224 bool isSetter = false;
225 Dart_FunctionIsSetter(function, &isSetter);
226 bool isGetter = false;
227 Dart_FunctionIsGetter(function, &isGetter);
228
229 if (noMethods && !isSetter && !isGetter)
230 continue;
231
232 // Skip setters as any setter we care to enumerate should have a mat ching getter.
233 // Setters without matching getters will still be callable but won't be enumerated.
234 if (isSetter)
235 continue;
236 }
237
238 // Strip off the leading typename from constructor name.
239 if (isConstructor)
240 functionName = stripClassName(functionName, Dart_TypeName(handle));
241
242 functionName = demangle(functionName);
243 properties->Set(*count, V8Converter::stringToV8(functionName));
244 *count = *count + 1;
245 }
246 }
247
248 void addClassNames(Dart_Handle library, v8::Local<v8::Array>& properties, intptr _t* count)
249 {
250 intptr_t length = 0;
251 Dart_Handle typeNames = Dart_LibraryGetClassNames(library);
252 ASSERT(!Dart_IsNull(typeNames));
253 ASSERT(Dart_IsList(typeNames));
254 Dart_ListLength(typeNames, &length);
255 for (intptr_t i = 0; i < length; i++) {
256 Dart_Handle typeName = Dart_ListGetAt(typeNames, i);
257 properties->Set(*count, V8Converter::stringToV8(typeName));
258 *count = *count + 1;
259 }
260 }
261
262 void addFieldNames(Dart_Handle fieldNames, v8::Local<v8::Array>& properties, int ptr_t* count)
263 {
264 ASSERT(!Dart_IsApiError(fieldNames));
265 ASSERT(Dart_IsList(fieldNames));
266 intptr_t length = 0;
267 Dart_ListLength(fieldNames, &length);
268 for (intptr_t i = 0; i < length; i += 2) {
269 Dart_Handle fieldName = Dart_ListGetAt(fieldNames, i);
270 properties->Set(*count, V8Converter::stringToV8(demangle(fieldName)));
271 *count = *count + 1;
272 }
273 }
274
275 template<typename CallbackInfo>
276 void setReturnValue(CallbackInfo info, Dart_Handle result)
277 {
278 if (Dart_IsError(result)) {
279 // FIXME: we would really prefer to call the following however it has
280 // bad unintended consequences as then JS cannot catch the thrown except ion.
281 // DartUtilities::reportProblem(DartUtilities::scriptExecutionContext(), result);
282 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
283 V8ThrowException::throwException(v8::String::NewFromUtf8(v8Isolate, Dart _GetError(result)), v8::Isolate::GetCurrent());
284 } else {
285 v8SetReturnValue(info, DartHandleProxy::create(result));
286 }
287 }
288
289 void DartHandleProxy::writePointerToProxy(v8::Local<v8::Object> proxy, Dart_Hand le value)
290 {
291 ASSERT(!proxy.IsEmpty());
292 DartPersistentValue* dartScriptValue = new DartPersistentValue(value);
293 proxy->SetAlignedPointerInInternalField(0, dartScriptValue);
294 v8::Isolate* isolate = v8::Isolate::GetCurrent();
295 v8::Persistent<v8::Object> persistentHandle;
296 DartHandleProxy::CallbackData* callbackData = new DartHandleProxy::CallbackD ata();
297 callbackData->value = dartScriptValue;
298 callbackData->handle.set(isolate, proxy);
299 callbackData->handle.setWeak(callbackData, &weakCallback);
300 }
301
302 intptr_t getLibraryId(v8::Local<v8::Object> proxy)
303 {
304 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
305 return (intptr_t)proxy.As<v8::Object>()->GetHiddenValue(v8::String::NewFromU tf8(v8Isolate, "libraryId"))->Int32Value();
306 }
307
308 // Returns a String of the library prefix or Dart_Null if no prefix is found.
309 Dart_Handle getLibraryPrefix(v8::Local<v8::Object> proxy)
310 {
311 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
312 v8::Local<v8::Value> prefix = proxy.As<v8::Object>()->GetHiddenValue(v8::Str ing::NewFromUtf8(v8Isolate, "prefix"));
313 if (*prefix && prefix->IsString())
314 return V8Converter::stringToDart(prefix);
315 return Dart_Null();
316 }
317
318 static void functionNamedPropertyGetter(v8::Local<v8::String> name, const v8::Pr opertyCallbackInfo<v8::Value>& info)
319 {
320 DartScopes scopes(info.Holder());
321 Dart_Handle handle = scopes.handle;
322
323 ASSERT(DartUtilities::isFunction(DartDOMData::current(), handle) || Dart_IsF unction(handle));
324 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
325 Dart_Handle ret = Dart_Invoke(handle, V8Converter::stringToDart(v8::String:: Concat(v8::String::NewFromUtf8(v8Isolate, "get:"), name)), 0, 0);
326 if (Dart_IsError(ret) && name->Equals(v8::String::NewFromUtf8(v8Isolate, "__ proto__")))
327 return;
328
329 setReturnValue(info, ret);
330 }
331
332 static void functionNamedPropertySetter(v8::Local<v8::String> property, v8::Loca l<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)
333 {
334 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
335 V8ThrowException::throwException(v8::String::NewFromUtf8(v8Isolate, "Dart fu nctions do not have writeable properties"), v8::Isolate::GetCurrent());
336 }
337
338 static void functionInvocationCallback(const v8::FunctionCallbackInfo<v8::Value> & args)
339 {
340 DartScopes scopes(args.Holder());
341 Dart_Handle handle = scopes.handle;
342
343 DartDOMData* domData = DartDOMData::current();
344 ASSERT(DartUtilities::isFunction(domData, handle) || Dart_IsFunction(handle) );
345 bool isConstructor = false;
346 Dart_FunctionIsConstructor(handle, &isConstructor);
347 if (args.IsConstructCall() != isConstructor) {
348 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
349 V8ThrowException::throwException(v8::String::NewFromUtf8(v8Isolate, isCo nstructor ? "Constructor called without new" : "Regular function called as const ructor"), v8Isolate);
350 return;
351 }
352
353 Vector<Dart_Handle> dartFunctionArgs;
354 for (intptr_t i = 0; i < args.Length(); ++i)
355 dartFunctionArgs.append(DartHandleProxy::unwrapValue(args[i]));
356
357 if (DartUtilities::isFunction(domData, handle)) {
358 setReturnValue(args, Dart_InvokeClosure(handle, dartFunctionArgs.size(), dartFunctionArgs.data()));
359 return;
360 }
361 Dart_Handle type = Dart_FunctionOwner(handle);
362 if (isConstructor) {
363 // FIXME: this seems like an overly complex way to have to invoke a cons tructor.
364 setReturnValue(args,
365 Dart_New(type, stripClassName(Dart_FunctionName(handle), Dart_TypeNa me(type)),
366 dartFunctionArgs.size(), dartFunctionArgs.data()));
367 } else {
368 // Workaround so that invoking toString on a Class object returns
369 // something meaningful instead of throwing an exception.
370 if (Dart_IsType(type)) {
371 bool isStatic = true;
372 Dart_FunctionIsStatic(handle, &isStatic);
373 // Attempting to invoke a static method on a Class object will fail
374 // so there is not much harm in returning a more user friendly
375 // result for toString().
376 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
377 if (!isStatic && V8Converter::stringToV8(Dart_FunctionName(handle))- >Equals(v8::String::NewFromUtf8(v8Isolate, "toString"))) {
378 setReturnValue(args, Dart_QualifiedTypeName(type));
379 return;
380 }
381 }
382 setReturnValue(args,
383 Dart_Invoke(type, Dart_FunctionName(handle), dartFunctionArgs.size() , dartFunctionArgs.data()));
384 }
385 }
386
387 static void typeProxyConstructorInvocationCallback(const v8::FunctionCallbackInf o<v8::Value>& args)
388 {
389 DartScopes scopes(args.Holder());
390 Dart_Handle handle = scopes.handle;
391
392 ASSERT(Dart_IsType(handle));
393
394 if (!args.IsConstructCall()) {
395 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
396 V8ThrowException::throwException(v8::String::NewFromUtf8(v8Isolate, "Con structors can only be invoked with 'new'"), v8Isolate);
397 return;
398 }
399
400 Vector<Dart_Handle> dartFunctionArgs;
401 for (intptr_t i = 0; i < args.Length(); ++i)
402 dartFunctionArgs.append(DartHandleProxy::unwrapValue(args[i]));
403
404 setReturnValue(args, Dart_New(handle, Dart_Null(), dartFunctionArgs.size(), dartFunctionArgs.data()));
405 }
406
407 void getImportedLibrariesMatchingPrefix(intptr_t libraryId, Dart_Handle prefix, Vector<std::pair<Dart_Handle, intptr_t> >* libraries)
408 {
409 Dart_Handle imports = Dart_GetLibraryImports(libraryId);
410 ASSERT(!Dart_IsError(imports));
411 // Unfortunately dart_tools_api.h adds a trailing dot to import prefixes.
412 if (!Dart_IsNull(prefix))
413 prefix = addTrailingDot(prefix);
414 intptr_t length = 0;
415 Dart_ListLength(imports, &length);
416 for (intptr_t i = 0; i < length; i += 2) {
417 Dart_Handle importPrefix = Dart_ListGetAt(imports, i);
418 ASSERT(Dart_IsNull(importPrefix) || Dart_IsString(importPrefix));
419 bool equals = false;
420 Dart_Handle ALLOW_UNUSED result = Dart_ObjectEquals(prefix, importPrefix , &equals);
421 ASSERT(!Dart_IsError(result));
422 if (equals) {
423 Dart_Handle importedLibraryIdHandle = Dart_ListGetAt(imports, i + 1) ;
424 ASSERT(Dart_IsInteger(importedLibraryIdHandle));
425 int64_t importedLibraryId;
426 Dart_IntegerToInt64(importedLibraryIdHandle, &importedLibraryId);
427 Dart_Handle libraryURL = Dart_GetLibraryURL(importedLibraryId);
428 ASSERT(!Dart_IsError(libraryURL));
429 Dart_Handle library = Dart_LookupLibrary(libraryURL);
430 ASSERT(Dart_IsLibrary(library));
431 libraries->append(std::pair<Dart_Handle, intptr_t>(library, imported LibraryId));
432 }
433 }
434 }
435
436 static bool libraryNamedPropertyGetterHelper(Dart_Handle library, Dart_Handle da rtName,
437 const v8::PropertyCallbackInfo<v8::Value>* info)
438 {
439 Dart_Handle ret;
440 ret = Dart_GetField(library, dartName);
441 if (!Dart_IsApiError(ret)) {
442 if (info)
443 setReturnValue(*info, ret);
444 return true;
445 }
446
447 ret = Dart_GetType(library, dartName, 0, 0);
448 if (!Dart_IsError(ret)) {
449 if (info)
450 v8SetReturnValue(*info, DartHandleProxy::createTypeProxy(ret, true)) ;
451 return true;
452 }
453
454 ret = Dart_LookupFunction(library, dartName);
455 if (!Dart_IsNull(ret) && !Dart_IsError(ret)) {
456 if (info)
457 setReturnValue(*info, ret);
458 return true;
459 }
460 return false;
461 }
462
463 /**
464 * Helper for getting library property values.
465 * Info may be 0 in which case no V8 If info is 0, no return value is set.
466 */
467 static bool libraryNamedPropertyGetterHelper(v8::Local<v8::String> name, v8::Loc al<v8::Object> holder,
468 const v8::PropertyCallbackInfo<v8::Value>* info)
469 {
470 DartScopes scopes(holder);
471 Dart_Handle handle = scopes.handle;
472
473 ASSERT(Dart_IsLibrary(handle));
474 intptr_t libraryId = getLibraryId(holder);
475 Dart_Handle dartName = V8Converter::stringToDart(name);
476 Dart_Handle prefix = getLibraryPrefix(holder);
477 bool hasLibraryPrefix = !Dart_IsNull(prefix) && Dart_IsString(prefix);
478
479 if (hasLibraryPrefix) {
480 Vector<std::pair<Dart_Handle, intptr_t> > libraries;
481 getImportedLibrariesMatchingPrefix(libraryId, prefix, &libraries);
482 for (size_t i = 0; i < libraries.size(); i++) {
483 if (libraryNamedPropertyGetterHelper(libraries[i].first, dartName, i nfo))
484 return true;
485 }
486 } else {
487 if (libraryNamedPropertyGetterHelper(handle, dartName, info))
488 return true;
489
490 // Check whether there is at least one library imported with the specifi ed prefix.
491 Vector<std::pair<Dart_Handle, intptr_t> > libraries;
492 getImportedLibrariesMatchingPrefix(libraryId, dartName, &libraries);
493 if (libraries.size() > 0) {
494 if (info)
495 v8SetReturnValue(*info, DartHandleProxy::createLibraryProxy(hand le, libraryId, dartName, false));
496 return true;
497 }
498 }
499
500 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
501 if (name->Equals(v8::String::NewFromUtf8(v8Isolate, "__proto__"))) {
502 if (info)
503 v8SetReturnValue(*info, v8::Null(v8Isolate));
504 return true;
505 }
506 return false;
507 }
508
509 static void libraryNamedPropertyGetter(v8::Local<v8::String> name, const v8::Pro pertyCallbackInfo<v8::Value>& info)
510 {
511 libraryNamedPropertyGetterHelper(name, info.Holder(), &info);
512 }
513
514 // FIXME: we need to handle prefixes when setting library properties as well
515 // for completness. Postponing implementing this for now as we hope Dart_Invoke
516 // can just be fixed to handle libraries correctly.
517 static void libraryNamedPropertySetter(v8::Local<v8::String> property, v8::Local <v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)
518 {
519 DartScopes scopes(info.Holder());
520 Dart_Handle handle = scopes.handle;
521
522 ASSERT(Dart_IsLibrary(handle));
523 Dart_Handle dartValue = DartHandleProxy::unwrapValue(value);
524 setReturnValue(info, Dart_SetField(handle, V8Converter::stringToDart(propert y), dartValue));
525 }
526
527 static void libraryQueryProperty(v8::Local<v8::String> name, const v8::PropertyC allbackInfo<v8::Integer>& info)
528 {
529 if (libraryNamedPropertyGetterHelper(name, info.Holder(), 0))
530 v8SetReturnValueInt(info, 0);
531 }
532
533 void libraryEnumerateHelper(Dart_Handle library, intptr_t libraryId, v8::Local<v 8::Array> properties, intptr_t* count)
534 {
535 addFunctionNames(library, properties, count, false, false);
536 addClassNames(library, properties, count);
537 addFieldNames(Dart_GetLibraryFields(libraryId), properties, count);
538 }
539
540 static void libraryPropertyEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info)
541 {
542 DartScopes scopes(info.Holder());
543 Dart_Handle handle = scopes.handle;
544
545 intptr_t libraryId = getLibraryId(info.Holder());
546 ASSERT(Dart_IsLibrary(handle));
547 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
548 v8::Local<v8::Array> cachedProperties = info.Holder().As<v8::Object>()->GetH iddenValue(v8::String::NewFromUtf8(v8Isolate, "cache")).As<v8::Array>();
549 if (*cachedProperties) {
550 v8SetReturnValue(info, cachedProperties);
551 return;
552 }
553
554 Dart_Handle prefix = getLibraryPrefix(info.Holder());
555 bool hasLibraryPrefix = Dart_IsString(prefix);
556
557 v8::Local<v8::Array> properties = v8::Array::New(v8Isolate);
558 intptr_t count = 0;
559
560 if (hasLibraryPrefix) {
561 Vector<std::pair<Dart_Handle, intptr_t> > libraries;
562 getImportedLibrariesMatchingPrefix(libraryId, prefix, &libraries);
563 for (size_t i = 0; i < libraries.size(); i++)
564 libraryEnumerateHelper(libraries[i].first, libraries[i].second, prop erties, &count);
565 } else {
566 libraryEnumerateHelper(handle, libraryId, properties, &count);
567 // Add all library prefixes of imports to the library.
568 Dart_Handle imports = Dart_GetLibraryImports(libraryId);
569 ASSERT(!Dart_IsError(imports));
570 intptr_t length = 0;
571 Dart_ListLength(imports, &length);
572 for (intptr_t i = 0; i < length; i += 2) {
573 Dart_Handle importPrefix = Dart_ListGetAt(imports, i);
574 if (!Dart_IsNull(importPrefix)) {
575 ASSERT(Dart_IsString(importPrefix));
576 properties->Set(count, V8Converter::stringToV8(
577 demangle(stripTrailingDot(importPrefix))));
578 count++;
579 }
580 }
581 }
582
583 info.Holder()->SetHiddenValue(v8::String::NewFromUtf8(v8Isolate, "cache"), p roperties);
584 v8SetReturnValue(info, properties);
585 }
586
587 bool isShowStatics(v8::Handle<v8::Value> value)
588 {
589 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
590 v8::Local<v8::Value> showStatics = value.As<v8::Object>()->GetHiddenValue(v8 ::String::NewFromUtf8(v8Isolate, "showStatics"));
591 ASSERT(*showStatics && showStatics->IsBoolean());
592 return showStatics->BooleanValue();
593 }
594
595 static void typeNamedPropertyGetter(v8::Local<v8::String> name, const v8::Proper tyCallbackInfo<v8::Value>& info)
596 {
597 DartScopes scopes(info.Holder());
598 Dart_Handle handle = scopes.handle;
599
600 Dart_Handle ret;
601 ASSERT(Dart_IsType(handle));
602 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
603 if (name->Equals(v8::String::NewFromUtf8(v8Isolate, "__proto__"))) {
604 // Due to Dart semantics, if we are showing statics, we need to
605 // not link types up to their superclasses as statics in superclasses
606 // are not visible in subclasses.
607 if (isShowStatics(info.Holder())) {
608 v8SetReturnValue(info, v8::Null(v8Isolate));
609 return;
610 }
611
612 Dart_Handle supertype = Dart_GetSupertype(handle);
613 if (!Dart_IsNull(supertype))
614 v8SetReturnValue(info, DartHandleProxy::createTypeProxy(supertype, f alse));
615 else
616 v8SetReturnValue(info, v8::Null(v8Isolate));
617 return;
618 }
619
620 Dart_Handle dartName = V8Converter::stringToDart(name);
621 ret = Dart_GetField(handle, dartName);
622 if (!Dart_IsError(ret)) {
623 setReturnValue(info, ret);
624 return;
625 }
626 ret = Dart_LookupFunction(handle, dartName);
627 if (!Dart_IsNull(ret) && !Dart_IsError(ret)) {
628 setReturnValue(info, ret);
629 return;
630 }
631
632 Dart_Handle typeName = Dart_TypeName(handle);
633 ASSERT(Dart_IsString(typeName));
634 Dart_Handle constructorName = buildConstructorName(typeName, V8Converter::st ringToDart(name));
635 ret = Dart_LookupFunction(handle, constructorName);
636 if (!Dart_IsNull(ret) && !Dart_IsError(ret))
637 setReturnValue(info, ret);
638 }
639
640 static void typeNamedPropertySetter(v8::Local<v8::String> property, v8::Local<v8 ::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)
641 {
642 DartScopes scopes(info.Holder());
643 Dart_Handle handle = scopes.handle;
644
645 ASSERT(Dart_IsType(handle));
646 Dart_Handle dartValue = DartHandleProxy::unwrapValue(value);
647 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
648 setReturnValue(info, Dart_Invoke(handle, V8Converter::stringToDart(v8::Strin g::Concat(v8::String::NewFromUtf8(v8Isolate, "set:"), property)), 1, &dartValue) );
649 }
650
651 static void typeQueryProperty(v8::Local<v8::String> name, const v8::PropertyCall backInfo<v8::Integer>& info)
652 {
653 DartScopes scopes(info.Holder());
654 Dart_Handle handle = scopes.handle;
655
656 ASSERT(Dart_IsType(handle));
657 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
658 if (name->Equals(v8::String::NewFromUtf8(v8Isolate, "__proto__"))
659 || typeHasMember(handle, V8Converter::stringToDart(name)))
660 return v8SetReturnValueInt(info, 0);
661 }
662
663 static void typePropertyEnumerator(const v8::PropertyCallbackInfo<v8::Array>& in fo)
664 {
665 DartScopes scopes(info.Holder());
666 Dart_Handle handle = scopes.handle;
667 bool showStatics = isShowStatics(info.Holder());
668
669 ASSERT(Dart_IsType(handle));
670
671 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
672 v8::Local<v8::Array> properties = v8::Array::New(v8Isolate);
673 intptr_t count = 0;
674 addFunctionNames(handle, properties, &count, !showStatics, false);
675 if (showStatics)
676 addFieldNames(Dart_GetStaticFields(handle), properties, &count);
677
678 properties->Set(count, v8::String::NewFromUtf8(v8Isolate, "__proto__"));
679 count++;
680 v8SetReturnValue(info, properties);
681 }
682
683 static void frameNamedPropertyGetter(v8::Local<v8::String> name, const v8::Prope rtyCallbackInfo<v8::Value>& info)
684 {
685 DartScopes scopes(info.Holder());
686 Dart_Handle handle = scopes.handle;
687
688 if (mapContainsKey(handle, V8Converter::stringToDart(name))) {
689 Dart_Handle indexedGetterOperator = Dart_NewStringFromCString("[]");
690 Dart_Handle dartName = V8Converter::stringToDart(name);
691 setReturnValue(info, Dart_Invoke(handle, indexedGetterOperator, 1, &dart Name));
692 }
693 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
694 if (name->Equals(v8::String::NewFromUtf8(v8Isolate, "__proto__"))) {
695 v8SetReturnValue(info, v8::Null(v8Isolate));
696 }
697 }
698
699 static void frameNamedPropertySetter(v8::Local<v8::String> property, v8::Local<v 8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info)
700 {
701 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
702 V8ThrowException::throwException(v8::String::NewFromUtf8(v8Isolate, "Dart do es not yet provide a debugger api for setting local fields"), v8Isolate);
703 }
704
705 static void frameQueryProperty(v8::Local<v8::String> name, const v8::PropertyCal lbackInfo<v8::Integer>& info)
706 {
707 DartScopes scopes(info.Holder());
708
709 if (mapContainsKey(scopes.handle, V8Converter::stringToDart(name)))
710 v8SetReturnValueInt(info, 0);
711 }
712
713 static void framePropertyEnumerator(const v8::PropertyCallbackInfo<v8::Array>& i nfo)
714 {
715 DartScopes scopes(info.Holder());
716 Dart_Handle keyList = getMapKeyList(scopes.handle);
717 ASSERT(!Dart_IsError(keyList));
718 ASSERT(Dart_IsList(keyList));
719
720 intptr_t length = 0;
721 Dart_ListLength(keyList, &length);
722 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
723 v8::Local<v8::Array> properties = v8::Array::New(v8Isolate, length);
724 for (intptr_t i = 0; i < length; i ++)
725 properties->Set(i, V8Converter::stringToV8(Dart_ListGetAt(keyList, i)));
726 v8SetReturnValue(info, properties);
727 }
728
729 static void namedPropertyGetter(v8::Local<v8::String> name, const v8::PropertyCa llbackInfo<v8::Value>& info)
730 {
731 DartScopes scopes(info.Holder());
732 Dart_Handle handle = scopes.handle;
733
734 ASSERT(Dart_IsInstance(handle));
735 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
736 if (name->Equals(v8::String::NewFromUtf8(v8Isolate, "__proto__"))) {
737 v8SetReturnValue(info, DartHandleProxy::createTypeProxy(Dart_InstanceGet Type(handle), false));
738 return;
739 }
740
741 v8::String::Utf8Value stringName(name);
742 const char* data = *stringName;
743 if (data[0] == ':' || data[0] == '#') {
744 // Look up a map key instead of a regular property as regular dart prope rty names
745 // cannot start with these symbols.
746 setReturnValue(info,
747 lookupValueForEncodedMapKey(handle, V8Converter::stringToDart(name)) );
748 return;
749 }
750 // Prefix for metadata used only by the Dart Editor debugger.
751 if (data[0] == '@') {
752 if (name->Equals(v8::String::NewFromUtf8(v8Isolate, "@staticFields"))) {
753 v8SetReturnValue(info, DartHandleProxy::createTypeProxy(Dart_Instanc eGetType(handle), true));
754 return;
755 }
756 if (name->Equals(v8::String::NewFromUtf8(v8Isolate, "@library"))) {
757 intptr_t libraryId = 0;
758 intptr_t classId = 0;
759 Dart_Handle ALLOW_UNUSED result = Dart_GetObjClassId(handle, &classI d);
760 ASSERT(!Dart_IsError(result));
761 result = Dart_GetClassInfo(classId, 0, &libraryId, 0, 0);
762 ASSERT(!Dart_IsError(result));
763 v8SetReturnValue(info, DartHandleProxy::createLibraryProxy(Dart_GetL ibraryFromId(libraryId), libraryId, Dart_Null(), false));
764 return;
765 }
766 }
767
768 Dart_Handle result = Dart_Invoke(handle, V8Converter::stringToDart(v8::Strin g::Concat(v8::String::NewFromUtf8(v8Isolate, "get:"), name)), 0, 0);
769 if (Dart_IsError(result)) {
770 // To match JS conventions, we should just return undefined if a
771 // property does not exist rather than throwing.
772 if (Dart_ErrorHasException(result) && isNoSuchMethodError(Dart_ErrorGetE xception(result)))
773 return;
774 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
775 v8Isolate->ThrowException(v8::String::NewFromUtf8(v8Isolate, Dart_GetErr or(result)));
776 return;
777 }
778 v8SetReturnValue(info, DartHandleProxy::create(result));
779 }
780
781 static void namedPropertySetter(v8::Local<v8::String> property, v8::Local<v8::Va lue> value, const v8::PropertyCallbackInfo<v8::Value>& info)
782 {
783 DartScopes scopes(info.Holder());
784 Dart_Handle handle = scopes.handle;
785
786 Dart_Handle dartValue = DartHandleProxy::unwrapValue(value);
787 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
788 setReturnValue(info, Dart_Invoke(handle, V8Converter::stringToDart(v8::Strin g::Concat(v8::String::NewFromUtf8(v8Isolate, "set:"), property)), 1, &dartValue) );
789 }
790
791 static void objectQueryProperty(v8::Local<v8::String> name, const v8::PropertyCa llbackInfo<v8::Integer>& info)
792 {
793 DartScopes scopes(info.Holder());
794 Dart_Handle handle = scopes.handle;
795
796 Dart_Handle ret;
797 ASSERT(Dart_IsInstance(handle));
798 v8::String::Utf8Value stringName(name);
799 const char* data = *stringName;
800
801 // Looking up a map key instead of a regular property... as regular dart pro perty names
802 // cannot start with these symbols.
803 if (data[0] == ':' || data[0] == '#') {
804 v8SetReturnValueInt(info, v8::ReadOnly);
805 return;
806 }
807 if (data[0] == '@') {
808 v8SetReturnValueInt(info, v8::DontEnum);
809 return;
810 }
811
812 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
813 ret = Dart_Invoke(handle, V8Converter::stringToDart(v8::String::Concat(v8::S tring::NewFromUtf8(v8Isolate, "get:"), name)), 0, 0);
814 if (Dart_IsError(ret) && !name->Equals(v8::String::NewFromUtf8(v8Isolate, "_ _proto__"))) {
815 return;
816 }
817 v8SetReturnValueInt(info, 0);
818 }
819
820 static void objectPropertyEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info)
821 {
822 DartScopes scopes(info.Holder());
823 Dart_Handle handle = scopes.handle;
824
825 ASSERT(Dart_IsInstance(handle));
826
827 Dart_Handle typeHandle = Dart_InstanceGetType(handle);
828
829 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
830 v8::Local<v8::Array> properties = v8::Array::New(v8Isolate);
831 intptr_t count = 0;
832 Dart_Handle mapKeys = getEncodedMapKeyList(handle);
833 if (Dart_IsList(mapKeys)) {
834 // If the object has map keys, add them all as properties at the start
835 // of the list. This aids for debugging although it risks confusing
836 // users.
837 intptr_t length = 0;
838 Dart_ListLength(mapKeys, &length);
839 for (intptr_t i = 0; i < length; i++) {
840 properties->Set(count, V8Converter::stringToV8(Dart_ListGetAt(mapKey s, i)));
841 count++;
842 }
843 }
844
845 Dart_Handle instanceFields = Dart_GetInstanceFields(handle);
846 intptr_t length = 0;
847 Dart_ListLength(instanceFields, &length);
848 for (intptr_t i = 0; i < length; i += 2) {
849 properties->Set(count, DartHandleProxy::create(
850 Dart_ListGetAt(instanceFields, i)));
851 count++;
852 }
853
854 while (!Dart_IsError(typeHandle) && !Dart_IsNull(typeHandle)) {
855 addFunctionNames(typeHandle, properties, &count, true, true);
856 typeHandle = Dart_GetSupertype(typeHandle);
857 }
858
859 properties->Set(count, v8::String::NewFromUtf8(v8Isolate, "@staticFields"));
860 count++;
861 properties->Set(count, v8::String::NewFromUtf8(v8Isolate, "@library"));
862 count++;
863 v8SetReturnValue(info, properties);
864 }
865
866 static void indexedGetter(uint32_t index, const v8::PropertyCallbackInfo<v8::Val ue>& info)
867 {
868 DartScopes scopes(info.Holder());
869 Dart_Handle handle = scopes.handle;
870
871 Dart_Handle ret = 0;
872 if (Dart_IsList(handle))
873 ret = Dart_ListGetAt(handle, index);
874 else
875 ret = Dart_Null();
876
877 setReturnValue(info, ret);
878 }
879
880 static void indexedSetter(uint32_t index, v8::Local<v8::Value> value, const v8:: PropertyCallbackInfo<v8::Value>& info)
881 {
882 DartScopes scopes(info.Holder());
883 Dart_Handle handle = scopes.handle;
884
885 Dart_Handle ret = 0;
886 if (Dart_IsList(handle))
887 ret = Dart_ListSetAt(handle, index, DartHandleProxy::unwrapValue(value)) ;
888 else
889 ret = Dart_Null();
890
891 setReturnValue(info, ret);
892 }
893
894 static void indexedEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info)
895 {
896 DartScopes scopes(info.Holder());
897 Dart_Handle handle = scopes.handle;
898
899 intptr_t length = 0;
900 if (Dart_IsList(handle))
901 Dart_ListLength(handle, &length);
902
903 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
904 v8::Local<v8::Array> indexes = v8::Array::New(v8Isolate, length);
905 for (int i = 0; i < length; i++)
906 indexes->Set(i, v8::Integer::New(v8Isolate, i));
907
908 v8SetReturnValue(info, indexes);
909 }
910
911 static v8::Local<v8::ObjectTemplate> setupInstanceTemplate(v8::Local<v8::Functio nTemplate> proxyTemplate)
912 {
913 v8::Local<v8::ObjectTemplate> instanceTemplate = proxyTemplate->InstanceTemp late();
914 instanceTemplate->SetInternalFieldCount(1);
915 return instanceTemplate;
916 }
917
918 static v8::Local<v8::FunctionTemplate> objectProxyTemplate(Dart_Handle instance)
919 {
920 DEFINE_STATIC_LOCAL(FunctionTemplateMap, map, ());
921 Dart_Handle dartType = Dart_InstanceGetType(instance);
922 ASSERT(!Dart_IsError(dartType));
923 Dart_Handle typeNameHandle = Dart_TypeName(dartType);
924 ASSERT(!Dart_IsError(typeNameHandle));
925 v8::Handle<v8::String> typeNameV8 = V8Converter::stringToV8(typeNameHandle);
926 String typeName = toCoreString(typeNameV8);
927 v8::Persistent<v8::FunctionTemplate>* proxyTemplate = map.get(typeName);
928 v8::Local<v8::FunctionTemplate> proxyTemplateLocal;
929 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
930 if (!proxyTemplate) {
931 proxyTemplate = new v8::Persistent<v8::FunctionTemplate>(v8Isolate, v8:: FunctionTemplate::New(v8Isolate));
932 proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, *pr oxyTemplate);
933 proxyTemplateLocal->SetClassName(typeNameV8);
934 map.set(typeName, proxyTemplate);
935 v8::Local<v8::ObjectTemplate> instanceTemplate = setupInstanceTemplate(p roxyTemplateLocal);
936 instanceTemplate->SetIndexedPropertyHandler(&indexedGetter, &indexedSett er, 0, 0, &indexedEnumerator);
937 instanceTemplate->SetNamedPropertyHandler(&namedPropertyGetter, &namedPr opertySetter, &objectQueryProperty, 0, &objectPropertyEnumerator);
938 } else {
939 proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, *pr oxyTemplate);
940 }
941 return proxyTemplateLocal;
942 }
943
944 static v8::Local<v8::FunctionTemplate> functionProxyTemplate()
945 {
946 DEFINE_STATIC_LOCAL(v8::Persistent<v8::FunctionTemplate>, proxyTemplate, ()) ;
947 v8::Local<v8::FunctionTemplate> proxyTemplateLocal;
948 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
949 if (proxyTemplate.IsEmpty()) {
950 proxyTemplate.Reset(v8::Isolate::GetCurrent(), v8::FunctionTemplate::New (v8Isolate));
951 proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, pro xyTemplate);
952 proxyTemplateLocal->SetClassName(v8::String::NewFromUtf8(v8Isolate, "[Da rt Function]"));
953 v8::Local<v8::ObjectTemplate> instanceTemplate = setupInstanceTemplate(p roxyTemplateLocal);
954 instanceTemplate->SetNamedPropertyHandler(&functionNamedPropertyGetter, &functionNamedPropertySetter);
955 instanceTemplate->SetCallAsFunctionHandler(&functionInvocationCallback);
956 } else {
957 proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, pro xyTemplate);
958 }
959 return proxyTemplateLocal;
960 }
961
962 static v8::Local<v8::FunctionTemplate> libraryProxyTemplate(v8::Handle<v8::Strin g> libraryNameV8)
963 {
964 DEFINE_STATIC_LOCAL(FunctionTemplateMap, map, ());
965 String typeName = toCoreString(libraryNameV8);
966 v8::Persistent<v8::FunctionTemplate>* proxyTemplate = map.get(typeName);
967 v8::Local<v8::FunctionTemplate> proxyTemplateLocal;
968 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
969 if (!proxyTemplate) {
970 proxyTemplate = new v8::Persistent<v8::FunctionTemplate>(v8Isolate, v8:: FunctionTemplate::New(v8Isolate));
971 proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, *pr oxyTemplate);
972 proxyTemplateLocal->SetClassName(libraryNameV8);
973 map.set(typeName, proxyTemplate);
974 v8::Local<v8::ObjectTemplate> instanceTemplate = setupInstanceTemplate(p roxyTemplateLocal);
975 instanceTemplate->SetNamedPropertyHandler(&libraryNamedPropertyGetter, & libraryNamedPropertySetter, &libraryQueryProperty, 0, &libraryPropertyEnumerator );
976 } else {
977 proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, *pr oxyTemplate);
978 }
979 return proxyTemplateLocal;
980 }
981
982 static v8::Local<v8::FunctionTemplate> typeProxyTemplate(Dart_Handle type)
983 {
984 DEFINE_STATIC_LOCAL(FunctionTemplateMap, map, ());
985 Dart_Handle typeNameHandle = Dart_TypeName(type);
986 ASSERT(!Dart_IsError(typeNameHandle));
987 v8::Handle<v8::String> typeNameV8 = V8Converter::stringToV8(typeNameHandle);
988 String typeName = toCoreString(typeNameV8);
989
990 v8::Persistent<v8::FunctionTemplate>* proxyTemplate = map.get(typeName);
991 v8::Local<v8::FunctionTemplate> proxyTemplateLocal;
992 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
993 if (!proxyTemplate) {
994 proxyTemplate = new v8::Persistent<v8::FunctionTemplate>(v8Isolate, v8:: FunctionTemplate::New(v8Isolate));
995 proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, *pr oxyTemplate);
996 proxyTemplateLocal->SetClassName(typeNameV8);
997 v8::Local<v8::ObjectTemplate> instanceTemplate = setupInstanceTemplate(p roxyTemplateLocal);
998 instanceTemplate->SetNamedPropertyHandler(&typeNamedPropertyGetter, &typ eNamedPropertySetter, &typeQueryProperty, 0, &typePropertyEnumerator);
999 instanceTemplate->SetCallAsFunctionHandler(&typeProxyConstructorInvocati onCallback);
1000 map.set(typeName, proxyTemplate);
1001 } else {
1002 proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, *pr oxyTemplate);
1003 }
1004 return proxyTemplateLocal;
1005 }
1006
1007 static v8::Local<v8::FunctionTemplate> frameProxyTemplate()
1008 {
1009 DEFINE_STATIC_LOCAL(v8::Persistent<v8::FunctionTemplate>, proxyTemplate, ()) ;
1010 v8::Local<v8::FunctionTemplate> proxyTemplateLocal;
1011 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
1012 if (proxyTemplate.IsEmpty()) {
1013 proxyTemplate.Reset(v8::Isolate::GetCurrent(), v8::FunctionTemplate::New (v8Isolate));
1014 proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, pro xyTemplate);
1015 proxyTemplateLocal->SetClassName(v8::String::NewFromUtf8(v8Isolate, "[Da rt Frame]"));
1016 v8::Local<v8::ObjectTemplate> instanceTemplate = setupInstanceTemplate(p roxyTemplateLocal);
1017 instanceTemplate->SetNamedPropertyHandler(&frameNamedPropertyGetter, &fr ameNamedPropertySetter, &frameQueryProperty, 0, &framePropertyEnumerator);
1018 } else {
1019 proxyTemplateLocal = v8::Local<v8::FunctionTemplate>::New(v8Isolate, pro xyTemplate);
1020 }
1021 return proxyTemplateLocal;
1022 }
1023
1024 v8::Handle<v8::Value> DartHandleProxy::create(Dart_Handle value)
1025 {
1026 v8::Context::Scope scope(DartUtilities::currentV8Context());
1027 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
1028
1029 if (Dart_IsNull(value))
1030 return v8::Null(v8Isolate);
1031 if (Dart_IsString(value))
1032 return V8Converter::stringToV8(value);
1033 if (Dart_IsBoolean(value))
1034 return V8Converter::booleanToV8(value);
1035 if (Dart_IsNumber(value))
1036 return V8Converter::numberToV8(value);
1037 v8::Local<v8::Object> proxy;
1038 // We could unwrap Dart DOM types to native types and then rewrap them as
1039 // JS DOM types but currently we choose not to instead returning JS
1040 // proxies for the Dart DOM types so that the Dart DOM APIs for DOM types
1041 // are exposed in the debugger instead of the JS APIs.
1042 // We attempt to get the best of both worlds by providing the method
1043 // getJavaScriptType to let debugger APIs treat these Dart proxies for
1044 // DOM types like native DOM types for cases such as visual Node
1045 // highlighting.
1046
1047 DartDOMData* domData = DartDOMData::current();
1048 // FIXME: refactor code so we do not have to check for Dart_IsFunction.
1049 if (DartUtilities::isFunction(domData, value) || Dart_IsFunction(value)) {
1050 proxy = functionProxyTemplate()->InstanceTemplate()->NewInstance();
1051 } else {
1052 ASSERT(Dart_IsInstance(value));
1053 proxy = objectProxyTemplate(value)->InstanceTemplate()->NewInstance();
1054 }
1055 writePointerToProxy(proxy, value);
1056 proxy->SetHiddenValue(v8::String::NewFromUtf8(v8Isolate, "dartProxy"), v8::B oolean::New(v8Isolate, true));
1057
1058 return proxy;
1059 }
1060
1061 v8::Handle<v8::Value> DartHandleProxy::createTypeProxy(Dart_Handle value, bool s howStatics)
1062 {
1063 ASSERT(Dart_IsType(value));
1064 v8::Local<v8::Object> proxy = typeProxyTemplate(value)->InstanceTemplate()-> NewInstance();
1065 writePointerToProxy(proxy, value);
1066 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
1067 proxy->SetHiddenValue(v8::String::NewFromUtf8(v8Isolate, "dartProxy"), v8::B oolean::New(v8Isolate, true));
1068 proxy->SetHiddenValue(v8::String::NewFromUtf8(v8Isolate, "showStatics"), v8: :Boolean::New(v8Isolate, showStatics));
1069 return proxy;
1070 }
1071
1072 /**
1073 * Returns the JavaScript type name following the Chrome debugger conventions
1074 * for Dart objects that have natural JavaScript analogs.
1075 * This enables visually consistent display of Dart Lists and JavaScript arrays,
1076 * functions, and DOM nodes.
1077 */
1078 const char* DartHandleProxy::getJavaScriptType(v8::Handle<v8::Value> value)
1079 {
1080 DartPersistentValue* scriptValue = readPointerFromProxy(value);
1081 ASSERT(scriptValue->isIsolateAlive());
1082 DartIsolateScope scope(scriptValue->isolate());
1083 DartApiScope apiScope;
1084 Dart_PersistentHandle handle = scriptValue->value();
1085
1086 if (Dart_IsInstance(handle)) {
1087 if (Dart_IsList(handle))
1088 return "array";
1089
1090 if (DartUtilities::isNode(handle))
1091 return "node";
1092 }
1093
1094 return 0;
1095 }
1096
1097 Node* DartHandleProxy::toNativeNode(v8::Handle<v8::Value> value)
1098 {
1099 DartPersistentValue* scriptValue = readPointerFromProxy(value);
1100 ASSERT(scriptValue->isIsolateAlive());
1101 DartIsolateScope scope(scriptValue->isolate());
1102 DartApiScope apiScope;
1103
1104 Dart_PersistentHandle handle = scriptValue->value();
1105 if (!DartUtilities::isNode(handle)) {
1106 // Not a DOM node.
1107 ASSERT_NOT_REACHED();
1108 return 0;
1109 }
1110 return DartUtilities::dartNodeToNativeNode(handle);
1111 }
1112
1113 /**
1114 * Creates a proxy for a Dart library.
1115 * If a string prefix is specified, we similuate that all requests to the librar y start with
1116 * the specified prefix.
1117 */
1118 v8::Handle<v8::Value> DartHandleProxy::createLibraryProxy(Dart_Handle value, int ptr_t libraryId, Dart_Handle prefix, bool asGlobal)
1119 {
1120 v8::Context::Scope scope(DartUtilities::currentV8Context());
1121 ASSERT(Dart_IsLibrary(value));
1122 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
1123 v8::Handle<v8::String> libraryNameV8 = Dart_IsNull(prefix) ? V8Converter::st ringToV8(Dart_GetLibraryURL(libraryId)) : v8::String::NewFromUtf8(v8Isolate, "[L ibrary Prefix]");
1124 v8::Local<v8::Object> proxy = libraryProxyTemplate(libraryNameV8)->InstanceT emplate()->NewInstance();
1125 writePointerToProxy(proxy, value);
1126 proxy->SetHiddenValue(v8::String::NewFromUtf8(v8Isolate, "libraryId"), v8::N umber::New(v8Isolate, libraryId));
1127 if (Dart_IsString(prefix))
1128 proxy->SetHiddenValue(v8::String::NewFromUtf8(v8Isolate, "prefix"), V8Co nverter::stringToV8(prefix));
1129
1130 if (asGlobal)
1131 proxy->SetHiddenValue(v8::String::NewFromUtf8(v8Isolate, "asGlobal"), v8 ::Boolean::New(v8Isolate, true));
1132
1133 proxy->SetHiddenValue(v8::String::NewFromUtf8(v8Isolate, "dartProxy"), v8::B oolean::New(v8Isolate, true));
1134 return proxy;
1135 }
1136
1137 v8::Handle<v8::Value> DartHandleProxy::createLocalScopeProxy(Dart_Handle localVa riables)
1138 {
1139 v8::Local<v8::Object> proxy = frameProxyTemplate()->InstanceTemplate()->NewI nstance();
1140 Dart_Handle localScopeVariableMap = createLocalVariablesMap(localVariables);
1141 ASSERT(!Dart_IsError(localScopeVariableMap));
1142 writePointerToProxy(proxy, localScopeVariableMap);
1143 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
1144 proxy->SetHiddenValue(v8::String::NewFromUtf8(v8Isolate, "dartProxy"), v8::B oolean::New(v8Isolate, true));
1145 return proxy;
1146 }
1147
1148 v8::Handle<v8::Value> DartHandleProxy::evaluate(Dart_Handle target, Dart_Handle expression, Dart_Handle localVariables)
1149 {
1150 DartDOMData* domData = DartDOMData::current();
1151 ASSERT(domData);
1152 ASSERT(Dart_IsList(localVariables) || Dart_IsNull(localVariables));
1153 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
1154 if (V8Converter::stringToV8(expression)->Equals(v8::String::NewFromUtf8(v8Is olate, "@NamesInScope"))) {
1155 // Special case: return an object specifying all names that are in
1156 // scope for the current target. FIXME: we could handle this a lot more
1157 // efficiently given we don't really care what the values of the
1158 // variables are just that they are in scope.
1159 if (Dart_IsLibrary(target))
1160 return DartHandleProxy::createLibraryProxy(target, DartUtilities::li braryHandleToLibraryId(target), Dart_Null(), true);
1161 return DartHandleProxy::create(target);
1162 }
1163
1164 Dart_Handle exception = 0;
1165 bool ret = DartUtilities::dartToBool(DartUtilities::invokeUtilsMethod("isJsE xpression", 1, &expression), exception);
1166 ASSERT(!exception);
1167 if (ret) {
1168 // FIXME(dartbug.com/13468): remove this hacky fallback of invoking JS
1169 // code when we believe a JS code fragment generated by the chrome
1170 // developer tools was passed to us rather than a fragment of true
1171 // Dart code.
1172 ASSERT(!v8Isolate->GetCurrentContext().IsEmpty());
1173 v8::Handle<v8::Value> result = V8ScriptRunner::compileAndRunInternalScri pt(V8Converter::stringToV8(expression), v8::Isolate::GetCurrent());
1174 return result;
1175 }
1176
1177 bool expectsConsoleApi = DartUtilities::dartToBool(DartUtilities::invokeUtil sMethod("expectsConsoleApi", 1, &expression), exception);
1178 ASSERT(!exception);
1179 if (expectsConsoleApi) {
1180 // Vector of local variables and injected console variables.
1181 Vector<Dart_Handle> locals;
1182 if (Dart_IsList(localVariables)) {
1183 DartUtilities::extractListElements(localVariables, exception, locals );
1184 ASSERT(!exception);
1185 }
1186 // Use JsInterop to proxy all properties and functions defined by
1187 // window.console._commandLineAPI
1188 v8::Isolate* v8Isolate = v8::Isolate::GetCurrent();
1189 v8::Handle<v8::Value> commandLineApiValue = v8Isolate->GetCurrentContext ()->Global()->Get(v8::String::NewFromUtf8(v8Isolate, "__commandLineAPI"));
1190 ASSERT(commandLineApiValue->IsObject());
1191 if (commandLineApiValue->IsObject()) {
1192 v8::Handle<v8::Object> commandLineApi = commandLineApiValue.As<v8::O bject>();
1193 v8::Local<v8::Array> propertyNames = commandLineApi->GetOwnPropertyN ames();
1194 uint32_t length = propertyNames->Length();
1195 ASSERT(length > 0);
1196 for (uint32_t i = 0; i < length; i++) {
1197 v8::Handle<v8::String> propertyName = propertyNames->Get(i).As<v 8::String>();
1198 ASSERT(!propertyNames.IsEmpty());
1199 v8::Handle<v8::Value> propertyValue = commandLineApi->Get(proper tyName);
1200
1201 Dart_Handle dartValue;
1202 if (propertyValue->IsFunction()) {
1203 dartValue = JsInterop::toDart(propertyValue);
1204 // We need to wrap the JsFunction object we get back
1205 // from the vanila JsInterop library so that users can
1206 // call it like a normal Dart function instead of
1207 // having to use the apply method.
1208 dartValue = Dart_Invoke(domData->jsLibrary(), Dart_NewString FromCString("_wrapAsDebuggerVarArgsFunction"), 1, &dartValue);
1209 } else {
1210 dartValue = JsInterop::toDart(propertyValue);
1211 }
1212 locals.append(V8Converter::stringToDart(propertyName));
1213 locals.append(dartValue);
1214 }
1215 }
1216 localVariables = DartUtilities::toList(locals, exception);
1217 ASSERT(!exception);
1218 }
1219
1220 Dart_Handle wrapExpressionArgs[2] = { expression, localVariables };
1221 Dart_Handle wrappedExpressionTuple =
1222 DartUtilities::invokeUtilsMethod("wrapExpressionAsClosure", 2, wrapExpre ssionArgs);
1223 ASSERT(Dart_IsList(wrappedExpressionTuple));
1224 Dart_Handle wrappedExpression = Dart_ListGetAt(wrappedExpressionTuple, 0);
1225 Dart_Handle wrappedExpressionArgs = Dart_ListGetAt(wrappedExpressionTuple, 1 );
1226
1227 ASSERT(Dart_IsString(wrappedExpression));
1228 Dart_Handle closure = Dart_EvaluateExpr(target, wrappedExpression);
1229 // There was a parse error. FIXME: consider cleaning up the line numbers in
1230 // the error message.
1231 if (Dart_IsError(closure))
1232 return V8ThrowException::throwException(v8::String::NewFromUtf8(v8Isolat e, Dart_GetError(closure)), v8::Isolate::GetCurrent());
1233
1234 // Invoke the closure passing in the expression arguments specified by
1235 // wrappedExpressionTuple.
1236 ASSERT(DartUtilities::isFunction(domData, closure));
1237 intptr_t length = 0;
1238 Dart_ListLength(wrappedExpressionArgs, &length);
1239 Vector<Dart_Handle> dartFunctionArgs;
1240 for (intptr_t i = 0; i < length; i ++)
1241 dartFunctionArgs.append(Dart_ListGetAt(wrappedExpressionArgs, i));
1242
1243 Dart_Handle result = Dart_InvokeClosure(closure, dartFunctionArgs.size(), da rtFunctionArgs.data());
1244 if (Dart_IsError(result))
1245 return V8ThrowException::throwException(v8::String::NewFromUtf8(v8Isolat e, Dart_GetError(result)), v8::Isolate::GetCurrent());
1246 return DartHandleProxy::create(result);
1247 }
1248
1249 }
OLDNEW
« no previous file with comments | « Source/bindings/core/dart/DartHandleProxy.h ('k') | Source/bindings/core/dart/DartInjectedScript.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698