Skip to content

Commit 96ca5db

Browse files
committed
Add JSNative utility class with static methods methods to efficiently manipulate typed JSInterop objects in cases where the member name is not known statically. These methods would be extension methods on JSObject if Dart supported extension methods. Update package js to export these methods. Implement in Dart2JS. Implement JS$ in dart2js.
BUG= R=alanknight@google.com, sra@google.com Review URL: https://codereview.chromium.org/2150313003 .
1 parent f5e157f commit 96ca5db

File tree

23 files changed

+1039
-233
lines changed

23 files changed

+1039
-233
lines changed

pkg/compiler/lib/src/js_backend/native_data.dart

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ class NativeData {
3535
Map<MemberElement, NativeBehavior> nativeFieldStoreBehavior =
3636
<FieldElement, NativeBehavior>{};
3737

38+
/// Prefix used to escape JS names that are not valid Dart names
39+
/// when using JSInterop.
40+
static const String _jsInteropEscapePrefix = r'JS$';
41+
3842
/// Returns `true` if [element] is explicitly marked as part of JsInterop.
3943
bool _isJsInterop(Element element) {
4044
return jsInteropNames.containsKey(element.declaration);
@@ -93,7 +97,7 @@ class NativeData {
9397
if (jsInteropName != null && jsInteropName.isNotEmpty) {
9498
return jsInteropName;
9599
}
96-
return element.isLibrary ? 'self' : element.name;
100+
return element.isLibrary ? 'self' : getUnescapedJSInteropName(element.name);
97101
}
98102

99103
/// Computes the name for [element] to use in the generated JavaScript. This
@@ -216,4 +220,12 @@ class NativeData {
216220
FieldElement field, NativeBehavior behavior) {
217221
nativeFieldStoreBehavior[field] = behavior;
218222
}
223+
224+
/// Apply JS$ escaping scheme to convert possible escaped Dart names into
225+
/// JS names.
226+
String getUnescapedJSInteropName(String name) {
227+
return name.startsWith(_jsInteropEscapePrefix)
228+
? name.substring(_jsInteropEscapePrefix.length)
229+
: name;
230+
}
219231
}

pkg/compiler/lib/src/js_emitter/program_builder/program_builder.dart

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,8 @@ class ProgramBuilder {
345345
for (Element e in elements) {
346346
if (e is ClassElement && backend.isJsInterop(e)) {
347347
e.declaration.forEachMember((_, Element member) {
348+
var jsName =
349+
backend.nativeData.getUnescapedJSInteropName(member.name);
348350
if (!member.isInstanceMember) return;
349351
if (member.isGetter || member.isField || member.isFunction) {
350352
var selectors =
@@ -354,7 +356,7 @@ class ProgramBuilder {
354356
var stubName = namer.invocationName(selector);
355357
if (stubNames.add(stubName.key)) {
356358
interceptorClass.callStubs.add(_buildStubMethod(stubName,
357-
js.js('function(obj) { return obj.# }', [member.name]),
359+
js.js('function(obj) { return obj.# }', [jsName]),
358360
element: member));
359361
}
360362
}
@@ -367,10 +369,8 @@ class ProgramBuilder {
367369
if (selectors != null && !selectors.isEmpty) {
368370
var stubName = namer.setterForElement(member);
369371
if (stubNames.add(stubName.key)) {
370-
interceptorClass.callStubs.add(_buildStubMethod(
371-
stubName,
372-
js.js('function(obj, v) { return obj.# = v }',
373-
[member.name]),
372+
interceptorClass.callStubs.add(_buildStubMethod(stubName,
373+
js.js('function(obj, v) { return obj.# = v }', [jsName]),
374374
element: member));
375375
}
376376
}
@@ -447,7 +447,7 @@ class ProgramBuilder {
447447
interceptorClass.callStubs.add(_buildStubMethod(
448448
stubName,
449449
js.js('function(receiver, #) { return receiver.#(#) }',
450-
[parameters, member.name, parameters]),
450+
[parameters, jsName, parameters]),
451451
element: member));
452452
}
453453
}

pkg/compiler/lib/src/native/native.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const Iterable<String> _allowedDartSchemePaths = const <String>[
1919
'html_common',
2020
'indexed_db',
2121
'js',
22+
'js_util',
2223
'svg',
2324
'_native_typed_data',
2425
'web_audio',

pkg/compiler/lib/src/ssa/builder.dart

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5619,14 +5619,15 @@ class SsaBuilder extends ast.Visitor
56195619
var filteredArguments = <HInstruction>[];
56205620
var parameterNameMap = new Map<String, js.Expression>();
56215621
params.orderedForEachParameter((ParameterElement parameter) {
5622-
// TODO(jacobr): throw if parameter names do not match names of property
5623-
// names in the class.
5622+
// TODO(jacobr): consider throwing if parameter names do not match
5623+
// names of properties in the class.
56245624
assert(parameter.isNamed);
56255625
HInstruction argument = arguments[i];
56265626
if (argument != null) {
56275627
filteredArguments.add(argument);
5628-
parameterNameMap[parameter.name] =
5629-
new js.InterpolatedExpression(positions++);
5628+
var jsName =
5629+
backend.nativeData.getUnescapedJSInteropName(parameter.name);
5630+
parameterNameMap[jsName] = new js.InterpolatedExpression(positions++);
56305631
}
56315632
i++;
56325633
});

pkg/js/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## 0.6.1
2+
* Add js_util library of utility methods to efficiently manipulate typed
3+
JavaScript interop objects in cases where the member name is not known
4+
statically. These methods would be extension methods on JSObject if
5+
Dart supported extension methods.
6+
17
## 0.6.0
28

39
* Version 0.6.0 is a complete rewrite of `package:js`.

pkg/js/lib/js_util.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
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.
4+
5+
/// Allows interoperability with Javascript APIs.
6+
library js_util;
7+
8+
export 'dart:js_util';

pkg/js/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: js
2-
version: 0.6.0
2+
version: 0.6.1
33
authors:
44
- Dart Team <misc@dartlang.org>
55
description: Access JavaScript from Dart.

runtime/bin/bin.gypi

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
'html_cc_file': '<(gen_source_dir)/html_gen.cc',
1212
'html_common_cc_file': '<(gen_source_dir)/html_common_gen.cc',
1313
'js_cc_file': '<(gen_source_dir)/js_gen.cc',
14+
'js_util_cc_file': '<(gen_source_dir)/js_util_gen.cc',
1415
'blink_cc_file': '<(gen_source_dir)/blink_gen.cc',
1516
'indexeddb_cc_file': '<(gen_source_dir)/indexeddb_gen.cc',
1617
'cached_patches_cc_file': '<(gen_source_dir)/cached_patches_gen.cc',
@@ -233,6 +234,38 @@
233234
},
234235
]
235236
},
237+
{
238+
'target_name': 'generate_js_util_cc_file',
239+
'type': 'none',
240+
'toolsets':['host'],
241+
'sources': [
242+
'../../sdk/lib/js_util/dartium/js_util_dartium.dart',
243+
],
244+
'actions': [
245+
{
246+
'action_name': 'generate_js_util_cc',
247+
'inputs': [
248+
'../tools/gen_library_src_paths.py',
249+
'<(builtin_in_cc_file)',
250+
'<@(_sources)',
251+
],
252+
'outputs': [
253+
'<(js_util_cc_file)',
254+
],
255+
'action': [
256+
'python',
257+
'tools/gen_library_src_paths.py',
258+
'--output', '<(js_util_cc_file)',
259+
'--input_cc', '<(builtin_in_cc_file)',
260+
'--include', 'bin/builtin.h',
261+
'--var_name', 'dart::bin::Builtin::js_util_source_paths_',
262+
'--library_name', 'dart:js_util',
263+
'<@(_sources)',
264+
],
265+
'message': 'Generating ''<(js_util_cc_file)'' file.'
266+
},
267+
]
268+
},
236269
{
237270
'target_name': 'generate_blink_cc_file',
238271
'type': 'none',
@@ -500,6 +533,7 @@
500533
'generate_html_cc_file#host',
501534
'generate_html_common_cc_file#host',
502535
'generate_js_cc_file#host',
536+
'generate_js_util_cc_file#host',
503537
'generate_blink_cc_file#host',
504538
'generate_indexeddb_cc_file#host',
505539
'generate_cached_patches_cc_file#host',
@@ -1262,6 +1296,7 @@
12621296
'<(html_cc_file)',
12631297
'<(html_common_cc_file)',
12641298
'<(js_cc_file)',
1299+
'<(js_util_cc_file)',
12651300
'<(blink_cc_file)',
12661301
'<(indexeddb_cc_file)',
12671302
'<(cached_patches_cc_file)',

runtime/bin/builtin.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ Builtin::builtin_lib_props Builtin::builtin_libraries_[] = {
2424
{ "dart:html", html_source_paths_, NULL, NULL, true },
2525
{ "dart:html_common", html_common_source_paths_, NULL, NULL, true},
2626
{ "dart:js", js_source_paths_, NULL, NULL, true},
27+
{ "dart:js_util", js_util_source_paths_, NULL, NULL, true},
2728
{ "dart:_blink", blink_source_paths_, NULL, NULL, true },
2829
{ "dart:indexed_db", indexeddb_source_paths_, NULL, NULL, true },
2930
{ "cached_patches.dart", cached_patches_source_paths_, NULL, NULL, true },

runtime/bin/builtin.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ class Builtin {
7474
static const char* html_source_paths_[];
7575
static const char* html_common_source_paths_[];
7676
static const char* js_source_paths_[];
77+
static const char* js_util_source_paths_[];
7778
static const char* blink_source_paths_[];
7879
static const char* indexeddb_source_paths_[];
7980
static const char* cached_patches_source_paths_[];

sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,12 @@ const Map<String, LibraryInfo> libraries = const {
116116
maturity: Maturity.STABLE,
117117
dart2jsPath: "js/dart2js/js_dart2js.dart"),
118118

119+
"js_util": const LibraryInfo(
120+
"js_util/dartium/js_util_dartium.dart",
121+
categories: "Client",
122+
maturity: Maturity.STABLE,
123+
dart2jsPath: "js_util/dart2js/js_util_dart2js.dart"),
124+
119125
"math": const LibraryInfo(
120126
"math/math.dart",
121127
categories: "Client,Server,Embedded",

sdk/lib/dart2dart.platform

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ indexed_db: indexed_db/dart2js/indexed_db_dart2js.dart
2525
io: io/io.dart
2626
isolate: isolate/isolate.dart
2727
js: js/dart2js/js_dart2js.dart
28+
js_util: js_util/dart2js/js_util_dart2js.dart
2829
math: math/math.dart
2930
mirrors: mirrors/mirrors.dart
3031
nativewrappers: html/dart2js/nativewrappers.dart

sdk/lib/dart_client.platform

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ indexed_db: indexed_db/dart2js/indexed_db_dart2js.dart
2626
io: unsupported:
2727
isolate: isolate/isolate.dart
2828
js: js/dart2js/js_dart2js.dart
29+
js_util: js_util/dart2js/js_util_dart2js.dart
2930
math: math/math.dart
3031
mirrors: mirrors/mirrors.dart
3132
nativewrappers: html/dart2js/nativewrappers.dart

sdk/lib/dart_shared.platform

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ indexed_db: indexed_db/dart2js/indexed_db_dart2js.dart
2424
io: io/io.dart
2525
isolate: isolate/isolate.dart
2626
js: js/dart2js/js_dart2js.dart
27+
js_util: js_util/dart2js/js_util_dart2js.dart
2728
math: math/math.dart
2829
mirrors: mirrors/mirrors.dart
2930
nativewrappers: html/dart2js/nativewrappers.dart

sdk/lib/js/dart2js/js_dart2js.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -707,7 +707,7 @@ _callDartFunctionFastCaptureThis(callback, self, List arguments) {
707707
return Function.apply(callback, [self]..addAll(arguments));
708708
}
709709

710-
Function /*=F*/ allowInterop/*<F extends Function>*/(Function /*=F*/ f) {
710+
Function/*=F*/ allowInterop/*<F extends Function>*/(Function/*=F*/ f) {
711711
if (JS('bool', 'typeof(#) == "function"', f)) {
712712
// Already supports interop, just use the existing function.
713713
return f;

0 commit comments

Comments
 (0)