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