Version 2.14.0-38.0.dev
Merge commit '90c309e9e436e3a9187225cd6c2d0dc95cfb7702' into 'dev'
diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json
index 6709196..761daab 100644
--- a/.dart_tool/package_config.json
+++ b/.dart_tool/package_config.json
@@ -11,7 +11,7 @@
"constraint, update this by running tools/generate_package_config.dart."
],
"configVersion": 2,
- "generated": "2021-04-22T20:51:04.585975",
+ "generated": "2021-04-23T17:16:06.111697",
"generator": "tools/generate_package_config.dart",
"packages": [
{
@@ -381,7 +381,7 @@
"name": "json_rpc_2",
"rootUri": "../third_party/pkg/json_rpc_2",
"packageUri": "lib/",
- "languageVersion": "2.2"
+ "languageVersion": "2.12"
},
{
"name": "kernel",
diff --git a/DEPS b/DEPS
index dab41b0..a7cc76e 100644
--- a/DEPS
+++ b/DEPS
@@ -123,7 +123,7 @@
"idl_parser_rev": "5fb1ebf49d235b5a70c9f49047e83b0654031eb7",
"intl_tag": "0.17.0-nullsafety",
"jinja2_rev": "2222b31554f03e62600cd7e383376a7c187967a1",
- "json_rpc_2_rev": "b8dfe403fd8528fd14399dee3a6527b55802dd4d",
+ "json_rpc_2_rev": "5ec32a2e0e99dedcef5b3237f93167cd22c2da50",
"linter_tag": "1.3.0",
"logging_rev": "e2f633b543ef89c54688554b15ca3d7e425b86a2",
"markupsafe_rev": "8f45f5cfa0009d2a70589bcda0349b8cb2b72783",
diff --git a/pkg/_fe_analyzer_shared/lib/src/scanner/token.dart b/pkg/_fe_analyzer_shared/lib/src/scanner/token.dart
index 4cc7473..74a310a 100644
--- a/pkg/_fe_analyzer_shared/lib/src/scanner/token.dart
+++ b/pkg/_fe_analyzer_shared/lib/src/scanner/token.dart
@@ -1269,11 +1269,11 @@
static const TokenType AMPERSAND = const TokenType(
'&', 'AMPERSAND', BITWISE_AND_PRECEDENCE, AMPERSAND_TOKEN,
- isOperator: true, isUserDefinableOperator: true);
+ isOperator: true, isBinaryOperator: true, isUserDefinableOperator: true);
static const TokenType AMPERSAND_AMPERSAND = const TokenType('&&',
'AMPERSAND_AMPERSAND', LOGICAL_AND_PRECEDENCE, AMPERSAND_AMPERSAND_TOKEN,
- isOperator: true);
+ isOperator: true, isBinaryOperator: true);
// This is not yet part of the language and not supported by fasta
static const TokenType AMPERSAND_AMPERSAND_EQ = const TokenType(
@@ -1303,11 +1303,11 @@
static const TokenType BAR = const TokenType(
'|', 'BAR', BITWISE_OR_PRECEDENCE, BAR_TOKEN,
- isOperator: true, isUserDefinableOperator: true);
+ isOperator: true, isBinaryOperator: true, isUserDefinableOperator: true);
static const TokenType BAR_BAR = const TokenType(
'||', 'BAR_BAR', LOGICAL_OR_PRECEDENCE, BAR_BAR_TOKEN,
- isOperator: true);
+ isOperator: true, isBinaryOperator: true);
// This is not yet part of the language and not supported by fasta
static const TokenType BAR_BAR_EQ = const TokenType(
@@ -1326,7 +1326,7 @@
static const TokenType CARET = const TokenType(
'^', 'CARET', BITWISE_XOR_PRECEDENCE, CARET_TOKEN,
- isOperator: true, isUserDefinableOperator: true);
+ isOperator: true, isBinaryOperator: true, isUserDefinableOperator: true);
static const TokenType CARET_EQ = const TokenType(
'^=', 'CARET_EQ', ASSIGNMENT_PRECEDENCE, CARET_EQ_TOKEN,
@@ -1347,7 +1347,7 @@
static const TokenType EQ_EQ = const TokenType(
'==', 'EQ_EQ', EQUALITY_PRECEDENCE, EQ_EQ_TOKEN,
- isOperator: true, isUserDefinableOperator: true);
+ isOperator: true, isBinaryOperator: true, isUserDefinableOperator: true);
/// The `===` operator is not supported in the Dart language
/// but is parsed as such by the scanner to support better recovery
@@ -1360,15 +1360,15 @@
static const TokenType GT = const TokenType(
'>', 'GT', RELATIONAL_PRECEDENCE, GT_TOKEN,
- isOperator: true, isUserDefinableOperator: true);
+ isOperator: true, isBinaryOperator: true, isUserDefinableOperator: true);
static const TokenType GT_EQ = const TokenType(
'>=', 'GT_EQ', RELATIONAL_PRECEDENCE, GT_EQ_TOKEN,
- isOperator: true, isUserDefinableOperator: true);
+ isOperator: true, isBinaryOperator: true, isUserDefinableOperator: true);
static const TokenType GT_GT = const TokenType(
'>>', 'GT_GT', SHIFT_PRECEDENCE, GT_GT_TOKEN,
- isOperator: true, isUserDefinableOperator: true);
+ isOperator: true, isBinaryOperator: true, isUserDefinableOperator: true);
static const TokenType GT_GT_EQ = const TokenType(
'>>=', 'GT_GT_EQ', ASSIGNMENT_PRECEDENCE, GT_GT_EQ_TOKEN,
@@ -1376,7 +1376,7 @@
static const TokenType GT_GT_GT = const TokenType(
'>>>', 'GT_GT_GT', SHIFT_PRECEDENCE, GT_GT_GT_TOKEN,
- isOperator: true, isUserDefinableOperator: true);
+ isOperator: true, isBinaryOperator: true, isUserDefinableOperator: true);
static const TokenType GT_GT_GT_EQ = const TokenType(
'>>>=', 'GT_GT_GT_EQ', ASSIGNMENT_PRECEDENCE, GT_GT_GT_EQ_TOKEN,
@@ -1395,15 +1395,15 @@
static const TokenType LT = const TokenType(
'<', 'LT', RELATIONAL_PRECEDENCE, LT_TOKEN,
- isOperator: true, isUserDefinableOperator: true);
+ isOperator: true, isBinaryOperator: true, isUserDefinableOperator: true);
static const TokenType LT_EQ = const TokenType(
'<=', 'LT_EQ', RELATIONAL_PRECEDENCE, LT_EQ_TOKEN,
- isOperator: true, isUserDefinableOperator: true);
+ isOperator: true, isBinaryOperator: true, isUserDefinableOperator: true);
static const TokenType LT_LT = const TokenType(
'<<', 'LT_LT', SHIFT_PRECEDENCE, LT_LT_TOKEN,
- isOperator: true, isUserDefinableOperator: true);
+ isOperator: true, isBinaryOperator: true, isUserDefinableOperator: true);
static const TokenType LT_LT_EQ = const TokenType(
'<<=', 'LT_LT_EQ', ASSIGNMENT_PRECEDENCE, LT_LT_EQ_TOKEN,
@@ -1411,7 +1411,7 @@
static const TokenType MINUS = const TokenType(
'-', 'MINUS', ADDITIVE_PRECEDENCE, MINUS_TOKEN,
- isOperator: true, isUserDefinableOperator: true);
+ isOperator: true, isBinaryOperator: true, isUserDefinableOperator: true);
static const TokenType MINUS_EQ = const TokenType(
'-=', 'MINUS_EQ', ASSIGNMENT_PRECEDENCE, MINUS_EQ_TOKEN,
@@ -1432,7 +1432,7 @@
static const TokenType PERCENT = const TokenType(
'%', 'PERCENT', MULTIPLICATIVE_PRECEDENCE, PERCENT_TOKEN,
- isOperator: true, isUserDefinableOperator: true);
+ isOperator: true, isBinaryOperator: true, isUserDefinableOperator: true);
static const TokenType PERCENT_EQ = const TokenType(
'%=', 'PERCENT_EQ', ASSIGNMENT_PRECEDENCE, PERCENT_EQ_TOKEN,
@@ -1447,7 +1447,7 @@
static const TokenType PLUS = const TokenType(
'+', 'PLUS', ADDITIVE_PRECEDENCE, PLUS_TOKEN,
- isOperator: true, isUserDefinableOperator: true);
+ isOperator: true, isBinaryOperator: true, isUserDefinableOperator: true);
static const TokenType PLUS_EQ = const TokenType(
'+=', 'PLUS_EQ', ASSIGNMENT_PRECEDENCE, PLUS_EQ_TOKEN,
@@ -1467,7 +1467,7 @@
static const TokenType QUESTION_QUESTION = const TokenType(
'??', 'QUESTION_QUESTION', IF_NULL_PRECEDENCE, QUESTION_QUESTION_TOKEN,
- isOperator: true);
+ isOperator: true, isBinaryOperator: true);
static const TokenType QUESTION_QUESTION_EQ = const TokenType('??=',
'QUESTION_QUESTION_EQ', ASSIGNMENT_PRECEDENCE, QUESTION_QUESTION_EQ_TOKEN,
@@ -1478,7 +1478,7 @@
static const TokenType SLASH = const TokenType(
'/', 'SLASH', MULTIPLICATIVE_PRECEDENCE, SLASH_TOKEN,
- isOperator: true, isUserDefinableOperator: true);
+ isOperator: true, isBinaryOperator: true, isUserDefinableOperator: true);
static const TokenType SLASH_EQ = const TokenType(
'/=', 'SLASH_EQ', ASSIGNMENT_PRECEDENCE, SLASH_EQ_TOKEN,
@@ -1486,7 +1486,7 @@
static const TokenType STAR = const TokenType(
'*', 'STAR', MULTIPLICATIVE_PRECEDENCE, STAR_TOKEN,
- isOperator: true, isUserDefinableOperator: true);
+ isOperator: true, isBinaryOperator: true, isUserDefinableOperator: true);
static const TokenType STAR_EQ = const TokenType(
'*=', 'STAR_EQ', ASSIGNMENT_PRECEDENCE, STAR_EQ_TOKEN,
@@ -1510,7 +1510,7 @@
static const TokenType TILDE_SLASH = const TokenType(
'~/', 'TILDE_SLASH', MULTIPLICATIVE_PRECEDENCE, TILDE_SLASH_TOKEN,
- isOperator: true, isUserDefinableOperator: true);
+ isOperator: true, isBinaryOperator: true, isUserDefinableOperator: true);
static const TokenType TILDE_SLASH_EQ = const TokenType(
'~/=', 'TILDE_SLASH_EQ', ASSIGNMENT_PRECEDENCE, TILDE_SLASH_EQ_TOKEN,
@@ -1661,6 +1661,11 @@
final bool isOperator;
/**
+ * `true` if this token type represents a binary operator.
+ */
+ final bool isBinaryOperator;
+
+ /**
* `true` if this token type represents a keyword starting a top level
* declaration such as `class`, `enum`, `import`, etc.
*/
@@ -1697,6 +1702,7 @@
const TokenType(this.lexeme, this.name, this.precedence, this.kind,
{this.isModifier: false,
this.isOperator: false,
+ this.isBinaryOperator: false,
this.isTopLevelKeyword: false,
this.isUserDefinableOperator: false,
String? stringValue: 'unspecified'})
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 084d2b3..c6f96a4 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -338,6 +338,7 @@
CompileTimeErrorCode.NON_VOID_RETURN_FOR_SETTER,
CompileTimeErrorCode.NOT_A_TYPE,
CompileTimeErrorCode.NOT_ASSIGNED_POTENTIALLY_NON_NULLABLE_LOCAL_VARIABLE,
+ CompileTimeErrorCode.NOT_BINARY_OPERATOR,
CompileTimeErrorCode.NOT_ENOUGH_POSITIONAL_ARGUMENTS,
CompileTimeErrorCode.NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD,
CompileTimeErrorCode.NOT_INITIALIZED_NON_NULLABLE_INSTANCE_FIELD_CONSTRUCTOR,
diff --git a/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart
index 4e6836f..abb22ed 100644
--- a/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/binary_expression_resolver.dart
@@ -27,7 +27,7 @@
BinaryExpressionResolver({
required ResolverVisitor resolver,
- }) : _resolver = resolver,
+ }) : _resolver = resolver,
_typePropertyResolver = resolver.typePropertyResolver,
_inferenceHelper = resolver.inferenceHelper;
@@ -62,11 +62,17 @@
return;
}
- if (operator.isUserDefinableOperator) {
+ if (operator.isUserDefinableOperator && operator.isBinaryOperator) {
_resolveUserDefinable(node);
return;
}
+ // Report an error if not already reported by the parser.
+ if (operator != TokenType.BANG_EQ_EQ && operator != TokenType.EQ_EQ_EQ) {
+ _errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.NOT_BINARY_OPERATOR, node, [operator.lexeme]);
+ }
+
_resolveUnsupportedOperator(node);
}
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index 9900a5e..7337eb5 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -9573,6 +9573,13 @@
/**
* Parameters:
+ * 0: the name of the operator that is not a binary operator.
+ */
+ static const CompileTimeErrorCode NOT_BINARY_OPERATOR = CompileTimeErrorCode(
+ 'NOT_BINARY_OPERATOR', "'{0}' isn't a binary operator.");
+
+ /**
+ * Parameters:
* 0: the expected number of required arguments
* 1: the actual number of positional arguments given
*/
diff --git a/pkg/analyzer/test/src/dart/resolution/binary_expression_test.dart b/pkg/analyzer/test/src/dart/resolution/binary_expression_test.dart
index 99c85ca..f3f1dea 100644
--- a/pkg/analyzer/test/src/dart/resolution/binary_expression_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/binary_expression_test.dart
@@ -147,6 +147,25 @@
);
}
+ test_bangEqEq() async {
+ await assertErrorsInCode(r'''
+f(int a, int b) {
+ a !== b;
+}
+''', [
+ error(ScannerErrorCode.UNSUPPORTED_OPERATOR, 22, 1),
+ ]);
+
+ assertBinaryExpression(
+ findNode.binary('a !== b'),
+ element: null,
+ type: 'dynamic',
+ );
+
+ assertType(findNode.simple('a !=='), 'int');
+ assertType(findNode.simple('b;'), 'int');
+ }
+
test_eqEq() async {
await assertNoErrorsInCode(r'''
f(int a, int b) {
diff --git a/pkg/analyzer/test/src/diagnostics/not_binary_operator_test.dart b/pkg/analyzer/test/src/diagnostics/not_binary_operator_test.dart
new file mode 100644
index 0000000..8d80332
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/not_binary_operator_test.dart
@@ -0,0 +1,23 @@
+// 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:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/context_collection_resolution.dart';
+
+main() {
+ defineReflectiveSuite(() {
+ defineReflectiveTests(NonBinaryOperatorTest);
+ });
+}
+
+@reflectiveTest
+class NonBinaryOperatorTest extends PubPackageResolutionTest {
+ test_unaryTilde() async {
+ await assertErrorsInCode('var a = 5 ~ 3;', [
+ error(CompileTimeErrorCode.NOT_BINARY_OPERATOR, 8, 5),
+ ]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/test_all.dart b/pkg/analyzer/test/src/diagnostics/test_all.dart
index 3d1234d..943c049 100644
--- a/pkg/analyzer/test/src/diagnostics/test_all.dart
+++ b/pkg/analyzer/test/src/diagnostics/test_all.dart
@@ -472,6 +472,7 @@
import 'not_a_type_test.dart' as not_a_type;
import 'not_assigned_potentially_non_nullable_local_variable_test.dart'
as not_assigned_potentially_non_nullable_local_variable;
+import 'not_binary_operator_test.dart' as not_binary_operator;
import 'not_enough_positional_arguments_test.dart'
as not_enough_positional_arguments;
import 'not_initialized_non_nullable_instance_field_test.dart'
@@ -970,6 +971,8 @@
non_bool_expression.main();
non_bool_negation_expression.main();
non_bool_operand.main();
+ non_const_call_to_literal_constructor.main();
+ non_const_map_as_expression_statement.main();
non_constant_annotation_constructor.main();
non_constant_list_element.main();
non_constant_case_expression_from_deferred_library.main();
@@ -995,8 +998,7 @@
non_void_return_for_setter.main();
not_a_type.main();
not_assigned_potentially_non_nullable_local_variable.main();
- non_const_call_to_literal_constructor.main();
- non_const_map_as_expression_statement.main();
+ not_binary_operator.main();
not_enough_positional_arguments.main();
not_initialized_non_nullable_instance_field.main();
not_initialized_non_nullable_variable.main();
diff --git a/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart b/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
index 8079a1e..b016b86 100644
--- a/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/class_stub_generator.dart
@@ -215,85 +215,101 @@
/// * `isStatic`.
/// * `name`.
/// * `isIntercepted.
-List<jsAst.Statement> buildTearOffCode(CompilerOptions options, Emitter emitter,
- Namer namer, CommonElements commonElements) {
+List<jsAst.Statement> buildTearOffCode(
+ CompilerOptions options, Emitter emitter, CommonElements commonElements) {
FunctionEntity closureFromTearOff = commonElements.closureFromTearOff;
- jsAst.Expression tearOffAccessExpression;
- jsAst.Expression tearOffGlobalObjectString;
- jsAst.Expression tearOffGlobalObject;
+ jsAst.Expression closureFromTearOffAccessExpression;
if (closureFromTearOff != null) {
- tearOffAccessExpression = emitter.staticFunctionAccess(closureFromTearOff);
- tearOffGlobalObject =
- js.stringPart(namer.globalObjectForMember(closureFromTearOff));
- tearOffGlobalObjectString =
- js.string(namer.globalObjectForMember(closureFromTearOff));
+ closureFromTearOffAccessExpression =
+ emitter.staticFunctionAccess(closureFromTearOff);
} else {
// Default values for mocked-up test libraries.
- tearOffAccessExpression =
+ closureFromTearOffAccessExpression =
js(r'''function() { throw "Helper 'closureFromTearOff' missing." }''');
- tearOffGlobalObjectString = js.string('MissingHelperFunction');
- tearOffGlobalObject = js(
- r'''(function() { throw "Helper 'closureFromTearOff' missing." })()''');
}
jsAst.Statement tearOffGetter;
- if (!options.useContentSecurityPolicy) {
- jsAst.Expression tearOffAccessText = new jsAst.UnparsedNode(
- tearOffAccessExpression, options.enableMinification, false);
- tearOffGetter = js.statement('''
-function tearOffGetter(funcs, applyTrampolineIndex, reflectionInfo, name, isIntercepted) {
- return isIntercepted
- ? new Function("funcs", "applyTrampolineIndex", "reflectionInfo", "name",
- #tearOffGlobalObjectString, "c",
- "return function tearOff_" + name + (functionCounter++) + "(receiver) {" +
- "if (c === null) c = " + #tearOffAccessText + "(" +
- "this, funcs, applyTrampolineIndex, reflectionInfo, false, true, name);" +
- "return new c(this, funcs[0], receiver, name);" +
- "}")(funcs, applyTrampolineIndex, reflectionInfo, name, #tearOffGlobalObject, null)
- : new Function("funcs", "applyTrampolineIndex", "reflectionInfo", "name",
- #tearOffGlobalObjectString, "c",
- "return function tearOff_" + name + (functionCounter++)+ "() {" +
- "if (c === null) c = " + #tearOffAccessText + "(" +
- "this, funcs, applyTrampolineIndex, reflectionInfo, false, false, name);" +
- "return new c(this, funcs[0], null, name);" +
- "}")(funcs, applyTrampolineIndex, reflectionInfo, name, #tearOffGlobalObject, null);
-}''', {
- 'tearOffAccessText': tearOffAccessText,
- 'tearOffGlobalObject': tearOffGlobalObject,
- 'tearOffGlobalObjectString': tearOffGlobalObjectString
- });
- } else {
- tearOffGetter = js.statement('''
+ if (options.useContentSecurityPolicy) {
+ tearOffGetter = js.statement(
+ '''
function tearOffGetter(funcs, applyTrampolineIndex, reflectionInfo, name, isIntercepted) {
var cache = null;
return isIntercepted
? function(receiver) {
- if (cache === null) cache = #(
+ if (cache === null) cache = #createTearOffClass(
this, funcs, applyTrampolineIndex, reflectionInfo, false, true, name);
return new cache(this, funcs[0], receiver, name);
}
: function() {
- if (cache === null) cache = #(
+ if (cache === null) cache = #createTearOffClass(
this, funcs, applyTrampolineIndex, reflectionInfo, false, false, name);
return new cache(this, funcs[0], null, name);
};
- }''', [tearOffAccessExpression, tearOffAccessExpression]);
+ }''',
+ {'createTearOffClass': closureFromTearOffAccessExpression},
+ );
+ } else {
+ // In the CSP version above, the allocation `new cache(...)` is polymorphic
+ // since the same JavaScript anonymous function is used for all instance
+ // tear-offs.
+ //
+ // The following code uses `new Function` to create a fresh instance method
+ // tear-off getter for each method, allowing the allocation to be
+ // monomorphic. This translates into a 2x performance improvement when a
+ // method is torn-off many times. The cost is that the getter, created via
+ // `new Function`, is more expensive to create, and that cost is at program
+ // startup.
+ //
+ // The a counter in the name ensures that the JavaScript engine does not
+ // attempt to fold all of the almost-identical functions back to the same
+ // instance of Function.
+ //
+ // Functions created by `new Function` are at the JavaScript global scope,
+ // so cannot close-over any values from an 'intermediate' enclosing scope.
+ // We use `new Function` to create a function that is immediately applied to
+ // create a context with the closed-over values. The closed-over values
+ // include parameters, (Dart) top-level definitions, and the local `cache`
+ // variable all in one context (passing `null` to initialize `cache`).
+ tearOffGetter = js.statement(
+ '''
+function tearOffGetter(funcs, applyTrampolineIndex, reflectionInfo, name, isIntercepted) {
+ return isIntercepted
+
+ ? new Function("funcs, applyTrampolineIndex, reflectionInfo, name, createTearOffClass, cache",
+ "return function tearOff_" + name + (functionCounter++) + "(receiver) {" +
+ "if (cache === null) cache = createTearOffClass(" +
+ "this, funcs, applyTrampolineIndex, reflectionInfo, false, true, name);" +
+ "return new cache(this, funcs[0], receiver, name);" +
+ "}")(funcs, applyTrampolineIndex, reflectionInfo, name, #createTearOffClass, null)
+
+ : new Function("funcs, applyTrampolineIndex, reflectionInfo, name, createTearOffClass, cache",
+ "return function tearOff_" + name + (functionCounter++)+ "() {" +
+ "if (cache === null) cache = createTearOffClass(" +
+ "this, funcs, applyTrampolineIndex, reflectionInfo, false, false, name);" +
+ "return new cache(this, funcs[0], null, name);" +
+ "}")(funcs, applyTrampolineIndex, reflectionInfo, name, #createTearOffClass, null);
+}''',
+ {'createTearOffClass': closureFromTearOffAccessExpression},
+ );
}
- jsAst.Statement tearOff = js.statement('''
- function tearOff(funcs, applyTrampolineIndex,
+ jsAst.Statement tearOff = js.statement(
+ '''
+ function tearOff(funcs, applyTrampolineIndex,
reflectionInfo, isStatic, name, isIntercepted) {
var cache = null;
return isStatic
? function() {
- if (cache === null) cache = #tearOff(
+ if (cache === null) cache = #createTearOffClass(
this, funcs, applyTrampolineIndex,
reflectionInfo, true, false, name).prototype;
return cache;
}
: tearOffGetter(funcs, applyTrampolineIndex,
reflectionInfo, name, isIntercepted);
- }''', {'tearOff': tearOffAccessExpression});
+ }''',
+ {'createTearOffClass': closureFromTearOffAccessExpression},
+ );
- return <jsAst.Statement>[tearOffGetter, tearOff];
+ return [tearOffGetter, tearOff];
}
diff --git a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
index 786b808..3b10c78 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/fragment_emitter.dart
@@ -768,8 +768,8 @@
'throwLateFieldADI': _emitter
.staticFunctionAccess(_closedWorld.commonElements.throwLateFieldADI),
'operatorIsPrefix': js.string(_namer.fixedNames.operatorIsPrefix),
- 'tearOffCode': new js.Block(buildTearOffCode(
- _options, _emitter, _namer, _closedWorld.commonElements)),
+ 'tearOffCode': new js.Block(
+ buildTearOffCode(_options, _emitter, _closedWorld.commonElements)),
'embeddedTypes': generateEmbeddedGlobalAccess(TYPES),
'embeddedInterceptorTags':
generateEmbeddedGlobalAccess(INTERCEPTORS_BY_TAG),
diff --git a/tools/VERSION b/tools/VERSION
index 1a66e10..1a5a54c 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 14
PATCH 0
-PRERELEASE 37
+PRERELEASE 38
PRERELEASE_PATCH 0
\ No newline at end of file