Version 2.13.0-111.0.dev
Merge commit 'b683098fde9611cea472cb081da2cea7ba15bc8b' into 'dev'
diff --git a/pkg/_js_interop_checks/lib/src/transformations/js_util_optimizer.dart b/pkg/_js_interop_checks/lib/src/transformations/js_util_optimizer.dart
new file mode 100644
index 0000000..d1d72dc
--- /dev/null
+++ b/pkg/_js_interop_checks/lib/src/transformations/js_util_optimizer.dart
@@ -0,0 +1,54 @@
+// Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:kernel/ast.dart';
+import 'package:kernel/core_types.dart';
+import 'package:kernel/kernel.dart';
+
+/// Replaces js_util methods with inline calls to foreign_helper JS which
+/// emits the code as a JavaScript code fragment.
+class JsUtilOptimizer extends Transformer {
+ final Procedure _jsTarget;
+ final Procedure _getPropertyTarget;
+
+ JsUtilOptimizer(CoreTypes coreTypes)
+ : _jsTarget =
+ coreTypes.index.getTopLevelMember('dart:_foreign_helper', 'JS'),
+ _getPropertyTarget =
+ coreTypes.index.getTopLevelMember('dart:js_util', 'getProperty') {}
+
+ /// Replaces js_util method calls with lowering straight to JS fragment call.
+ ///
+ /// Lowers the following types of js_util calls:
+ /// - `getProperty` for any argument types
+ @override
+ visitStaticInvocation(StaticInvocation node) {
+ if (node.target == _getPropertyTarget) {
+ node = _lowerGetProperty(node);
+ }
+ node.transformChildren(this);
+ return node;
+ }
+
+ /// Lowers the given js_util `getProperty` call to the foreign_helper JS call
+ /// for any argument type. Lowers `getProperty(o, name)` to
+ /// `JS('Object|Null', '#.#', o, name)`.
+ StaticInvocation _lowerGetProperty(StaticInvocation node) {
+ Arguments args = node.arguments;
+ assert(args.positional.length == 2);
+ return StaticInvocation(
+ _jsTarget,
+ Arguments(
+ [
+ StringLiteral("Object|Null"),
+ StringLiteral("#.#"),
+ args.positional.first,
+ args.positional.last
+ ],
+ // TODO(rileyporter): Copy type from getProperty when it's generic.
+ types: [DynamicType()],
+ ))
+ ..fileOffset = node.fileOffset;
+ }
+}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart b/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart
index 56d2102..795eabe 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/feature_computer.dart
@@ -106,18 +106,7 @@
localVariableDistance,
startsWithDollar,
superMatches,
- ], [
- 1.00, // contextType
- 1.00, // elementKind
- 0.50, // hasDeprecated
- 1.00, // inheritanceDistance
- 1.00, // isConstant
- 1.00, // isNoSuchMethod
- 1.00, // keyword
- 1.00, // localVariableDistance
- 0.50, // startsWithDollar
- 1.00, // superMatches
- ]);
+ ], FeatureComputer.featureWeights);
return (average + 1.0) / 2.0;
}
@@ -138,6 +127,38 @@
/// An object that computes the values of features.
class FeatureComputer {
+ /// The names of features whose values are averaged.
+ static List<String> featureNames = [
+ 'contextType',
+ 'elementKind',
+ 'hasDeprecated',
+ 'inheritanceDistance',
+ 'isConstant',
+ 'isNoSuchMethod',
+ 'keyword',
+ 'localVariableDistance',
+ 'startsWithDollar',
+ 'superMatches',
+ ];
+
+ /// The values of the weights used to compute an average of feature values.
+ static List<double> featureWeights = defaultFeatureWeights;
+
+ /// The default values of the weights used to compute an average of feature
+ /// values.
+ static const List<double> defaultFeatureWeights = [
+ 1.00, // contextType
+ 1.00, // elementKind
+ 0.50, // hasDeprecated
+ 1.00, // inheritanceDistance
+ 1.00, // isConstant
+ 1.00, // isNoSuchMethod
+ 1.00, // keyword
+ 1.00, // localVariableDistance
+ 0.50, // startsWithDollar
+ 1.00, // superMatches
+ ];
+
/// The type system used to perform operations on types.
final TypeSystem typeSystem;
diff --git a/pkg/analysis_server/tool/code_completion/completion_metrics.dart b/pkg/analysis_server/tool/code_completion/completion_metrics.dart
index 2a9e75d..744cd50 100644
--- a/pkg/analysis_server/tool/code_completion/completion_metrics.dart
+++ b/pkg/analysis_server/tool/code_completion/completion_metrics.dart
@@ -13,6 +13,7 @@
import 'package:analysis_server/src/services/completion/completion_core.dart';
import 'package:analysis_server/src/services/completion/completion_performance.dart';
import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
+import 'package:analysis_server/src/services/completion/dart/feature_computer.dart';
import 'package:analysis_server/src/services/completion/dart/probability_range.dart';
import 'package:analysis_server/src/services/completion/dart/relevance_tables.g.dart';
import 'package:analysis_server/src/services/completion/dart/suggestion_builder.dart';
@@ -600,6 +601,21 @@
CompletionMetricsComputer(this.rootPath, this.options);
+ /// Compare the metrics when each feature is used in isolation.
+ void compareIndividualFeatures() {
+ var featureNames = FeatureComputer.featureNames;
+ var featureCount = featureNames.length;
+ for (var i = 0; i < featureCount; i++) {
+ var weights = List.filled(featureCount, 0.00);
+ weights[i] = 1.00;
+ targetMetrics.add(CompletionMetrics(featureNames[i], enableFunction: () {
+ FeatureComputer.featureWeights = weights;
+ }, disableFunction: () {
+ FeatureComputer.featureWeights = FeatureComputer.defaultFeatureWeights;
+ }));
+ }
+ }
+
/// Compare the relevance [tables] to the default relevance tables.
void compareRelevanceTables(List<RelevanceTables> tables) {
assert(tables.isNotEmpty);
@@ -622,10 +638,14 @@
enableFunction: null, disableFunction: null));
// To compare two or more relevance tables, uncomment the line below and
- // add the `RelevanceTable`s to the list. The default relevance tables
+ // add the `RelevanceTables` to the list. The default relevance tables
// should not be included in the list.
// compareRelevanceTables([]);
+ // To compare the relative benefit from each of the features, uncomment the
+ // line below.
+// compareIndividualFeatures();
+
final collection = AnalysisContextCollection(
includedPaths: [rootPath],
resourceProvider: PhysicalResourceProvider.INSTANCE,
diff --git a/pkg/compiler/lib/src/kernel/dart2js_target.dart b/pkg/compiler/lib/src/kernel/dart2js_target.dart
index 5103adc..60301f2 100644
--- a/pkg/compiler/lib/src/kernel/dart2js_target.dart
+++ b/pkg/compiler/lib/src/kernel/dart2js_target.dart
@@ -9,6 +9,7 @@
import 'package:_fe_analyzer_shared/src/messages/codes.dart'
show Message, LocatedMessage;
import 'package:_js_interop_checks/js_interop_checks.dart';
+import 'package:_js_interop_checks/src/transformations/js_util_optimizer.dart';
import 'package:kernel/ast.dart' as ir;
import 'package:kernel/class_hierarchy.dart';
import 'package:kernel/core_types.dart';
@@ -92,8 +93,10 @@
@override
List<String> get extraIndexedLibraries => const [
+ 'dart:_foreign_helper',
'dart:_interceptors',
'dart:_js_helper',
+ 'dart:js_util'
];
@override
@@ -127,7 +130,11 @@
{void logger(String msg),
ChangedStructureNotifier changedStructureNotifier}) {
_nativeClasses ??= JsInteropChecks.getNativeClasses(component);
+ var jsUtilOptimizer = JsUtilOptimizer(coreTypes);
for (var library in libraries) {
+ // TODO (rileyporter): Merge js_util optimizations with other lowerings
+ // in the single pass in `transformations/lowering.dart`.
+ jsUtilOptimizer.visitLibrary(library);
JsInteropChecks(
coreTypes,
diagnosticReporter as DiagnosticReporter<Message, LocatedMessage>,
diff --git a/pkg/dev_compiler/lib/src/kernel/target.dart b/pkg/dev_compiler/lib/src/kernel/target.dart
index 8318288..ffc64a4 100644
--- a/pkg/dev_compiler/lib/src/kernel/target.dart
+++ b/pkg/dev_compiler/lib/src/kernel/target.dart
@@ -16,6 +16,7 @@
import 'package:kernel/target/targets.dart';
import 'package:kernel/transformations/track_widget_constructor_locations.dart';
import 'package:_js_interop_checks/js_interop_checks.dart';
+import 'package:_js_interop_checks/src/transformations/js_util_optimizer.dart';
import 'constants.dart' show DevCompilerConstantsBackend;
import 'kernel_helpers.dart';
@@ -92,11 +93,13 @@
'dart:collection',
'dart:html',
'dart:indexed_db',
+ 'dart:js_util',
'dart:math',
'dart:svg',
'dart:web_audio',
'dart:web_gl',
'dart:web_sql',
+ 'dart:_foreign_helper',
'dart:_interceptors',
'dart:_js_helper',
'dart:_native_typed_data',
@@ -152,8 +155,10 @@
{void Function(String msg) logger,
ChangedStructureNotifier changedStructureNotifier}) {
_nativeClasses ??= JsInteropChecks.getNativeClasses(component);
+ var jsUtilOptimizer = JsUtilOptimizer(coreTypes);
for (var library in libraries) {
_CovarianceTransformer(library).transform();
+ jsUtilOptimizer.visitLibrary(library);
JsInteropChecks(
coreTypes,
diagnosticReporter as DiagnosticReporter<Message, LocatedMessage>,
diff --git a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
index 547cc29..a759519 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
@@ -989,6 +989,13 @@
return result;
}
+ /// Execute the statement using the [StatementConstantEvaluator].
+ Constant execute(Statement statement) {
+ StatementConstantEvaluator statementEvaluator =
+ new StatementConstantEvaluator(this);
+ return statement.accept(statementEvaluator);
+ }
+
/// Create an error-constant indicating that an error has been detected during
/// constant evaluation.
AbortConstant createErrorConstant(TreeNode node, Message message,
@@ -2738,17 +2745,7 @@
if (value is AbortConstant) return value;
env.updateVariableValue(parameter, value);
}
- Statement body = function.body;
- if (body is ReturnStatement) {
- if (!enableConstFunctions) {
- return createInvalidExpressionConstant(
- node, "Return statements are not supported.");
- }
- return body.expression.accept(this);
- } else {
- return createInvalidExpressionConstant(
- node, "Unsupported statement: ${body.runtimeType}.");
- }
+ return execute(function.body);
});
}
@@ -3209,6 +3206,27 @@
}
}
+class StatementConstantEvaluator extends StatementVisitor<Constant> {
+ ConstantEvaluator exprEvaluator;
+
+ StatementConstantEvaluator(this.exprEvaluator) {
+ if (!exprEvaluator.enableConstFunctions) {
+ throw new UnsupportedError("Const functions feature is not enabled.");
+ }
+ }
+
+ /// Evaluate the expression using the [ConstantEvaluator].
+ Constant evaluate(Expression expr) => expr.accept(exprEvaluator);
+
+ @override
+ Constant defaultStatement(Statement node) => throw new UnsupportedError(
+ 'Statement constant evaluation does not support ${node.runtimeType}.');
+
+ @override
+ Constant visitReturnStatement(ReturnStatement node) =>
+ evaluate(node.expression);
+}
+
class ConstantCoverage {
final Map<Uri, Set<Reference>> constructorCoverage;
diff --git a/pkg/front_end/test/spell_checking_list_code.txt b/pkg/front_end/test/spell_checking_list_code.txt
index 8fe1b6b..ba25ffb 100644
--- a/pkg/front_end/test/spell_checking_list_code.txt
+++ b/pkg/front_end/test/spell_checking_list_code.txt
@@ -389,6 +389,7 @@
established
estimate
eval
+execute
exhausted
existence
existentially
diff --git a/tests/language/const_functions/const_functions_disabled_simple_invocations.dart b/tests/language/const_functions/const_functions_disabled_simple_invocations_test.dart
similarity index 100%
rename from tests/language/const_functions/const_functions_disabled_simple_invocations.dart
rename to tests/language/const_functions/const_functions_disabled_simple_invocations_test.dart
diff --git a/tests/language/const_functions/const_functions_simple_invocations.dart b/tests/language/const_functions/const_functions_simple_invocations_test.dart
similarity index 100%
rename from tests/language/const_functions/const_functions_simple_invocations.dart
rename to tests/language/const_functions/const_functions_simple_invocations_test.dart
diff --git a/tests/lib/js/js_util/properties_test.dart b/tests/lib/js/js_util/properties_test.dart
index 986c431..ab0b844 100644
--- a/tests/lib/js/js_util/properties_test.dart
+++ b/tests/lib/js/js_util/properties_test.dart
@@ -31,6 +31,7 @@
external num get a;
external num bar();
external Object get objectProperty;
+ external List get list;
}
@JS('Foo')
@@ -213,6 +214,11 @@
js_util.callMethod(
js_util.getProperty(f, 'fnList')[0], 'apply', [f, []]),
equals(42));
+ expect(js_util.getProperty(f.list, "0"), equals(2));
+ var index = 0;
+ expect(js_util.getProperty(f.list, index++), equals(2));
+ expect(index, equals(1));
+ expect(js_util.getProperty(f.list, index), equals(4));
// Accessing nested object properites.
var objectProperty = js_util.getProperty(f, 'objectProperty');
@@ -222,6 +228,13 @@
expect(
js_util.getProperty(objectProperty, 'functionProperty') is Function,
isTrue);
+ // Using nested getProperty calls.
+ expect(
+ js_util.getProperty(
+ js_util.getProperty(
+ js_util.getProperty(f, 'objectProperty'), 'list'),
+ 1),
+ equals(20));
// Using a variable for the property name.
String propertyName = 'a';
@@ -289,6 +302,10 @@
expect(js_util.getProperty(f.objectProperty, 'c'), equals('new val'));
js_util.setProperty(f.objectProperty, 'list', [1, 2, 3]);
expect(js_util.getProperty(f.objectProperty, 'list')[1], equals(2));
+ // Using a nested getProperty call.
+ js_util.setProperty(
+ js_util.getProperty(f, 'objectProperty'), 'c', 'nested val');
+ expect(js_util.getProperty(f.objectProperty, 'c'), equals('nested val'));
// Using a variable for the property name.
String propertyName = 'bar';
@@ -317,6 +334,11 @@
// Call method on a nested function property.
expect(js_util.callMethod(f.objectProperty, 'functionProperty', []),
equals('Function Property'));
+ // Using a nested getProperty call.
+ expect(
+ js_util.callMethod(
+ js_util.getProperty(f, 'objectProperty'), 'functionProperty', []),
+ equals('Function Property'));
// Call method with different args.
expect(
diff --git a/tests/lib_2/js/js_util/properties_test.dart b/tests/lib_2/js/js_util/properties_test.dart
index 986c431..ab0b844 100644
--- a/tests/lib_2/js/js_util/properties_test.dart
+++ b/tests/lib_2/js/js_util/properties_test.dart
@@ -31,6 +31,7 @@
external num get a;
external num bar();
external Object get objectProperty;
+ external List get list;
}
@JS('Foo')
@@ -213,6 +214,11 @@
js_util.callMethod(
js_util.getProperty(f, 'fnList')[0], 'apply', [f, []]),
equals(42));
+ expect(js_util.getProperty(f.list, "0"), equals(2));
+ var index = 0;
+ expect(js_util.getProperty(f.list, index++), equals(2));
+ expect(index, equals(1));
+ expect(js_util.getProperty(f.list, index), equals(4));
// Accessing nested object properites.
var objectProperty = js_util.getProperty(f, 'objectProperty');
@@ -222,6 +228,13 @@
expect(
js_util.getProperty(objectProperty, 'functionProperty') is Function,
isTrue);
+ // Using nested getProperty calls.
+ expect(
+ js_util.getProperty(
+ js_util.getProperty(
+ js_util.getProperty(f, 'objectProperty'), 'list'),
+ 1),
+ equals(20));
// Using a variable for the property name.
String propertyName = 'a';
@@ -289,6 +302,10 @@
expect(js_util.getProperty(f.objectProperty, 'c'), equals('new val'));
js_util.setProperty(f.objectProperty, 'list', [1, 2, 3]);
expect(js_util.getProperty(f.objectProperty, 'list')[1], equals(2));
+ // Using a nested getProperty call.
+ js_util.setProperty(
+ js_util.getProperty(f, 'objectProperty'), 'c', 'nested val');
+ expect(js_util.getProperty(f.objectProperty, 'c'), equals('nested val'));
// Using a variable for the property name.
String propertyName = 'bar';
@@ -317,6 +334,11 @@
// Call method on a nested function property.
expect(js_util.callMethod(f.objectProperty, 'functionProperty', []),
equals('Function Property'));
+ // Using a nested getProperty call.
+ expect(
+ js_util.callMethod(
+ js_util.getProperty(f, 'objectProperty'), 'functionProperty', []),
+ equals('Function Property'));
// Call method with different args.
expect(
diff --git a/tools/VERSION b/tools/VERSION
index 283b038..24f1ba5 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 13
PATCH 0
-PRERELEASE 110
+PRERELEASE 111
PRERELEASE_PATCH 0
\ No newline at end of file