Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit fee865e

Browse files
author
Dart CI
committed
Version 2.13.0-111.0.dev
Merge commit 'b683098fde9611cea472cb081da2cea7ba15bc8b' into 'dev'
2 parents b776411 + b683098 commit fee865e

File tree

12 files changed

+195
-25
lines changed

12 files changed

+195
-25
lines changed
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Copyright (c) 2021, 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+
import 'package:kernel/ast.dart';
6+
import 'package:kernel/core_types.dart';
7+
import 'package:kernel/kernel.dart';
8+
9+
/// Replaces js_util methods with inline calls to foreign_helper JS which
10+
/// emits the code as a JavaScript code fragment.
11+
class JsUtilOptimizer extends Transformer {
12+
final Procedure _jsTarget;
13+
final Procedure _getPropertyTarget;
14+
15+
JsUtilOptimizer(CoreTypes coreTypes)
16+
: _jsTarget =
17+
coreTypes.index.getTopLevelMember('dart:_foreign_helper', 'JS'),
18+
_getPropertyTarget =
19+
coreTypes.index.getTopLevelMember('dart:js_util', 'getProperty') {}
20+
21+
/// Replaces js_util method calls with lowering straight to JS fragment call.
22+
///
23+
/// Lowers the following types of js_util calls:
24+
/// - `getProperty` for any argument types
25+
@override
26+
visitStaticInvocation(StaticInvocation node) {
27+
if (node.target == _getPropertyTarget) {
28+
node = _lowerGetProperty(node);
29+
}
30+
node.transformChildren(this);
31+
return node;
32+
}
33+
34+
/// Lowers the given js_util `getProperty` call to the foreign_helper JS call
35+
/// for any argument type. Lowers `getProperty(o, name)` to
36+
/// `JS('Object|Null', '#.#', o, name)`.
37+
StaticInvocation _lowerGetProperty(StaticInvocation node) {
38+
Arguments args = node.arguments;
39+
assert(args.positional.length == 2);
40+
return StaticInvocation(
41+
_jsTarget,
42+
Arguments(
43+
[
44+
StringLiteral("Object|Null"),
45+
StringLiteral("#.#"),
46+
args.positional.first,
47+
args.positional.last
48+
],
49+
// TODO(rileyporter): Copy type from getProperty when it's generic.
50+
types: [DynamicType()],
51+
))
52+
..fileOffset = node.fileOffset;
53+
}
54+
}

pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -106,18 +106,7 @@ double weightedAverage(
106106
localVariableDistance,
107107
startsWithDollar,
108108
superMatches,
109-
], [
110-
1.00, // contextType
111-
1.00, // elementKind
112-
0.50, // hasDeprecated
113-
1.00, // inheritanceDistance
114-
1.00, // isConstant
115-
1.00, // isNoSuchMethod
116-
1.00, // keyword
117-
1.00, // localVariableDistance
118-
0.50, // startsWithDollar
119-
1.00, // superMatches
120-
]);
109+
], FeatureComputer.featureWeights);
121110
return (average + 1.0) / 2.0;
122111
}
123112

@@ -138,6 +127,38 @@ double _weightedAverage(List<double> values, List<double> weights) {
138127

139128
/// An object that computes the values of features.
140129
class FeatureComputer {
130+
/// The names of features whose values are averaged.
131+
static List<String> featureNames = [
132+
'contextType',
133+
'elementKind',
134+
'hasDeprecated',
135+
'inheritanceDistance',
136+
'isConstant',
137+
'isNoSuchMethod',
138+
'keyword',
139+
'localVariableDistance',
140+
'startsWithDollar',
141+
'superMatches',
142+
];
143+
144+
/// The values of the weights used to compute an average of feature values.
145+
static List<double> featureWeights = defaultFeatureWeights;
146+
147+
/// The default values of the weights used to compute an average of feature
148+
/// values.
149+
static const List<double> defaultFeatureWeights = [
150+
1.00, // contextType
151+
1.00, // elementKind
152+
0.50, // hasDeprecated
153+
1.00, // inheritanceDistance
154+
1.00, // isConstant
155+
1.00, // isNoSuchMethod
156+
1.00, // keyword
157+
1.00, // localVariableDistance
158+
0.50, // startsWithDollar
159+
1.00, // superMatches
160+
];
161+
141162
/// The type system used to perform operations on types.
142163
final TypeSystem typeSystem;
143164

pkg/analysis_server/tool/code_completion/completion_metrics.dart

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import 'package:analysis_server/src/protocol_server.dart' as protocol;
1313
import 'package:analysis_server/src/services/completion/completion_core.dart';
1414
import 'package:analysis_server/src/services/completion/completion_performance.dart';
1515
import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
16+
import 'package:analysis_server/src/services/completion/dart/feature_computer.dart';
1617
import 'package:analysis_server/src/services/completion/dart/probability_range.dart';
1718
import 'package:analysis_server/src/services/completion/dart/relevance_tables.g.dart';
1819
import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
@@ -600,6 +601,21 @@ class CompletionMetricsComputer {
600601

601602
CompletionMetricsComputer(this.rootPath, this.options);
602603

604+
/// Compare the metrics when each feature is used in isolation.
605+
void compareIndividualFeatures() {
606+
var featureNames = FeatureComputer.featureNames;
607+
var featureCount = featureNames.length;
608+
for (var i = 0; i < featureCount; i++) {
609+
var weights = List.filled(featureCount, 0.00);
610+
weights[i] = 1.00;
611+
targetMetrics.add(CompletionMetrics(featureNames[i], enableFunction: () {
612+
FeatureComputer.featureWeights = weights;
613+
}, disableFunction: () {
614+
FeatureComputer.featureWeights = FeatureComputer.defaultFeatureWeights;
615+
}));
616+
}
617+
}
618+
603619
/// Compare the relevance [tables] to the default relevance tables.
604620
void compareRelevanceTables(List<RelevanceTables> tables) {
605621
assert(tables.isNotEmpty);
@@ -622,10 +638,14 @@ class CompletionMetricsComputer {
622638
enableFunction: null, disableFunction: null));
623639

624640
// To compare two or more relevance tables, uncomment the line below and
625-
// add the `RelevanceTable`s to the list. The default relevance tables
641+
// add the `RelevanceTables` to the list. The default relevance tables
626642
// should not be included in the list.
627643
// compareRelevanceTables([]);
628644

645+
// To compare the relative benefit from each of the features, uncomment the
646+
// line below.
647+
// compareIndividualFeatures();
648+
629649
final collection = AnalysisContextCollection(
630650
includedPaths: [rootPath],
631651
resourceProvider: PhysicalResourceProvider.INSTANCE,

pkg/compiler/lib/src/kernel/dart2js_target.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ library compiler.src.kernel.dart2js_target;
99
import 'package:_fe_analyzer_shared/src/messages/codes.dart'
1010
show Message, LocatedMessage;
1111
import 'package:_js_interop_checks/js_interop_checks.dart';
12+
import 'package:_js_interop_checks/src/transformations/js_util_optimizer.dart';
1213
import 'package:kernel/ast.dart' as ir;
1314
import 'package:kernel/class_hierarchy.dart';
1415
import 'package:kernel/core_types.dart';
@@ -92,8 +93,10 @@ class Dart2jsTarget extends Target {
9293

9394
@override
9495
List<String> get extraIndexedLibraries => const [
96+
'dart:_foreign_helper',
9597
'dart:_interceptors',
9698
'dart:_js_helper',
99+
'dart:js_util'
97100
];
98101

99102
@override
@@ -127,7 +130,11 @@ class Dart2jsTarget extends Target {
127130
{void logger(String msg),
128131
ChangedStructureNotifier changedStructureNotifier}) {
129132
_nativeClasses ??= JsInteropChecks.getNativeClasses(component);
133+
var jsUtilOptimizer = JsUtilOptimizer(coreTypes);
130134
for (var library in libraries) {
135+
// TODO (rileyporter): Merge js_util optimizations with other lowerings
136+
// in the single pass in `transformations/lowering.dart`.
137+
jsUtilOptimizer.visitLibrary(library);
131138
JsInteropChecks(
132139
coreTypes,
133140
diagnosticReporter as DiagnosticReporter<Message, LocatedMessage>,

pkg/dev_compiler/lib/src/kernel/target.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import 'package:kernel/target/changed_structure_notifier.dart';
1616
import 'package:kernel/target/targets.dart';
1717
import 'package:kernel/transformations/track_widget_constructor_locations.dart';
1818
import 'package:_js_interop_checks/js_interop_checks.dart';
19+
import 'package:_js_interop_checks/src/transformations/js_util_optimizer.dart';
1920

2021
import 'constants.dart' show DevCompilerConstantsBackend;
2122
import 'kernel_helpers.dart';
@@ -92,11 +93,13 @@ class DevCompilerTarget extends Target {
9293
'dart:collection',
9394
'dart:html',
9495
'dart:indexed_db',
96+
'dart:js_util',
9597
'dart:math',
9698
'dart:svg',
9799
'dart:web_audio',
98100
'dart:web_gl',
99101
'dart:web_sql',
102+
'dart:_foreign_helper',
100103
'dart:_interceptors',
101104
'dart:_js_helper',
102105
'dart:_native_typed_data',
@@ -152,8 +155,10 @@ class DevCompilerTarget extends Target {
152155
{void Function(String msg) logger,
153156
ChangedStructureNotifier changedStructureNotifier}) {
154157
_nativeClasses ??= JsInteropChecks.getNativeClasses(component);
158+
var jsUtilOptimizer = JsUtilOptimizer(coreTypes);
155159
for (var library in libraries) {
156160
_CovarianceTransformer(library).transform();
161+
jsUtilOptimizer.visitLibrary(library);
157162
JsInteropChecks(
158163
coreTypes,
159164
diagnosticReporter as DiagnosticReporter<Message, LocatedMessage>,

pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -989,6 +989,13 @@ class ConstantEvaluator extends ExpressionVisitor<Constant> {
989989
return result;
990990
}
991991

992+
/// Execute the statement using the [StatementConstantEvaluator].
993+
Constant execute(Statement statement) {
994+
StatementConstantEvaluator statementEvaluator =
995+
new StatementConstantEvaluator(this);
996+
return statement.accept(statementEvaluator);
997+
}
998+
992999
/// Create an error-constant indicating that an error has been detected during
9931000
/// constant evaluation.
9941001
AbortConstant createErrorConstant(TreeNode node, Message message,
@@ -2738,17 +2745,7 @@ class ConstantEvaluator extends ExpressionVisitor<Constant> {
27382745
if (value is AbortConstant) return value;
27392746
env.updateVariableValue(parameter, value);
27402747
}
2741-
Statement body = function.body;
2742-
if (body is ReturnStatement) {
2743-
if (!enableConstFunctions) {
2744-
return createInvalidExpressionConstant(
2745-
node, "Return statements are not supported.");
2746-
}
2747-
return body.expression.accept(this);
2748-
} else {
2749-
return createInvalidExpressionConstant(
2750-
node, "Unsupported statement: ${body.runtimeType}.");
2751-
}
2748+
return execute(function.body);
27522749
});
27532750
}
27542751

@@ -3209,6 +3206,27 @@ class ConstantEvaluator extends ExpressionVisitor<Constant> {
32093206
}
32103207
}
32113208

3209+
class StatementConstantEvaluator extends StatementVisitor<Constant> {
3210+
ConstantEvaluator exprEvaluator;
3211+
3212+
StatementConstantEvaluator(this.exprEvaluator) {
3213+
if (!exprEvaluator.enableConstFunctions) {
3214+
throw new UnsupportedError("Const functions feature is not enabled.");
3215+
}
3216+
}
3217+
3218+
/// Evaluate the expression using the [ConstantEvaluator].
3219+
Constant evaluate(Expression expr) => expr.accept(exprEvaluator);
3220+
3221+
@override
3222+
Constant defaultStatement(Statement node) => throw new UnsupportedError(
3223+
'Statement constant evaluation does not support ${node.runtimeType}.');
3224+
3225+
@override
3226+
Constant visitReturnStatement(ReturnStatement node) =>
3227+
evaluate(node.expression);
3228+
}
3229+
32123230
class ConstantCoverage {
32133231
final Map<Uri, Set<Reference>> constructorCoverage;
32143232

pkg/front_end/test/spell_checking_list_code.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,7 @@ establish
389389
established
390390
estimate
391391
eval
392+
execute
392393
exhausted
393394
existence
394395
existentially

tests/lib/js/js_util/properties_test.dart

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ class Foo {
3131
external num get a;
3232
external num bar();
3333
external Object get objectProperty;
34+
external List get list;
3435
}
3536

3637
@JS('Foo')
@@ -213,6 +214,11 @@ main() {
213214
js_util.callMethod(
214215
js_util.getProperty(f, 'fnList')[0], 'apply', [f, []]),
215216
equals(42));
217+
expect(js_util.getProperty(f.list, "0"), equals(2));
218+
var index = 0;
219+
expect(js_util.getProperty(f.list, index++), equals(2));
220+
expect(index, equals(1));
221+
expect(js_util.getProperty(f.list, index), equals(4));
216222

217223
// Accessing nested object properites.
218224
var objectProperty = js_util.getProperty(f, 'objectProperty');
@@ -222,6 +228,13 @@ main() {
222228
expect(
223229
js_util.getProperty(objectProperty, 'functionProperty') is Function,
224230
isTrue);
231+
// Using nested getProperty calls.
232+
expect(
233+
js_util.getProperty(
234+
js_util.getProperty(
235+
js_util.getProperty(f, 'objectProperty'), 'list'),
236+
1),
237+
equals(20));
225238

226239
// Using a variable for the property name.
227240
String propertyName = 'a';
@@ -289,6 +302,10 @@ main() {
289302
expect(js_util.getProperty(f.objectProperty, 'c'), equals('new val'));
290303
js_util.setProperty(f.objectProperty, 'list', [1, 2, 3]);
291304
expect(js_util.getProperty(f.objectProperty, 'list')[1], equals(2));
305+
// Using a nested getProperty call.
306+
js_util.setProperty(
307+
js_util.getProperty(f, 'objectProperty'), 'c', 'nested val');
308+
expect(js_util.getProperty(f.objectProperty, 'c'), equals('nested val'));
292309

293310
// Using a variable for the property name.
294311
String propertyName = 'bar';
@@ -317,6 +334,11 @@ main() {
317334
// Call method on a nested function property.
318335
expect(js_util.callMethod(f.objectProperty, 'functionProperty', []),
319336
equals('Function Property'));
337+
// Using a nested getProperty call.
338+
expect(
339+
js_util.callMethod(
340+
js_util.getProperty(f, 'objectProperty'), 'functionProperty', []),
341+
equals('Function Property'));
320342

321343
// Call method with different args.
322344
expect(

0 commit comments

Comments
 (0)