From 3040857983a5c7dc60eb2c3d00b57ba0cae8754b Mon Sep 17 00:00:00 2001 From: Orta Date: Mon, 19 Jul 2021 09:31:37 +0100 Subject: [PATCH 1/2] Use the compiler options as a backup for finding compiler options from inside the param handling code --- packages/sandbox/src/compilerOptions.ts | 46 +++++++++----- packages/sandbox/src/index.ts | 2 +- .../test/defaultCompilerOptions.test.ts | 61 +++++++++++++++++++ 3 files changed, 93 insertions(+), 16 deletions(-) create mode 100644 packages/sandbox/test/defaultCompilerOptions.test.ts diff --git a/packages/sandbox/src/compilerOptions.ts b/packages/sandbox/src/compilerOptions.ts index ec202423c15f..35842b172d70 100644 --- a/packages/sandbox/src/compilerOptions.ts +++ b/packages/sandbox/src/compilerOptions.ts @@ -60,24 +60,40 @@ export function getDefaultSandboxCompilerOptions(config: SandboxConfig, monaco: * Loop through all of the entries in the existing compiler options then compare them with the * query params and return an object which is the changed settings via the query params */ -export const getCompilerOptionsFromParams = (options: CompilerOptions, params: URLSearchParams): CompilerOptions => { - const urlDefaults = Object.entries(options).reduce((acc: any, [key, value]) => { - if (params.has(key)) { - const urlValue = params.get(key)! - - if (urlValue === "true") { - acc[key] = true - } else if (urlValue === "false") { - acc[key] = false - } else if (!isNaN(parseInt(urlValue, 10))) { - acc[key] = parseInt(urlValue, 10) +export const getCompilerOptionsFromParams = ( + playgroundDefaults: CompilerOptions, + ts: typeof import("typescript"), + params: URLSearchParams +): CompilerOptions => { + const returnedOptions: CompilerOptions = {} + + params.forEach((val, key) => { + // First use the defaults object to drop compiler flags which are already set to the default + if (playgroundDefaults[key]) { + let toSet = undefined + if (val === "true" && playgroundDefaults[key] !== true) { + toSet = true + } else if (val === "false" && playgroundDefaults[key] !== false) { + toSet = false + } else if (!isNaN(parseInt(val, 10)) && playgroundDefaults[key] !== parseInt(val, 10)) { + toSet = parseInt(val, 10) } - } - return acc - }, {}) + if (toSet !== undefined) returnedOptions[key] = toSet + } else { + // If that doesn't work, double check that the flag exists and allow it through + // @ts-ignore + const flagExists = ts.optionDeclarations.find(opt => opt.name === key) + if (flagExists) { + let realValue: number | boolean = true + if (val === "false") realValue = false + if (!isNaN(parseInt(val, 10))) realValue = parseInt(val, 10) + returnedOptions[key] = realValue + } + } + }) - return urlDefaults + return returnedOptions } // Can't set sandbox to be the right type because the param would contain this function diff --git a/packages/sandbox/src/index.ts b/packages/sandbox/src/index.ts index 5117a00cb90d..0723b71081aa 100644 --- a/packages/sandbox/src/index.ts +++ b/packages/sandbox/src/index.ts @@ -123,7 +123,7 @@ export const createTypeScriptSandbox = ( let compilerOptions: CompilerOptions if (!config.suppressAutomaticallyGettingCompilerFlags) { const params = new URLSearchParams(location.search) - let queryParamCompilerOptions = getCompilerOptionsFromParams(compilerDefaults, params) + let queryParamCompilerOptions = getCompilerOptionsFromParams(compilerDefaults, ts, params) if (Object.keys(queryParamCompilerOptions).length) config.logger.log("[Compiler] Found compiler options in query params: ", queryParamCompilerOptions) compilerOptions = { ...compilerDefaults, ...queryParamCompilerOptions } diff --git a/packages/sandbox/test/defaultCompilerOptions.test.ts b/packages/sandbox/test/defaultCompilerOptions.test.ts new file mode 100644 index 000000000000..9c02b024fa90 --- /dev/null +++ b/packages/sandbox/test/defaultCompilerOptions.test.ts @@ -0,0 +1,61 @@ +import { getCompilerOptionsFromParams, getDefaultSandboxCompilerOptions } from "../src/compilerOptions" +import ts from "typescript" + +const fauxMonaco: any = { + languages: { + typescript: { + ModuleResolutionKind: ts.ModuleResolutionKind, + ScriptTarget: ts.ScriptTarget, + JsxEmit: ts.JsxEmit, + ModuleKind: ts.ModuleKind, + }, + }, +} + +describe(getCompilerOptionsFromParams, () => { + it("ignores compiler flags which are the same as the defaults", () => { + // noImplicitReturns=true is the default, and shouldnt be in the object + const params = new URLSearchParams("?noImplicitThis=false&noImplicitReturns=true#code/JYOw") + const defaults = getDefaultSandboxCompilerOptions({ filetype: "js" } as any, fauxMonaco) + + expect(getCompilerOptionsFromParams(defaults, ts, params)).toMatchInlineSnapshot(` + Object { + "noImplicitThis": false, + } + `) + }) + + it("ignores non-compiler flags", () => { + // noImplicitReturns=true is the default, and shouldnt be in the object + const params = new URLSearchParams("?asdasdasdasd=false") + const defaults = getDefaultSandboxCompilerOptions({ filetype: "js" } as any, fauxMonaco) + + expect(getCompilerOptionsFromParams(defaults, ts, params)).toMatchInlineSnapshot(`Object {}`) + }) + + it("hanndles mapped types like target et", () => { + // noImplicitReturns=true is the default, and shouldnt be in the object + const params = new URLSearchParams("?target=6") + const defaults = getDefaultSandboxCompilerOptions({ filetype: "js" } as any, fauxMonaco) + + expect(getCompilerOptionsFromParams(defaults, ts, params)).toMatchInlineSnapshot(` + Object { + "target": 6, + } + `) + }) + + it("handles settings options which haven't been given defaults in the monaco defaults", () => { + const search = "?ts=4.4.0-beta&exactOptionalPropertyTypes=true#code/JYOw" + const params = new URLSearchParams(search) + expect(params.has("exactOptionalPropertyTypes")).toBeTruthy() + + const defaults = getDefaultSandboxCompilerOptions({ filetype: "js" } as any, fauxMonaco) + + expect(getCompilerOptionsFromParams(defaults, ts, params)).toMatchInlineSnapshot(` + Object { + "exactOptionalPropertyTypes": true, + } + `) + }) +}) From 1f63d5aecaab5858b953b60518a5aa70975d9a21 Mon Sep 17 00:00:00 2001 From: Orta Date: Mon, 19 Jul 2021 09:57:29 +0100 Subject: [PATCH 2/2] Adds strict to the playground defaults and some test tweasks --- packages/sandbox/src/compilerOptions.ts | 2 ++ packages/sandbox/test/defaultCompilerOptions.test.ts | 4 +--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/sandbox/src/compilerOptions.ts b/packages/sandbox/src/compilerOptions.ts index 35842b172d70..353b1d9fe2ae 100644 --- a/packages/sandbox/src/compilerOptions.ts +++ b/packages/sandbox/src/compilerOptions.ts @@ -10,6 +10,8 @@ type Monaco = typeof import("monaco-editor") export function getDefaultSandboxCompilerOptions(config: SandboxConfig, monaco: Monaco) { const useJavaScript = config.filetype === "js" const settings: CompilerOptions = { + strict: true, + noImplicitAny: true, strictNullChecks: !useJavaScript, strictFunctionTypes: true, diff --git a/packages/sandbox/test/defaultCompilerOptions.test.ts b/packages/sandbox/test/defaultCompilerOptions.test.ts index 9c02b024fa90..c4cf6201479e 100644 --- a/packages/sandbox/test/defaultCompilerOptions.test.ts +++ b/packages/sandbox/test/defaultCompilerOptions.test.ts @@ -26,15 +26,13 @@ describe(getCompilerOptionsFromParams, () => { }) it("ignores non-compiler flags", () => { - // noImplicitReturns=true is the default, and shouldnt be in the object const params = new URLSearchParams("?asdasdasdasd=false") const defaults = getDefaultSandboxCompilerOptions({ filetype: "js" } as any, fauxMonaco) expect(getCompilerOptionsFromParams(defaults, ts, params)).toMatchInlineSnapshot(`Object {}`) }) - it("hanndles mapped types like target et", () => { - // noImplicitReturns=true is the default, and shouldnt be in the object + it("handles mapped types like target et", () => { const params = new URLSearchParams("?target=6") const defaults = getDefaultSandboxCompilerOptions({ filetype: "js" } as any, fauxMonaco)