Skip to content

Multi-input compilation#1

Merged
mmkal merged 10 commits into
mainfrom
spike/multi-input
Jun 27, 2026
Merged

Multi-input compilation#1
mmkal merged 10 commits into
mainfrom
spike/multi-input

Conversation

@mmkal

@mmkal mmkal commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

What changes

Adds a virtual project compile path to tswasm with two public call shapes:

ts.compile('const value = 1')
ts.compile({
  files: {
    'src/index.ts': 'export const value = 1',
  },
})

The string form is shorthand for a generated virtual project with entrypoint: 'index.ts', an index.ts source file, and a virtual tsconfig.json selecting that file. (The older { code, fileName } object shape is removed.)

Project requests resolve relative imports between in-memory files. Emitted JavaScript is returned from result.outputs:

const result = ts.compile({
  files: {
    'src/a.ts': 'export const aa = 1',
    'src/b.ts': "import { aa } from './a'\n\nexport const bb = aa + 0.5",
  },
})

console.log(result.outputs['src/b.js'])

entrypoint selects which emitted output also populates result.js:

const result = ts.compile({
  entrypoint: 'src/b.ts',
  files: {
    'src/a.ts': 'export const aa = 1',
    'src/b.ts': "import { aa } from './a'\n\nexport const bb = aa + 0.5",
  },
})

console.log(result.js) // equivalent to result.outputs['src/b.js']

Project requests can include an optional virtual cwd and an optional virtual tsconfig file path. If tsconfig is omitted and files contains tsconfig.json at the virtual cwd, tswasm uses that virtual config like tsc would. Passing tsconfig: 'tsconfig.lib.json' selects a non-default config file, and the selected config must be present in files.

Type roots are configured the normal TypeScript way in compilerOptions.typeRoots; when absent, TypeScript Go derives default node_modules/@types roots from the virtual cwd/config path.

const result = ts.compile({
  cwd: '/app',
  entrypoint: 'src/index.ts',
  tsconfig: 'tsconfig.lib.json',
  files: {
    'tsconfig.lib.json': JSON.stringify({
      compilerOptions: {
        moduleResolution: 'Bundler',
        types: ['custom'],
      },
      files: ['src/index.ts'],
    }),
    'src/index.ts': "import { external } from 'pkg'\n\nexport const value = external + typedValue",
    'node_modules/pkg/package.json': JSON.stringify({ name: 'pkg', types: 'index.d.ts' }),
    'node_modules/pkg/index.d.ts': 'export const external: number',
    'node_modules/@types/custom/index.d.ts': 'declare const typedValue: number',
  },
})

Reviewer notes

  • result.js is populated from the emitted output for entrypoint when one is provided.
  • Project requests put emitted JS in result.outputs, including .js, .mjs, and .cjs outputs.
  • Diagnostics include fileName when TypeScript Go reports one, relative to the virtual cwd when possible.
  • The package does not read host files, real node_modules, package dependencies, or declaration files unless they are supplied in the project files map.
  • Added CONTEXT.md to pin down the virtual project/config/cwd/entrypoint terminology from the spike.

Verification

  • pnpm run build && pnpm exec vitest run test/compile.test.ts
  • pnpm run release:check

Note

Medium Risk
Public API break (CompileRequest removed) and substantial wasm compile-path changes affect how all callers build inputs and read results; behavior is well covered by new integration tests but edge cases around config/file selection remain possible.

Overview
Replaces the single-file { code, fileName } API with virtual project compilation: compile({ files, entrypoint?, tsconfig?, cwd? }), while compile(string) still works by expanding to index.ts plus a virtual tsconfig.json.

The Go wasm layer now builds programs from an in-memory file map, optionally parses virtual tsconfig via TypeScript Go’s config parser (including default tsconfig.json at virtual cwd), emits all JS outputs into result.outputs (.js/.mjs/.cjs), and sets result.js from the entrypoint emit. Diagnostics gain optional fileName; success is derived from diagnostics even when emit is skipped (e.g. noEmit).

Docs (README.md, new CONTEXT.md) and integration tests cover multi-file imports, virtual node_modules/typeRoots, and benchmarks now exercise the project request shape.

Reviewed by Cursor Bugbot for commit dec08d0. Bugbot is set up for automated code reviews on this repo. Configure here.

@mmkal mmkal changed the title Spike multi-input compilation Multi-input compilation Jun 25, 2026
@mmkal mmkal marked this pull request as ready for review June 25, 2026 08:57

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 48a61ec. Configure here.

Comment thread go/tswasm-wasm/main.go
@mmkal mmkal merged commit 318f91d into main Jun 27, 2026
3 checks passed
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.

1 participant