Files
e2b-dev--e2b/packages/js-sdk
Mish Ushakov 64e9bc02b6 fix(js-sdk): unpin useDefineForClassFields — make caller-directory resolution emit-invariant (#1539)
Follow-up to #1536, which pinned `useDefineForClassFields: false` in the
js-sdk tsconfig because raising `target` to `es2022` flips the default
to `true`, and that broke the template builder. This PR fixes the root
cause and removes the pin, so the SDK now compiles with the standard
es2022 `[[Define]]` class-field semantics.

## Root cause

`TemplateBase` resolved its default `fileContextPath` in a **class field
initializer**:

```ts
private fileContextPath: PathLike =
  runtime === 'browser' ? '.' : (getCallerDirectory(STACK_TRACE_DEPTH) ?? '.')
```

With native class fields (define semantics), V8 evaluates field
initializers in an extra `<instance_members_initializer>` stack frame:

```
at getCallerDirectory (utils.ts)
at <instance_members_initializer> (index.ts)   ← extra frame under define semantics
at new TemplateBase (index.ts)
at Template (index.ts)
at user code                                    ← fixed-depth walk lands one frame short
```

`getCallerDirectory` walks the stack at a fixed depth, so it landed on
the SDK's own `src/template` directory instead of the caller's —
`.copy('folder/*', …)` then globbed against the wrong base dir (`Error:
No files found in .../src/template/...`), and the resulting client-side
failure mis-attributed build-step stack traces (the two
`stacktrace.test.ts` failures were cascades of this one bug).

## Fix

Move the default resolution into the constructor body, where the stack
shape is identical under both emits:

```ts
constructor(options?: TemplateOptions) {
  this.fileContextPath =
    options?.fileContextPath ??
    (runtime === 'browser' ? '.' : (getCallerDirectory(STACK_TRACE_DEPTH) ?? '.'))
```

The call is now emit-invariant (same `STACK_TRACE_DEPTH`), so the
tsconfig pin is removed. The method-level `getCallerFrame` call sites
were never affected — method bodies don't change shape with class-field
semantics.

Only the js-sdk is touched: the Python SDKs resolve the caller via
`inspect` and don't have this failure mode, and the CLI bundle doesn't
include `TemplateBase`.

## Usage example

Fixes relative-path resolution for SDK consumers whose toolchain emits
native class fields (e.g. esbuild/vitest with `target: es2022+`):

```ts
// user-project/scripts/template.ts
const template = Template()
  .fromBaseImage()
  .copy('assets/*', '/app/assets') // now resolves against user-project/scripts/,
                                   // not the SDK's own directory
```

## Verification

- `tests/template/stacktrace.test.ts` — 30/30 pass with the flag
defaulted (`true`), and still 30/30 when explicitly set back to `false`
(emit-invariance)
- `tests/template/build.test.ts` — 4/4 pass against the real backend
(real `.copy` glob + build)
- Smoke-tested built `dist/index.mjs` and `dist/index.js` from an
external directory: `fileContextPath` resolves to the importing script's
directory in both
- Unit project A/B: identical results with and without this change
(remaining failures are pre-existing `E2B_API_KEY`-gated live tests)
- `pnpm run typecheck`, `lint`, `format` 

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-14 05:01:53 -07:00
..
2025-08-21 08:45:25 -07:00
2025-06-05 07:10:07 -07:00
2026-07-13 15:42:35 +00:00

E2B Logo

Last 1 month downloads for the JavaScript SDK

What is E2B?

E2B is an open-source infrastructure that allows you to run AI-generated code in secure isolated sandboxes in the cloud. To start and control sandboxes, use our JavaScript SDK or Python SDK.

Run your first Sandbox

1. Install SDK

npm i e2b

2. Get your E2B API key

  1. Sign up to E2B here.
  2. Get your API key here.
  3. Set environment variable with your API key
E2B_API_KEY=e2b_***

3. Start a sandbox and run commands

import Sandbox from 'e2b'

const sandbox = await Sandbox.create()
const result = await sandbox.commands.run('echo "Hello from E2B!"')
console.log(result.stdout) // Hello from E2B!

4. Code execution with Code Interpreter

If you need runCode(), install the Code Interpreter SDK:

npm i @e2b/code-interpreter
import { Sandbox } from '@e2b/code-interpreter'

const sandbox = await Sandbox.create()
const execution = await sandbox.runCode('x = 1; x += 1; x')
console.log(execution.text)  // outputs 2

5. Check docs

Visit E2B documentation.

6. E2B cookbook

Visit our Cookbook to get inspired by examples with different LLMs and AI frameworks.