esm - backport worker related changes (#225672)

This commit is contained in:
Benjamin Pasero
2024-08-15 13:46:45 +02:00
committed by GitHub
parent 0aad4fe8d6
commit fdc8d882e2
36 changed files with 619 additions and 358 deletions

View File

@@ -131,7 +131,7 @@ function createESMSourcesAndResources2(options) {
}
if (file === 'tsconfig.json') {
const tsConfig = JSON.parse(fs.readFileSync(path.join(SRC_FOLDER, file)).toString());
tsConfig.compilerOptions.module = 'es6';
tsConfig.compilerOptions.module = 'es2022';
tsConfig.compilerOptions.outDir = path.join(path.relative(OUT_FOLDER, OUT_RESOURCES_FOLDER), 'vs').replace(/\\/g, '/');
write(getDestAbsoluteFilePath(file), JSON.stringify(tsConfig, null, '\t'));
continue;

View File

@@ -157,7 +157,7 @@ export function createESMSourcesAndResources2(options: IOptions2): void {
if (file === 'tsconfig.json') {
const tsConfig = JSON.parse(fs.readFileSync(path.join(SRC_FOLDER, file)).toString());
tsConfig.compilerOptions.module = 'es6';
tsConfig.compilerOptions.module = 'es2022';
tsConfig.compilerOptions.outDir = path.join(path.relative(OUT_FOLDER, OUT_RESOURCES_FOLDER), 'vs').replace(/\\/g, '/');
write(getDestAbsoluteFilePath(file), JSON.stringify(tsConfig, null, '\t'));
continue;

124
src/bootstrap-amd.js vendored
View File

@@ -11,20 +11,16 @@
* @import { IProductConfiguration } from './vs/base/common/product'
*/
// ESM-comment-begin
const isESM = false;
// ESM-comment-end
// ESM-uncomment-begin
// import * as path from 'path';
// import * as fs from 'fs';
// import { fileURLToPath } from 'url';
// import { createRequire, register } from 'node:module';
// import { product, pkg } from './bootstrap-meta.js';
// import * as bootstrapNode from './bootstrap-node.js';
// import './bootstrap-node.js';
// import * as performance from './vs/base/common/performance.js';
//
// const require = createRequire(import.meta.url);
// const isESM = true;
// const module = { exports: {} };
// const __dirname = path.dirname(fileURLToPath(import.meta.url));
//
@@ -171,77 +167,77 @@ async function doSetupNLS() {
//#region Loader Config
if (isESM) {
// ESM-uncomment-begin
// /**
// * @param {string=} entrypoint
// * @param {(value: any) => void} [onLoad]
// * @param {(err: Error) => void} [onError]
// */
// module.exports.load = function (entrypoint, onLoad, onError) {
// if (!entrypoint) {
// return;
// }
/**
* @param {string=} entrypoint
* @param {(value: any) => void} [onLoad]
* @param {(err: Error) => void} [onError]
*/
module.exports.load = function (entrypoint, onLoad, onError) {
if (!entrypoint) {
return;
}
// entrypoint = `./${entrypoint}.js`;
entrypoint = `./${entrypoint}.js`;
// onLoad = onLoad || function () { };
// onError = onError || function (err) { console.error(err); };
onLoad = onLoad || function () { };
onError = onError || function (err) { console.error(err); };
// setupNLS().then(() => {
// performance.mark(`code/fork/willLoadCode`);
// import(entrypoint).then(onLoad, onError);
// });
// };
// ESM-uncomment-end
setupNLS().then(() => {
performance.mark(`code/fork/willLoadCode`);
import(entrypoint).then(onLoad, onError);
});
};
} else {
// ESM-comment-begin
// @ts-ignore
const loader = require('./vs/loader');
// @ts-ignore
const loader = require('./vs/loader');
loader.config({
baseUrl: bootstrapNode.fileUriFromPath(__dirname, { isWindows: process.platform === 'win32' }),
catchError: true,
nodeRequire,
amdModulesPattern: /^vs\//,
recordStats: true
});
loader.config({
baseUrl: bootstrapNode.fileUriFromPath(__dirname, { isWindows: process.platform === 'win32' }),
catchError: true,
nodeRequire,
amdModulesPattern: /^vs\//,
recordStats: true
// Running in Electron
if (process.env['ELECTRON_RUN_AS_NODE'] || process.versions['electron']) {
loader.define('fs', ['original-fs'], function (/** @type {import('fs')} */originalFS) {
return originalFS; // replace the patched electron fs with the original node fs for all AMD code
});
}
// Running in Electron
if (process.env['ELECTRON_RUN_AS_NODE'] || process.versions['electron']) {
loader.define('fs', ['original-fs'], function (/** @type {import('fs')} */originalFS) {
return originalFS; // replace the patched electron fs with the original node fs for all AMD code
/**
* @param {string=} entrypoint
* @param {(value: any) => void} [onLoad]
* @param {(err: Error) => void} [onError]
*/
module.exports.load = function (entrypoint, onLoad, onError) {
if (!entrypoint) {
return;
}
// code cache config
if (process.env['VSCODE_CODE_CACHE_PATH']) {
loader.config({
nodeCachedData: {
path: process.env['VSCODE_CODE_CACHE_PATH'],
seed: entrypoint
}
});
}
/**
* @param {string=} entrypoint
* @param {(value: any) => void} [onLoad]
* @param {(err: Error) => void} [onError]
*/
module.exports.load = function (entrypoint, onLoad, onError) {
if (!entrypoint) {
return;
}
onLoad = onLoad || function () { };
onError = onError || function (err) { console.error(err); };
// code cache config
if (process.env['VSCODE_CODE_CACHE_PATH']) {
loader.config({
nodeCachedData: {
path: process.env['VSCODE_CODE_CACHE_PATH'],
seed: entrypoint
}
});
}
onLoad = onLoad || function () { };
onError = onError || function (err) { console.error(err); };
setupNLS().then(() => {
performance.mark('code/fork/willLoadCode');
loader([entrypoint], onLoad, onError);
});
};
}
setupNLS().then(() => {
performance.mark('code/fork/willLoadCode');
loader([entrypoint], onLoad, onError);
});
};
// ESM-comment-end
//#endregion

83
src/bootstrap-node.js vendored
View File

@@ -10,18 +10,12 @@
const path = require('path');
const fs = require('fs');
const Module = require('module');
const isESM = false;
// ESM-comment-end
// ESM-uncomment-begin
// import * as path from 'path';
// import * as fs from 'fs';
// import { fileURLToPath } from 'url';
// import { createRequire } from 'node:module';
//
// const require = createRequire(import.meta.url);
// const Module = require('module');
// const isESM = true;
// const module = { exports: {} };
// const __dirname = path.dirname(fileURLToPath(import.meta.url));
// ESM-uncomment-end
@@ -86,32 +80,31 @@ module.exports.devInjectNodeModuleLookupPath = function (injectPath) {
}
const Module = require('node:module');
if (isESM) {
// register a loader hook
// ESM-uncomment-begin
// Module.register('./bootstrap-import.js', { parentURL: import.meta.url, data: injectPath });
// ESM-uncomment-end
} else {
const nodeModulesPath = path.join(__dirname, '../node_modules');
// ESM-uncomment-begin
// // register a loader hook
// Module.register('./bootstrap-import.js', { parentURL: import.meta.url, data: injectPath });
// ESM-uncomment-end
// ESM-comment-begin
const nodeModulesPath = path.join(__dirname, '../node_modules');
// @ts-ignore
const originalResolveLookupPaths = Module._resolveLookupPaths;
// @ts-ignore
const originalResolveLookupPaths = Module._resolveLookupPaths;
// @ts-ignore
Module._resolveLookupPaths = function (moduleName, parent) {
const paths = originalResolveLookupPaths(moduleName, parent);
if (Array.isArray(paths)) {
for (let i = 0, len = paths.length; i < len; i++) {
if (paths[i] === nodeModulesPath) {
paths.splice(i, 0, injectPath);
break;
}
// @ts-ignore
Module._resolveLookupPaths = function (moduleName, parent) {
const paths = originalResolveLookupPaths(moduleName, parent);
if (Array.isArray(paths)) {
for (let i = 0, len = paths.length; i < len; i++) {
if (paths[i] === nodeModulesPath) {
paths.splice(i, 0, injectPath);
break;
}
}
}
return paths;
};
}
return paths;
};
// ESM-comment-end
};
module.exports.removeGlobalNodeModuleLookupPaths = function () {
@@ -207,30 +200,28 @@ module.exports.configurePortable = function (product) {
* Helper to enable ASAR support.
*/
module.exports.enableASARSupport = function () {
if (isESM) {
return; // TODO@esm ASAR support is disabled in ESM
} else {
const NODE_MODULES_PATH = path.join(__dirname, '../node_modules');
const NODE_MODULES_ASAR_PATH = `${NODE_MODULES_PATH}.asar`;
// ESM-comment-begin
const NODE_MODULES_PATH = path.join(__dirname, '../node_modules');
const NODE_MODULES_ASAR_PATH = `${NODE_MODULES_PATH}.asar`;
// @ts-ignore
const originalResolveLookupPaths = Module._resolveLookupPaths;
// @ts-ignore
const originalResolveLookupPaths = Module._resolveLookupPaths;
// @ts-ignore
Module._resolveLookupPaths = function (request, parent) {
const paths = originalResolveLookupPaths(request, parent);
if (Array.isArray(paths)) {
for (let i = 0, len = paths.length; i < len; i++) {
if (paths[i] === NODE_MODULES_PATH) {
paths.splice(i, 0, NODE_MODULES_ASAR_PATH);
break;
}
// @ts-ignore
Module._resolveLookupPaths = function (request, parent) {
const paths = originalResolveLookupPaths(request, parent);
if (Array.isArray(paths)) {
for (let i = 0, len = paths.length; i < len; i++) {
if (paths[i] === NODE_MODULES_PATH) {
paths.splice(i, 0, NODE_MODULES_ASAR_PATH);
break;
}
}
}
return paths;
};
}
return paths;
};
// ESM-comment-end
};
/**

View File

@@ -15,13 +15,6 @@
/* eslint-disable no-restricted-globals */
// ESM-comment-begin
const isESM = false;
// ESM-comment-end
// ESM-uncomment-begin
// const isESM = true;
// ESM-uncomment-end
(function (factory) {
// @ts-ignore
globalThis.MonacoBootstrapWindow = factory();
@@ -95,133 +88,133 @@ const isESM = false;
window['MonacoEnvironment'] = {};
if (isESM) {
// ESM-uncomment-begin
// // Signal before require()
// if (typeof options?.beforeRequire === 'function') {
// options.beforeRequire(configuration);
// }
// Signal before require()
if (typeof options?.beforeRequire === 'function') {
options.beforeRequire(configuration);
}
// const baseUrl = new URL(`${fileUriFromPath(configuration.appRoot, { isWindows: safeProcess.platform === 'win32', scheme: 'vscode-file', fallbackAuthority: 'vscode-app' })}/out/`);
// globalThis._VSCODE_FILE_ROOT = baseUrl.toString();
const baseUrl = new URL(`${fileUriFromPath(configuration.appRoot, { isWindows: safeProcess.platform === 'win32', scheme: 'vscode-file', fallbackAuthority: 'vscode-app' })}/out/`);
globalThis._VSCODE_FILE_ROOT = baseUrl.toString();
// // DEV ---------------------------------------------------------------------------------------
// // DEV: This is for development and enables loading CSS via import-statements via import-maps.
// // DEV: For each CSS modules that we have we defined an entry in the import map that maps to
// // DEV: a blob URL that loads the CSS via a dynamic @import-rule.
// // DEV ---------------------------------------------------------------------------------------
// if (Array.isArray(configuration.cssModules) && configuration.cssModules.length > 0) {
// performance.mark('code/willAddCssLoader');
// DEV ---------------------------------------------------------------------------------------
// DEV: This is for development and enables loading CSS via import-statements via import-maps.
// DEV: For each CSS modules that we have we defined an entry in the import map that maps to
// DEV: a blob URL that loads the CSS via a dynamic @import-rule.
// DEV ---------------------------------------------------------------------------------------
if (Array.isArray(configuration.cssModules) && configuration.cssModules.length > 0) {
performance.mark('code/willAddCssLoader');
// const style = document.createElement('style');
// style.type = 'text/css';
// style.media = 'screen';
// style.id = 'vscode-css-loading';
// document.head.appendChild(style);
const style = document.createElement('style');
style.type = 'text/css';
style.media = 'screen';
style.id = 'vscode-css-loading';
document.head.appendChild(style);
// globalThis._VSCODE_CSS_LOAD = function (url) {
// style.textContent += `@import url(${url});\n`;
// };
globalThis._VSCODE_CSS_LOAD = function (url) {
style.textContent += `@import url(${url});\n`;
};
// /**
// * @type { { imports: Record<string, string> }}
// */
// const importMap = { imports: {} };
// for (const cssModule of configuration.cssModules) {
// const cssUrl = new URL(cssModule, baseUrl).href;
// const jsSrc = `globalThis._VSCODE_CSS_LOAD('${cssUrl}');\n`;
// const blob = new Blob([jsSrc], { type: 'application/javascript' });
// importMap.imports[cssUrl] = URL.createObjectURL(blob);
// }
/**
* @type { { imports: Record<string, string> }}
*/
const importMap = { imports: {} };
for (const cssModule of configuration.cssModules) {
const cssUrl = new URL(cssModule, baseUrl).href;
const jsSrc = `globalThis._VSCODE_CSS_LOAD('${cssUrl}');\n`;
const blob = new Blob([jsSrc], { type: 'application/javascript' });
importMap.imports[cssUrl] = URL.createObjectURL(blob);
// const ttp = window.trustedTypes?.createPolicy('vscode-bootstrapImportMap', { createScript(value) { return value; }, });
// const importMapSrc = JSON.stringify(importMap, undefined, 2);
// const importMapScript = document.createElement('script');
// importMapScript.type = 'importmap';
// importMapScript.setAttribute('nonce', '0c6a828f1297');
// // @ts-ignore
// importMapScript.textContent = ttp?.createScript(importMapSrc) ?? importMapSrc;
// document.head.appendChild(importMapScript);
// performance.mark('code/didAddCssLoader');
// }
// const result = Promise.all(modulePaths.map(modulePath => {
// if (modulePath.includes('vs/css!')) {
// // ESM/CSS when seeing the old `vs/css!` prefix we use that as a signal to
// // load CSS via a <link> tag
// const cssModule = modulePath.replace('vs/css!', '');
// const link = document.createElement('link');
// link.rel = 'stylesheet';
// link.href = new URL(`${cssModule}.css`, baseUrl).href;
// document.head.appendChild(link);
// return Promise.resolve();
// } else {
// // ESM/JS module loading
// return import(new URL(`${modulePath}.js`, baseUrl).href);
// }
// }));
// result.then((res) => invokeResult(res[0]), onUnexpectedError);
// ESM-uncomment-end
// ESM-comment-begin
/** @type {LoaderConfig} */
const loaderConfig = {
baseUrl: `${fileUriFromPath(configuration.appRoot, { isWindows: safeProcess.platform === 'win32', scheme: 'vscode-file', fallbackAuthority: 'vscode-app' })}/out`,
preferScriptTags: true
};
// use a trusted types policy when loading via script tags
loaderConfig.trustedTypesPolicy = window.trustedTypes?.createPolicy('amdLoader', {
createScriptURL(value) {
if (value.startsWith(window.location.origin)) {
return value;
}
const ttp = window.trustedTypes?.createPolicy('vscode-bootstrapImportMap', { createScript(value) { return value; }, });
const importMapSrc = JSON.stringify(importMap, undefined, 2);
const importMapScript = document.createElement('script');
importMapScript.type = 'importmap';
importMapScript.setAttribute('nonce', '0c6a828f1297');
// @ts-ignore
importMapScript.textContent = ttp?.createScript(importMapSrc) ?? importMapSrc;
document.head.appendChild(importMapScript);
performance.mark('code/didAddCssLoader');
throw new Error(`Invalid script url: ${value}`);
}
});
const result = Promise.all(modulePaths.map(modulePath => {
if (modulePath.includes('vs/css!')) {
// ESM/CSS when seeing the old `vs/css!` prefix we use that as a signal to
// load CSS via a <link> tag
const cssModule = modulePath.replace('vs/css!', '');
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = new URL(`${cssModule}.css`, baseUrl).href;
document.head.appendChild(link);
return Promise.resolve();
// Teach the loader the location of the node modules we use in renderers
// This will enable to load these modules via <script> tags instead of
// using a fallback such as node.js require which does not exist in sandbox
const baseNodeModulesPath = isDev ? '../node_modules' : '../node_modules.asar';
loaderConfig.paths = {
'@vscode/tree-sitter-wasm': `${baseNodeModulesPath}/@vscode/tree-sitter-wasm/wasm/tree-sitter.js`,
'vscode-textmate': `${baseNodeModulesPath}/vscode-textmate/release/main.js`,
'vscode-oniguruma': `${baseNodeModulesPath}/vscode-oniguruma/release/main.js`,
'vsda': `${baseNodeModulesPath}/vsda/index.js`,
'@xterm/xterm': `${baseNodeModulesPath}/@xterm/xterm/lib/xterm.js`,
'@xterm/addon-clipboard': `${baseNodeModulesPath}/@xterm/addon-clipboard/lib/addon-clipboard.js`,
'@xterm/addon-image': `${baseNodeModulesPath}/@xterm/addon-image/lib/addon-image.js`,
'@xterm/addon-search': `${baseNodeModulesPath}/@xterm/addon-search/lib/addon-search.js`,
'@xterm/addon-serialize': `${baseNodeModulesPath}/@xterm/addon-serialize/lib/addon-serialize.js`,
'@xterm/addon-unicode11': `${baseNodeModulesPath}/@xterm/addon-unicode11/lib/addon-unicode11.js`,
'@xterm/addon-webgl': `${baseNodeModulesPath}/@xterm/addon-webgl/lib/addon-webgl.js`,
'@vscode/iconv-lite-umd': `${baseNodeModulesPath}/@vscode/iconv-lite-umd/lib/iconv-lite-umd.js`,
'jschardet': `${baseNodeModulesPath}/jschardet/dist/jschardet.min.js`,
'@vscode/vscode-languagedetection': `${baseNodeModulesPath}/@vscode/vscode-languagedetection/dist/lib/index.js`,
'vscode-regexp-languagedetection': `${baseNodeModulesPath}/vscode-regexp-languagedetection/dist/index.js`,
'tas-client-umd': `${baseNodeModulesPath}/tas-client-umd/lib/tas-client-umd.js`
};
} else {
// ESM/JS module loading
return import(new URL(`${modulePath}.js`, baseUrl).href);
}
}));
result.then((res) => invokeResult(res[0]), onUnexpectedError);
} else {
/** @type {LoaderConfig} */
const loaderConfig = {
baseUrl: `${fileUriFromPath(configuration.appRoot, { isWindows: safeProcess.platform === 'win32', scheme: 'vscode-file', fallbackAuthority: 'vscode-app' })}/out`,
preferScriptTags: true
};
// use a trusted types policy when loading via script tags
loaderConfig.trustedTypesPolicy = window.trustedTypes?.createPolicy('amdLoader', {
createScriptURL(value) {
if (value.startsWith(window.location.origin)) {
return value;
}
throw new Error(`Invalid script url: ${value}`);
}
});
// Teach the loader the location of the node modules we use in renderers
// This will enable to load these modules via <script> tags instead of
// using a fallback such as node.js require which does not exist in sandbox
const baseNodeModulesPath = isDev ? '../node_modules' : '../node_modules.asar';
loaderConfig.paths = {
'@vscode/tree-sitter-wasm': `${baseNodeModulesPath}/@vscode/tree-sitter-wasm/wasm/tree-sitter.js`,
'vscode-textmate': `${baseNodeModulesPath}/vscode-textmate/release/main.js`,
'vscode-oniguruma': `${baseNodeModulesPath}/vscode-oniguruma/release/main.js`,
'vsda': `${baseNodeModulesPath}/vsda/index.js`,
'@xterm/xterm': `${baseNodeModulesPath}/@xterm/xterm/lib/xterm.js`,
'@xterm/addon-clipboard': `${baseNodeModulesPath}/@xterm/addon-clipboard/lib/addon-clipboard.js`,
'@xterm/addon-image': `${baseNodeModulesPath}/@xterm/addon-image/lib/addon-image.js`,
'@xterm/addon-search': `${baseNodeModulesPath}/@xterm/addon-search/lib/addon-search.js`,
'@xterm/addon-serialize': `${baseNodeModulesPath}/@xterm/addon-serialize/lib/addon-serialize.js`,
'@xterm/addon-unicode11': `${baseNodeModulesPath}/@xterm/addon-unicode11/lib/addon-unicode11.js`,
'@xterm/addon-webgl': `${baseNodeModulesPath}/@xterm/addon-webgl/lib/addon-webgl.js`,
'@vscode/iconv-lite-umd': `${baseNodeModulesPath}/@vscode/iconv-lite-umd/lib/iconv-lite-umd.js`,
'jschardet': `${baseNodeModulesPath}/jschardet/dist/jschardet.min.js`,
'@vscode/vscode-languagedetection': `${baseNodeModulesPath}/@vscode/vscode-languagedetection/dist/lib/index.js`,
'vscode-regexp-languagedetection': `${baseNodeModulesPath}/vscode-regexp-languagedetection/dist/index.js`,
'tas-client-umd': `${baseNodeModulesPath}/tas-client-umd/lib/tas-client-umd.js`
};
// Signal before require.config()
if (typeof options?.beforeLoaderConfig === 'function') {
options.beforeLoaderConfig(loaderConfig);
}
// Configure loader
require.config(loaderConfig);
// Signal before require()
if (typeof options?.beforeRequire === 'function') {
options.beforeRequire(configuration);
}
// Actually require the main module as specified
require(modulePaths, invokeResult, onUnexpectedError);
// Signal before require.config()
if (typeof options?.beforeLoaderConfig === 'function') {
options.beforeLoaderConfig(loaderConfig);
}
// Configure loader
require.config(loaderConfig);
// Signal before require()
if (typeof options?.beforeRequire === 'function') {
options.beforeRequire(configuration);
}
// Actually require the main module as specified
require(modulePaths, invokeResult, onUnexpectedError);
// ESM-comment-end
/**
* @param {any} firstModule
*/

View File

@@ -5,9 +5,18 @@
import { createTrustedTypesPolicy } from 'vs/base/browser/trustedTypes';
import { onUnexpectedError } from 'vs/base/common/errors';
import { COI } from 'vs/base/common/network';
import { AppResourcePath, COI, FileAccess } from 'vs/base/common/network';
import { URI } from 'vs/base/common/uri';
import { IWorker, IWorkerCallback, IWorkerFactory, logOnceWebWorkerWarning } from 'vs/base/common/worker/simpleWorker';
import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
import { coalesce } from 'vs/base/common/arrays';
// ESM-comment-begin
const isESM = false;
// ESM-comment-end
// ESM-uncomment-begin
// const isESM = true;
// ESM-uncomment-end
// Reuse the trusted types policy defined from worker bootstrap
// when available.
@@ -23,10 +32,10 @@ export function createBlobWorker(blobUrl: string, options?: WorkerOptions): Work
if (!blobUrl.startsWith('blob:')) {
throw new URIError('Not a blob-url: ' + blobUrl);
}
return new Worker(ttPolicy ? ttPolicy.createScriptURL(blobUrl) as unknown as string : blobUrl, options);
return new Worker(ttPolicy ? ttPolicy.createScriptURL(blobUrl) as unknown as string : blobUrl, { ...options, type: isESM ? 'module' : undefined });
}
function getWorker(label: string): Worker | Promise<Worker> {
function getWorker(workerMainLocation: URI | undefined, label: string): Worker | Promise<Worker> {
// Option for hosts to overwrite the worker script (used in the standalone editor)
interface IMonacoEnvironment {
getWorker?(moduleId: string, label: string): Worker | Promise<Worker>;
@@ -39,56 +48,76 @@ function getWorker(label: string): Worker | Promise<Worker> {
}
if (typeof monacoEnvironment.getWorkerUrl === 'function') {
const workerUrl = monacoEnvironment.getWorkerUrl('workerMain.js', label);
return new Worker(ttPolicy ? ttPolicy.createScriptURL(workerUrl) as unknown as string : workerUrl, { name: label });
return new Worker(ttPolicy ? ttPolicy.createScriptURL(workerUrl) as unknown as string : workerUrl, { name: label, type: isESM ? 'module' : undefined });
}
}
// ESM-comment-begin
if (typeof require === 'function') {
// check if the JS lives on a different origin
const workerMain = require.toUrl('vs/base/worker/workerMain.js'); // explicitly using require.toUrl(), see https://github.com/microsoft/vscode/issues/107440#issuecomment-698982321
const workerUrl = getWorkerBootstrapUrl(workerMain, label);
return new Worker(ttPolicy ? ttPolicy.createScriptURL(workerUrl) as unknown as string : workerUrl, { name: label });
const workerMainLocation = require.toUrl('vs/base/worker/workerMain.js'); // explicitly using require.toUrl(), see https://github.com/microsoft/vscode/issues/107440#issuecomment-698982321
const factoryModuleId = 'vs/base/worker/defaultWorkerFactory.js';
const workerBaseUrl = require.toUrl(factoryModuleId).slice(0, -factoryModuleId.length); // explicitly using require.toUrl(), see https://github.com/microsoft/vscode/issues/107440#issuecomment-698982321
const workerUrl = getWorkerBootstrapUrl(label, workerMainLocation, workerBaseUrl);
return new Worker(ttPolicy ? ttPolicy.createScriptURL(workerUrl) as unknown as string : workerUrl, { name: label, type: isESM ? 'module' : undefined });
}
// ESM-comment-end
if (workerMainLocation) {
const workerUrl = getWorkerBootstrapUrl(label, workerMainLocation.toString(true));
const worker = new Worker(ttPolicy ? ttPolicy.createScriptURL(workerUrl) as unknown as string : workerUrl, { name: label, type: isESM ? 'module' : undefined });
if (isESM) {
return whenESMWorkerReady(worker);
} else {
return worker;
}
}
throw new Error(`You must define a function MonacoEnvironment.getWorkerUrl or MonacoEnvironment.getWorker`);
}
// ESM-comment-begin
export function getWorkerBootstrapUrl(scriptPath: string, label: string): string {
if (/^((http:)|(https:)|(file:))/.test(scriptPath) && scriptPath.substring(0, globalThis.origin.length) !== globalThis.origin) {
function getWorkerBootstrapUrl(label: string, workerScriptUrl: string, workerBaseUrl?: string): string {
if (/^((http:)|(https:)|(file:))/.test(workerScriptUrl) && workerScriptUrl.substring(0, globalThis.origin.length) !== globalThis.origin) {
// this is the cross-origin case
// i.e. the webpage is running at a different origin than where the scripts are loaded from
} else {
const start = scriptPath.lastIndexOf('?');
const end = scriptPath.lastIndexOf('#', start);
const start = workerScriptUrl.lastIndexOf('?');
const end = workerScriptUrl.lastIndexOf('#', start);
const params = start > 0
? new URLSearchParams(scriptPath.substring(start + 1, ~end ? end : undefined))
? new URLSearchParams(workerScriptUrl.substring(start + 1, ~end ? end : undefined))
: new URLSearchParams();
COI.addSearchParam(params, true, true);
const search = params.toString();
if (!search) {
scriptPath = `${scriptPath}#${label}`;
workerScriptUrl = `${workerScriptUrl}#${label}`;
} else {
scriptPath = `${scriptPath}?${params.toString()}#${label}`;
workerScriptUrl = `${workerScriptUrl}?${params.toString()}#${label}`;
}
}
const factoryModuleId = 'vs/base/worker/defaultWorkerFactory.js';
const workerBaseUrl = require.toUrl(factoryModuleId).slice(0, -factoryModuleId.length); // explicitly using require.toUrl(), see https://github.com/microsoft/vscode/issues/107440#issuecomment-698982321
const blob = new Blob([[
const blob = new Blob([coalesce([
`/*${label}*/`,
`globalThis.MonacoEnvironment = { baseUrl: '${workerBaseUrl}' };`,
workerBaseUrl ? `globalThis.MonacoEnvironment = { baseUrl: '${workerBaseUrl}' };` : undefined,
`globalThis._VSCODE_NLS_MESSAGES = ${JSON.stringify(globalThis._VSCODE_NLS_MESSAGES)};`,
`globalThis._VSCODE_NLS_LANGUAGE = ${JSON.stringify(globalThis._VSCODE_NLS_LANGUAGE)};`,
`globalThis._VSCODE_FILE_ROOT = '${globalThis._VSCODE_FILE_ROOT}';`,
`const ttPolicy = globalThis.trustedTypes?.createPolicy('defaultWorkerFactory', { createScriptURL: value => value });`,
`globalThis.workerttPolicy = ttPolicy;`,
`importScripts(ttPolicy?.createScriptURL('${scriptPath}') ?? '${scriptPath}');`,
isESM ? `await import(ttPolicy?.createScriptURL('${workerScriptUrl}') ?? '${workerScriptUrl}');` : `importScripts(ttPolicy?.createScriptURL('${workerScriptUrl}') ?? '${workerScriptUrl}');`, //
isESM ? `globalThis.postMessage({ type: 'vscode-worker-ready' });` : undefined, // in ESM signal we are ready after the async import
`/*${label}*/`
].join('')], { type: 'application/javascript' });
]).join('')], { type: 'application/javascript' });
return URL.createObjectURL(blob);
}
// ESM-comment-end
function whenESMWorkerReady(worker: Worker): Promise<Worker> {
return new Promise<Worker>((resolve, reject) => {
worker.onmessage = function (e) {
if (e.data.type === 'vscode-worker-ready') {
worker.onmessage = null;
resolve(worker);
}
};
worker.onerror = reject;
});
}
function isPromiseLike<T>(obj: any): obj is PromiseLike<T> {
if (typeof obj.then === 'function') {
@@ -107,11 +136,11 @@ class WebWorker extends Disposable implements IWorker {
private readonly label: string;
private worker: Promise<Worker> | null;
constructor(moduleId: string, id: number, label: string, onMessageCallback: IWorkerCallback, onErrorCallback: (err: any) => void) {
constructor(workerMainLocation: URI | undefined, moduleId: string, id: number, label: string, onMessageCallback: IWorkerCallback, onErrorCallback: (err: any) => void) {
super();
this.id = id;
this.label = label;
const workerOrPromise = getWorker(label);
const workerOrPromise = getWorker(workerMainLocation, label);
if (isPromiseLike(workerOrPromise)) {
this.worker = workerOrPromise;
} else {
@@ -161,19 +190,26 @@ export class DefaultWorkerFactory implements IWorkerFactory {
private _label: string | undefined;
private _webWorkerFailedBeforeError: any;
constructor(label: string | undefined) {
constructor(private readonly workerMainLocation: URI | undefined, label: string | undefined) {
this._label = label;
this._webWorkerFailedBeforeError = false;
}
public create(moduleId: string, onMessageCallback: IWorkerCallback, onErrorCallback: (err: any) => void): IWorker {
public create(modules: { moduleId: string; esmModuleId: string }, onMessageCallback: IWorkerCallback, onErrorCallback: (err: any) => void): IWorker {
const workerId = (++DefaultWorkerFactory.LAST_WORKER_ID);
if (this._webWorkerFailedBeforeError) {
throw this._webWorkerFailedBeforeError;
}
return new WebWorker(moduleId, workerId, this._label || 'anonymous' + workerId, onMessageCallback, (err) => {
let workerMainLocation = this.workerMainLocation;
const moduleId = modules.moduleId;
if (isESM) {
workerMainLocation = FileAccess.asBrowserUri(`${modules.esmModuleId}.esm.js` as AppResourcePath);
}
return new WebWorker(workerMainLocation, moduleId, workerId, this._label || 'anonymous' + workerId, onMessageCallback, (err) => {
logOnceWebWorkerWarning(err);
this._webWorkerFailedBeforeError = err;
onErrorCallback(err);

View File

@@ -253,7 +253,12 @@ class FileAccessImpl {
* **Note:** use `dom.ts#asCSSUrl` whenever the URL is to be used in CSS context.
*/
asBrowserUri(resourcePath: AppResourcePath | ''): URI {
// ESM-comment-begin
const uri = this.toUri(resourcePath, require);
// ESM-comment-end
// ESM-uncomment-begin
// const uri = this.toUri(resourcePath);
// ESM-uncomment-end
return this.uriToBrowserUri(uri);
}
@@ -300,7 +305,12 @@ class FileAccessImpl {
* is responsible for loading.
*/
asFileUri(resourcePath: AppResourcePath | ''): URI {
// ESM-comment-begin
const uri = this.toUri(resourcePath, require);
// ESM-comment-end
// ESM-uncomment-begin
// const uri = this.toUri(resourcePath);
// ESM-uncomment-end
return this.uriToFileUri(uri);
}
@@ -325,12 +335,25 @@ class FileAccessImpl {
return uri;
}
private toUri(uriOrModule: URI | string, moduleIdToUrl: { toUrl(moduleId: string): string }): URI {
private toUri(uriOrModule: URI | string, moduleIdToUrl?: { toUrl(moduleId: string): string }): URI {
if (URI.isUri(uriOrModule)) {
return uriOrModule;
}
return URI.parse(moduleIdToUrl.toUrl(uriOrModule));
if (globalThis._VSCODE_FILE_ROOT) {
const rootUriOrPath = globalThis._VSCODE_FILE_ROOT;
// File URL (with scheme)
if (/^\w[\w\d+.-]*:\/\//.test(rootUriOrPath)) {
return URI.joinPath(URI.parse(rootUriOrPath, true), uriOrModule);
}
// File Path (no scheme)
const modulePath = paths.join(rootUriOrPath, uriOrModule);
return URI.file(modulePath);
}
return URI.parse(moduleIdToUrl!.toUrl(uriOrModule));
}
}

View File

@@ -6,10 +6,18 @@
import { transformErrorForSerialization } from 'vs/base/common/errors';
import { Emitter, Event } from 'vs/base/common/event';
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
import { AppResourcePath, FileAccess } from 'vs/base/common/network';
import { getAllMethodNames } from 'vs/base/common/objects';
import { isWeb } from 'vs/base/common/platform';
import * as strings from 'vs/base/common/strings';
// ESM-comment-begin
const isESM = false;
// ESM-comment-end
// ESM-uncomment-begin
// const isESM = true;
// ESM-uncomment-end
const INITIALIZE = '$initialize';
export interface IWorker extends IDisposable {
@@ -22,7 +30,7 @@ export interface IWorkerCallback {
}
export interface IWorkerFactory {
create(moduleId: string, callback: IWorkerCallback, onErrorCallback: (err: any) => void): IWorker;
create(modules: { moduleId: string; esmModuleId: string }, callback: IWorkerCallback, onErrorCallback: (err: any) => void): IWorker;
}
let webWorkerWarningLogged = false;
@@ -276,7 +284,7 @@ export class SimpleWorkerClient<W extends object, H extends object> extends Disp
let lazyProxyReject: ((err: any) => void) | null = null;
this._worker = this._register(workerFactory.create(
'vs/base/common/worker/simpleWorker',
{ moduleId: 'vs/base/common/worker/simpleWorker', esmModuleId: moduleId },
(msg: Message) => {
this._protocol.handleMessage(msg);
},
@@ -532,6 +540,19 @@ export class SimpleWorkerServer<H extends object> {
globalThis.require.config(loaderConfig);
}
if (isESM) {
const url = FileAccess.asBrowserUri(`${moduleId}.js` as AppResourcePath).toString(true);
return import(`${url}`).then((module: { create: IRequestHandlerFactory<H> }) => {
this._requestHandler = module.create(hostProxy);
if (!this._requestHandler) {
throw new Error(`No RequestHandler!`);
}
return getAllMethodNames(this._requestHandler);
});
}
return new Promise<string[]>((resolve, reject) => {
// Use the global require to be sure to get the global config

View File

@@ -0,0 +1,42 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IRequestHandlerFactory, SimpleWorkerServer } from 'vs/base/common/worker/simpleWorker';
type MessageEvent = {
data: any;
};
declare const globalThis: {
postMessage: (message: any) => void;
onmessage: (event: MessageEvent) => void;
};
let initialized = false;
function initialize<H extends object>(factory: IRequestHandlerFactory<H>) {
if (initialized) {
return;
}
initialized = true;
const simpleWorker = new SimpleWorkerServer<H>(
msg => globalThis.postMessage(msg),
host => factory(host)
);
globalThis.onmessage = (e: MessageEvent) => {
simpleWorker.onmessage(e.data);
};
}
export function bootstrapSimpleWorker<H extends object>(factory: IRequestHandlerFactory<H>) {
globalThis.onmessage = (_e: MessageEvent) => {
// Ignore first message in this case and initialize if not yet initialized
if (!initialized) {
initialize(factory);
}
};
}

View File

@@ -13,6 +13,7 @@
): undefined | Pick<TrustedTypePolicy<Options>, 'name' | Extract<keyof Options, keyof TrustedTypePolicyOptions>>;
}
const monacoEnvironment: IMonacoEnvironment | undefined = (globalThis as any).MonacoEnvironment;
const monacoBaseUrl = monacoEnvironment && monacoEnvironment.baseUrl ? monacoEnvironment.baseUrl : '../../../';
function createTrustedTypesPolicy<Options extends TrustedTypePolicyOptions>(
@@ -111,23 +112,42 @@
});
}
function loadCode(moduleId: string) {
loadAMDLoader().then(() => {
configureAMDLoader();
require([moduleId], function (ws) {
setTimeout(function () {
const messageHandler = ws.create((msg: any, transfer?: Transferable[]) => {
(<any>globalThis).postMessage(msg, transfer);
}, null);
function loadCode(moduleId: string): Promise<SimpleWorkerModule> {
// ESM-uncomment-begin
// const moduleUrl = new URL(`${moduleId}.js`, globalThis._VSCODE_FILE_ROOT);
// return import(moduleUrl.href);
// ESM-uncomment-end
globalThis.onmessage = (e: MessageEvent) => messageHandler.onmessage(e.data, e.ports);
while (beforeReadyMessages.length > 0) {
const e = beforeReadyMessages.shift()!;
messageHandler.onmessage(e.data, e.ports);
}
}, 0);
// ESM-comment-begin
return loadAMDLoader().then(() => {
configureAMDLoader();
return new Promise<SimpleWorkerModule>((resolve, reject) => {
require([moduleId], resolve, reject);
});
});
// ESM-comment-end
}
interface MessageHandler {
onmessage(msg: any, ports: readonly MessagePort[]): void;
}
// shape of vs/base/common/worker/simpleWorker.ts
interface SimpleWorkerModule {
create(postMessage: (msg: any, transfer?: Transferable[]) => void): MessageHandler;
}
function setupWorkerServer(ws: SimpleWorkerModule) {
setTimeout(function () {
const messageHandler = ws.create((msg: any, transfer?: Transferable[]) => {
(<any>globalThis).postMessage(msg, transfer);
});
self.onmessage = (e: MessageEvent) => messageHandler.onmessage(e.data, e.ports);
while (beforeReadyMessages.length > 0) {
self.onmessage(beforeReadyMessages.shift()!);
}
}, 0);
}
// If the loader is already defined, configure it immediately
@@ -146,6 +166,10 @@
}
isFirstMessage = false;
loadCode(message.data);
loadCode(message.data).then((ws) => {
setupWorkerServer(ws);
}, (err) => {
console.error(err);
});
};
})();

View File

@@ -63,6 +63,7 @@ export class EditorWorkerService extends Disposable implements IEditorWorkerServ
private readonly _logService: ILogService;
constructor(
workerMainLocation: URI | undefined,
@IModelService modelService: IModelService,
@ITextResourceConfigurationService configurationService: ITextResourceConfigurationService,
@ILogService logService: ILogService,
@@ -71,7 +72,7 @@ export class EditorWorkerService extends Disposable implements IEditorWorkerServ
) {
super();
this._modelService = modelService;
this._workerManager = this._register(new WorkerManager(this._modelService, languageConfigurationService));
this._workerManager = this._register(new WorkerManager(workerMainLocation, this._modelService, languageConfigurationService));
this._logService = logService;
// register default link-provider and default completions-provider
@@ -281,7 +282,7 @@ class WorkerManager extends Disposable {
private _editorWorkerClient: EditorWorkerClient | null;
private _lastWorkerUsedTime: number;
constructor(modelService: IModelService, private readonly languageConfigurationService: ILanguageConfigurationService) {
constructor(private readonly workerMainLocation: URI | undefined, modelService: IModelService, private readonly languageConfigurationService: ILanguageConfigurationService) {
super();
this._modelService = modelService;
this._editorWorkerClient = null;
@@ -335,7 +336,7 @@ class WorkerManager extends Disposable {
public withWorker(): Promise<EditorWorkerClient> {
this._lastWorkerUsedTime = (new Date()).getTime();
if (!this._editorWorkerClient) {
this._editorWorkerClient = new EditorWorkerClient(this._modelService, false, 'editorWorkerService', this.languageConfigurationService);
this._editorWorkerClient = new EditorWorkerClient(this.workerMainLocation, this._modelService, false, 'editorWorkerService', this.languageConfigurationService);
}
return Promise.resolve(this._editorWorkerClient);
}
@@ -484,6 +485,7 @@ export class EditorWorkerClient extends Disposable implements IEditorWorkerClien
private _disposed = false;
constructor(
workerMainLocation: URI | undefined,
modelService: IModelService,
keepIdleModels: boolean,
label: string | undefined,
@@ -492,7 +494,7 @@ export class EditorWorkerClient extends Disposable implements IEditorWorkerClien
super();
this._modelService = modelService;
this._keepIdleModels = keepIdleModels;
this._workerFactory = new DefaultWorkerFactory(label);
this._workerFactory = new DefaultWorkerFactory(workerMainLocation, label);
this._worker = null;
this._modelManager = null;
}

View File

@@ -3,6 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { FileAccess } from 'vs/base/common/network';
import { getAllMethodNames } from 'vs/base/common/objects';
import { URI } from 'vs/base/common/uri';
import { EditorWorkerClient } from 'vs/editor/browser/services/editorWorkerService';
@@ -14,7 +15,14 @@ import { IModelService } from 'vs/editor/common/services/model';
* Specify an AMD module to load that will `create` an object that will be proxied.
*/
export function createWebWorker<T extends object>(modelService: IModelService, languageConfigurationService: ILanguageConfigurationService, opts: IWebWorkerOptions): MonacoWebWorker<T> {
return new MonacoWebWorkerImpl<T>(modelService, languageConfigurationService, opts);
return new MonacoWebWorkerImpl<T>(undefined, modelService, languageConfigurationService, opts);
}
/**
* @internal
*/
export function createWorkbenchWebWorker<T extends object>(modelService: IModelService, languageConfigurationService: ILanguageConfigurationService, opts: IWebWorkerOptions): MonacoWebWorker<T> {
return new MonacoWebWorkerImpl<T>(FileAccess.asBrowserUri('vs/base/worker/workerMain.js'), modelService, languageConfigurationService, opts);
}
/**
@@ -68,8 +76,8 @@ class MonacoWebWorkerImpl<T extends object> extends EditorWorkerClient implement
private _foreignModuleCreateData: any | null;
private _foreignProxy: Promise<T> | null;
constructor(modelService: IModelService, languageConfigurationService: ILanguageConfigurationService, opts: IWebWorkerOptions) {
super(modelService, opts.keepIdleModels || false, opts.label, languageConfigurationService);
constructor(workerMainLocation: URI | undefined, modelService: IModelService, languageConfigurationService: ILanguageConfigurationService, opts: IWebWorkerOptions) {
super(workerMainLocation, modelService, opts.keepIdleModels || false, opts.label, languageConfigurationService);
this._foreignModuleId = opts.moduleId;
this._foreignModuleCreateData = opts.createData || null;
this._foreignModuleHost = opts.host || null;

View File

@@ -0,0 +1,9 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { create } from 'vs/editor/common/services/editorSimpleWorker';
import { bootstrapSimpleEditorWorker } from './editorWorkerBootstrap';
bootstrapSimpleEditorWorker(create);

View File

@@ -26,10 +26,18 @@ import { DetailedLineRangeMapping } from '../diff/rangeMapping';
import { linesDiffComputers } from 'vs/editor/common/diff/linesDiffComputers';
import { createProxyObject, getAllMethodNames } from 'vs/base/common/objects';
import { IDocumentDiffProviderOptions } from 'vs/editor/common/diff/documentDiffProvider';
import { AppResourcePath, FileAccess } from 'vs/base/common/network';
import { BugIndicatingError } from 'vs/base/common/errors';
import { IDocumentColorComputerTarget, computeDefaultDocumentColors } from 'vs/editor/common/languages/defaultDocumentColorsComputer';
import { FindSectionHeaderOptions, SectionHeader, findSectionHeaders } from 'vs/editor/common/services/findSectionHeaders';
// ESM-comment-begin
const isESM = false;
// ESM-comment-end
// ESM-uncomment-begin
// const isESM = true;
// ESM-uncomment-end
export interface IMirrorModel extends IMirrorTextModel {
readonly uri: URI;
readonly version: number;
@@ -818,20 +826,21 @@ export class EditorSimpleWorker implements IRequestHandler, IDisposable {
// static foreing module
return Promise.resolve(getAllMethodNames(this._foreignModule));
}
// ESM-comment-begin
return new Promise<any>((resolve, reject) => {
require([moduleId], (foreignModule: { create: IForeignModuleFactory }) => {
const onModuleCallback = (foreignModule: { create: IForeignModuleFactory }) => {
this._foreignModule = foreignModule.create(ctx, createData);
resolve(getAllMethodNames(this._foreignModule));
};
}, reject);
if (!isESM) {
require([`${moduleId}`], onModuleCallback, reject);
} else {
const url = FileAccess.asBrowserUri(`${moduleId}.js` as AppResourcePath).toString(true);
import(`${url}`).then(onModuleCallback).catch(reject);
}
});
// ESM-comment-end
// ESM-uncomment-begin
// return Promise.reject(new Error(`Unexpected usage`));
// ESM-uncomment-end
}
// foreign method request

View File

@@ -0,0 +1,51 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { SimpleWorkerServer } from 'vs/base/common/worker/simpleWorker';
import { EditorSimpleWorker } from 'vs/editor/common/services/editorSimpleWorker';
import { IEditorWorkerHost } from 'vs/editor/common/services/editorWorkerHost';
type MessageEvent = {
data: any;
};
declare const globalThis: {
postMessage: (message: any) => void;
onmessage: (event: MessageEvent) => void;
};
let initialized = false;
export function initialize(factory: any) {
if (initialized) {
return;
}
initialized = true;
const simpleWorker = new SimpleWorkerServer((msg) => {
globalThis.postMessage(msg);
}, (host: IEditorWorkerHost) => new EditorSimpleWorker(host, null));
globalThis.onmessage = (e: MessageEvent) => {
simpleWorker.onmessage(e.data);
};
}
globalThis.onmessage = (e: MessageEvent) => {
// Ignore first message in this case and initialize if not yet initialized
if (!initialized) {
initialize(null);
}
};
type CreateFunction<C, D, R = any> = (ctx: C, data: D) => R;
export function bootstrapSimpleEditorWorker<C, D, R>(createFn: CreateFunction<C, D, R>) {
globalThis.onmessage = () => {
initialize((ctx: C, createData: D) => {
return createFn.call(self, ctx, createData);
});
};
}

View File

@@ -13,6 +13,7 @@ import { ILanguageConfigurationService } from 'vs/editor/common/languages/langua
import { Disposable } from 'vs/base/common/lifecycle';
import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures';
import { registerEditorFeature } from 'vs/editor/common/editorFeatures';
import { FileAccess } from 'vs/base/common/network';
export class DefaultDocumentColorProvider implements DocumentColorProvider {
@@ -22,7 +23,7 @@ export class DefaultDocumentColorProvider implements DocumentColorProvider {
modelService: IModelService,
languageConfigurationService: ILanguageConfigurationService,
) {
this._editorWorkerClient = new EditorWorkerClient(modelService, false, 'editorWorkerService', languageConfigurationService);
this._editorWorkerClient = new EditorWorkerClient(FileAccess.asBrowserUri('vs/base/worker/workerMain.js'), modelService, false, 'editorWorkerService', languageConfigurationService);
}
async provideDocumentColors(model: ITextModel, _token: CancellationToken): Promise<IColorInformation[] | null> {

View File

@@ -66,7 +66,7 @@ suite('suggest, word distance', function () {
private _worker = new EditorSimpleWorker(new class extends mock<IEditorWorkerHost>() { }, null);
constructor() {
super(modelService, new class extends mock<ITextResourceConfigurationService>() { }, new NullLogService(), new TestLanguageConfigurationService(), new LanguageFeaturesService());
super(undefined, modelService, new class extends mock<ITextResourceConfigurationService>() { }, new NullLogService(), new TestLanguageConfigurationService(), new LanguageFeaturesService());
this._worker.acceptNewModel({
url: model.uri.toString(),
lines: model.getLinesContent(),

View File

@@ -3,30 +3,4 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { SimpleWorkerServer } from 'vs/base/common/worker/simpleWorker';
import { EditorSimpleWorker } from 'vs/editor/common/services/editorSimpleWorker';
import { IEditorWorkerHost } from 'vs/editor/common/services/editorWorkerHost';
let initialized = false;
export function initialize(foreignModule: any) {
if (initialized) {
return;
}
initialized = true;
const simpleWorker = new SimpleWorkerServer((msg) => {
globalThis.postMessage(msg);
}, (host: IEditorWorkerHost) => new EditorSimpleWorker(host, foreignModule));
globalThis.onmessage = (e: MessageEvent) => {
simpleWorker.onmessage(e.data);
};
}
globalThis.onmessage = (e: MessageEvent) => {
// Ignore first message in this case and initialize if not yet initialized
if (!initialized) {
initialize(null);
}
};
export * from 'vs/editor/common/services/editorWorkerBootstrap';

View File

@@ -3,7 +3,6 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/editor/common/languages/languageConfigurationRegistry';
import 'vs/editor/standalone/browser/standaloneCodeEditorService';
import 'vs/editor/standalone/browser/standaloneLayoutService';
import 'vs/platform/undoRedo/common/undoRedoService';
@@ -89,6 +88,8 @@ import { IStorageService, InMemoryStorageService } from 'vs/platform/storage/com
import { DefaultConfiguration } from 'vs/platform/configuration/common/configurations';
import { WorkspaceEdit } from 'vs/editor/common/languages';
import { AccessibilitySignal, AccessibilityModality, IAccessibilitySignalService, Sound } from 'vs/platform/accessibilitySignal/browser/accessibilitySignalService';
import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures';
import { ILanguageConfigurationService } from 'vs/editor/common/languages/languageConfigurationRegistry';
import { LogService } from 'vs/platform/log/common/logService';
import { getEditorFeatures } from 'vs/editor/common/editorFeatures';
import { onUnexpectedError } from 'vs/base/common/errors';
@@ -1072,6 +1073,18 @@ class StandaloneContextMenuService extends ContextMenuService {
}
}
class StandaloneEditorWorkerService extends EditorWorkerService {
constructor(
@IModelService modelService: IModelService,
@ITextResourceConfigurationService configurationService: ITextResourceConfigurationService,
@ILogService logService: ILogService,
@ILanguageConfigurationService languageConfigurationService: ILanguageConfigurationService,
@ILanguageFeaturesService languageFeaturesService: ILanguageFeaturesService,
) {
super(undefined, modelService, configurationService, logService, languageConfigurationService, languageFeaturesService);
}
}
class StandaloneAccessbilitySignalService implements IAccessibilitySignalService {
_serviceBrand: undefined;
async playSignal(cue: AccessibilitySignal, options: {}): Promise<void> {
@@ -1130,7 +1143,7 @@ registerSingleton(IContextKeyService, ContextKeyService, InstantiationType.Eager
registerSingleton(IProgressService, StandaloneProgressService, InstantiationType.Eager);
registerSingleton(IEditorProgressService, StandaloneEditorProgressService, InstantiationType.Eager);
registerSingleton(IStorageService, InMemoryStorageService, InstantiationType.Eager);
registerSingleton(IEditorWorkerService, EditorWorkerService, InstantiationType.Eager);
registerSingleton(IEditorWorkerService, StandaloneEditorWorkerService, InstantiationType.Eager);
registerSingleton(IBulkEditService, StandaloneBulkEditService, InstantiationType.Eager);
registerSingleton(IWorkspaceTrustManagementService, StandaloneWorkspaceTrustManagementService, InstantiationType.Eager);
registerSingleton(ITextModelService, StandaloneTextModelService, InstantiationType.Eager);

View File

@@ -0,0 +1,9 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { create } from './profileAnalysisWorker';
import { bootstrapSimpleWorker } from 'vs/base/common/worker/simpleWorkerBootstrap';
bootstrapSimpleWorker(create);

View File

@@ -5,6 +5,7 @@
import { DefaultWorkerFactory } from 'vs/base/browser/defaultWorkerFactory';
import { FileAccess } from 'vs/base/common/network';
import { URI } from 'vs/base/common/uri';
import { SimpleWorkerClient } from 'vs/base/common/worker/simpleWorker';
import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/common/extensions';
@@ -41,7 +42,7 @@ class ProfileAnalysisWorkerService implements IProfileAnalysisWorkerService {
declare _serviceBrand: undefined;
private readonly _workerFactory = new DefaultWorkerFactory('CpuProfileAnalysis');
private readonly _workerFactory = new DefaultWorkerFactory(FileAccess.asBrowserUri('vs/base/worker/workerMain.js'), 'CpuProfileAnalysis');
constructor(
@ITelemetryService private readonly _telemetryService: ITelemetryService,

View File

@@ -0,0 +1,9 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { create } from './extensionHostWorker';
const data = create();
self.onmessage = (e) => data.onmessage(e.data);

View File

@@ -0,0 +1,24 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { FileAccess } from 'vs/base/common/network';
import { EditorWorkerService } from 'vs/editor/browser/services/editorWorkerService';
import { ILanguageConfigurationService } from 'vs/editor/common/languages/languageConfigurationRegistry';
import { ILanguageFeaturesService } from 'vs/editor/common/services/languageFeatures';
import { IModelService } from 'vs/editor/common/services/model';
import { ITextResourceConfigurationService } from 'vs/editor/common/services/textResourceConfiguration';
import { ILogService } from 'vs/platform/log/common/log';
export class WorkbenchEditorWorkerService extends EditorWorkerService {
constructor(
@IModelService modelService: IModelService,
@ITextResourceConfigurationService configurationService: ITextResourceConfigurationService,
@ILogService logService: ILogService,
@ILanguageConfigurationService languageConfigurationService: ILanguageConfigurationService,
@ILanguageFeaturesService languageFeaturesService: ILanguageFeaturesService,
) {
super(FileAccess.asBrowserUri('vs/base/worker/workerMain.js'), modelService, configurationService, logService, languageConfigurationService, languageFeaturesService);
}
}

View File

@@ -13,6 +13,7 @@ import { INotebookService } from 'vs/workbench/contrib/notebook/common/notebookS
import { NotebookEditorSimpleWorker } from 'vs/workbench/contrib/notebook/common/services/notebookSimpleWorker';
import { INotebookWorkerHost } from 'vs/workbench/contrib/notebook/common/services/notebookWorkerHost';
import { INotebookEditorWorkerService } from 'vs/workbench/contrib/notebook/common/services/notebookWorkerService';
import { FileAccess } from 'vs/base/common/network';
export class NotebookEditorWorkerServiceImpl extends Disposable implements INotebookEditorWorkerService {
declare readonly _serviceBrand: undefined;
@@ -207,7 +208,7 @@ class NotebookWorkerClient extends Disposable {
constructor(private readonly _notebookService: INotebookService, label: string) {
super();
this._workerFactory = new DefaultWorkerFactory(label);
this._workerFactory = new DefaultWorkerFactory(FileAccess.asBrowserUri('vs/base/worker/workerMain.js'), label);
this._worker = null;
this._modelManager = null;

View File

@@ -0,0 +1,9 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { bootstrapSimpleWorker } from 'vs/base/common/worker/simpleWorkerBootstrap';
import { create } from './notebookSimpleWorker';
bootstrapSimpleWorker(create);

View File

@@ -9,7 +9,7 @@ import { IModelService } from 'vs/editor/common/services/model';
import { ILink } from 'vs/editor/common/languages';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { OUTPUT_MODE_ID, LOG_MODE_ID } from 'vs/workbench/services/output/common/output';
import { MonacoWebWorker, createWebWorker } from 'vs/editor/browser/services/webWorker';
import { MonacoWebWorker, createWorkbenchWebWorker } from 'vs/editor/browser/services/webWorker';
import { ICreateData, OutputLinkComputer } from 'vs/workbench/contrib/output/common/outputLinkComputer';
import { IDisposable, dispose, Disposable } from 'vs/base/common/lifecycle';
import { ILanguageConfigurationService } from 'vs/editor/common/languages/languageConfigurationRegistry';
@@ -73,7 +73,7 @@ export class OutputLinkProvider extends Disposable {
workspaceFolders: this.contextService.getWorkspace().folders.map(folder => folder.uri.toString())
};
this.worker = createWebWorker<OutputLinkComputer>(this.modelService, this.languageConfigurationService, {
this.worker = createWorkbenchWebWorker<OutputLinkComputer>(this.modelService, this.languageConfigurationService, {
moduleId: 'vs/workbench/contrib/output/common/outputLinkComputer',
createData,
label: 'outputLinkComputer'

View File

@@ -189,7 +189,7 @@ export class WebWorkerExtensionHost extends Disposable implements IExtensionHost
type: event.data.type,
data: {
baseUrl,
workerUrl: isESM ? FileAccess.asBrowserUri(factoryModuleId).toString(true) : require.toUrl(factoryModuleId),
workerUrl: isESM ? FileAccess.asBrowserUri('vs/workbench/api/worker/extensionHostWorker.esm.js').toString(true) : require.toUrl(factoryModuleId),
fileRoot: globalThis._VSCODE_FILE_ROOT,
nls: {
messages: globalThis._VSCODE_NLS_MESSAGES,

View File

@@ -0,0 +1,10 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { LanguageDetectionSimpleWorker } from './languageDetectionSimpleWorker';
import { bootstrapSimpleWorker } from 'vs/base/common/worker/simpleWorkerBootstrap';
import { IEditorWorkerHost } from 'vs/editor/common/services/editorWorkerHost';
bootstrapSimpleWorker<IEditorWorkerHost>(host => new LanguageDetectionSimpleWorker(host, () => { return {}; }));

View File

@@ -4,6 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import type { ModelOperations, ModelResult } from '@vscode/vscode-languagedetection';
import { importAMDNodeModule } from 'vs/amdX';
import { StopWatch } from 'vs/base/common/stopwatch';
import { IRequestHandler } from 'vs/base/common/worker/simpleWorker';
import { EditorSimpleWorker } from 'vs/editor/common/services/editorSimpleWorker';
@@ -103,7 +104,7 @@ export class LanguageDetectionSimpleWorker extends EditorSimpleWorker {
}
const uri: string = await this._host.fhr('getRegexpModelUri', []);
try {
this._regexpModel = await import(uri) as RegexpModel;
this._regexpModel = await importAMDNodeModule(uri, '') as RegexpModel;
return this._regexpModel;
} catch (e) {
this._regexpLoadFailed = true;
@@ -137,7 +138,7 @@ export class LanguageDetectionSimpleWorker extends EditorSimpleWorker {
}
const uri: string = await this._host.fhr('getIndexJsUri', []);
const { ModelOperations } = await import(uri) as typeof import('@vscode/vscode-languagedetection');
const { ModelOperations } = await importAMDNodeModule(uri, '') as typeof import('@vscode/vscode-languagedetection');
this._modelOperations = new ModelOperations({
modelJsonLoaderFunc: async () => {
const response = await fetch(await this._host.fhr('getModelJsonUri', []));

View File

@@ -24,6 +24,7 @@ import { IEditorService } from 'vs/workbench/services/editor/common/editorServic
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage';
import { LRUCache } from 'vs/base/common/map';
import { ILogService } from 'vs/platform/log/common/log';
import { canASAR } from 'vs/base/common/amd';
const TOP_LANG_COUNTS = 12;
@@ -66,21 +67,22 @@ export class LanguageDetectionService extends Disposable implements ILanguageDet
) {
super();
const useAsar = canASAR && this._environmentService.isBuilt && !isWeb;
this._languageDetectionWorkerClient = this._register(new LanguageDetectionWorkerClient(
modelService,
languageService,
telemetryService,
// TODO: See if it's possible to bundle vscode-languagedetection
this._environmentService.isBuilt && !isWeb
// TODO@esm: See if it's possible to bundle vscode-languagedetection
useAsar
? FileAccess.asBrowserUri(`${moduleLocationAsar}/dist/lib/index.js`).toString(true)
: FileAccess.asBrowserUri(`${moduleLocation}/dist/lib/index.js`).toString(true),
this._environmentService.isBuilt && !isWeb
useAsar
? FileAccess.asBrowserUri(`${moduleLocationAsar}/model/model.json`).toString(true)
: FileAccess.asBrowserUri(`${moduleLocation}/model/model.json`).toString(true),
this._environmentService.isBuilt && !isWeb
useAsar
? FileAccess.asBrowserUri(`${moduleLocationAsar}/model/group1-shard1of1.bin`).toString(true)
: FileAccess.asBrowserUri(`${moduleLocation}/model/group1-shard1of1.bin`).toString(true),
this._environmentService.isBuilt && !isWeb
useAsar
? FileAccess.asBrowserUri(`${regexpModuleLocationAsar}/dist/index.js`).toString(true)
: FileAccess.asBrowserUri(`${regexpModuleLocation}/dist/index.js`).toString(true),
languageConfigurationService
@@ -234,7 +236,7 @@ export class LanguageDetectionWorkerClient extends EditorWorkerClient {
private readonly _regexpModelUri: string,
languageConfigurationService: ILanguageConfigurationService,
) {
super(modelService, true, 'languageDetectionWorkerService', languageConfigurationService);
super(FileAccess.asBrowserUri('vs/base/worker/workerMain.js'), modelService, true, 'languageDetectionWorkerService', languageConfigurationService);
}
private _getOrCreateLanguageDetectionWorker(): Promise<IWorkerClient<LanguageDetectionSimpleWorker>> {

View File

@@ -21,7 +21,7 @@ import { InstantiationType, registerSingleton } from 'vs/platform/instantiation/
import { ILocalFileSearchSimpleWorker, ILocalFileSearchSimpleWorkerHost } from 'vs/workbench/services/search/common/localFileSearchWorkerTypes';
import { memoize } from 'vs/base/common/decorators';
import { HTMLFileSystemProvider } from 'vs/platform/files/browser/htmlFileSystemProvider';
import { Schemas } from 'vs/base/common/network';
import { FileAccess, Schemas } from 'vs/base/common/network';
import { URI, UriComponents } from 'vs/base/common/uri';
import { Emitter, Event } from 'vs/base/common/event';
import { localize } from 'vs/nls';
@@ -64,7 +64,7 @@ export class LocalFileSearchWorkerClient extends Disposable implements ISearchRe
) {
super();
this._worker = null;
this._workerFactory = new DefaultWorkerFactory('localFileSearchWorker');
this._workerFactory = new DefaultWorkerFactory(FileAccess.asBrowserUri('vs/base/worker/workerMain.js'), 'localFileSearchWorker');
}
sendTextSearchMatch(match: IFileMatch<UriComponents>, queryId: number): void {

View File

@@ -0,0 +1,9 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { bootstrapSimpleWorker } from 'vs/base/common/worker/simpleWorkerBootstrap';
import { create } from 'vs/workbench/services/search/worker/localFileSearch';
bootstrapSimpleWorker(create);

View File

@@ -128,23 +128,15 @@ export class ThreadedBackgroundTokenizerFactory implements IDisposable {
}
private async _createWorkerProxy(): Promise<TextMateTokenizationWorker | null> {
const textmateModuleLocation: AppResourcePath = `${nodeModulesPath}/vscode-textmate`;
const textmateModuleLocationAsar: AppResourcePath = `${nodeModulesAsarPath}/vscode-textmate`;
const onigurumaModuleLocation: AppResourcePath = `${nodeModulesPath}/vscode-oniguruma`;
const onigurumaModuleLocationAsar: AppResourcePath = `${nodeModulesAsarPath}/vscode-oniguruma`;
const useAsar = canASAR && this._environmentService.isBuilt && !isWeb;
const textmateLocation: AppResourcePath = useAsar ? textmateModuleLocationAsar : textmateModuleLocation;
const onigurumaLocation: AppResourcePath = useAsar ? onigurumaModuleLocationAsar : onigurumaModuleLocation;
const textmateMain: AppResourcePath = `${textmateLocation}/release/main.js`;
const onigurumaMain: AppResourcePath = `${onigurumaLocation}/release/main.js`;
const onigurumaWASM: AppResourcePath = `${onigurumaLocation}/release/onig.wasm`;
const uri = FileAccess.asBrowserUri(textmateMain).toString(true);
const createData: ICreateData = {
grammarDefinitions: this._grammarDefinitions,
textmateMainUri: uri,
onigurumaMainUri: FileAccess.asBrowserUri(onigurumaMain).toString(true),
onigurumaWASMUri: FileAccess.asBrowserUri(onigurumaWASM).toString(true),
};
const host: ITextMateWorkerHost = {

View File

@@ -11,6 +11,7 @@ import { ICreateGrammarResult, TMGrammarFactory } from 'vs/workbench/services/te
import { IValidEmbeddedLanguagesMap, IValidGrammarDefinition, IValidTokenTypeMap } from 'vs/workbench/services/textMate/common/TMScopeRegistry';
import type { IOnigLib, IRawTheme, StackDiff } from 'vscode-textmate';
import { TextMateWorkerTokenizer } from './textMateWorkerTokenizer';
import { importAMDNodeModule } from 'vs/amdX';
/**
* Defines the worker entry point. Must be exported and named `create`.
@@ -27,8 +28,6 @@ export interface ITextMateWorkerHost {
export interface ICreateData {
grammarDefinitions: IValidGrammarDefinitionDTO[];
textmateMainUri: string;
onigurumaMainUri: string;
onigurumaWASMUri: string;
}
@@ -78,9 +77,8 @@ export class TextMateTokenizationWorker {
}
private async _loadTMGrammarFactory(grammarDefinitions: IValidGrammarDefinition[]): Promise<TMGrammarFactory> {
const uri = this._createData.textmateMainUri;
const vscodeTextmate = await import(uri);
const vscodeOniguruma = await import(this._createData.onigurumaMainUri);
const vscodeTextmate = await importAMDNodeModule<typeof import('vscode-textmate')>('vscode-textmate', 'release/main.js');
const vscodeOniguruma = await importAMDNodeModule<typeof import('vscode-oniguruma')>('vscode-oniguruma', 'release/main.js');
const response = await fetch(this._createData.onigurumaWASMUri);
// Using the response directly only works if the server sets the MIME type 'application/wasm'.

View File

@@ -129,7 +129,7 @@ import { ContextViewService } from 'vs/platform/contextview/browser/contextViewS
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
import { IListService, ListService } from 'vs/platform/list/browser/listService';
import { IEditorWorkerService } from 'vs/editor/common/services/editorWorker';
import { EditorWorkerService } from 'vs/editor/browser/services/editorWorkerService';
import { WorkbenchEditorWorkerService } from 'vs/workbench/contrib/codeEditor/browser/workbenchEditorWorkerService';
import { MarkerDecorationsService } from 'vs/editor/common/services/markerDecorationsService';
import { IMarkerDecorationsService } from 'vs/editor/common/services/markerDecorations';
import { IMarkerService } from 'vs/platform/markers/common/markers';
@@ -154,7 +154,7 @@ registerSingleton(IExtensionStorageService, ExtensionStorageService, Instantiati
registerSingleton(IExtensionGalleryService, ExtensionGalleryService, InstantiationType.Delayed);
registerSingleton(IContextViewService, ContextViewService, InstantiationType.Delayed);
registerSingleton(IListService, ListService, InstantiationType.Delayed);
registerSingleton(IEditorWorkerService, EditorWorkerService, InstantiationType.Eager /* registers link detection and word based suggestions for any document */);
registerSingleton(IEditorWorkerService, WorkbenchEditorWorkerService, InstantiationType.Eager /* registers link detection and word based suggestions for any document */);
registerSingleton(IMarkerDecorationsService, MarkerDecorationsService, InstantiationType.Delayed);
registerSingleton(IMarkerService, MarkerService, InstantiationType.Delayed);
registerSingleton(IContextKeyService, ContextKeyService, InstantiationType.Delayed);

View File

@@ -5,6 +5,9 @@
</head>
<body>
<div id="container" style="width:800px;height:600px;border:1px solid #ccc"></div>
<script>
globalThis._VSCODE_FILE_ROOT = 'http://127.0.0.1:8563/dist/';
</script>
<script src="./core.bundle.js"></script>
</body>
</html>