Version 2.18.0-46.0.dev
Merge commit 'e5f4b8506631a3ea92b9d078d75959cc7173ec0d' into 'dev'
diff --git a/pkg/analysis_server/test/analysis/get_hover_test.dart b/pkg/analysis_server/test/analysis/get_hover_test.dart
index 71b27ad..5c4b1fd 100644
--- a/pkg/analysis_server/test/analysis/get_hover_test.dart
+++ b/pkg/analysis_server/test/analysis/get_hover_test.dart
@@ -7,7 +7,6 @@
import 'package:test/test.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
-import '../analysis_abstract.dart';
import '../analysis_server_base.dart';
void main() {
@@ -18,26 +17,26 @@
}
@reflectiveTest
-class AnalysisHoverBazelTest extends AbstractAnalysisTest {
+class AnalysisHoverBazelTest extends BazelWorkspaceAnalysisServerTest {
Future<void> test_bazel_notOwnedUri() async {
- newFile('/workspace/WORKSPACE', '');
- projectPath = newFolder('/workspace').path;
- testFile = convertPath('/workspace/dart/my/lib/test.dart');
-
newFile(
- '/workspace/bazel-genfiles/dart/my/lib/test.dart',
+ '$workspaceRootPath/bazel-genfiles/dart/my/lib/test.dart',
'// generated',
);
- await createProject();
+ await setRoots(included: [workspaceRootPath], excluded: []);
- addTestFile('''
+ var testFile = newFile('$myPackageLibPath/test.dart', '''
class A {}
''');
- var request = AnalysisGetHoverParams(testFile, 0).toRequest('0');
- var response = await waitResponse(request);
- expect(response.error, isNotNull);
+ var request = AnalysisGetHoverParams(testFile.path, 0).toRequest('0');
+ var response = await handleRequest(request);
+ assertResponseFailure(
+ response,
+ requestId: '0',
+ errorCode: RequestErrorCode.FILE_NOT_ANALYZED,
+ );
}
}
diff --git a/pkg/analysis_server/test/analysis_server_base.dart b/pkg/analysis_server/test/analysis_server_base.dart
index 8291e45..9406033f 100644
--- a/pkg/analysis_server/test/analysis_server_base.dart
+++ b/pkg/analysis_server/test/analysis_server_base.dart
@@ -5,7 +5,6 @@
import 'dart:async';
import 'package:analysis_server/src/analysis_server.dart';
-import 'package:analysis_server/src/domain_analysis.dart';
import 'package:analysis_server/src/protocol_server.dart';
import 'package:analysis_server/src/server/crash_reporting_attachments.dart';
import 'package:analysis_server/src/utilities/mocks.dart';
@@ -68,7 +67,22 @@
}
}
-class PubPackageAnalysisServerTest with ResourceProviderMixin {
+class BazelWorkspaceAnalysisServerTest extends ContextResolutionTest {
+ String get myPackageLibPath => '$myPackageRootPath/lib';
+
+ String get myPackageRootPath => '$workspaceRootPath/dart/my';
+
+ Folder get workspaceRoot => getFolder(workspaceRootPath);
+
+ String get workspaceRootPath => '/workspace';
+
+ @override
+ void createDefaultFiles() {
+ newFile('$workspaceRootPath/WORKSPACE', '');
+ }
+}
+
+class ContextResolutionTest with ResourceProviderMixin {
final TestPluginManager pluginManager = TestPluginManager();
late final MockServerChannel serverChannel;
late final AnalysisServer server;
@@ -76,56 +90,8 @@
final List<GeneralAnalysisService> _analysisGeneralServices = [];
final Map<AnalysisService, List<String>> _analysisFileSubscriptions = {};
- AnalysisDomainHandler get analysisDomain {
- return server.handlers.whereType<AnalysisDomainHandler>().single;
- }
-
- List<String> get experiments => [
- EnableString.enhanced_enums,
- EnableString.named_arguments_anywhere,
- EnableString.super_parameters,
- ];
-
- /// The path that is not in [workspaceRootPath], contains external packages.
- String get packagesRootPath => '/packages';
-
Folder get sdkRoot => newFolder('/sdk');
- File get testFile => getFile(testFilePath);
-
- analysis.AnalysisOptions get testFileAnalysisOptions {
- var analysisDriver = server.getAnalysisDriver(testFile.path)!;
- return analysisDriver.analysisOptions;
- }
-
- String get testFileContent => testFile.readAsStringSync();
-
- String get testFilePath => '$testPackageLibPath/test.dart';
-
- String get testPackageLibPath => '$testPackageRootPath/lib';
-
- Folder get testPackageRoot => getFolder(testPackageRootPath);
-
- String get testPackageRootPath => '$workspaceRootPath/test';
-
- String get testPackageTestPath => '$testPackageRootPath/test';
-
- Folder get workspaceRoot => getFolder(workspaceRootPath);
-
- String get workspaceRootPath => '/home';
-
- Future<void> addAnalysisSubscription(
- AnalysisService service,
- File file,
- ) async {
- (_analysisFileSubscriptions[service] ??= []).add(file.path);
- await handleSuccessfulRequest(
- AnalysisSetSubscriptionsParams(
- _analysisFileSubscriptions,
- ).toRequest('0'),
- );
- }
-
Future<void> addGeneralAnalysisSubscription(
GeneralAnalysisService service,
) async {
@@ -133,11 +99,6 @@
await _setGeneralAnalysisSubscriptions();
}
- /// TODO(scheglov) rename
- void addTestFile(String content) {
- newFile(testFilePath, content);
- }
-
void assertResponseFailure(
Response response, {
required String requestId,
@@ -149,20 +110,7 @@
);
}
- void deleteTestPackageAnalysisOptionsFile() {
- deleteAnalysisOptionsYamlFile(testPackageRootPath);
- }
-
- void deleteTestPackageConfigJsonFile() {
- deletePackageConfigJsonFile(testPackageRootPath);
- }
-
- /// Returns the offset of [search] in [testFileContent].
- /// Fails if not found.
- /// TODO(scheglov) Rename it.
- int findOffset(String search) {
- return offsetInFile(testFile, search);
- }
+ void createDefaultFiles() {}
Future<Response> handleRequest(Request request) async {
return await serverChannel.sendRequest(request);
@@ -175,19 +123,6 @@
return response;
}
- void modifyTestFile(String content) {
- modifyFile(testFilePath, content);
- }
-
- /// Returns the offset of [search] in [file].
- /// Fails if not found.
- int offsetInFile(File file, String search) {
- var content = file.readAsStringSync();
- var offset = content.indexOf(search);
- expect(offset, isNot(-1));
- return offset;
- }
-
void processNotification(Notification notification) {}
Future<void> removeGeneralAnalysisSubscription(
@@ -229,13 +164,7 @@
root: sdkRoot,
);
- writeTestPackageConfig();
-
- writeTestPackageAnalysisOptionsFile(
- AnalysisOptionsFileConfig(
- experiments: experiments,
- ),
- );
+ createDefaultFiles();
serverChannel.notifications.listen(processNotification);
@@ -263,6 +192,104 @@
await server.onAnalysisComplete;
}
+ Future<void> _setGeneralAnalysisSubscriptions() async {
+ await handleSuccessfulRequest(
+ AnalysisSetGeneralSubscriptionsParams(
+ _analysisGeneralServices,
+ ).toRequest('0'),
+ );
+ }
+}
+
+class PubPackageAnalysisServerTest extends ContextResolutionTest {
+ List<String> get experiments => [
+ EnableString.enhanced_enums,
+ EnableString.named_arguments_anywhere,
+ EnableString.super_parameters,
+ ];
+
+ /// The path that is not in [workspaceRootPath], contains external packages.
+ String get packagesRootPath => '/packages';
+
+ File get testFile => getFile(testFilePath);
+
+ analysis.AnalysisOptions get testFileAnalysisOptions {
+ var analysisDriver = server.getAnalysisDriver(testFile.path)!;
+ return analysisDriver.analysisOptions;
+ }
+
+ String get testFileContent => testFile.readAsStringSync();
+
+ String get testFilePath => '$testPackageLibPath/test.dart';
+
+ String get testPackageLibPath => '$testPackageRootPath/lib';
+
+ Folder get testPackageRoot => getFolder(testPackageRootPath);
+
+ String get testPackageRootPath => '$workspaceRootPath/test';
+
+ String get testPackageTestPath => '$testPackageRootPath/test';
+
+ Folder get workspaceRoot => getFolder(workspaceRootPath);
+
+ String get workspaceRootPath => '/home';
+
+ Future<void> addAnalysisSubscription(
+ AnalysisService service,
+ File file,
+ ) async {
+ (_analysisFileSubscriptions[service] ??= []).add(file.path);
+ await handleSuccessfulRequest(
+ AnalysisSetSubscriptionsParams(
+ _analysisFileSubscriptions,
+ ).toRequest('0'),
+ );
+ }
+
+ /// TODO(scheglov) rename
+ void addTestFile(String content) {
+ newFile(testFilePath, content);
+ }
+
+ @override
+ void createDefaultFiles() {
+ writeTestPackageConfig();
+
+ writeTestPackageAnalysisOptionsFile(
+ AnalysisOptionsFileConfig(
+ experiments: experiments,
+ ),
+ );
+ }
+
+ void deleteTestPackageAnalysisOptionsFile() {
+ deleteAnalysisOptionsYamlFile(testPackageRootPath);
+ }
+
+ void deleteTestPackageConfigJsonFile() {
+ deletePackageConfigJsonFile(testPackageRootPath);
+ }
+
+ /// Returns the offset of [search] in [testFileContent].
+ /// Fails if not found.
+ /// TODO(scheglov) Rename it.
+ int findOffset(String search) {
+ return offsetInFile(testFile, search);
+ }
+
+ void modifyTestFile(String content) {
+ modifyFile(testFilePath, content);
+ }
+
+ /// Returns the offset of [search] in [file].
+ /// Fails if not found.
+ int offsetInFile(File file, String search) {
+ var content = file.readAsStringSync();
+ var offset = content.indexOf(search);
+ expect(offset, isNot(-1));
+ return offset;
+ }
+
void writePackageConfig(Folder root, PackageConfigFileBuilder config) {
newPackageConfigJsonFile(
root.path,
@@ -299,12 +326,4 @@
void writeTestPackagePubspecYamlFile(String content) {
newPubspecYamlFile(testPackageRootPath, content);
}
-
- Future<void> _setGeneralAnalysisSubscriptions() async {
- await handleSuccessfulRequest(
- AnalysisSetGeneralSubscriptionsParams(
- _analysisGeneralServices,
- ).toRequest('0'),
- );
- }
}
diff --git a/pkg/compiler/lib/src/kernel/dart2js_target.dart b/pkg/compiler/lib/src/kernel/dart2js_target.dart
index 9430808..a5172df 100644
--- a/pkg/compiler/lib/src/kernel/dart2js_target.dart
+++ b/pkg/compiler/lib/src/kernel/dart2js_target.dart
@@ -43,9 +43,11 @@
RegExp(r'(?<!generated_)tests/web/native'),
RegExp(r'(?<!generated_)tests/web/internal'),
'generated_tests/web/native/native_test',
+ 'generated_tests/web/internal/deferred_url_test',
RegExp(r'(?<!generated_)tests/web_2/native'),
RegExp(r'(?<!generated_)tests/web_2/internal'),
'generated_tests/web_2/native/native_test',
+ 'generated_tests/web_2/internal/deferred_url_test',
];
bool allowedNativeTest(Uri uri) {
diff --git a/pkg/compiler/test/dump_info/data/js_members.dart b/pkg/compiler/test/dump_info/data/js_members.dart
new file mode 100644
index 0000000..0d2e390
--- /dev/null
+++ b/pkg/compiler/test/dump_info/data/js_members.dart
@@ -0,0 +1,199 @@
+@JS()
+library js_parameters_test;
+
+import 'package:js/js.dart';
+import 'package:expect/expect.dart';
+
+@JS()
+external void eval(String code);
+
+@JS()
+class Foo {
+ external factory Foo();
+ /*member: Foo.singleArg:function=[{
+ "id": "function/memory:sdk/tests/web/native/main.dart::Foo.singleArg",
+ "kind": "function",
+ "name": "singleArg",
+ "size": 70,
+ "outputUnit": "outputUnit/main",
+ "parent": "class/memory:sdk/tests/web/native/main.dart::Foo",
+ "children": [],
+ "modifiers": {
+ "static": false,
+ "const": false,
+ "factory": false,
+ "external": true
+ },
+ "returnType": "dynamic",
+ "inferredReturnType": "[null|subclass=Object]",
+ "parameters": [
+ {
+ "name": "a",
+ "type": "[exact=JSUInt31]",
+ "declaredType": "dynamic"
+ }
+ ],
+ "sideEffects": "SideEffects(reads anything; writes anything)",
+ "inlinedCount": 0,
+ "code": "singleArg$1(receiver, p0) {\n return receiver.singleArg(p0);\n }",
+ "type": "dynamic Function(dynamic)"
+}]*/
+ external singleArg(a);
+ /*member: Foo.singlePositionalArg:function=[{
+ "id": "function/memory:sdk/tests/web/native/main.dart::Foo.singlePositionalArg",
+ "kind": "function",
+ "name": "singlePositionalArg",
+ "size": 174,
+ "outputUnit": "outputUnit/main",
+ "parent": "class/memory:sdk/tests/web/native/main.dart::Foo",
+ "children": [],
+ "modifiers": {
+ "static": false,
+ "const": false,
+ "factory": false,
+ "external": true
+ },
+ "returnType": "dynamic",
+ "inferredReturnType": "[null|subclass=Object]",
+ "parameters": [
+ {
+ "name": "a",
+ "type": "[null|exact=JSUInt31]",
+ "declaredType": "dynamic"
+ }
+ ],
+ "sideEffects": "SideEffects(reads anything; writes anything)",
+ "inlinedCount": 0,
+ "code": "singlePositionalArg$1(receiver, p0) {\n return receiver.singlePositionalArg(p0);\n }\nsinglePositionalArg$0(receiver) {\n return receiver.singlePositionalArg();\n }",
+ "type": "dynamic Function([dynamic])"
+}]*/
+ external singlePositionalArg([dynamic? a]);
+ /*member: Foo.mixedPositionalArgs:function=[{
+ "id": "function/memory:sdk/tests/web/native/main.dart::Foo.mixedPositionalArgs",
+ "kind": "function",
+ "name": "mixedPositionalArgs",
+ "size": 188,
+ "outputUnit": "outputUnit/main",
+ "parent": "class/memory:sdk/tests/web/native/main.dart::Foo",
+ "children": [],
+ "modifiers": {
+ "static": false,
+ "const": false,
+ "factory": false,
+ "external": true
+ },
+ "returnType": "dynamic",
+ "inferredReturnType": "[null|subclass=Object]",
+ "parameters": [
+ {
+ "name": "a",
+ "type": "[exact=JSUInt31]",
+ "declaredType": "dynamic"
+ },
+ {
+ "name": "b",
+ "type": "[null|exact=JSUInt31]",
+ "declaredType": "dynamic"
+ }
+ ],
+ "sideEffects": "SideEffects(reads anything; writes anything)",
+ "inlinedCount": 0,
+ "code": "mixedPositionalArgs$1(receiver, p0) {\n return receiver.mixedPositionalArgs(p0);\n }\nmixedPositionalArgs$2(receiver, p0, p1) {\n return receiver.mixedPositionalArgs(p0, p1);\n }",
+ "type": "dynamic Function(dynamic,[dynamic])"
+}]*/
+ external mixedPositionalArgs(a, [dynamic? b]);
+}
+
+@JS()
+class Bar {
+ external static singleArg(a);
+ external static singlePositionalArg([dynamic? a]);
+ external static mixedPositionalArgs(a, [dynamic? b]);
+}
+
+external singleArg(a);
+external singlePositionalArg([dynamic? a]);
+external mixedPositionalArgs(a, [dynamic? b]);
+
+/*member: main:
+ function=[{
+ "id": "function/memory:sdk/tests/web/native/main.dart::main",
+ "kind": "function",
+ "name": "main",
+ "size": 1783,
+ "outputUnit": "outputUnit/main",
+ "parent": "library/memory:sdk/tests/web/native/main.dart::",
+ "children": [],
+ "modifiers": {
+ "static": false,
+ "const": false,
+ "factory": false,
+ "external": false
+ },
+ "returnType": "dynamic",
+ "inferredReturnType": "[null]",
+ "parameters": [],
+ "sideEffects": "SideEffects(reads anything; writes anything)",
+ "inlinedCount": 0,
+ "code": "main() {\n var foo, t1;\n self.eval(\" function Foo() {}\\n Foo.prototype.singleArg = function(a) {\\n return a;\\n }\\n Foo.prototype.singlePositionalArg = singleArg;\\n Foo.prototype.mixedPositionalArgs = function(a, b) {\\n if (arguments.length == 0) return a;\\n return arguments[arguments.length - 1];\\n }\\n var Bar = {\\n singleArg: function(a) {\\n return a;\\n },\\n singlePositionalArg: singleArg,\\n mixedPositionalArgs: function(a, b) {\\n if (arguments.length == 0) return a;\\n return arguments[arguments.length - 1];\\n },\\n };\\n function singleArg(a) {\\n return a;\\n }\\n var singlePositionalArg = singleArg;\\n function mixedPositionalArgs(a, b) {\\n if (arguments.length == 0) return a;\\n return arguments[arguments.length - 1];\\n }\\n \");\n foo = new self.Foo();\n t1 = J.getInterceptor$x(foo);\n A.Expect_equals(t1.singleArg$1(foo, 2), 2);\n A.Expect_equals(t1.singlePositionalArg$1(foo, 2), 2);\n A.Expect_equals(t1.singlePositionalArg$0(foo), null);\n A.Expect_equals(t1.mixedPositionalArgs$1(foo, 3), 3);\n A.Expect_equals(t1.mixedPositionalArgs$2(foo, 3, 4), 4);\n A.Expect_equals(self.Bar.singleArg(2), 2);\n A.Expect_equals(self.Bar.singlePositionalArg(2), 2);\n A.Expect_equals(self.Bar.singlePositionalArg(), null);\n A.Expect_equals(self.Bar.mixedPositionalArgs(3), 3);\n A.Expect_equals(self.Bar.mixedPositionalArgs(3, 4), 4);\n A.Expect_equals(self.singleArg(2), 2);\n A.Expect_equals(self.singlePositionalArg(2), 2);\n A.Expect_equals(self.singlePositionalArg(), null);\n A.Expect_equals(self.mixedPositionalArgs(3), 3);\n A.Expect_equals(self.mixedPositionalArgs(3, 4), 4);\n }",
+ "type": "dynamic Function()"
+}],
+ holding=[
+ {"id":"function/dart:_interceptors::getNativeInterceptor","mask":null},
+ {"id":"function/memory:sdk/tests/web/native/main.dart::Foo.mixedPositionalArgs","mask":"[subclass=LegacyJavaScriptObject]"},
+ {"id":"function/memory:sdk/tests/web/native/main.dart::Foo.mixedPositionalArgs","mask":"[subclass=LegacyJavaScriptObject]"},
+ {"id":"function/memory:sdk/tests/web/native/main.dart::Foo.singleArg","mask":"[subclass=LegacyJavaScriptObject]"},
+ {"id":"function/memory:sdk/tests/web/native/main.dart::Foo.singlePositionalArg","mask":"[subclass=LegacyJavaScriptObject]"},
+ {"id":"function/memory:sdk/tests/web/native/main.dart::Foo.singlePositionalArg","mask":"[subclass=LegacyJavaScriptObject]"},
+ {"id":"function/package:expect/expect.dart::Expect.equals","mask":null}]
+*/
+main() {
+ eval(r"""
+ function Foo() {}
+ Foo.prototype.singleArg = function(a) {
+ return a;
+ }
+ Foo.prototype.singlePositionalArg = singleArg;
+ Foo.prototype.mixedPositionalArgs = function(a, b) {
+ if (arguments.length == 0) return a;
+ return arguments[arguments.length - 1];
+ }
+ var Bar = {
+ singleArg: function(a) {
+ return a;
+ },
+ singlePositionalArg: singleArg,
+ mixedPositionalArgs: function(a, b) {
+ if (arguments.length == 0) return a;
+ return arguments[arguments.length - 1];
+ },
+ };
+ function singleArg(a) {
+ return a;
+ }
+ var singlePositionalArg = singleArg;
+ function mixedPositionalArgs(a, b) {
+ if (arguments.length == 0) return a;
+ return arguments[arguments.length - 1];
+ }
+ """);
+
+ var foo = Foo();
+ Expect.equals(foo.singleArg(2), 2);
+ Expect.equals(foo.singlePositionalArg(2), 2);
+ Expect.equals(foo.singlePositionalArg(), null);
+ Expect.equals(foo.mixedPositionalArgs(3), 3);
+ Expect.equals(foo.mixedPositionalArgs(3, 4), 4);
+
+ Expect.equals(Bar.singleArg(2), 2);
+ Expect.equals(Bar.singlePositionalArg(2), 2);
+ Expect.equals(Bar.singlePositionalArg(), null);
+ Expect.equals(Bar.mixedPositionalArgs(3), 3);
+ Expect.equals(Bar.mixedPositionalArgs(3, 4), 4);
+
+ Expect.equals(singleArg(2), 2);
+ Expect.equals(singlePositionalArg(2), 2);
+ Expect.equals(singlePositionalArg(), null);
+ Expect.equals(mixedPositionalArgs(3), 3);
+ Expect.equals(mixedPositionalArgs(3, 4), 4);
+}
diff --git a/sdk/lib/_internal/js_runtime/lib/js_helper.dart b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
index cd6018f..ae676e0 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
@@ -2768,7 +2768,7 @@
String _computeBaseUrl() {
String script = thisScript!;
- return JS('', '#.substring(0, #.lastIndexOf("/"))', script, script);
+ return JS('', '#.substring(0, #.lastIndexOf("/") + 1)', script, script);
}
/// Trusted Type policy [1] for generating validated URLs for scripts for
@@ -2810,11 +2810,14 @@
Object _getBasedScriptUrl(String component) {
final base = _thisScriptBaseUrl;
final encodedComponent = _encodeURIComponent(component);
- final url = '$base/$encodedComponent';
+ final url = '$base$encodedComponent';
final policy = _deferredLoadingTrustedTypesPolicy;
return JS('', '#.createScriptURL(#)', policy, url);
}
+Object getBasedScriptUrlForTesting(String component) =>
+ _getBasedScriptUrl(component);
+
String _encodeURIComponent(String component) {
return JS('', 'self.encodeURIComponent(#)', component);
}
diff --git a/tests/web/internal/deferred_url_test.dart b/tests/web/internal/deferred_url_test.dart
new file mode 100644
index 0000000..3624bef
--- /dev/null
+++ b/tests/web/internal/deferred_url_test.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2022, 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 'dart:_js_helper';
+import 'dart:_foreign_helper';
+import 'dart:_js_embedded_names';
+
+import 'package:expect/expect.dart';
+
+main() {
+ String currentScriptUrl = 'x/main.dart.js';
+ String expectedPartUrl = 'x/part.js';
+ // We make use of the multi-tests format to test multiple scenarios, that's
+ // because internally dart:_js_helper computes what the current script
+ // location is and caches the result in a final variable. As a result, we
+ // can only set it once per test.
+ currentScriptUrl = 'x/y/main.dart.js'; //# 01: ok
+ expectedPartUrl = 'x/y/part.js'; //# 01: continued
+
+ currentScriptUrl = 'main.dart.js'; //# 02: ok
+ expectedPartUrl = 'part.js'; //# 02: continued
+
+ currentScriptUrl = '/main.dart.js'; //# 03: ok
+ expectedPartUrl = '/part.js'; //# 03: continued
+
+ // Override the currentScript. This depends on the internal implementation
+ // of [thisScript].
+ JS('', '# = {"src": #}', JS_EMBEDDED_GLOBAL('', CURRENT_SCRIPT),
+ currentScriptUrl);
+ Object url = getBasedScriptUrlForTesting("part.js");
+ Expect.equals(expectedPartUrl, JS('', '#.toString()', url));
+}
diff --git a/tests/web/web.status b/tests/web/web.status
index d20e136..9613b8b 100644
--- a/tests/web/web.status
+++ b/tests/web/web.status
@@ -4,6 +4,7 @@
[ $compiler != dart2js ]
dummy_compiler_test: SkipByDesign # Issue 30773. Test should be migrated as a unit test of dart2js, is only intended to test self-hosting.
+internal/deferred_url_test: SkipByDesign # test specific for the dart2js runtime
[ $compiler != dart2wasm ]
wasm/*: SkipByDesign
diff --git a/tests/web_2/internal/deferred_url_test.dart b/tests/web_2/internal/deferred_url_test.dart
new file mode 100644
index 0000000..813fa2a
--- /dev/null
+++ b/tests/web_2/internal/deferred_url_test.dart
@@ -0,0 +1,34 @@
+// Copyright (c) 2022, 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.
+
+// @dart = 2.11
+import 'dart:_js_helper';
+import 'dart:_foreign_helper';
+import 'dart:_js_embedded_names';
+
+import 'package:expect/expect.dart';
+
+main() {
+ String currentScriptUrl = 'x/main.dart.js';
+ String expectedPartUrl = 'x/part.js';
+ // We make use of the multi-tests format to test multiple scenarios, that's
+ // because internally dart:_js_helper computes what the current script
+ // location is and caches the result in a final variable. As a result, we
+ // can only set it once per test.
+ currentScriptUrl = 'x/y/main.dart.js'; //# 01: ok
+ expectedPartUrl = 'x/y/part.js'; //# 01: continued
+
+ currentScriptUrl = 'main.dart.js'; //# 02: ok
+ expectedPartUrl = 'part.js'; //# 02: continued
+
+ currentScriptUrl = '/main.dart.js'; //# 03: ok
+ expectedPartUrl = '/part.js'; //# 03: continued
+
+ // Override the currentScript. This depends on the internal implementation
+ // of [thisScript].
+ JS('', '# = {"src": #}', JS_EMBEDDED_GLOBAL('', CURRENT_SCRIPT),
+ currentScriptUrl);
+ Object url = getBasedScriptUrlForTesting("part.js");
+ Expect.equals(expectedPartUrl, JS('', '#.toString()', url));
+}
diff --git a/tests/web_2/web_2.status b/tests/web_2/web_2.status
index c54cd80..6d902367 100644
--- a/tests/web_2/web_2.status
+++ b/tests/web_2/web_2.status
@@ -4,6 +4,7 @@
[ $compiler != dart2js ]
dummy_compiler_test: SkipByDesign # Issue 30773. Test should be migrated as a unit test of dart2js, is only intended to test self-hosting.
+internal/deferred_url_test: SkipByDesign # test specific for the dart2js runtime
[ $runtime == jsshell ]
deferred/load_in_correct_order_test: SkipByDesign # jsshell preamble does not support this test.
diff --git a/tools/VERSION b/tools/VERSION
index bbee9a8..401b5ca 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 18
PATCH 0
-PRERELEASE 45
+PRERELEASE 46
PRERELEASE_PATCH 0
\ No newline at end of file