diff --git a/.github/openclaw/qualification/patches/010-arraybuffer-accounting.patch b/.github/openclaw/qualification/patches/010-arraybuffer-accounting.patch index bdbf1f837aefa..791f134348fad 100644 --- a/.github/openclaw/qualification/patches/010-arraybuffer-accounting.patch +++ b/.github/openclaw/qualification/patches/010-arraybuffer-accounting.patch @@ -885,10 +885,10 @@ index f85d1129..43c9a8be 100644 } diff --git a/test/js/node/process/arraybuffer-accounting.fixture.mjs b/test/js/node/process/arraybuffer-accounting.fixture.mjs new file mode 100644 -index 0000000000000000000000000000000000000000..d2bce713c2bd0a7bc66262eb327e1a6cf52676b4 +index 0000000000000000000000000000000000000000..8611deb06e3f23ad5605ac7693efcfb6c833a16d --- /dev/null +++ b/test/js/node/process/arraybuffer-accounting.fixture.mjs -@@ -0,0 +1,361 @@ +@@ -0,0 +1,366 @@ +import assert from "node:assert/strict"; +import { once } from "node:events"; +import { readFileSync } from "node:fs"; @@ -1081,6 +1081,11 @@ index 0000000000000000000000000000000000000000..d2bce713c2bd0a7bc66262eb327e1a6c + return [before, retained, isolated, released]; +} + ++// Keep JIT compilation of the busy loop separate from this large fixture. ++function spinUntilReleased(flag) { ++ while (!Atomics.load(flag, 0)) {} ++} ++ +const kind = isMainThread ? process.argv[2] : typeof workerData === "string" ? workerData : workerData.kind; +if (!isMainThread && ["busy", "wait", "shutdown", "startup"].includes(kind)) { + // Finish startup work before comparing snapshots of a fresh allocation. @@ -1091,7 +1096,7 @@ index 0000000000000000000000000000000000000000..d2bce713c2bd0a7bc66262eb327e1a6c + if (kind === "wait") { + assert.equal(Atomics.wait(flag, 0, 0), "ok"); + } else { -+ while (!Atomics.load(flag, 0)) {} ++ spinUntilReleased(flag); + } + parentPort.postMessage("released"); +} else if (!isMainThread && kind === "transfer") { diff --git a/.github/openclaw/qualify-arm64.sh b/.github/openclaw/qualify-arm64.sh new file mode 100644 index 0000000000000..62d790b490714 --- /dev/null +++ b/.github/openclaw/qualify-arm64.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash +set -euo pipefail +: "${ENGINE_BUILD_DIR:?}" "${QUALIFICATION_DIR:?}" +case "$(uname -m)" in arm64|aarch64) ;; *) echo 'Native ARM64 host required' >&2; exit 1;; esac +mkdir -p "$QUALIFICATION_DIR" +QUALIFICATION_DIR=$(cd "$QUALIFICATION_DIR" && pwd) +jsc="$ENGINE_BUILD_DIR/bin/jsc" +"$ENGINE_BUILD_DIR/bin/testmasm" > "$QUALIFICATION_DIR/testmasm.log" 2>&1 +"$ENGINE_BUILD_DIR/bin/testFFI" > "$QUALIFICATION_DIR/testffi.log" 2>&1 +Tools/Scripts/run-jsc-stress-tests JSTests/stress --jsc "$jsc" --child-processes "${ENGINE_TEST_JOBS:-4}" \ + --filter 'promise|microtask|dynamic-import|bun-async-context|module-loader|top-level-await|async-module|module-namespace|intl-segmenter|callsite-syntax-positions|stack-position-regressions|error-stack' \ + --output-dir "$QUALIFICATION_DIR/jsc-stress" --no-retry > "$QUALIFICATION_DIR/jsc-stress.log" 2>&1 +python3 .github/openclaw/verify-jsc-results.py "$QUALIFICATION_DIR/jsc-stress" --require module-namespace-esmodule-marker.js --require callsite-syntax-positions.js --require stack-position-regressions.js +Tools/Scripts/run-jsc-stress-tests JSTests/modules.yaml --jsc "$jsc" --child-processes "${ENGINE_TEST_JOBS:-4}" \ + --output-dir "$QUALIFICATION_DIR/jsc-modules" --no-retry > "$QUALIFICATION_DIR/jsc-modules.log" 2>&1 +# Accounting requires generational GC; run its established explicit modes below. +for fixture in array-buffer-accounting heap-allocation-sampling; do + for tier in interpreter baseline dfg ftl concurrent; do + args=(--useGenerationalGC=true --forceMiniVMMode=false --useDollarVM=true) + case "$tier" in + interpreter) args+=(--useJIT=false);; + baseline) args+=(--useDFGJIT=false --useFTLJIT=false);; + dfg) args+=(--useFTLJIT=false --useConcurrentJIT=false --thresholdForJITAfterWarmUp=10 --thresholdForOptimizeAfterWarmUp=20);; + ftl) args+=(--useConcurrentJIT=false --thresholdForJITAfterWarmUp=10 --thresholdForOptimizeAfterWarmUp=20 --thresholdForFTLOptimizeAfterWarmUp=20);; + concurrent) args+=(--gcAtEnd=true --useConcurrentGC=true);; + esac + "$jsc" "${args[@]}" "JSTests/stress/$fixture.js" > "$QUALIFICATION_DIR/$fixture-$tier.log" 2>&1 + done +done +python3 - "$QUALIFICATION_DIR" "$(git rev-parse HEAD)" <<'PY' +import json, platform, sys +from pathlib import Path +out = Path(sys.argv[1]) +counts = {} +for suite, minimum in [('jsc-stress', 1400), ('jsc-modules', 1600)]: + lines = (out / suite / 'results').read_text().splitlines() + assert len(lines) >= minimum and all(line.endswith(': PASS') for line in lines), suite + counts[suite] = len(lines) +assert 'testAdd64RegisterAddress()' in (out / 'testmasm.log').read_text() +(out / 'arm64-gate.json').write_text(json.dumps({'passed': True, 'source': sys.argv[2], 'machine': platform.machine(), 'system': platform.system(), 'counts': counts, 'accounting_modes': 5, 'sampling_modes': 5, 'testmasm': True, 'testffi': True}, indent=2) + '\n') +PY diff --git a/.github/openclaw/qualify-windows-arm64.ps1 b/.github/openclaw/qualify-windows-arm64.ps1 index aef074b11c02f..6efb28d2ea535 100644 --- a/.github/openclaw/qualify-windows-arm64.ps1 +++ b/.github/openclaw/qualify-windows-arm64.ps1 @@ -36,5 +36,18 @@ $result = & $jsc -e $probe if ($LASTEXITCODE -ne 0 -or $result -cne 'windows-arm64-jsc-ok') { throw 'Native JSC startup/JIT probe failed.' } & $ffi if ($LASTEXITCODE -ne 0) { throw 'Native testFFI failed.' } -@{ passed = $true; source = $Source; lane = $label; sha256 = $digest; architecture = 'arm64'; startup = $true; dfg = $true; ffi = $true } | +$fixture = Join-Path $PSScriptRoot '../../JSTests/stress/array-buffer-accounting.js' +$modes = @( + @{ Name = 'interpreter'; Flags = @('--useJIT=false') }, + @{ Name = 'baseline'; Flags = @('--useDFGJIT=false', '--useFTLJIT=false') }, + @{ Name = 'dfg'; Flags = @('--useFTLJIT=false', '--useConcurrentJIT=false') }, + @{ Name = 'ftl'; Flags = @('--useConcurrentJIT=false', '--thresholdForJITAfterWarmUp=10', '--thresholdForOptimizeAfterWarmUp=20', '--thresholdForFTLOptimizeAfterWarmUp=20') }, + @{ Name = 'concurrent'; Flags = @('--gcAtEnd=true', '--useConcurrentGC=true') } +) +foreach ($mode in $modes) { + $flags = @('--useGenerationalGC=true', '--forceMiniVMMode=false') + $mode.Flags + & $jsc @flags $fixture *> (Join-Path $OutputDirectory "accounting-$($mode.Name).log") + if ($LASTEXITCODE -ne 0) { throw "Native ARM64 ArrayBuffer accounting failed in $($mode.Name) mode." } +} +@{ passed = $true; source = $Source; lane = $label; sha256 = $digest; architecture = 'arm64'; startup = $true; dfg = $true; ffi = $true; arraybuffer_accounting = $true; arraybuffer_modes = $modes.Count } | ConvertTo-Json | Set-Content -Encoding utf8 (Join-Path $OutputDirectory 'gate.json') diff --git a/.github/openclaw/release-notes.md b/.github/openclaw/release-notes.md index 6cafb51159dea..66197fc905888 100644 --- a/.github/openclaw/release-notes.md +++ b/.github/openclaw/release-notes.md @@ -1,3 +1,5 @@ +This release fixes ARM64 register-to-memory 64-bit addition, restoring DFG typed-array allocation accounting and preserving the source register. The testmasm regression checks the stored sum, source register, adjacent memory and 64-bit wraparound. Native macOS and Linux ARM64 qualification covers assembler tests and JSC interpreter, baseline, DFG, FTL and concurrent-GC modes. + This release adds the non-LTO Windows ARM64 artifact to the qualified OpenClaw engine on upstream `5718a6ec579b98362ea7276a426deedcc6281ef5`, with native Windows 11 ARM64 startup, DFG JIT and FFI gates bound to the archive and source. - Build Windows ARM64 with the unchanged upstream cross-compilation recipe and require both JSC and testFFI to be native ARM64 PE files. @@ -14,7 +16,7 @@ The previously released engine changes remain included: - Synchronize the accounting-related parallel-helper assertion and visited-memory counters. - Preserve syntax-selected stack positions for calls, constructors, property reads and async continuations, including live/captured stacks and cache replay; thanks @robobun for the upstream source-position work. -Qualification includes all ten artifact builds, Linux JSC module/promise/namespace/Segmenter and allocation-sampling regressions, the W113 paired Bun selection, a build of the exact prepared upstream-synced Bun runtime with its required namespace API adapter and candidate manifest with startup and unchanged upstream memory-release tests, and a separate build with feature adapters for the complete fork selection and patch regressions. Syntax-selected stack positions are checked across execution tiers, live/captured stacks, and cache replay. Other targets have build/provenance proof; native runtime qualification covers Linux x64 and Windows ARM64 JSC startup, DFG JIT and FFI probes. Bun consumer qualification is separate. +Qualification includes all ten artifact builds, Linux JSC module/promise/namespace/Segmenter and allocation-sampling regressions, the paired Bun selection, a build of the exact prepared upstream-synced Bun runtime with its required namespace API adapter and candidate manifest with startup and unchanged upstream memory-release tests, and a separate build with feature adapters for the complete fork selection and patch regressions. Syntax-selected stack positions are checked across execution tiers, live/captured stacks, and cache replay. Other targets have build/provenance proof; native runtime qualification additionally covers macOS and Linux ARM64 assembler/JSC regressions, and Windows ARM64 JSC startup, DFG JIT, FFI and five ArrayBuffer accounting modes. Bun consumer qualification is separate. The new engine requires Bun's updated mimalloc idle hook and matching embedding adapters. A manifest-only update of the original sync tree does not compile: its old namespace marker access must be replaced by the namespace adapter (Bun #106), paired atomically with this engine. Consumers must rebuild with the manifest's exact headers and libraries; an older executable is not interchangeable. diff --git a/.github/openclaw/release.py b/.github/openclaw/release.py index aba2f3b73ffad..9da4dcffb14e3 100644 --- a/.github/openclaw/release.py +++ b/.github/openclaw/release.py @@ -54,7 +54,8 @@ def assemble(inputs,out,source): if (windows.get('passed') is not True or windows.get('source')!=source or windows.get('lane')!='bun-webkit-windows-arm64' or windows.get('architecture')!='arm64' or windows.get('sha256')!=artifacts['bun-webkit-windows-arm64.tar.gz']['sha256'] - or any(windows.get(k) is not True for k in ('startup','dfg','ffi'))): + or any(windows.get(k) is not True for k in ('startup','dfg','ffi','arraybuffer_accounting')) + or windows.get('arraybuffer_modes')!=5): raise ValueError('missing or mismatched native Windows ARM64 qualification') gate['windows_arm64']=windows # Retain low-level provenance and test logs as a separate archive. diff --git a/.github/openclaw/test_release.py b/.github/openclaw/test_release.py index 81422454b4917..59733006b6572 100644 --- a/.github/openclaw/test_release.py +++ b/.github/openclaw/test_release.py @@ -24,10 +24,10 @@ def setUp(self): (d/(label+'.manifest.json')).write_text(json.dumps({'source':SOURCE,'lane':{'label':label},'files':{f.name:{'sha256':release.sha(f),'size':f.stat().st_size}}})) w=self.inputs/'windows-arm64-qualification';w.mkdir() archive=self.inputs/'bun-webkit-windows-arm64/bun-webkit-windows-arm64.tar.gz' - (w/'gate.json').write_text(json.dumps({'passed':True,'source':SOURCE,'lane':'bun-webkit-windows-arm64','architecture':'arm64','sha256':release.sha(archive),'startup':True,'dfg':True,'ffi':True})) + (w/'gate.json').write_text(json.dumps({'passed':True,'source':SOURCE,'lane':'bun-webkit-windows-arm64','architecture':'arm64','sha256':release.sha(archive),'startup':True,'dfg':True,'ffi':True,'arraybuffer_accounting':True,'arraybuffer_modes':5})) def test_windows_gate_rejects_wrong_source_digest_or_failed_probe(self): p=self.inputs/'windows-arm64-qualification/gate.json';original=json.loads(p.read_text()) - for key,value in [('source','b'*40),('sha256','0'*64),('architecture','x64'),('startup',False),('dfg',False),('ffi',False)]: + for key,value in [('source','b'*40),('sha256','0'*64),('architecture','x64'),('startup',False),('dfg',False),('ffi',False),('arraybuffer_accounting',False),('arraybuffer_accounting',None),('arraybuffer_modes',4),('arraybuffer_modes',None)]: with self.subTest(key=key): p.write_text(json.dumps({**original,key:value})) with self.assertRaisesRegex(ValueError,'native Windows ARM64'):self.assemble() diff --git a/.github/workflows/openclaw-arm64.yml b/.github/workflows/openclaw-arm64.yml new file mode 100644 index 0000000000000..b30beb1924467 --- /dev/null +++ b/.github/workflows/openclaw-arm64.yml @@ -0,0 +1,64 @@ +name: OpenClaw ARM64 regressions +on: + pull_request: + branches: [openclaw/main, openclaw/release-5718a6ec] + workflow_dispatch: +permissions: + contents: read +concurrency: + group: openclaw-arm64-${{ github.ref }} + cancel-in-progress: true +jobs: + linux-arm64: + if: github.repository == 'openclaw/WebKit' + runs-on: ubuntu-24.04-arm + timeout-minutes: 150 + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 + with: + ref: ${{ github.event.pull_request.head.sha || github.sha }} + persist-credentials: false + sparse-checkout-cone-mode: false + sparse-checkout: | + /* + !/LayoutTests/ + !/JSTests/* + !/PerformanceTests/ + !/Websites/ + !/ManualTests/ + !/WebDriverTests/ + /JSTests/stress/ + /JSTests/modules/ + /JSTests/*.yaml + /JSTests/BUN-TEST-DIFFERENCES.md + - name: Install native build and regression tools + run: | + curl -fsSL --retry 5 https://apt.llvm.org/llvm-snapshot.gpg.key | sudo tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc > /dev/null + echo 'deb https://apt.llvm.org/noble/ llvm-toolchain-noble-23 main' | sudo tee /etc/apt/sources.list.d/llvm.list + sudo apt-get update -qq + sudo apt-get install -y --no-install-recommends cmake ninja-build clang-23 lld-23 libicu-dev ruby ruby-highline libjson-pp-perl + - name: Build native ARM64 JSC and assembler tests + run: | + test "$(uname -m)" = aarch64 + cmake -S . -B "$RUNNER_TEMP/jsc-build" -G Ninja \ + -DPORT=JSCOnly -DCMAKE_BUILD_TYPE=Release -DDEVELOPER_MODE=ON -DCMAKE_COMPILE_WARNING_AS_ERROR=OFF \ + -DENABLE_STATIC_JSC=ON -DUSE_BUN_JSC_ADDITIONS=ON -DUSE_BUN_EVENT_LOOP=ON \ + -DUSE_MIMALLOC=ON -DUSE_EXTERNAL_MIMALLOC=OFF -DENABLE_FTL_JIT=ON \ + -DENABLE_BUN_SKIP_FAILING_ASSERTIONS=ON -DALLOW_LINE_AND_COLUMN_NUMBER_IN_BUILTINS=ON \ + -DENABLE_REMOTE_INSPECTOR=ON -DCMAKE_C_COMPILER=clang-23 -DCMAKE_CXX_COMPILER=clang++-23 + cmake --build "$RUNNER_TEMP/jsc-build" --target jsc testmasm testFFI -j4 + - name: Qualify assembler and all JIT tiers + env: + ENGINE_BUILD_DIR: ${{ runner.temp }}/jsc-build + QUALIFICATION_DIR: ${{ runner.temp }}/arm64-proof + run: bash .github/openclaw/qualify-arm64.sh + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a + if: always() + with: + name: linux-arm64-proof + path: | + ${{ runner.temp }}/arm64-proof/*.json + ${{ runner.temp }}/arm64-proof/*.log + ${{ runner.temp }}/arm64-proof/jsc-*/results + if-no-files-found: warn + retention-days: 7 diff --git a/.github/workflows/openclaw-artifacts.yml b/.github/workflows/openclaw-artifacts.yml index 9ac93a721a4dd..040c845c8ce7f 100644 --- a/.github/workflows/openclaw-artifacts.yml +++ b/.github/workflows/openclaw-artifacts.yml @@ -164,7 +164,9 @@ jobs: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 with: persist-credentials: false - sparse-checkout: .github + sparse-checkout: | + .github + JSTests/stress - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c with: name: bun-webkit-windows-arm64 @@ -173,9 +175,12 @@ jobs: shell: pwsh run: ./.github/openclaw/qualify-windows-arm64.ps1 -ArtifactDirectory "$env:RUNNER_TEMP/windows-artifact" -OutputDirectory "$env:RUNNER_TEMP/windows-proof" -Source $env:GITHUB_SHA - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a + if: always() with: name: windows-arm64-qualification - path: ${{ runner.temp }}/windows-proof/gate.json + path: | + ${{ runner.temp }}/windows-proof/gate.json + ${{ runner.temp }}/windows-proof/accounting-*.log if-no-files-found: error retention-days: 7 assemble: diff --git a/.github/workflows/openclaw-checks.yml b/.github/workflows/openclaw-checks.yml index 8b02b858f46bf..03c1224998363 100644 --- a/.github/workflows/openclaw-checks.yml +++ b/.github/workflows/openclaw-checks.yml @@ -49,7 +49,9 @@ jobs: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 with: persist-credentials: false - sparse-checkout: .github + sparse-checkout: | + .github + JSTests/stress - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c with: name: bun-webkit-windows-arm64 @@ -58,9 +60,12 @@ jobs: shell: pwsh run: ./.github/openclaw/qualify-windows-arm64.ps1 -ArtifactDirectory "$env:RUNNER_TEMP/windows-artifact" -OutputDirectory "$env:RUNNER_TEMP/windows-proof" -Source $env:GITHUB_SHA - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a + if: always() with: name: windows-arm64-qualification - path: ${{ runner.temp }}/windows-proof/gate.json + path: | + ${{ runner.temp }}/windows-proof/gate.json + ${{ runner.temp }}/windows-proof/accounting-*.log if-no-files-found: error retention-days: 7 linux-native: diff --git a/OPENCLAW.md b/OPENCLAW.md index 6384a6d9cd2eb..082b4d44fafd2 100644 --- a/OPENCLAW.md +++ b/OPENCLAW.md @@ -49,7 +49,7 @@ results, and checks Segmenter, four Proxy regressions, both 14-variant ALS hook modes and at least 14 worker resource-limit cases. Other platforms are built; this gate does not claim native runtime qualification on every architecture. A Windows 11 ARM64 job verifies archive provenance and native ARM64 PE identity, -then runs JSC startup, DFG JIT and testFFI probes. Assembly and publication require +then runs JSC startup, DFG JIT, testFFI and ArrayBuffer accounting in five execution modes. Assembly and publication require its source- and archive-bound receipt. ## Publish and verify @@ -150,6 +150,10 @@ baseline. Engine and Bun headers and libraries must be rebuilt together. ## Unreleased +## ARM64 arithmetic and Windows artifacts (2026-10-05) + +- Fix ARM64 register-to-memory 64-bit addition so DFG typed-array allocations update their accounting counter without corrupting the source register; cover the operation in testmasm and qualify native ARM64 JSC across interpreter and JIT tiers. + - Add the upstream non-LTO Windows ARM64 archive and require native Windows 11 ARM64 startup, JIT and FFI qualification before publication. ## Repeated stack coordinates (2026-10-05) diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h b/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h index 17088a7e5f519..144b6b7b47b55 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h @@ -453,7 +453,7 @@ class MacroAssemblerARM64 : public AbstractMacroAssembler { void add64(RegisterID src, Address dest) { load64(dest, getCachedDataTempRegisterIDAndInvalidate()); - m_assembler.add<64>(src, dataTempRegister, dataTempRegister); + m_assembler.add<64>(dataTempRegister, dataTempRegister, src); store64(dataTempRegister, dest); } diff --git a/Source/JavaScriptCore/assembler/testmasm.cpp b/Source/JavaScriptCore/assembler/testmasm.cpp index 3f495628f492d..07351f816cee3 100644 --- a/Source/JavaScriptCore/assembler/testmasm.cpp +++ b/Source/JavaScriptCore/assembler/testmasm.cpp @@ -1028,6 +1028,28 @@ void testAdd64Imm32() } } +void testAdd64RegisterAddress() +{ + auto add = compile([] (CCallHelpers& jit) { + emitFunctionPrologue(jit); + jit.add64(GPRInfo::argumentGPR1, CCallHelpers::Address(GPRInfo::argumentGPR0, sizeof(uint64_t))); + jit.move(GPRInfo::argumentGPR1, GPRInfo::returnValueGPR); + emitFunctionEpilogue(jit); + jit.ret(); + }); + + for (auto initial : int64Operands()) { + for (auto source : int64Operands()) { + uint64_t values[] = { 0x0123456789abcdefULL, static_cast(initial), 0xfedcba9876543210ULL }; + auto result = invoke(add, values, static_cast(source)); + CHECK_EQ(values[1], static_cast(initial) + static_cast(source)); + CHECK_EQ(result, static_cast(source)); + CHECK_EQ(values[0], 0x0123456789abcdefULL); + CHECK_EQ(values[2], 0xfedcba9876543210ULL); + } + } +} + void testAdd64ArgImm32() { for (auto immediate : int32Operands()) { @@ -8534,6 +8556,7 @@ void run(const char* filter) WTF_IGNORES_THREAD_SAFETY_ANALYSIS RUN(testAdd32Imm()); RUN(testAdd32ArgImm()); RUN(testAdd64Imm32()); + RUN(testAdd64RegisterAddress()); RUN(testAdd64ArgImm32()); RUN(testAdd64Imm64()); RUN(testAdd64ArgImm64()); diff --git a/jsc.md b/jsc.md index 5aa7268664e2a..7fb788afffd64 100644 --- a/jsc.md +++ b/jsc.md @@ -2,6 +2,8 @@ ## Unreleased +- Fix ARM64 MacroAssembler register-to-memory `add64` operand order, restoring DFG typed-array allocation accounting and preserving the source register. + - Fix `Intl.Segmenter` containing lookups around surrogate pairs so segment boundaries and word status agree with iteration. - Expose the require(esm) `__esModule` marker as an own enumerable namespace property while preserving unmarked imports and live bindings. Adapts [oven-sh/WebKit#279](https://github.com/oven-sh/WebKit/pull/279). Thanks @robobun!