diff --git a/build/filters.js b/build/filters.js index 095cf733f8ca7..fc4c937d3e7f2 100644 --- a/build/filters.js +++ b/build/filters.js @@ -36,7 +36,7 @@ module.exports.unicodeFilter = [ '!LICENSES.chromium.html', '!**/LICENSE', - '!**/*.{dll,exe,png,bmp,jpg,scpt,cur,ttf,woff,eot,template,ico,icns,opus}', + '!**/*.{dll,exe,png,bmp,jpg,scpt,cur,ttf,woff,eot,template,ico,icns,opus,wasm}', '!**/test/**', '!**/*.test.ts', '!**/*.{d.ts,json,md}', @@ -85,6 +85,7 @@ module.exports.indentationFilter = [ '!test/smoke/out/**', '!extensions/typescript-language-features/test-workspace/**', '!extensions/typescript-language-features/resources/walkthroughs/**', + '!extensions/typescript-language-features/node-maintainer/**', '!extensions/markdown-math/notebook-out/**', '!extensions/ipynb/notebook-out/**', '!extensions/vscode-api-tests/testWorkspace/**', @@ -112,7 +113,7 @@ module.exports.indentationFilter = [ '!src/vs/*/**/*.d.ts', '!src/typings/**/*.d.ts', '!extensions/**/*.d.ts', - '!**/*.{svg,exe,png,bmp,jpg,scpt,bat,cmd,cur,ttf,woff,eot,md,ps1,template,yaml,yml,d.ts.recipe,ico,icns,plist,opus,admx,adml}', + '!**/*.{svg,exe,png,bmp,jpg,scpt,bat,cmd,cur,ttf,woff,eot,md,ps1,template,yaml,yml,d.ts.recipe,ico,icns,plist,opus,admx,adml,wasm}', '!build/{lib,download,linux,darwin}/**/*.js', '!build/**/*.sh', '!build/azure-pipelines/**/*.js', @@ -154,6 +155,7 @@ module.exports.copyrightFilter = [ '!**/*.disabled', '!**/*.code-workspace', '!**/*.js.map', + '!**/*.wasm', '!build/**/*.init', '!build/linux/libcxx-fetcher.*', '!resources/linux/snap/snapcraft.yaml', @@ -163,6 +165,7 @@ module.exports.copyrightFilter = [ '!extensions/markdown-language-features/media/highlight.css', '!extensions/markdown-math/notebook-out/**', '!extensions/ipynb/notebook-out/**', + '!extensions/typescript-language-features/node-maintainer/**', '!extensions/html-language-features/server/src/modes/typescript/*', '!extensions/*/server/bin/*', '!src/vs/editor/test/node/classification/typescript-test.ts', diff --git a/extensions/shared.webpack.config.js b/extensions/shared.webpack.config.js index 5a9ccd93d30fc..4b0ec1cb0abf1 100644 --- a/extensions/shared.webpack.config.js +++ b/extensions/shared.webpack.config.js @@ -138,6 +138,9 @@ function withBrowserDefaults(/**@type WebpackConfig & { context: string }*/extCo }, }, ] + }, { + test: /\.wasm$/, + type: 'asset/inline' }] }, externals: { diff --git a/extensions/typescript-language-features/package-manager/.eslintrc.js b/extensions/typescript-language-features/package-manager/.eslintrc.js new file mode 100644 index 0000000000000..63ef38ea46b5c --- /dev/null +++ b/extensions/typescript-language-features/package-manager/.eslintrc.js @@ -0,0 +1,11 @@ +module.exports = { + "parserOptions": { + "tsconfigRootDir": __dirname, + "project": "./tsconfig.json" + }, + "rules": { + "@typescript-eslint/prefer-optional-chain": "warn", + "@typescript-eslint/prefer-readonly": "warn" + } +}; + diff --git a/extensions/typescript-language-features/package-manager/README.md b/extensions/typescript-language-features/package-manager/README.md new file mode 100644 index 0000000000000..058df33811fc8 --- /dev/null +++ b/extensions/typescript-language-features/package-manager/README.md @@ -0,0 +1,40 @@ +# Package Manager + +This package is a web-compatible package manager built with tsserverlib +compatibility in mind. It does not require a "real" filesystem or a "real" NPM +installation, but instead uses [orogene](https://github.com/orogene/orogene) +to perform package management operations. + +It is largely a thin wrapper around Orogene's [node-maintainer WASM +API](https://github.com/orogene/orogene/blob/abba96e6662c3465a498fbe6154ffcf2fe33fac4/crates/node-maintainer/src/wasm.rs). + +## Updating vendored `node-maintainer` + +Currently, this package vendors a prebuilt version of `node-maintainer` into +the `./node-maintainer` directory. This has to be manually built and updated +as needed whenever there are desired changes from orogene. + +To update the directory: + +1. `rm -rf ./node-maintainer` +2. clone https://github.com/orogene/orogene somewhere. See the [contributing + instructions](https://github.com/orogene/orogene/blob/abba96e6662c3465a498fbe6154ffcf2fe33fac4/CONTRIBUTING.md#getting-up-and-running) + for a guide on how to set up and build wasm modules. +3. `mv /path/to/orogene/crates/node-maintainer/pkg ./node-maintainer` +4. `git add node-maintainer && git commit -m 'updated node-maintainer' + +## A Note on Build Requirements + +To get this branch working, as of today (4/7/2023), you need to use a +TypeScript release that includes [this +commit](https://github.com/microsoft/TypeScript/commit/d23b7e7c52c471732079a9834bbfeef53b1a1697), +which has been merged into `main`, but not released yet. + +In order to use an unreleased TypeScript with VS Code: + +1. At the `../..` (`vscode/extensions/`) level, you should `npm link` the + version of typescript you want. + 1. Go to your `typescript` source checkout + 2. Call `npm link` + 3. Go to `vscode/extensions` + 4. Call `npm link typescript` diff --git a/extensions/typescript-language-features/package-manager/node-maintainer/README.md b/extensions/typescript-language-features/package-manager/node-maintainer/README.md new file mode 100644 index 0000000000000..2510288f05f9c --- /dev/null +++ b/extensions/typescript-language-features/package-manager/node-maintainer/README.md @@ -0,0 +1,19 @@ +# `node-maintainer` + +An NPM dependency resolver for building `node_modules/` trees and +extracting them to their final resting place. + +## Orogene + +This package is part of [Orogene](https://orogene.dev), a package manager for +`node_modules/`. + +## Contributing + +For contributing guidelines, please see the [main orogenee +repository](https://github.com/orogene/orogene). + +## License + +For licensing information, please check [the LICENSE file in the Orogene +repository](https://github.com/orogene/orogene/blob/main/LICENSE). diff --git a/extensions/typescript-language-features/package-manager/node-maintainer/node_maintainer.d.ts b/extensions/typescript-language-features/package-manager/node-maintainer/node_maintainer.d.ts new file mode 100644 index 0000000000000..b6df152b81f2f --- /dev/null +++ b/extensions/typescript-language-features/package-manager/node-maintainer/node_maintainer.d.ts @@ -0,0 +1,491 @@ +/* tslint:disable */ +/* eslint-disable */ +/** +* Resolves a dependency tree using `spec` as the root package. +* @param {string} spec +* @param {any} opts +* @returns {Promise} +*/ +export function resolveSpec(spec: string, opts: any): Promise; +/** +* Returns a dependency tree using a `package.json` manifest as the root +* package. +* @param {PackageJson} manifest +* @param {any} opts +* @returns {Promise} +*/ +export function resolveManifest(manifest: PackageJson, opts: any): Promise; +/** +* Resolves a `Packument` for the given package `spec`. +* +* This uses default `Nassun` options and does not cache the result. +* To configure `Nassun`, and/or enable more efficient caching/reuse, +* look at `Package#packument` instead. +* @param {string} spec +* @param {any} opts +* @returns {Promise} +*/ +export function packument(spec: string, opts: any): Promise; +/** +* Resolves a partial ("corgi") version of the `Packument` for the given +* package `spec`. +* +* This uses default `Nassun` options and does not cache the result. +* To configure `Nassun`, and/or enable more efficient caching/reuse, +* look at `Package#packument` instead. +* @param {string} spec +* @param {any} opts +* @returns {Promise} +*/ +export function corgiPackument(spec: string, opts: any): Promise; +/** +* Resolves version metadata from the given package `spec`, using the default +* resolution algorithm. +* +* This uses default `Nassun` options and does not cache the result. To +* configure `Nassun`, and/or enable more efficient caching/reuse, look at +* `Package#metadata` instead. +* @param {string} spec +* @param {any} opts +* @returns {Promise} +*/ +export function metadata(spec: string, opts: any): Promise; +/** +* Resolves a partial ("corgi") version of the version metadata from the +* given package `spec`, using the default resolution algorithm. +* +* This uses default `Nassun` settings and does not cache the result. To +* configure `Nassun`, and/or enable more efficient caching/reuse, look at +* `Package#metadata` instead. +* @param {string} spec +* @param {any} opts +* @returns {Promise} +*/ +export function corgiMetadata(spec: string, opts: any): Promise; +/** +* Resolves a tarball from the given package `spec`, using the +* default resolution algorithm. This tarball will have its data checked +* if the package metadata fetched includes integrity information. +* +* This uses default `Nassun` settings and does not cache the result. +* To configure `Nassun`, and/or enable more efficient caching/reuse, +* look at `Package#tarball` instead. +* @param {string} spec +* @param {any} opts +* @returns {Promise} +*/ +export function tarball(spec: string, opts: any): Promise; +/** +* Resolves to a `ReadableStream` of entries from the given package +* `spec`, using the default resolution algorithm. The source tarball will +* have its data checked if the package metadata fetched includes integrity +* information. +* +* This uses default `Nassun` settings and does not cache the result. To +* configure `Nassun`, and/or enable more efficient caching/reuse, look at +* `Package#entries` instead. +* @param {string} spec +* @param {any} opts +* @returns {Promise} +*/ +export function entries(spec: string, opts: any): Promise; + +export interface NodeMaintainerError { + message: string; + code?: string; +} + +export interface PackageJson { + dependencies?: Record; + devDependencies?: Record; + peerDependencies?: Record; + optionalDependencies?: Record; + bundledDependencies?: string[]; +} + + +export interface NodeMaintainerOptions { + registry?: string; + scopedRegistries?: Map; + concurrency?: number; + kdlLock?: string; + npmLock?: string; + defaultTag?: string; +} + +export interface NodeMaintainer { + inner: NodeMaintainer; +} + + +/** + * Error type thrown by the Nassun API. + */ +export interface NassunError { + message: string; + code?: string; +} + +/** + * An entry extracted from a package tarball. + */ +export interface Entry { + type: number; + mtime: number; + size: number; + path: string; + contents: ReadableStream; +} + + +export interface NassunOpts { + registry?: string; + scopedRegistries?: Map; +} + +/** +*/ +export class IntoUnderlyingByteSource { + free(): void; +/** +* @param {any} controller +*/ + start(controller: any): void; +/** +* @param {any} controller +* @returns {Promise} +*/ + pull(controller: any): Promise; +/** +*/ + cancel(): void; +/** +*/ + readonly autoAllocateChunkSize: number; +/** +*/ + readonly type: any; +} +/** +*/ +export class IntoUnderlyingSink { + free(): void; +/** +* @param {any} chunk +* @returns {Promise} +*/ + write(chunk: any): Promise; +/** +* @returns {Promise} +*/ + close(): Promise; +/** +* @param {any} reason +* @returns {Promise} +*/ + abort(reason: any): Promise; +} +/** +*/ +export class IntoUnderlyingSource { + free(): void; +/** +* @param {any} controller +* @returns {Promise} +*/ + pull(controller: any): Promise; +/** +*/ + cancel(): void; +} +/** +* NPM package client used to resolve and fetch package data and metadata. +*/ +export class Nassun { + free(): void; +/** +* Create a new Nassun instance with the given options. +* @param {any} opts +*/ + constructor(opts: any); +/** +* Resolve a spec (e.g. `foo@^1.2.3`, `github:foo/bar`, etc), to a +* `Package` that can be used for further operations. +* @param {string} spec +* @returns {Promise} +*/ + resolve(spec: string): Promise; +/** +* Resolves a packument object for the given package `spec`. +* @param {string} spec +* @returns {Promise} +*/ + packument(spec: string): Promise; +/** +* Resolves version metadata from the given package `spec`. +* @param {string} spec +* @returns {Promise} +*/ + metadata(spec: string): Promise; +/** +* Resolves a partial (corgi) version of the packument object for the +* given package `spec`. +* @param {string} spec +* @returns {Promise} +*/ + corgiPackument(spec: string): Promise; +/** +* Resolves a partial (corgi) version of the version metadata from the +* given package `spec`. +* @param {string} spec +* @returns {Promise} +*/ + corgiMetadata(spec: string): Promise; +/** +* Resolves a `ReadableStream` tarball from the given package +* `spec`. This tarball will have its data checked if the package +* metadata fetched includes integrity information. +* @param {string} spec +* @returns {Promise} +*/ + tarball(spec: string): Promise; +/** +* Resolves to a `ReadableStream` of entries from the given package +* `spec`, using the default resolution algorithm. The source tarball will +* have its data checked if the package metadata fetched includes integrity +* information. +* @param {string} spec +* @returns {Promise} +*/ + entries(spec: string): Promise; +} +/** +* An NPM-compatible dependency resolver. NodeMaintainer builds trees of +* package nodes that can be used to generate lockfiles or fetch package +* tarballs, or even extract them to where they would live in `node_modules`. +*/ +export class NodeMaintainer { + free(): void; +/** +* Resolves a dependency tree using `spec` as the root package. +* @param {string} spec +* @param {any} opts +* @returns {Promise} +*/ + static resolveSpec(spec: string, opts: any): Promise; +/** +* Returns a dependency tree using a `package.json` manifest as the root +* package. +* @param {PackageJson} manifest +* @param {any} opts +* @returns {Promise} +*/ + static resolveManifest(manifest: PackageJson, opts: any): Promise; +/** +* Returns the contents of a package-lock.kdl lockfile for this resolved tree. +* @returns {string} +*/ + toKdl(): string; +/** +* Given a path within node_modules, returns the package that the +* referenced file/directory belongs to. +* @param {string} path +* @returns {Package | undefined} +*/ + packageAtPath(path: string): Package | undefined; +/** +* Concurrently over all packages in the tree, calling `f` on each. +* @param {Function} f +* @returns {Promise} +*/ + forEachPackage(f: Function): Promise; +} +/** +* Options for configuration for various `NodeMaintainer` operations. +*/ +export class NodeMaintainerOptions { + free(): void; +} +/** +* A resolved package. A concrete version has been determined from its +* PackageSpec by the version resolver. +*/ +export class Package { + free(): void; +/** +* The partial (corgi) version of the packument that this `Package` was +* resolved from. +* @returns {Promise} +*/ + corgiPackument(): Promise; +/** +* The partial (corgi) version of the version metadata, aka roughly the +* metadata defined in `package.json`. +* @returns {Promise} +*/ + corgiMetadata(): Promise; +/** +* The full packument that this `Package` was resolved from. +* @returns {Promise} +*/ + packument(): Promise; +/** +* The version metadata, aka roughly the metadata defined in +* `package.json`. +* @returns {Promise} +*/ + metadata(): Promise; +/** +* A `ReadableStream` tarball for this package. This tarball +* will have its data checked if the package metadata fetched includes +* integrity information. +* @returns {Promise} +*/ + tarball(): Promise; +/** +* A `ReadableStream` of entries for this package. The source +* tarball will have its data checked if the package metadata fetched +* includes integrity information. +* @returns {Promise} +*/ + entries(): Promise; +/** +* Original package spec that this `Package` was resolved from. +*/ + readonly from: any; +/** +* Name of the package, as it should be used in the dependency graph. +*/ + readonly name: any; +/** +* The package resolution information that this `Package` was created from. +*/ + readonly resolved: any; +} +/** +* Raw options for [`pipeTo()`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream/pipeTo). +*/ +export class PipeOptions { + free(): void; +/** +*/ + readonly preventAbort: boolean; +/** +*/ + readonly preventCancel: boolean; +/** +*/ + readonly preventClose: boolean; +/** +*/ + readonly signal: AbortSignal | undefined; +} +/** +*/ +export class QueuingStrategy { + free(): void; +/** +*/ + readonly highWaterMark: number; +} +/** +* Raw options for [`getReader()`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream/getReader). +*/ +export class ReadableStreamGetReaderOptions { + free(): void; +/** +*/ + readonly mode: any; +} + +export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module; + +export interface InitOutput { + readonly memory: WebAssembly.Memory; + readonly __wbg_nodemaintaineroptions_free: (a: number) => void; + readonly __wbg_nodemaintainer_free: (a: number) => void; + readonly nodemaintainer_resolveSpec: (a: number, b: number, c: number) => number; + readonly nodemaintainer_resolveManifest: (a: number, b: number) => number; + readonly nodemaintainer_toKdl: (a: number, b: number) => void; + readonly nodemaintainer_packageAtPath: (a: number, b: number, c: number) => number; + readonly nodemaintainer_forEachPackage: (a: number, b: number) => number; + readonly resolveSpec: (a: number, b: number, c: number) => number; + readonly resolveManifest: (a: number, b: number) => number; + readonly packument: (a: number, b: number, c: number) => number; + readonly corgiPackument: (a: number, b: number, c: number) => number; + readonly metadata: (a: number, b: number, c: number) => number; + readonly corgiMetadata: (a: number, b: number, c: number) => number; + readonly tarball: (a: number, b: number, c: number) => number; + readonly entries: (a: number, b: number, c: number) => number; + readonly __wbg_nassun_free: (a: number) => void; + readonly nassun_new: (a: number, b: number) => void; + readonly nassun_resolve: (a: number, b: number, c: number) => number; + readonly nassun_packument: (a: number, b: number, c: number) => number; + readonly nassun_metadata: (a: number, b: number, c: number) => number; + readonly nassun_corgiPackument: (a: number, b: number, c: number) => number; + readonly nassun_corgiMetadata: (a: number, b: number, c: number) => number; + readonly nassun_tarball: (a: number, b: number, c: number) => number; + readonly nassun_entries: (a: number, b: number, c: number) => number; + readonly __wbg_package_free: (a: number) => void; + readonly package_from: (a: number) => number; + readonly package_name: (a: number) => number; + readonly package_resolved: (a: number) => number; + readonly package_corgiPackument: (a: number) => number; + readonly package_corgiMetadata: (a: number) => number; + readonly package_packument: (a: number) => number; + readonly package_metadata: (a: number) => number; + readonly package_tarball: (a: number) => number; + readonly package_entries: (a: number) => number; + readonly __wbg_readablestreamgetreaderoptions_free: (a: number) => void; + readonly readablestreamgetreaderoptions_mode: (a: number) => number; + readonly __wbg_pipeoptions_free: (a: number) => void; + readonly pipeoptions_preventClose: (a: number) => number; + readonly pipeoptions_preventCancel: (a: number) => number; + readonly pipeoptions_preventAbort: (a: number) => number; + readonly pipeoptions_signal: (a: number) => number; + readonly __wbg_queuingstrategy_free: (a: number) => void; + readonly queuingstrategy_highWaterMark: (a: number) => number; + readonly __wbg_intounderlyingsource_free: (a: number) => void; + readonly intounderlyingsource_pull: (a: number, b: number) => number; + readonly intounderlyingsource_cancel: (a: number) => void; + readonly __wbg_intounderlyingsink_free: (a: number) => void; + readonly intounderlyingsink_write: (a: number, b: number) => number; + readonly intounderlyingsink_close: (a: number) => number; + readonly intounderlyingsink_abort: (a: number, b: number) => number; + readonly __wbg_intounderlyingbytesource_free: (a: number) => void; + readonly intounderlyingbytesource_type: (a: number) => number; + readonly intounderlyingbytesource_autoAllocateChunkSize: (a: number) => number; + readonly intounderlyingbytesource_start: (a: number, b: number) => void; + readonly intounderlyingbytesource_pull: (a: number, b: number) => number; + readonly intounderlyingbytesource_cancel: (a: number) => void; + readonly __wbindgen_export_0: (a: number) => number; + readonly __wbindgen_export_1: (a: number, b: number, c: number) => number; + readonly __wbindgen_export_2: WebAssembly.Table; + readonly __wbindgen_export_3: (a: number, b: number, c: number) => void; + readonly __wbindgen_export_4: (a: number, b: number, c: number) => void; + readonly __wbindgen_add_to_stack_pointer: (a: number) => number; + readonly __wbindgen_export_5: (a: number, b: number) => void; + readonly __wbindgen_export_6: (a: number) => void; + readonly __wbindgen_export_7: (a: number, b: number, c: number, d: number) => void; +} + +export type SyncInitInput = BufferSource | WebAssembly.Module; +/** +* Instantiates the given `module`, which can either be bytes or +* a precompiled `WebAssembly.Module`. +* +* @param {SyncInitInput} module +* +* @returns {InitOutput} +*/ +export function initSync(module: SyncInitInput): InitOutput; + +/** +* If `module_or_path` is {RequestInfo} or {URL}, makes a request and +* for everything else, calls `WebAssembly.instantiate` directly. +* +* @param {InitInput | Promise} module_or_path +* +* @returns {Promise} +*/ +export default function init (module_or_path?: InitInput | Promise): Promise; diff --git a/extensions/typescript-language-features/package-manager/node-maintainer/node_maintainer.js b/extensions/typescript-language-features/package-manager/node-maintainer/node_maintainer.js new file mode 100644 index 0000000000000..029d97f44d336 --- /dev/null +++ b/extensions/typescript-language-features/package-manager/node-maintainer/node_maintainer.js @@ -0,0 +1,1527 @@ +import { bytes_literal } from './snippets/wasm-streams-42e57edbcd526312/inline0.js'; + +let wasm; + +const heap = new Array(128).fill(undefined); + +heap.push(undefined, null, true, false); + +function getObject(idx) { return heap[idx]; } + +let heap_next = heap.length; + +function dropObject(idx) { + if (idx < 132) return; + heap[idx] = heap_next; + heap_next = idx; +} + +function takeObject(idx) { + const ret = getObject(idx); + dropObject(idx); + return ret; +} + +const cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }); + +cachedTextDecoder.decode(); + +let cachedUint8Memory0 = null; + +function getUint8Memory0() { + if (cachedUint8Memory0 === null || cachedUint8Memory0.byteLength === 0) { + cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer); + } + return cachedUint8Memory0; +} + +function getStringFromWasm0(ptr, len) { + return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len)); +} + +function addHeapObject(obj) { + if (heap_next === heap.length) heap.push(heap.length + 1); + const idx = heap_next; + heap_next = heap[idx]; + + heap[idx] = obj; + return idx; +} + +let WASM_VECTOR_LEN = 0; + +const cachedTextEncoder = new TextEncoder('utf-8'); + +const encodeString = (typeof cachedTextEncoder.encodeInto === 'function' + ? function (arg, view) { + return cachedTextEncoder.encodeInto(arg, view); +} + : function (arg, view) { + const buf = cachedTextEncoder.encode(arg); + view.set(buf); + return { + read: arg.length, + written: buf.length + }; +}); + +function passStringToWasm0(arg, malloc, realloc) { + + if (realloc === undefined) { + const buf = cachedTextEncoder.encode(arg); + const ptr = malloc(buf.length); + getUint8Memory0().subarray(ptr, ptr + buf.length).set(buf); + WASM_VECTOR_LEN = buf.length; + return ptr; + } + + let len = arg.length; + let ptr = malloc(len); + + const mem = getUint8Memory0(); + + let offset = 0; + + for (; offset < len; offset++) { + const code = arg.charCodeAt(offset); + if (code > 0x7F) break; + mem[ptr + offset] = code; + } + + if (offset !== len) { + if (offset !== 0) { + arg = arg.slice(offset); + } + ptr = realloc(ptr, len, len = offset + arg.length * 3); + const view = getUint8Memory0().subarray(ptr + offset, ptr + len); + const ret = encodeString(arg, view); + + offset += ret.written; + } + + WASM_VECTOR_LEN = offset; + return ptr; +} + +function isLikeNone(x) { + return x === undefined || x === null; +} + +let cachedInt32Memory0 = null; + +function getInt32Memory0() { + if (cachedInt32Memory0 === null || cachedInt32Memory0.byteLength === 0) { + cachedInt32Memory0 = new Int32Array(wasm.memory.buffer); + } + return cachedInt32Memory0; +} + +let cachedFloat64Memory0 = null; + +function getFloat64Memory0() { + if (cachedFloat64Memory0 === null || cachedFloat64Memory0.byteLength === 0) { + cachedFloat64Memory0 = new Float64Array(wasm.memory.buffer); + } + return cachedFloat64Memory0; +} + +let cachedBigInt64Memory0 = null; + +function getBigInt64Memory0() { + if (cachedBigInt64Memory0 === null || cachedBigInt64Memory0.byteLength === 0) { + cachedBigInt64Memory0 = new BigInt64Array(wasm.memory.buffer); + } + return cachedBigInt64Memory0; +} + +function debugString(val) { + // primitive types + const type = typeof val; + if (type == 'number' || type == 'boolean' || val == null) { + return `${val}`; + } + if (type == 'string') { + return `"${val}"`; + } + if (type == 'symbol') { + const description = val.description; + if (description == null) { + return 'Symbol'; + } else { + return `Symbol(${description})`; + } + } + if (type == 'function') { + const name = val.name; + if (typeof name == 'string' && name.length > 0) { + return `Function(${name})`; + } else { + return 'Function'; + } + } + // objects + if (Array.isArray(val)) { + const length = val.length; + let debug = '['; + if (length > 0) { + debug += debugString(val[0]); + } + for(let i = 1; i < length; i++) { + debug += ', ' + debugString(val[i]); + } + debug += ']'; + return debug; + } + // Test for built-in + const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val)); + let className; + if (builtInMatches.length > 1) { + className = builtInMatches[1]; + } else { + // Failed to match the standard '[object ClassName]' + return toString.call(val); + } + if (className == 'Object') { + // we're a user defined class or Object + // JSON.stringify avoids problems with cycles, and is generally much + // easier than looping through ownProperties of `val`. + try { + return 'Object(' + JSON.stringify(val) + ')'; + } catch (_) { + return 'Object'; + } + } + // errors + if (val instanceof Error) { + return `${val.name}: ${val.message}\n${val.stack}`; + } + // TODO we could test for more things here, like `Set`s and `Map`s. + return className; +} + +function makeMutClosure(arg0, arg1, dtor, f) { + const state = { a: arg0, b: arg1, cnt: 1, dtor }; + const real = (...args) => { + // First up with a closure we increment the internal reference + // count. This ensures that the Rust closure environment won't + // be deallocated while we're invoking it. + state.cnt++; + const a = state.a; + state.a = 0; + try { + return f(a, state.b, ...args); + } finally { + if (--state.cnt === 0) { + wasm.__wbindgen_export_2.get(state.dtor)(a, state.b); + + } else { + state.a = a; + } + } + }; + real.original = state; + + return real; +} +function __wbg_adapter_50(arg0, arg1, arg2) { + wasm.__wbindgen_export_3(arg0, arg1, addHeapObject(arg2)); +} + +function __wbg_adapter_53(arg0, arg1, arg2) { + wasm.__wbindgen_export_4(arg0, arg1, addHeapObject(arg2)); +} + +/** +* Resolves a dependency tree using `spec` as the root package. +* @param {string} spec +* @param {any} opts +* @returns {Promise} +*/ +export function resolveSpec(spec, opts) { + const ptr0 = passStringToWasm0(spec, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.resolveSpec(ptr0, len0, addHeapObject(opts)); + return takeObject(ret); +} + +/** +* Returns a dependency tree using a `package.json` manifest as the root +* package. +* @param {PackageJson} manifest +* @param {any} opts +* @returns {Promise} +*/ +export function resolveManifest(manifest, opts) { + const ret = wasm.resolveManifest(addHeapObject(manifest), addHeapObject(opts)); + return takeObject(ret); +} + +/** +* Resolves a `Packument` for the given package `spec`. +* +* This uses default `Nassun` options and does not cache the result. +* To configure `Nassun`, and/or enable more efficient caching/reuse, +* look at `Package#packument` instead. +* @param {string} spec +* @param {any} opts +* @returns {Promise} +*/ +export function packument(spec, opts) { + const ptr0 = passStringToWasm0(spec, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.packument(ptr0, len0, addHeapObject(opts)); + return takeObject(ret); +} + +/** +* Resolves a partial ("corgi") version of the `Packument` for the given +* package `spec`. +* +* This uses default `Nassun` options and does not cache the result. +* To configure `Nassun`, and/or enable more efficient caching/reuse, +* look at `Package#packument` instead. +* @param {string} spec +* @param {any} opts +* @returns {Promise} +*/ +export function corgiPackument(spec, opts) { + const ptr0 = passStringToWasm0(spec, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.corgiPackument(ptr0, len0, addHeapObject(opts)); + return takeObject(ret); +} + +/** +* Resolves version metadata from the given package `spec`, using the default +* resolution algorithm. +* +* This uses default `Nassun` options and does not cache the result. To +* configure `Nassun`, and/or enable more efficient caching/reuse, look at +* `Package#metadata` instead. +* @param {string} spec +* @param {any} opts +* @returns {Promise} +*/ +export function metadata(spec, opts) { + const ptr0 = passStringToWasm0(spec, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.metadata(ptr0, len0, addHeapObject(opts)); + return takeObject(ret); +} + +/** +* Resolves a partial ("corgi") version of the version metadata from the +* given package `spec`, using the default resolution algorithm. +* +* This uses default `Nassun` settings and does not cache the result. To +* configure `Nassun`, and/or enable more efficient caching/reuse, look at +* `Package#metadata` instead. +* @param {string} spec +* @param {any} opts +* @returns {Promise} +*/ +export function corgiMetadata(spec, opts) { + const ptr0 = passStringToWasm0(spec, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.corgiMetadata(ptr0, len0, addHeapObject(opts)); + return takeObject(ret); +} + +/** +* Resolves a tarball from the given package `spec`, using the +* default resolution algorithm. This tarball will have its data checked +* if the package metadata fetched includes integrity information. +* +* This uses default `Nassun` settings and does not cache the result. +* To configure `Nassun`, and/or enable more efficient caching/reuse, +* look at `Package#tarball` instead. +* @param {string} spec +* @param {any} opts +* @returns {Promise} +*/ +export function tarball(spec, opts) { + const ptr0 = passStringToWasm0(spec, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.tarball(ptr0, len0, addHeapObject(opts)); + return takeObject(ret); +} + +/** +* Resolves to a `ReadableStream` of entries from the given package +* `spec`, using the default resolution algorithm. The source tarball will +* have its data checked if the package metadata fetched includes integrity +* information. +* +* This uses default `Nassun` settings and does not cache the result. To +* configure `Nassun`, and/or enable more efficient caching/reuse, look at +* `Package#entries` instead. +* @param {string} spec +* @param {any} opts +* @returns {Promise} +*/ +export function entries(spec, opts) { + const ptr0 = passStringToWasm0(spec, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.entries(ptr0, len0, addHeapObject(opts)); + return takeObject(ret); +} + +function handleError(f, args) { + try { + return f.apply(this, args); + } catch (e) { + wasm.__wbindgen_export_6(addHeapObject(e)); + } +} +function __wbg_adapter_224(arg0, arg1, arg2, arg3) { + wasm.__wbindgen_export_7(arg0, arg1, addHeapObject(arg2), addHeapObject(arg3)); +} + +/** +*/ +export class IntoUnderlyingByteSource { + + static __wrap(ptr) { + const obj = Object.create(IntoUnderlyingByteSource.prototype); + obj.ptr = ptr; + + return obj; + } + + __destroy_into_raw() { + const ptr = this.ptr; + this.ptr = 0; + + return ptr; + } + + free() { + const ptr = this.__destroy_into_raw(); + wasm.__wbg_intounderlyingbytesource_free(ptr); + } + /** + * @returns {any} + */ + get type() { + const ret = wasm.intounderlyingbytesource_type(this.ptr); + return takeObject(ret); + } + /** + * @returns {number} + */ + get autoAllocateChunkSize() { + const ret = wasm.intounderlyingbytesource_autoAllocateChunkSize(this.ptr); + return ret >>> 0; + } + /** + * @param {any} controller + */ + start(controller) { + wasm.intounderlyingbytesource_start(this.ptr, addHeapObject(controller)); + } + /** + * @param {any} controller + * @returns {Promise} + */ + pull(controller) { + const ret = wasm.intounderlyingbytesource_pull(this.ptr, addHeapObject(controller)); + return takeObject(ret); + } + /** + */ + cancel() { + const ptr = this.__destroy_into_raw(); + wasm.intounderlyingbytesource_cancel(ptr); + } +} +/** +*/ +export class IntoUnderlyingSink { + + __destroy_into_raw() { + const ptr = this.ptr; + this.ptr = 0; + + return ptr; + } + + free() { + const ptr = this.__destroy_into_raw(); + wasm.__wbg_intounderlyingsink_free(ptr); + } + /** + * @param {any} chunk + * @returns {Promise} + */ + write(chunk) { + const ret = wasm.intounderlyingsink_write(this.ptr, addHeapObject(chunk)); + return takeObject(ret); + } + /** + * @returns {Promise} + */ + close() { + const ptr = this.__destroy_into_raw(); + const ret = wasm.intounderlyingsink_close(ptr); + return takeObject(ret); + } + /** + * @param {any} reason + * @returns {Promise} + */ + abort(reason) { + const ptr = this.__destroy_into_raw(); + const ret = wasm.intounderlyingsink_abort(ptr, addHeapObject(reason)); + return takeObject(ret); + } +} +/** +*/ +export class IntoUnderlyingSource { + + static __wrap(ptr) { + const obj = Object.create(IntoUnderlyingSource.prototype); + obj.ptr = ptr; + + return obj; + } + + __destroy_into_raw() { + const ptr = this.ptr; + this.ptr = 0; + + return ptr; + } + + free() { + const ptr = this.__destroy_into_raw(); + wasm.__wbg_intounderlyingsource_free(ptr); + } + /** + * @param {any} controller + * @returns {Promise} + */ + pull(controller) { + const ret = wasm.intounderlyingsource_pull(this.ptr, addHeapObject(controller)); + return takeObject(ret); + } + /** + */ + cancel() { + const ptr = this.__destroy_into_raw(); + wasm.intounderlyingsource_cancel(ptr); + } +} +/** +* NPM package client used to resolve and fetch package data and metadata. +*/ +export class Nassun { + + static __wrap(ptr) { + const obj = Object.create(Nassun.prototype); + obj.ptr = ptr; + + return obj; + } + + __destroy_into_raw() { + const ptr = this.ptr; + this.ptr = 0; + + return ptr; + } + + free() { + const ptr = this.__destroy_into_raw(); + wasm.__wbg_nassun_free(ptr); + } + /** + * Create a new Nassun instance with the given options. + * @param {any} opts + */ + constructor(opts) { + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + wasm.nassun_new(retptr, addHeapObject(opts)); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + var r2 = getInt32Memory0()[retptr / 4 + 2]; + if (r2) { + throw takeObject(r1); + } + return Nassun.__wrap(r0); + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + } + } + /** + * Resolve a spec (e.g. `foo@^1.2.3`, `github:foo/bar`, etc), to a + * `Package` that can be used for further operations. + * @param {string} spec + * @returns {Promise} + */ + resolve(spec) { + const ptr0 = passStringToWasm0(spec, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.nassun_resolve(this.ptr, ptr0, len0); + return takeObject(ret); + } + /** + * Resolves a packument object for the given package `spec`. + * @param {string} spec + * @returns {Promise} + */ + packument(spec) { + const ptr0 = passStringToWasm0(spec, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.nassun_packument(this.ptr, ptr0, len0); + return takeObject(ret); + } + /** + * Resolves version metadata from the given package `spec`. + * @param {string} spec + * @returns {Promise} + */ + metadata(spec) { + const ptr0 = passStringToWasm0(spec, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.nassun_metadata(this.ptr, ptr0, len0); + return takeObject(ret); + } + /** + * Resolves a partial (corgi) version of the packument object for the + * given package `spec`. + * @param {string} spec + * @returns {Promise} + */ + corgiPackument(spec) { + const ptr0 = passStringToWasm0(spec, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.nassun_corgiPackument(this.ptr, ptr0, len0); + return takeObject(ret); + } + /** + * Resolves a partial (corgi) version of the version metadata from the + * given package `spec`. + * @param {string} spec + * @returns {Promise} + */ + corgiMetadata(spec) { + const ptr0 = passStringToWasm0(spec, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.nassun_corgiMetadata(this.ptr, ptr0, len0); + return takeObject(ret); + } + /** + * Resolves a `ReadableStream` tarball from the given package + * `spec`. This tarball will have its data checked if the package + * metadata fetched includes integrity information. + * @param {string} spec + * @returns {Promise} + */ + tarball(spec) { + const ptr0 = passStringToWasm0(spec, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.nassun_tarball(this.ptr, ptr0, len0); + return takeObject(ret); + } + /** + * Resolves to a `ReadableStream` of entries from the given package + * `spec`, using the default resolution algorithm. The source tarball will + * have its data checked if the package metadata fetched includes integrity + * information. + * @param {string} spec + * @returns {Promise} + */ + entries(spec) { + const ptr0 = passStringToWasm0(spec, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.nassun_entries(this.ptr, ptr0, len0); + return takeObject(ret); + } +} +/** +* An NPM-compatible dependency resolver. NodeMaintainer builds trees of +* package nodes that can be used to generate lockfiles or fetch package +* tarballs, or even extract them to where they would live in `node_modules`. +*/ +export class NodeMaintainer { + + static __wrap(ptr) { + const obj = Object.create(NodeMaintainer.prototype); + obj.ptr = ptr; + + return obj; + } + + __destroy_into_raw() { + const ptr = this.ptr; + this.ptr = 0; + + return ptr; + } + + free() { + const ptr = this.__destroy_into_raw(); + wasm.__wbg_nodemaintainer_free(ptr); + } + /** + * Resolves a dependency tree using `spec` as the root package. + * @param {string} spec + * @param {any} opts + * @returns {Promise} + */ + static resolveSpec(spec, opts) { + const ptr0 = passStringToWasm0(spec, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.nodemaintainer_resolveSpec(ptr0, len0, addHeapObject(opts)); + return takeObject(ret); + } + /** + * Returns a dependency tree using a `package.json` manifest as the root + * package. + * @param {PackageJson} manifest + * @param {any} opts + * @returns {Promise} + */ + static resolveManifest(manifest, opts) { + const ret = wasm.nodemaintainer_resolveManifest(addHeapObject(manifest), addHeapObject(opts)); + return takeObject(ret); + } + /** + * Returns the contents of a package-lock.kdl lockfile for this resolved tree. + * @returns {string} + */ + toKdl() { + try { + const retptr = wasm.__wbindgen_add_to_stack_pointer(-16); + wasm.nodemaintainer_toKdl(retptr, this.ptr); + var r0 = getInt32Memory0()[retptr / 4 + 0]; + var r1 = getInt32Memory0()[retptr / 4 + 1]; + var r2 = getInt32Memory0()[retptr / 4 + 2]; + var r3 = getInt32Memory0()[retptr / 4 + 3]; + var ptr0 = r0; + var len0 = r1; + if (r3) { + ptr0 = 0; len0 = 0; + throw takeObject(r2); + } + return getStringFromWasm0(ptr0, len0); + } finally { + wasm.__wbindgen_add_to_stack_pointer(16); + wasm.__wbindgen_export_5(ptr0, len0); + } + } + /** + * Given a path within node_modules, returns the package that the + * referenced file/directory belongs to. + * @param {string} path + * @returns {Package | undefined} + */ + packageAtPath(path) { + const ptr0 = passStringToWasm0(path, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1); + const len0 = WASM_VECTOR_LEN; + const ret = wasm.nodemaintainer_packageAtPath(this.ptr, ptr0, len0); + return ret === 0 ? undefined : Package.__wrap(ret); + } + /** + * Concurrently over all packages in the tree, calling `f` on each. + * @param {Function} f + * @returns {Promise} + */ + forEachPackage(f) { + const ret = wasm.nodemaintainer_forEachPackage(this.ptr, addHeapObject(f)); + return takeObject(ret); + } +} +/** +* Options for configuration for various `NodeMaintainer` operations. +*/ +export class NodeMaintainerOptions { + + __destroy_into_raw() { + const ptr = this.ptr; + this.ptr = 0; + + return ptr; + } + + free() { + const ptr = this.__destroy_into_raw(); + wasm.__wbg_nodemaintaineroptions_free(ptr); + } +} +/** +* A resolved package. A concrete version has been determined from its +* PackageSpec by the version resolver. +*/ +export class Package { + + static __wrap(ptr) { + const obj = Object.create(Package.prototype); + obj.ptr = ptr; + + return obj; + } + + __destroy_into_raw() { + const ptr = this.ptr; + this.ptr = 0; + + return ptr; + } + + free() { + const ptr = this.__destroy_into_raw(); + wasm.__wbg_package_free(ptr); + } + /** + * Original package spec that this `Package` was resolved from. + * @returns {any} + */ + get from() { + const ret = wasm.package_from(this.ptr); + return takeObject(ret); + } + /** + * Name of the package, as it should be used in the dependency graph. + * @returns {any} + */ + get name() { + const ret = wasm.package_name(this.ptr); + return takeObject(ret); + } + /** + * The package resolution information that this `Package` was created from. + * @returns {any} + */ + get resolved() { + const ret = wasm.package_resolved(this.ptr); + return takeObject(ret); + } + /** + * The partial (corgi) version of the packument that this `Package` was + * resolved from. + * @returns {Promise} + */ + corgiPackument() { + const ret = wasm.package_corgiPackument(this.ptr); + return takeObject(ret); + } + /** + * The partial (corgi) version of the version metadata, aka roughly the + * metadata defined in `package.json`. + * @returns {Promise} + */ + corgiMetadata() { + const ret = wasm.package_corgiMetadata(this.ptr); + return takeObject(ret); + } + /** + * The full packument that this `Package` was resolved from. + * @returns {Promise} + */ + packument() { + const ret = wasm.package_packument(this.ptr); + return takeObject(ret); + } + /** + * The version metadata, aka roughly the metadata defined in + * `package.json`. + * @returns {Promise} + */ + metadata() { + const ret = wasm.package_metadata(this.ptr); + return takeObject(ret); + } + /** + * A `ReadableStream` tarball for this package. This tarball + * will have its data checked if the package metadata fetched includes + * integrity information. + * @returns {Promise} + */ + tarball() { + const ret = wasm.package_tarball(this.ptr); + return takeObject(ret); + } + /** + * A `ReadableStream` of entries for this package. The source + * tarball will have its data checked if the package metadata fetched + * includes integrity information. + * @returns {Promise} + */ + entries() { + const ret = wasm.package_entries(this.ptr); + return takeObject(ret); + } +} +/** +* Raw options for [`pipeTo()`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream/pipeTo). +*/ +export class PipeOptions { + + __destroy_into_raw() { + const ptr = this.ptr; + this.ptr = 0; + + return ptr; + } + + free() { + const ptr = this.__destroy_into_raw(); + wasm.__wbg_pipeoptions_free(ptr); + } + /** + * @returns {boolean} + */ + get preventClose() { + const ret = wasm.pipeoptions_preventClose(this.ptr); + return ret !== 0; + } + /** + * @returns {boolean} + */ + get preventCancel() { + const ret = wasm.pipeoptions_preventCancel(this.ptr); + return ret !== 0; + } + /** + * @returns {boolean} + */ + get preventAbort() { + const ret = wasm.pipeoptions_preventAbort(this.ptr); + return ret !== 0; + } + /** + * @returns {AbortSignal | undefined} + */ + get signal() { + const ret = wasm.pipeoptions_signal(this.ptr); + return takeObject(ret); + } +} +/** +*/ +export class QueuingStrategy { + + static __wrap(ptr) { + const obj = Object.create(QueuingStrategy.prototype); + obj.ptr = ptr; + + return obj; + } + + __destroy_into_raw() { + const ptr = this.ptr; + this.ptr = 0; + + return ptr; + } + + free() { + const ptr = this.__destroy_into_raw(); + wasm.__wbg_queuingstrategy_free(ptr); + } + /** + * @returns {number} + */ + get highWaterMark() { + const ret = wasm.queuingstrategy_highWaterMark(this.ptr); + return ret; + } +} +/** +* Raw options for [`getReader()`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream/getReader). +*/ +export class ReadableStreamGetReaderOptions { + + __destroy_into_raw() { + const ptr = this.ptr; + this.ptr = 0; + + return ptr; + } + + free() { + const ptr = this.__destroy_into_raw(); + wasm.__wbg_readablestreamgetreaderoptions_free(ptr); + } + /** + * @returns {any} + */ + get mode() { + const ret = wasm.readablestreamgetreaderoptions_mode(this.ptr); + return takeObject(ret); + } +} + +async function load(module, imports) { + if (typeof Response === 'function' && module instanceof Response) { + if (typeof WebAssembly.instantiateStreaming === 'function') { + try { + return await WebAssembly.instantiateStreaming(module, imports); + + } catch (e) { + if (module.headers.get('Content-Type') != 'application/wasm') { + console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e); + + } else { + throw e; + } + } + } + + const bytes = await module.arrayBuffer(); + return await WebAssembly.instantiate(bytes, imports); + + } else { + const instance = await WebAssembly.instantiate(module, imports); + + if (instance instanceof WebAssembly.Instance) { + return { instance, module }; + + } else { + return instance; + } + } +} + +function getImports() { + const imports = {}; + imports.wbg = {}; + imports.wbg.__wbindgen_object_drop_ref = function(arg0) { + takeObject(arg0); + }; + imports.wbg.__wbindgen_string_new = function(arg0, arg1) { + const ret = getStringFromWasm0(arg0, arg1); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_string_get = function(arg0, arg1) { + const obj = getObject(arg1); + const ret = typeof(obj) === 'string' ? obj : undefined; + var ptr0 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1); + var len0 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len0; + getInt32Memory0()[arg0 / 4 + 0] = ptr0; + }; + imports.wbg.__wbg_nodemaintainer_new = function(arg0) { + const ret = NodeMaintainer.__wrap(arg0); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_is_bigint = function(arg0) { + const ret = typeof(getObject(arg0)) === 'bigint'; + return ret; + }; + imports.wbg.__wbindgen_bigint_from_u64 = function(arg0) { + const ret = BigInt.asUintN(64, arg0); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_jsval_eq = function(arg0, arg1) { + const ret = getObject(arg0) === getObject(arg1); + return ret; + }; + imports.wbg.__wbindgen_is_object = function(arg0) { + const val = getObject(arg0); + const ret = typeof(val) === 'object' && val !== null; + return ret; + }; + imports.wbg.__wbindgen_is_undefined = function(arg0) { + const ret = getObject(arg0) === undefined; + return ret; + }; + imports.wbg.__wbindgen_in = function(arg0, arg1) { + const ret = getObject(arg0) in getObject(arg1); + return ret; + }; + imports.wbg.__wbindgen_cb_drop = function(arg0) { + const obj = takeObject(arg0).original; + if (obj.cnt-- == 1) { + obj.a = 0; + return true; + } + const ret = false; + return ret; + }; + imports.wbg.__wbindgen_error_new = function(arg0, arg1) { + const ret = new Error(getStringFromWasm0(arg0, arg1)); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_number_new = function(arg0) { + const ret = arg0; + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_is_string = function(arg0) { + const ret = typeof(getObject(arg0)) === 'string'; + return ret; + }; + imports.wbg.__wbg_package_new = function(arg0) { + const ret = Package.__wrap(arg0); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_object_clone_ref = function(arg0) { + const ret = getObject(arg0); + return addHeapObject(ret); + }; + imports.wbg.__wbg_new_abda76e883ba8a5f = function() { + const ret = new Error(); + return addHeapObject(ret); + }; + imports.wbg.__wbg_stack_658279fe44541cf6 = function(arg0, arg1) { + const ret = getObject(arg1).stack; + const ptr0 = passStringToWasm0(ret, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1); + const len0 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len0; + getInt32Memory0()[arg0 / 4 + 0] = ptr0; + }; + imports.wbg.__wbg_error_f851667af71bcfc6 = function(arg0, arg1) { + try { + console.error(getStringFromWasm0(arg0, arg1)); + } finally { + wasm.__wbindgen_export_5(arg0, arg1); + } + }; + imports.wbg.__wbindgen_bigint_from_i64 = function(arg0) { + const ret = arg0; + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_jsval_loose_eq = function(arg0, arg1) { + const ret = getObject(arg0) == getObject(arg1); + return ret; + }; + imports.wbg.__wbindgen_boolean_get = function(arg0) { + const v = getObject(arg0); + const ret = typeof(v) === 'boolean' ? (v ? 1 : 0) : 2; + return ret; + }; + imports.wbg.__wbindgen_number_get = function(arg0, arg1) { + const obj = getObject(arg1); + const ret = typeof(obj) === 'number' ? obj : undefined; + getFloat64Memory0()[arg0 / 8 + 1] = isLikeNone(ret) ? 0 : ret; + getInt32Memory0()[arg0 / 4 + 0] = !isLikeNone(ret); + }; + imports.wbg.__wbg_String_91fba7ded13ba54c = function(arg0, arg1) { + const ret = String(getObject(arg1)); + const ptr0 = passStringToWasm0(ret, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1); + const len0 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len0; + getInt32Memory0()[arg0 / 4 + 0] = ptr0; + }; + imports.wbg.__wbg_getwithrefkey_15c62c2b8546208d = function(arg0, arg1) { + const ret = getObject(arg0)[getObject(arg1)]; + return addHeapObject(ret); + }; + imports.wbg.__wbg_set_20cbc34131e76824 = function(arg0, arg1, arg2) { + getObject(arg0)[takeObject(arg1)] = takeObject(arg2); + }; + imports.wbg.__wbg_fetch_cf75ae0b20981e3e = function(arg0) { + const ret = fetch(getObject(arg0)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_newwithsource_d169ed5262a23b74 = function(arg0, arg1) { + const ret = new ReadableStream(IntoUnderlyingSource.__wrap(arg0), QueuingStrategy.__wrap(arg1)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_newwithbytesource_33937abb6afe07ad = function() { return handleError(function (arg0) { + const ret = new ReadableStream(IntoUnderlyingByteSource.__wrap(arg0)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_getReader_2dcca5fb18e09eed = function() { return handleError(function (arg0) { + const ret = getObject(arg0).getReader(); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_close_a41954830b65c455 = function(arg0) { + getObject(arg0).close(); + }; + imports.wbg.__wbg_enqueue_3a8a8e67e44d2567 = function(arg0, arg1) { + getObject(arg0).enqueue(getObject(arg1)); + }; + imports.wbg.__wbg_byobRequest_a3c74c3694777d1b = function(arg0) { + const ret = getObject(arg0).byobRequest; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_close_045ed342139beb7d = function(arg0) { + getObject(arg0).close(); + }; + imports.wbg.__wbg_view_d1a31268af734e5d = function(arg0) { + const ret = getObject(arg0).view; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_respond_f4778bef04e912a6 = function(arg0, arg1) { + getObject(arg0).respond(arg1 >>> 0); + }; + imports.wbg.__wbg_buffer_610b70c8fd30da2d = function(arg0) { + const ret = getObject(arg0).buffer; + return addHeapObject(ret); + }; + imports.wbg.__wbg_byteOffset_ede786cfcf88d3dd = function(arg0) { + const ret = getObject(arg0).byteOffset; + return ret; + }; + imports.wbg.__wbg_byteLength_1fef7842ca4200fa = function(arg0) { + const ret = getObject(arg0).byteLength; + return ret; + }; + imports.wbg.__wbg_cancel_ec971cf80c0cb93c = function(arg0) { + const ret = getObject(arg0).cancel(); + return addHeapObject(ret); + }; + imports.wbg.__wbg_releaseLock_63a4cb6bda4eb742 = function() { return handleError(function (arg0) { + getObject(arg0).releaseLock(); + }, arguments) }; + imports.wbg.__wbg_read_2ca7e46df6e5a6f6 = function(arg0) { + const ret = getObject(arg0).read(); + return addHeapObject(ret); + }; + imports.wbg.__wbg_done_a0a250be29d69e10 = function(arg0) { + const ret = getObject(arg0).done; + return ret; + }; + imports.wbg.__wbg_value_b71fc239df8382f0 = function(arg0) { + const ret = getObject(arg0).value; + return addHeapObject(ret); + }; + imports.wbg.__wbg_bytesliteral_efe7d360639bf32b = function() { + const ret = bytes_literal(); + return addHeapObject(ret); + }; + imports.wbg.__wbg_newwithstrandinit_c45f0dc6da26fd03 = function() { return handleError(function (arg0, arg1, arg2) { + const ret = new Request(getStringFromWasm0(arg0, arg1), getObject(arg2)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_signal_686bf5a4acff74a1 = function(arg0) { + const ret = getObject(arg0).signal; + return addHeapObject(ret); + }; + imports.wbg.__wbg_new_a16bcd3b8d000a4f = function() { return handleError(function () { + const ret = new AbortController(); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_abort_5f06bf3b2954cf33 = function(arg0) { + getObject(arg0).abort(); + }; + imports.wbg.__wbg_fetch_661ffba2a4f2519c = function(arg0, arg1) { + const ret = getObject(arg0).fetch(getObject(arg1)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_instanceof_Response_fb3a4df648c1859b = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof Response; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_url_8ec2534cdfacb103 = function(arg0, arg1) { + const ret = getObject(arg1).url; + const ptr0 = passStringToWasm0(ret, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1); + const len0 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len0; + getInt32Memory0()[arg0 / 4 + 0] = ptr0; + }; + imports.wbg.__wbg_status_d483a4ac847f380a = function(arg0) { + const ret = getObject(arg0).status; + return ret; + }; + imports.wbg.__wbg_headers_6093927dc359903e = function(arg0) { + const ret = getObject(arg0).headers; + return addHeapObject(ret); + }; + imports.wbg.__wbg_body_aeb10a3b63770556 = function(arg0) { + const ret = getObject(arg0).body; + return isLikeNone(ret) ? 0 : addHeapObject(ret); + }; + imports.wbg.__wbg_text_f61464d781b099f0 = function() { return handleError(function (arg0) { + const ret = getObject(arg0).text(); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_new_f1c3a9c2533a55b8 = function() { return handleError(function () { + const ret = new Headers(); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_append_1be1d651f9ecf2eb = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) { + getObject(arg0).append(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4)); + }, arguments) }; + imports.wbg.__wbg_get_27fe3dac1c4d0224 = function(arg0, arg1) { + const ret = getObject(arg0)[arg1 >>> 0]; + return addHeapObject(ret); + }; + imports.wbg.__wbg_length_e498fbc24f9c1d4f = function(arg0) { + const ret = getObject(arg0).length; + return ret; + }; + imports.wbg.__wbg_new_b525de17f44a8943 = function() { + const ret = new Array(); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_is_function = function(arg0) { + const ret = typeof(getObject(arg0)) === 'function'; + return ret; + }; + imports.wbg.__wbg_newnoargs_2b8b6bd7753c76ba = function(arg0, arg1) { + const ret = new Function(getStringFromWasm0(arg0, arg1)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_new_f841cc6f2098f4b5 = function() { + const ret = new Map(); + return addHeapObject(ret); + }; + imports.wbg.__wbg_next_b7d530c04fd8b217 = function(arg0) { + const ret = getObject(arg0).next; + return addHeapObject(ret); + }; + imports.wbg.__wbg_next_88560ec06a094dea = function() { return handleError(function (arg0) { + const ret = getObject(arg0).next(); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_done_1ebec03bbd919843 = function(arg0) { + const ret = getObject(arg0).done; + return ret; + }; + imports.wbg.__wbg_value_6ac8da5cc5b3efda = function(arg0) { + const ret = getObject(arg0).value; + return addHeapObject(ret); + }; + imports.wbg.__wbg_iterator_55f114446221aa5a = function() { + const ret = Symbol.iterator; + return addHeapObject(ret); + }; + imports.wbg.__wbg_get_baf4855f9a986186 = function() { return handleError(function (arg0, arg1) { + const ret = Reflect.get(getObject(arg0), getObject(arg1)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_call_95d1ea488d03e4e8 = function() { return handleError(function (arg0, arg1) { + const ret = getObject(arg0).call(getObject(arg1)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_new_f9876326328f45ed = function() { + const ret = new Object(); + return addHeapObject(ret); + }; + imports.wbg.__wbg_self_e7c1f827057f6584 = function() { return handleError(function () { + const ret = self.self; + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_window_a09ec664e14b1b81 = function() { return handleError(function () { + const ret = window.window; + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_globalThis_87cbb8506fecf3a9 = function() { return handleError(function () { + const ret = globalThis.globalThis; + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_global_c85a9259e621f3db = function() { return handleError(function () { + const ret = global.global; + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_set_17224bc548dd1d7b = function(arg0, arg1, arg2) { + getObject(arg0)[arg1 >>> 0] = takeObject(arg2); + }; + imports.wbg.__wbg_isArray_39d28997bf6b96b4 = function(arg0) { + const ret = Array.isArray(getObject(arg0)); + return ret; + }; + imports.wbg.__wbg_instanceof_ArrayBuffer_a69f02ee4c4f5065 = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof ArrayBuffer; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_new_15d3966e9981a196 = function(arg0, arg1) { + const ret = new Error(getStringFromWasm0(arg0, arg1)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_call_9495de66fdbe016b = function() { return handleError(function (arg0, arg1, arg2) { + const ret = getObject(arg0).call(getObject(arg1), getObject(arg2)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_call_96878afb7a8201ca = function() { return handleError(function (arg0, arg1, arg2, arg3) { + const ret = getObject(arg0).call(getObject(arg1), getObject(arg2), getObject(arg3)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbg_set_388c4c6422704173 = function(arg0, arg1, arg2) { + const ret = getObject(arg0).set(getObject(arg1), getObject(arg2)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_isSafeInteger_8c4789029e885159 = function(arg0) { + const ret = Number.isSafeInteger(getObject(arg0)); + return ret; + }; + imports.wbg.__wbg_entries_4e1315b774245952 = function(arg0) { + const ret = Object.entries(getObject(arg0)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_instanceof_Promise_4333c4e5587e8936 = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof Promise; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_new_9d3a9ce4282a18a8 = function(arg0, arg1) { + try { + var state0 = {a: arg0, b: arg1}; + var cb0 = (arg0, arg1) => { + const a = state0.a; + state0.a = 0; + try { + return __wbg_adapter_224(a, state0.b, arg0, arg1); + } finally { + state0.a = a; + } + }; + const ret = new Promise(cb0); + return addHeapObject(ret); + } finally { + state0.a = state0.b = 0; + } + }; + imports.wbg.__wbg_resolve_fd40f858d9db1a04 = function(arg0) { + const ret = Promise.resolve(getObject(arg0)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_catch_44bf25c15946bac0 = function(arg0, arg1) { + const ret = getObject(arg0).catch(getObject(arg1)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_then_ec5db6d509eb475f = function(arg0, arg1) { + const ret = getObject(arg0).then(getObject(arg1)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_then_f753623316e2873a = function(arg0, arg1, arg2) { + const ret = getObject(arg0).then(getObject(arg1), getObject(arg2)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_buffer_cf65c07de34b9a08 = function(arg0) { + const ret = getObject(arg0).buffer; + return addHeapObject(ret); + }; + imports.wbg.__wbg_newwithbyteoffsetandlength_9fb2f11355ecadf5 = function(arg0, arg1, arg2) { + const ret = new Uint8Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0); + return addHeapObject(ret); + }; + imports.wbg.__wbg_new_537b7341ce90bb31 = function(arg0) { + const ret = new Uint8Array(getObject(arg0)); + return addHeapObject(ret); + }; + imports.wbg.__wbg_set_17499e8aa4003ebd = function(arg0, arg1, arg2) { + getObject(arg0).set(getObject(arg1), arg2 >>> 0); + }; + imports.wbg.__wbg_length_27a2afe8ab42b09f = function(arg0) { + const ret = getObject(arg0).length; + return ret; + }; + imports.wbg.__wbg_instanceof_Uint8Array_01cebe79ca606cca = function(arg0) { + let result; + try { + result = getObject(arg0) instanceof Uint8Array; + } catch { + result = false; + } + const ret = result; + return ret; + }; + imports.wbg.__wbg_has_3feea89d34bd7ad5 = function() { return handleError(function (arg0, arg1) { + const ret = Reflect.has(getObject(arg0), getObject(arg1)); + return ret; + }, arguments) }; + imports.wbg.__wbg_set_6aa458a4ebdb65cb = function() { return handleError(function (arg0, arg1, arg2) { + const ret = Reflect.set(getObject(arg0), getObject(arg1), getObject(arg2)); + return ret; + }, arguments) }; + imports.wbg.__wbg_stringify_029a979dfb73aa17 = function() { return handleError(function (arg0) { + const ret = JSON.stringify(getObject(arg0)); + return addHeapObject(ret); + }, arguments) }; + imports.wbg.__wbindgen_bigint_get_as_i64 = function(arg0, arg1) { + const v = getObject(arg1); + const ret = typeof(v) === 'bigint' ? v : undefined; + getBigInt64Memory0()[arg0 / 8 + 1] = isLikeNone(ret) ? BigInt(0) : ret; + getInt32Memory0()[arg0 / 4 + 0] = !isLikeNone(ret); + }; + imports.wbg.__wbindgen_debug_string = function(arg0, arg1) { + const ret = debugString(getObject(arg1)); + const ptr0 = passStringToWasm0(ret, wasm.__wbindgen_export_0, wasm.__wbindgen_export_1); + const len0 = WASM_VECTOR_LEN; + getInt32Memory0()[arg0 / 4 + 1] = len0; + getInt32Memory0()[arg0 / 4 + 0] = ptr0; + }; + imports.wbg.__wbindgen_throw = function(arg0, arg1) { + throw new Error(getStringFromWasm0(arg0, arg1)); + }; + imports.wbg.__wbindgen_rethrow = function(arg0) { + throw takeObject(arg0); + }; + imports.wbg.__wbindgen_memory = function() { + const ret = wasm.memory; + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_closure_wrapper2178 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 747, __wbg_adapter_50); + return addHeapObject(ret); + }; + imports.wbg.__wbindgen_closure_wrapper2759 = function(arg0, arg1, arg2) { + const ret = makeMutClosure(arg0, arg1, 967, __wbg_adapter_53); + return addHeapObject(ret); + }; + + return imports; +} + +function initMemory(imports, maybe_memory) { + +} + +function finalizeInit(instance, module) { + wasm = instance.exports; + init.__wbindgen_wasm_module = module; + cachedBigInt64Memory0 = null; + cachedFloat64Memory0 = null; + cachedInt32Memory0 = null; + cachedUint8Memory0 = null; + + + return wasm; +} + +function initSync(module) { + const imports = getImports(); + + initMemory(imports); + + if (!(module instanceof WebAssembly.Module)) { + module = new WebAssembly.Module(module); + } + + const instance = new WebAssembly.Instance(module, imports); + + return finalizeInit(instance, module); +} + +async function init(input) { + if (typeof input === 'undefined') { + input = new URL('node_maintainer_bg.wasm', import.meta.url); + } + const imports = getImports(); + + if (typeof input === 'string' || (typeof Request === 'function' && input instanceof Request) || (typeof URL === 'function' && input instanceof URL)) { + input = fetch(input); + } + + initMemory(imports); + + const { instance, module } = await load(await input, imports); + + return finalizeInit(instance, module); +} + +export { initSync } +export default init; diff --git a/extensions/typescript-language-features/package-manager/node-maintainer/node_maintainer_bg.wasm b/extensions/typescript-language-features/package-manager/node-maintainer/node_maintainer_bg.wasm new file mode 100644 index 0000000000000..2974c9835227f Binary files /dev/null and b/extensions/typescript-language-features/package-manager/node-maintainer/node_maintainer_bg.wasm differ diff --git a/extensions/typescript-language-features/package-manager/node-maintainer/node_maintainer_bg.wasm.d.ts b/extensions/typescript-language-features/package-manager/node-maintainer/node_maintainer_bg.wasm.d.ts new file mode 100644 index 0000000000000..77397cc906c11 --- /dev/null +++ b/extensions/typescript-language-features/package-manager/node-maintainer/node_maintainer_bg.wasm.d.ts @@ -0,0 +1,68 @@ +/* tslint:disable */ +/* eslint-disable */ +export const memory: WebAssembly.Memory; +export function __wbg_nodemaintaineroptions_free(a: number): void; +export function __wbg_nodemaintainer_free(a: number): void; +export function nodemaintainer_resolveSpec(a: number, b: number, c: number): number; +export function nodemaintainer_resolveManifest(a: number, b: number): number; +export function nodemaintainer_toKdl(a: number, b: number): void; +export function nodemaintainer_packageAtPath(a: number, b: number, c: number): number; +export function nodemaintainer_forEachPackage(a: number, b: number): number; +export function resolveSpec(a: number, b: number, c: number): number; +export function resolveManifest(a: number, b: number): number; +export function packument(a: number, b: number, c: number): number; +export function corgiPackument(a: number, b: number, c: number): number; +export function metadata(a: number, b: number, c: number): number; +export function corgiMetadata(a: number, b: number, c: number): number; +export function tarball(a: number, b: number, c: number): number; +export function entries(a: number, b: number, c: number): number; +export function __wbg_nassun_free(a: number): void; +export function nassun_new(a: number, b: number): void; +export function nassun_resolve(a: number, b: number, c: number): number; +export function nassun_packument(a: number, b: number, c: number): number; +export function nassun_metadata(a: number, b: number, c: number): number; +export function nassun_corgiPackument(a: number, b: number, c: number): number; +export function nassun_corgiMetadata(a: number, b: number, c: number): number; +export function nassun_tarball(a: number, b: number, c: number): number; +export function nassun_entries(a: number, b: number, c: number): number; +export function __wbg_package_free(a: number): void; +export function package_from(a: number): number; +export function package_name(a: number): number; +export function package_resolved(a: number): number; +export function package_corgiPackument(a: number): number; +export function package_corgiMetadata(a: number): number; +export function package_packument(a: number): number; +export function package_metadata(a: number): number; +export function package_tarball(a: number): number; +export function package_entries(a: number): number; +export function __wbg_readablestreamgetreaderoptions_free(a: number): void; +export function readablestreamgetreaderoptions_mode(a: number): number; +export function __wbg_pipeoptions_free(a: number): void; +export function pipeoptions_preventClose(a: number): number; +export function pipeoptions_preventCancel(a: number): number; +export function pipeoptions_preventAbort(a: number): number; +export function pipeoptions_signal(a: number): number; +export function __wbg_queuingstrategy_free(a: number): void; +export function queuingstrategy_highWaterMark(a: number): number; +export function __wbg_intounderlyingsource_free(a: number): void; +export function intounderlyingsource_pull(a: number, b: number): number; +export function intounderlyingsource_cancel(a: number): void; +export function __wbg_intounderlyingsink_free(a: number): void; +export function intounderlyingsink_write(a: number, b: number): number; +export function intounderlyingsink_close(a: number): number; +export function intounderlyingsink_abort(a: number, b: number): number; +export function __wbg_intounderlyingbytesource_free(a: number): void; +export function intounderlyingbytesource_type(a: number): number; +export function intounderlyingbytesource_autoAllocateChunkSize(a: number): number; +export function intounderlyingbytesource_start(a: number, b: number): void; +export function intounderlyingbytesource_pull(a: number, b: number): number; +export function intounderlyingbytesource_cancel(a: number): void; +export function __wbindgen_export_0(a: number): number; +export function __wbindgen_export_1(a: number, b: number, c: number): number; +export const __wbindgen_export_2: WebAssembly.Table; +export function __wbindgen_export_3(a: number, b: number, c: number): void; +export function __wbindgen_export_4(a: number, b: number, c: number): void; +export function __wbindgen_add_to_stack_pointer(a: number): number; +export function __wbindgen_export_5(a: number, b: number): void; +export function __wbindgen_export_6(a: number): void; +export function __wbindgen_export_7(a: number, b: number, c: number, d: number): void; diff --git a/extensions/typescript-language-features/package-manager/node-maintainer/package.json b/extensions/typescript-language-features/package-manager/node-maintainer/package.json new file mode 100644 index 0000000000000..93deb0fb1cccc --- /dev/null +++ b/extensions/typescript-language-features/package-manager/node-maintainer/package.json @@ -0,0 +1,24 @@ +{ + "name": "node-maintainer", + "collaborators": [ + "Orogene Maintainers and Contributors" + ], + "description": "NPM dependency tree resolver for Orogene.", + "version": "0.3.23", + "license": "Apache-2.0", + "repository": { + "type": "git", + "url": "https://github.com/orogene/orogene" + }, + "files": [ + "node_maintainer_bg.wasm", + "node_maintainer.js", + "node_maintainer.d.ts" + ], + "module": "node_maintainer.js", + "homepage": "https://orogene.dev", + "types": "node_maintainer.d.ts", + "sideEffects": [ + "./snippets/*" + ] +} \ No newline at end of file diff --git a/extensions/typescript-language-features/package-manager/node-maintainer/snippets/wasm-streams-42e57edbcd526312/inline0.js b/extensions/typescript-language-features/package-manager/node-maintainer/snippets/wasm-streams-42e57edbcd526312/inline0.js new file mode 100644 index 0000000000000..6427b8c24d6c8 --- /dev/null +++ b/extensions/typescript-language-features/package-manager/node-maintainer/snippets/wasm-streams-42e57edbcd526312/inline0.js @@ -0,0 +1 @@ +export function bytes_literal() { return "bytes"; } \ No newline at end of file diff --git a/extensions/typescript-language-features/package-manager/package.json b/extensions/typescript-language-features/package-manager/package.json new file mode 100644 index 0000000000000..ede2d3b70da22 --- /dev/null +++ b/extensions/typescript-language-features/package-manager/package.json @@ -0,0 +1,5 @@ +{ + "name": "package-manager", + "module": "packageManager.ts", + "private": true +} diff --git a/extensions/typescript-language-features/package-manager/packageManager.ts b/extensions/typescript-language-features/package-manager/packageManager.ts new file mode 100644 index 0000000000000..8c45922146421 --- /dev/null +++ b/extensions/typescript-language-features/package-manager/packageManager.ts @@ -0,0 +1,420 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +import { basename, dirname, isAbsolute, join } from 'path'; +import { resolveManifest, initSync, Nassun, NodeMaintainer, Package } from './node-maintainer'; +import nmWasm from './node-maintainer/node_maintainer_bg.wasm'; + +initSync(dataURItoUint8Array(nmWasm as unknown as string)); + +const decoder = new TextDecoder(); + +export interface InstallProjectOpts { + addPackages?: string[]; + removePackages?: string[]; + packageType?: PackageType; + pkgJson?: string; + npmLock?: string; + kdlLock?: string; +} + +export enum PackageType { + Dependency = 'dependencies', + DevDependency = 'devDependencies', + OptionalDependency = 'optionalDependencies', + PeerDependency = 'peerDependencies', +} + +// This is the subset of ts.server.System that we actually need. +export interface FileSystem { + readDirectory(path: string, extensions?: readonly string[], exclude?: readonly string[], include?: readonly string[], depth?: number): string[]; + deleteFile?(path: string): void; + createDirectory(path: string): void; + writeFile(path: string, data: string, writeByteOrderMark?: boolean): void; + directoryExists(path: string): boolean; + readFile(path: string, encoding?: string): string | undefined; +} + +// The meta file is placed in `node_modules/.meta.json` and records what +// packages have actually been installed. +interface MetaFile { + packages?: Record; +} + +export class PackageManager { + private readonly nassun: Nassun = new Nassun({}); + + constructor(private readonly fs: FileSystem) { } + + async resolveProject(root: string, opts: InstallProjectOpts = {}) { + if (opts.addPackages || opts.removePackages) { + await this.updateJson(join(root, 'package.json'), opts); + } + console.time(`dependency resolution: ${root}`); + const maintainer = await this.resolveMaintainer(root, opts); + console.timeEnd(`dependency resolution: ${root}`); + return new ResolvedProject(this.fs, maintainer, root); + } + + private async updateJson(packageJsonPath: string, opts: InstallProjectOpts = {}) { + const packageType = opts.packageType ?? PackageType.Dependency; + const corgis = await Promise.all((opts.addPackages ?? []).map(async pkg => this.nassun.corgiMetadata(pkg))); + let pkgJson; + try { + pkgJson = this.readJson(packageJsonPath); + } catch (e) { + console.error('failed to read package.json', e); + pkgJson = {}; + } + + for (const packageName of opts.removePackages ?? []) { + delete pkgJson.dependencies?.[packageName]; + delete pkgJson.devDependencies?.[packageName]; + delete pkgJson.optionalDependencies?.[packageName]; + delete pkgJson.peerDependencies?.[packageName]; + } + + for (const corgi of corgis) { + if (!pkgJson[packageType]) { + pkgJson[packageType] = {}; + } + pkgJson[packageType][corgi.name] = `^${corgi.version}`; + } + + const stringified = JSON.stringify(pkgJson, undefined, 2); + this.fs.writeFile(packageJsonPath, stringified); + } + + private async resolveMaintainer(root: string, opts: InstallProjectOpts): Promise { + const pkgJson = opts.pkgJson || this.fs.readFile(join(root, 'package.json')) || '{}'; + const kdlPkgLock = opts.kdlLock || this.fs.readFile(join(root, 'package-lock.kdl')); + const npmPkgLock = opts.npmLock || this.fs.readFile(join(root, 'package-lock.json')); + return resolveManifest(JSON.parse(pkgJson.trim()), { kdlLock: kdlPkgLock, npmLock: npmPkgLock }); + } + + /** + * What it says on the tin. Reads a JSON file from the given path. Throws + * if the file doesn't exist (as opposed to returning `undefined`, like + * fs.readFile does). + */ + private readJson(path: string): any { + const data = this.fs.readFile(path); + if (!data) { + throw new Error('Failed to read file: ' + path); + } + return JSON.parse(data.trim()); + } +} + +/** + * An entry extracted from a package tarball. + */ +interface Entry { + type: number; + mtime: number; + size: number; + path: string; + contents: ReadableStream; +} + +export class ResolvedProject { + private readonly prefix: string; + private readonly metaPath: string; + + constructor(private readonly fs: FileSystem, private readonly maintainer: NodeMaintainer, private readonly root: string) { + this.prefix = join(root, 'node_modules'); + this.metaPath = join(this.prefix, '.meta.json'); + } + + /** + * Synchronizes the project's node_modules directory with the current resolved dependencies, pruning any extraneous ones. + */ + async restore() { + console.time(`project restore: ${this.root}`); + this.pruneExtraneous(); + await this.extractMissing(); + this.writeLockfile(); + console.timeEnd(`project restore: ${this.root}`); + } + + /** + * Extracts a package at the given path. If a package has already been + * extracted to that location, it will be replaced. + * + * @param path to a package + * @returns The number of files extracted, or undefined if the path + */ + async restorePackageAt(path: string): Promise { + console.time(`restore package at: ${path}`); + this.checkPath(path); + const meta: MetaFile = JSON.parse(this.fs.readFile(this.metaPath) || '{}'); + if (!meta.packages) { + meta.packages = {}; + } + const projRoot = this.getProjectRoot(path); + + if (!projRoot) { + console.error('root not found for ', path); + console.timeEnd(`restore package at: ${path}`); + return; + } + + const pkgPath = packagePath(path); + const pkg = this.packageAtPath(path.slice(projRoot.length)); + if (!pkg) { + console.error('no package at path', path, pkgPath); + console.timeEnd(`restore package at: ${path}`); + return; + } + + if (pkg && pkgPath && meta.packages?.[pkgPath.slice(this.prefix.length)]?.resolved === pkg.resolved) { + // Already installed and synced. No need to do anything else! + console.timeEnd(`restore package at: ${path}`); + return; + } else { + rimraf(this.fs, pkgPath); + } + + let count; + try { + // NB(zkat): load-bearing `await`. We need to await here because + // otherwise we'll have a use-after-free error when extracting the + // package entries. + count = await this.extractPackageTo(pkg, pkgPath); + meta.packages[pkgPath.slice(this.prefix.length)] = { + name: pkg.name, + resolved: pkg.resolved + }; + } catch (e) { + console.error('error extracting: ', e); + console.timeEnd(`restore package at: ${path}`); + throw e; + } finally { + pkg.free(); + } + rimraf(this.fs, this.metaPath); + this.fs.writeFile(this.metaPath, JSON.stringify(meta, null, 2)); + this.writeLockfile(); + console.timeEnd(`restore package at: ${path}`); + return count; + } + + /** + * Deletes/prunes files and directories that aren't expected to be there + * by the currently-calculated tree. Extraneous calculation happens based on the contents of `.meta.json` + * @returns + */ + pruneExtraneous(): number { + const meta = JSON.parse(this.fs.readFile(this.metaPath) || '{}'); + let count = 0; + + if (!this.fs.directoryExists(this.prefix)) { + return count; + } + + for (const entryPath of walkDir(this.fs, this.prefix)) { + if (entryPath === this.metaPath) { + // Leave the meta path alone. + continue; + } + const pkgPath = packagePath(entryPath); + // Only look at toplevel package paths. + if (pkgPath === entryPath) { + const subPath = pkgPath.slice(this.prefix.length); + const pkg = this.packageAtPath(subPath); + try { + if (pkg && meta.packages?.[pkgPath.slice(this.prefix.length)]?.resolved === pkg.resolved) { + // There's a valid package here. Move along. + } else { + // Extraneous! + count++; + rimraf(this.fs, entryPath); + } + } finally { + pkg?.free(); + } + } + } + + return count; + } + + private packageAtPath(path: string): Package | undefined { + return this.maintainer.packageAtPath(path); + } + + private getProjectRoot(path: string): string | undefined { + const pkgPath = path.match(/(^.*\/)node_modules/); + return pkgPath?.[1]; + } + + private checkPath(path: string) { + if (!path.startsWith(this.root)) { + throw new Error(`Path ${path} is not in project root ${this.root}`); + } + if (!isAbsolute(path)) { + throw new Error(`Path ${path} is not absolute`); + } + } + + private async extractPackageTo(pkg: Package, pkgPath: string): Promise { + const mkdirCache = new Set(); + mkdirp(mkdirCache, this.fs, pkgPath); + // Clean up the directory, in case it already exists, but leave + // node_modules alone to avoid clobbering other packages. + for (const file of this.fs.readDirectory(pkgPath)) { + if (basename(file) === 'node_modules') { + continue; + } + rimraf(this.fs, file); + } + const entries = >await pkg.entries(); + const reader = entries.getReader(); + let fileCount = 0; + while (true) { + const { done, value: entry } = await reader.read(); + if (done) { + break; + } + + // Strip the first level of a package, just like NPM does. + const entryPath = join(pkgPath, entry.path.replace(/^([^/]*\/)?/, '')); + + // We simulate directories based on files we find. + mkdirp(mkdirCache, this.fs, dirname(entryPath)); + // Types are registered here: + // https://www.gnu.org/software/tar/manual/html_node/Standard.html. + // You can get these numbers by just doing `'5'.codePointAt(0)`, + // but we may as well hard-code the three values we actually care + // about here. + if (entry.type === 53) { + // '5' == 53 == directory + mkdirp(mkdirCache, this.fs, entryPath); + await drainStream(entry.contents); + } else if (entry.type === 0 || entry.type === 48) { + // '0' == 48 or '\x00' == 0 == regular file + const data = await streamToArrayBuffer(entry.contents, entry.size); + this.fs.writeFile(entryPath, decoder.decode(data)); + fileCount++; + } else { + // Anything else, we throw away, but we have to make sure to + // drain any contents before we can continue reading the + // tarball. + await drainStream(entry.contents); + } + } + + return fileCount; + } + + private async extractMissing() { + const meta: MetaFile = { packages: {} }; + await this.maintainer.forEachPackage(async (pkg: Package, path: string) => { + const fullPath = join(this.prefix, path); + meta.packages![path] = { + name: pkg.name, + resolved: pkg.resolved + }; + try { + if (!this.fs.directoryExists(fullPath)) { + await this.extractPackageTo(pkg, fullPath); + } + } finally { + pkg.free(); + } + }); + rimraf(this.fs, this.metaPath); + this.fs.writeFile(this.metaPath, JSON.stringify(meta, null, 2)); + } + + private writeLockfile() { + this.fs.writeFile(join(this.root, 'package-lock.kdl'), this.maintainer.toKdl()); + } + +} + +//---- Utils + +/** + * Given a full path to a particular file, presumably inside a package, + * this returns the path of the package containing that file. + * @param path the full file path to the file. + * @returns the subpath of the package itself + */ +export function packagePath(path: string): string { + return path.replace(/(^.*\/node_modules\/(?:@[^/]+\/)?[^/]+)\/?(?!node_modules\/).*/, '$1'); +} + +// via https://stackoverflow.com/questions/12168909/blob-from-dataurl +function dataURItoUint8Array(dataURI: string) { + const byteString = atob(dataURI.split(',')[1]); + const ab = new ArrayBuffer(byteString.length); + const ia = new Uint8Array(ab); + for (let i = 0; i < byteString.length; i++) { + ia[i] = byteString.charCodeAt(i); + } + return ia; +} + +async function drainStream(stream: ReadableStream): Promise { + const reader = stream.getReader(); + while (true) { // eslint-disable-line no-constant-condition + const { done } = await reader.read(); + if (done) { + break; + } + } + return reader.closed; +} + +async function streamToArrayBuffer(stream: ReadableStream, length: number): Promise { + const result = new Uint8Array(length); + const reader = stream.getReader(); + let idx = 0; + while (true) { // eslint-disable-line no-constant-condition + const { done, value } = await reader.read(); + if (done) { + break; + } + result.set(value, idx); + idx += value.length; + } + return result; +} + +function* walkDir(fs: FileSystem, path: string) { + let contents = fs.readDirectory(path); + while (contents.length) { + const entry = contents.shift()!; + const entryPath = join(path, entry); + if (fs.directoryExists(entryPath)) { + contents = fs.readDirectory(entryPath).map(e => join(entry, e)).concat(contents); + } + yield entryPath; + } +} + +function mkdirp(cache: Set, fs: FileSystem, path: string) { + path.split('/').reduce((dir: string, next: string) => { + const joined = join(dir, next); + if (!cache.has(joined) && !fs.directoryExists(joined)) { + fs.createDirectory(joined); + cache.add(joined); + } + return joined; + }, ''); +} + +function rimraf(fs: FileSystem, path: string) { + if (fs.directoryExists(path)) { + for (const subPath of fs.readDirectory(path).map(e => join(path, e))) { + rimraf(fs, subPath); + } + } + try { + fs.deleteFile?.(path); + } catch (e) { + // shou ga nai + } +} diff --git a/extensions/typescript-language-features/package-manager/tsconfig.json b/extensions/typescript-language-features/package-manager/tsconfig.json new file mode 100644 index 0000000000000..390a38c67eda8 --- /dev/null +++ b/extensions/typescript-language-features/package-manager/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "types": [ + "node" + ] + } +} diff --git a/extensions/typescript-language-features/package.json b/extensions/typescript-language-features/package.json index 37b710db7454d..662cbaf7f17c9 100644 --- a/extensions/typescript-language-features/package.json +++ b/extensions/typescript-language-features/package.json @@ -34,12 +34,12 @@ ], "dependencies": { "@vscode/extension-telemetry": "0.7.5", - "jsonc-parser": "^3.2.0", - "semver": "5.5.1", - "vscode-tas-client": "^0.1.63", "@vscode/sync-api-client": "^0.7.2", "@vscode/sync-api-common": "^0.7.2", "@vscode/sync-api-service": "^0.7.3", + "jsonc-parser": "^3.2.0", + "semver": "5.5.1", + "vscode-tas-client": "^0.1.63", "vscode-uri": "^3.0.3" }, "devDependencies": { @@ -1253,6 +1253,13 @@ "description": "%configuration.tsserver.web.projectWideIntellisense.suppressSemanticErrors%", "scope": "window" }, + "typescript.experimental.tsserver.web.typeAcquisition.enabled": { + "type": "boolean", + "default": false, + "description": "%configuration.experimental.tsserver.web.typeAcquisition.enabled%", + "scope": "window", + "tags": ["experimental"] + }, "typescript.preferGoToSourceDefinition": { "type": "boolean", "default": false, diff --git a/extensions/typescript-language-features/package.nls.json b/extensions/typescript-language-features/package.nls.json index cb5406fecaeec..eade82a3a8774 100644 --- a/extensions/typescript-language-features/package.nls.json +++ b/extensions/typescript-language-features/package.nls.json @@ -211,6 +211,7 @@ "configuration.suggest.objectLiteralMethodSnippets.enabled": "Enable/disable snippet completions for methods in object literals. Requires using TypeScript 4.7+ in the workspace.", "configuration.tsserver.web.projectWideIntellisense.enabled": "Enable/disable project-wide IntelliSense on web. Requires that VS Code is running in a trusted context.", "configuration.tsserver.web.projectWideIntellisense.suppressSemanticErrors": "Suppresses semantic errors. This is needed when using external packages as these can't be included analyzed on web.", + "configuration.experimental.tsserver.web.typeAcquisition.enabled": "Enable/disable package acquisition on the web.", "walkthroughs.nodejsWelcome.title": "Get started with JavaScript and Node.js", "walkthroughs.nodejsWelcome.description": "Make the most of Visual Studio Code's first-class JavaScript experience.", "walkthroughs.nodejsWelcome.downloadNode.forMacOrWindows.title": "Install Node.js", diff --git a/extensions/typescript-language-features/src/configuration/configuration.ts b/extensions/typescript-language-features/src/configuration/configuration.ts index cab1cf4c81904..d7662d8a9afae 100644 --- a/extensions/typescript-language-features/src/configuration/configuration.ts +++ b/extensions/typescript-language-features/src/configuration/configuration.ts @@ -112,6 +112,7 @@ export interface TypeScriptServiceConfiguration { readonly useSyntaxServer: SyntaxServerConfiguration; readonly webProjectWideIntellisenseEnabled: boolean; readonly webProjectWideIntellisenseSuppressSemanticErrors: boolean; + readonly webExperimentalTypeAcquisition: boolean; readonly enableProjectDiagnostics: boolean; readonly maxTsServerMemory: number; readonly enablePromptUseWorkspaceTsdk: boolean; @@ -144,6 +145,7 @@ export abstract class BaseServiceConfigurationProvider implements ServiceConfigu useSyntaxServer: this.readUseSyntaxServer(configuration), webProjectWideIntellisenseEnabled: this.readWebProjectWideIntellisenseEnable(configuration), webProjectWideIntellisenseSuppressSemanticErrors: this.readWebProjectWideIntellisenseSuppressSemanticErrors(configuration), + webExperimentalTypeAcquisition: this.readWebExperimentalTypeAcquisition(configuration), enableProjectDiagnostics: this.readEnableProjectDiagnostics(configuration), maxTsServerMemory: this.readMaxTsServerMemory(configuration), enablePromptUseWorkspaceTsdk: this.readEnablePromptUseWorkspaceTsdk(configuration), @@ -173,6 +175,10 @@ export abstract class BaseServiceConfigurationProvider implements ServiceConfigu return configuration.get('typescript.disableAutomaticTypeAcquisition', false); } + protected readWebExperimentalTypeAcquisition(configuration: vscode.WorkspaceConfiguration): boolean { + return configuration.get('typescript.experimental.tsserver.web.typeAcquisition.enabled', false); + } + protected readLocale(configuration: vscode.WorkspaceConfiguration): string | null { const value = configuration.get('typescript.locale', 'auto'); return !value || value === 'auto' ? null : value; diff --git a/extensions/typescript-language-features/src/extension.browser.ts b/extensions/typescript-language-features/src/extension.browser.ts index 5098231005acb..9644de1fb134f 100644 --- a/extensions/typescript-language-features/src/extension.browser.ts +++ b/extensions/typescript-language-features/src/extension.browser.ts @@ -23,6 +23,8 @@ import { Logger } from './logging/logger'; import { getPackageInfo } from './utils/packageInfo'; import { isWebAndHasSharedArrayBuffers } from './utils/platform'; import { PluginManager } from './tsServer/plugins'; +import { MemFs } from './filesystems/memFs'; +import { AutoInstallerFs } from './filesystems/autoInstallerFs'; class StaticVersionProvider implements ITypeScriptVersionProvider { @@ -98,6 +100,14 @@ export async function activate(context: vscode.ExtensionContext): Promise { context.subscriptions.push(lazilyActivateClient(lazyClientHost, pluginManager, activeJsTsEditorTracker, async () => { await preload(logger); })); + context.subscriptions.push(vscode.workspace.registerFileSystemProvider('vscode-global-typings', new MemFs(), { + isCaseSensitive: true, + isReadonly: false + })); + context.subscriptions.push(vscode.workspace.registerFileSystemProvider('vscode-node-modules', new AutoInstallerFs(), { + isCaseSensitive: true, + isReadonly: false + })); return getExtensionApi(onCompletionAccepted.event, pluginManager); } @@ -124,6 +134,5 @@ async function preload(logger: Logger): Promise { } } catch (error) { logger.info(`Loading workspace content for repository ${workspaceUri.toString()} failed: ${error instanceof Error ? error.toString() : 'Unknown reason'}`); - console.error(error); } } diff --git a/extensions/typescript-language-features/src/filesystems/autoInstallerFs.ts b/extensions/typescript-language-features/src/filesystems/autoInstallerFs.ts new file mode 100644 index 0000000000000..0197dd0f54782 --- /dev/null +++ b/extensions/typescript-language-features/src/filesystems/autoInstallerFs.ts @@ -0,0 +1,252 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as vscode from 'vscode'; +import { MemFs } from './memFs'; +import { URI } from 'vscode-uri'; +import { PackageManager, FileSystem, packagePath } from '../../package-manager/packageManager'; +import { join, basename, dirname } from 'path'; + +const TEXT_DECODER = new TextDecoder('utf-8'); +const TEXT_ENCODER = new TextEncoder(); + +export class AutoInstallerFs implements vscode.FileSystemProvider { + + private readonly memfs = new MemFs(); + private readonly fs: FileSystem; + private readonly projectCache = new Map>(); + private readonly watcher: vscode.FileSystemWatcher; + private readonly _emitter = new vscode.EventEmitter(); + + readonly onDidChangeFile: vscode.Event = this._emitter.event; + + constructor() { + this.watcher = vscode.workspace.createFileSystemWatcher('**/{package.json,package-lock.json,package-lock.kdl}'); + const handler = (uri: URI) => { + const root = dirname(uri.path); + if (this.projectCache.delete(root)) { + (async () => { + const pm = new PackageManager(this.fs); + const opts = await this.getInstallOpts(uri, root); + const proj = await pm.resolveProject(root, opts); + proj.pruneExtraneous(); + // TODO: should this fire on vscode-node-modules instead? + // NB(kmarchan): This should tell TSServer that there's + // been changes inside node_modules and it needs to + // re-evaluate things. + this._emitter.fire([{ + type: vscode.FileChangeType.Changed, + uri: uri.with({ path: join(root, 'node_modules') }) + }]); + })(); + } + }; + this.watcher.onDidChange(handler); + this.watcher.onDidCreate(handler); + this.watcher.onDidDelete(handler); + const memfs = this.memfs; + memfs.onDidChangeFile((e) => { + this._emitter.fire(e.map(ev => ({ + type: ev.type, + // TODO: we're gonna need a MappedUri dance... + uri: ev.uri.with({ scheme: 'memfs' }) + }))); + }); + this.fs = { + readDirectory(path: string, _extensions?: readonly string[], _exclude?: readonly string[], _include?: readonly string[], _depth?: number): string[] { + return memfs.readDirectory(URI.file(path)).map(([name, _]) => name); + }, + + deleteFile(path: string): void { + memfs.delete(URI.file(path)); + }, + + createDirectory(path: string): void { + memfs.createDirectory(URI.file(path)); + }, + + writeFile(path: string, data: string, _writeByteOrderMark?: boolean): void { + memfs.writeFile(URI.file(path), TEXT_ENCODER.encode(data), { overwrite: true, create: true }); + }, + + directoryExists(path: string): boolean { + try { + const stat = memfs.stat(URI.file(path)); + return stat.type === vscode.FileType.Directory; + } catch (e) { + return false; + } + }, + + readFile(path: string, _encoding?: string): string | undefined { + try { + return TEXT_DECODER.decode(memfs.readFile(URI.file(path))); + } catch (e) { + return undefined; + } + } + }; + } + + watch(resource: vscode.Uri): vscode.Disposable { + const mapped = URI.file(new MappedUri(resource).path); + console.log('watching', mapped); + return this.memfs.watch(mapped); + } + + async stat(uri: vscode.Uri): Promise { + // console.log('stat', uri.toString()); + const mapped = new MappedUri(uri); + + // TODO: case sensitivity configuration + + // We pretend every single node_modules or @types directory ever actually + // exists. + if (basename(mapped.path) === 'node_modules' || basename(mapped.path) === '@types') { + return { + mtime: 0, + ctime: 0, + type: vscode.FileType.Directory, + size: 0 + }; + } + + await this.ensurePackageContents(mapped); + + return this.memfs.stat(URI.file(mapped.path)); + } + + async readDirectory(uri: vscode.Uri): Promise<[string, vscode.FileType][]> { + // console.log('readDirectory', uri.toString()); + const mapped = new MappedUri(uri); + await this.ensurePackageContents(mapped); + + return this.memfs.readDirectory(URI.file(mapped.path)); + } + + async readFile(uri: vscode.Uri): Promise { + // console.log('readFile', uri.toString()); + const mapped = new MappedUri(uri); + await this.ensurePackageContents(mapped); + + return this.memfs.readFile(URI.file(mapped.path)); + } + + writeFile(_uri: vscode.Uri, _content: Uint8Array, _options: { create: boolean; overwrite: boolean }): void { + throw new Error('not implemented'); + } + + rename(_oldUri: vscode.Uri, _newUri: vscode.Uri, _options: { overwrite: boolean }): void { + throw new Error('not implemented'); + } + + delete(_uri: vscode.Uri): void { + throw new Error('not implemented'); + } + + createDirectory(_uri: vscode.Uri): void { + throw new Error('not implemented'); + } + + private async ensurePackageContents(incomingUri: MappedUri): Promise { + // console.log('ensurePackageContents', incomingUri.path); + + // If we're not looking for something inside node_modules, bail early. + if (!incomingUri.path.includes('node_modules')) { + throw vscode.FileSystemError.FileNotFound(); + } + + // standard lib files aren't handled through here + if (incomingUri.path.includes('node_modules/@typescript') || incomingUri.path.includes('node_modules/@types/typescript__')) { + throw vscode.FileSystemError.FileNotFound(); + } + + const root = this.getProjectRoot(incomingUri.path); + + const pkgPath = packagePath(incomingUri.path); + if (!root || this.projectCache.get(root)?.has(pkgPath)) { + return; + } + + const proj = await (new PackageManager(this.fs)).resolveProject(root, await this.getInstallOpts(incomingUri.original, root)); + + const restore = proj.restorePackageAt(incomingUri.path); + try { + await restore; + } catch (e) { + console.error(`failed to restore package at ${incomingUri.path}: `, e); + throw e; + } + if (!this.projectCache.has(root)) { + this.projectCache.set(root, new Set()); + } + this.projectCache.get(root)!.add(pkgPath); + } + + private async getInstallOpts(originalUri: URI, root: string) { + const vsfs = vscode.workspace.fs; + let pkgJson; + try { + pkgJson = TEXT_DECODER.decode(await vsfs.readFile(originalUri.with({ path: join(root, 'package.json') }))); + } catch (e) { } + + let kdlLock; + try { + kdlLock = TEXT_DECODER.decode(await vsfs.readFile(originalUri.with({ path: join(root, 'package-lock.kdl') }))); + } catch (e) { } + + let npmLock; + try { + npmLock = TEXT_DECODER.decode(await vsfs.readFile(originalUri.with({ path: join(root, 'package-lock.json') }))); + } catch (e) { } + + return { + pkgJson, + kdlLock, + npmLock + }; + } + + private getProjectRoot(path: string): string | undefined { + const pkgPath = path.match(/(^.*)\/node_modules/); + return pkgPath?.[1]; + } + + // --- manage file events + +} + +class MappedUri { + readonly raw: vscode.Uri; + readonly original: vscode.Uri; + readonly mapped: vscode.Uri; + constructor(uri: vscode.Uri) { + this.raw = uri; + + const parts = uri.path.match(/^\/([^\/]+)\/([^\/]*)(?:\/(.+))?$/); + if (!parts) { + throw new Error(`Invalid path: ${uri.path}`); + } + + const scheme = parts[1]; + const authority = parts[2] === 'ts-nul-authority' ? '' : parts[2]; + const path = parts[3]; + this.original = URI.from({ scheme, authority, path: (path ? '/' + path : path) }); + this.mapped = this.original.with({ scheme: this.raw.scheme, authority: this.raw.authority }); + } + + get path() { + return this.mapped.path; + } + get scheme() { + return this.mapped.scheme; + } + get authority() { + return this.mapped.authority; + } + get flatPath() { + return join('/', this.scheme, this.authority, this.path); + } +} diff --git a/extensions/typescript-language-features/src/filesystems/memFs.ts b/extensions/typescript-language-features/src/filesystems/memFs.ts new file mode 100644 index 0000000000000..02476ec180426 --- /dev/null +++ b/extensions/typescript-language-features/src/filesystems/memFs.ts @@ -0,0 +1,198 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as vscode from 'vscode'; +import { basename, dirname } from 'path'; + +export class MemFs implements vscode.FileSystemProvider { + + private readonly root = new FsEntry( + new Map(), + 0, + 0, + ); + + stat(uri: vscode.Uri): vscode.FileStat { + // console.log('stat', uri.toString()); + const entry = this.getEntry(uri); + if (!entry) { + throw vscode.FileSystemError.FileNotFound(); + } + + return entry; + } + + readDirectory(uri: vscode.Uri): [string, vscode.FileType][] { + // console.log('readDirectory', uri.toString()); + + const entry = this.getEntry(uri); + if (!entry) { + throw vscode.FileSystemError.FileNotFound(); + } + + return [...entry.contents.entries()].map(([name, entry]) => [name, entry.type]); + } + + readFile(uri: vscode.Uri): Uint8Array { + // console.log('readFile', uri.toString()); + + const entry = this.getEntry(uri); + if (!entry) { + throw vscode.FileSystemError.FileNotFound(); + } + + return entry.data; + } + + writeFile(uri: vscode.Uri, content: Uint8Array, { create, overwrite }: { create: boolean; overwrite: boolean }): void { + // console.log('writeFile', uri.toString()); + + const dir = this.getParent(uri); + + const fileName = basename(uri.path); + const dirContents = dir.contents; + + const time = Date.now() / 1000; + const entry = dirContents.get(basename(uri.path)); + if (!entry) { + if (create) { + dirContents.set(fileName, new FsEntry(content, time, time)); + this._emitter.fire([{ type: vscode.FileChangeType.Created, uri }]); + } else { + throw vscode.FileSystemError.FileNotFound(); + } + } else { + if (overwrite) { + entry.mtime = time; + entry.data = content; + this._emitter.fire([{ type: vscode.FileChangeType.Changed, uri }]); + } else { + throw vscode.FileSystemError.NoPermissions('overwrite option was not passed in'); + } + } + } + + rename(_oldUri: vscode.Uri, _newUri: vscode.Uri, _options: { overwrite: boolean }): void { + throw new Error('not implemented'); + } + + delete(uri: vscode.Uri): void { + try { + const dir = this.getParent(uri); + dir.contents.delete(basename(uri.path)); + this._emitter.fire([{ type: vscode.FileChangeType.Deleted, uri }]); + } catch (e) { } + } + + createDirectory(uri: vscode.Uri): void { + // console.log('createDirectory', uri.toString()); + const dir = this.getParent(uri); + const now = Date.now() / 1000; + dir.contents.set(basename(uri.path), new FsEntry(new Map(), now, now)); + } + + private getEntry(uri: vscode.Uri): FsEntry | void { + // TODO: have this throw FileNotFound itself? + // TODO: support configuring case sensitivity + let node: FsEntry = this.root; + for (const component of uri.path.split('/')) { + if (!component) { + // Skip empty components (root, stuff between double slashes, + // trailing slashes) + continue; + } + + if (node.type !== vscode.FileType.Directory) { + // We're looking at a File or such, so bail. + return; + } + + const next = node.contents.get(component); + + if (!next) { + // not found! + return; + } + + node = next; + } + return node; + } + + private getParent(uri: vscode.Uri) { + const dir = this.getEntry(uri.with({ path: dirname(uri.path) })); + if (!dir) { + throw vscode.FileSystemError.FileNotFound(); + } + return dir; + } + + // --- manage file events + + private readonly _emitter = new vscode.EventEmitter(); + + readonly onDidChangeFile: vscode.Event = this._emitter.event; + private readonly watchers = new Map>; + + watch(resource: vscode.Uri): vscode.Disposable { + if (!this.watchers.has(resource.path)) { + this.watchers.set(resource.path, new Set()); + } + const sy = Symbol(resource.path); + return new vscode.Disposable(() => { + const watcher = this.watchers.get(resource.path); + if (watcher) { + watcher.delete(sy); + if (!watcher.size) { + this.watchers.delete(resource.path); + } + } + }); + } +} + +class FsEntry { + get type(): vscode.FileType { + if (this._data instanceof Uint8Array) { + return vscode.FileType.File; + } else { + return vscode.FileType.Directory; + } + } + + get size(): number { + if (this.type === vscode.FileType.Directory) { + return [...this.contents.values()].reduce((acc: number, entry: FsEntry) => acc + entry.size, 0); + } else { + return this.data.length; + } + } + + constructor( + private _data: Uint8Array | Map, + public ctime: number, + public mtime: number, + ) { } + + get data() { + if (this.type === vscode.FileType.Directory) { + throw vscode.FileSystemError.FileIsADirectory; + } + return this._data; + } + set data(val: Uint8Array) { + if (this.type === vscode.FileType.Directory) { + throw vscode.FileSystemError.FileIsADirectory; + } + this._data = val; + } + + get contents() { + if (this.type !== vscode.FileType.Directory) { + throw vscode.FileSystemError.FileNotADirectory; + } + return >this._data; + } +} diff --git a/extensions/typescript-language-features/src/tsServer/serverProcess.browser.ts b/extensions/typescript-language-features/src/tsServer/serverProcess.browser.ts index cd54bdca2fb38..1ce92ef04c8d6 100644 --- a/extensions/typescript-language-features/src/tsServer/serverProcess.browser.ts +++ b/extensions/typescript-language-features/src/tsServer/serverProcess.browser.ts @@ -41,13 +41,15 @@ export class WorkerServerProcessFactory implements TsServerProcessFactory { tsServerLog: TsServerLog | undefined, ) { const tsServerPath = version.tsServerPath; - return new WorkerServerProcess(kind, tsServerPath, this._extensionUri, [ + const launchArgs = [ ...args, - - // Explicitly give TS Server its path so it can - // load local resources + // Explicitly give TS Server its path so it can load local resources '--executingFilePath', tsServerPath, - ], tsServerLog); + ]; + if (_configuration.webExperimentalTypeAcquisition) { + launchArgs.push('--experimentalTypeAcquisition'); + } + return new WorkerServerProcess(kind, tsServerPath, this._extensionUri, launchArgs, tsServerLog); } } diff --git a/extensions/typescript-language-features/tsconfig.json b/extensions/typescript-language-features/tsconfig.json index dbed493cc43bb..59169c18bfdcb 100644 --- a/extensions/typescript-language-features/tsconfig.json +++ b/extensions/typescript-language-features/tsconfig.json @@ -2,6 +2,7 @@ "extends": "../tsconfig.base.json", "compilerOptions": { "outDir": "./out", + "esModuleInterop": true, "experimentalDecorators": true, "types": [ "node" diff --git a/extensions/typescript-language-features/web/README.md b/extensions/typescript-language-features/web/README.md index 9cae35b8cf39f..eda9e9cb00b54 100644 --- a/extensions/typescript-language-features/web/README.md +++ b/extensions/typescript-language-features/web/README.md @@ -1,154 +1,45 @@ # vscode-wasm-typescript -Language server host for typescript using vscode's sync-api in the browser -## TODOs +Language server host for typescript using vscode's sync-api in the browser. -### Prototype +## Getting up and running -- [x] get semantic diagnostics rendering squigglies - - typescriptserviceclient.ts has some functions that look at `scheme` to determine some features (hasCapabilityForResource) (also getWorkspaceRootForResource) - - known schemes are in utils/fileSchemes.ts, but don't include vscode-test-web - - adding vscode-test-web in a couple places didn't help, maybe I need to be hackier - - nope, another predicate is `isWeb`, so I had to change place(s) it's used too -- [x] cancellation +To test this out, you'll need three shells: -### Cleanup +1. `yarn watch` for vscode itself +2. `yarn watch-web` for the web side +3. `node /scripts/code-web.js --coi` -- [x] point webpack hack to node_modules; link those files to locally built ones -- [x] create one or more MessageChannels for various communication -- [x] shut down normal listener - - starting the server currently crashes because ts.sys isn't defined -- I think it's a race condition. - In any case it'll need to get shut down before then, which may not be possible without changing Typescript. - - LATER: Turns out you can skip the existing server by depending on tsserverlibrary instead of tsserver. -- [x] figure out a webpack-native way to generate tsserver.web.js if possible -- [x] path rewriting is pretty loosey-goosey; likely to be incorrect some of the time - - invert the logic from TypeScriptServiceClient.normalizedPath for requests - - invert the function from webServer.ts for responses (maybe) - - something with getWorkspaceRootForResource (or anything else that checks `resouce.scheme`) -- [x] put files one level down from virtual root -- [x] fill in missing environment files like lib.dom.d.ts - - toResource's isWeb branch *probably* knows where to find this, just need to put it in the virtual FS - - I guess during setup in serverProcess.browser.ts. - - Not sure whether it needs to have the data or just a fs entry. - - Wait, I don't know how files get added to the FS normally. -- [x] cancellation should only retain one cancellation checker - - the one that matches the current request id - - but that means tracking (or retrieving from tsserver) the request id (aka seq?) - - and correctly setting/resetting it on the cancellation token too. - - I looked at the tsserver code. I think the web case is close to the single-pipe node case, - so I just require that requestId is set in order to call the *current* cancellation checker. - - Any incoming message with a cancellation checker will overwrite the current one. -- [x] Cancellation code in vscode is suspiciously prototypey. - - Specifically, it adds the vscode-wasm cancellation to original cancellation code, but should actually switch to the former for web only. - - looks like `isWeb()` is a way to check for being on the web -- [x] create multiple watchers - - on-demand instead of watching everything and checking on watch firing -- [x] get file watching to work - - it could *already* work, I just don't know how to test it - - look at extensions/markdown-language-features/src/client/fileWatchingManager.ts to see if I can use that - - later: it is OK. its main difference is that you can watch files in not-yet-created directories, and it maintains - a web of directory watches that then check whether the file is eventually created. - - even later: well, it works even though it is similar to my code. - I'm not sure what is different. -- [x] copy fileWatchingManager.ts to web/ ; there's no sharing code between extensions -- [x] Find out scheme the web actually uses instead of vscode-test-web (or switch over entirely to isWeb) -- [x] Need to parse and pass args through so that the syntax server isn't hard-coded to actually be another semantic server -- [x] think about implementing all the other ServerHost methods - - [x] copy importPlugin from previous version of webServer.ts - - [x] also copy details from - - previous implementation (although it's syntax-only so only covers part) - - node implementation in typescript proper -- [x] make realpath support symlinks similarly to node's realpath. - - Johannes says that the filesystem automatically follows symlinks, - so I don't think this is needed. -- [x] organise webServer.ts into multiple files - - OR at least re-arrange it so the diff with the previous version is smaller - - split it into multiple files after the initial PR -- [x] clear out TODOs -- [x] add semicolons everywhere; vscode's lint doesn't seem to complain, but the code clearly uses them -- [x] Further questions about host methods based on existing implementations - - `require` -- is this needed? In TS, it's only used in project system - - `trace` -- is this needed? In TS, it's only used in project system - - `useCaseSensitiveFileNames` -- old version says 'false' is the - safest option, but the virtual fs is case sensitive. Is the old - version still better? - - `writeOutputIsTTY` -- I'm using apiClient.vscode.terminal.write -- is it a tty? - - `getWidthOfTerminal` -- I don't know where to find this on apiClient.vscode.terminal either - - `clearScreen` -- node version writes \x1BC to the terminal. Would - this work for vscode? - - `readFile/writeFile` -- TS handles utf8, utf16le and manually - converts big-endian to utf16 little-endian. How does the in-memory - filesystem handle this? There's no place to specify encoding. (And - `writeFile` currently ignores the flag to write a BOM.) - - `resolvePath` -- node version uses path.resolve. Is it OK to use - that? Or should I re-implement it? Just use identity like the old - web code? - - `getDirectories`/`readDirectory` - - the node code manually skips '.' and '..' in the array returned by - readDirectory. Is this needed? - - `createSHA256Hash` -- the browser version is async, so I skipped it - - `realpath` -- still skips symlinks, I need to figure out what node does +The last command will open a browser window. You'll want to add `?vscode-coi=` +to the end. This is for enabling shared array buffers. So, for example: +`http://localhost:8080/?vscode-coi=`. -### Bugs +### Working on type acquisition -- [x] Response `seq` is always 0. -- [ ] current method of encoding /scheme/authority means that (node) module resolution looks for /scheme/node_modules and /node_modules - - even though they can't possibly exist - - probably not a problem though -- [x] problems pane doesn't clear problems issued on tsconfig. - - This is a known problem in normal usage as well. -- [x] renaming a file throws a No Project error to the console. -- [x] gotodef in another file throws and the editor has a special UI for it. - - definitionProviderBase.getSymbolLocations calls toOpenedFilePath which eventually calls the new / code - - then it calls client.execute which appears to actually request/response to the tsserver - - then the response body is mapped over location.file >> client.toResource >> fromTextSpan - - toResource has isWeb support, as well as (now unused) inMemoryResourcePrefix support - - so I can just redo whatever that did and it'll be fine +In order to work with web's new type acquisition, you'll need to enable +`TypeScript > Experimental > Tsserver > Web: Enable Project Wide Intellisense` +in your VS Code options (`Ctrl-,`), you may need to reload the page. -### Done -- [x] need to update 0.2 -> 0.7.* API (once it's working properly) -- [x] including reshuffling the webpack hack if needed -- [x] need to use the settings recommended by Sheetal -- [x] ProjectService always requests a typesMap.json at the cwd -- [x] sync-api-client says fs is rooted at memfs:/sample-folder; the protocol 'memfs:' is confusing our file parsing I think -- [x] nothing ever seems to find tsconfig.json -- [x] messages aren't actually coming through, just the message from the first request - - fixed by simplifying the listener setup for now -- [x] once messages work, you can probably log by postMessage({ type: 'log', body: "some logging text" }) -- [x] implement realpath, modifiedtime, resolvepath, then turn semantic mode on -- [x] file watching implemented with saved map of filename to callback, and forwarding +This happens when working in a regular `.js` file on a dependency without +declared types. You should be able to open `file.js` and write something like +`import lodash from 'lodash';` at the top of the file and, after a moment, get +types and other intellisense features (like Go To Def/Source Def) working as +expected. This scenario works off Tsserver's own Automatic Type Acquisition +capabilities, and simulates a "global" types cache stored at +`/vscode-global-typings/ts-nul-authority/project`, which is backed by an +in-memory `MemFs` `FileSystemProvider`. -### Also +### Simulated `node_modules` -- [ ] ATA will eventually need a host interface, or an improvement of the existing one (?) - -## Notes - -messages received by extension AND host use paths like ^/memfs/ts-nul-authority/sample-folder/file.ts -- problem: pretty sure the extension doesn't know what to do with that: it's not putting down error spans in file.ts -- question: why is the extension requesting quickinfo in that URI format? And it works! (probably because the result is a tooltip, not an in-file span) -- problem: weird concatenations with memfs:/ in the middle -- problem: weird concatenations with ^/memfs/ts-nul-authority in the middle - -question: where is the population of sample-folder with a bunch of files happening? - -question: Is that location writable while it's running? - -but readFile is getting called with things like memfs:/sample-folder/memfs:/typesMap.json - directoryExists with /sample-folder/node_modules/@types and /node_modules/@types - same for watchDirectory - watchDirectory with /sample-folder/^ and directoryExists with /sample-folder/^/memfs/ts-nul-authority/sample-folder/workspaces/ - watchFile with /sample-folder/memfs:/sample-folder/memfs:/lib.es2020.full.d.ts - -### LATER: - -OK, so the paths that tsserver has look like this: ^/scheme/mount/whatever.ts -but the paths the filesystem has look like this: scheme:/whatever.ts (not sure about 'mount', that's only when cloning from the fs) -so you have to shave off the scheme that the host combined with the path and put on the scheme that the vfs is using. - -### LATER 2: - -Some commands ask for getExecutingFilePath or getCurrentDirectory and cons up a path themselves. -This works, because URI.from({ scheme, path }) matches what the fs has in it -Problem: In *some* messages (all?), vscode then refers to /x.ts and ^/vscode-test-web/mount/x.ts (or ^/memfs/ts-nul-authority/x.ts) +For regular `.ts` files, instead of going through Tsserver's type acquisition, +a separate `AutoInstallerFs` is used to create a "virtual" `node_modules` that +extracts desired packages on demand, to an underlying `MemFs`. This will +happen any time a filesystem operation is done inside a `node_modules` folder +across any project in the workspace, and will use the "real" `package.json` +(and, if present, `package-lock.json`) to resolve the dependency tree. +A fallback is then set up such that when a URI like +`memfs:/path/to/node_modules/lodash/lodash.d.ts` is accessed, that gets +redirected to +`vscode-node-modules:/ts-nul-authority/memfs/ts-nul-authority/path/to/node_modules/lodash/lodash.d.ts`, +which will be sent to the `AutoInstallerFs`. diff --git a/extensions/typescript-language-features/web/jsTyping.ts b/extensions/typescript-language-features/web/jsTyping.ts new file mode 100644 index 0000000000000..bd940e88c1c37 --- /dev/null +++ b/extensions/typescript-language-features/web/jsTyping.ts @@ -0,0 +1,78 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +/// Utilities copied from ts.JsTyping internals + +export const enum NameValidationResult { + Ok, + EmptyName, + NameTooLong, + NameStartsWithDot, + NameStartsWithUnderscore, + NameContainsNonURISafeCharacters +} + +type PackageNameValidationResult = NameValidationResult | ScopedPackageNameValidationResult; + +interface ScopedPackageNameValidationResult { + readonly name: string; + readonly isScopeName: boolean; + readonly result: NameValidationResult; +} + +enum CharacterCodes { + _ = 0x5F, + dot = 0x2E, +} + +const maxPackageNameLength = 214; + +// Validates package name using rules defined at https://docs.npmjs.com/files/package.json +// Copied from typescript/jsTypings.ts +export function validatePackageNameWorker(packageName: string, supportScopedPackage: true): ScopedPackageNameValidationResult; +export function validatePackageNameWorker(packageName: string, supportScopedPackage: false): NameValidationResult; +export function validatePackageNameWorker(packageName: string, supportScopedPackage: boolean): PackageNameValidationResult { + if (!packageName) { + return NameValidationResult.EmptyName; + } + if (packageName.length > maxPackageNameLength) { + return NameValidationResult.NameTooLong; + } + if (packageName.charCodeAt(0) === CharacterCodes.dot) { + return NameValidationResult.NameStartsWithDot; + } + if (packageName.charCodeAt(0) === CharacterCodes._) { + return NameValidationResult.NameStartsWithUnderscore; + } + + // check if name is scope package like: starts with @ and has one '/' in the middle + // scoped packages are not currently supported + if (supportScopedPackage) { + const matches = /^@([^/]+)\/([^/]+)$/.exec(packageName); + if (matches) { + const scopeResult = validatePackageNameWorker(matches[1], /*supportScopedPackage*/ false); + if (scopeResult !== NameValidationResult.Ok) { + return { name: matches[1], isScopeName: true, result: scopeResult }; + } + const packageResult = validatePackageNameWorker(matches[2], /*supportScopedPackage*/ false); + if (packageResult !== NameValidationResult.Ok) { + return { name: matches[2], isScopeName: false, result: packageResult }; + } + return NameValidationResult.Ok; + } + } + + if (encodeURIComponent(packageName) !== packageName) { + return NameValidationResult.NameContainsNonURISafeCharacters; + } + + return NameValidationResult.Ok; +} + +export interface TypingResolutionHost { + directoryExists(path: string): boolean; + fileExists(fileName: string): boolean; + readFile(path: string, encoding?: string): string | undefined; + readDirectory(rootDir: string, extensions: readonly string[], excludes: readonly string[] | undefined, includes: readonly string[] | undefined, depth?: number): string[]; +} diff --git a/extensions/typescript-language-features/web/tsconfig.json b/extensions/typescript-language-features/web/tsconfig.json index 9944d5b63d8f9..531d57bddcbff 100644 --- a/extensions/typescript-language-features/web/tsconfig.json +++ b/extensions/typescript-language-features/web/tsconfig.json @@ -2,8 +2,7 @@ "extends": "../../tsconfig.base.json", "compilerOptions": { "outDir": "../../out", - "module": "nodenext", - "moduleDetection": "legacy", + "esModuleInterop": true, "experimentalDecorators": true, "types": [ "node" diff --git a/extensions/typescript-language-features/web/typingsInstaller.ts b/extensions/typescript-language-features/web/typingsInstaller.ts new file mode 100644 index 0000000000000..4ae480c895840 --- /dev/null +++ b/extensions/typescript-language-features/web/typingsInstaller.ts @@ -0,0 +1,213 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/* + * This file implements the global typings installer API for web clients. It + * uses [nassun](https://docs.rs/nassun) and + * [node-maintainer](https://docs.rs/node-maintainer) to install typings + * in-memory (and maybe eventually cache them in IndexedDB?). + * + * Implementing a typings installer involves implementing two parts: + * + * -> ITypingsInstaller: the "top level" interface that tsserver uses to + * request typings. Implementers of this interface are what actually get + * passed to tsserver. + * + * -> TypingsInstaller: an abstract class that implements a good chunk of + * the "generic" functionality for what ITypingsInstaller needs to do. For + * implementation detail reasons, it does this in a "server/client" model of + * sorts. In our case, we don't need a separate process, or even _quite_ a + * pure "server/client" model, so we play along a bit for the sake of reusing + * the stuff the abstract class is already doing for us. + */ + +import * as ts from 'typescript/lib/tsserverlibrary'; +import { join } from 'path'; +import { NameValidationResult, validatePackageNameWorker } from './jsTyping'; +import { PackageManager, PackageType } from '../package-manager/packageManager'; + +type InstallerResponse = ts.server.PackageInstalledResponse | ts.server.SetTypings | ts.server.InvalidateCachedTypings | ts.server.BeginInstallTypes | ts.server.EndInstallTypes; + +/** + * The "server" part of the "server/client" model. This is the part that + * actually gets instantiated and passed to tsserver. + */ +export default class WebTypingsInstallerClient implements ts.server.ITypingsInstaller { + + private projectService: ts.server.ProjectService | undefined; + + private requestedRegistry = false; + + private typesRegistryCache: Map> = new Map(); + + private readonly server: Promise; + + constructor( + private readonly fs: ts.server.ServerHost, + readonly globalTypingsCacheLocation: string, + ) { + this.server = WebTypingsInstallerServer.initialize( + (response: InstallerResponse) => this.handleResponse(response), + this.fs, + globalTypingsCacheLocation + ); + } + + /** + * TypingsInstaller expects a "server/client" model, and as such, some of + * its methods are implemented in terms of sending responses back to a + * client. This method is a catch-all for those responses generated by + * TypingsInstaller internals. + */ + private async handleResponse(response: InstallerResponse): Promise { + switch (response.kind) { + case 'action::packageInstalled': + case 'action::invalidate': + case 'action::set': + this.projectService!.updateTypingsForProject(response); + break; + case 'event::beginInstallTypes': + case 'event::endInstallTypes': + // Don't care. + break; + default: + throw new Error(`unexpected response: ${response}`); + } + } + + // NB(kmarchan): this is a code action that expects an actual NPM-specific + // installation. We shouldn't mess with this ourselves. + async installPackage(_options: ts.server.InstallPackageOptionsWithProject): Promise { + throw new Error('not implemented'); + } + + // NB(kmarchan): As far as I can tell, this is only ever used for + // completions? + isKnownTypesPackageName(packageName: string): boolean { + console.log('isKnownTypesPackageName', packageName); + const looksLikeValidName = validatePackageNameWorker(packageName, true); + if (looksLikeValidName.result !== NameValidationResult.Ok) { + return false; + } + + if (this.requestedRegistry) { + return !!this.typesRegistryCache && this.typesRegistryCache.has(packageName); + } + + this.requestedRegistry = true; + this.server.then(s => this.typesRegistryCache = s.typesRegistry); + return false; + } + + enqueueInstallTypingsRequest(p: ts.server.Project, typeAcquisition: ts.TypeAcquisition, unresolvedImports: ts.SortedReadonlyArray): void { + console.log('enqueueInstallTypingsRequest', typeAcquisition, unresolvedImports); + const req = ts.server.createInstallTypingsRequest(p, typeAcquisition, unresolvedImports); + this.server.then(s => s.install(req)); + } + + attach(projectService: ts.server.ProjectService): void { + this.projectService = projectService; + } + + onProjectClosed(_projectService: ts.server.Project): void { + // noop + } +} + +/** + * Internal implementation of the "server" part of the "server/client" model. + * This takes advantage of the existing TypingsInstaller to reuse a lot of + * already-implemented logic around package installation, but with + * installation details handled by Nassun/Node Maintainer. + */ +class WebTypingsInstallerServer extends ts.server.typingsInstaller.TypingsInstaller { + + private static readonly typesRegistryPackageName = 'types-registry'; + + private constructor( + override typesRegistry: Map>, + private readonly handleResponse: (response: InstallerResponse) => void, + fs: ts.server.ServerHost, + private readonly packageManager: PackageManager, + globalTypingsCachePath: string, + ) { + super(fs, globalTypingsCachePath, join(globalTypingsCachePath, 'fakeSafeList') as ts.Path, join(globalTypingsCachePath, 'fakeTypesMapLocation') as ts.Path, Infinity); + } + + /** + * Because loading the typesRegistry is an async operation for us, we need + * to have a separate "constructor" that will be used by + * WebTypingsInstallerClient. + * + * @returns a promise that resolves to a WebTypingsInstallerServer + */ + static async initialize( + handleResponse: (response: InstallerResponse) => void, + fs: ts.server.ServerHost, + globalTypingsCachePath: string, + ): Promise { + const pm = new PackageManager(fs); + const pkgJson = join(globalTypingsCachePath, 'package.json'); + if (!fs.fileExists(pkgJson)) { + fs.writeFile(pkgJson, '{"private":true}'); + } + const resolved = await pm.resolveProject(globalTypingsCachePath, { + addPackages: [this.typesRegistryPackageName] + }); + await resolved.restore(); + + const registry = new Map>(); + const indexPath = join(globalTypingsCachePath, 'node_modules/types-registry/index.json'); + const index = WebTypingsInstallerServer.readJson(fs, indexPath); + for (const [packageName, entry] of Object.entries(index.entries)) { + registry.set(packageName, entry as ts.MapLike); + } + console.log('ATA registry loaded'); + return new WebTypingsInstallerServer(registry, handleResponse, fs, pm, globalTypingsCachePath); + } + + /** + * Implements the actual logic of installing a set of given packages. It + * does this by looking up the latest versions of those packages using + * Nassun, then handing Node Maintainer the updated package.json to run a + * full install (modulo existing lockfiles, which can make this faster). + */ + protected override installWorker(requestId: number, packageNames: string[], cwd: string, onRequestCompleted: ts.server.typingsInstaller.RequestCompletedAction): void { + console.log('installWorker', requestId, cwd); + (async () => { + try { + const resolved = await this.packageManager.resolveProject(cwd, { + addPackages: packageNames, + packageType: PackageType.DevDependency + }); + await resolved.restore(); + onRequestCompleted(true); + } catch (e) { + onRequestCompleted(false); + } + })(); + } + + /** + * This is a thing that TypingsInstaller uses internally to send + * responses, and we'll need to handle this in the Client later. + */ + protected override sendResponse(response: InstallerResponse): void { + this.handleResponse(response); + } + + /** + * What it says on the tin. Reads a JSON file from the given path. Throws + * if the file doesn't exist (as opposed to returning `undefined`, like + * fs.readFile does). + */ + private static readJson(fs: ts.server.ServerHost, path: string): any { + const data = fs.readFile(path); + if (!data) { + throw new Error('Failed to read file: ' + path); + } + return JSON.parse(data.trim()); + } +} diff --git a/extensions/typescript-language-features/web/webServer.ts b/extensions/typescript-language-features/web/webServer.ts index 1db00fe2a9d4c..40209d3c79638 100644 --- a/extensions/typescript-language-features/web/webServer.ts +++ b/extensions/typescript-language-features/web/webServer.ts @@ -5,10 +5,12 @@ /// /// -import * as ts from 'typescript/lib/tsserverlibrary'; -import { ApiClient, FileType, Requests } from '@vscode/sync-api-client'; +import { ApiClient, FileStat, FileSystem, FileType, Requests } from '@vscode/sync-api-client'; import { ClientConnection } from '@vscode/sync-api-common/browser'; +import { basename } from 'path'; +import * as ts from 'typescript/lib/tsserverlibrary'; import { URI } from 'vscode-uri'; +import WebTypingsInstaller from './typingsInstaller'; // GLOBALS const watchFiles: Map = new Map(); @@ -68,7 +70,7 @@ function updateWatch(event: 'create' | 'change' | 'delete', uri: URI, extensionU type ServerHostWithImport = ts.server.ServerHost & { importPlugin(root: string, moduleName: string): Promise }; -function createServerHost(extensionUri: URI, logger: ts.server.Logger, apiClient: ApiClient | undefined, args: string[], fsWatcher: MessagePort): ServerHostWithImport { +function createServerHost(extensionUri: URI, logger: ts.server.Logger, apiClient: ApiClient | undefined, args: string[], fsWatcher: MessagePort, enabledExperimentalTypeAcquisition: boolean): ServerHostWithImport { const currentDirectory = '/'; const fs = apiClient?.vscode.workspace.fileSystem; let watchId = 0; @@ -80,7 +82,6 @@ function createServerHost(extensionUri: URI, logger: ts.server.Logger, apiClient const directorySeparator: string = (ts as any).directorySeparator; const executingFilePath = findArgument(args, '--executingFilePath') || location + ''; const getExecutingDirectoryPath = memoize(() => memoize(() => ensureTrailingDirectorySeparator(getDirectoryPath(executingFilePath)))); - // Later we could map ^memfs:/ to do something special if we want to enable more functionality like module resolution or something like that const getWebPath = (path: string) => path.startsWith(directorySeparator) ? path.replace(directorySeparator, getExecutingDirectoryPath()) : undefined; const textDecoder = new TextDecoder(); @@ -101,32 +102,50 @@ function createServerHost(extensionUri: URI, logger: ts.server.Logger, apiClient return { close() { } }; } + console.log('watching file:', path); + logVerbose('fs.watchFile', { path }); watchFiles.set(path, { path, callback, pollingInterval, options }); - watchId++; - fsWatcher.postMessage({ type: 'watchFile', uri: toResource(path), id: watchId }); + const watchIds = [++watchId]; + const res = toResource(path); + fsWatcher.postMessage({ type: 'watchFile', uri: res, id: watchIds[0] }); + if (enabledExperimentalTypeAcquisition && looksLikeNodeModules(path)) { + watchIds.push(++watchId); + fsWatcher.postMessage({ type: 'watchFile', uri: mapUri(res, 'vscode-node-modules'), id: watchIds[1] }); + } return { close() { logVerbose('fs.watchFile.close', { path }); watchFiles.delete(path); - fsWatcher.postMessage({ type: 'dispose', id: watchId }); + for (const id of watchIds) { + fsWatcher.postMessage({ type: 'dispose', id }); + } } }; }, watchDirectory(path: string, callback: ts.DirectoryWatcherCallback, recursive?: boolean, options?: ts.WatchOptions): ts.FileWatcher { logVerbose('fs.watchDirectory', { path }); + console.log('watching dir:', path); + watchDirectories.set(path, { path, callback, recursive, options }); - watchId++; - fsWatcher.postMessage({ type: 'watchDirectory', recursive, uri: toResource(path), id: watchId }); + const watchIds = [++watchId]; + const res = toResource(path); + fsWatcher.postMessage({ type: 'watchDirectory', recursive, uri: res, id: watchIds[0] }); + if (enabledExperimentalTypeAcquisition && looksLikeNodeModules(path)) { + watchIds.push(++watchId); + fsWatcher.postMessage({ type: 'watchDirectory', uri: mapUri(res, 'vscode-node-modules'), id: watchIds[1] }); + } return { close() { logVerbose('fs.watchDirectory.close', { path }); watchDirectories.delete(path); - fsWatcher.postMessage({ type: 'dispose', id: watchId }); + for (const id of watchIds) { + fsWatcher.postMessage({ type: 'dispose', id }); + } } }; }, @@ -190,14 +209,28 @@ function createServerHost(extensionUri: URI, logger: ts.server.Logger, apiClient } } + let uri; + try { + uri = toResource(path); + } catch (e) { + return undefined; + } + + let contents: Uint8Array | undefined; try { // We need to slice the bytes since we can't pass a shared array to text decoder - const contents = fs.readFile(toResource(path)).slice(); - return textDecoder.decode(contents); + contents = fs.readFile(uri); } catch (error) { - logNormal('Error fs.readFile', { path, error: error + '' }); - return undefined; + if (!enabledExperimentalTypeAcquisition) { + return undefined; + } + try { + contents = fs.readFile(mapUri(uri, 'vscode-node-modules')); + } catch (e) { + return undefined; + } } + return textDecoder.decode(contents.slice()); }, getFileSize(path) { logVerbose('fs.getFileSize', { path }); @@ -206,12 +239,19 @@ function createServerHost(extensionUri: URI, logger: ts.server.Logger, apiClient throw new Error('not supported'); } + const uri = toResource(path); + let ret = 0; try { - return fs.stat(toResource(path)).size; - } catch (error) { - logNormal('Error fs.getFileSize', { path, error: error + '' }); - return 0; + ret = fs.stat(uri).size; + } catch (_error) { + if (enabledExperimentalTypeAcquisition) { + try { + ret = fs.stat(mapUri(uri, 'vscode-node-modules')).size; + } catch (_error) { + } + } } + return ret; }, writeFile(path, data, writeByteOrderMark) { logVerbose('fs.writeFile', { path }); @@ -224,10 +264,21 @@ function createServerHost(extensionUri: URI, logger: ts.server.Logger, apiClient data = byteOrderMarkIndicator + data; } + let uri; try { - fs.writeFile(toResource(path), textEncoder.encode(data)); + uri = toResource(path); + } catch (e) { + return; + } + const encoded = textEncoder.encode(data); + try { + fs.writeFile(uri, encoded); + const name = basename(uri.path); + if (uri.scheme !== 'vscode-global-typings' && (name === 'package.json' || name === 'package-lock.json' || name === 'package-lock.kdl')) { + fs.writeFile(mapUri(uri, 'vscode-node-modules'), encoded); + } } catch (error) { - logNormal('Error fs.writeFile', { path, error: error + '' }); + console.error('fs.writeFile', { path, error }); } }, resolvePath(path: string): string { @@ -248,12 +299,24 @@ function createServerHost(extensionUri: URI, logger: ts.server.Logger, apiClient return request.status === 200; } + let uri; try { - return fs.stat(toResource(path)).type === FileType.File; - } catch (error) { - logNormal('Error fs.fileExists', { path, error: error + '' }); + uri = toResource(path); + } catch (e) { return false; } + let ret = false; + try { + ret = fs.stat(uri).type === FileType.File; + } catch (_error) { + if (enabledExperimentalTypeAcquisition) { + try { + ret = fs.stat(mapUri(uri, 'vscode-node-modules')).type === FileType.File; + } catch (_error) { + } + } + } + return ret; }, directoryExists(path: string): boolean { logVerbose('fs.directoryExists', { path }); @@ -262,10 +325,32 @@ function createServerHost(extensionUri: URI, logger: ts.server.Logger, apiClient return false; } + let uri; try { - return fs.stat(toResource(path)).type === FileType.Directory; - } catch (error) { - logNormal('Error fs.directoryExists', { path, error: error + '' }); + uri = toResource(path); + } catch (_error) { + return false; + } + + let stat: FileStat | undefined = undefined; + try { + stat = fs.stat(uri); + } catch (_error) { + if (enabledExperimentalTypeAcquisition) { + try { + stat = fs.stat(mapUri(uri, 'vscode-node-modules')); + } catch (_error) { + } + } + } + if (stat) { + if (path.startsWith('/https') && !path.endsWith('.d.ts')) { + // TODO: Hack, https "file system" can't actually tell what is a file vs directory + return stat.type === FileType.File || stat.type === FileType.Directory; + } + + return stat.type === FileType.Directory; + } else { return false; } }, @@ -301,12 +386,19 @@ function createServerHost(extensionUri: URI, logger: ts.server.Logger, apiClient throw new Error('not supported'); } + const uri = toResource(path); + let s: FileStat | undefined = undefined; try { - return new Date(fs.stat(toResource(path)).mtime); - } catch (error) { - logNormal('Error fs.getModifiedTime', { path, error: error + '' }); - return undefined; + s = fs.stat(uri); + } catch (_e) { + if (enabledExperimentalTypeAcquisition) { + try { + s = fs.stat(mapUri(uri, 'vscode-node-modules')); + } catch (_e) { + } + } } + return s && new Date(s.mtime); }, deleteFile(path: string): void { logVerbose('fs.deleteFile', { path }); @@ -333,13 +425,19 @@ function createServerHost(extensionUri: URI, logger: ts.server.Logger, apiClient base64encode: input => Buffer.from(input).toString('base64'), }; - /** For module resolution only; symlinks aren't supported yet. */ + // For module resolution only. `node_modules` is also automatically mapped + // as if all node_modules-like paths are symlinked. function realpath(path: string): string { - // skip paths without .. or ./ or /. - if (!path.match(/\.\.|\/\.|\.\//)) { + const isNm = looksLikeNodeModules(path) && !path.startsWith('/vscode-global-typings/'); + // skip paths without .. or ./ or /. And things that look like node_modules + if (!isNm && !path.match(/\.\.|\/\.|\.\//)) { return path; } - const uri = toResource(path); + + let uri = toResource(path); + if (isNm) { + uri = mapUri(uri, 'vscode-node-modules'); + } const out = [uri.scheme]; if (uri.authority) { out.push(uri.authority); } for (const part of uri.path.split('/')) { @@ -363,31 +461,35 @@ function createServerHost(extensionUri: URI, logger: ts.server.Logger, apiClient throw new Error('not supported'); } + const uri = toResource(path || '.'); + let entries: [string, FileType][] = []; + const files: string[] = []; + const directories: string[] = []; try { - const uri = toResource(path || '.'); - const entries = fs.readDirectory(uri); - const files: string[] = []; - const directories: string[] = []; - for (const [entry, type] of entries) { - // This is necessary because on some file system node fails to exclude - // '.' and '..'. See https://github.com/nodejs/node/issues/4002 - if (entry === '.' || entry === '..') { - continue; - } + entries = fs.readDirectory(uri); + } catch (_e) { + try { + entries = fs.readDirectory(mapUri(uri, 'vscode-node-modules')); + } catch (_e) { + } + } + for (const [entry, type] of entries) { + // This is necessary because on some file system node fails to exclude + // '.' and '..'. See https://github.com/nodejs/node/issues/4002 + if (entry === '.' || entry === '..') { + continue; + } - if (type === FileType.File) { - files.push(entry); - } - else if (type === FileType.Directory) { - directories.push(entry); - } + if (type === FileType.File) { + files.push(entry); + } + else if (type === FileType.Directory) { + directories.push(entry); } - files.sort(); - directories.sort(); - return { files, directories }; - } catch (e) { - return { files: [], directories: [] }; } + files.sort(); + directories.sort(); + return { files, directories }; } /** @@ -435,6 +537,10 @@ function looksLikeLibDtsPath(filepath: string) { return filepath.startsWith('/lib.') && filepath.endsWith('.d.ts'); } +function looksLikeNodeModules(filepath: string) { + return filepath.includes('/node_modules'); +} + function filePathToResourceUri(filepath: string): URI | undefined { const parts = filepath.match(/^\/([^\/]+)\/([^\/]*)(?:\/(.+))?$/); if (!parts) { @@ -469,14 +575,15 @@ class WasmCancellationToken implements ts.server.ServerCancellationToken { } interface StartSessionOptions { - globalPlugins: ts.server.SessionOptions['globalPlugins']; - pluginProbeLocations: ts.server.SessionOptions['pluginProbeLocations']; - allowLocalPluginLoads: ts.server.SessionOptions['allowLocalPluginLoads']; - useSingleInferredProject: ts.server.SessionOptions['useSingleInferredProject']; - useInferredProjectPerProjectRoot: ts.server.SessionOptions['useInferredProjectPerProjectRoot']; - suppressDiagnosticEvents: ts.server.SessionOptions['suppressDiagnosticEvents']; - noGetErrOnBackgroundUpdate: ts.server.SessionOptions['noGetErrOnBackgroundUpdate']; - serverMode: ts.server.SessionOptions['serverMode']; + readonly globalPlugins: ts.server.SessionOptions['globalPlugins']; + readonly pluginProbeLocations: ts.server.SessionOptions['pluginProbeLocations']; + readonly allowLocalPluginLoads: ts.server.SessionOptions['allowLocalPluginLoads']; + readonly useSingleInferredProject: ts.server.SessionOptions['useSingleInferredProject']; + readonly useInferredProjectPerProjectRoot: ts.server.SessionOptions['useInferredProjectPerProjectRoot']; + readonly suppressDiagnosticEvents: ts.server.SessionOptions['suppressDiagnosticEvents']; + readonly noGetErrOnBackgroundUpdate: ts.server.SessionOptions['noGetErrOnBackgroundUpdate']; + readonly serverMode: ts.server.SessionOptions['serverMode']; + readonly disableAutomaticTypingAcquisition: boolean; } class WorkerSession extends ts.server.Session<{}> { @@ -486,17 +593,20 @@ class WorkerSession extends ts.server.Session<{}> { constructor( host: ts.server.ServerHost, + fs: FileSystem | undefined, options: StartSessionOptions, - public readonly port: MessagePort, + private readonly port: MessagePort, logger: ts.server.Logger, hrtime: ts.server.SessionOptions['hrtime'] ) { const cancellationToken = new WasmCancellationToken(); + const typingsInstaller = options.disableAutomaticTypingAcquisition || !fs ? ts.server.nullTypingsInstaller : new WebTypingsInstaller(host, '/vscode-global-typings/ts-nul-authority/projects'); + super({ host, cancellationToken, ...options, - typingsInstaller: ts.server.nullTypingsInstaller, // TODO: Someday! + typingsInstaller, byteLength: () => { throw new Error('Not implemented'); }, // Formats the message text in send of Session which is overridden in this class so not needed hrtime, logger, @@ -631,7 +741,7 @@ async function initializeSession(args: string[], extensionUri: URI, ports: { tss logger.info(`Version: 0.0.0`); logger.info(`Arguments: ${args.join(' ')}`); logger.info(`ServerMode: ${serverMode} unknownServerMode: ${unknownServerMode}`); - const options = { + const options: StartSessionOptions = { globalPlugins: findArgumentStringArray(args, '--globalPlugins'), pluginProbeLocations: findArgumentStringArray(args, '--pluginProbeLocations'), allowLocalPluginLoads: hasArgument(args, '--allowLocalPluginLoads'), @@ -639,22 +749,27 @@ async function initializeSession(args: string[], extensionUri: URI, ports: { tss useInferredProjectPerProjectRoot: hasArgument(args, '--useInferredProjectPerProjectRoot'), suppressDiagnosticEvents: hasArgument(args, '--suppressDiagnosticEvents'), noGetErrOnBackgroundUpdate: hasArgument(args, '--noGetErrOnBackgroundUpdate'), - serverMode + serverMode, + disableAutomaticTypingAcquisition: hasArgument(args, '--disableAutomaticTypingAcquisition'), }; + let sys: ServerHostWithImport; + let fs: FileSystem | undefined; if (hasArgument(args, '--enableProjectWideIntelliSenseOnWeb')) { + const enabledExperimentalTypeAcquisition = hasArgument(args, '--experimentalTypeAcquisition'); const connection = new ClientConnection(ports.sync); await connection.serviceReady(); - sys = createServerHost(extensionUri, logger, new ApiClient(connection), args, ports.watcher); + const apiClient = new ApiClient(connection); + fs = apiClient.vscode.workspace.fileSystem; + sys = createServerHost(extensionUri, logger, apiClient, args, ports.watcher, enabledExperimentalTypeAcquisition); } else { - sys = createServerHost(extensionUri, logger, undefined, args, ports.watcher); - + sys = createServerHost(extensionUri, logger, undefined, args, ports.watcher, false); } setSys(sys); - session = new WorkerSession(sys, options, ports.tsserver, logger, hrtime); + session = new WorkerSession(sys, fs, options, ports.tsserver, logger, hrtime); session.listen(); } @@ -703,3 +818,15 @@ const listener = async (e: any) => { console.error(`unexpected message on main channel: ${JSON.stringify(e)}`); }; addEventListener('message', listener); + +function mapUri(uri: URI, mappedScheme: string): URI { + if (uri.scheme === 'vscode-global-typings') { + throw new Error('can\'t map vscode-global-typings'); + } + if (!uri.authority) { + uri = uri.with({ authority: 'ts-nul-authority' }); + } + uri = uri.with({ scheme: mappedScheme, path: `/${uri.scheme}/${uri.authority || 'ts-nul-authority'}${uri.path}` }); + + return uri; +} diff --git a/extensions/typescript-language-features/yarn.lock b/extensions/typescript-language-features/yarn.lock index a86d12d0e3fff..245b73893db31 100644 --- a/extensions/typescript-language-features/yarn.lock +++ b/extensions/typescript-language-features/yarn.lock @@ -4,14 +4,14 @@ "@azure/abort-controller@^1.0.0": version "1.1.0" - resolved "https://registry.yarnpkg.com/@azure/abort-controller/-/abort-controller-1.1.0.tgz#788ee78457a55af8a1ad342acb182383d2119249" + resolved "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.1.0.tgz" integrity sha512-TrRLIoSQVzfAJX9H1JeFjzAoDGcoK1IYX1UImfceTZpsyYfWr09Ss1aHW1y5TrrR3iq6RZLBwJ3E24uwPhwahw== dependencies: tslib "^2.2.0" "@azure/core-auth@^1.4.0": version "1.4.0" - resolved "https://registry.yarnpkg.com/@azure/core-auth/-/core-auth-1.4.0.tgz#6fa9661c1705857820dbc216df5ba5665ac36a9e" + resolved "https://registry.npmjs.org/@azure/core-auth/-/core-auth-1.4.0.tgz" integrity sha512-HFrcTgmuSuukRf/EdPmqBrc5l6Q5Uu+2TbuhaKbgaCpP2TfAeiNaQPAadxO+CYBRHGUzIDteMAjFspFLDLnKVQ== dependencies: "@azure/abort-controller" "^1.0.0" @@ -19,7 +19,7 @@ "@azure/core-rest-pipeline@^1.10.0": version "1.10.1" - resolved "https://registry.yarnpkg.com/@azure/core-rest-pipeline/-/core-rest-pipeline-1.10.1.tgz#348290847ca31b9eecf9cf5de7519aaccdd30968" + resolved "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.10.1.tgz" integrity sha512-Kji9k6TOFRDB5ZMTw8qUf2IJ+CeJtsuMdAHox9eqpTf1cefiNMpzrfnF6sINEBZJsaVaWgQ0o48B6kcUH68niA== dependencies: "@azure/abort-controller" "^1.0.0" @@ -35,14 +35,14 @@ "@azure/core-tracing@^1.0.1": version "1.0.1" - resolved "https://registry.yarnpkg.com/@azure/core-tracing/-/core-tracing-1.0.1.tgz#352a38cbea438c4a83c86b314f48017d70ba9503" + resolved "https://registry.npmjs.org/@azure/core-tracing/-/core-tracing-1.0.1.tgz" integrity sha512-I5CGMoLtX+pI17ZdiFJZgxMJApsK6jjfm85hpgp3oazCdq5Wxgh4wMr7ge/TTWW1B5WBuvIOI1fMU/FrOAMKrw== dependencies: tslib "^2.2.0" "@azure/core-util@^1.0.0": version "1.1.1" - resolved "https://registry.yarnpkg.com/@azure/core-util/-/core-util-1.1.1.tgz#8f87b3dd468795df0f0849d9f096c3e7b29452c1" + resolved "https://registry.npmjs.org/@azure/core-util/-/core-util-1.1.1.tgz" integrity sha512-A4TBYVQCtHOigFb2ETiiKFDocBoI1Zk2Ui1KpI42aJSIDexF7DHQFpnjonltXAIU/ceH+1fsZAWWgvX6/AKzog== dependencies: "@azure/abort-controller" "^1.0.0" @@ -50,14 +50,14 @@ "@azure/logger@^1.0.0": version "1.0.3" - resolved "https://registry.yarnpkg.com/@azure/logger/-/logger-1.0.3.tgz#6e36704aa51be7d4a1bae24731ea580836293c96" + resolved "https://registry.npmjs.org/@azure/logger/-/logger-1.0.3.tgz" integrity sha512-aK4s3Xxjrx3daZr3VylxejK3vG5ExXck5WOHDJ8in/k9AqlfIyFMMT1uG7u8mNjX+QRILTIn0/Xgschfh/dQ9g== dependencies: tslib "^2.2.0" "@microsoft/1ds-core-js@3.2.8", "@microsoft/1ds-core-js@^3.2.8": version "3.2.8" - resolved "https://registry.yarnpkg.com/@microsoft/1ds-core-js/-/1ds-core-js-3.2.8.tgz#1b6b7d9bb858238c818ccf4e4b58ece7aeae5760" + resolved "https://registry.npmjs.org/@microsoft/1ds-core-js/-/1ds-core-js-3.2.8.tgz" integrity sha512-9o9SUAamJiTXIYwpkQDuueYt83uZfXp8zp8YFix1IwVPwC9RmE36T2CX9gXOeq1nDckOuOduYpA8qHvdh5BGfQ== dependencies: "@microsoft/applicationinsights-core-js" "2.8.9" @@ -66,7 +66,7 @@ "@microsoft/1ds-post-js@^3.2.8": version "3.2.8" - resolved "https://registry.yarnpkg.com/@microsoft/1ds-post-js/-/1ds-post-js-3.2.8.tgz#46793842cca161bf7a2a5b6053c349f429e55110" + resolved "https://registry.npmjs.org/@microsoft/1ds-post-js/-/1ds-post-js-3.2.8.tgz" integrity sha512-SjlRoNcXcXBH6WQD/5SkkaCHIVqldH3gDu+bI7YagrOVJ5APxwT1Duw9gm3L1FjFa9S2i81fvJ3EVSKpp9wULA== dependencies: "@microsoft/1ds-core-js" "3.2.8" @@ -75,7 +75,7 @@ "@microsoft/applicationinsights-channel-js@2.8.9": version "2.8.9" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-channel-js/-/applicationinsights-channel-js-2.8.9.tgz#840656f3c716de8b3eb0a98c122aa1b92bb8ebfb" + resolved "https://registry.npmjs.org/@microsoft/applicationinsights-channel-js/-/applicationinsights-channel-js-2.8.9.tgz" integrity sha512-fMBsAEB7pWtPn43y72q9Xy5E5y55r6gMuDQqRRccccVoQDPXyS57VCj5IdATblctru0C6A8XpL2vRyNmEsu0Vg== dependencies: "@microsoft/applicationinsights-common" "2.8.9" @@ -85,7 +85,7 @@ "@microsoft/applicationinsights-common@2.8.9": version "2.8.9" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-common/-/applicationinsights-common-2.8.9.tgz#a75e4a3143a7fd797687830c0ddd2069fd900827" + resolved "https://registry.npmjs.org/@microsoft/applicationinsights-common/-/applicationinsights-common-2.8.9.tgz" integrity sha512-mObn1moElyxZaGIRF/IU3cOaeKMgxghXnYEoHNUCA2e+rNwBIgxjyKkblFIpmGuHf4X7Oz3o3yBWpaC6AoMpig== dependencies: "@microsoft/applicationinsights-core-js" "2.8.9" @@ -94,7 +94,7 @@ "@microsoft/applicationinsights-core-js@2.8.9": version "2.8.9" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.8.9.tgz#0e5d207acfae6986a6fc97249eeb6117e523bf1b" + resolved "https://registry.npmjs.org/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-2.8.9.tgz" integrity sha512-HRuIuZ6aOWezcg/G5VyFDDWGL8hDNe/ljPP01J7ImH2kRPEgbtcfPSUMjkamGMefgdq81GZsSoC/NNGTP4pp2w== dependencies: "@microsoft/applicationinsights-shims" "2.0.2" @@ -102,12 +102,12 @@ "@microsoft/applicationinsights-shims@2.0.2", "@microsoft/applicationinsights-shims@^2.0.2": version "2.0.2" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-shims/-/applicationinsights-shims-2.0.2.tgz#92b36a09375e2d9cb2b4203383b05772be837085" + resolved "https://registry.npmjs.org/@microsoft/applicationinsights-shims/-/applicationinsights-shims-2.0.2.tgz" integrity sha512-PoHEgsnmcqruLNHZ/amACqdJ6YYQpED0KSRe6J7gIJTtpZC1FfFU9b1fmDKDKtFoUSrPzEh1qzO3kmRZP0betg== "@microsoft/applicationinsights-web-basic@^2.8.9": version "2.8.9" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-web-basic/-/applicationinsights-web-basic-2.8.9.tgz#eed2f3d1e19069962ed2155915c1656e6936e1d5" + resolved "https://registry.npmjs.org/@microsoft/applicationinsights-web-basic/-/applicationinsights-web-basic-2.8.9.tgz" integrity sha512-CH0J8JFOy7MjK8JO4pXXU+EML+Ilix+94PMZTX5EJlBU1in+mrik74/8qSg3UC4ekPi12KwrXaHCQSVC3WseXQ== dependencies: "@microsoft/applicationinsights-channel-js" "2.8.9" @@ -118,29 +118,29 @@ "@microsoft/applicationinsights-web-snippet@^1.0.1": version "1.0.1" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-web-snippet/-/applicationinsights-web-snippet-1.0.1.tgz#6bb788b2902e48bf5d460c38c6bb7fedd686ddd7" + resolved "https://registry.npmjs.org/@microsoft/applicationinsights-web-snippet/-/applicationinsights-web-snippet-1.0.1.tgz" integrity sha512-2IHAOaLauc8qaAitvWS+U931T+ze+7MNWrDHY47IENP5y2UA0vqJDu67kWZDdpCN1fFC77sfgfB+HV7SrKshnQ== "@microsoft/dynamicproto-js@^1.1.7": version "1.1.7" - resolved "https://registry.yarnpkg.com/@microsoft/dynamicproto-js/-/dynamicproto-js-1.1.7.tgz#ede48dd3f85af14ee369c805e5ed5b84222b9fe2" + resolved "https://registry.npmjs.org/@microsoft/dynamicproto-js/-/dynamicproto-js-1.1.7.tgz" integrity sha512-SK3D3aVt+5vOOccKPnGaJWB5gQ8FuKfjboUJHedMP7gu54HqSCXX5iFXhktGD8nfJb0Go30eDvs/UDoTnR2kOA== "@opentelemetry/api@^1.0.4": version "1.2.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.2.0.tgz#89ef99401cde6208cff98760b67663726ef26686" + resolved "https://registry.npmjs.org/@opentelemetry/api/-/api-1.2.0.tgz" integrity sha512-0nBr+VZNKm9tvNDZFstI3Pq1fCTEDK5OZTnVKNvBNAKgd0yIvmwsP4m61rEv7ZP+tOUjWJhROpxK5MsnlF911g== "@opentelemetry/core@1.7.0", "@opentelemetry/core@^1.0.1": version "1.7.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.7.0.tgz#83bdd1b7a4ceafcdffd6590420657caec5f7b34c" + resolved "https://registry.npmjs.org/@opentelemetry/core/-/core-1.7.0.tgz" integrity sha512-AVqAi5uc8DrKJBimCTFUT4iFI+5eXpo4sYmGbQ0CypG0piOTHE2g9c5aSoTGYXu3CzOmJZf7pT6Xh+nwm5d6yQ== dependencies: "@opentelemetry/semantic-conventions" "1.7.0" "@opentelemetry/resources@1.7.0": version "1.7.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-1.7.0.tgz#90ccd3a6a86b4dfba4e833e73944bd64958d78c5" + resolved "https://registry.npmjs.org/@opentelemetry/resources/-/resources-1.7.0.tgz" integrity sha512-u1M0yZotkjyKx8dj+46Sg5thwtOTBmtRieNXqdCRiWUp6SfFiIP0bI+1XK3LhuXqXkBXA1awJZaTqKduNMStRg== dependencies: "@opentelemetry/core" "1.7.0" @@ -148,7 +148,7 @@ "@opentelemetry/sdk-trace-base@^1.0.1": version "1.7.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.7.0.tgz#b498424e0c6340a9d80de63fd408c5c2130a60a5" + resolved "https://registry.npmjs.org/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.7.0.tgz" integrity sha512-Iz84C+FVOskmauh9FNnj4+VrA+hG5o+tkMzXuoesvSfunVSioXib0syVFeNXwOm4+M5GdWCuW632LVjqEXStIg== dependencies: "@opentelemetry/core" "1.7.0" @@ -157,27 +157,27 @@ "@opentelemetry/semantic-conventions@1.7.0", "@opentelemetry/semantic-conventions@^1.0.1": version "1.7.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.7.0.tgz#af80a1ef7cf110ea3a68242acd95648991bcd763" + resolved "https://registry.npmjs.org/@opentelemetry/semantic-conventions/-/semantic-conventions-1.7.0.tgz" integrity sha512-FGBx/Qd09lMaqQcogCHyYrFEpTx4cAjeS+48lMIR12z7LdH+zofGDVQSubN59nL6IpubfKqTeIDu9rNO28iHVA== "@tootallnate/once@2": version "2.0.0" - resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf" + resolved "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz" integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A== "@types/node@16.x": version "16.11.6" - resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.6.tgz#6bef7a2a0ad684cf6e90fcfe31cecabd9ce0a3ae" + resolved "https://registry.npmjs.org/@types/node/-/node-16.11.6.tgz" integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w== "@types/semver@^5.5.0": version "5.5.0" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-5.5.0.tgz#146c2a29ee7d3bae4bf2fcb274636e264c813c45" + resolved "https://registry.npmjs.org/@types/semver/-/semver-5.5.0.tgz" integrity sha512-41qEJgBH/TWgo5NFSvBCJ1qkoi3Q6ONSF2avrHq1LVEZfYpdHmj0y9SuTK+u9ZhG1sYQKBL1AWXKyLWP4RaUoQ== "@vscode/extension-telemetry@0.7.5": version "0.7.5" - resolved "https://registry.yarnpkg.com/@vscode/extension-telemetry/-/extension-telemetry-0.7.5.tgz#bf965731816e08c3f146f96d901ec67954fc913b" + resolved "https://registry.npmjs.org/@vscode/extension-telemetry/-/extension-telemetry-0.7.5.tgz" integrity sha512-fJ5y3TcpqqkFYHneabYaoB4XAhDdVflVm+TDKshw9VOs77jkgNS4UA7LNXrWeO0eDne3Sh3JgURf+xzc1rk69w== dependencies: "@microsoft/1ds-core-js" "^3.2.8" @@ -187,7 +187,7 @@ "@vscode/sync-api-client@^0.7.2": version "0.7.2" - resolved "https://registry.yarnpkg.com/@vscode/sync-api-client/-/sync-api-client-0.7.2.tgz#0644bff66a5eff636bcd8eb483d34796b9f90d2d" + resolved "https://registry.npmjs.org/@vscode/sync-api-client/-/sync-api-client-0.7.2.tgz" integrity sha512-HQHz57RVKmR8sTEen1Y/T3r6mzDX7IaUJz/O2RJkn0Qu9ThvCsakLP0N+1iiwPnPfUfmNSwQXbSw8bEQFPcpYQ== dependencies: "@vscode/sync-api-common" "0.7.2" @@ -195,12 +195,12 @@ "@vscode/sync-api-common@0.7.2", "@vscode/sync-api-common@^0.7.2": version "0.7.2" - resolved "https://registry.yarnpkg.com/@vscode/sync-api-common/-/sync-api-common-0.7.2.tgz#705060ee6a0108c24e145e687613becdb4292b33" + resolved "https://registry.npmjs.org/@vscode/sync-api-common/-/sync-api-common-0.7.2.tgz" integrity sha512-ne1XEeDIYA3mp4oo1QoF1fqFedd0Vf4ybMmLb9HixbTyXy/qwMNL2p6OjXjOsmx6w2q9eqzGA5W/OPRSJxTTIQ== "@vscode/sync-api-service@^0.7.3": version "0.7.3" - resolved "https://registry.yarnpkg.com/@vscode/sync-api-service/-/sync-api-service-0.7.3.tgz#6cb7bd23c4a7378e4b92ca3638501a9be1937152" + resolved "https://registry.npmjs.org/@vscode/sync-api-service/-/sync-api-service-0.7.3.tgz" integrity sha512-m2AmmfG4uzfjLMgWRHQ3xnBkdwCiUTO68vdw1XuzMsOb39Jwm9xr5bVVxwOFR9lPC0FfO1H6FUxBhZQvg7itPA== dependencies: "@vscode/sync-api-common" "0.7.2" @@ -208,14 +208,14 @@ agent-base@6: version "6.0.2" - resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" + resolved "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz" integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ== dependencies: debug "4" applicationinsights@2.4.1: version "2.4.1" - resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-2.4.1.tgz#4de4c4dd3c7c4a44445cfbf3d15808fc0dcc423d" + resolved "https://registry.npmjs.org/applicationinsights/-/applicationinsights-2.4.1.tgz" integrity sha512-0n0Ikd0gzSm460xm+M0UTWIwXrhrH/0bqfZatcJjYObWyefxfAxapGEyNnSGd1Tg90neHz+Yhf+Ff/zgvPiQYA== dependencies: "@azure/core-auth" "^1.4.0" @@ -232,14 +232,14 @@ applicationinsights@2.4.1: async-hook-jl@^1.7.6: version "1.7.6" - resolved "https://registry.yarnpkg.com/async-hook-jl/-/async-hook-jl-1.7.6.tgz#4fd25c2f864dbaf279c610d73bf97b1b28595e68" + resolved "https://registry.npmjs.org/async-hook-jl/-/async-hook-jl-1.7.6.tgz" integrity sha512-gFaHkFfSxTjvoxDMYqDuGHlcRyUuamF8s+ZTtJdDzqjws4mCt7v0vuV79/E2Wr2/riMQgtG4/yUtXWs1gZ7JMg== dependencies: stack-chain "^1.3.7" async-listener@^0.6.0: version "0.6.10" - resolved "https://registry.yarnpkg.com/async-listener/-/async-listener-0.6.10.tgz#a7c97abe570ba602d782273c0de60a51e3e17cbc" + resolved "https://registry.npmjs.org/async-listener/-/async-listener-0.6.10.tgz" integrity sha512-gpuo6xOyF4D5DE5WvyqZdPA3NGhiT6Qf07l7DCB0wwDEsLvDIbCr6j9S5aj5Ch96dLace5tXVzWBZkxU/c5ohw== dependencies: semver "^5.3.0" @@ -247,19 +247,19 @@ async-listener@^0.6.0: asynckit@^0.4.0: version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + resolved "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz" integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== axios@^0.26.1: version "0.26.1" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.26.1.tgz#1ede41c51fcf51bbbd6fd43669caaa4f0495aaa9" + resolved "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz" integrity sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA== dependencies: follow-redirects "^1.14.8" cls-hooked@^4.2.2: version "4.2.2" - resolved "https://registry.yarnpkg.com/cls-hooked/-/cls-hooked-4.2.2.tgz#ad2e9a4092680cdaffeb2d3551da0e225eae1908" + resolved "https://registry.npmjs.org/cls-hooked/-/cls-hooked-4.2.2.tgz" integrity sha512-J4Xj5f5wq/4jAvcdgoGsL3G103BtWpZrMo8NEinRltN+xpTZdI+M38pyQqhuFU/P792xkMFvnKSf+Lm81U1bxw== dependencies: async-hook-jl "^1.7.6" @@ -268,14 +268,14 @@ cls-hooked@^4.2.2: combined-stream@^1.0.8: version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + resolved "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz" integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== dependencies: delayed-stream "~1.0.0" continuation-local-storage@^3.2.1: version "3.2.1" - resolved "https://registry.yarnpkg.com/continuation-local-storage/-/continuation-local-storage-3.2.1.tgz#11f613f74e914fe9b34c92ad2d28fe6ae1db7ffb" + resolved "https://registry.npmjs.org/continuation-local-storage/-/continuation-local-storage-3.2.1.tgz" integrity sha512-jx44cconVqkCEEyLSKWwkvUXwO561jXMa3LPjTPsm5QR22PA0/mhe33FT4Xb5y74JDvt/Cq+5lm8S8rskLv9ZA== dependencies: async-listener "^0.6.0" @@ -283,43 +283,43 @@ continuation-local-storage@^3.2.1: debug@4: version "4.3.4" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" delayed-stream@~1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + resolved "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz" integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== diagnostic-channel-publishers@1.0.5: version "1.0.5" - resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-1.0.5.tgz#df8c317086c50f5727fdfb5d2fce214d2e4130ae" + resolved "https://registry.npmjs.org/diagnostic-channel-publishers/-/diagnostic-channel-publishers-1.0.5.tgz" integrity sha512-dJwUS0915pkjjimPJVDnS/QQHsH0aOYhnZsLJdnZIMOrB+csj8RnZhWTuwnm8R5v3Z7OZs+ksv5luC14DGB7eg== diagnostic-channel@1.1.0: version "1.1.0" - resolved "https://registry.yarnpkg.com/diagnostic-channel/-/diagnostic-channel-1.1.0.tgz#6985e9dfedfbc072d91dc4388477e4087147756e" + resolved "https://registry.npmjs.org/diagnostic-channel/-/diagnostic-channel-1.1.0.tgz" integrity sha512-fwujyMe1gj6rk6dYi9hMZm0c8Mz8NDMVl2LB4iaYh3+LIAThZC8RKFGXWG0IML2OxAit/ZFRgZhMkhQ3d/bobQ== dependencies: semver "^5.3.0" emitter-listener@^1.0.1, emitter-listener@^1.1.1: version "1.1.2" - resolved "https://registry.yarnpkg.com/emitter-listener/-/emitter-listener-1.1.2.tgz#56b140e8f6992375b3d7cb2cab1cc7432d9632e8" + resolved "https://registry.npmjs.org/emitter-listener/-/emitter-listener-1.1.2.tgz" integrity sha512-Bt1sBAGFHY9DKY+4/2cV6izcKJUf5T7/gkdmkxzX/qv9CcGH8xSwVRW5mtX03SWJtRTWSOpzCuWN9rBFYZepZQ== dependencies: shimmer "^1.2.0" follow-redirects@^1.14.8: version "1.15.1" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.1.tgz#0ca6a452306c9b276e4d3127483e29575e207ad5" + resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz" integrity sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA== form-data@^4.0.0: version "4.0.0" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + resolved "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz" integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== dependencies: asynckit "^0.4.0" @@ -328,7 +328,7 @@ form-data@^4.0.0: http-proxy-agent@^5.0.0: version "5.0.0" - resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43" + resolved "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz" integrity sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w== dependencies: "@tootallnate/once" "2" @@ -337,7 +337,7 @@ http-proxy-agent@^5.0.0: https-proxy-agent@^5.0.0: version "5.0.1" - resolved "https://registry.yarnpkg.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz#c59ef224a04fe8b754f3db0063a25ea30d0005d6" + resolved "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz" integrity sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA== dependencies: agent-base "6" @@ -345,71 +345,74 @@ https-proxy-agent@^5.0.0: jsonc-parser@^3.2.0: version "3.2.0" - resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.0.tgz#31ff3f4c2b9793f89c67212627c51c6394f88e76" + resolved "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz" integrity sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w== mime-db@1.52.0: version "1.52.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + resolved "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== mime-types@^2.1.12: version "2.1.35" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + resolved "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== dependencies: mime-db "1.52.0" ms@2.1.2: version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +"node-maintainer@file:node-maintainer": + version "0.1.0" + semver@5.5.1: version "5.5.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.1.tgz#7dfdd8814bdb7cabc7be0fb1d734cfb66c940477" + resolved "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz" integrity sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw== semver@^5.3.0, semver@^5.4.1: version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + resolved "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== shimmer@^1.1.0, shimmer@^1.2.0: version "1.2.1" - resolved "https://registry.yarnpkg.com/shimmer/-/shimmer-1.2.1.tgz#610859f7de327b587efebf501fb43117f9aff337" + resolved "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz" integrity sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw== stack-chain@^1.3.7: version "1.3.7" - resolved "https://registry.yarnpkg.com/stack-chain/-/stack-chain-1.3.7.tgz#d192c9ff4ea6a22c94c4dd459171e3f00cea1285" + resolved "https://registry.npmjs.org/stack-chain/-/stack-chain-1.3.7.tgz" integrity sha512-D8cWtWVdIe/jBA7v5p5Hwl5yOSOrmZPWDPe2KxQ5UAGD+nxbxU0lKXA4h85Ta6+qgdKVL3vUxsbIZjc1kBG7ug== tas-client@0.1.58: version "0.1.58" - resolved "https://registry.yarnpkg.com/tas-client/-/tas-client-0.1.58.tgz#67d66bf0e27df5276ebc751105e6ad47791c36d8" + resolved "https://registry.npmjs.org/tas-client/-/tas-client-0.1.58.tgz" integrity sha512-fOWii4wQXuo9Zl0oXgvjBzZWzKc5MmUR6XQWX93WU2c1SaP1plPo/zvXP8kpbZ9fvegFOHdapszYqMTRq/SRtg== dependencies: axios "^0.26.1" tslib@^2.2.0: version "2.4.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.1.tgz#0d0bfbaac2880b91e22df0768e55be9753a5b17e" + resolved "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz" integrity sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA== uuid@^8.3.0: version "8.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + resolved "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== vscode-tas-client@^0.1.63: version "0.1.63" - resolved "https://registry.yarnpkg.com/vscode-tas-client/-/vscode-tas-client-0.1.63.tgz#df89e67e9bf7ecb46471a0fb8a4a522d2aafad65" + resolved "https://registry.npmjs.org/vscode-tas-client/-/vscode-tas-client-0.1.63.tgz" integrity sha512-TY5TPyibzi6rNmuUB7eRVqpzLzNfQYrrIl/0/F8ukrrbzOrKVvS31hM3urE+tbaVrnT+TMYXL16GhX57vEowhA== dependencies: tas-client "0.1.58" vscode-uri@3.0.3, vscode-uri@^3.0.3: version "3.0.3" - resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.0.3.tgz#a95c1ce2e6f41b7549f86279d19f47951e4f4d84" + resolved "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.0.3.tgz" integrity sha512-EcswR2S8bpR7fD0YPeS7r2xXExrScVMxg4MedACaWHEtx9ftCF/qHG1xGkolzTPcEmjTavCQgbVzHUIdTMzFGA==