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

Side by Side Diff: sdk/lib/js/dartium/js_dartium.dart

Issue 1415463019: Make Dartium JS interop implementation more robust in the presence of JS paths that touch dart:html… (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 1 month 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
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 /** 5 /**
6 * Support for interoperating with JavaScript. 6 * Support for interoperating with JavaScript.
7 * 7 *
8 * This library provides access to JavaScript objects from Dart, allowing 8 * This library provides access to JavaScript objects from Dart, allowing
9 * Dart code to get and set properties, and call methods of JavaScript objects 9 * Dart code to get and set properties, and call methods of JavaScript objects
10 * and invoke JavaScript functions. The library takes care of converting 10 * and invoke JavaScript functions. The library takes care of converting
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after
303 if (declaration is mirrors.MethodMirror && declaration.isSetter) { 303 if (declaration is mirrors.MethodMirror && declaration.isSetter) {
304 assert(name.endsWith("=")); 304 assert(name.endsWith("="));
305 name = name.substring(0, name.length - 1); 305 name = name.substring(0, name.length - 1);
306 } 306 }
307 return name; 307 return name;
308 } 308 }
309 309
310 final _JS_LIBRARY_PREFIX = "js_library"; 310 final _JS_LIBRARY_PREFIX = "js_library";
311 final _UNDEFINED_VAR = "_UNDEFINED_JS_CONST"; 311 final _UNDEFINED_VAR = "_UNDEFINED_JS_CONST";
312 312
313 String _accessJsPath(String path) => 313 String _accessJsPath(String path) {
314 "${_JS_LIBRARY_PREFIX}.context${path.split(".").map((p) => "['$p']").join('' )}"; 314 var parts = path.split(".");
315 var sb = new StringBuffer();
316 sb
317 ..write('${_JS_LIBRARY_PREFIX}.JsNative.getProperty(' * parts.length)
318 ..write("${_JS_LIBRARY_PREFIX}.context");
319 for (var p in parts) {
320 sb.write(", '$p')");
321 }
322 return sb.toString();
323 }
324
325
326 String _accessJsPathSetter(String path) {
327 var parts = path.split(".");
328 return "${_JS_LIBRARY_PREFIX}.JsNative.setProperty(${_accessJsPath(parts.getRa nge(0, parts.length - 1).join('.'))
329 }, '{parts.end}', v)";
330 }
315 331
316 @Deprecated("Internal Use Only") 332 @Deprecated("Internal Use Only")
317 void addMemberHelper( 333 void addMemberHelper(
318 mirrors.MethodMirror declaration, String path, StringBuffer sb, 334 mirrors.MethodMirror declaration, String path, StringBuffer sb,
319 {bool isStatic: false, String memberName}) { 335 {bool isStatic: false, String memberName}) {
320 if (!declaration.isConstructor) { 336 if (!declaration.isConstructor) {
321 var jsName = _getJsMemberName(declaration); 337 var jsName = _getJsMemberName(declaration);
322 path = (path != null && path.isNotEmpty) ? "${path}.${jsName}" : jsName; 338 path = (path != null && path.isNotEmpty) ? "${path}.${jsName}" : jsName;
323 } 339 }
324 var name = memberName != null ? memberName : _getDeclarationName(declaration); 340 var name = memberName != null ? memberName : _getDeclarationName(declaration);
325 if (declaration.isConstructor) { 341 if (declaration.isConstructor) {
326 sb.write("factory"); 342 sb.write("factory");
327 } else if (isStatic) { 343 } else if (isStatic) {
328 sb.write("static"); 344 sb.write("static");
329 } else { 345 } else {
330 sb.write("patch"); 346 sb.write("patch");
331 } 347 }
332 sb.write(" "); 348 sb.write(" ");
333 if (declaration.isGetter) { 349 if (declaration.isGetter) {
334 sb.write("get $name => ${_accessJsPath(path)};"); 350 sb.write("get $name => ${_JS_LIBRARY_PREFIX}.maybeWrapTypedInterop(${_access JsPath(path)});");
335 } else if (declaration.isSetter) { 351 } else if (declaration.isSetter) {
336 sb.write("set $name(v) => ${_accessJsPath(path)} = v;"); 352 sb.write("set $name(v) => ${_JS_LIBRARY_PREFIX}.maybeWrapTypedInterop(${_acc essJsPathSetter(path)});");
337 } else { 353 } else {
338 sb.write("$name("); 354 sb.write("$name(");
339 bool hasOptional = false; 355 bool hasOptional = false;
340 int i = 0; 356 int i = 0;
341 var args = <String>[]; 357 var args = <String>[];
342 for (var p in declaration.parameters) { 358 for (var p in declaration.parameters) {
343 assert(!p.isNamed); // XXX throw 359 assert(!p.isNamed); // XXX throw
344 assert(!p.hasDefaultValue); 360 assert(!p.hasDefaultValue);
345 if (i > 0) { 361 if (i > 0) {
346 sb.write(", "); 362 sb.write(", ");
347 } 363 }
348 if (p.isOptional && !hasOptional) { 364 if (p.isOptional && !hasOptional) {
349 sb.write("["); 365 sb.write("[");
350 hasOptional = true; 366 hasOptional = true;
351 } 367 }
352 var arg = "p$i"; 368 var arg = "p$i";
353 args.add(arg); 369 args.add(arg);
354 sb.write(arg); 370 sb.write(arg);
355 if (p.isOptional) { 371 if (p.isOptional) {
356 sb.write("=${_UNDEFINED_VAR}"); 372 sb.write("=${_UNDEFINED_VAR}");
357 } 373 }
358 i++; 374 i++;
359 } 375 }
360 if (hasOptional) { 376 if (hasOptional) {
361 sb.write("]"); 377 sb.write("]");
362 } 378 }
363 // TODO(jacobr): 379 // TODO(jacobr):
364 sb.write(") => "); 380 sb.write(") => ");
381 sb.write('${_JS_LIBRARY_PREFIX}.maybeWrapTypedInterop(');
365 if (declaration.isConstructor) { 382 if (declaration.isConstructor) {
366 sb.write("new ${_JS_LIBRARY_PREFIX}.JsObject("); 383 sb.write("new ${_JS_LIBRARY_PREFIX}.JsObject(");
367 } 384 }
368 sb 385 sb
369 ..write(_accessJsPath(path)) 386 ..write(_accessJsPath(path))
370 ..write(declaration.isConstructor ? "," : ".apply(") 387 ..write(declaration.isConstructor ? "," : ".apply(")
371 ..write("[${args.join(",")}]"); 388 ..write("[${args.join(",")}]");
372 389
373 if (hasOptional) { 390 if (hasOptional) {
374 sb.write(".takeWhile((i) => i != ${_UNDEFINED_VAR}).toList()"); 391 sb.write(".takeWhile((i) => i != ${_UNDEFINED_VAR}).toList()");
375 } 392 }
376 sb.write(");"); 393 sb.write("));");
377 } 394 }
378 sb.write("\n"); 395 sb.write("\n");
379 } 396 }
380 397
381 // TODO(jacobr): make this check more robust. 398 // TODO(jacobr): make this check more robust.
382 bool _isExternal(mirrors.Mirror mirror) { 399 bool _isExternal(mirrors.Mirror mirror) {
383 /* 400 /*
384 var source = mirror.source; 401 var source = mirror.source;
385 return source != null && source.startsWith("external "); 402 return source != null && source.startsWith("external ");
386 */ 403 */
(...skipping 459 matching lines...) Expand 10 before | Expand all | Expand 10 after
846 863
847 bool get _finalized native "Js_interfacesFinalized_Callback"; 864 bool get _finalized native "Js_interfacesFinalized_Callback";
848 865
849 JsObject get context { 866 JsObject get context {
850 if (_cachedContext == null) { 867 if (_cachedContext == null) {
851 _cachedContext = _context; 868 _cachedContext = _context;
852 } 869 }
853 return _cachedContext; 870 return _cachedContext;
854 } 871 }
855 872
873 @Deprecated("Internal Use Only")
874 maybeWrapTypedInterop(o) =>
875 html_common.wrap_jso_no_SerializedScriptvalue(o);
876
856 _maybeWrap(o) { 877 _maybeWrap(o) {
857 var wrapped = html_common.wrap_jso_no_SerializedScriptvalue(o); 878 var wrapped = html_common.wrap_jso_no_SerializedScriptvalue(o);
858 if (identical(wrapped, o)) return o; 879 if (identical(wrapped, o)) return o;
859 return (wrapped is html.Blob || 880 return (wrapped is html.Blob ||
860 wrapped is html.Event || 881 wrapped is html.Event ||
861 wrapped is indexed_db.KeyRange || 882 wrapped is indexed_db.KeyRange ||
862 wrapped is html.ImageData || 883 wrapped is html.ImageData ||
863 wrapped is html.Node || 884 wrapped is html.Node ||
864 wrapped is TypedData || 885 wrapped is TypedData ||
865 wrapped is html.Window) ? wrapped : o; 886 wrapped is html.Window) ? wrapped : o;
(...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after
1095 } 1116 }
1096 var ret = this[name]; 1117 var ret = this[name];
1097 if (matches != null && matches._checkReturnType(ret)) return ret; 1118 if (matches != null && matches._checkReturnType(ret)) return ret;
1098 if (ret is Function || 1119 if (ret is Function ||
1099 (ret is JsFunction /* shouldn't be needed in the future*/) && 1120 (ret is JsFunction /* shouldn't be needed in the future*/) &&
1100 _allowedMethods.containsKey( 1121 _allowedMethods.containsKey(
1101 invocation.memberName)) return ret; // Warning: we have not bound "this"... we could type check on the Function but that is of little value in Dart. 1122 invocation.memberName)) return ret; // Warning: we have not bound "this"... we could type check on the Function but that is of little value in Dart.
1102 throwError(); 1123 throwError();
1103 } else { 1124 } else {
1104 // TODO(jacobr): should we throw if the JavaScript object doesn't have t he property? 1125 // TODO(jacobr): should we throw if the JavaScript object doesn't have t he property?
1105 return this[name]; 1126 return maybeWrapTypedInterop(this._operator_getter(name));
1106 } 1127 }
1107 } else if (invocation.isSetter) { 1128 } else if (invocation.isSetter) {
1108 if (CHECK_JS_INVOCATIONS) { 1129 if (CHECK_JS_INVOCATIONS) {
1109 var matches = _allowedSetters[invocation.memberName]; 1130 var matches = _allowedSetters[invocation.memberName];
1110 if (matches == null || 1131 if (matches == null ||
1111 !matches.checkInvocation(invocation)) throwError(); 1132 !matches.checkInvocation(invocation)) throwError();
1112 } 1133 }
1113 assert(name.endsWith("=")); 1134 assert(name.endsWith("="));
1114 name = name.substring(0, name.length - 1); 1135 name = name.substring(0, name.length - 1);
1115 return this[name] = invocation.positionalArguments.first; 1136 return maybeWrapTypedInterop(_operator_setter(
1137 name, invocation.positionalArguments.first));
1116 } else { 1138 } else {
1117 // TODO(jacobr): also allow calling getters that look like functions. 1139 // TODO(jacobr): also allow calling getters that look like functions.
1118 var matches; 1140 var matches;
1119 if (CHECK_JS_INVOCATIONS) { 1141 if (CHECK_JS_INVOCATIONS) {
1120 matches = _allowedMethods[invocation.memberName]; 1142 matches = _allowedMethods[invocation.memberName];
1121 if (matches == null || 1143 if (matches == null ||
1122 !matches.checkInvocation(invocation)) throwError(); 1144 !matches.checkInvocation(invocation)) throwError();
1123 } 1145 }
1124 var ret = this.callMethod(name, _buildArgs(invocation)); 1146 var ret = maybeWrapTypedInterop(this._callMethod(name, _buildArgs(invocati on)));
1125 if (CHECK_JS_INVOCATIONS) { 1147 if (CHECK_JS_INVOCATIONS) {
1126 if (!matches._checkReturnType(ret)) throwError(); 1148 if (!matches._checkReturnType(ret)) throwError();
1127 } 1149 }
1128 return ret; 1150 return ret;
1129 } 1151 }
1130 } 1152 }
1131 1153
1132 _callMethod(String name, List args) native "JsObject_callMethod"; 1154 _callMethod(String name, List args) native "JsObject_callMethod";
1133 } 1155 }
1134 1156
1135 // JavaScript interop methods that do not automatically wrap to dart:html types. 1157 // JavaScript interop methods that do not automatically wrap to dart:html types.
1136 // Warning: this API is not exposed to dart:js. 1158 // Warning: this API is not exposed to dart:js.
1137 @Deprecated("Internal Use Only") 1159 @Deprecated("Internal Use Only")
1138 class JsNative { 1160 class JsNative {
1139 static getProperty(JsObject o, name) { 1161 static getProperty(o, name) {
1140 return o._operator_getter(name); 1162 o = unwrap_jso(o);
1163 return o != null ? o._operator_getter(name) : null;
1141 } 1164 }
1142 1165
1143 static callMethod(JsObject o, String method, List args) { 1166 static setProperty(o, name, value) {
1144 return o._callMethod(method, args); 1167 return unwrap_jso(o)._operator_setter(name, value);
1168 }
1169
1170 static callMethod(o, String method, List args) {
1171 return unwrap_jso(o)._callMethod(method, args);
1145 } 1172 }
1146 1173
1147 static getArrayIndex(JsArray array, int index) { 1174 static getArrayIndex(JsArray array, int index) {
1148 array._checkIndex(index); 1175 array._checkIndex(index);
1149 return getProperty(array, index); 1176 return getProperty(array, index);
1150 } 1177 }
1151 1178
1152 /** 1179 /**
1153 * Same behavior as new JsFunction.withThis except that JavaScript "this" is n ot 1180 * Same behavior as new JsFunction.withThis except that JavaScript "this" is n ot
1154 * wrapped. 1181 * wrapped.
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
1373 return f; 1400 return f;
1374 } else { 1401 } else {
1375 var ret = _interopCaptureThisExpando[f]; 1402 var ret = _interopCaptureThisExpando[f];
1376 if (ret == null) { 1403 if (ret == null) {
1377 ret = new JsFunction.withThis(f); 1404 ret = new JsFunction.withThis(f);
1378 _interopCaptureThisExpando[f] = ret; 1405 _interopCaptureThisExpando[f] = ret;
1379 } 1406 }
1380 return ret; 1407 return ret;
1381 } 1408 }
1382 } 1409 }
OLDNEW
« no previous file with comments | « no previous file | tests/html/js_typed_interop_test.dart » ('j') | tests/html/js_typed_interop_test.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698