{
  "textDocument": {
    "uri": "file:///a/file.ts",
    "languageId": "javascript",
    "version": 1,
    "text": "// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.\n\n// @ts-check\n/// <reference path=\"./compiler.d.ts\" />\n// deno-lint-ignore-file no-undef\n\n// This module is the entry point for \"compiler\" isolate, ie. the one\n// that is created when Deno needs to type check TypeScript, and in some\n// instances convert TypeScript to JavaScript.\n\n// Removes the `__proto__` for security reasons.  This intentionally makes\n// Deno non compliant with ECMA-262 Annex B.2.2.1\ndelete Object.prototype.__proto__;\n\n((window) => {\n  /** @type {DenoCore} */\n  const core = window.Deno.core;\n\n  let logDebug = false;\n  let logSource = \"JS\";\n\n  function setLogDebug(debug, source) {\n    logDebug = debug;\n    if (source) {\n      logSource = source;\n    }\n  }\n\n  function debug(...args) {\n    if (logDebug) {\n      const stringifiedArgs = args.map((arg) =>\n        typeof arg === \"string\" ? arg : JSON.stringify(arg)\n      ).join(\" \");\n      // adding a non-zero integer value to the end of the debug string causes\n      // the message to be printed to stderr instead of stdout, which is better\n      // aligned to the behaviour of debug messages\n      core.print(`DEBUG ${logSource} - ${stringifiedArgs}\\n`, 1);\n    }\n  }\n\n  function error(...args) {\n    const stringifiedArgs = args.map((arg) =>\n      typeof arg === \"string\" || arg instanceof Error\n        ? String(arg)\n        : JSON.stringify(arg)\n    ).join(\" \");\n    core.print(`ERROR ${logSource} = ${stringifiedArgs}\\n`, 1);\n  }\n\n  class AssertionError extends Error {\n    constructor(msg) {\n      super(msg);\n      this.name = \"AssertionError\";\n    }\n  }\n\n  function assert(cond, msg = \"Assertion failed.\") {\n    if (!cond) {\n      throw new AssertionError(msg);\n    }\n  }\n\n  /** @type {Map<string, ts.SourceFile>} */\n  const sourceFileCache = new Map();\n\n  /** @param {ts.DiagnosticRelatedInformation} diagnostic */\n  function fromRelatedInformation({\n    start,\n    length,\n    file,\n    messageText: msgText,\n    ...ri\n  }) {\n    let messageText;\n    let messageChain;\n    if (typeof msgText === \"object\") {\n      messageChain = msgText;\n    } else {\n      messageText = msgText;\n    }\n    if (start !== undefined && length !== undefined && file) {\n      const startPos = file.getLineAndCharacterOfPosition(start);\n      const sourceLine = file.getFullText().split(\"\\n\")[startPos.line];\n      const fileName = file.fileName;\n      return {\n        start: startPos,\n        end: file.getLineAndCharacterOfPosition(start + length),\n        fileName,\n        messageChain,\n        messageText,\n        sourceLine,\n        ...ri,\n      };\n    } else {\n      return {\n        messageChain,\n        messageText,\n        ...ri,\n      };\n    }\n  }\n\n  /** @param {ts.Diagnostic[]} diagnostics */\n  function fromTypeScriptDiagnostic(diagnostics) {\n    return diagnostics.map(({ relatedInformation: ri, source, ...diag }) => {\n      /** @type {any} */\n      const value = fromRelatedInformation(diag);\n      value.relatedInformation = ri\n        ? ri.map(fromRelatedInformation)\n        : undefined;\n      value.source = source;\n      return value;\n    });\n  }\n\n  // Using incremental compile APIs requires that all\n  // paths must be either relative or absolute. Since\n  // analysis in Rust operates on fully resolved URLs,\n  // it makes sense to use the same scheme here.\n  const ASSETS = \"asset:///\";\n  const CACHE = \"cache:///\";\n\n  /** Diagnostics that are intentionally ignored when compiling TypeScript in\n   * Deno, as they provide misleading or incorrect information. */\n  const IGNORED_DIAGNOSTICS = [\n    // TS1208: All files must be modules when the '--isolatedModules' flag is\n    // provided.  We can ignore because we guarantee that all files are\n    // modules.\n    1208,\n    // TS1375: 'await' expressions are only allowed at the top level of a file\n    // when that file is a module, but this file has no imports or exports.\n    // Consider adding an empty 'export {}' to make this file a module.\n    1375,\n    // TS1103: 'for-await-of' statement is only allowed within an async function\n    // or async generator.\n    1103,\n    // TS2306: File 'file:///Users/rld/src/deno/subdir/amd_like.js' is\n    // not a module.\n    2306,\n    // TS2691: An import path cannot end with a '.ts' extension. Consider\n    // importing 'bad-module' instead.\n    2691,\n    // TS2792: Cannot find module. Did you mean to set the 'moduleResolution'\n    // option to 'node', or to add aliases to the 'paths' option?\n    2792,\n    // TS5009: Cannot find the common subdirectory path for the input files.\n    5009,\n    // TS5055: Cannot write file\n    // 'http://localhost:4545/subdir/mt_application_x_javascript.j4.js'\n    // because it would overwrite input file.\n    5055,\n    // TypeScript is overly opinionated that only CommonJS modules kinds can\n    // support JSON imports.  Allegedly this was fixed in\n    // Microsoft/TypeScript#26825 but that doesn't seem to be working here,\n    // so we will ignore complaints about this compiler setting.\n    5070,\n    // TS7016: Could not find a declaration file for module '...'. '...'\n    // implicitly has an 'any' type.  This is due to `allowJs` being off by\n    // default but importing of a JavaScript module.\n    7016,\n  ];\n\n  const SNAPSHOT_COMPILE_OPTIONS = {\n    esModuleInterop: true,\n    jsx: ts.JsxEmit.React,\n    module: ts.ModuleKind.ESNext,\n    noEmit: true,\n    strict: true,\n    target: ts.ScriptTarget.ESNext,\n  };\n\n  class ScriptSnapshot {\n    /** @type {string} */\n    specifier;\n    /** @type {string} */\n    version;\n    /**\n     * @param {string} specifier\n     * @param {string} version \n     */\n    constructor(specifier, version) {\n      this.specifier = specifier;\n      this.version = version;\n    }\n    /**\n     * @param {number} start \n     * @param {number} end \n     * @returns {string}\n     */\n    getText(start, end) {\n      const { specifier, version } = this;\n      debug(\n        `snapshot.getText(${start}, ${end}) specifier: ${specifier} version: ${version}`,\n      );\n      return core.jsonOpSync(\"op_get_text\", { specifier, version, start, end });\n    }\n    /**\n     * @returns {number}\n     */\n    getLength() {\n      const { specifier, version } = this;\n      debug(`snapshot.getLength() specifier: ${specifier} version: ${version}`);\n      return core.jsonOpSync(\"op_get_length\", { specifier, version });\n    }\n    /**\n     * @param {ScriptSnapshot} oldSnapshot\n     * @returns {ts.TextChangeRange | undefined}\n     */\n    getChangeRange(oldSnapshot) {\n      const { specifier, version } = this;\n      const { version: oldVersion } = oldSnapshot;\n      const oldLength = oldSnapshot.getLength();\n      debug(\n        `snapshot.getLength() specifier: ${specifier} oldVersion: ${oldVersion} version: ${version}`,\n      );\n      return core.jsonOpSync(\n        \"op_get_change_range\",\n        { specifier, oldLength, oldVersion, version },\n      );\n    }\n    dispose() {\n      const { specifier, version } = this;\n      debug(`snapshot.dispose() specifier: ${specifier} version: ${version}`);\n      core.jsonOpSync(\"op_dispose\", { specifier, version });\n    }\n  }\n\n  /** @type {ts.CompilerOptions} */\n  let compilationSettings = {};\n\n  /** @type {ts.LanguageService} */\n  let languageService;\n\n  /** An object literal of the incremental compiler host, which provides the\n   * specific \"bindings\" to the Deno environment that tsc needs to work.\n   *\n   * @type {ts.CompilerHost & ts.LanguageServiceHost} */\n  const host = {\n    fileExists(fileName) {\n      debug(`host.fileExists(\"${fileName}\")`);\n      return false;\n    },\n    readFile(specifier) {\n      debug(`host.readFile(\"${specifier}\")`);\n      return core.jsonOpSync(\"op_load\", { specifier }).data;\n    },\n    getSourceFile(\n      specifier,\n      languageVersion,\n      _onError,\n      _shouldCreateNewSourceFile,\n    ) {\n      debug(\n        `host.getSourceFile(\"${specifier}\", ${\n          ts.ScriptTarget[languageVersion]\n        })`,\n      );\n      let sourceFile = sourceFileCache.get(specifier);\n      if (sourceFile) {\n        return sourceFile;\n      }\n\n      /** @type {{ data: string; hash?: string; scriptKind: ts.ScriptKind }} */\n      const { data, hash, scriptKind } = core.jsonOpSync(\n        \"op_load\",\n        { specifier },\n      );\n      assert(\n        data != null,\n        `\"data\" is unexpectedly null for \"${specifier}\".`,\n      );\n      sourceFile = ts.createSourceFile(\n        specifier,\n        data,\n        languageVersion,\n        false,\n        scriptKind,\n      );\n      sourceFile.moduleName = specifier;\n      sourceFile.version = hash;\n      sourceFileCache.set(specifier, sourceFile);\n      return sourceFile;\n    },\n    getDefaultLibFileName() {\n      return `${ASSETS}/lib.esnext.d.ts`;\n    },\n    getDefaultLibLocation() {\n      return ASSETS;\n    },\n    writeFile(fileName, data, _writeByteOrderMark, _onError, sourceFiles) {\n      debug(`host.writeFile(\"${fileName}\")`);\n      let maybeSpecifiers;\n      if (sourceFiles) {\n        maybeSpecifiers = sourceFiles.map((sf) => sf.moduleName);\n      }\n      return core.jsonOpSync(\n        \"op_emit\",\n        { maybeSpecifiers, fileName, data },\n      );\n    },\n    getCurrentDirectory() {\n      return CACHE;\n    },\n    getCanonicalFileName(fileName) {\n      return fileName;\n    },\n    useCaseSensitiveFileNames() {\n      return true;\n    },\n    getNewLine() {\n      return \"\\n\";\n    },\n    resolveModuleNames(specifiers, base) {\n      debug(`host.resolveModuleNames()`);\n      debug(`  base: ${base}`);\n      debug(`  specifiers: ${specifiers.join(\", \")}`);\n      /** @type {Array<[string, ts.Extension] | undefined>} */\n      const resolved = core.jsonOpSync(\"op_resolve\", {\n        specifiers,\n        base,\n      });\n      if (resolved) {\n        const result = resolved.map((item) => {\n          if (item) {\n            const [resolvedFileName, extension] = item;\n            return {\n              resolvedFileName,\n              extension,\n              isExternalLibraryImport: false,\n            };\n          }\n          return undefined;\n        });\n        result.length = specifiers.length;\n        return result;\n      } else {\n        return new Array(specifiers.length);\n      }\n    },\n    createHash(data) {\n      return core.jsonOpSync(\"op_create_hash\", { data }).hash;\n    },\n\n    // LanguageServiceHost\n    getCompilationSettings() {\n      debug(\"host.getCompilationSettings()\");\n      return compilationSettings;\n    },\n    getScriptFileNames() {\n      debug(\"host.getScriptFileNames()\");\n      return core.jsonOpSync(\"op_script_names\", undefined);\n    },\n    getScriptVersion(specifier) {\n      debug(`host.getScriptVersion(\"${specifier}\")`);\n      const sourceFile = sourceFileCache.get(specifier);\n      if (sourceFile) {\n        return sourceFile.version ?? \"1\";\n      }\n      return core.jsonOpSync(\"op_script_version\", { specifier });\n    },\n    getScriptSnapshot(specifier) {\n      debug(`host.getScriptSnapshot(\"${specifier}\")`);\n      const sourceFile = sourceFileCache.get(specifier);\n      if (sourceFile) {\n        return {\n          getText(start, end) {\n            return sourceFile.text.substring(start, end);\n          },\n          getLength() {\n            return sourceFile.text.length;\n          },\n          getChangeRange() {\n            return undefined;\n          },\n        };\n      }\n      /** @type {string | undefined} */\n      const version = core.jsonOpSync(\"op_script_version\", { specifier });\n      if (version != null) {\n        return new ScriptSnapshot(specifier, version);\n      }\n      return undefined;\n    },\n  };\n\n  /** @type {Array<[string, number]>} */\n  const stats = [];\n  let statsStart = 0;\n\n  function performanceStart() {\n    stats.length = 0;\n    statsStart = Date.now();\n    ts.performance.enable();\n  }\n\n  /**\n   * @param {{ program: ts.Program | ts.EmitAndSemanticDiagnosticsBuilderProgram, fileCount?: number }} options \n   */\n  function performanceProgram({ program, fileCount }) {\n    if (program) {\n      if (\"getProgram\" in program) {\n        program = program.getProgram();\n      }\n      stats.push([\"Files\", program.getSourceFiles().length]);\n      stats.push([\"Nodes\", program.getNodeCount()]);\n      stats.push([\"Identifiers\", program.getIdentifierCount()]);\n      stats.push([\"Symbols\", program.getSymbolCount()]);\n      stats.push([\"Types\", program.getTypeCount()]);\n      stats.push([\"Instantiations\", program.getInstantiationCount()]);\n    } else if (fileCount != null) {\n      stats.push([\"Files\", fileCount]);\n    }\n    const programTime = ts.performance.getDuration(\"Program\");\n    const bindTime = ts.performance.getDuration(\"Bind\");\n    const checkTime = ts.performance.getDuration(\"Check\");\n    const emitTime = ts.performance.getDuration(\"Emit\");\n    stats.push([\"Parse time\", programTime]);\n    stats.push([\"Bind time\", bindTime]);\n    stats.push([\"Check time\", checkTime]);\n    stats.push([\"Emit time\", emitTime]);\n    stats.push(\n      [\"Total TS time\", programTime + bindTime + checkTime + emitTime],\n    );\n  }\n\n  function performanceEnd() {\n    const duration = Date.now() - statsStart;\n    stats.push([\"Compile time\", duration]);\n    return stats;\n  }\n\n  /**\n   * @typedef {object} Request\n   * @property {Record<string, any>} config\n   * @property {boolean} debug\n   * @property {string[]} rootNames\n   */\n\n  /** The API that is called by Rust when executing a request.\n   * @param {Request} request\n   */\n  function exec({ config, debug: debugFlag, rootNames }) {\n    setLogDebug(debugFlag, \"TS\");\n    performanceStart();\n    debug(\">>> exec start\", { rootNames });\n    debug(config);\n\n    const { options, errors: configFileParsingDiagnostics } = ts\n      .convertCompilerOptionsFromJson(config, \"\");\n    // The `allowNonTsExtensions` is a \"hidden\" compiler option used in VSCode\n    // which is not allowed to be passed in JSON, we need it to allow special\n    // URLs which Deno supports. So we need to either ignore the diagnostic, or\n    // inject it ourselves.\n    Object.assign(options, { allowNonTsExtensions: true });\n    const program = ts.createIncrementalProgram({\n      rootNames,\n      options,\n      host,\n      configFileParsingDiagnostics,\n    });\n\n    const { diagnostics: emitDiagnostics } = program.emit();\n\n    const diagnostics = [\n      ...program.getConfigFileParsingDiagnostics(),\n      ...program.getSyntacticDiagnostics(),\n      ...program.getOptionsDiagnostics(),\n      ...program.getGlobalDiagnostics(),\n      ...program.getSemanticDiagnostics(),\n      ...emitDiagnostics,\n    ].filter(({ code }) => !IGNORED_DIAGNOSTICS.includes(code));\n    performanceProgram({ program });\n\n    core.jsonOpSync(\"op_respond\", {\n      diagnostics: fromTypeScriptDiagnostic(diagnostics),\n      stats: performanceEnd(),\n    });\n    debug(\"<<< exec stop\");\n  }\n\n  /**\n   * @param {number} id \n   * @param {any} data \n   */\n  function respond(id, data = null) {\n    core.jsonOpSync(\"op_respond\", { id, data });\n  }\n\n  /**\n   * @param {LanguageServerRequest} request \n   */\n  function serverRequest({ id, ...request }) {\n    debug(`serverRequest()`, { id, ...request });\n    switch (request.method) {\n      case \"configure\": {\n        const { options, errors } = ts\n          .convertCompilerOptionsFromJson(request.compilerOptions, \"\");\n        Object.assign(options, { allowNonTsExtensions: true });\n        if (errors.length) {\n          debug(ts.formatDiagnostics(errors, host));\n        }\n        compilationSettings = options;\n        return respond(id, true);\n      }\n      case \"getAsset\": {\n        const sourceFile = host.getSourceFile(\n          request.specifier,\n          ts.ScriptTarget.ESNext,\n        );\n        return respond(id, sourceFile && sourceFile.text);\n      }\n      case \"getDiagnostics\": {\n        try {\n          /** @type {Record<string, any[]>} */\n          const diagnosticMap = {};\n          for (const specifier of request.specifiers) {\n            diagnosticMap[specifier] = fromTypeScriptDiagnostic([\n              ...languageService.getSemanticDiagnostics(specifier),\n              ...languageService.getSuggestionDiagnostics(specifier),\n              ...languageService.getSyntacticDiagnostics(specifier),\n            ].filter(({ code }) => !IGNORED_DIAGNOSTICS.includes(code)));\n          }\n          return respond(id, diagnosticMap);\n        } catch (e) {\n          if (\"stack\" in e) {\n            error(e.stack);\n          } else {\n            error(e);\n          }\n          return respond(id, {});\n        }\n      }\n      case \"getQuickInfo\": {\n        return respond(\n          id,\n          languageService.getQuickInfoAtPosition(\n            request.specifier,\n            request.position,\n          ),\n        );\n      }\n      case \"getCompletions\": {\n        return respond(\n          id,\n          languageService.getCompletionsAtPosition(\n            request.specifier,\n            request.position,\n            request.preferences,\n          ),\n        );\n      }\n      case \"getDocumentHighlights\": {\n        return respond(\n          id,\n          languageService.getDocumentHighlights(\n            request.specifier,\n            request.position,\n            request.filesToSearch,\n          ),\n        );\n      }\n      case \"getReferences\": {\n        return respond(\n          id,\n          languageService.getReferencesAtPosition(\n            request.specifier,\n            request.position,\n          ),\n        );\n      }\n      case \"getDefinition\": {\n        return respond(\n          id,\n          languageService.getDefinitionAndBoundSpan(\n            request.specifier,\n            request.position,\n          ),\n        );\n      }\n      case \"getImplementation\": {\n        return respond(\n          id,\n          languageService.getImplementationAtPosition(\n            request.specifier,\n            request.position,\n          ),\n        );\n      }\n      case \"findRenameLocations\": {\n        return respond(\n          id,\n          languageService.findRenameLocations(\n            request.specifier,\n            request.position,\n            request.findInStrings,\n            request.findInComments,\n            request.providePrefixAndSuffixTextForRename,\n          ),\n        );\n      }\n      default:\n        throw new TypeError(\n          // @ts-ignore exhausted case statement sets type to never\n          `Invalid request method for request: \"${request.method}\" (${id})`,\n        );\n    }\n  }\n\n  /** @param {{ debug: boolean; }} init */\n  function serverInit({ debug: debugFlag }) {\n    if (hasStarted) {\n      throw new Error(\"The language server has already been initialized.\");\n    }\n    hasStarted = true;\n    languageService = ts.createLanguageService(host);\n    core.ops();\n    setLogDebug(debugFlag, \"TSLS\");\n    debug(\"serverInit()\");\n  }\n\n  let hasStarted = false;\n\n  /** Startup the runtime environment, setting various flags.\n   * @param {{ debugFlag?: boolean; legacyFlag?: boolean; }} msg\n   */\n  function startup({ debugFlag = false }) {\n    if (hasStarted) {\n      throw new Error(\"The compiler runtime already started.\");\n    }\n    hasStarted = true;\n    core.ops();\n    setLogDebug(!!debugFlag, \"TS\");\n  }\n\n  // Setup the compiler runtime during the build process.\n  core.ops();\n  core.registerErrorClass(\"Error\", Error);\n\n  // A build time only op that provides some setup information that is used to\n  // ensure the snapshot is setup properly.\n  /** @type {{ buildSpecifier: string; libs: string[] }} */\n  const { buildSpecifier, libs } = core.jsonOpSync(\"op_build_info\", {});\n  for (const lib of libs) {\n    const specifier = `lib.${lib}.d.ts`;\n    // we are using internal APIs here to \"inject\" our custom libraries into\n    // tsc, so things like `\"lib\": [ \"deno.ns\" ]` are supported.\n    if (!ts.libs.includes(lib)) {\n      ts.libs.push(lib);\n      ts.libMap.set(lib, `lib.${lib}.d.ts`);\n    }\n    // we are caching in memory common type libraries that will be re-used by\n    // tsc on when the snapshot is restored\n    assert(\n      host.getSourceFile(`${ASSETS}${specifier}`, ts.ScriptTarget.ESNext),\n    );\n  }\n  // this helps ensure as much as possible is in memory that is re-usable\n  // before the snapshotting is done, which helps unsure fast \"startup\" for\n  // subsequent uses of tsc in Deno.\n  const TS_SNAPSHOT_PROGRAM = ts.createProgram({\n    rootNames: [buildSpecifier],\n    options: SNAPSHOT_COMPILE_OPTIONS,\n    host,\n  });\n  ts.getPreEmitDiagnostics(TS_SNAPSHOT_PROGRAM);\n\n  // exposes the two functions that are called by `tsc::exec()` when type\n  // checking TypeScript.\n  globalThis.startup = startup;\n  globalThis.exec = exec;\n\n  // exposes the functions that are called when the compiler is used as a\n  // language service.\n  globalThis.serverInit = serverInit;\n  globalThis.serverRequest = serverRequest;\n})(this);\n"
  }
}