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

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

Issue 18169002: Improve Dart Debugger performance and robustness by creating Dart wrappers using the standard SetNa… (Closed) Base URL: svn://svn.chromium.org/multivm/trunk/webkit
Patch Set: Checkpoint Created 7 years, 5 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 | Annotate | Revision Log
« no previous file with comments | « Source/bindings/dart/DartHandleProxy.h ('k') | Source/bindings/dart/DartUtilities.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2012 Google Inc. All rights reserved. 2 * Copyright (C) 2012 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 10 matching lines...) Expand all
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 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. 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */ 29 */
30 #include "config.h" 30 #include "config.h"
31 #include "DartNode.h"
31 #include "bindings/dart/DartHandleProxy.h" 32 #include "bindings/dart/DartHandleProxy.h"
32
33 #include "bindings/dart/DartScriptValue.h" 33 #include "bindings/dart/DartScriptValue.h"
34 #include "bindings/dart/DartUtilities.h" 34 #include "bindings/dart/DartUtilities.h"
35 #include "bindings/dart/V8Converter.h" 35 #include "bindings/dart/V8Converter.h"
36 #include "bindings/v8/PageScriptDebugServer.h"
37 #include "bindings/v8/ScriptController.h"
38 #include "bindings/v8/ScriptState.h"
39 #include "bindings/v8/V8Binding.h"
40
41 #include "core/platform/Logging.h"
42
43 #include "wtf/StdLibExtras.h"
36 44
37 #include <dart_debugger_api.h> 45 #include <dart_debugger_api.h>
38 46
39 namespace WebCore { 47 namespace WebCore {
40 48
41 static v8::Persistent<v8::FunctionTemplate> proxyTemplate(); 49 typedef HashMap<String, v8::Persistent<v8::FunctionTemplate> > FunctionTemplateM ap;
42 50
43 static DartScriptValue* readPointerFromProxy(v8::Handle<v8::Value> proxy) 51 static v8::Persistent<v8::FunctionTemplate> objectProxyTemplate(Dart_Handle inst ance);
52 static v8::Persistent<v8::FunctionTemplate> functionProxyTemplate();
53 static v8::Persistent<v8::FunctionTemplate> libraryProxyTemplate();
54 static v8::Persistent<v8::FunctionTemplate> classProxyTemplate(Dart_Handle clazz );
55 static v8::Persistent<v8::FunctionTemplate> frameProxyTemplate();
56
57 DartScriptValue* readPointerFromProxy(v8::Handle<v8::Value> proxy)
44 { 58 {
45 void* pointer = proxy.As<v8::Object>()->GetAlignedPointerFromInternalField(0 ); 59 void* pointer = proxy.As<v8::Object>()->GetAlignedPointerFromInternalField(0 );
46 return static_cast<DartScriptValue*>(pointer); 60 return static_cast<DartScriptValue*>(pointer);
47 } 61 }
48 62
49 static void weakCallback(v8::Isolate* isolate, v8::Persistent<v8::Object>* proxy , void*) 63 static void weakCallback(v8::Isolate* isolate, v8::Persistent<v8::Object>* proxy , void*)
50 { 64 {
51 delete readPointerFromProxy(*proxy); 65 delete readPointerFromProxy(*proxy);
52 proxy->Dispose(isolate); 66 proxy->Dispose(isolate);
53 } 67 }
54 68
69 static Dart_Handle unwrapValue(v8::Handle<v8::Value> value)
70 {
71 if (DartHandleProxy::isDartProxy(value)) {
72 return Dart_HandleFromPersistent(readPointerFromProxy(value)->value());
73 }
74 Dart_Handle exception = 0;
75 Dart_Handle handle = V8Converter::toDart(value, exception);
76 ASSERT(!exception);
77 return handle;
78 }
79
80 bool libraryHasMember(Dart_Handle library, Dart_Handle name)
Jacob 2013/07/11 18:52:27 Requested Dart API: "LibraryHasMember" or somethin
81 {
82 return !Dart_IsError(Dart_GetField(library, name))
83 || !Dart_IsError(Dart_GetClass(library, name))
84 || Dart_IsFunction(Dart_LookupFunction(library, name));
85 }
86
87 bool classHasMember(Dart_Handle clazz, Dart_Handle name)
88 {
Jacob 2013/07/11 18:52:27 Requested Dart Api: "ClassHasMember" would be nice
89 return !Dart_IsError(Dart_GetField(clazz, name)) || Dart_IsFunction(Dart_Loo kupFunction(clazz, name));
90 }
91
92 Dart_Handle getEncodedMapKeyList(Dart_Handle object)
93 {
94 return DartUtilities::invokeUtilsMethod("getEncodedMapKeyList", 1, &object);
95 }
96
97 Dart_Handle stripTrailingDot(Dart_Handle str)
98 {
99 return DartUtilities::invokeUtilsMethod("stripTrailingDot", 1, &str);
100 }
101
102 Dart_Handle addTrailingDot(Dart_Handle str)
103 {
104 return DartUtilities::invokeUtilsMethod("addTrailingDot", 1, &str);
105 }
106
107 Dart_Handle lookupValueForEncodedMapKey(Dart_Handle object, Dart_Handle key)
108 {
109 Dart_Handle args[] = {object, key};
110 return DartUtilities::invokeUtilsMethod("lookupValueForEncodedMapKey", 2, ar gs);
111 }
112
113 Dart_Handle buildConstructorName(Dart_Handle className, Dart_Handle constructorN ame)
114 {
115 Dart_Handle args[] = {className, constructorName};
116 return DartUtilities::invokeUtilsMethod("buildConstructorName", 2, args);
117 }
118
119 Dart_Handle stripClassName(Dart_Handle str, Dart_Handle className)
120 {
121 Dart_Handle args[] = {str, className};
122 return DartUtilities::invokeUtilsMethod("stripClassName", 2, args);
123 }
124
125 Dart_Handle isNode(Dart_Handle clazz)
126 {
127 return DartUtilities::invokeUtilsMethod("isNode", 1, &clazz);
128 }
129
130 void addFunctionNames(Dart_Handle handle, v8::Local<v8::Array>& properties, intp tr_t* count, bool isInstance, bool noMethods)
131 {
132 intptr_t length = 0;
133 Dart_Handle functionNames = Dart_GetFunctionNames(handle);
134 ASSERT(!Dart_IsError(functionNames));
135 bool isLibrary = Dart_IsLibrary(handle);
136 Dart_ListLength(functionNames, &length);
137 for (intptr_t i = 0; i < length; i++) {
138 Dart_Handle functionName = Dart_ListGetAt(functionNames, i);
139 Dart_Handle function = Dart_LookupFunction(handle, functionName);
140 bool isStatic = false;
141 Dart_FunctionIsStatic(function, &isStatic);
142
143 bool isConstructor = false;
144 Dart_FunctionIsConstructor(function, &isConstructor);
145
146 if (!isLibrary) {
147 if (isInstance && (isStatic || isConstructor))
148 continue;
149
150 bool isSetter = false;
151 Dart_FunctionIsSetter(function, &isSetter);
152 bool isGetter = false;
153 Dart_FunctionIsGetter(function, &isGetter);
154
155 if (noMethods && !isSetter && !isGetter)
156 continue;
157
158 if (isInstance && (isSetter || isStatic || isConstructor))
159 continue;
160 }
161
162 // Strip off the leading classname from constructor name.
163 if (isConstructor)
Jacob 2013/07/11 18:52:27 Nit: why are constructor names prefixed with the c
164 functionName = stripClassName(functionName, Dart_ClassName(handle));
165
166 properties->Set(*count, V8Converter::stringToV8(functionName));
167 *count = *count + 1;
168 }
169 }
170
171 void addClassNames(Dart_Handle library, v8::Local<v8::Array>& properties, intptr _t* count)
172 {
173 intptr_t length = 0;
174 Dart_Handle classNames = Dart_LibraryGetClassNames(library);
175 ASSERT(!Dart_IsNull(classNames));
176 ASSERT(Dart_IsList(classNames));
177 Dart_ListLength(classNames, &length);
178 for (intptr_t i = 0; i < length; i++) {
179 Dart_Handle className = Dart_ListGetAt(classNames, i);
180 properties->Set(*count, V8Converter::stringToV8(className));
181 *count = *count + 1;
182 }
183 }
184
185 void addFieldNames(intptr_t libraryId, v8::Local<v8::Array>& properties, intptr_ t* count)
186 {
187 intptr_t length = 0;
188 Dart_Handle fieldNames = Dart_GetLibraryFields(libraryId);
189 ASSERT(!Dart_IsNull(fieldNames));
190 ASSERT(Dart_IsList(fieldNames));
191 Dart_ListLength(fieldNames, &length);
192 for (intptr_t i = 0; i < length; i+=2) {
193 Dart_Handle fieldName = Dart_ListGetAt(fieldNames, i);
194 properties->Set(*count, V8Converter::stringToV8(fieldName));
195 *count = *count + 1;
196 }
197 }
198
199 static v8::Handle<v8::Value> convertResult(Dart_Handle result)
200 {
201 if (Dart_IsError(result)) {
202 // FIXME: we would really prefer to call the following however it has
203 // bad unintended consequences as then JS cannot catch the thrown except ion.
204 // DartUtilities::reportProblem(DartUtilities::scriptExecutionContext(), result);
205 // return v8::Undefined();
206
207 return v8::ThrowException(v8::String::New(Dart_GetError(result)));
208 }
209 return DartHandleProxy::create(result);
210 }
211
212 void setDartHandleInternalField(v8::Local<v8::Object> proxy, Dart_Handle value)
213 {
214 proxy->SetAlignedPointerInInternalField(0, new DartScriptValue(value));
215 v8::Isolate* isolate = v8::Isolate::GetCurrent();
216 v8::Persistent<v8::Object> persistentHandle = v8::Persistent<v8::Object>::Ne w(isolate, proxy);
217 persistentHandle.MakeWeak<v8::Object, void>(0, &weakCallback);
218 }
219
220 intptr_t getLibraryId(v8::Local<v8::Object> proxy)
221 {
222 return (intptr_t)proxy.As<v8::Object>()->GetHiddenValue(v8::String::NewSymbo l("libraryId"))->Int32Value();
223 }
224
225 // Returns a String of the library prefix or Dart_Null if no prefix is found.
226 Dart_Handle getLibraryPrefix(v8::Local<v8::Object> proxy)
227 {
228 v8::Local<v8::Value> prefix = proxy.As<v8::Object>()->GetHiddenValue(v8::Str ing::NewSymbol("prefix"));
229 if (*prefix && prefix->IsString())
230 return V8Converter::stringToDart(prefix);
231 return Dart_Null();
232 }
233
234 static v8::Handle<v8::Value> functionNamedPropertyGetter(v8::Local<v8::String> n ame, const v8::AccessorInfo& info)
235 {
236 DartScriptValue* scriptValue = readPointerFromProxy(info.This());
237 ASSERT(scriptValue->isIsolateAlive());
238 DartIsolateScope scope(scriptValue->isolate());
239 DartApiScope apiScope;
240 Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value());
241
242 Dart_Handle ret;
243 ASSERT(Dart_IsFunction(handle) || Dart_IsClosure(handle));
244
245 ret = Dart_Invoke(handle, V8Converter::stringToDart(v8::String::Concat(v8::S tring::New("get:"), name)), 0, 0);
Jacob 2013/07/11 18:52:27 For classes, I can just call Dart_Invoke with the
246 if (Dart_IsError(ret) && name->Equals(v8::String::NewSymbol("__proto__")))
247 return v8::Undefined();
248
249 return convertResult(ret);
250 }
251
252 static v8::Handle<v8::Value> functionNamedPropertySetter(v8::Local<v8::String> p roperty, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
253 {
254 return throwError(v8ReferenceError, "Dart functions do not have writeable pr operties", v8::Isolate::GetCurrent());
255 }
256
257 static v8::Handle<v8::Value> functionInvocationCallback(v8::Arguments const& arg s)
258 {
259 DartScriptValue* scriptValue = readPointerFromProxy(args.Holder());
260 ASSERT(scriptValue->isIsolateAlive());
261 DartIsolateScope scope(scriptValue->isolate());
262 DartApiScope apiScope;
263 Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value());
264
265 ASSERT(Dart_IsFunction(handle) || Dart_IsClosure(handle));
266 bool isConstructor = false;
267 Dart_FunctionIsConstructor(handle, &isConstructor);
268 if (args.IsConstructCall() != isConstructor) {
269 return throwError(v8ReferenceError,
270 isConstructor ? "Constructor called without new" : "Regular function called as constructor",
271 v8::Isolate::GetCurrent());
272 }
273
274 Vector<Dart_Handle> dartFunctionArgs;
275 for (uint32_t i = 0; i < args.Length(); ++i)
276 dartFunctionArgs.append(unwrapValue(args[i]));
277
278 if (Dart_IsClosure(handle))
279 return convertResult(Dart_InvokeClosure(handle, dartFunctionArgs.size(), dartFunctionArgs.data()));
280 Dart_Handle clazz = Dart_FunctionOwner(handle);
281 if (isConstructor)
282 // FIXME: this seems like an overly complex way to have to invoke a cons tructor.
Jacob 2013/07/11 18:52:27 nit: this seems more complex than needed.
283 return convertResult(
284 Dart_New(clazz, stripClassName(Dart_FunctionName(handle), Dart_Class Name(clazz)),
285 dartFunctionArgs.size(), dartFunctionArgs.data()));
286 else
287 return convertResult(
288 Dart_Invoke(clazz, Dart_FunctionName(handle), dartFunctionArgs.size( ), dartFunctionArgs.data()));
289 }
290
291 static v8::Handle<v8::Value> classProxyConstructorInvocationCallback(v8::Argumen ts const& args)
292 {
293 DartScriptValue* scriptValue = readPointerFromProxy(args.Holder());
294 ASSERT(scriptValue->isIsolateAlive());
295 DartIsolateScope scope(scriptValue->isolate());
296 DartApiScope apiScope;
297 Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value());
298
299 ASSERT(Dart_IsClass(handle));
300
301 if (!args.IsConstructCall())
302 return throwError(v8SyntaxError, "Constructors can only be invoked with 'new'", v8::Isolate::GetCurrent());
303
304 Vector<Dart_Handle> dartFunctionArgs;
305 for (uint32_t i = 0; i < args.Length(); ++i)
306 dartFunctionArgs.append(unwrapValue(args[i]));
307
308 return convertResult(Dart_New(handle, Dart_Null(), dartFunctionArgs.size(), dartFunctionArgs.data()));
309 }
310
311 void getImportedLibrariesMatchingPrefix(int32_t libraryId, Dart_Handle prefix, V ector<std::pair<Dart_Handle, intptr_t> >* libraries)
Jacob 2013/07/11 18:52:27 It would be nice if I didn't have to do all this w
312 {
313 Dart_Handle imports = Dart_GetLibraryImports(libraryId);
314 ASSERT(!Dart_IsError(imports));
315 // Unfortunately dart_debugger_api.h adds a trailing dot to import prefixes.
316 if (!Dart_IsNull(prefix))
317 prefix = addTrailingDot(prefix);
318 intptr_t length = 0;
319 Dart_ListLength(imports, &length);
320 for (intptr_t i = 0; i < length; i += 2) {
321 Dart_Handle importPrefix = Dart_ListGetAt(imports, i);
322 ASSERT(Dart_IsNull(importPrefix) || Dart_IsString(importPrefix));
323 bool equals = false;
324 Dart_Handle result = Dart_ObjectEquals(prefix, importPrefix, &equals);
325 ASSERT(!Dart_IsError(result));
326 if (equals) {
327 Dart_Handle importedLibraryIdHandle = Dart_ListGetAt(imports, i + 1) ;
328 ASSERT(Dart_IsInteger(importedLibraryIdHandle));
329 int64_t importedLibraryId;
330 Dart_IntegerToInt64(importedLibraryIdHandle, &importedLibraryId);
331 Dart_Handle libraryURL = Dart_GetLibraryURL(importedLibraryId);
332 ASSERT(!Dart_IsError(libraryURL));
333 Dart_Handle library = Dart_LookupLibrary(libraryURL);
334 ASSERT(Dart_IsLibrary(library));
335 libraries->append(std::pair<Dart_Handle, intptr_t>(library, imported LibraryId));
336 }
337 }
338 }
339
340 static v8::Handle<v8::Value> libraryNamedPropertyGetterHelper(Dart_Handle librar y, Dart_Handle dartName, bool* handled)
341 {
Jacob 2013/07/11 18:52:27 would be nice if I could just call Dart_Invoke ins
342 Dart_Handle ret;
343 ret = Dart_GetField(library, dartName);
344 if (!Dart_IsApiError(ret)) {
345 *handled = true;
346 return convertResult(ret);
347 }
348
349 ret = Dart_GetClass(library, dartName);
350 if (!Dart_IsError(ret)) {
351 *handled = true;
352 return convertResult(ret);
353 }
354
355 ret = Dart_LookupFunction(library, dartName);
356 if (!Dart_IsNull(ret) && !Dart_IsError(ret)) {
Jacob 2013/07/15 18:03:26 why do i have a null check here?
357 *handled = true;
358 return convertResult(ret);
359 }
360 return v8::Undefined();
361 }
362
363 static v8::Handle<v8::Value> libraryNamedPropertyGetterHelper(v8::Local<v8::Stri ng> name,
364 const v8::AccessorInfo& info, bool* handled)
365 {
Jacob 2013/07/11 18:52:27 This is a mess due to handling prefixes. It would
366 DartScriptValue* scriptValue = readPointerFromProxy(info.This());
367 ASSERT(scriptValue->isIsolateAlive());
368 DartIsolateScope scope(scriptValue->isolate());
369 DartApiScope apiScope;
370 Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value());
371
372 Dart_Handle ret;
373 ASSERT(Dart_IsLibrary(handle));
374 intptr_t libraryId = getLibraryId(info.This());
375 Dart_Handle dartName = V8Converter::stringToDart(name);
376 Dart_Handle prefix = getLibraryPrefix(info.This());
377 bool hasLibraryPrefix = !Dart_IsNull(prefix) && Dart_IsString(prefix);
378
379 if (hasLibraryPrefix) {
380 Vector<std::pair<Dart_Handle, intptr_t> > libraries;
381 getImportedLibrariesMatchingPrefix(libraryId, prefix, &libraries);
382 for (size_t i = 0; i < libraries.size(); i++) {
383 v8::Handle<v8::Value> returnValue = libraryNamedPropertyGetterHelper (libraries[i].first, dartName, handled);
384 if (*handled)
385 return returnValue;
386 }
387 } else {
388 v8::Handle<v8::Value> returnValue = libraryNamedPropertyGetterHelper(han dle, dartName, handled);
389 if (*handled)
390 return returnValue;
391
392 // Check whether there is at least one library imported with the specifi ed prefix.
393 Vector<std::pair<Dart_Handle, intptr_t> > libraries;
394 getImportedLibrariesMatchingPrefix(libraryId, dartName, &libraries);
395 if (libraries.size() > 0) {
396 *handled = true;
397 return DartHandleProxy::createLibraryProxy(handle, libraryId, dartNa me);
398 }
399 }
400
401 if (name->Equals(v8::String::NewSymbol("__proto__"))) {
402 *handled = true;
403 return v8::Null();
404 }
405 return v8::Undefined();
406 }
407
408 static v8::Handle<v8::Value> libraryNamedPropertyGetter(v8::Local<v8::String> na me, const v8::AccessorInfo& info)
409 {
410 bool handled = false;
411 v8::Handle<v8::Value> ret = libraryNamedPropertyGetterHelper(name, info, &ha ndled);
412 if (handled)
413 return ret;
414 return v8::ThrowException(v8::Exception::ReferenceError(v8::String::Concat(n ame, v8::String::New(" is not defined"))));
415 }
416
417 // TODO(jacobr): need to handle prefixes in this case as well.
418 // Before checkin, handle prefixes correctly.
419 static v8::Handle<v8::Value> libraryNamedPropertySetter(v8::Local<v8::String> pr operty, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
420 {
421 DartScriptValue* scriptValue = readPointerFromProxy(info.This());
422 ASSERT(scriptValue->isIsolateAlive());
423 DartIsolateScope scope(scriptValue->isolate());
424 DartApiScope apiScope;
425 Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value());
426
427 Dart_Handle ret;
428 ASSERT(Dart_IsLibrary(handle));
429 Dart_Handle dartValue = unwrapValue(value);
430 ret = Dart_SetField(handle, V8Converter::stringToDart(property), dartValue);
431 return convertResult(ret);
432 }
433
434 static v8::Handle<v8::Integer> libraryQueryProperty(v8::Local<v8::String> name, const v8::AccessorInfo& info)
435 {
436 bool handled = false;
437 libraryNamedPropertyGetterHelper(name, info, &handled);
438 return handled ? v8Integer(0, info.GetIsolate()) : v8::Handle<v8::Integer>() ;
439 }
440
441 void libraryEnumerateHelper(Dart_Handle library, intptr_t libraryId, v8::Local<v 8::Array> properties, intptr_t* count)
442 {
443 addFunctionNames(library, properties, count, false, false);
444 addClassNames(library, properties, count);
445 addFieldNames(libraryId, properties, count);
446 }
447
448 static v8::Handle<v8::Array> libraryPropertyEnumerator(const v8::AccessorInfo& i nfo)
449 {
Jacob 2013/07/11 18:52:27 It would be nice if Dart libraries provided a meth
450 DartScriptValue* scriptValue = readPointerFromProxy(info.This());
451 ASSERT(scriptValue->isIsolateAlive());
452 DartIsolateScope scope(scriptValue->isolate());
453 DartApiScope apiScope;
454 Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value());
455
456 intptr_t libraryId = getLibraryId(info.This());
457 ASSERT(Dart_IsLibrary(handle));
458 v8::Local<v8::Array> cachedProperties = info.This().As<v8::Object>()->GetHid denValue(v8::String::NewSymbol("cache")).As<v8::Array>();
459 if (*cachedProperties)
460 return cachedProperties;
461
462 Dart_Handle prefix = getLibraryPrefix(info.This());
463 bool hasLibraryPrefix = Dart_IsString(prefix);
464
465 v8::Local<v8::Array> properties = v8::Array::New();
466 intptr_t count = 0;
467
468 if (hasLibraryPrefix) {
469 Vector<std::pair<Dart_Handle, intptr_t> > libraries;
470 getImportedLibrariesMatchingPrefix(libraryId, prefix, &libraries);
471 for (intptr_t i = 0; i < libraries.size(); i++)
472 libraryEnumerateHelper(libraries[i].first, libraries[i].second, prop erties, &count);
473 } else {
474 libraryEnumerateHelper(handle, libraryId, properties, &count);
475 // Add all library prefixes of imports to the library.
476 Dart_Handle imports = Dart_GetLibraryImports(libraryId);
477 ASSERT(!Dart_IsError(imports));
478 intptr_t length = 0;
479 Dart_ListLength(imports, &length);
480 for (intptr_t i = 0; i < length; i += 2) {
481 Dart_Handle importPrefix = Dart_ListGetAt(imports, i);
482 if (!Dart_IsNull(importPrefix)) {
483 ASSERT(Dart_IsString(importPrefix));
484 properties->Set(count, V8Converter::stringToV8(
485 stripTrailingDot(importPrefix)));
486 count++;
487 }
488 bool equals = false;
489 }
490 }
491 info.This()->SetHiddenValue(v8::String::NewSymbol("cache"), properties);
492 return properties;
493 }
494
495 static v8::Handle<v8::Value> classNamedPropertyGetter(v8::Local<v8::String> name , const v8::AccessorInfo& info)
496 {
497 DartScriptValue* scriptValue = readPointerFromProxy(info.This());
498 ASSERT(scriptValue->isIsolateAlive());
499 DartIsolateScope scope(scriptValue->isolate());
500 DartApiScope apiScope;
501 Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value());
502
503 Dart_Handle ret;
504 ASSERT(Dart_IsClass(handle));
505 // XXX hack... remove... FILE A BUG!
506 bool isDynamic = false;
Jacob 2013/07/11 18:52:27 What should we do about the class "dynamic". It ex
507 Dart_ObjectEquals(Dart_ClassName(handle), Dart_NewStringFromCString("dynamic "), &isDynamic);
508
509 if (!Dart_ClassIsTypedef(handle) && !Dart_ClassIsFunctionType(handle) && !is Dynamic) {
Jacob 2013/07/11 18:52:27 Similarly to the case of Library, it would be nice
510
511 Dart_Handle dartName = V8Converter::stringToDart(name);
512 ret = Dart_GetField(handle, dartName);
513 if (!Dart_IsError(ret))
514 return convertResult(ret);
515 ret = Dart_LookupFunction(handle, dartName);
516 if (!Dart_IsNull(ret) && !Dart_IsError(ret))
517 return convertResult(ret);
518
519 Dart_Handle className = Dart_ClassName(handle);
520 ASSERT(Dart_IsString(className));
521 Dart_Handle constructorName = buildConstructorName(className, V8Converte r::stringToDart(name));
522 ret = Dart_LookupFunction(handle, constructorName);
523 if (!Dart_IsNull(ret) && !Dart_IsError(ret))
524 return convertResult(ret);
525 }
526
527 if (name->Equals(v8::String::NewSymbol("__proto__"))) {
528 Dart_Handle superclass = Dart_GetSuperclass(handle);
529 if (!Dart_IsError(superclass))
530 return DartHandleProxy::create(superclass);
531 return v8::Undefined();
532 }
533 return v8::ThrowException(v8::Exception::ReferenceError(v8::String::Concat(n ame, v8::String::New(" is not defined"))));
534 }
535
536 static v8::Handle<v8::Value> classNamedPropertySetter(v8::Local<v8::String> prop erty, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
537 {
538 DartScriptValue* scriptValue = readPointerFromProxy(info.This());
539 ASSERT(scriptValue->isIsolateAlive());
540 DartIsolateScope scope(scriptValue->isolate());
541 DartApiScope apiScope;
542 Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value());
543
544 Dart_Handle ret;
545 ASSERT(Dart_IsClass(handle));
546 Dart_Handle dartValue = unwrapValue(value);
547 ret = Dart_Invoke(handle, V8Converter::stringToDart(v8::String::Concat(v8::S tring::New("set:"), property)), 1, &dartValue);
Jacob 2013/07/11 18:52:27 TODO(jacobr): similar to the case of Libraries, th
548 return convertResult(ret);
549 }
550
551 static v8::Handle<v8::Integer> classQueryProperty(v8::Local<v8::String> name, co nst v8::AccessorInfo& info)
552 {
553 DartScriptValue* scriptValue = readPointerFromProxy(info.This());
554 ASSERT(scriptValue->isIsolateAlive());
555 DartIsolateScope scope(scriptValue->isolate());
556 DartApiScope apiScope;
557 Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value());
558
559 Dart_Handle ret;
560 ASSERT(Dart_IsClass(handle));
561 if (classHasMember(handle, V8Converter::stringToDart(name)))
562 return v8Integer(0, info.GetIsolate());
563 return v8::Handle<v8::Integer>();
564 }
565
566 static v8::Handle<v8::Array> classPropertyEnumerator(const v8::AccessorInfo& inf o)
567 {
568 DartScriptValue* scriptValue = readPointerFromProxy(info.This());
569 ASSERT(scriptValue->isIsolateAlive());
570 DartIsolateScope scope(scriptValue->isolate());
571 DartApiScope apiScope;
572 Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value());
573
574 ASSERT(Dart_IsClass(handle));
575
576 v8::Local<v8::Array> properties = v8::Array::New();
577 intptr_t count = 0;
578 addFunctionNames(handle, properties, &count, false, false);
Jacob 2013/07/11 18:52:27 it would be nice if there was just an Dart API met
579 return properties;
580 }
581
582 // Returns the index in the list of the property if it is found, -1 otherwise.
583 static int findMatchingNamedProperty(Dart_Handle list, v8::Local<v8::String> nam e)
584 {
585 // FIXME: perhaps push this logic into Dart code instead.
586 v8::String::Utf8Value stringValue(name);
587 const char* nameData = *stringValue;
588 intptr_t nameLength = stringValue.length();
589
590 intptr_t length = 0;
591 Dart_ListLength(list, &length);
592 for (intptr_t i = 0; i < length; i += 2) {
593 intptr_t candidateNameLength = 0;
594 uint8_t* candidateData = 0;
595 intptr_t candidateLength = 0;
596 Dart_StringToUTF8(Dart_ListGetAt(list, i), &candidateData, &candidateLen gth);
597 if ((candidateLength >= nameLength
598 && (candidateLength == nameLength || candidateData[nameLength] == '@ '))
599 && !memcmp(candidateData, nameData, nameLength))
600 return i / 2;
601 }
602 return -1;
603 }
604
605 static v8::Handle<v8::Value> frameNamedPropertyGetter(v8::Local<v8::String> name , const v8::AccessorInfo& info)
606 {
Jacob 2013/07/11 18:52:27 It would be nice if the local frame was just expos
607 DartScriptValue* scriptValue = readPointerFromProxy(info.This());
608 ASSERT(scriptValue->isIsolateAlive());
609 DartIsolateScope scope(scriptValue->isolate());
610 DartApiScope apiScope;
611 Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value());
612
613 ASSERT(Dart_IsList(handle));
614 int index = findMatchingNamedProperty(handle, name);
615 if (index != -1)
616 return convertResult(Dart_ListGetAt(handle, index * 2 + 1));
617 if (name->Equals(v8::String::NewSymbol("this")))
618 return v8::Undefined();
619 return v8::ThrowException(v8::Exception::ReferenceError(v8::String::Concat(n ame, v8::String::New(" is not defined"))));
620 }
621
622 static v8::Handle<v8::Value> frameNamedPropertySetter(v8::Local<v8::String> prop erty, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
623 {
Jacob 2013/07/11 18:52:27 This is the one case where we can't manipulate Dat
624 return throwError(v8ReferenceError, "Dart does not yet provide a debugger ap i for setting local fields", v8::Isolate::GetCurrent());
625 }
626
627 static v8::Handle<v8::Integer> frameQueryProperty(v8::Local<v8::String> name, co nst v8::AccessorInfo& info)
628 {
629 DartScriptValue* scriptValue = readPointerFromProxy(info.This());
630 ASSERT(scriptValue->isIsolateAlive());
631 DartIsolateScope scope(scriptValue->isolate());
632 DartApiScope apiScope;
633 Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value());
634
635 ASSERT(Dart_IsList(handle));
636 int index = findMatchingNamedProperty(handle, name);
637 return index == -1 ? v8::Handle<v8::Integer>() : v8Integer(0, info.GetIsolat e());
638 }
639
640 static v8::Handle<v8::Array> framePropertyEnumerator(const v8::AccessorInfo& inf o)
641 {
642 DartScriptValue* scriptValue = readPointerFromProxy(info.This());
643 ASSERT(scriptValue->isIsolateAlive());
644 DartIsolateScope scope(scriptValue->isolate());
645 DartApiScope apiScope;
646 Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value());
647
648 ASSERT(Dart_IsList(handle));
649
650 intptr_t length = 0;
651 Dart_ListLength(handle, &length);
652 v8::Local<v8::Array> properties = v8::Array::New(length / 2);
653 for (intptr_t i = 0; i < length; i += 2) {
654 // Truncate everything after the '@'.
Jacob 2013/07/11 18:52:27 it would be nice if there was an option to get nam
655 // TODO(jacobr): we shouldn't have to do this, there should be an API th at provides
656 // Mirror APIs on frames directly.
657 const char* nameData = 0;
658 Dart_StringToCString(Dart_ListGetAt(handle, i), &nameData);
659 ASSERT(nameData);
660 if (!nameData)
661 continue;
662
663 intptr_t nameLength = strlen(nameData);
664
665 for (intptr_t j = 0; j < nameLength; j++) {
666 if (nameData[j] == '@') {
667 nameLength = j;
668 break;
669 }
670 }
671 properties->Set(i / 2, v8::String::New(nameData, nameLength));
672 }
673 return properties;
674 }
675
676 static v8::Handle<v8::Value> namedPropertyGetter(v8::Local<v8::String> name, con st v8::AccessorInfo& info)
677 {
678 DartScriptValue* scriptValue = readPointerFromProxy(info.This());
679 ASSERT(scriptValue->isIsolateAlive());
680 DartIsolateScope scope(scriptValue->isolate());
681 DartApiScope apiScope;
682 Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value());
683
684 Dart_Handle ret;
685 ASSERT(Dart_IsInstance(handle));
686 v8::String::Utf8Value stringName(name);
687 const char* data = *stringName;
688 if (data[0] == ':' || data[0] == '#') {
689 // Look up a map key instead of a regular property as regular dart prope rty names
690 // cannot start with these symbols.
691 return convertResult(
692 lookupValueForEncodedMapKey(handle, V8Converter::stringToDart(name)) );
693 }
694
695 ret = Dart_Invoke(handle, V8Converter::stringToDart(v8::String::Concat(v8::S tring::New("get:"), name)), 0, 0);
696 if (Dart_IsError(ret) && name->Equals(v8::String::NewSymbol("__proto__")))
697 return DartHandleProxy::create(Dart_GetObjClass(handle));
698
699 return convertResult(ret);
700 }
701
702 static v8::Handle<v8::Value> namedPropertySetter(v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
703 {
704 DartScriptValue* scriptValue = readPointerFromProxy(info.This());
705 ASSERT(scriptValue->isIsolateAlive());
706 DartIsolateScope scope(scriptValue->isolate());
707 DartApiScope apiScope;
708 Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value());
709
710 Dart_Handle ret;
711 Dart_Handle dartValue = unwrapValue(value);
712 ret = Dart_Invoke(handle, V8Converter::stringToDart(v8::String::Concat(v8::S tring::New("set:"), property)), 1, &dartValue);
713 if (Dart_IsError(ret)) {
714 Dart_Handle dartPropertyName = V8Converter::stringToDart(property);
715 Dart_Handle indexedGetterOperator = Dart_NewStringFromCString("[]=");
716 Dart_Handle args[] = {dartPropertyName, dartValue};
717 ret = Dart_Invoke(handle, indexedGetterOperator, 2, args);
718 }
719 return convertResult(ret);
720 }
721
722 // FIXME: duplicated code with getter. XXX
723 static v8::Handle<v8::Integer> objectQueryProperty(v8::Local<v8::String> name, c onst v8::AccessorInfo& info)
724 {
725 DartScriptValue* scriptValue = readPointerFromProxy(info.This());
726 ASSERT(scriptValue->isIsolateAlive());
727 DartIsolateScope scope(scriptValue->isolate());
728 DartApiScope apiScope;
729 Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value());
730
731 Dart_Handle ret;
732 ASSERT(Dart_IsInstance(handle));
733 v8::String::Utf8Value stringName(name);
734 const char* data = *stringName;
735
736 // Looking up a map key instead of a regular property... as regular dart pro perty names
737 // cannot start with these symbols.
738 if (data[0] == ':' || data[0] == '#')
739 return v8Integer(0, info.GetIsolate());
740
741 ret = Dart_Invoke(handle, V8Converter::stringToDart(v8::String::Concat(v8::S tring::New("get:"), name)), 0, 0);
742 if (Dart_IsError(ret)) {
743 if (name->Equals(v8::String::NewSymbol("__proto__")))
744 return v8Integer(0, info.GetIsolate());
745 return v8::Handle<v8::Integer>();
746 }
747 return v8Integer(0, info.GetIsolate());
748 }
749
750 static v8::Handle<v8::Array> objectPropertyEnumerator(const v8::AccessorInfo& in fo)
751 {
752 DartScriptValue* scriptValue = readPointerFromProxy(info.This());
753 ASSERT(scriptValue->isIsolateAlive());
754 DartIsolateScope scope(scriptValue->isolate());
755 DartApiScope apiScope;
756 Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value());
757
758 ASSERT(Dart_IsInstance(handle));
759
760 Dart_Handle typeHandle;
761 if (Dart_IsInstance(handle))
762 typeHandle = Dart_InstanceGetClass(handle);
763 else
764 typeHandle = handle;
765
766 v8::Local<v8::Array> properties = v8::Array::New();
767 intptr_t count = 0;
768
769 Dart_Handle mapKeys = getEncodedMapKeyList(handle);
770 if (Dart_IsList(mapKeys)) {
771 // If the object has map keys, add them all as properties at the start
772 // of the list. This aids for debugging although it risks confusing
773 // users.
774 intptr_t length = 0;
775 Dart_ListLength(mapKeys, &length);
776 for (intptr_t i = 0; i < length; i++) {
777 properties->Set(count, V8Converter::stringToV8(Dart_ListGetAt(mapKey s, i)));
778 count++;
779 }
780 }
781
782 Dart_Handle instanceFields = Dart_GetInstanceFields(handle);
783 intptr_t length = 0;
784 Dart_ListLength(instanceFields, &length);
785 for (intptr_t i = 0; i < length; i += 2) {
786 properties->Set(count, DartHandleProxy::create(
787 Dart_ListGetAt(instanceFields, i)));
788 count++;
789 }
790
791 while (!Dart_IsError(typeHandle) && !Dart_IsNull(typeHandle)) {
792 intptr_t interfaceCount = 0;
793 Dart_ClassGetInterfaceCount(typeHandle, &interfaceCount);
794 for (intptr_t i = 0; i < interfaceCount; i++) {
795 addFunctionNames(Dart_ClassGetInterfaceAt(typeHandle, i),
796 properties, &count, true, true);
797 }
798 // TODO(jacobr): is this duplicated work?
799 addFunctionNames(typeHandle, properties, &count, true, true);
800 typeHandle = Dart_GetSuperclass(typeHandle);
801 }
802 return properties;
803 }
804
805 static v8::Handle<v8::Value> indexedGetter(uint32_t index, const v8::AccessorInf o& info)
806 {
807 DartScriptValue* scriptValue = readPointerFromProxy(info.This());
808 ASSERT(scriptValue->isIsolateAlive());
809 DartIsolateScope scope(scriptValue->isolate());
810 DartApiScope apiScope;
811 Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value());
812
813 Dart_Handle ret = 0;
814 if (Dart_IsList(handle))
815 ret = Dart_ListGetAt(handle, index);
816 else
817 ret = Dart_Null();
818
819 return convertResult(ret);
820 }
821
822 static v8::Handle<v8::Value> indexedSetter(uint32_t index, v8::Local<v8::Value> value, const v8::AccessorInfo& info)
823 {
824 DartScriptValue* scriptValue = readPointerFromProxy(info.This());
825 ASSERT(scriptValue->isIsolateAlive());
826 DartIsolateScope scope(scriptValue->isolate());
827 DartApiScope apiScope;
828 Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value());
829
830 Dart_Handle ret = 0;
831 if (Dart_IsList(handle))
832 ret = Dart_ListSetAt(handle, index, unwrapValue(value));
833 else
834 ret = Dart_Null();
835
836 return convertResult(ret);
837 }
838
839 static v8::Handle<v8::Array> indexedEnumerator(const v8::AccessorInfo& info)
840 {
841 DartScriptValue* scriptValue = readPointerFromProxy(info.This());
842 ASSERT(scriptValue->isIsolateAlive());
843 DartIsolateScope scope(scriptValue->isolate());
844 DartApiScope apiScope;
845 Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value());
846
847 intptr_t length = 0;
848 if (Dart_IsList(handle))
849 Dart_ListLength(handle, &length);
850
851 v8::Local<v8::Array> indexes = v8::Array::New(length);
852 for (int i = 0; i < length; i++)
853 indexes->Set(i, v8::Integer::New(i));
854
855 return indexes;
856 }
857
858 static v8::Local<v8::ObjectTemplate> setupInstanceTemplate(v8::Persistent<v8::Fu nctionTemplate> proxyTemplate)
859 {
860 v8::Local<v8::ObjectTemplate> instanceTemplate = proxyTemplate->InstanceTemp late();
861 instanceTemplate->SetInternalFieldCount(1);
862 return instanceTemplate;
863 }
864
865 static v8::Persistent<v8::FunctionTemplate> objectProxyTemplate(Dart_Handle inst ance)
866 {
867 DEFINE_STATIC_LOCAL(FunctionTemplateMap, map, ());
868 // FIXME: we should switch to Dart_InstanceGetType when possible.
869 Dart_Handle dartType = Dart_InstanceGetClass(instance);
870 ASSERT(!Dart_IsError(dartType));
871 Dart_Handle classNameHandle = Dart_ClassName(dartType);
872 ASSERT(!Dart_IsError(classNameHandle));
873 if (Dart_IsError(classNameHandle))
874 classNameHandle = Dart_NewStringFromCString("MYSTERY DART CLAZZ XXX");
875 ASSERT(!Dart_IsError(classNameHandle));
876 v8::Handle<v8::String> classNameV8 = V8Converter::stringToV8(classNameHandle );
877 String className = toWebCoreString(classNameV8);
878 v8::Persistent<v8::FunctionTemplate> proxyTemplate = map.get(className);
879
880 if (proxyTemplate.IsEmpty()) {
881 proxyTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::Isolate::G etCurrent(), v8::FunctionTemplate::New());
882 proxyTemplate->SetClassName(classNameV8);
883 map.set(className, proxyTemplate);
884 v8::Local<v8::ObjectTemplate> instanceTemplate = setupInstanceTemplate(p roxyTemplate);
885 instanceTemplate->SetIndexedPropertyHandler(&indexedGetter, &indexedSett er, 0, 0, &indexedEnumerator);
886 instanceTemplate->SetNamedPropertyHandler(&namedPropertyGetter, &namedPr opertySetter, &objectQueryProperty, 0, &objectPropertyEnumerator);
887 }
888 return proxyTemplate;
889 }
890
891 static v8::Persistent<v8::FunctionTemplate> functionProxyTemplate()
892 {
893 static v8::Persistent<v8::FunctionTemplate> proxyTemplate;
894 if (proxyTemplate.IsEmpty()) {
895 proxyTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::Isolate::G etCurrent(), v8::FunctionTemplate::New());
896 proxyTemplate->SetClassName(v8::String::New("[Dart Function]"));
897 v8::Local<v8::ObjectTemplate> instanceTemplate = setupInstanceTemplate(p roxyTemplate);
898 instanceTemplate->SetNamedPropertyHandler(&functionNamedPropertyGetter, &functionNamedPropertySetter);
899 instanceTemplate->SetCallAsFunctionHandler(&functionInvocationCallback);
900 }
901 return proxyTemplate;
902 }
903
904 static v8::Persistent<v8::FunctionTemplate> libraryProxyTemplate()
905 {
906 static v8::Persistent<v8::FunctionTemplate> proxyTemplate;
907 if (proxyTemplate.IsEmpty()) {
908 proxyTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::Isolate::G etCurrent(), v8::FunctionTemplate::New());
909 proxyTemplate->SetClassName(v8::String::New("[Dart Library]"));
910 v8::Local<v8::ObjectTemplate> instanceTemplate = setupInstanceTemplate(p roxyTemplate);
911 instanceTemplate->SetNamedPropertyHandler(&libraryNamedPropertyGetter, & libraryNamedPropertySetter, &libraryQueryProperty, 0, &libraryPropertyEnumerator );
912 }
913 return proxyTemplate;
914 }
915
916 static v8::Persistent<v8::FunctionTemplate> classProxyTemplate(Dart_Handle clazz )
917 {
918 DEFINE_STATIC_LOCAL(FunctionTemplateMap, map, ());
919 Dart_Handle classNameHandle = Dart_ClassName(clazz);
920 ASSERT(!Dart_IsError(classNameHandle));
921 v8::Handle<v8::String> classNameV8 = V8Converter::stringToV8(classNameHandle );
922 String className = toWebCoreString(classNameV8);
923
924 v8::Persistent<v8::FunctionTemplate> proxyTemplate = map.get(className);
925 if (proxyTemplate.IsEmpty()) {
926 proxyTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::Isolate::G etCurrent(), v8::FunctionTemplate::New());
927 proxyTemplate->SetClassName(classNameV8);
928 v8::Local<v8::ObjectTemplate> instanceTemplate = setupInstanceTemplate(p roxyTemplate);
929 instanceTemplate->SetNamedPropertyHandler(&classNamedPropertyGetter, &cl assNamedPropertySetter, &classQueryProperty, 0, &classPropertyEnumerator);
930 instanceTemplate->SetCallAsFunctionHandler(&classProxyConstructorInvocat ionCallback);
931 map.set(className, proxyTemplate);
932 }
933 return proxyTemplate;
934 }
935
936 static v8::Persistent<v8::FunctionTemplate> frameProxyTemplate()
937 {
938 static v8::Persistent<v8::FunctionTemplate> proxyTemplate;
939 if (proxyTemplate.IsEmpty()) {
940 proxyTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::Isolate::G etCurrent(), v8::FunctionTemplate::New());
941 proxyTemplate->SetClassName(v8::String::New("[Dart Frame]"));
942 v8::Local<v8::ObjectTemplate> instanceTemplate = setupInstanceTemplate(p roxyTemplate);
943 instanceTemplate->SetNamedPropertyHandler(&frameNamedPropertyGetter, &fr ameNamedPropertySetter, &frameQueryProperty, 0, &framePropertyEnumerator);
944 }
945 return proxyTemplate;
946 }
947
55 v8::Handle<v8::Value> DartHandleProxy::create(Dart_Handle value) 948 v8::Handle<v8::Value> DartHandleProxy::create(Dart_Handle value)
56 { 949 {
57 v8::Context::Scope scope(DartUtilities::currentV8Context()); 950 v8::Context::Scope scope(DartUtilities::currentV8Context());
58 951
59 if (Dart_IsNull(value)) 952 if (Dart_IsNull(value))
60 return v8::Null(); 953 return v8::Null();
61 if (Dart_IsString(value)) 954 if (Dart_IsString(value))
62 return V8Converter::stringToV8(value); 955 return V8Converter::stringToV8(value);
63 if (Dart_IsBoolean(value)) 956 if (Dart_IsBoolean(value))
64 return V8Converter::booleanToV8(value); 957 return V8Converter::booleanToV8(value);
65 if (Dart_IsNumber(value)) 958 if (Dart_IsNumber(value))
66 return V8Converter::numberToV8(value); 959 return V8Converter::numberToV8(value);
67 960 v8::Local<v8::Object> proxy;
68 v8::Local<v8::Object> proxy = proxyTemplate()->InstanceTemplate()->NewInstan ce(); 961 // TODO(jacobr): could optimize the order of these checks.
69 proxy->SetAlignedPointerInInternalField(0, new DartScriptValue(value)); 962 if (Dart_IsFunction(value) || Dart_IsClosure(value))
70 v8::Isolate* isolate = v8::Isolate::GetCurrent(); 963 proxy = functionProxyTemplate()->InstanceTemplate()->NewInstance();
71 v8::Persistent<v8::Object> persistentHandle = v8::Persistent<v8::Object>::Ne w(isolate, proxy); 964 else if (Dart_IsInstance(value))
72 persistentHandle.MakeWeak<v8::Object, void>(0, &weakCallback); 965 proxy = objectProxyTemplate(value)->InstanceTemplate()->NewInstance();
73 proxy->Set(v8::String::New("isProxy"), v8::Boolean::New(true)); 966 else {
967 ASSERT(Dart_IsClass(value));
968 proxy = classProxyTemplate(value)->InstanceTemplate()->NewInstance();
969 }
970 setDartHandleInternalField(proxy, value);
971 proxy->SetHiddenValue(v8::String::NewSymbol("dartProxy"), v8::Boolean::New(t rue));
972
74 return proxy; 973 return proxy;
75 } 974 }
76 975
77 v8::Handle<v8::Value> DartHandleProxy::createForLibrary(intptr_t libraryId) 976 bool DartHandleProxy::isDartProxy(v8::Handle<v8::Value> value)
78 { 977 {
79 Dart_Handle libraryURL = Dart_GetLibraryURL(libraryId); 978 if (value->IsObject()) {
80 ASSERT(!Dart_IsError(libraryURL)); 979 v8::Local<v8::Value> hiddenValue = value.As<v8::Object>()->GetHiddenValu e(v8::String::NewSymbol("dartProxy"));
81 Dart_Handle library = Dart_LookupLibrary(libraryURL); 980 return *hiddenValue && hiddenValue->IsBoolean();
82 v8::Handle<v8::Object> libraryProxy = create(library)->ToObject(); 981 }
83 libraryProxy->SetHiddenValue(v8::String::New("libraryId"), v8::Number::New(l ibraryId)); 982 return false;
84 return libraryProxy; 983 }
85 } 984
86 985 const char* DartHandleProxy::getType(v8::Handle<v8::Value> value) {
87 class DartReceiverScope { 986 DartScriptValue* scriptValue = readPointerFromProxy(value);
88 public: 987 ASSERT(scriptValue->isIsolateAlive());
89 DartReceiverScope(const v8::Arguments& args) 988 DartIsolateScope scope(scriptValue->isolate());
90 : m_receiver(readPointerFromProxy(args[0])) 989 DartApiScope apiScope;
91 , m_isolateScope(m_receiver->isolate()) 990 Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value());
92 , m_apiScope() 991
93 { 992 if (Dart_IsInstance(handle)) {
94 } 993 if (Dart_IsList(handle))
95 994 return "array";
96 Dart_Handle receiver() { return Dart_HandleFromPersistent(m_receiver->value( )); } 995
97 996 Dart_Handle exception = 0;
98 private: 997 if (DartUtilities::dartToBool(isNode(handle), exception))
99 DartScriptValue* m_receiver; 998 return "node";
100 DartIsolateScope m_isolateScope; 999 ASSERT(!exception);
101 DartApiScope m_apiScope; 1000 }
102 }; 1001
103 1002 return 0;
104 static v8::Persistent<v8::FunctionTemplate> proxyTemplate() 1003 }
105 { 1004
106 static v8::Persistent<v8::FunctionTemplate> proxyTemplate; 1005 Node* DartHandleProxy::toNativeNode(v8::Handle<v8::Value> value) {
107 if (proxyTemplate.IsEmpty()) { 1006 DartScriptValue* scriptValue = readPointerFromProxy(value);
108 proxyTemplate = v8::Persistent<v8::FunctionTemplate>::New(v8::Isolate::G etCurrent(), v8::FunctionTemplate::New()); 1007 ASSERT(scriptValue->isIsolateAlive());
109 v8::Local<v8::ObjectTemplate> instanceTemplate = proxyTemplate->Instance Template(); 1008 DartIsolateScope scope(scriptValue->isolate());
110 instanceTemplate->SetInternalFieldCount(1); 1009 DartApiScope apiScope;
111 } 1010 Dart_Handle handle = Dart_HandleFromPersistent(scriptValue->value());
112 return proxyTemplate;
113 }
114
115 static Dart_Handle unwrapValue(v8::Handle<v8::Value> value)
116 {
117 if (proxyTemplate()->HasInstance(value))
118 return Dart_HandleFromPersistent(readPointerFromProxy(value)->value());
119 Dart_Handle exception = 0; 1011 Dart_Handle exception = 0;
120 Dart_Handle handle = V8Converter::toDart(value, exception); 1012 Node* node = DartNode::toNative(handle, exception);
121 ASSERT(!exception); 1013 ASSERT(!exception);
122 return handle; 1014 return node;
123 } 1015 }
124 1016
125 static v8::Handle<v8::Value> convertResult(Dart_Handle result) 1017 /**
126 { 1018 * Creates a proxy for a Dart library.
127 if (Dart_IsError(result)) { 1019 * If a string prefix is specified, we similuate that all requests to the librar y start with
128 // Consider wrapping not as a string, but as dedicated 1020 * the specified prefix.
129 // exception wrapper. 1021 */
130 return v8::String::New("<Exception thrown>"); 1022 v8::Handle<v8::Value> DartHandleProxy::createLibraryProxy(Dart_Handle value, int 32_t libraryId, Dart_Handle prefix)
131 } 1023 {
Jacob 2013/07/11 18:52:27 why do I have to keep around both a handle to a li
132 return DartHandleProxy::create(result); 1024 v8::Context::Scope scope(DartUtilities::currentV8Context());
133 } 1025 ASSERT(Dart_IsLibrary(value));
134 1026 v8::Local<v8::Object> proxy = libraryProxyTemplate()->InstanceTemplate()->Ne wInstance();
135 // --- Objects ---- 1027 setDartHandleInternalField(proxy, value);
136 1028 proxy->SetHiddenValue(v8::String::NewSymbol("libraryId"), v8::Number::New(li braryId));
137 static v8::Handle<v8::Value> instanceGetClass(const v8::Arguments& args) 1029 if (Dart_IsString(prefix))
138 { 1030 proxy->SetHiddenValue(v8::String::NewSymbol("prefix"), V8Converter::stri ngToV8(prefix));
139 DartReceiverScope scope(args); 1031
140 return convertResult(Dart_InstanceGetClass(scope.receiver())); 1032 proxy->SetHiddenValue(v8::String::NewSymbol("dartProxy"), v8::Boolean::New(t rue));
141 } 1033 return proxy;
142 1034 }
143 // --- Lists --- 1035
144 1036 v8::Handle<v8::Value> DartHandleProxy::createLocalScopeProxy(Dart_Handle localVa riables)
145 static v8::Handle<v8::Value> isList(const v8::Arguments& args) 1037 {
146 { 1038 v8::Local<v8::Object> proxy = frameProxyTemplate()->InstanceTemplate()->NewI nstance();
147 DartReceiverScope scope(args); 1039 setDartHandleInternalField(proxy, localVariables);
148 return v8::Boolean::New(Dart_IsList(scope.receiver())); 1040 proxy->SetHiddenValue(v8::String::NewSymbol("dartProxy"), v8::Boolean::New(t rue));
149 } 1041 return proxy;
150 1042 }
151 static v8::Handle<v8::Value> listGetAt(const v8::Arguments& args) 1043
152 { 1044 }
153 DartReceiverScope scope(args);
154 return convertResult(Dart_ListGetAt(scope.receiver(), args[1]->Int32Value()) );
155 }
156
157 static v8::Handle<v8::Value> listSetAt(const v8::Arguments& args)
158 {
159 DartReceiverScope scope(args);
160 return convertResult(Dart_ListSetAt(scope.receiver(), args[1]->Int32Value(), unwrapValue(args[2])));
161 }
162
163 // --- Classes and Interfaces ---
164
165 static v8::Handle<v8::Value> className(const v8::Arguments& args)
166 {
167 DartReceiverScope scope(args);
168 return convertResult(Dart_ClassName(scope.receiver()));
169 }
170
171 static v8::Handle<v8::Value> classGetLibrary(const v8::Arguments& args)
172 {
173 DartReceiverScope scope(args);
174 return convertResult(Dart_ClassGetLibrary(scope.receiver()));
175 }
176
177 static v8::Handle<v8::Value> getSuperclass(const v8::Arguments& args)
178 {
179 DartReceiverScope scope(args);
180 return convertResult(Dart_GetSuperclass(scope.receiver()));
181 }
182
183 // --- Function and Variable Declarations ---
184
185 static v8::Handle<v8::Value> getFunctionNames(const v8::Arguments& args)
186 {
187 DartReceiverScope scope(args);
188 return V8Converter::listToV8(Dart_GetFunctionNames(scope.receiver()));
189 }
190
191 static v8::Handle<v8::Value> getClassNames(const v8::Arguments& args)
192 {
193 DartReceiverScope scope(args);
194 Dart_Handle classNames = Dart_LibraryGetClassNames(scope.receiver());
195 ASSERT(!Dart_IsError(classNames) && !Dart_IsNull(classNames));
196 return V8Converter::listToV8(classNames);
197 }
198
199 static v8::Handle<v8::Value> lookupClass(const v8::Arguments& args)
200 {
201 DartReceiverScope scope(args);
202 return convertResult(Dart_GetClass(scope.receiver(), V8Converter::stringToDa rt(args[1])));
203 }
204
205 static v8::Handle<v8::Value> lookupFunction(const v8::Arguments& args)
206 {
207 DartReceiverScope scope(args);
208
209 Dart_Handle function = Dart_LookupFunction(scope.receiver(), V8Converter::st ringToDart(args[1]));
210 ASSERT(!Dart_IsError(function) && !Dart_IsNull(function));
211
212 Dart_Handle result;
213 UNUSED_PARAM(result);
214
215 bool isAbstract;
216 result = Dart_FunctionIsAbstract(function, &isAbstract);
217 ASSERT(!Dart_IsError(result));
218 bool isStatic;
219 result = Dart_FunctionIsStatic(function, &isStatic);
220 ASSERT(!Dart_IsError(result));
221 bool isConstructor;
222 result = Dart_FunctionIsConstructor(function, &isConstructor);
223 ASSERT(!Dart_IsError(result));
224 bool isGetter;
225 result = Dart_FunctionIsGetter(function, &isGetter);
226 ASSERT(!Dart_IsError(result));
227 bool isSetter;
228 result = Dart_FunctionIsSetter(function, &isSetter);
229 ASSERT(!Dart_IsError(result));
230 int64_t fixedParameterCount;
231 int64_t optionalParamerterCount;
232 result = Dart_FunctionParameterCounts(function, &fixedParameterCount, &optio nalParamerterCount);
233 ASSERT(!Dart_IsError(result));
234
235 v8::Handle<v8::Object> description = v8::Object::New();
236 description->Set(v8::String::New("isAbstract"), v8::Boolean::New(isAbstract) );
237 description->Set(v8::String::New("isStatic"), v8::Boolean::New(isStatic));
238 description->Set(v8::String::New("isConstructor"), v8::Boolean::New(isConstr uctor));
239 description->Set(v8::String::New("isGetter"), v8::Boolean::New(isGetter));
240 description->Set(v8::String::New("isSetter"), v8::Boolean::New(isSetter));
241 description->Set(v8::String::New("fixedParameterCount"), v8::Integer::New(fi xedParameterCount));
242 description->Set(v8::String::New("optionalParamerterCount"), v8::Integer::Ne w(optionalParamerterCount));
243 return description;
244 }
245
246 static v8::Handle<v8::Value> getVariableNames(const v8::Arguments& args)
247 {
248 DartReceiverScope scope(args);
249 return V8Converter::listToV8(Dart_GetVariableNames(scope.receiver()));
250 }
251
252 static v8::Handle<v8::Value> lookupVariable(const v8::Arguments& args)
253 {
254 DartReceiverScope scope(args);
255 Dart_Handle variable = Dart_LookupVariable(scope.receiver(), V8Converter::st ringToDart(args[1]));
256 ASSERT(!Dart_IsError(variable) && !Dart_IsNull(variable));
257
258 Dart_Handle result;
259 UNUSED_PARAM(result);
260
261 bool isStatic;
262 result = Dart_VariableIsStatic(variable, &isStatic);
263 ASSERT(!Dart_IsError(result));
264 bool isFinal;
265 result = Dart_VariableIsFinal(variable, &isFinal);
266 ASSERT(!Dart_IsError(result));
267
268 v8::Local<v8::Object> description = v8::Object::New();
269 description->Set(v8::String::New("isStatic"), v8::Boolean::New(isStatic));
270 description->Set(v8::String::New("isFinal"), v8::Boolean::New(isFinal));
271 return description;
272 }
273
274 // --- Constructors, Methods, and Fields ---
275
276 static v8::Handle<v8::Value> invoke(const v8::Arguments& args)
277 {
278 DartReceiverScope scope(args);
279 Vector<Dart_Handle> dartFunctionArgs;
280 v8::Handle<v8::Array> v8FunctionArgs = args[2].As<v8::Array>();
281 for (uint32_t i = 0; i < v8FunctionArgs->Length(); ++i)
282 dartFunctionArgs.append(unwrapValue(v8FunctionArgs->Get(i)));
283 return convertResult(Dart_Invoke(scope.receiver(), V8Converter::stringToDart (args[1]), dartFunctionArgs.size(), dartFunctionArgs.data()));
284 }
285
286 static v8::Handle<v8::Value> dartNew(const v8::Arguments& args)
287 {
288 DartReceiverScope scope(args);
289 Vector<Dart_Handle> dartConstructorArgs;
290 v8::Handle<v8::Array> v8ConstructorArgs = args[2].As<v8::Array>();
291 for (uint32_t i = 0; i < v8ConstructorArgs->Length(); ++i)
292 dartConstructorArgs.append(unwrapValue(v8ConstructorArgs->Get(i)));
293 return convertResult(Dart_New(scope.receiver(), V8Converter::stringToDart(ar gs[1]), dartConstructorArgs.size(), dartConstructorArgs.data()));
294 }
295
296 static v8::Handle<v8::Value> getField(const v8::Arguments& args)
297 {
298 DartReceiverScope scope(args);
299
300 return convertResult(Dart_GetField(scope.receiver(), V8Converter::stringToDa rt(args[1])));
301 }
302
303 static v8::Handle<v8::Value> setField(const v8::Arguments& args)
304 {
305 DartReceiverScope scope(args);
306 v8::Handle<v8::Array> v8FunctionArgs = args[2].As<v8::Array>();
307 ASSERT(v8FunctionArgs->Length() == 1);
308 return convertResult(Dart_SetField(scope.receiver(), V8Converter::stringToDa rt(args[1]), unwrapValue(v8FunctionArgs->Get(0))));
309 }
310
311 // --- Scripts and Libraries ---
312
313 static v8::Handle<v8::Value> libraryName(const v8::Arguments& args)
314 {
315 DartReceiverScope scope(args);
316 return convertResult(Dart_LibraryName(scope.receiver()));
317 }
318
319 static v8::Handle<v8::Value> libraryUrl(const v8::Arguments& args)
320 {
321 DartReceiverScope scope(args);
322 return convertResult(Dart_LibraryUrl(scope.receiver()));
323 }
324
325 static v8::Handle<v8::Value> libraryImports(const v8::Arguments& args)
326 {
327 DartReceiverScope scope(args);
328 int32_t libraryId = args[0].As<v8::Object>()->GetHiddenValue(v8::String::New ("libraryId"))->Int32Value();
329 Dart_Handle imports = Dart_GetLibraryImports(libraryId);
330 ASSERT(!Dart_IsError(imports));
331 intptr_t length = 0;
332 Dart_ListLength(imports, &length);
333 v8::Handle<v8::Array> result = v8::Array::New();
334 for (intptr_t i = 0; i < length; i += 2) {
335 Dart_Handle prefix = Dart_ListGetAt(imports, i);
336 result->Set(i, DartHandleProxy::create(prefix));
337 Dart_Handle importedLibraryIdHandle = Dart_ListGetAt(imports, i + 1);
338 ASSERT(Dart_IsInteger(importedLibraryIdHandle));
339 int64_t importedLibraryId;
340 Dart_IntegerToInt64(importedLibraryIdHandle, &importedLibraryId);
341 result->Set(i + 1, DartHandleProxy::createForLibrary(importedLibraryId)) ;
342 }
343 return result;
344 }
345
346 void DartHandleProxy::getMirrorAPI(v8::Handle<v8::Object> container)
347 {
348 V8Scope v8scope;
349 container->Set(v8::String::New("instanceGetClass"), v8::FunctionTemplate::Ne w(&instanceGetClass)->GetFunction());
350 container->Set(v8::String::New("isList"), v8::FunctionTemplate::New(&isList) ->GetFunction());
351 container->Set(v8::String::New("listGetAt"), v8::FunctionTemplate::New(&list GetAt)->GetFunction());
352 container->Set(v8::String::New("listSetAt"), v8::FunctionTemplate::New(&list SetAt)->GetFunction());
353 container->Set(v8::String::New("className"), v8::FunctionTemplate::New(&clas sName)->GetFunction());
354 container->Set(v8::String::New("classGetLibrary"), v8::FunctionTemplate::New (&classGetLibrary)->GetFunction());
355 container->Set(v8::String::New("getSuperclass"), v8::FunctionTemplate::New(& getSuperclass)->GetFunction());
356 container->Set(v8::String::New("getFunctionNames"), v8::FunctionTemplate::Ne w(&getFunctionNames)->GetFunction());
357 container->Set(v8::String::New("getClassNames"), v8::FunctionTemplate::New(& getClassNames)->GetFunction());
358 container->Set(v8::String::New("lookupFunction"), v8::FunctionTemplate::New( &lookupFunction)->GetFunction());
359 container->Set(v8::String::New("lookupClass"), v8::FunctionTemplate::New(&lo okupClass)->GetFunction());
360 container->Set(v8::String::New("getVariableNames"), v8::FunctionTemplate::Ne w(&getVariableNames)->GetFunction());
361 container->Set(v8::String::New("lookupVariable"), v8::FunctionTemplate::New( &lookupVariable)->GetFunction());
362 container->Set(v8::String::New("invoke"), v8::FunctionTemplate::New(&invoke) ->GetFunction());
363 container->Set(v8::String::New("dartNew"), v8::FunctionTemplate::New(&dartNe w)->GetFunction());
364 container->Set(v8::String::New("getField"), v8::FunctionTemplate::New(&getFi eld)->GetFunction());
365 container->Set(v8::String::New("setField"), v8::FunctionTemplate::New(&setFi eld)->GetFunction());
366 container->Set(v8::String::New("libraryName"), v8::FunctionTemplate::New(&li braryName)->GetFunction());
367 container->Set(v8::String::New("libraryUrl"), v8::FunctionTemplate::New(&lib raryUrl)->GetFunction());
368 container->Set(v8::String::New("libraryImports"), v8::FunctionTemplate::New( &libraryImports)->GetFunction());
369 }
370
371 }
OLDNEW
« no previous file with comments | « Source/bindings/dart/DartHandleProxy.h ('k') | Source/bindings/dart/DartUtilities.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698