mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-05-28 18:26:54 +00:00
feat: allow configuration of the typescript-compiler (#66241)
This commit is contained in:
committed by
GitHub
parent
c94fe2d40e
commit
2972485a87
@@ -41,7 +41,7 @@ vi.mock(
|
||||
await compiler.setup({ useNodeModules: true });
|
||||
return {
|
||||
...actual,
|
||||
checkTSServiceIsReady: () => Promise.resolve(true),
|
||||
setupTSCompiler: () => Promise.resolve(true),
|
||||
compileTypeScriptCode: code => {
|
||||
const { result, error } = compiler.compile(code, 'index.tsx');
|
||||
if (error) throw error;
|
||||
|
||||
@@ -20,7 +20,7 @@ import { version } from '@freecodecamp/browser-scripts/package.json';
|
||||
import { WorkerExecutor } from './worker-executor';
|
||||
import {
|
||||
compileTypeScriptCode,
|
||||
checkTSServiceIsReady
|
||||
setupTSCompiler
|
||||
} from './typescript-worker-handler';
|
||||
|
||||
const protectTimeout = 100;
|
||||
@@ -148,7 +148,7 @@ const getJSXModuleTranspiler = loopProtectOptions => async challengeFile => {
|
||||
|
||||
const getTSTranspiler = loopProtectOptions => async challengeFile => {
|
||||
await loadBabel();
|
||||
await checkTSServiceIsReady();
|
||||
await setupTSCompiler();
|
||||
const babelOptions = getBabelOptions(presetsJS, loopProtectOptions);
|
||||
return flow(
|
||||
partial(transformHeadTailAndContents, compileTypeScriptCode),
|
||||
@@ -159,7 +159,7 @@ const getTSTranspiler = loopProtectOptions => async challengeFile => {
|
||||
const getTSXModuleTranspiler = loopProtectOptions => async challengeFile => {
|
||||
await loadBabel();
|
||||
await loadPresetReact();
|
||||
await checkTSServiceIsReady();
|
||||
await setupTSCompiler();
|
||||
const baseOptions = getBabelOptions(presetsJSX, loopProtectOptions);
|
||||
const babelOptions = {
|
||||
...baseOptions,
|
||||
|
||||
@@ -31,10 +31,12 @@ export function compileTypeScriptCode(code: string): Promise<string> {
|
||||
});
|
||||
}
|
||||
|
||||
export function checkTSServiceIsReady(): Promise<boolean> {
|
||||
export function setupTSCompiler(
|
||||
compilerOptions?: Record<string, unknown>
|
||||
): Promise<boolean> {
|
||||
return awaitResponse({
|
||||
messenger: getTypeScriptWorker(),
|
||||
message: { type: 'check-is-ready' },
|
||||
message: { type: 'setup', ...(compilerOptions && { compilerOptions }) },
|
||||
onMessage: (data, onSuccess) => {
|
||||
if (data.type === 'ready') {
|
||||
onSuccess(true);
|
||||
|
||||
@@ -16,10 +16,15 @@ export class Compiler {
|
||||
this.tsvfs = tsvfs;
|
||||
}
|
||||
|
||||
async setup(opts?: { useNodeModules: boolean }) {
|
||||
async setup(opts?: { useNodeModules?: boolean; compilerOptions?: unknown }) {
|
||||
const ts = this.ts;
|
||||
const tsvfs = this.tsvfs;
|
||||
|
||||
const parsedOptions = ts.convertCompilerOptionsFromJson(
|
||||
opts?.compilerOptions ?? {},
|
||||
'/'
|
||||
);
|
||||
|
||||
const compilerOptions: CompilerOptions = {
|
||||
target: ts.ScriptTarget.ES2024,
|
||||
module: ts.ModuleKind.Preserve, // Babel is handling module transformation, so TS should leave them alone.
|
||||
@@ -28,7 +33,8 @@ export class Compiler {
|
||||
// sync with TypeScript over time. It was last synced with TypeScript
|
||||
// 3.8.0-rc."
|
||||
jsx: ts.JsxEmit.Preserve, // Babel will handle JSX,
|
||||
allowUmdGlobalAccess: true // Necessary because React is loaded via a UMD script.
|
||||
allowUmdGlobalAccess: true, // Necessary because React is loaded via a UMD script.
|
||||
...parsedOptions.options
|
||||
};
|
||||
|
||||
const fsMap = opts?.useNodeModules
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import type { CompilerOptions } from 'typescript';
|
||||
import { Compiler } from './modules/typescript-compiler';
|
||||
|
||||
// Most of the ts types are only a guideline. This is because we're not bundling
|
||||
@@ -23,9 +24,10 @@ interface TSCompiledMessage {
|
||||
error: string;
|
||||
}
|
||||
|
||||
interface CheckIsReadyRequestEvent extends MessageEvent {
|
||||
interface SetupEvent extends MessageEvent {
|
||||
data: {
|
||||
type: 'check-is-ready';
|
||||
type: 'setup';
|
||||
compilerOptions?: CompilerOptions;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -59,12 +61,10 @@ function importTS(version: string) {
|
||||
cachedVersion = version;
|
||||
}
|
||||
|
||||
ctx.onmessage = (
|
||||
e: TSCompileEvent | CheckIsReadyRequestEvent | CancelEvent
|
||||
) => {
|
||||
ctx.onmessage = (e: TSCompileEvent | SetupEvent | CancelEvent) => {
|
||||
const { data, ports } = e;
|
||||
if (data.type === 'check-is-ready') {
|
||||
void handleCheckIsReadyRequest(ports[0]);
|
||||
if (data.type === 'setup') {
|
||||
void handleSetupRequest(data, ports[0]);
|
||||
} else if (data.type === 'cancel') {
|
||||
handleCancelRequest(data);
|
||||
} else {
|
||||
@@ -75,15 +75,16 @@ ctx.onmessage = (
|
||||
importTS(TS_VERSION);
|
||||
|
||||
const compiler = new Compiler(ts, tsvfs);
|
||||
const isSetup = compiler.setup();
|
||||
|
||||
// This lets the client know that there is nothing to cancel.
|
||||
function handleCancelRequest({ value }: { value: number }) {
|
||||
postMessage({ type: 'is-alive', text: value });
|
||||
}
|
||||
|
||||
async function handleCheckIsReadyRequest(port: MessagePort) {
|
||||
await isSetup;
|
||||
async function handleSetupRequest(data: SetupEvent['data'], port: MessagePort) {
|
||||
await compiler.setup({
|
||||
compilerOptions: data.compilerOptions
|
||||
});
|
||||
// We freeze this to prevent learners from getting the worker into a weird
|
||||
// state.
|
||||
Object.freeze(self);
|
||||
|
||||
Reference in New Issue
Block a user