diff --git a/packages/playground-v2/src/compiler-distribution.ts b/packages/playground-v2/src/compiler-distribution.ts index 3772eb9ced54..99edd4f342b5 100644 --- a/packages/playground-v2/src/compiler-distribution.ts +++ b/packages/playground-v2/src/compiler-distribution.ts @@ -1,5 +1,6 @@ import { prerelease, valid } from "semver" import { fetchCompilerResource, type CompilerAssetMetadata } from "./compiler-assets" +import { isPullRequestCompilerVersion } from "./compiler-versions" export type CompilerModules = { sync: string @@ -19,10 +20,10 @@ export type CompilerDistribution = CompilerModules & { } export async function loadPublishedCompilerDistribution(version: string): Promise { - const [main, artifact] = await Promise.all([ - loadPackage("typescript", version), - loadPackage("@typescript/typescript-wasip1-wasm", version), - ]) + const [mainName, artifactName] = isPullRequestCompilerVersion(version) + ? ["@typescript-deploys/pr-build", "@typescript-deploys/pr-build-wasip1-wasm"] + : ["typescript", "@typescript/typescript-wasip1-wasm"] + const [main, artifact] = await Promise.all([loadPackage(mainName, version), loadPackage(artifactName, version)]) if (main.revision !== artifact.revision) { throw new Error(`TypeScript API and WASI artifact revisions do not match for ${version}`) } diff --git a/packages/playground-v2/src/compiler-versions.ts b/packages/playground-v2/src/compiler-versions.ts index aa3a384e60d4..ccf46d407387 100644 --- a/packages/playground-v2/src/compiler-versions.ts +++ b/packages/playground-v2/src/compiler-versions.ts @@ -12,7 +12,12 @@ export type CompilerVersionChoice = { } export function isWasmCompilerVersion(version: string) { - return valid(version) !== null && gte(version, "7.1.0-dev.20261030.1") + return isPullRequestCompilerVersion(version) || (valid(version) !== null && gte(version, "7.1.0-dev.20261030.1")) +} + +// Builds of microsoft/TypeScript pull requests, published as @typescript-deploys/pr-build. +export function isPullRequestCompilerVersion(version: string) { + return /^\d+\.\d+\.\d+-pr\.[1-9]\d*\.[1-9]\d*$/.test(version) } export function isUnsupportedNativeCompilerVersion(version: string) { diff --git a/packages/playground-v2/src/native-compiler.test.ts b/packages/playground-v2/src/native-compiler.test.ts index c30ec6c9cd42..ad6ba2999363 100644 --- a/packages/playground-v2/src/native-compiler.test.ts +++ b/packages/playground-v2/src/native-compiler.test.ts @@ -6,7 +6,7 @@ import { API } from "@typescript/typescript/sync" import * as ast from "@typescript/typescript/ast" import { instantiateWasm, WasmTransport } from "@typescript/typescript/wasm" import { NativeCompiler, type NativeCompileInput } from "./native-compiler" -import { legacyCompilerBaseUrl } from "./compiler-distribution" +import { legacyCompilerBaseUrl, loadPublishedCompilerDistribution } from "./compiler-distribution" import { compilerVersionChoices, isUnsupportedNativeCompilerVersion, @@ -560,14 +560,75 @@ test("overlapping legacy library loads wait for dependencies beneath cached root }) test("native versions start at the WASM nightly and exclude the published beta", () => { - for (const version of ["7.1.0-dev.20261030.1", "7.1.0-dev.20261031.1", "7.1.0-rc", "7.1.0", "7.2.0-beta", "8.0.0"]) { + for (const version of [ + "7.1.0-dev.20261030.1", + "7.1.0-dev.20261031.1", + "7.1.0-rc", + "7.1.0", + "7.2.0-beta", + "8.0.0", + "7.1.0-pr.65000.3", + ]) { assert.equal(isWasmCompilerVersion(version), true, version) } - for (const version of ["7.1.0-beta", "7.1.0-dev.20261029.1", "7.0.2", "6.0.3", "next", "pr-build"]) { + for (const version of [ + "7.1.0-beta", + "7.1.0-dev.20261029.1", + "7.0.2", + "6.0.3", + "next", + "pr-build", + "4.4.0-pr-12345-1", + ]) { assert.equal(isWasmCompilerVersion(version), false, version) } }) +test("pull request builds load from the @typescript-deploys/pr-build packages", async () => { + const version = "7.1.0-pr.65000.3" + const main = `https://unpkg.com/@typescript-deploys/pr-build@${version}/` + const wasm = `https://unpkg.com/@typescript-deploys/pr-build-wasip1-wasm@${version}/` + const file = (path: string) => ({ path, size: 1, integrity: `sha256-${"A".repeat(43)}=` }) + const responses: Record = { + [`${main}package.json`]: { + name: "@typescript-deploys/pr-build", + version, + gitHead: "abc", + exports: { + "./sync": "./dist/api/sync/api.js", + "./async": "./dist/api/async/api.js", + "./ast": "./dist/ast/index.js", + "./wasm": "./dist/wasm/index.js", + "./schemas/tsconfig.schema.json": "./schemas/tsconfig.schema.json", + }, + }, + [`${main}?meta`]: { files: [file("/schemas/tsconfig.schema.json")] }, + [`${wasm}package.json`]: { + name: "@typescript-deploys/pr-build-wasip1-wasm", + version, + gitHead: "abc", + exports: { "./lib/tsc.wasm": "./lib/tsc.wasm" }, + }, + [`${wasm}lib/?meta`]: { files: [file("/lib/tsc.wasm"), file("/lib/lib.d.ts")] }, + } + const originalFetch = globalThis.fetch + globalThis.fetch = async url => { + const body = responses[String(url)] + return body ? Response.json(body) : new Response(null, { status: 404 }) + } + try { + const distribution = await loadPublishedCompilerDistribution(version) + assert.equal(distribution.wasm.href, `${wasm}lib/tsc.wasm`) + assert.equal(distribution.sync, `${main}dist/api/sync/api.js`) + assert.deepEqual( + distribution.libraries.map(url => url.href), + [`${wasm}lib/lib.d.ts`] + ) + } finally { + globalThis.fetch = originalFetch + } +}) + test("the native default follows Nightly until a supported stable release is published", () => { const published = { versions: ["7.0.2", "7.1.0-dev.20261030.1", "7.1.0-dev.20261031.1", "7.1.0", "7.2.0-dev.20261101.1"],