Skip to content

Handle symbols installed on Promise by Node's async_hooks#1115

Merged
mhofman merged 12 commits intomasterfrom
mhofman/handle-async-hooks-promise
Mar 21, 2022
Merged

Handle symbols installed on Promise by Node's async_hooks#1115
mhofman merged 12 commits intomasterfrom
mhofman/handle-async-hooks-promise

Conversation

@mhofman
Copy link
Copy Markdown
Contributor

@mhofman mhofman commented Mar 15, 2022

Closes #1105
Layers on top of #1114

Node 14.18 and 16.61 introduced a change (nodejs/node#39135) to async_hooks that enabled the fast-path for promise hooks even in the presence of a destroy hook. The fast-path logic removes the wrapper object which was previously used to hold the async hooks metadata for each promise instance, such as async ids and a property bag related to the liveness of the promise instance, causing these to be attached directly to the promise instance as own symbols.

When a debugger enables async stack traces (Debugger.setAsyncCallStackDepth({maxDepth}) with maxDepth > 0), node's inspector support internally enables async_hooks with a destroy hook 2 3 4, causing all promises to gain these symbols.

The init promise hooks is the main source of symbol attachments. It runs synchronously right after the constructor returns and before the caller gets the reference. While that would normally cause all promise instances to gain these symbols as own property before the program gets a chance to freeze them, other promise hooks enforce the presence of async ids on existing promise objects. If async_hooks is enabled after a promise has already been created and frozen, for example by attaching the debugger later, it will fail to attach these symbols, throwing a TypeError synchronously.

Until node removes these symbols as own property, or handles assignment failure (see nodejs/node#42229), we workaround the issue by installing accessors for these symbols on the Promise.prototype, which defines them as an own property (non-enumerable to avoid polluting the console output), and falls-back to a WeakMap for non-extensible promise instances.

The accessors handle both async ids, and the destroyed symbol. While the latter is not strictly necessary as it's always installed during init and never late, it's more consistent to handle it similarly to async ids, and has the added benefit of removing enumerable pollution.

The async_hooks logic is added to @endo/init because of the dependency on a node import. lockdown is updated to whitelist these symbols on the promise prototype. It would be better to have lockdown remove these by default and require a taming option to leave them in place, but I didn't find a way to thread that into the whitelist logic to make it conditional.

Footnotes

  1. https://github.com/nodejs/node/issues/42229#issuecomment-1062145546

  2. https://github.com/nodejs/node/blob/d4d0b09122d91478881ee7fd36eb3c9f78f8452d/src/inspector_agent.cc#L411-L424

  3. https://github.com/nodejs/node/blob/d4d0b09122d91478881ee7fd36eb3c9f78f8452d/lib/internal/bootstrap/pre_execution.js#L303-L316

  4. https://github.com/nodejs/node/blob/master/lib/internal/inspector_async_hook.js

@mhofman mhofman requested review from erights and kriskowal March 15, 2022 19:08
@mhofman mhofman linked an issue Mar 15, 2022 that may be closed by this pull request
@mhofman mhofman force-pushed the mhofman/handle-async-hooks-promise branch from 958be31 to 4dbf59d Compare March 15, 2022 19:14
Comment thread packages/init/node-async_hooks.js Outdated
Comment thread packages/init/node-async_hooks.js Outdated
};

const setAsyncIdFallback = (promise, symbol, value) => {
const state = getAsyncHookFallbackState(promise, true);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(nitpick) 3 function signatures here have boolean arguments, each meaning different things. using an options object where the boolean is named in the caller as well would limit the lookups one has to make while reading the body of the current function to remember what the boolean did.

Comment thread packages/init/node-async_hooks.js Outdated
bootstrapData.length = 0;
const { length } = promisesData;
if (length > 1) {
// console.warn('Found multiple potential candidates');
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you aware of a situation when this would happen? AFAIR it shouldn't be possible.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did see it happen at one point when I was exploring, and then couldn't reproduce. not sure why exactly, but I kept the check around.

Copy link
Copy Markdown
Member

@naugtur naugtur Mar 15, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would mean the init hook was called twice. I'd consider that a bug in Node.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it created multiple promise instances for some reason.

Copy link
Copy Markdown
Member

@gibson042 gibson042 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM modulo some nits

Comment thread packages/init/node-async_hooks.js Outdated
Comment thread packages/init/node-async_hooks.js
Comment thread packages/init/test/test-async_hooks.js Outdated
Comment thread packages/init/test/test-async_hooks.js Outdated
Comment thread packages/init/test/test-async_hooks.js Outdated
Comment thread packages/ses/src/whitelist.js Outdated
Copy link
Copy Markdown
Contributor

@erights erights left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am uncomfortable making these weird symbols into apparent well-known symbols by adding them as statics to the Symbol constructor. Let's discuss before we go forward with this.

Comment thread packages/init/node-async_hooks.js Outdated
if (!wellKnownName) {
throw new Error('Unknown symbol');
} else if (!Symbol[wellKnownName]) {
Symbol[wellKnownName] = symbol;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am uncomfortable making these weird symbols into apparent well-known symbols by adding them as statics to the Symbol constructor. Let's discuss before we go forward with this.

@mhofman mhofman force-pushed the mhofman/fix-well-known-symbol-whitelist branch 2 times, most recently from 9d2b638 to 6f6fffb Compare March 16, 2022 01:59
@mhofman mhofman force-pushed the mhofman/handle-async-hooks-promise branch from 7764ea1 to d62e8cf Compare March 16, 2022 02:40
@mhofman mhofman requested a review from erights March 16, 2022 02:41
@mhofman
Copy link
Copy Markdown
Contributor Author

mhofman commented Mar 16, 2022

@erights I switched away from making the async hooks symbols registered and using the new ability to name unique symbols in the whitelist. PTAL

@mhofman mhofman force-pushed the mhofman/handle-async-hooks-promise branch from d62e8cf to 02d90b9 Compare March 16, 2022 03:09
@mhofman
Copy link
Copy Markdown
Contributor Author

mhofman commented Mar 16, 2022

It was brought up that @endo/init may be used in non-Node environments, in which case we'll need either different entrypoints for each environment, or a shim for async_hooks, with the following shape:

export class AsyncResource {};
export const createHook = () => ({ enable() {}, disable() {} });

@mhofman mhofman force-pushed the mhofman/fix-well-known-symbol-whitelist branch 2 times, most recently from 899a957 to 5139dad Compare March 16, 2022 23:46
Base automatically changed from mhofman/fix-well-known-symbol-whitelist to master March 16, 2022 23:55
@mhofman mhofman force-pushed the mhofman/handle-async-hooks-promise branch from 02d90b9 to 65c52e3 Compare March 17, 2022 00:12
@mhofman
Copy link
Copy Markdown
Contributor Author

mhofman commented Mar 17, 2022

I've updated the PR to only include the async_hooks patch on node based on conditional exports, and included a test, but I'm getting an apparently unrelated failure:

Cannot read property 'buildError' of undefined

attn @kriskowal

Comment thread packages/init/pre-remoting.js
@kriskowal
Copy link
Copy Markdown
Member

@mhofman I’ve added a commit that should unblock the build with makeArchive.

Comment thread packages/ses/package.json Outdated
"types": "./index.d.ts",
"exports": {
".": {
"import": "./dist/ses.umd.js",
Copy link
Copy Markdown
Contributor Author

@mhofman mhofman Mar 17, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should there be a "browser" fallback keeping UMD for the browser use case (after import and require) ?

@mhofman
Copy link
Copy Markdown
Contributor Author

mhofman commented Mar 17, 2022

@mhofman I’ve added a commit that should unblock the build with makeArchive.

Well except I've taken a reliance on self references. I think I'll move the async hooks logic in a separate taming package that endo/init takes a dependency on for now?

@mhofman mhofman force-pushed the mhofman/handle-async-hooks-promise branch from 1b224d9 to 4b73064 Compare March 17, 2022 18:55
@mhofman
Copy link
Copy Markdown
Contributor Author

mhofman commented Mar 17, 2022

@erights PTAL

Copy link
Copy Markdown
Contributor

@erights erights left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just noticed that all the normal source files of this init package are at top level in the package, rather than nested in a src directory. Please move the normal source files into a src directory.

Other than that, my review is still in progress, but looking good to me so far.

Copy link
Copy Markdown
Contributor

@erights erights left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review done. Everything I understood LGTM except the directory structure. I did look at all the node/async_hook manipulation code, and it seemed fine to the extent I understood it. Mostly I was amazed at how many cases you had to wrestle with!

@mhofman
Copy link
Copy Markdown
Contributor Author

mhofman commented Mar 19, 2022

I just noticed that all the normal source files of this init package are at top level in the package, rather than nested in a src directory. Please move the normal source files into a src directory.

I believe the files were in the root because they are all entrypoints. While package.json "exports" now allows us to remap this anywhere, I think it's best to keep the regular entrypoints in place for tools which don't support remapping. I have however moved all other/new files into src. @kriskowal does the structure look good by you?

@kriskowal
Copy link
Copy Markdown
Member

kriskowal commented Mar 21, 2022

I just noticed that all the normal source files of this init package are at top level in the package, rather than nested in a src directory. Please move the normal source files into a src directory.

I believe the files were in the root because they are all entrypoints. While package.json "exports" now allows us to remap this anywhere, I think it's best to keep the regular entrypoints in place for tools which don't support remapping. I have however moved all other/new files into src. @kriskowal does the structure look good by you?

Yes, @michaelfig and I have agreed that, due to limitations of interoperability between Node.js versions that recognize exports and other systems that do not yet, we will place all entry-point modules (modules that are public) at the top level, and any other module under src as an indication that it is private.

For the same reason, we determined that the exports needs to just alias these entry-modules in-place, including the .js extension.

Copy link
Copy Markdown
Member

@kriskowal kriskowal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I approve in terms of general structure and willingness to maintain. I don’t begin to grasp the implications of async_hooks, but the effect of this change seems good to me.

Comment thread packages/init/node-async_hooks.js Outdated
Comment thread packages/init/pre-remoting.js
Comment thread packages/init/package.json
@mhofman mhofman merged commit 06827b9 into master Mar 21, 2022
@mhofman mhofman deleted the mhofman/handle-async-hooks-promise branch March 21, 2022 21:24
@mhofman mhofman mentioned this pull request Aug 23, 2022
turadg pushed a commit that referenced this pull request Feb 23, 2026
… load path (#3085)

## Plan: Fix lint failure

- [x] Identified lint failure as Prettier formatting issue
- [x] Ran Prettier --write on test file
- [x] Verified tests still pass
- [x] Verified lint passes

<!-- START COPILOT ORIGINAL PROMPT -->



<details>

<summary>Original prompt</summary>

> 
> ----
> 
> *This section details on the original issue you should resolve*
> 
> <issue_title>Remove async_hooks patch</issue_title>
> <issue_description>`@endo/init` started patching `node:async_hooks` in
#1115 to address debugger issues (see #1105).
> 
> While Node.js's async_hooks implementation remains incompatible with
frozen promises, I hear Node.js's inspector support has since stopped
relying on async_hooks, so we should be able to remove the patch
entirely. This may be needed as there are signs our async_hooks monkey
patch is partially broken under Node.js 24.</issue_description>
> 
> <agent_instructions>Remove the patch and its remnants which break in
Node 24. Include a changesets entry that references issue #1105 that led
us to include it to for local debugging of node processes in lockdown
mode. We don't know whether it's still necessary in Node 20+ so we've
removed it. If it still is, we'll restore the functionality in a new way
that is compatible with Node 24</agent_instructions>
> 
> ## Comments on the Issue (you are @copilot in this section)
> 
> <comments>
> <comment_new><author>@kriskowal</author><body>
> What’s the oldest Node.js version that the patch is necessary? Do we
have the option of applying the patch contingent on
`process.version`?</body></comment_new>
> <comment_new><author>@turadg</author><body>
> > This may be needed as there are signs our async_hooks monkey patch
is partially broken under Node.js 24.
> 
> Confirmed in
https://github.com/endojs/endo/actions/runs/21961549067/job/63440058166?pr=3083
> 
> ```
>   TypeError: this._enable is not a function
> at AsyncLocalStorage.run
(packages/init/src/node-async-local-storage-patch.js:72:8)
>     at packages/init/test/async_hooks.test.js:88:14
> ```
> 
> Can we go ahead and remove the patch?</body></comment_new>
> </comments>
> 


</details>



<!-- START COPILOT CODING AGENT SUFFIX -->

- Fixes #3012

<!-- START COPILOT CODING AGENT TIPS -->
---

✨ Let Copilot coding agent [set things up for
you](https://github.com/endojs/endo/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot)
— coding agent works faster and does higher quality work when set up for
your repo.
@github-actions github-actions Bot mentioned this pull request Feb 19, 2026
boneskull added a commit that referenced this pull request Feb 26, 2026
This PR was opened by the [Changesets
release](https://github.com/changesets/action) GitHub action. When
you're ready to do a release, you can merge this and publish to npm
yourself or [setup this action to publish
automatically](https://github.com/changesets/action#with-publishing). If
you're not ready to do a release yet, that's fine, whenever you add more
changesets to master, this PR will be updated.


# Releases
## @endo/compartment-mapper@2.0.0

### Major Changes

- [#3082](#3082)
[`2e00276`](2e00276)
Thanks [@boneskull](https://github.com/boneskull)! - - **Breaking:**
`CompartmentMapDescriptor` no longer has a `path` property.
- **Breaking:** `CompartmentMapDescriptor`'s `label` property is now a
_canonical name_ (a string of one or more npm package names separated by
`>`).
- **Breaking:** The `CompartmentMapDescriptor` returned by
`captureFromMap()`
now uses canonical names as the keys in its `compartments` property.
- Breaking types: `CompartmentMapDescriptor`, `CompartmentDescriptor`,
`ModuleConfiguration` (renamed from `ModuleDescriptor`) and
`ModuleSource`
        have all been narrowed into discrete subtypes.
- `captureFromMap()`, `loadLocation()` and `importLocation()` now accept
a
`moduleSourceHook` option. This hook is called when processing each
module
source, receiving the module source data (location, language, bytes, or
error
        information) and the canonical name of the containing package.
- `captureFromMap()` now accepts a `packageConnectionsHook` option. This
hook is
called for each retained compartment with its canonical name and the set
of
canonical names of compartments it links to (its connections). Useful
for
        analyzing or visualizing the dependency graph.
- `mapNodeModules()`, `loadLocation()`, `importLocation()`,
`makeScript()`,
`makeFunctor()`, and `writeScript()` now accept the following hook
options:
- `unknownCanonicalNameHook`: Called for each canonical name mentioned
in
policy but not found in the compartment map. Useful for detecting policy
            misconfigurations.
- `packageDependenciesHook`: Called for each package with its set of
dependencies. Can return partial updates to modify the dependencies,
            enabling dependency filtering or injection based on policy.
- `packageDataHook`: Called once with data about all packages found
while
crawling `node_modules`, just prior to creation of a compartment map.
- When dynamic requires are enabled via configuration, execution now
takes
policy into consideration when no other relationship (for example, a
dependent/dependee relationship) between two Compartments exists. When
policy
explicitly allows access from package _A_ to _B_ and _A_ dynamically
requires
_B_ (via absolute path or otherwise), the operation will succeed. This
can
occur _if and only if_ dynamic requires are enabled _and_ a policy is
        provided.
    -   Improved error messaging for policy enforcement failures.

### Patch Changes

- [#3055](#3055)
[`81b4c40`](81b4c40)
Thanks [@naugtur](https://github.com/naugtur)! - - Introduces additional
signal to consider an export from a package an ESM module when it's
selected via an `import` key in `exports` in package.json in case no
other indication of it being an ESM module is present.

- Updated dependencies
\[[`2e00276`](2e00276),
[`a29ecd4`](a29ecd4),
[`a7d3d26`](a7d3d26),
[`d83b1ab`](d83b1ab)]:
    -   ses@1.15.0
    -   @endo/module-source@1.4.0
    -   @endo/zip@1.1.0

## @endo/bundle-source@4.2.0

### Minor Changes

- [#3008](#3008)
[`d83b1ab`](d83b1ab)
Thanks [@kriskowal](https://github.com/kriskowal)! - - Relaxes
dependence on a global, post-lockdown `harden` function by taking a
    dependency on the new `@endo/harden` package.
Consequently, bundles will now entrain a `harden` implementation that is
superfluous if the bundled program is guaranteed to run in a
post-lockdown
    HardenedJS environment.
To compensate, use `bundle-source` with `-C hardened` or the analogous
feature
    for packaging conditions with your preferred bundler tool.
This will hollow out `@endo/harden` and defer exclusively to the global
    `harden`.

### Patch Changes

- [#3083](#3083)
[`644ab15`](644ab15)
Thanks [@turadg](https://github.com/turadg)! - Fix bundle cache corner
cases, improve cache-root validation, and clarify CLI docs for
`endoScript` bundle format.

- Updated dependencies
\[[`2e00276`](2e00276),
[`029dcc4`](029dcc4),
[`d83b1ab`](d83b1ab),
[`b8b52ce`](b8b52ce),
[`a2c32ec`](a2c32ec),
[`81b4c40`](81b4c40)]:
    -   @endo/compartment-mapper@2.0.0
    -   @endo/harden@1.1.0
    -   @endo/promise-kit@1.2.0
    -   @endo/init@1.1.13
    -   @endo/evasive-transform@2.1.0

## @endo/captp@4.5.0

### Minor Changes

- [#3008](#3008)
[`d83b1ab`](d83b1ab)
Thanks [@kriskowal](https://github.com/kriskowal)! - - Relaxes
dependence on a global, post-lockdown `harden` function by taking a
    dependency on the new `@endo/harden` package.
Consequently, bundles will now entrain a `harden` implementation that is
superfluous if the bundled program is guaranteed to run in a
post-lockdown
    HardenedJS environment.
To compensate, use `bundle-source` with `-C hardened` or the analogous
feature
    for packaging conditions with your preferred bundler tool.
This will hollow out `@endo/harden` and defer exclusively to the global
    `harden`.

### Patch Changes

- Updated dependencies
\[[`2e00276`](2e00276),
[`029dcc4`](029dcc4),
[`d83b1ab`](d83b1ab),
[`98f77e9`](98f77e9)]:
    -   @endo/errors@1.3.0
    -   @endo/harden@1.1.0
    -   @endo/eventual-send@1.4.0
    -   @endo/marshal@1.9.0
    -   @endo/nat@5.2.0
    -   @endo/pass-style@1.7.0
    -   @endo/promise-kit@1.2.0

## @endo/check-bundle@1.1.0

### Minor Changes

- [#3008](#3008)
[`d83b1ab`](d83b1ab)
Thanks [@kriskowal](https://github.com/kriskowal)! - - Relaxes
dependence on a global, post-lockdown `harden` function by taking a
    dependency on the new `@endo/harden` package.
Consequently, bundles will now entrain a `harden` implementation that is
superfluous if the bundled program is guaranteed to run in a
post-lockdown
    HardenedJS environment.
To compensate, use `bundle-source` with `-C hardened` or the analogous
feature
    for packaging conditions with your preferred bundler tool.
This will hollow out `@endo/harden` and defer exclusively to the global
    `harden`.

### Patch Changes

- Updated dependencies
\[[`2e00276`](2e00276),
[`2e00276`](2e00276),
[`029dcc4`](029dcc4),
[`81b4c40`](81b4c40)]:
    -   @endo/errors@1.3.0
    -   @endo/compartment-mapper@2.0.0
    -   @endo/harden@1.1.0

## @endo/common@1.3.0

### Minor Changes

- [#3082](#3082)
[`2e00276`](2e00276)
Thanks [@boneskull](https://github.com/boneskull)! - Deprecates this
package's support for the checkFoo/assertCheck pattern (`Checker`,
`identChecker`) in favor of the confirm/reject pattern supported by
@endo/errors/rejector.js.

- [#3008](#3008)
[`d83b1ab`](d83b1ab)
Thanks [@kriskowal](https://github.com/kriskowal)! - - Relaxes
dependence on a global, post-lockdown `harden` function by taking a
    dependency on the new `@endo/harden` package.
Consequently, bundles will now entrain a `harden` implementation that is
superfluous if the bundled program is guaranteed to run in a
post-lockdown
    HardenedJS environment.
To compensate, use `bundle-source` with `-C hardened` or the analogous
feature
    for packaging conditions with your preferred bundler tool.
This will hollow out `@endo/harden` and defer exclusively to the global
    `harden`.

### Patch Changes

- Updated dependencies
\[[`2e00276`](2e00276),
[`029dcc4`](029dcc4),
[`d83b1ab`](d83b1ab)]:
    -   @endo/errors@1.3.0
    -   @endo/harden@1.1.0
    -   @endo/eventual-send@1.4.0
    -   @endo/promise-kit@1.2.0

## @endo/errors@1.3.0

### Minor Changes

- [#3082](#3082)
[`2e00276`](2e00276)
Thanks [@boneskull](https://github.com/boneskull)! - - Exports
`assert.details` under its own name (i.e., `details`).

- `hideAndHardenFunction` - If a function `foo` is first frozen with
`hideAndHardenFunction(foo)` rather than `freeze(foo)` or `harden(foo)`,
then `foo.name` is changed from `'foo'` to `'__HIDE_foo'`. When
`stackFiltering: 'concise'` or `stackFiltering: 'omit-frames'`, then
(currently only on v8), the stack frames for that function are omitted
from the stacks reported by our causal console.
    -   The new `Rejector` type supports the confirmFoo/reject pattern:

        ```js
        @import {FAIL, hideAndHardenFunction} from '@Endo@errors';
        @import {Rejector} from '@endo/errors/rejector.js';

        const confirmFoo = (specimen, reject: Rejector) =>
test(specimen) || reject && reject`explanation of what went wrong`;

        export const isFoo = specimen => confirmFoo(specimen, false);
        hideAndHardenFunction(isFoo);

        export const assertFoo = specimen => {
          confirmFoo(specimen, FAIL);
        };
        hideAndHardenFunction(assertFoo);
        ```

        Both `false` and `Fail` satisfy the `Rejector` type.
We also deprecate the old checkFoo/assertChecker pattern from
@endo/common.
The exported `isFoo` and `assertFoo` behave the same as they had when
then they were using the checkFoo/assertChecker pattern, but are now
internally faster and clearer.

### Patch Changes

- Updated dependencies
\[[`2e00276`](2e00276),
[`029dcc4`](029dcc4),
[`a29ecd4`](a29ecd4)]:
    -   ses@1.15.0
    -   @endo/harden@1.1.0

## @endo/evasive-transform@2.1.0

### Minor Changes

- [#3026](#3026)
[`a2c32ec`](a2c32ec)
Thanks [@naugtur](https://github.com/naugtur)! - - Add
meaning-preserving transformation of expressions and literals containing
content that would otherwise be rejected by SES for looking like dynamic
import or HTML-like comments. Previously only comments were transformed.
Use `onlyComments` option to opt-out of the new behavior.

## @endo/eventual-send@1.4.0

### Minor Changes

- [#3008](#3008)
[`d83b1ab`](d83b1ab)
Thanks [@kriskowal](https://github.com/kriskowal)! - - Relaxes
dependence on a global, post-lockdown `harden` function by taking a
    dependency on the new `@endo/harden` package.
Consequently, bundles will now entrain a `harden` implementation that is
superfluous if the bundled program is guaranteed to run in a
post-lockdown
    HardenedJS environment.
To compensate, use `bundle-source` with `-C hardened` or the analogous
feature
    for packaging conditions with your preferred bundler tool.
This will hollow out `@endo/harden` and defer exclusively to the global
    `harden`.

### Patch Changes

- Updated dependencies
\[[`029dcc4`](029dcc4)]:
    -   @endo/harden@1.1.0

## @endo/exo@1.6.0

### Minor Changes

- [#3008](#3008)
[`d83b1ab`](d83b1ab)
Thanks [@kriskowal](https://github.com/kriskowal)! - - Relaxes
dependence on a global, post-lockdown `harden` function by taking a
    dependency on the new `@endo/harden` package.
Consequently, bundles will now entrain a `harden` implementation that is
superfluous if the bundled program is guaranteed to run in a
post-lockdown
    HardenedJS environment.
To compensate, use `bundle-source` with `-C hardened` or the analogous
feature
    for packaging conditions with your preferred bundler tool.
This will hollow out `@endo/harden` and defer exclusively to the global
    `harden`.

### Patch Changes

- Updated dependencies
\[[`2e00276`](2e00276),
[`98f77e9`](98f77e9),
[`029dcc4`](029dcc4),
[`2e00276`](2e00276),
[`98f77e9`](98f77e9),
[`d83b1ab`](d83b1ab),
[`c488503`](c488503),
[`98f77e9`](98f77e9)]:
    -   @endo/errors@1.3.0
    -   @endo/patterns@1.8.0
    -   @endo/harden@1.1.0
    -   @endo/common@1.3.0
    -   @endo/eventual-send@1.4.0
    -   @endo/pass-style@1.7.0

## @endo/harden@1.1.0

### Minor Changes

- [#3008](#3008)
[`029dcc4`](029dcc4)
Thanks [@kriskowal](https://github.com/kriskowal)! - - Introduces
`@endo/harden`, providing a `harden` implementation that works
    both inside and outside HardenedJS.
- Supports the `hardened` and `harden:unsafe` build conditions to select
        hardened-environment and no-op behaviors.
- Detects pre-lockdown use of `harden` so `lockdown()` fails with a
helpful
        error instead of leaving modules incorrectly hardened.

All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit
guidelines.

## @endo/import-bundle@1.6.0

### Minor Changes

- [#3008](#3008)
[`d83b1ab`](d83b1ab)
Thanks [@kriskowal](https://github.com/kriskowal)! - - Relaxes
dependence on a global, post-lockdown `harden` function by taking a
    dependency on the new `@endo/harden` package.
Consequently, bundles will now entrain a `harden` implementation that is
superfluous if the bundled program is guaranteed to run in a
post-lockdown
    HardenedJS environment.
To compensate, use `bundle-source` with `-C hardened` or the analogous
feature
    for packaging conditions with your preferred bundler tool.
This will hollow out `@endo/harden` and defer exclusively to the global
    `harden`.

### Patch Changes

- Updated dependencies
\[[`2e00276`](2e00276),
[`2e00276`](2e00276),
[`2e00276`](2e00276),
[`029dcc4`](029dcc4),
[`a29ecd4`](a29ecd4),
[`81b4c40`](81b4c40)]:
    -   ses@1.15.0
    -   @endo/errors@1.3.0
    -   @endo/compartment-mapper@2.0.0
    -   @endo/harden@1.1.0

## @endo/lp32@1.2.0

### Minor Changes

- [#3008](#3008)
[`d83b1ab`](d83b1ab)
Thanks [@kriskowal](https://github.com/kriskowal)! - - Relaxes
dependence on a global, post-lockdown `harden` function by taking a
    dependency on the new `@endo/harden` package.
Consequently, bundles will now entrain a `harden` implementation that is
superfluous if the bundled program is guaranteed to run in a
post-lockdown
    HardenedJS environment.
To compensate, use `bundle-source` with `-C hardened` or the analogous
feature
    for packaging conditions with your preferred bundler tool.
This will hollow out `@endo/harden` and defer exclusively to the global
    `harden`.

### Patch Changes

- Updated dependencies
\[[`2e00276`](2e00276),
[`2e00276`](2e00276),
[`029dcc4`](029dcc4),
[`a29ecd4`](a29ecd4),
[`d83b1ab`](d83b1ab)]:
    -   ses@1.15.0
    -   @endo/errors@1.3.0
    -   @endo/harden@1.1.0
    -   @endo/stream@1.3.0

## @endo/marshal@1.9.0

### Minor Changes

- [#3008](#3008)
[`d83b1ab`](d83b1ab)
Thanks [@kriskowal](https://github.com/kriskowal)! - - Relaxes
dependence on a global, post-lockdown `harden` function by taking a
    dependency on the new `@endo/harden` package.
Consequently, bundles will now entrain a `harden` implementation that is
superfluous if the bundled program is guaranteed to run in a
post-lockdown
    HardenedJS environment.
To compensate, use `bundle-source` with `-C hardened` or the analogous
feature
    for packaging conditions with your preferred bundler tool.
This will hollow out `@endo/harden` and defer exclusively to the global
    `harden`.

### Patch Changes

- Updated dependencies
\[[`2e00276`](2e00276),
[`029dcc4`](029dcc4),
[`2e00276`](2e00276),
[`d83b1ab`](d83b1ab),
[`98f77e9`](98f77e9)]:
    -   @endo/errors@1.3.0
    -   @endo/harden@1.1.0
    -   @endo/common@1.3.0
    -   @endo/eventual-send@1.4.0
    -   @endo/nat@5.2.0
    -   @endo/pass-style@1.7.0
    -   @endo/promise-kit@1.2.0

## @endo/memoize@1.2.0

### Minor Changes

- [#3008](#3008)
[`d83b1ab`](d83b1ab)
Thanks [@kriskowal](https://github.com/kriskowal)! - - Relaxes
dependence on a global, post-lockdown `harden` function by taking a
    dependency on the new `@endo/harden` package.
Consequently, bundles will now entrain a `harden` implementation that is
superfluous if the bundled program is guaranteed to run in a
post-lockdown
    HardenedJS environment.
To compensate, use `bundle-source` with `-C hardened` or the analogous
feature
    for packaging conditions with your preferred bundler tool.
This will hollow out `@endo/harden` and defer exclusively to the global
    `harden`.

### Patch Changes

- Updated dependencies
\[[`2e00276`](2e00276),
[`029dcc4`](029dcc4),
[`a29ecd4`](a29ecd4)]:
    -   ses@1.15.0
    -   @endo/harden@1.1.0

## @endo/module-source@1.4.0

### Minor Changes

- [#3008](#3008)
[`a7d3d26`](a7d3d26)
Thanks [@kriskowal](https://github.com/kriskowal)! - - Transitively
freezes the properties of `ModuleSource` constructors and
    instances without requiring lockdown, for greater safety against
    supply-chain-attack.
`ModuleSource`, particularly through the `@endo/module-source/shim.js`,
necessarily runs before `lockdown` is called (if ever) and cannot rely
on
`harden`, so must preemptively transitively freeze its properties to be
    a hardened module, regardless of whether `lockdown` is ever called.

### Patch Changes

- Updated dependencies
\[[`2e00276`](2e00276),
[`029dcc4`](029dcc4),
[`a29ecd4`](a29ecd4)]:
    -   ses@1.15.0
    -   @endo/harden@1.1.0

## @endo/nat@5.2.0

### Minor Changes

- [#3008](#3008)
[`d83b1ab`](d83b1ab)
Thanks [@kriskowal](https://github.com/kriskowal)! - - Relaxes
dependence on a global, post-lockdown `harden` function by taking a
    dependency on the new `@endo/harden` package.
Consequently, bundles will now entrain a `harden` implementation that is
superfluous if the bundled program is guaranteed to run in a
post-lockdown
    HardenedJS environment.
To compensate, use `bundle-source` with `-C hardened` or the analogous
feature
    for packaging conditions with your preferred bundler tool.
This will hollow out `@endo/harden` and defer exclusively to the global
    `harden`.

## @endo/netstring@1.1.0

### Minor Changes

- [#3008](#3008)
[`d83b1ab`](d83b1ab)
Thanks [@kriskowal](https://github.com/kriskowal)! - - Relaxes
dependence on a global, post-lockdown `harden` function by taking a
    dependency on the new `@endo/harden` package.
Consequently, bundles will now entrain a `harden` implementation that is
superfluous if the bundled program is guaranteed to run in a
post-lockdown
    HardenedJS environment.
To compensate, use `bundle-source` with `-C hardened` or the analogous
feature
    for packaging conditions with your preferred bundler tool.
This will hollow out `@endo/harden` and defer exclusively to the global
    `harden`.

### Patch Changes

- Updated dependencies
\[[`2e00276`](2e00276),
[`029dcc4`](029dcc4),
[`a29ecd4`](a29ecd4),
[`d83b1ab`](d83b1ab),
[`b8b52ce`](b8b52ce)]:
    -   ses@1.15.0
    -   @endo/harden@1.1.0
    -   @endo/promise-kit@1.2.0
    -   @endo/stream@1.3.0
    -   @endo/init@1.1.13

## @endo/pass-style@1.7.0

### Minor Changes

- [#3008](#3008)
[`d83b1ab`](d83b1ab)
Thanks [@kriskowal](https://github.com/kriskowal)! - - Relaxes
dependence on a global, post-lockdown `harden` function by taking a
    dependency on the new `@endo/harden` package.
Consequently, bundles will now entrain a `harden` implementation that is
superfluous if the bundled program is guaranteed to run in a
post-lockdown
    HardenedJS environment.
To compensate, use `bundle-source` with `-C hardened` or the analogous
feature
    for packaging conditions with your preferred bundler tool.
This will hollow out `@endo/harden` and defer exclusively to the global
    `harden`.

- [#3082](#3082)
[`98f77e9`](98f77e9)
Thanks [@boneskull](https://github.com/boneskull)! - - Deprecates
`assertChecker`. Use `Fail` in the confirm/reject pattern instead, as
supported by `@endo/errors/rejector.js`.
- Enables `passStyleOf` to make errors passable as a side-effect when
SES locks down with `hardenTaming` set to `unsafe`, which impacts errors
on V8 starting with Node.js 21, and similar engines, that own a `stack`
getter and setter that would otherwise be repaired as a side-effect of
`harden`.

### Patch Changes

- Updated dependencies
\[[`2e00276`](2e00276),
[`029dcc4`](029dcc4),
[`2e00276`](2e00276),
[`d83b1ab`](d83b1ab)]:
    -   @endo/errors@1.3.0
    -   @endo/harden@1.1.0
    -   @endo/common@1.3.0
    -   @endo/eventual-send@1.4.0
    -   @endo/promise-kit@1.2.0

## @endo/patterns@1.8.0

### Minor Changes

- [#3082](#3082)
[`98f77e9`](98f77e9)
Thanks [@boneskull](https://github.com/boneskull)! - `@endo/patterns`
now exports a new `getNamedMethodGuards(interfaceGuard)` that returns
that interface guard's record of method guards. The motivation is to
support interface inheritance expressed by patterns like

    ```js
    const I2 = M.interface('I2', {
      ...getNamedMethodGuards(I1),
      doMore: M.call().returns(M.any()),
    });
    ```

See `@endo/exo`'s `exo-wobbly-point.test.js` to see it in action
together with an experiment in class inheritance.

- [#3008](#3008)
[`d83b1ab`](d83b1ab)
Thanks [@kriskowal](https://github.com/kriskowal)! - - Relaxes
dependence on a global, post-lockdown `harden` function by taking a
    dependency on the new `@endo/harden` package.
Consequently, bundles will now entrain a `harden` implementation that is
superfluous if the bundled program is guaranteed to run in a
post-lockdown
    HardenedJS environment.
To compensate, use `bundle-source` with `-C hardened` or the analogous
feature
    for packaging conditions with your preferred bundler tool.
This will hollow out `@endo/harden` and defer exclusively to the global
    `harden`.

### Patch Changes

- [#3082](#3082)
[`98f77e9`](98f77e9)
Thanks [@boneskull](https://github.com/boneskull)! - The `sloppy` option
for `@endo/patterns` interface guards is deprecated. Use `defaultGuards`
instead.

- [#3065](#3065)
[`c488503`](c488503)
Thanks [@gibson042](https://github.com/gibson042)! - -
`containerHasSplit` now hardens its output(s) when working with
copyArrays,
    ensuring that each output is itself a copyArray instance.

- Updated dependencies
\[[`2e00276`](2e00276),
[`029dcc4`](029dcc4),
[`2e00276`](2e00276),
[`d83b1ab`](d83b1ab),
[`98f77e9`](98f77e9)]:
    -   @endo/errors@1.3.0
    -   @endo/harden@1.1.0
    -   @endo/common@1.3.0
    -   @endo/eventual-send@1.4.0
    -   @endo/marshal@1.9.0
    -   @endo/pass-style@1.7.0
    -   @endo/promise-kit@1.2.0

## @endo/promise-kit@1.2.0

### Minor Changes

- [#3008](#3008)
[`d83b1ab`](d83b1ab)
Thanks [@kriskowal](https://github.com/kriskowal)! - - Relaxes
dependence on a global, post-lockdown `harden` function by taking a
    dependency on the new `@endo/harden` package.
Consequently, bundles will now entrain a `harden` implementation that is
superfluous if the bundled program is guaranteed to run in a
post-lockdown
    HardenedJS environment.
To compensate, use `bundle-source` with `-C hardened` or the analogous
feature
    for packaging conditions with your preferred bundler tool.
This will hollow out `@endo/harden` and defer exclusively to the global
    `harden`.

### Patch Changes

- Updated dependencies
\[[`2e00276`](2e00276),
[`029dcc4`](029dcc4),
[`a29ecd4`](a29ecd4)]:
    -   ses@1.15.0
    -   @endo/harden@1.1.0

## ses@1.15.0

### Minor Changes

- [#3082](#3082)
[`2e00276`](2e00276)
Thanks [@boneskull](https://github.com/boneskull)! - - Adds
`assert.makeError` and deprecates `assert.error` as an alias, matching
    the API already exported from `@endo/errors`.
- Before this version, the `assert` left in global scope before
`lockdown`
would redact errors and would be replaced by `lockdown` with a version
that
did _not_ redact errors if the caller opted-in with `errorTaming`
        set to one of the `unsafe` variants.
After this version, the reverse is true: the `assert` left in global
scope
        before `lockdown` does not redact.
Then, `lockdown` replaces `assert` with a redacting `assert` unless the
caller opted-out with `errorTaming` set to one of the `unsafe` variants.

- [#3008](#3008)
[`a29ecd4`](a29ecd4)
Thanks [@kriskowal](https://github.com/kriskowal)! - - `lockdown` and
`repairIntrinsics` now detect when code has already called a
`harden` imported from `@endo/harden` before lockdown, and fail with a
clear
    error about hardened modules executing before lockdown.
- Adds `Object[Symbol.for('harden')]` as a variant of
`globalThis.harden` that
cannot be overridden by an endowment named `harden` in compartments.

## @endo/ses-ava@1.4.0

### Minor Changes

- [#3082](#3082)
[`2e00276`](2e00276)
Thanks [@boneskull](https://github.com/boneskull)! - - Introduces a
`ses-ava` command for running tests with multiple AVA configurations.
- Adds an `@endo/ses-ava/test.js` module for getting a `test` function
        appropriate for your configuration.
- Adds an `@endo/ses-ava/prepare-endo-config.js` module suitable for use
in the
`require` clause of an AVA configuration, such that
`@endo/ses-ava/test.js`
        exports a wrapped SES-AVA `test` function.

### Patch Changes

- Updated dependencies
\[[`2e00276`](2e00276),
[`029dcc4`](029dcc4),
[`a29ecd4`](a29ecd4),
[`b8b52ce`](b8b52ce)]:
    -   ses@1.15.0
    -   @endo/harden@1.1.0
    -   @endo/init@1.1.13

## @endo/stream@1.3.0

### Minor Changes

- [#3008](#3008)
[`d83b1ab`](d83b1ab)
Thanks [@kriskowal](https://github.com/kriskowal)! - - Relaxes
dependence on a global, post-lockdown `harden` function by taking a
    dependency on the new `@endo/harden` package.
Consequently, bundles will now entrain a `harden` implementation that is
superfluous if the bundled program is guaranteed to run in a
post-lockdown
    HardenedJS environment.
To compensate, use `bundle-source` with `-C hardened` or the analogous
feature
    for packaging conditions with your preferred bundler tool.
This will hollow out `@endo/harden` and defer exclusively to the global
    `harden`.

### Patch Changes

- Updated dependencies
\[[`2e00276`](2e00276),
[`029dcc4`](029dcc4),
[`a29ecd4`](a29ecd4),
[`d83b1ab`](d83b1ab)]:
    -   ses@1.15.0
    -   @endo/harden@1.1.0
    -   @endo/eventual-send@1.4.0
    -   @endo/promise-kit@1.2.0

## @endo/stream-node@1.2.0

### Minor Changes

- [#3008](#3008)
[`d83b1ab`](d83b1ab)
Thanks [@kriskowal](https://github.com/kriskowal)! - - Relaxes
dependence on a global, post-lockdown `harden` function by taking a
    dependency on the new `@endo/harden` package.
Consequently, bundles will now entrain a `harden` implementation that is
superfluous if the bundled program is guaranteed to run in a
post-lockdown
    HardenedJS environment.
To compensate, use `bundle-source` with `-C hardened` or the analogous
feature
    for packaging conditions with your preferred bundler tool.
This will hollow out `@endo/harden` and defer exclusively to the global
    `harden`.

### Patch Changes

- Updated dependencies
\[[`2e00276`](2e00276),
[`2e00276`](2e00276),
[`029dcc4`](029dcc4),
[`a29ecd4`](a29ecd4),
[`d83b1ab`](d83b1ab),
[`b8b52ce`](b8b52ce)]:
    -   ses@1.15.0
    -   @endo/errors@1.3.0
    -   @endo/harden@1.1.0
    -   @endo/stream@1.3.0
    -   @endo/init@1.1.13

## @endo/zip@1.1.0

### Minor Changes

- [#3008](#3008)
[`d83b1ab`](d83b1ab)
Thanks [@kriskowal](https://github.com/kriskowal)! - - Relaxes
dependence on a global, post-lockdown `harden` function by taking a
    dependency on the new `@endo/harden` package.
Consequently, bundles will now entrain a `harden` implementation that is
superfluous if the bundled program is guaranteed to run in a
post-lockdown
    HardenedJS environment.
To compensate, use `bundle-source` with `-C hardened` or the analogous
feature
    for packaging conditions with your preferred bundler tool.
This will hollow out `@endo/harden` and defer exclusively to the global
    `harden`.

## @endo/init@1.1.13

### Patch Changes

- [#3085](#3085)
[`b8b52ce`](b8b52ce)
Thanks [@copilot-swe-agent](https://github.com/apps/copilot-swe-agent)!
- Move async_hooks patch to dedicated entrypoint for Node.js 24
compatibility

The async_hooks patch was originally added in #1115 to address debugger
issues (#1105) for local debugging of Node.js processes in lockdown
mode. However, the patch is breaking in Node.js 24, and it's unclear
whether it's still necessary in Node.js 20+.

To maintain backward compatibility while fixing the Node.js 24 breakage,
the patch has been moved from the default import path to a new dedicated
entrypoint `@endo/init/debug-async-hooks.js`. This allows users who need
the async_hooks patch for debugging in older Node.js versions to opt-in
explicitly, while preventing breakage for users on Node.js 24+.

If you were relying on the async_hooks patch, import
`@endo/init/debug-async-hooks.js` instead of `@endo/init/debug.js`. Note
that this entrypoint may not work correctly in Node.js 24+.

- Updated dependencies
\[[`029dcc4`](029dcc4),
[`d83b1ab`](d83b1ab)]:
    -   @endo/harden@1.1.0
    -   @endo/eventual-send@1.4.0
    -   @endo/promise-kit@1.2.0

## @endo/cli@2.3.12

### Patch Changes

- Updated dependencies
\[[`2e00276`](2e00276),
[`2e00276`](2e00276),
[`98f77e9`](98f77e9),
[`2e00276`](2e00276),
[`029dcc4`](029dcc4),
[`a29ecd4`](a29ecd4),
[`644ab15`](644ab15),
[`98f77e9`](98f77e9),
[`d83b1ab`](d83b1ab),
[`b8b52ce`](b8b52ce),
[`c488503`](c488503),
[`98f77e9`](98f77e9),
[`81b4c40`](81b4c40)]:
    -   ses@1.15.0
    -   @endo/errors@1.3.0
    -   @endo/patterns@1.8.0
    -   @endo/compartment-mapper@2.0.0
    -   @endo/harden@1.1.0
    -   @endo/bundle-source@4.2.0
    -   @endo/eventual-send@1.4.0
    -   @endo/exo@1.6.0
    -   @endo/import-bundle@1.6.0
    -   @endo/pass-style@1.7.0
    -   @endo/promise-kit@1.2.0
    -   @endo/stream-node@1.2.0
    -   @endo/init@1.1.13
    -   @endo/daemon@2.5.2

## @endo/daemon@2.5.2

### Patch Changes

- Updated dependencies
\[[`2e00276`](2e00276),
[`2e00276`](2e00276),
[`98f77e9`](98f77e9),
[`2e00276`](2e00276),
[`029dcc4`](029dcc4),
[`a29ecd4`](a29ecd4),
[`98f77e9`](98f77e9),
[`d83b1ab`](d83b1ab),
[`b8b52ce`](b8b52ce),
[`c488503`](c488503),
[`81b4c40`](81b4c40)]:
    -   ses@1.15.0
    -   @endo/errors@1.3.0
    -   @endo/patterns@1.8.0
    -   @endo/compartment-mapper@2.0.0
    -   @endo/harden@1.1.0
    -   @endo/captp@4.5.0
    -   @endo/eventual-send@1.4.0
    -   @endo/exo@1.6.0
    -   @endo/import-bundle@1.6.0
    -   @endo/marshal@1.9.0
    -   @endo/netstring@1.1.0
    -   @endo/promise-kit@1.2.0
    -   @endo/stream-node@1.2.0
    -   @endo/stream@1.3.0
    -   @endo/init@1.1.13

## @endo/test262-runner@0.1.49

### Patch Changes

- Updated dependencies
\[[`2e00276`](2e00276),
[`2e00276`](2e00276),
[`a29ecd4`](a29ecd4),
[`81b4c40`](81b4c40)]:
    -   ses@1.15.0
    -   @endo/compartment-mapper@2.0.0
kriskowal pushed a commit to endojs/endo-but-for-bots that referenced this pull request Apr 22, 2026
… load path (#3085)

## Plan: Fix lint failure

- [x] Identified lint failure as Prettier formatting issue
- [x] Ran Prettier --write on test file
- [x] Verified tests still pass
- [x] Verified lint passes

<!-- START COPILOT ORIGINAL PROMPT -->



<details>

<summary>Original prompt</summary>

> 
> ----
> 
> *This section details on the original issue you should resolve*
> 
> <issue_title>Remove async_hooks patch</issue_title>
> <issue_description>`@endo/init` started patching `node:async_hooks` in
endojs/endo#1115 to address debugger issues (see endojs/endo#1105).
> 
> While Node.js's async_hooks implementation remains incompatible with
frozen promises, I hear Node.js's inspector support has since stopped
relying on async_hooks, so we should be able to remove the patch
entirely. This may be needed as there are signs our async_hooks monkey
patch is partially broken under Node.js 24.</issue_description>
> 
> <agent_instructions>Remove the patch and its remnants which break in
Node 24. Include a changesets entry that references issue #1105 that led
us to include it to for local debugging of node processes in lockdown
mode. We don't know whether it's still necessary in Node 20+ so we've
removed it. If it still is, we'll restore the functionality in a new way
that is compatible with Node 24</agent_instructions>
> 
> ## Comments on the Issue (you are @copilot in this section)
> 
> <comments>
> <comment_new><author>@kriskowal</author><body>
> What’s the oldest Node.js version that the patch is necessary? Do we
have the option of applying the patch contingent on
`process.version`?</body></comment_new>
> <comment_new><author>@turadg</author><body>
> > This may be needed as there are signs our async_hooks monkey patch
is partially broken under Node.js 24.
> 
> Confirmed in
https://github.com/endojs/endo/actions/runs/21961549067/job/63440058166?pr=3083
> 
> ```
>   TypeError: this._enable is not a function
> at AsyncLocalStorage.run
(packages/init/src/node-async-local-storage-patch.js:72:8)
>     at packages/init/test/async_hooks.test.js:88:14
> ```
> 
> Can we go ahead and remove the patch?</body></comment_new>
> </comments>
> 


</details>



<!-- START COPILOT CODING AGENT SUFFIX -->

- Fixes endojs/endo#3012

<!-- START COPILOT CODING AGENT TIPS -->
---

✨ Let Copilot coding agent [set things up for
you](https://github.com/endojs/endo/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot)
— coding agent works faster and does higher quality work when set up for
your repo.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Node bug causes failures within the vscode Debug Console

5 participants