Skip to content

Update sobek and regexp2 - #6218

Merged
mstoykov merged 2 commits into
masterfrom
updateSobek
Jul 28, 2026
Merged

mstoykov merged 2 commits into
masterfrom
updateSobek

Conversation

@mstoykov

@mstoykov mstoykov commented Jul 27, 2026 •

Copy link
Copy Markdown
Contributor

What?

Update sobek and regexp2/v2 by extension

Why?

To bet quite a few big updates to JavaScript runtime liste blow:

sobek:

  • WeakMap/WeakSet entries are now actually collectable. Instead of storing values in a map hanging off each key *Object (which kept them alive as long as the key was reachable), weak maps hold their own mutex-guarded map keyed by object identity and use runtime.AddCleanup to drop entries when the key is collected.
  • Object and Symbol shrank: both derive identity from their own address, so Object.id, Object.weakRefs, Symbol.h and Runtime.genId are gone.
  • String.prototype.split no longer round-trips through UTF-8, with dedicated ASCII and UTF-16 paths; indexOf/lastIndexOf on unicode strings use bytes.Index/LastIndex above a 32-unit crossover instead of a naive scan. CompareTo compares UTF-16 code units, fixing ordering around surrogates.
  • Several typed array fixes: filter, toSorted and with ignored the view's offset when writing to the destination; slice mishandled forward-overlapping buffers; with validated the index before coercing its argument, so a detaching valueOf was missed; out-of-bounds foreign sets no longer fall through to the generic path.
  • baseObject.setForeignIdx passed its arguments in the wrong order, sending the property name as the value.

regexp2:

  • Backtracking is now bounded. MaxBacktrackingStackSize (default 100000, negative to disable) and OptionMaxBacktrackingStackSize cap the track stack, and a match that exceeds it fails with ErrBacktrackingStackLimit rather than growing until it runs out of memory. This complements MatchTimeout for catastrophic patterns.
  • Bool-only matching APIs run a second compiled program with capture marks removed for slots the pattern never observes.
  • The "advance past an empty match" logic moved into scan(), replacing four copies in FindNextMatch, findAllRunesIndex and both replace runners, and keeps Runtextstart put so \G behaves.
  • Leading single-set patterns get a prefix-scan fast path, and alternations precompute their distinct first runes.
  • Fixes a CharSet aliased and mutated during fixed-set analysis, and collapses a repeat of an empty expression that otherwise cost a backtracking frame per iteration.

Checklist

  • I have performed a self-review of my code.
  • I have commented on my code, particularly in hard-to-understand areas.
  • I have added tests for my changes.
  • I have run linter and tests locally (make check) and all pass.

Checklist: Documentation (only for k6 maintainers and if relevant)

Please do not merge this PR until the following items are filled out.

  • I have added the correct milestone and labels to the PR.
  • I have updated the release notes: link
  • I have updated or added an issue to the k6-documentation: grafana/k6-docs#NUMBER if applicable
  • I have updated or added an issue to the TypeScript definitions: grafana/k6-DefinitelyTyped#NUMBER if applicable

Related PR(s)/Issue(s)

sobek: 267a0e055bb4 -> 7781506a890f
regexp2/v2: v2.2.2 -> v2.5.2 (indirect)

sobek:
- WeakMap/WeakSet entries are now actually collectable. Instead of storing
  values in a map hanging off each key *Object (which kept them alive as long
  as the key was reachable), weak maps hold their own mutex-guarded map keyed
  by object identity and use runtime.AddCleanup to drop entries when the key
  is collected.
- Object and Symbol shrank: both derive identity from their own address, so
  Object.id, Object.weakRefs, Symbol.h and Runtime.genId are gone.
- String.prototype.split no longer round-trips through UTF-8, with dedicated
  ASCII and UTF-16 paths; indexOf/lastIndexOf on unicode strings use
  bytes.Index/LastIndex above a 32-unit crossover instead of a naive scan.
  CompareTo compares UTF-16 code units, fixing ordering around surrogates.
- Several typed array fixes: filter, toSorted and with ignored the view's
  offset when writing to the destination; slice mishandled forward-overlapping
  buffers; with validated the index before coercing its argument, so a
  detaching valueOf was missed; out-of-bounds foreign sets no longer fall
  through to the generic path.
- baseObject.setForeignIdx passed its arguments in the wrong order, sending
  the property name as the value.

regexp2:
- Backtracking is now bounded. MaxBacktrackingStackSize (default 100000,
  negative to disable) and OptionMaxBacktrackingStackSize cap the track stack,
  and a match that exceeds it fails with ErrBacktrackingStackLimit rather than
  growing until it runs out of memory. This complements MatchTimeout for
  catastrophic patterns.
- Bool-only matching APIs run a second compiled program with capture marks
  removed for slots the pattern never observes.
- The "advance past an empty match" logic moved into scan(), replacing four
  copies in FindNextMatch, findAllRunesIndex and both replace runners, and
  keeps Runtextstart put so \G behaves.
- Leading single-set patterns get a prefix-scan fast path, and alternations
  precompute their distinct first runes.
- Fixes a CharSet aliased and mutated during fixed-set analysis, and collapses
  a repeat of an empty expression that otherwise cost a backtracking frame per
  iteration.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@mstoykov mstoykov added this to the v2.2.0 milestone Jul 27, 2026
@mstoykov
mstoykov requested a review from a team as a code owner July 27, 2026 16:15
@mstoykov
mstoykov requested review from inancgumus and janHildebrandt98 and removed request for a team July 27, 2026 16:15
@mstoykov
mstoykov temporarily deployed to azure-trusted-signing July 27, 2026 16:21 — with GitHub Actions Inactive
@mstoykov
mstoykov temporarily deployed to azure-trusted-signing July 27, 2026 16:29 — with GitHub Actions Inactive
@mstoykov
mstoykov temporarily deployed to azure-trusted-signing July 27, 2026 16:31 — with GitHub Actions Inactive
@mstoykov
mstoykov merged commit 29ac39c into master Jul 28, 2026
59 checks passed
@mstoykov
mstoykov deleted the updateSobek branch July 28, 2026 10:18
@cursor cursor Bot mentioned this pull request Jul 28, 2026
3 of 8 tasks
social4hyq pushed a commit to social4hyq/homebrew-core that referenced this pull request Sep 20, 2026
k6 2.2.0

Created-by: HarmonybrewBot
Commit-by: HarmonybrewBot
Merged-by: HarmonybrewBot
Description: Created by `brew bump`

---

Created with `brew bump-formula-pr`.<details>
  <summary>release notes</summary>
  <pre>k6 `v2.2.0` is here 🎉! This release includes:

- `k6 cloud run --local-execution` now streams k6's logs to Grafana Cloud, so the test run's log view works for local execution too.
- `chromium.connectOverCDP()`, which connects browser tests to an already-running Chromium instance.
- `TextEncoder` and `TextDecoder` available as globals, and `WritableStream` support in `k6/experimental/streams`.
- A `k6 cloud load-zone list` command.
- Two new experimental feature flags: `merge-run-tags` and `freeze-env`.

## Breaking changes

There are no breaking changes in this release.

## New features

### `k6 cloud run --local-execution` streams logs to Grafana Cloud [#6171](grafana/k6#6171)

When a cloud test runs locally with `k6 cloud run --local-execution`, k6's logs now stream to the Grafana Cloud test run, so the run's log view is populated the same way it is for cloud execution. Previously, local-execution logs stayed on the machine running k6 and never reached the cloud. Work with Grafana's secrets management to safely work with secrets and redact them if they're accidentally leaked into logs are pushed. Use the new `--no-cloud-logs` flag opts out to opt out of streaming of logs when working with `--local-execution`:

```shell
k6 cloud run --local-execution script.js
k6 cloud run --local-execution --no-cloud-logs script.js
```

### Connect to a running browser with `chromium.connectOverCDP()` [#6165](grafana/k6#6165)

The browser module can now attach to an existing Chromium-based browser over the Chrome DevTools Protocol, mirroring Playwright's `browserType.connectOverCDP()`. Pass the browser's WebSocket endpoint and k6 manages the returned browser's connection — it's auto-closed at the end of the iteration, though you can call `close()` earlier to release the connection on demand.

```js
import { chromium } from 'k6/browser';

export default async function () {
  const browser = await chromium.connectOverCDP('ws://localhost:9222/devtools/browser/<id>');
  const page = await browser.newPage();

  try {
    await page.goto('https://quickpizza.grafana.com/');
  } finally {
    await page.close();
    await browser.close();
  }
}
```

Unlike the `K6_BROWSER_WS_URL` environment variable, the endpoint is a runtime value — you can, for example, request a fresh session URL from a browser provider's API in `setup()` and connect to it from the iterations.

### `TextEncoder` and `TextDecoder` globals [#6182](grafana/k6#6182)

`TextEncoder` and `TextDecoder` are now available as standard globals in both the init and VU contexts, no import required — matching how they are exposed in browsers and other JavaScript runtimes.

```js
const encoded = new TextEncoder().encode('Hello, world!');
const decoded = new TextDecoder().decode(encoded);
```

### `WritableStream` in `k6/experimental/streams` [#6132](grafana/k6#6132)

The experimental streams module now implements `WritableStream` and `WritableStreamDefaultWriter` following the WHATWG Streams specification, complementing the existing `ReadableStream` and paving the way for a future `TransformStream` implementation.

```js
import { WritableStream } from 'k6/experimental/streams';

export default async function () {
  const stream = new WritableStream({
    write(chunk) {
      console.log(`wrote ${chunk}`);
    },
  });

  const writer = stream.getWriter();
  await writer.write('hello');
  await writer.close();
}
```

### `k6 cloud load-zone list` command [#6142](grafana/k6#6142)

A new `k6 cloud load-zone list` subcommand lists the load zones — public and private — available in the configured Grafana Cloud k6 stack, mirroring the existing `k6 cloud project list` command. Output defaults to a human-readable table; pass `--json` to emit a JSON array instead.

```console
$ k6 cloud load-zone list
Load zones for https://example.grafana.net:

ID                     NAME                     TYPE      AVAILABLE
amazon:us:ashburn      Ashburn, US (Amazon)     public    yes
amazon:sa:cape town    Cape Town, SA (Amazon)   public    yes
```

### Configurable `handleSummary()` timeout [#5854](grafana/k6#5854)

The time budget for the `handleSummary()` callback — previously hardcoded to 120 seconds — is now configurable through the `handleSummaryTimeout` option or the `K6_HANDLE_SUMMARY_TIMEOUT` environment variable, so long-running tests with heavy summaries no longer fail with `handleSummary() execution timed out`. Thanks, @LBaronceli!

```js
export const options = {
  handleSummaryTimeout: '5m',
};
```

### New experimental feature flags: `merge-run-tags` and `freeze-env`

Two new experimental flags join the feature-flag system introduced in v2.1.0:

- [#5714](grafana/k6#5714) `merge-run-tags` merges run tags per key across config layers, so `options.tags` in a script is no longer silently discarded when `--tag` or `K6_TAGS` is also used — higher-priority layers win on conflicting keys instead of replacing the whole map. Thanks, @yordis!
- [#6032](grafana/k6#6032) `freeze-env` freezes the `__ENV` object, so modifications from script code throw a `TypeError` (in strict mode) instead of silently persisting across iterations and scenarios. Thanks, @lohitkolluri!

```shell
k6 run --features merge-run-tags,freeze-env script.js
```

## UX improvements and enhancements

- [#5631](grafana/k6#5631) Makes the browser module's header accessors — `response.allHeaders()`, `headerValue()`, `headerValues()`, and `headersArray()` — return the raw wire headers (including `Set-Cookie` and security-related headers), correctly paired with each hop of a redirect chain instead of Chrome's provisional headers. As part of this, `headerValues()` now matches header names case-insensitively and splits repeated values on newlines rather than commas, and the `browser_data_sent`/`browser_data_received` metrics now include the raw header bytes and no longer vary run-to-run with CDP event ordering.
- [#6208](grafana/k6#6208) Makes `k6 cloud` reject the run flags (for example, `--vus`) with an `unknown flag` error and a non-zero exit code. Previously `k6 cloud --vus 10 script.js` accepted the flags, printed the help text, and exited 0 — running tests with `k6 cloud` directly was deprecated in v2.0.0 in favor of `k6 cloud run`.
- [#6096](grafana/k6#6096) Points the cloud secrets error at `K6_CLOUD_SECRETS_TOKEN` and `K6_CLOUD_SECRETS_ENDPOINT` when a test run is reused via `K6_CLOUD_PUSH_REF_ID` under `--local-execution`, instead of suggesting the `--local-execution` flag the user is already using.
- [#6196](grafana/k6#6196) Adds `catch` blocks to the browser examples so a failing iteration reports the original error instead of a subsequent `page.close()` failure. Thanks, @locker95!

## Bug fixes

- [#6234](grafana/k6#6234) Classifies HTTP/2 errors by message so the `error_code` metric tag stays correct when k6 is built with Go 1.27 (whose `x/net/http2` delegates to the standard library), and explicitly enables HTTP/2 negotiation on VU transports.
- [#6232](grafana/k6#6232) Drains queued log entries in the Loki hook at shutdown so `--out loki` and cloud log streaming no longer lose the final batch, and emits a `k6 dropped N log messages` warning when the cloud log buffer overflows instead of dropping logs silently.
- [#6125](grafana/k6#6125) Serializes the first concurrent open of a file in the caching filesystem so parallel `fs.open()` calls on the same file no longer read zero or truncated bytes.
- [#6147](grafana/k6#6147) Fixes a data race and inconsistent request-interception state when browser routes are added or removed concurrently. Thanks, @somak2kai!
- [#6070](grafana/k6#6070) Flushes buffered file log output once per second so recent logs aren't lost when k6 is killed before shutdown. Thanks, @rohan-patnaik!
- [#6205](grafana/k6#6205) Stops sending an invalid `Sec-WebSocket-Protocol` header when tailing Grafana Cloud logs; spec-strict servers rejected the handshake with `websocket: bad handshake`.
- [#6200](grafana/k6#6200) Leaves a counter's `rate` unset when the observed duration is zero, instead of computing `+Inf` and spuriously failing `rate` thresholds. Thanks, @samarth70!
- [#6195](grafana/k6#6195) Initializes a gauge's maximum from the first sample so all-negative gauge series no longer report `max=0`. Thanks, @Solaris-star!
- [#6145](grafana/k6#6145) Prevents the OpenTelemetry output from panicking at startup when basic auth is configured without `K6_OTEL_HEADERS`. Thanks, @lukdz!
- [#6140](grafana/k6#6140) Stops `SharedArray` deep-freezing JS primitives, which needlessly wrapped large strings in `String` objects — cutting memory usage in the reported reproduction from roughly 1 GB to 100 MB.

## Maintenance and internal improvements

- [#6126](grafana/k6#6126), [#6224](grafana/k6#6224), [#6229](grafana/k6#6229) Adds anonymous extension usage to the k6 usage report: a run reports the Go module path, version, and type of registry-cataloged extensions it actually uses (imported `k6/x/` modules, output extensions selected with `--out`, and `k6 x` subcommands). Private and unlisted extensions are never reported, and the existing `--no-usage-report` opt-out covers it.
- [#6183](grafana/k6#6183), [#6218](grafana/k6#6218) Updates Sobek and regexp2, making `W

See merge request: Harmonybrew/homebrew-core!16299

This branch was previously deployed

1 inactive deployment
azure-trusted-signing — d6fdc0ea Deployed Jul 27, 2026 by mstoykov via sign-packages #10132
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants