Skip to content

Commit 5337fc0

Browse files
author
Olivier Chafik
committed
Compile package:js.{rest, spread} helpers.
Note: need new package:js release before merging this in (#24623). Maybe it's time to think again about sneaking JsName + JsPeerInterface into it? (dart-archive/dev_compiler#135) BUG=dart-archive/dev_compiler#310 [email protected] Review URL: https://codereview.chromium.org/1424133007 .
1 parent d8c7cd7 commit 5337fc0

File tree

11 files changed

+114
-22
lines changed

11 files changed

+114
-22
lines changed

pkg/dev_compiler/lib/src/codegen/js_codegen.dart

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import '../utils.dart';
3131

3232
import 'code_generator.dart';
3333
import 'js_field_storage.dart';
34+
import 'js_interop.dart';
3435
import 'js_names.dart' as JS;
3536
import 'js_metalet.dart' as JS;
3637
import 'js_module_item_order.dart';
@@ -247,7 +248,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
247248
void visitLibraryDirective(LibraryDirective node) {
248249
assert(_jsModuleValue == null);
249250

250-
var jsName = findAnnotation(node.element, _isJsNameAnnotation);
251+
var jsName = findAnnotation(node.element, isJsNameAnnotation);
251252
_jsModuleValue =
252253
getConstantField(jsName, 'name', types.stringType)?.toStringValue();
253254
}
@@ -420,7 +421,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
420421
JS.Statement visitClassDeclaration(ClassDeclaration node) {
421422
var classElem = node.element;
422423
var type = classElem.type;
423-
var jsName = findAnnotation(classElem, _isJsNameAnnotation);
424+
var jsName = findAnnotation(classElem, isJsNameAnnotation);
424425

425426
if (jsName != null) return _emitJsType(node.name.name, jsName);
426427

@@ -441,7 +442,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
441442
_classHeritage(classElem), _emitClassMethods(node, ctors, fields));
442443

443444
String jsPeerName;
444-
var jsPeer = findAnnotation(classElem, _isJsPeerInterface);
445+
var jsPeer = findAnnotation(classElem, isJsPeerInterface);
445446
if (jsPeer != null) {
446447
jsPeerName =
447448
getConstantField(jsPeer, 'name', types.stringType)?.toStringValue();
@@ -596,7 +597,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
596597
jsMethods.add(_emitImplicitConstructor(node, fields));
597598
}
598599

599-
bool hasJsPeer = findAnnotation(element, _isJsPeerInterface) != null;
600+
bool hasJsPeer = findAnnotation(element, isJsPeerInterface) != null;
600601

601602
bool hasIterator = false;
602603
for (var m in node.members) {
@@ -1853,6 +1854,9 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
18531854
for (var arg in node.arguments) {
18541855
if (arg is NamedExpression) {
18551856
named.add(_visit(arg));
1857+
} else if (arg is MethodInvocation && isJsSpreadInvocation(arg)) {
1858+
args.add(
1859+
new JS.RestParameter(_visit(arg.argumentList.arguments.single)));
18561860
} else {
18571861
args.add(_visit(arg));
18581862
}
@@ -1871,8 +1875,8 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
18711875
}
18721876

18731877
@override
1874-
List<JS.Identifier> visitFormalParameterList(FormalParameterList node) {
1875-
var result = <JS.Identifier>[];
1878+
List<JS.Parameter> visitFormalParameterList(FormalParameterList node) {
1879+
var result = <JS.Parameter>[];
18761880
for (FormalParameter param in node.parameters) {
18771881
if (param.kind == ParameterKind.NAMED) {
18781882
result.add(_namedArgTemp);
@@ -2519,8 +2523,12 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
25192523
_visit(node.expression);
25202524

25212525
@override
2522-
visitFormalParameter(FormalParameter node) =>
2523-
visitSimpleIdentifier(node.identifier);
2526+
visitFormalParameter(FormalParameter node) {
2527+
var id = visitSimpleIdentifier(node.identifier);
2528+
2529+
var isRestArg = findAnnotation(node.element, isJsRestAnnotation) != null;
2530+
return isRestArg ? new JS.RestParameter(id) : id;
2531+
}
25242532

25252533
@override
25262534
JS.This visitThisExpression(ThisExpression node) => new JS.This();
@@ -2682,7 +2690,7 @@ class JSCodegenVisitor extends GeneralizingAstVisitor with ClosureAnnotator {
26822690
// TODO(jmesserly): ideally we'd check the method and see if it is marked
26832691
// `external`, but that doesn't work because it isn't in the element model.
26842692
bool _useNativeJsIndexer(DartType type) =>
2685-
findAnnotation(type.element, _isJsNameAnnotation) != null;
2693+
findAnnotation(type.element, isJsNameAnnotation) != null;
26862694

26872695
/// Gets the target of a [PropertyAccess], [IndexExpression], or
26882696
/// [MethodInvocation]. These three nodes can appear in a [CascadeExpression].
@@ -3301,12 +3309,6 @@ String jsLibraryName(LibraryElement library) => canonicalLibraryName(library);
33013309
// TODO(jmesserly): avoid the round tripping through quoted form.
33023310
JS.LiteralString _propertyName(String name) => js.string(name, "'");
33033311

3304-
// TODO(jmesserly): validate the library. See issue #135.
3305-
bool _isJsNameAnnotation(DartObject value) => value.type.name == 'JsName';
3306-
3307-
bool _isJsPeerInterface(DartObject value) =>
3308-
value.type.name == 'JsPeerInterface';
3309-
33103312
// TODO(jacobr): we would like to do something like the following
33113313
// but we don't have summary support yet.
33123314
// bool _supportJsExtensionMethod(AnnotatedNode node) =>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright (c) 2015, 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+
library dev_compiler.src.js_interop;
6+
7+
import 'package:analyzer/src/generated/ast.dart';
8+
import 'package:analyzer/src/generated/element.dart';
9+
import 'package:analyzer/src/generated/constant.dart';
10+
11+
bool _isJsLibType(String expectedName, Element e) =>
12+
e?.name == expectedName && _isJsLib(e.library);
13+
14+
bool _isJsLib(LibraryElement e) {
15+
var libName = e?.name;
16+
return libName == 'js' ||
17+
libName == 'js.varargs' ||
18+
libName == 'dart._js_helper';
19+
}
20+
21+
bool isJsRestAnnotation(DartObjectImpl value) =>
22+
_isJsLibType('_Rest', value.type.element);
23+
24+
bool isJsSpreadInvocation(MethodInvocation i) =>
25+
_isJsLibType('spread', i.methodName?.bestElement);
26+
27+
// TODO(jmesserly): Move JsName, JsPeerInterface to package:js (see issue #135).
28+
bool isJsNameAnnotation(DartObjectImpl value) => value.type.name == 'JsName';
29+
30+
bool isJsPeerInterface(DartObjectImpl value) =>
31+
value.type.name == 'JsPeerInterface';

pkg/dev_compiler/lib/src/compiler.dart

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -479,9 +479,11 @@ abstract class AbstractCompiler {
479479

480480
AnalysisErrorListener createErrorReporter(
481481
AnalysisContext context, CompilerOptions options) {
482-
return options.htmlReport ? new HtmlReporter(context) : options.dumpInfo
483-
? new SummaryReporter(context, options.logLevel)
484-
: new LogReporter(context, useColors: options.useColors);
482+
return options.htmlReport
483+
? new HtmlReporter(context)
484+
: options.dumpInfo
485+
? new SummaryReporter(context, options.logLevel)
486+
: new LogReporter(context, useColors: options.useColors);
485487
}
486488

487489
// TODO(jmesserly): find a better home for these.

pkg/dev_compiler/pubspec.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ dependencies:
1414
cli_util: ^0.0.1
1515
crypto: ^0.9.0
1616
html: ^0.12.0
17+
js: ^0.6.0-beta.6
1718
logging: ">=0.9.2 <0.12.0"
1819
path: ^1.3.0
1920
pub_semver: ^1.1.0
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
dart_library.library('js/src/varargs', null, /* Imports */[
2+
"dart/_runtime",
3+
'dart/core'
4+
], /* Lazy imports */[
5+
], function(exports, dart, core) {
6+
'use strict';
7+
let dartx = dart.dartx;
8+
class _Rest extends core.Object {
9+
_Rest() {
10+
}
11+
}
12+
dart.setSignature(_Rest, {
13+
constructors: () => ({_Rest: [_Rest, []]})
14+
});
15+
let rest = dart.const(new _Rest());
16+
function spread(args) {
17+
dart.throw(new core.StateError('The spread function cannot be called, ' + 'it should be compiled away.'));
18+
}
19+
dart.fn(spread);
20+
// Exports:
21+
exports.rest = rest;
22+
exports.spread = spread;
23+
});
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
// Messages from compiling varargs.dart
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
dart_library.library('varargs', null, /* Imports */[
2+
"dart/_runtime"
3+
], /* Lazy imports */[
4+
], function(exports, dart) {
5+
'use strict';
6+
let dartx = dart.dartx;
7+
function varargsTest(x, ...others) {
8+
let args = [1, others];
9+
dart.dsend(x, 'call', ...args);
10+
}
11+
dart.fn(varargsTest);
12+
function varargsTest2(x, ...others) {
13+
let args = [1, others];
14+
dart.dsend(x, 'call', ...args);
15+
}
16+
dart.fn(varargsTest2);
17+
// Exports:
18+
exports.varargsTest = varargsTest;
19+
exports.varargsTest2 = varargsTest2;
20+
});
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
// Messages from compiling varargs.dart
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import 'package:js/src/varargs.dart' as js;
2+
import 'package:js/src/varargs.dart' show rest, spread;
3+
4+
varargsTest(x, @js.rest others) {
5+
var args = [1, others];
6+
x.call(js.spread(args));
7+
}
8+
9+
varargsTest2(x, @rest others) {
10+
var args = [1, others];
11+
x.call(spread(args));
12+
}

pkg/dev_compiler/tool/input_sdk/private/js_helper.dart

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ class _Patch {
2424

2525
const _Patch patch = const _Patch();
2626

27-
2827
/// Marks the internal map in dart2js, so that internal libraries can is-check
2928
// them.
3029
abstract class InternalMap {
@@ -176,7 +175,7 @@ class Primitives {
176175
/// In minified mode, uses the unminified names if available.
177176
static String objectToString(Object object) {
178177
// String name = objectTypeName(object);
179-
String name = JS('String', 'dart.typeName(dart.realRuntimeType(#))', object);
178+
String name = JS('String', 'dart.typeName(dart.realRuntimeType(#))', object);
180179
return "Instance of '$name'";
181180
}
182181

pkg/dev_compiler/tool/sdk_expected_errors.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ warning: [DownCastComposite] IterableMixinWorkaround.firstWhere(this, test, orEl
1515
warning: [DownCastComposite] IterableMixinWorkaround.lastWhereList(this, test, orElse) (dynamic) will need runtime check to cast to type E (dart:_interceptors/js_array.dart, line 173, col 12)
1616
warning: [DownCastComposite] IterableMixinWorkaround.singleWhere(this, test) (dynamic) will need runtime check to cast to type E (dart:_interceptors/js_array.dart, line 177, col 12)
1717
warning: [DownCastComposite] JS('var', '#[#]', this, index) (dynamic) will need runtime check to cast to type E (dart:_interceptors/js_array.dart, line 313, col 12)
18-
warning: [DownCastComposite] charCodes (dynamic) will need runtime check to cast to type List<int> (dart:_js_helper, line 265, col 31)
19-
warning: [DownCastComposite] JS('', '#.value', ret) (dynamic) will need runtime check to cast to type E (dart:_js_helper, line 780, col 16)
18+
warning: [DownCastComposite] charCodes (dynamic) will need runtime check to cast to type List<int> (dart:_js_helper, line 264, col 31)
19+
warning: [DownCastComposite] JS('', '#.value', ret) (dynamic) will need runtime check to cast to type E (dart:_js_helper, line 779, col 16)
2020
warning: [DownCastComposite] JS('JSExtendableArray', r'#.split(#)', this, pattern) (dynamic) will need runtime check to cast to type List<String> (dart:_interceptors/js_string.dart, line 86, col 14)
2121
warning: [DownCastComposite] JS('JSExtendableArray', r'#.split(#)', this, re) (dynamic) will need runtime check to cast to type List<String> (dart:_interceptors/js_string.dart, line 89, col 14)
2222
warning: [DownCastComposite] JS('JSExtendableArray|Null', r'#.exec(#)', _nativeRegExp, checkString(string)) (dynamic) will need runtime check to cast to type List<String> (dart:_js_helper/regexp_helper.dart, line 108, col 22)

0 commit comments

Comments
 (0)