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

Side by Side Diff: sky/engine/bindings-dart/core/dart/DartHandleProxy.cpp

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

Powered by Google App Engine
This is Rietveld 408576698