├── .github └── workflows │ └── autoroll.yml ├── .gitignore ├── README.md ├── autoroll.ts └── patches ├── 0001-Remove-googletest-visibility-workaround-in-BUILD.gn.patch ├── 0002-Fix-crash-on-Apple-Silicon-when-mprotect-fails-expec.patch └── 0003-Revert-Remove-support-for-import-assertions.patch /.github/workflows/autoroll.yml: -------------------------------------------------------------------------------- 1 | name: Autoroll 2 | 3 | on: 4 | schedule: 5 | - cron: '0 10 * * *' 6 | workflow_dispatch: 7 | inputs: 8 | checkVersions: 9 | description: 'Check V8 versions' 10 | default: true 11 | type: boolean 12 | push: 13 | branches: [autoroll] 14 | 15 | permissions: write-all 16 | 17 | jobs: 18 | update: 19 | runs-on: ubuntu-latest 20 | steps: 21 | - name: Clone repository 22 | uses: actions/checkout@v3 23 | with: 24 | fetch-depth: 1 25 | - uses: denoland/setup-deno@main 26 | with: 27 | deno-version: v1.x 28 | - name: Setup Git user 29 | run: | 30 | git config --global user.name "github-actions[bot]" 31 | git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com" 32 | git config --global user.password ${{ github.token }} 33 | git config --global url."https://${{ github.actor }}:${{ github.token }}@github.com/".insteadOf "https://github.com/" 34 | - name: Run autoroll script 35 | env: 36 | CHECK_V8_VERSIONS: ${{ github.events.inputs.checkVersions }} 37 | run: deno run -A ./autoroll.ts 38 | 39 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | ./v8 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # denoland/v8 2 | 3 | This repository exists to float patches ontop the of 4 | [upstream v8 repo][upstream] for use in [rusty_v8][rusty_v8]. The patches that 5 | are floated are not functional changes to V8 code. Instead all patches are only 6 | here to help accomodate build system differences between Chromium and rusty_v8. 7 | 8 | [upstream]: https://chromium.googlesource.com/v8/v8.git 9 | [rusty_v8]: https://github.com/denoland/rusty_v8 10 | 11 | ## How this repo works 12 | 13 | This repository contains an autoroll script that runs every night. This script 14 | maintains branches in the format `$V8_VERSION-lkgr-denoland` for the last few V8 15 | releases. These branches are a mirror of the upstream `$V8_VERSION-lkgr` 16 | branches, except with the patches from the `patches/` directory applied. 17 | 18 | Currently the following V8 branches are actively updated: 19 | 20 | - `13.4-lkgr-denoland` 21 | 22 | ## Contributing 23 | 24 | For submitting patches to this repo, please contact the maintainers 25 | [on Discord][discord] in the `#dev-rusty_v8` channel. 26 | 27 | [discord]: https://discord.gg/deno 28 | -------------------------------------------------------------------------------- /autoroll.ts: -------------------------------------------------------------------------------- 1 | const V8_VERSIONS = [ 2 | "13.7", 3 | ]; 4 | 5 | const checkVersions = !!Deno.env.get("CHECK_V8_VERSIONS"); 6 | 7 | // Extract the V8 version from the include/v8-version.h file. 8 | function extractVersion(versionDotH: string) { 9 | const MAJOR_PREFIX = "#define V8_MAJOR_VERSION "; 10 | const MINOR_PREFIX = "#define V8_MINOR_VERSION "; 11 | const BUILD_PREFIX = "#define V8_BUILD_NUMBER "; 12 | const PATCH_PREFIX = "#define V8_PATCH_LEVEL "; 13 | 14 | const lines = versionDotH.split("\n"); 15 | const major = parseInt(lines.find((s) => s.startsWith(MAJOR_PREFIX))! 16 | .substring(MAJOR_PREFIX.length)); 17 | const minor = parseInt(lines.find((s) => s.startsWith(MINOR_PREFIX))! 18 | .substring(MINOR_PREFIX.length)); 19 | const build = parseInt(lines.find((s) => s.startsWith(BUILD_PREFIX))! 20 | .substring(BUILD_PREFIX.length)); 21 | const patch = parseInt(lines.find((s) => s.startsWith(PATCH_PREFIX))! 22 | .substring(PATCH_PREFIX.length)); 23 | 24 | return `${major}.${minor}.${build}.${patch}`; 25 | } 26 | 27 | // This function runs a specified subcommand and waits until the command exits 28 | // with code 0. 29 | async function run(cmd: string, args: string[], cwd: string = "./v8") { 30 | console.log("$", cmd, ...args); 31 | const command = new Deno.Command(cmd, { args, cwd }); 32 | const output = await command.output(); 33 | if (!output.success) { 34 | console.error(`Failed to run ${cmd} ${args.join(" ")}`); 35 | Deno.exit(1); 36 | } 37 | } 38 | 39 | // This function runs a specified subcommand and waits until the command exits 40 | // with code 0. 41 | async function runAndCollect( 42 | cmd: string, 43 | args: string[], 44 | cwd: string = "./v8", 45 | ): Promise { 46 | console.log("$", cmd, ...args); 47 | const command = new Deno.Command(cmd, { args, cwd, stdout: "piped" }); 48 | const output = await command.output(); 49 | if (!output.success) { 50 | console.error(`Failed to run ${cmd} ${args.join(" ")}`); 51 | Deno.exit(1); 52 | } 53 | return output.stdout; 54 | } 55 | 56 | async function pathExists(path: string): Promise { 57 | try { 58 | await Deno.stat(path); 59 | return true; 60 | } catch { 61 | return false; 62 | } 63 | } 64 | 65 | if (!await pathExists("./v8/.git")) { 66 | console.log("Cloning V8. This might take a couple of minutes."); 67 | await run("git", [ 68 | "clone", 69 | "https://chromium.googlesource.com/v8/v8.git", 70 | "v8", 71 | ], "."); 72 | 73 | console.log("Configuring denoland remote."); 74 | await run("git", [ 75 | "remote", 76 | "add", 77 | "denoland", 78 | "https://github.com/denoland/v8.git", 79 | ]); 80 | } 81 | 82 | console.log("Fetching denoland remote."); 83 | await run("git", ["fetch", "denoland"]); 84 | 85 | for (const version of V8_VERSIONS) { 86 | const UPSTREAM_LKGR = `${version}-lkgr`; 87 | const DENOLAND_LKGR = `${version}-lkgr-denoland`; 88 | 89 | let currentVersion = null; 90 | const resp = await fetch( 91 | `https://api.github.com/repos/denoland/v8/contents/include/v8-version.h?ref=${DENOLAND_LKGR}`, 92 | { 93 | headers: { 94 | "User-Agent": "denoland/v8 auto updater", 95 | Accept: "application/vnd.github.v3.raw", 96 | }, 97 | }, 98 | ); 99 | if (resp.status === 200) { 100 | const versionDotH = await resp.text(); 101 | currentVersion = extractVersion(versionDotH); 102 | } 103 | 104 | // Create a $V8_VERSION-lkgr-denoland branch from the upstream 105 | // $V8_VERSION-lkgr branch. 106 | await run("git", [ 107 | "checkout", 108 | "-b", 109 | DENOLAND_LKGR, 110 | `origin/${UPSTREAM_LKGR}`, 111 | ]); 112 | 113 | const versionDotH = await Deno.readTextFile("./v8/include/v8-version.h"); 114 | const upstreamVersion = extractVersion(versionDotH); 115 | 116 | if (checkVersions) { 117 | // If the upstream version does not match the current version, then we need to 118 | // roll. 119 | if (upstreamVersion === currentVersion) { 120 | console.log( 121 | `Upstream version ${upstreamVersion} matches current version ${currentVersion}. No need to roll ${UPSTREAM_LKGR}.`, 122 | ); 123 | continue; 124 | } 125 | 126 | console.log( 127 | `Upstream version ${upstreamVersion} does not match current version ${currentVersion}. Rolling ${UPSTREAM_LKGR}...`, 128 | ); 129 | } 130 | // Get list of all patches in the ../patches directory. 131 | const patches = [...Deno.readDirSync("./patches")] 132 | .map((x) => `../patches/${x.name}`); 133 | 134 | patches.sort(); 135 | 136 | for (const patch of patches) { 137 | // Apply the patch file. 138 | console.log(`Applying patch ${patch}`); 139 | await run("git", ["am", "-3", patch]); 140 | } 141 | 142 | // Force push the branch to the denoland remote. 143 | console.log("Pushing the branch to the remote. This might take a minute."); 144 | await run("git", ["push", "--force", "denoland", DENOLAND_LKGR]); 145 | 146 | // Get the current commit. 147 | const commit = await runAndCollect("git", ["rev-parse", DENOLAND_LKGR]); 148 | const currentCommit = new TextDecoder().decode(commit).trim(); 149 | 150 | // Create a tag for the new version. 151 | const TAG = `${upstreamVersion}-denoland-${currentCommit.slice(0, 20)}`; 152 | console.log(`Creating tag ${TAG}`); 153 | await run("git", ["tag", TAG]); 154 | 155 | // Push the tag to the denoland remote. 156 | console.log("Pushing the tag to the remote."); 157 | await run("git", ["push", "denoland", TAG]); 158 | } 159 | -------------------------------------------------------------------------------- /patches/0001-Remove-googletest-visibility-workaround-in-BUILD.gn.patch: -------------------------------------------------------------------------------- 1 | From fe0790450d0c8668e859d125e952bd3687267adb Mon Sep 17 00:00:00 2001 2 | From: Divy Srivastava 3 | Date: Tue, 5 Dec 2023 09:35:57 +0530 4 | Subject: [PATCH] Remove googletest visibility workaround in BUILD.gn 5 | 6 | --- 7 | third_party/googletest/BUILD.gn | 18 ------------------ 8 | 1 file changed, 18 deletions(-) 9 | 10 | diff --git a/third_party/googletest/BUILD.gn b/third_party/googletest/BUILD.gn 11 | index 1cf84b3..0918a49 100644 12 | --- a/third_party/googletest/BUILD.gn 13 | +++ b/third_party/googletest/BUILD.gn 14 | @@ -2,8 +2,6 @@ 15 | # Use of this source code is governed by a BSD-style license that can be 16 | # found in the LICENSE file. 17 | 18 | -import("../../gni/v8.gni") 19 | - 20 | config("gtest_config") { 21 | visibility = [ ":*" ] # gmock also shares this config. 22 | 23 | @@ -91,14 +89,6 @@ source_set("gtest") { 24 | configs -= [ "//build/config/compiler:chromium_code" ] 25 | configs += [ "//build/config/compiler:no_chromium_code" ] 26 | 27 | - # V8-only workaround for http://crbug.com/chromium/1191946. Ensures that 28 | - # googletest is compiled with the same visibility such as the rest of V8, see 29 | - # https://source.chromium.org/chromium/chromium/src/+/master:v8/gni/v8.gni 30 | - if ((is_posix || is_fuchsia) && (v8_enable_backtrace || v8_monolithic)) { 31 | - configs -= [ "//build/config/gcc:symbol_visibility_hidden" ] 32 | - configs += [ "//build/config/gcc:symbol_visibility_default" ] 33 | - } 34 | - 35 | deps = [] 36 | 37 | if (is_fuchsia) { 38 | @@ -143,14 +133,6 @@ source_set("gmock") { 39 | "src/googlemock/src/gmock.cc", 40 | ] 41 | 42 | - # V8-only workaround for http://crbug.com/chromium/1191946. Ensures that 43 | - # googletest is compiled with the same visibility such as the rest of V8, see 44 | - # https://source.chromium.org/chromium/chromium/src/+/master:v8/gni/v8.gni 45 | - if ((is_posix || is_fuchsia) && (v8_enable_backtrace || v8_monolithic)) { 46 | - configs -= [ "//build/config/gcc:symbol_visibility_hidden" ] 47 | - configs += [ "//build/config/gcc:symbol_visibility_default" ] 48 | - } 49 | - 50 | public_configs = [ 51 | ":gmock_config", 52 | ":gtest_config", 53 | -- 54 | 2.37.1 (Apple Git-137.1) 55 | 56 | -------------------------------------------------------------------------------- /patches/0002-Fix-crash-on-Apple-Silicon-when-mprotect-fails-expec.patch: -------------------------------------------------------------------------------- 1 | From 183144148764c4288d63639ff0a7f46e18203fa7 Mon Sep 17 00:00:00 2001 2 | From: Bert Belder 3 | Date: Wed, 25 May 2022 20:40:04 +0200 4 | Subject: [PATCH 3/4] Fix crash on Apple Silicon when mprotect() fails 5 | expectedly 6 | 7 | --- 8 | src/base/platform/platform-posix.cc | 12 ++++++------ 9 | 1 file changed, 6 insertions(+), 6 deletions(-) 10 | 11 | diff --git a/src/base/platform/platform-posix.cc b/src/base/platform/platform-posix.cc 12 | index da42cda6c4..f29d754e77 100644 13 | --- a/src/base/platform/platform-posix.cc 14 | +++ b/src/base/platform/platform-posix.cc 15 | @@ -479,12 +479,6 @@ bool OS::SetPermissions(void* address, size_t size, MemoryPermission access) { 16 | int prot = GetProtectionFromMemoryPermission(access); 17 | int ret = mprotect(address, size, prot); 18 | 19 | - // Setting permissions can fail if the limit of VMAs is exceeded. 20 | - // Any failure that's not OOM likely indicates a bug in the caller (e.g. 21 | - // using an invalid mapping) so attempt to catch that here to facilitate 22 | - // debugging of these failures. 23 | - if (ret != 0) CHECK_EQ(ENOMEM, errno); 24 | - 25 | // MacOS 11.2 on Apple Silicon refuses to switch permissions from 26 | // rwx to none. Just use madvise instead. 27 | #if defined(V8_OS_DARWIN) 28 | @@ -494,6 +488,12 @@ bool OS::SetPermissions(void* address, size_t size, MemoryPermission access) { 29 | } 30 | #endif 31 | 32 | + // Setting permissions can fail if the limit of VMAs is exceeded. 33 | + // Any failure that's not OOM likely indicates a bug in the caller (e.g. 34 | + // using an invalid mapping) so attempt to catch that here to facilitate 35 | + // debugging of these failures. 36 | + if (ret != 0) CHECK_EQ(ENOMEM, errno); 37 | + 38 | if (ret == 0 && access == OS::MemoryPermission::kNoAccess) { 39 | // This is advisory; ignore errors and continue execution. 40 | USE(DiscardSystemPages(address, size)); 41 | 42 | -- 43 | 2.37.3 44 | 45 | -------------------------------------------------------------------------------- /patches/0003-Revert-Remove-support-for-import-assertions.patch: -------------------------------------------------------------------------------- 1 | From acb5b33caa4c97a3ab12c6fe0fc2c90cfcd76f93 Mon Sep 17 00:00:00 2001 2 | From: Ryan Dahl 3 | Date: Fri, 7 Feb 2025 16:51:12 -0800 4 | Subject: [PATCH] Revert "[import-attributes] Remove support for import 5 | assertions" 6 | 7 | This reverts commit 8e18266a98042875335dcba7f4e30f7397f4ba4d. 8 | --- 9 | BUILD.bazel | 4 +- 10 | BUILD.gn | 4 +- 11 | include/v8-isolate.h | 2 +- 12 | include/v8-script.h | 2 +- 13 | src/ast/modules.h | 2 +- 14 | src/common/message-template.h | 9 +- 15 | src/execution/isolate.cc | 68 ++-- 16 | src/flags/flag-definitions.h | 3 +- 17 | src/init/bootstrapper.cc | 1 + 18 | ...ort-attributes.cc => import-assertions.cc} | 2 +- 19 | ...mport-attributes.h => import-assertions.h} | 6 +- 20 | src/parsing/parser-base.h | 8 +- 21 | src/parsing/parser.cc | 18 +- 22 | src/parsing/parser.h | 2 +- 23 | test/cctest/test-api.cc | 10 +- 24 | ...s => modules-import-assertions-fail-1.mjs} | 3 +- 25 | .../fail/modules-import-assertions-fail-1.out | 6 + 26 | ...s => modules-import-assertions-fail-2.mjs} | 3 +- 27 | ...t => modules-import-assertions-fail-2.out} | 1 + 28 | ...s => modules-import-assertions-fail-3.mjs} | 3 +- 29 | .../fail/modules-import-assertions-fail-3.out | 4 + 30 | .../fail/modules-import-attributes-fail-1.out | 5 - 31 | .../fail/modules-import-attributes-fail-3.out | 4 - 32 | ...modules-skip-1-import-assertions-fail.mjs} | 0 33 | ...odules-skip-3-import-assertions-fail.json} | 0 34 | .../harmony/modules-import-assertions-1.mjs | 9 + 35 | .../harmony/modules-import-assertions-2.mjs | 9 + 36 | .../harmony/modules-import-assertions-3.mjs | 9 + 37 | .../harmony/modules-import-assertions-4.mjs | 9 + 38 | .../modules-import-assertions-dynamic-1.mjs | 12 + 39 | .../modules-import-assertions-dynamic-10.mjs | 19 + 40 | .../modules-import-assertions-dynamic-11.mjs | 19 + 41 | .../modules-import-assertions-dynamic-12.mjs | 26 ++ 42 | .../modules-import-assertions-dynamic-2.mjs | 13 + 43 | .../modules-import-assertions-dynamic-3.mjs | 13 + 44 | .../modules-import-assertions-dynamic-4.mjs | 14 + 45 | .../modules-import-assertions-dynamic-5.mjs | 12 + 46 | .../modules-import-assertions-dynamic-6.mjs | 18 + 47 | .../modules-import-assertions-dynamic-7.mjs | 63 ++++ 48 | .../modules-import-assertions-dynamic-8.mjs | 13 + 49 | .../modules-import-assertions-dynamic-9.mjs | 13 + 50 | .../modules-import-attributes-dynamic-7.mjs | 4 +- 51 | ...tributes-dynamic-assertions-fallback-1.mjs | 15 + 52 | ...tributes-dynamic-assertions-fallback-2.mjs | 15 + 53 | .../harmony/modules-skip-imports-json-1.mjs | 4 +- 54 | .../PrivateAccessorAccess.golden | 8 +- 55 | .../PrivateMethodAccess.golden | 4 +- 56 | .../StaticPrivateMethodAccess.golden | 30 +- 57 | test/unittests/objects/modules-unittest.cc | 52 +-- 58 | test/unittests/parser/parsing-unittest.cc | 330 ++++++++++++++---- 59 | 50 files changed, 736 insertions(+), 167 deletions(-) 60 | rename src/parsing/{import-attributes.cc => import-assertions.cc} (91%) 61 | rename src/parsing/{import-attributes.h => import-assertions.h} (87%) 62 | rename test/message/fail/{modules-import-attributes-fail-1.mjs => modules-import-assertions-fail-1.mjs} (60%) 63 | create mode 100644 test/message/fail/modules-import-assertions-fail-1.out 64 | rename test/message/fail/{modules-import-attributes-fail-2.mjs => modules-import-assertions-fail-2.mjs} (62%) 65 | rename test/message/fail/{modules-import-attributes-fail-2.out => modules-import-assertions-fail-2.out} (61%) 66 | rename test/message/fail/{modules-import-attributes-fail-3.mjs => modules-import-assertions-fail-3.mjs} (67%) 67 | create mode 100644 test/message/fail/modules-import-assertions-fail-3.out 68 | delete mode 100644 test/message/fail/modules-import-attributes-fail-1.out 69 | delete mode 100644 test/message/fail/modules-import-attributes-fail-3.out 70 | rename test/message/fail/{modules-skip-1-import-attributes-fail.mjs => modules-skip-1-import-assertions-fail.mjs} (100%) 71 | rename test/message/fail/{modules-skip-3-import-attributes-fail.json => modules-skip-3-import-assertions-fail.json} (100%) 72 | create mode 100644 test/mjsunit/harmony/modules-import-assertions-1.mjs 73 | create mode 100644 test/mjsunit/harmony/modules-import-assertions-2.mjs 74 | create mode 100644 test/mjsunit/harmony/modules-import-assertions-3.mjs 75 | create mode 100644 test/mjsunit/harmony/modules-import-assertions-4.mjs 76 | create mode 100644 test/mjsunit/harmony/modules-import-assertions-dynamic-1.mjs 77 | create mode 100644 test/mjsunit/harmony/modules-import-assertions-dynamic-10.mjs 78 | create mode 100644 test/mjsunit/harmony/modules-import-assertions-dynamic-11.mjs 79 | create mode 100644 test/mjsunit/harmony/modules-import-assertions-dynamic-12.mjs 80 | create mode 100644 test/mjsunit/harmony/modules-import-assertions-dynamic-2.mjs 81 | create mode 100644 test/mjsunit/harmony/modules-import-assertions-dynamic-3.mjs 82 | create mode 100644 test/mjsunit/harmony/modules-import-assertions-dynamic-4.mjs 83 | create mode 100644 test/mjsunit/harmony/modules-import-assertions-dynamic-5.mjs 84 | create mode 100644 test/mjsunit/harmony/modules-import-assertions-dynamic-6.mjs 85 | create mode 100644 test/mjsunit/harmony/modules-import-assertions-dynamic-7.mjs 86 | create mode 100644 test/mjsunit/harmony/modules-import-assertions-dynamic-8.mjs 87 | create mode 100644 test/mjsunit/harmony/modules-import-assertions-dynamic-9.mjs 88 | create mode 100644 test/mjsunit/harmony/modules-import-attributes-dynamic-assertions-fallback-1.mjs 89 | create mode 100644 test/mjsunit/harmony/modules-import-attributes-dynamic-assertions-fallback-2.mjs 90 | 91 | diff --git a/BUILD.bazel b/BUILD.bazel 92 | index 474fe56bf9..f7fac1ec21 100644 93 | --- a/BUILD.bazel 94 | +++ b/BUILD.bazel 95 | @@ -2221,8 +2221,8 @@ filegroup( 96 | "src/parsing/expression-scope.h", 97 | "src/parsing/func-name-inferrer.cc", 98 | "src/parsing/func-name-inferrer.h", 99 | - "src/parsing/import-attributes.cc", 100 | - "src/parsing/import-attributes.h", 101 | + "src/parsing/import-assertions.cc", 102 | + "src/parsing/import-assertions.h", 103 | "src/parsing/keywords-gen.h", 104 | "src/parsing/literal-buffer.cc", 105 | "src/parsing/literal-buffer.h", 106 | diff --git a/BUILD.gn b/BUILD.gn 107 | index 94147651f9..5c490cfb6f 100644 108 | --- a/BUILD.gn 109 | +++ b/BUILD.gn 110 | @@ -4065,7 +4065,7 @@ v8_header_set("v8_internal_headers") { 111 | "src/objects/waiter-queue-node.h", 112 | "src/parsing/expression-scope.h", 113 | "src/parsing/func-name-inferrer.h", 114 | - "src/parsing/import-attributes.h", 115 | + "src/parsing/import-assertions.h", 116 | "src/parsing/keywords-gen.h", 117 | "src/parsing/literal-buffer.h", 118 | "src/parsing/parse-info.h", 119 | @@ -5585,7 +5585,7 @@ v8_source_set("v8_base_without_compiler") { 120 | "src/objects/visitors.cc", 121 | "src/objects/waiter-queue-node.cc", 122 | "src/parsing/func-name-inferrer.cc", 123 | - "src/parsing/import-attributes.cc", 124 | + "src/parsing/import-assertions.cc", 125 | "src/parsing/literal-buffer.cc", 126 | "src/parsing/parse-info.cc", 127 | "src/parsing/parser.cc", 128 | diff --git a/include/v8-isolate.h b/include/v8-isolate.h 129 | index 006928ee72..29b0f74af6 100644 130 | --- a/include/v8-isolate.h 131 | +++ b/include/v8-isolate.h 132 | @@ -585,7 +585,7 @@ class V8_EXPORT Isolate { 133 | kDurationFormat = 117, 134 | kInvalidatedNumberStringNotRegexpLikeProtector = 118, 135 | kOBSOLETE_RegExpUnicodeSetIncompatibilitiesWithUnicodeMode = 119, 136 | - kOBSOLETE_ImportAssertionDeprecatedSyntax = 120, 137 | + kImportAssertionDeprecatedSyntax = 120, 138 | kLocaleInfoObsoletedGetters = 121, 139 | kLocaleInfoFunctions = 122, 140 | kCompileHintsMagicAll = 123, 141 | diff --git a/include/v8-script.h b/include/v8-script.h 142 | index 244a5a7781..0c81aae011 100644 143 | --- a/include/v8-script.h 144 | +++ b/include/v8-script.h 145 | @@ -155,7 +155,7 @@ class V8_EXPORT ModuleRequest : public Data { 146 | */ 147 | Local GetImportAttributes() const; 148 | 149 | - V8_DEPRECATED("Use GetImportAttributes instead") 150 | + V8_DEPRECATE_SOON("Use GetImportAttributes instead") 151 | Local GetImportAssertions() const { 152 | return GetImportAttributes(); 153 | } 154 | diff --git a/src/ast/modules.h b/src/ast/modules.h 155 | index 748f12da3e..104931194b 100644 156 | --- a/src/ast/modules.h 157 | +++ b/src/ast/modules.h 158 | @@ -5,7 +5,7 @@ 159 | #ifndef V8_AST_MODULES_H_ 160 | #define V8_AST_MODULES_H_ 161 | 162 | -#include "src/parsing/import-attributes.h" 163 | +#include "src/parsing/import-assertions.h" 164 | #include "src/parsing/scanner.h" // Only for Scanner::Location. 165 | #include "src/zone/zone-containers.h" 166 | 167 | diff --git a/src/common/message-template.h b/src/common/message-template.h 168 | index 14a868c28f..630336ca1e 100644 169 | --- a/src/common/message-template.h 170 | +++ b/src/common/message-template.h 171 | @@ -115,7 +115,10 @@ namespace internal { 172 | T(IllegalInvocation, "Illegal invocation") \ 173 | T(ImmutablePrototypeSet, \ 174 | "Immutable prototype object '%' cannot have their prototype set") \ 175 | - T(ImportAttributesDuplicateKey, "Import attribute has duplicate key '%'") \ 176 | + T(ImportAssertDeprecated, \ 177 | + "'assert' is deprecated in import statements and support will be removed " \ 178 | + "in %; use 'with' instead") \ 179 | + T(ImportAssertionDuplicateKey, "Import assertion has duplicate key '%'") \ 180 | T(ImportCallNotNewExpression, "Cannot use new with import") \ 181 | T(ImportOutsideModule, "Cannot use import statement outside a module") \ 182 | T(ImportMetaOutsideModule, "Cannot use 'import.meta' outside a module") \ 183 | @@ -161,7 +164,7 @@ namespace internal { 184 | T(NonCoercibleWithProperty, \ 185 | "Cannot destructure property '%' of '%' as it is %.") \ 186 | T(NonExtensibleProto, "% is not extensible") \ 187 | - T(NonObjectAttributesOption, "The 'with' option must be an object") \ 188 | + T(NonObjectAssertOption, "The 'assert' option must be an object") \ 189 | T(NonObjectInInstanceOfCheck, \ 190 | "Right-hand side of 'instanceof' is not an object") \ 191 | T(NonObjectPrivateNameAccess, "Cannot access private name % from %") \ 192 | @@ -173,7 +176,7 @@ namespace internal { 193 | "Cannot set properties of % (setting '%')") \ 194 | T(NonObjectImportArgument, \ 195 | "The second argument to import() must be an object") \ 196 | - T(NonStringImportAttributeValue, "Import attribute value must be a string") \ 197 | + T(NonStringImportAssertionValue, "Import assertion value must be a string") \ 198 | T(NoSetterInCallback, "Cannot set property % of % which has only a getter") \ 199 | T(NotAnIterator, "% is not an iterator") \ 200 | T(PromiseNewTargetUndefined, \ 201 | diff --git a/src/execution/isolate.cc b/src/execution/isolate.cc 202 | index 0d7b5d2812..5e7e5b2e40 100644 203 | --- a/src/execution/isolate.cc 204 | +++ b/src/execution/isolate.cc 205 | @@ -6533,7 +6533,8 @@ MaybeDirectHandle Isolate::GetImportAttributesFromArgument( 206 | 207 | // The parser shouldn't have allowed the second argument to import() if 208 | // the flag wasn't enabled. 209 | - DCHECK(v8_flags.harmony_import_attributes); 210 | + DCHECK(v8_flags.harmony_import_assertions || 211 | + v8_flags.harmony_import_attributes); 212 | 213 | if (!IsJSReceiver(*import_options_argument)) { 214 | this->Throw( 215 | @@ -6557,62 +6558,87 @@ MaybeDirectHandle Isolate::GetImportAttributesFromArgument( 216 | } 217 | } 218 | 219 | - // If there is no 'with' option in the options bag, it's not an error. Just do 220 | - // the import() as if no attributes were provided. 221 | + if (v8_flags.harmony_import_assertions && 222 | + (!v8_flags.harmony_import_attributes || 223 | + IsUndefined(*import_attributes_object))) { 224 | + Handle assert_key = factory()->assert_string(); 225 | + if (!JSReceiver::GetProperty(this, import_options_argument_receiver, 226 | + assert_key) 227 | + .ToHandle(&import_attributes_object)) { 228 | + // This can happen if the property has a getter function that throws 229 | + // an error. 230 | + return MaybeHandle(); 231 | + } 232 | + 233 | + if (V8_UNLIKELY(!IsUndefined(*import_attributes_object))) { 234 | + MessageLocation* location = nullptr; 235 | + MessageLocation computed_location; 236 | + if (ComputeLocation(&computed_location)) { 237 | + location = &computed_location; 238 | + } 239 | + DirectHandle message = MessageHandler::MakeMessageObject( 240 | + this, MessageTemplate::kImportAssertDeprecated, location, 241 | + factory()->NewStringFromAsciiChecked("V8 v12.6 and Chrome 126")); 242 | + message->set_error_level(v8::Isolate::kMessageWarning); 243 | + MessageHandler::ReportMessage(this, location, message); 244 | + } 245 | + } 246 | + 247 | + // If there is no 'with' or 'assert' option in the options bag, it's not an 248 | + // error. Just do the import() as if no assertions were provided. 249 | if (IsUndefined(*import_attributes_object)) return import_attributes_array; 250 | 251 | if (!IsJSReceiver(*import_attributes_object)) { 252 | this->Throw( 253 | - *factory()->NewTypeError(MessageTemplate::kNonObjectAttributesOption)); 254 | - return MaybeDirectHandle(); 255 | + *factory()->NewTypeError(MessageTemplate::kNonObjectAssertOption)); 256 | + return MaybeHandle(); 257 | } 258 | 259 | DirectHandle import_attributes_object_receiver = 260 | Cast(import_attributes_object); 261 | 262 | - DirectHandle attribute_keys; 263 | + Handle assertion_keys; 264 | if (!KeyAccumulator::GetKeys(this, import_attributes_object_receiver, 265 | KeyCollectionMode::kOwnOnly, ENUMERABLE_STRINGS, 266 | GetKeysConversion::kConvertToString) 267 | - .ToHandle(&attribute_keys)) { 268 | - // This happens if the attributes object is a Proxy whose ownKeys() or 269 | + .ToHandle(&assertion_keys)) { 270 | + // This happens if the assertions object is a Proxy whose ownKeys() or 271 | // getOwnPropertyDescriptor() trap throws. 272 | return MaybeDirectHandle(); 273 | } 274 | 275 | bool has_non_string_attribute = false; 276 | 277 | - // The attributes will be passed to the host in the form: [key1, 278 | + // The assertions will be passed to the host in the form: [key1, 279 | // value1, key2, value2, ...]. 280 | constexpr size_t kAttributeEntrySizeForDynamicImport = 2; 281 | import_attributes_array = factory()->NewFixedArray(static_cast( 282 | - attribute_keys->length() * kAttributeEntrySizeForDynamicImport)); 283 | - for (int i = 0; i < attribute_keys->length(); i++) { 284 | - DirectHandle attribute_key(Cast(attribute_keys->get(i)), 285 | - this); 286 | - DirectHandle attribute_value; 287 | + assertion_keys->length() * kAttributeEntrySizeForDynamicImport)); 288 | + for (int i = 0; i < assertion_keys->length(); i++) { 289 | + Handle assertion_key(Cast(assertion_keys->get(i)), this); 290 | + Handle assertion_value; 291 | if (!Object::GetPropertyOrElement(this, import_attributes_object_receiver, 292 | - attribute_key) 293 | - .ToHandle(&attribute_value)) { 294 | + assertion_key) 295 | + .ToHandle(&assertion_value)) { 296 | // This can happen if the property has a getter function that throws 297 | // an error. 298 | return MaybeDirectHandle(); 299 | } 300 | 301 | - if (!IsString(*attribute_value)) { 302 | + if (!IsString(*assertion_value)) { 303 | has_non_string_attribute = true; 304 | } 305 | 306 | import_attributes_array->set((i * kAttributeEntrySizeForDynamicImport), 307 | - *attribute_key); 308 | + *assertion_key); 309 | import_attributes_array->set((i * kAttributeEntrySizeForDynamicImport) + 1, 310 | - *attribute_value); 311 | + *assertion_value); 312 | } 313 | 314 | if (has_non_string_attribute) { 315 | this->Throw(*factory()->NewTypeError( 316 | - MessageTemplate::kNonStringImportAttributeValue)); 317 | - return MaybeDirectHandle(); 318 | + MessageTemplate::kNonStringImportAssertionValue)); 319 | + return MaybeHandle(); 320 | } 321 | 322 | return import_attributes_array; 323 | diff --git a/src/flags/flag-definitions.h b/src/flags/flag-definitions.h 324 | index 2fa08475e1..b47621fd39 100644 325 | --- a/src/flags/flag-definitions.h 326 | +++ b/src/flags/flag-definitions.h 327 | @@ -275,7 +275,8 @@ DEFINE_BOOL(js_shipping, true, "enable all shipped JavaScript features") 328 | #define HARMONY_INPROGRESS_BASE(V) \ 329 | V(harmony_temporal, "Temporal") \ 330 | V(harmony_shadow_realm, "harmony ShadowRealm") \ 331 | - V(harmony_struct, "harmony structs, shared structs, and shared arrays") 332 | + V(harmony_struct, "harmony structs, shared structs, and shared arrays") \ 333 | + V(harmony_import_assertions, "harmony import assertions (deprecated)") 334 | 335 | #define JAVASCRIPT_INPROGRESS_FEATURES_BASE(V) \ 336 | V(js_decorators, "decorators") \ 337 | diff --git a/src/init/bootstrapper.cc b/src/init/bootstrapper.cc 338 | index 6eb45b5e1b..a349810519 100644 339 | --- a/src/init/bootstrapper.cc 340 | +++ b/src/init/bootstrapper.cc 341 | @@ -5506,6 +5506,7 @@ void Genesis::InitializeConsole(DirectHandle extras_binding) { 342 | #define EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(id) \ 343 | void Genesis::InitializeGlobal_##id() {} 344 | 345 | +EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_import_assertions) 346 | EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(harmony_import_attributes) 347 | EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(js_regexp_modifiers) 348 | EMPTY_INITIALIZE_GLOBAL_FOR_FEATURE(js_regexp_duplicate_named_groups) 349 | diff --git a/src/parsing/import-attributes.cc b/src/parsing/import-assertions.cc 350 | similarity index 91% 351 | rename from src/parsing/import-attributes.cc 352 | rename to src/parsing/import-assertions.cc 353 | index 4d0fb40d2f..3d30bd7b5b 100644 354 | --- a/src/parsing/import-attributes.cc 355 | +++ b/src/parsing/import-assertions.cc 356 | @@ -2,7 +2,7 @@ 357 | // Use of this source code is governed by a BSD-style license that can be 358 | // found in the LICENSE file. 359 | 360 | -#include "src/parsing/import-attributes.h" 361 | +#include "src/parsing/import-assertions.h" 362 | 363 | #include "src/ast/ast-value-factory.h" 364 | 365 | diff --git a/src/parsing/import-attributes.h b/src/parsing/import-assertions.h 366 | similarity index 87% 367 | rename from src/parsing/import-attributes.h 368 | rename to src/parsing/import-assertions.h 369 | index 33a7617f14..4f0541672b 100644 370 | --- a/src/parsing/import-attributes.h 371 | +++ b/src/parsing/import-assertions.h 372 | @@ -2,8 +2,8 @@ 373 | // Use of this source code is governed by a BSD-style license that can be 374 | // found in the LICENSE file. 375 | 376 | -#ifndef V8_PARSING_IMPORT_ATTRIBUTES_H_ 377 | -#define V8_PARSING_IMPORT_ATTRIBUTES_H_ 378 | +#ifndef V8_PARSING_IMPORT_ASSERTIONS_H_ 379 | +#define V8_PARSING_IMPORT_ASSERTIONS_H_ 380 | 381 | #include "src/parsing/scanner.h" // Only for Scanner::Location. 382 | #include "src/zone/zone-containers.h" 383 | @@ -29,4 +29,4 @@ class ImportAttributes 384 | } // namespace internal 385 | } // namespace v8 386 | 387 | -#endif // V8_PARSING_IMPORT_ATTRIBUTES_H_ 388 | +#endif // V8_PARSING_IMPORT_ASSERTIONS_H_ 389 | diff --git a/src/parsing/parser-base.h b/src/parsing/parser-base.h 390 | index 2265d1882a..0379e98b37 100644 391 | --- a/src/parsing/parser-base.h 392 | +++ b/src/parsing/parser-base.h 393 | @@ -4193,15 +4193,17 @@ ParserBase::ParseImportExpressions() { 394 | v8_flags.js_source_phase_imports); 395 | // TODO(42204365): Enable import attributes with source phase import once 396 | // specified. 397 | - if (v8_flags.harmony_import_attributes && 398 | - phase == ModuleImportPhase::kEvaluation && Check(Token::kComma)) { 399 | + const bool check_import_attributes = (v8_flags.harmony_import_assertions || 400 | + v8_flags.harmony_import_attributes) && 401 | + phase == ModuleImportPhase::kEvaluation; 402 | + if (check_import_attributes && Check(Token::kComma)) { 403 | if (Check(Token::kRightParen)) { 404 | // A trailing comma allowed after the specifier. 405 | return factory()->NewImportCallExpression(specifier, phase, pos); 406 | } else { 407 | ExpressionT import_options = ParseAssignmentExpressionCoverGrammar(); 408 | Check(Token::kComma); // A trailing comma is allowed after the import 409 | - // attributes. 410 | + // assertions. 411 | Expect(Token::kRightParen); 412 | return factory()->NewImportCallExpression(specifier, phase, 413 | import_options, pos); 414 | diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc 415 | index 88acee17b8..878333c0df 100644 416 | --- a/src/parsing/parser.cc 417 | +++ b/src/parsing/parser.cc 418 | @@ -1446,10 +1446,26 @@ ImportAttributes* Parser::ParseImportWithOrAssertClause() { 419 | // LiteralPropertyName 420 | // LiteralPropertyName ':' StringLiteral , WithEntries 421 | 422 | + // (DEPRECATED) 423 | + // AssertClause : 424 | + // assert '{' '}' 425 | + // assert '{' WithEntries ','? '}' 426 | + 427 | auto import_attributes = zone()->New(zone()); 428 | 429 | if (v8_flags.harmony_import_attributes && Check(Token::kWith)) { 430 | // 'with' keyword consumed 431 | + } else if (v8_flags.harmony_import_assertions && 432 | + !scanner()->HasLineTerminatorBeforeNext() && 433 | + CheckContextualKeyword(ast_value_factory()->assert_string())) { 434 | + // The 'assert' contextual keyword is deprecated in favor of 'with', and we 435 | + // need to investigate feasibility of unshipping. 436 | + // 437 | + // TODO(v8:13856): Remove once decision is made to unship 'assert' or keep. 438 | + ++use_counts_[v8::Isolate::kImportAssertionDeprecatedSyntax]; 439 | + info_->pending_error_handler()->ReportWarningAt( 440 | + position(), end_position(), MessageTemplate::kImportAssertDeprecated, 441 | + "V8 v12.6 and Chrome 126"); 442 | } else { 443 | return import_attributes; 444 | } 445 | @@ -1475,7 +1491,7 @@ ImportAttributes* Parser::ParseImportWithOrAssertClause() { 446 | attribute_key, std::make_pair(attribute_value, location))); 447 | if (!result.second) { 448 | // It is a syntax error if two WithEntries have the same key. 449 | - ReportMessageAt(location, MessageTemplate::kImportAttributesDuplicateKey, 450 | + ReportMessageAt(location, MessageTemplate::kImportAssertionDuplicateKey, 451 | attribute_key); 452 | break; 453 | } 454 | diff --git a/src/parsing/parser.h b/src/parsing/parser.h 455 | index 084329bdd9..72e29f68ff 100644 456 | --- a/src/parsing/parser.h 457 | +++ b/src/parsing/parser.h 458 | @@ -16,7 +16,7 @@ 459 | #include "src/base/small-vector.h" 460 | #include "src/base/threaded-list.h" 461 | #include "src/common/globals.h" 462 | -#include "src/parsing/import-attributes.h" 463 | +#include "src/parsing/import-assertions.h" 464 | #include "src/parsing/parse-info.h" 465 | #include "src/parsing/parser-base.h" 466 | #include "src/parsing/parsing.h" 467 | -- 468 | 2.44.0 469 | 470 | --------------------------------------------------------------------------------