diff --git a/src/Runner.Language.Server/Program.cs b/src/Runner.Language.Server/Program.cs index 8e50002848a..5ee2184e38d 100644 --- a/src/Runner.Language.Server/Program.cs +++ b/src/Runner.Language.Server/Program.cs @@ -20,57 +20,86 @@ using Runner.Language.Server; #if WASM -Console.WriteLine("Loading Lsp..."); - -_ = Task.Run(async () => { - var crlf = System.Text.Encoding.UTF8.GetBytes("\r\n\r\n"); - while(true) { - Console.WriteLine("Read Message"); - var result = await Interop.Output.Reader.ReadAsync(); - Console.WriteLine("Got Message len = " + result.Buffer.Length); - var header = ""; - var body = ""; - var remainingBody = 0; - foreach (var cp in result.Buffer) - { - var span = cp; - while(span.Length > 0) { - if(remainingBody == 0) { - int endOfHeader = span.Span.IndexOf(crlf); - if(endOfHeader == -1) { - header += System.Text.Encoding.UTF8.GetString(span.Span); - - span = span.Slice(span.Length); - // Console.WriteLine(header); - } else { - header += System.Text.Encoding.UTF8.GetString(span.Slice(0, endOfHeader).Span); - - Console.WriteLine(header); - - remainingBody = int.Parse(header.Split(": ")[1]); - header = ""; - body = ""; - span = span.Slice(endOfHeader + 4); - } - } else { - var n = Math.Min(span.Length, remainingBody); - body += System.Text.Encoding.UTF8.GetString(span.Slice(0, n).Span); - remainingBody -= n; - span = span.Slice(n); +if(args.Length == 0 || args.Length == 1 && args[0] == "--webworker") { + Console.WriteLine("Loading Lsp..."); + _ = Task.Run(async () => { + var crlf = System.Text.Encoding.UTF8.GetBytes("\r\n\r\n"); + while(true) { + Console.WriteLine("Read Message"); + var result = await Interop.Output.Reader.ReadAsync(); + if(result.IsCanceled) { + System.Environment.Exit(1); + return; + } + Console.WriteLine("Got Message len = " + result.Buffer.Length); + var header = ""; + var body = ""; + var remainingBody = 0; + foreach (var cp in result.Buffer) + { + var span = cp; + while(span.Length > 0) { if(remainingBody == 0) { - await Interop.SendOutputMessageAsync(body); + int endOfHeader = span.Span.IndexOf(crlf); + if(endOfHeader == -1) { + header += System.Text.Encoding.UTF8.GetString(span.Span); + + span = span.Slice(span.Length); + // Console.WriteLine(header); + } else { + header += System.Text.Encoding.UTF8.GetString(span.Slice(0, endOfHeader).Span); + + Console.WriteLine(header); + + remainingBody = int.Parse(header.Split(": ")[1]); + + header = ""; + body = ""; + span = span.Slice(endOfHeader + 4); + } + } else { + var n = Math.Min(span.Length, remainingBody); + body += System.Text.Encoding.UTF8.GetString(span.Slice(0, n).Span); + remainingBody -= n; + span = span.Slice(n); + if(remainingBody == 0) { + await Interop.SendOutputMessageAsync(body); + } } } } + if(result.IsCompleted) { + System.Environment.Exit(0); + return; + } + Interop.Output.Reader.AdvanceTo(result.Buffer.End); } - Interop.Output.Reader.AdvanceTo(result.Buffer.End); - } -}).ConfigureAwait(false); + }).ConfigureAwait(false); +} else if(args.Length == 1 && args[0] == "--stdio") { + Interop.IsNode = true; + _ = Task.Run(async () => { + while(true) { + var result = await Interop.Output.Reader.ReadAsync(); + if(result.IsCanceled) { + System.Environment.Exit(1); + return; + } + foreach (var cp in result.Buffer) { + await Interop.SendOutputMessageAsync(System.Text.Encoding.UTF8.GetString(cp.ToArray())); + } + if(result.IsCompleted) { + System.Environment.Exit(0); + return; + } + Interop.Output.Reader.AdvanceTo(result.Buffer.End); + } + }).ConfigureAwait(false); +} #endif var server = await LanguageServer.From( - options => + options => { options #if WASM .WithInput(Interop.Input.Reader) @@ -158,7 +187,13 @@ logger.LogInformation("Scoped Config: {@Config}", scopedConfig); } - ) + ); +#if WASM + if(Interop.IsNode) { + options.WithHandler(); + } +#endif + } ).ConfigureAwait(false); await server.WaitForExit.ConfigureAwait(false); @@ -166,12 +201,18 @@ #if WASM public static partial class Interop { + public static bool IsNode { get; set; } + [JSImport("sendOutputMessageAsync", "extension.js")] internal static partial Task SendOutputMessageAsync(string message); [SupportedOSPlatform("browser")] [JSExport] public async static Task SendInputMessageAsync(string message) { + if(Interop.IsNode) { + await Input.Writer.WriteAsync(System.Text.Encoding.UTF8.GetBytes(message)); + return; + } Console.WriteLine("Message received"); Console.WriteLine(message); diff --git a/src/runner-server-web-vscode/client/package-lock.json b/src/runner-server-web-vscode/client/package-lock.json new file mode 100644 index 00000000000..06800762648 --- /dev/null +++ b/src/runner-server-web-vscode/client/package-lock.json @@ -0,0 +1,107 @@ +{ + "name": "runner-server-web-vscode-client", + "version": "0.0.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "runner-server-web-vscode-client", + "version": "0.0.1", + "license": "MIT", + "dependencies": { + "vscode-languageclient": "^9.0.1" + }, + "devDependencies": { + "@types/vscode": "^1.85.0" + }, + "engines": { + "vscode": "^1.85.0" + } + }, + "node_modules/@types/vscode": { + "version": "1.95.0", + "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.95.0.tgz", + "integrity": "sha512-0LBD8TEiNbet3NvWsmn59zLzOFu/txSlGxnv5yAFHCrhG9WvAnR3IvfHzMOs2aeWqgvNjq9pO99IUw8d3n+unw==", + "dev": true, + "license": "MIT" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/vscode-jsonrpc": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", + "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/vscode-languageclient": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-9.0.1.tgz", + "integrity": "sha512-JZiimVdvimEuHh5olxhxkht09m3JzUGwggb5eRUkzzJhZ2KjCN0nh55VfiED9oez9DyF8/fz1g1iBV3h+0Z2EA==", + "license": "MIT", + "dependencies": { + "minimatch": "^5.1.0", + "semver": "^7.3.7", + "vscode-languageserver-protocol": "3.17.5" + }, + "engines": { + "vscode": "^1.82.0" + } + }, + "node_modules/vscode-languageserver-protocol": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", + "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "license": "MIT", + "dependencies": { + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.5" + } + }, + "node_modules/vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", + "license": "MIT" + } + } +} diff --git a/src/runner-server-web-vscode/client/src/browserClientMain.ts b/src/runner-server-web-vscode/client/src/browserClientMain.ts index 398338f92cb..1864cdb9d1a 100644 --- a/src/runner-server-web-vscode/client/src/browserClientMain.ts +++ b/src/runner-server-web-vscode/client/src/browserClientMain.ts @@ -3,16 +3,97 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ExtensionContext, Uri, workspace } from 'vscode'; -import { LanguageClientOptions } from 'vscode-languageclient'; +import { commands, EventEmitter, ExtensionContext, Pseudoterminal, QuickPickItem, Uri, window, workspace } from 'vscode'; +import { BaseLanguageClient, LanguageClientOptions } from 'vscode-languageclient'; import { LanguageClient } from 'vscode-languageclient/browser'; +import { LanguageClient as LanguageClientNode } from 'vscode-languageclient/node'; +import { spawn } from 'child_process'; -let client: LanguageClient | undefined; +let client: BaseLanguageClient | undefined; // this method is called when vs code is activated export async function activate(context: ExtensionContext) { + commands.registerCommand("runner.server.runworkflow", async (workflow, events) => { + console.log(`runner.server.runworkflow ${workflow}`) - console.log('lsp-web-extension-sample activated!'); + const writeEmitter = new EventEmitter(); + const closeEmitter = new EventEmitter(); + + const pty: Pseudoterminal = { + onDidWrite: writeEmitter.event, + onDidClose: closeEmitter.event, + open: () => {}, + close: () => {} + }; + window.createTerminal({ + isTransient: false, + pty: pty, + name: "Runner.Client" + }) + + var sel : string = events.length === 1 ? events : await window.showQuickPick(events, { canPickMany: false }) + var args = ['--event', sel || 'push', '-W', Uri.parse(workflow).fsPath ]; + + let startproc = spawn('Runner.Client', args, { windowsHide: true, stdio: 'pipe', shell: false, env: { ...process.env, FORCE_COLOR: "1" } }); + startproc.stdout.on('data', async (data) => { + var sdata = data.asciiSlice(); + writeEmitter.fire(sdata.replace(/\r?\n/g, "\r\n")); + }); + startproc.stderr.on('data', async (data) => { + var sdata = data.asciiSlice(); + writeEmitter.fire(sdata.replace(/\r?\n/g, "\r\n")); + }); + startproc.addListener('exit', code => { + writeEmitter.fire(`\r\nProcess Exited with code ${code}.\r\n`); + pty.handleInput = msg => closeEmitter.fire(); + }); + }); + commands.registerCommand("runner.server.runjob", async (workflow, job, events) => { + if(typeof job === 'object') { + var jobs : QuickPickItem[] = []; + for(var j of job) { + jobs.push({ + label: j.name, + detail: j.jobIdLong + }); + } + job = (await window.showQuickPick(jobs, { canPickMany: false, title: "Select matrix job entry" }))?.detail; + if(!job) { + throw new Error("No job selected"); + } + } + console.log(`runner.server.runjob ${workflow}.${job}`) + const writeEmitter = new EventEmitter(); + const closeEmitter = new EventEmitter(); + const pty: Pseudoterminal = { + onDidWrite: writeEmitter.event, + onDidClose: closeEmitter.event, + open: () => {}, + close: () => {} + }; + window.createTerminal({ + isTransient: false, + pty: pty, + name: "Runner.Client" + }) + + var sel : string = events.length === 1 ? events : await window.showQuickPick(events, { canPickMany: false }) + var args = [ '--event', sel || 'push', '-W', Uri.parse(workflow).fsPath, '-j', job ]; + + let startproc = spawn('Runner.Client', args, { windowsHide: true, stdio: 'pipe', shell: false, env: { ...process.env, FORCE_COLOR: "1" } }); + startproc.stdout.on('data', async (data) => { + var sdata = data.asciiSlice(); + writeEmitter.fire(sdata.replace(/\r?\n/g, "\r\n")); + }); + startproc.stderr.on('data', async (data) => { + var sdata = data.asciiSlice(); + writeEmitter.fire(sdata.replace(/\r?\n/g, "\r\n")); + }); + startproc.addListener('exit', code => { + writeEmitter.fire(`\r\nProcess Exited with code ${code}.\r\n`); + pty.handleInput = msg => closeEmitter.fire(); + }); + }); /* * all except the code to create the language client in not browser specific @@ -27,9 +108,30 @@ export async function activate(context: ExtensionContext) { initializationOptions: {} }; - client = await createWorkerLanguageClient(context, clientOptions); - - await client.start(); + if(globalThis.process) { + console.log("Starting Language Server") + client = new LanguageClientNode( + 'Runner.Server', + 'Runner.Server Language Server', + { + run: { + transport: 0, + module: context.asAbsolutePath("server/dist/nodeServerMain.js"), + + }, + debug: { + transport: 0, + module: context.asAbsolutePath("server/dist/nodeServerMain.js") + } + }, + { + documentSelector: [ { language: "yaml" }, { language: "azure-pipelines" } ], + } + ); + } else { + client = await createWorkerLanguageClient(context, clientOptions); + } + await client.start(); console.log('lsp-web-extension-sample server is ready'); } diff --git a/src/runner-server-web-vscode/package-lock.json b/src/runner-server-web-vscode/package-lock.json index 82c3778548c..d667862cf32 100644 --- a/src/runner-server-web-vscode/package-lock.json +++ b/src/runner-server-web-vscode/package-lock.json @@ -7,6 +7,7 @@ "": { "name": "runner-server-web-vscode", "version": "0.0.1", + "hasInstallScript": true, "license": "MIT", "devDependencies": { "@typescript-eslint/eslint-plugin": "^6.20.0", diff --git a/src/runner-server-web-vscode/package.json b/src/runner-server-web-vscode/package.json index 73258ee56d7..060616b2593 100644 --- a/src/runner-server-web-vscode/package.json +++ b/src/runner-server-web-vscode/package.json @@ -29,6 +29,7 @@ ] }, "browser": "./client/dist/browserClientMain", + "main": "./client/dist/nodeClientMain", "scripts": { "vscode:prepublish": "npm run build", "postinstall": "cd client && npm install && cd ../server && npm install && cd ..", diff --git a/src/runner-server-web-vscode/server/package-lock.json b/src/runner-server-web-vscode/server/package-lock.json new file mode 100644 index 00000000000..bfbc6b7837b --- /dev/null +++ b/src/runner-server-web-vscode/server/package-lock.json @@ -0,0 +1,63 @@ +{ + "name": "runner-server-web-vscode-server", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "runner-server-web-vscode-server", + "version": "1.0.0", + "license": "MIT", + "dependencies": { + "vscode-languageserver": "^9.0.1", + "vscode-languageserver-textdocument": "^1.0.11" + }, + "engines": { + "node": "*" + } + }, + "node_modules/vscode-jsonrpc": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", + "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/vscode-languageserver": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz", + "integrity": "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==", + "license": "MIT", + "dependencies": { + "vscode-languageserver-protocol": "3.17.5" + }, + "bin": { + "installServerIntoExtension": "bin/installServerIntoExtension" + } + }, + "node_modules/vscode-languageserver-protocol": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", + "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "license": "MIT", + "dependencies": { + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.5" + } + }, + "node_modules/vscode-languageserver-textdocument": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz", + "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==", + "license": "MIT" + }, + "node_modules/vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", + "license": "MIT" + } + } +} diff --git a/src/runner-server-web-vscode/server/src/browserServerMain.ts b/src/runner-server-web-vscode/server/src/browserServerMain.ts index d27b5b5fae2..8d27d9ceb57 100644 --- a/src/runner-server-web-vscode/server/src/browserServerMain.ts +++ b/src/runner-server-web-vscode/server/src/browserServerMain.ts @@ -7,23 +7,33 @@ import { Semaphore } from 'vscode-jsonrpc/lib/common/semaphore' import { RAL } from 'vscode-languageserver'; -console.log('running server lsp-web-extension-sample'); +import { nodeRequire } from './config' (async () => { var freadSemaphore = new Semaphore(1); var writeMsg = new Semaphore(1); try { + var isNode = typeof globalThis.postMessage !== 'function'; + if(isNode) { + process.stdout.setEncoding('utf8'); + process.stdin.setEncoding('utf8'); + } var getBoot = new Promise((resolve, reject) => { - onmessage = (msg) => { - if(msg.data.error) { - reject(msg.data.error); - } else { - resolve(msg.data.data); + if(isNode) { + resolve("file://" + __dirname + "/../src/build/AppBundle/_framework/blazor.boot.json") + } else { + onmessage = (msg) => { + if(msg.data.error) { + reject(msg.data.error); + } else { + resolve(msg.data.data); + } } } }); - postMessage({ getpath: true }); - + if(!isNode) { + postMessage({ getpath: true }); + } var { basePaths, customImports } = require("./config.js") basePaths.basedir = await getBoot; @@ -31,10 +41,11 @@ console.log('running server lsp-web-extension-sample'); customImports["dotnet.runtime.js"] = require("./build/AppBundle/_framework/dotnet.runtime.js"); customImports["dotnet.native.js"] = require("./build/AppBundle/_framework/dotnet.native.js"); - var items = 0; - var citem = 0; var runtime = await dotnet.withOnConfigLoaded(async (config : any) => { - items = Object.keys(config.resources.assembly).length; + config.resources.wasmSymbols = {} + // 2024-10-28 Unknown breaking change in .net8.0 deployed pdb's that refuse to be served by marketplace cdn + config.debugLevel = 0; + config.resources.pdb = {}; }).withConfigSrc(basePaths.basedir).withResourceLoader((type : string, name : string, defaultUri : string, integrity : string, behavior : string) => { if(type === "dotnetjs") { // Allow both nodejs and browser to use the same code @@ -42,14 +53,14 @@ console.log('running server lsp-web-extension-sample'); return defaultUri; } return freadSemaphore.lock(async () => { - if(type === "assembly") { - console.log({ message: name, increment: citem++ / items }); - } if(name.endsWith(".dat")) { name = name.substring(0, name.length - 3) + "icu"; } - // return await fetch(self.location.toString() + "/../build/AppBundle/_framework/" + name) + if(isNode) { + var nodeContent = nodeRequire("fs").readFileSync(__dirname + "/../src/build/AppBundle/_framework/" + name); + return new Response(nodeContent, { status: 200 }); + } var getContent = new Promise((resolve, reject) => { onmessage = (msg) => { if(msg.data.error) { @@ -65,58 +76,48 @@ console.log('running server lsp-web-extension-sample'); }); }).create(); - const messageWriter = new BrowserMessageWriter(self); + const messageWriter = isNode ? null : new BrowserMessageWriter(self); runtime.setModuleImports("extension.js", { sendOutputMessageAsync: async (data : string) => { - await writeMsg.lock(() => { - console.log(data); - messageWriter.write(JSON.parse(data)); - }); + if(isNode) { + await writeMsg.lock(async () => { await new Promise((accept) => { + process.stdout.write(data, accept); + }) + }); + } else { + await writeMsg.lock(() => { + console.log(data); + messageWriter?.write(JSON.parse(data)); + }); + } } }); - runtime.runMainAndExit("Runner.Language.Server", []); - var SendInputMessageAsync = runtime.BINDING.bind_static_method("[Runner.Language.Server] Interop:SendInputMessageAsync") - - postMessage({ loaded: true }) - /* browser specific setup code */ - const messageReader = new BrowserMessageReader(self); + runtime.runMainAndExit("Runner.Language.Server", isNode ? [ "--stdio" ] : []); + var SendInputMessageAsync = runtime.BINDING.bind_static_method("[Runner.Language.Server] Interop:SendInputMessageAsync") - var lastContentLength = -1; var readSemaphore = new Semaphore(1); - var buffer = RAL().messageBuffer.create('utf-8'); - - messageReader.listen(async cbc => { - readSemaphore.lock(async () => { - // var data = await RAL().applicationJson.encoder.encode(cbc, { charset: "utf-8" }) - // console.log(data); + if(isNode) { + process.stdin.on('readable', async () => { + readSemaphore.lock(async () => { + let chunk; + while ((chunk = process.stdin.read()) !== null) { + await SendInputMessageAsync(chunk); + } + }); + }); + } else { + postMessage({ loaded: true }) + /* browser specific setup code */ - // var enc = new TextEncoder(); + const messageReader = new BrowserMessageReader(self); - // var d = enc.encode("Content-Length: " + data.length + "\r\n\r\n"); - - - - // var orglen = d.byteLength; - // var nlen = (len: number) => Math.ceil(len / 4) * 4; - // await SendInputMessageAsync(new Int32Array(d.buffer), orglen) - // orglen = - // await SendInputMessageAsync(new Int32Array(data), data.byteLength) - await SendInputMessageAsync(JSON.stringify(cbc)); - // buffer.append(data); - // if(lastContentLength === -1) { - // var headers = buffer.tryReadHeaders(true); - // const contentLength = headers?.get('content-length'); - // const length = parseInt(contentLength!); - // lastContentLength = length; - // } - // var result = buffer.tryReadBody(lastContentLength); - // if(result) { - // lastContentLength = -1; - // messageWriter.write(await RAL().applicationJson.decoder.decode(result, { charset: "utf-8" })) - // } + messageReader.listen(async cbc => { + readSemaphore.lock(async () => { + await SendInputMessageAsync(JSON.stringify(cbc)); + }) }) - }) + } } catch(err) { diff --git a/src/runner-server-web-vscode/server/src/config.d.ts b/src/runner-server-web-vscode/server/src/config.d.ts new file mode 100644 index 00000000000..26c9aaef4bd --- /dev/null +++ b/src/runner-server-web-vscode/server/src/config.d.ts @@ -0,0 +1 @@ +export function nodeRequire(url : string) : any \ No newline at end of file diff --git a/src/runner-server-web-vscode/server/src/config.js b/src/runner-server-web-vscode/server/src/config.js index 2d29ece7501..8ff709a58c7 100644 --- a/src/runner-server-web-vscode/server/src/config.js +++ b/src/runner-server-web-vscode/server/src/config.js @@ -11,3 +11,6 @@ export var customImports = { export async function myimport(url) { return customImports[url]; } +export function nodeRequire(url) { + return __non_webpack_require__(url); +} diff --git a/src/runner-server-web-vscode/webpack.config.js b/src/runner-server-web-vscode/webpack.config.js index 4ad59596d3e..db4afc4a5cf 100644 --- a/src/runner-server-web-vscode/webpack.config.js +++ b/src/runner-server-web-vscode/webpack.config.js @@ -58,6 +58,50 @@ const browserClientConfig = { devtool: 'nosources-source-map', }; +/** @type WebpackConfig */ +const nodeClientConfig = { + context: path.join(__dirname, 'client'), + mode: 'none', + target: 'node', // web extensions run in a webworker context + entry: { + nodeClientMain: './src/browserClientMain.ts', + }, + output: { + filename: '[name].js', + path: path.join(__dirname, 'client', 'dist'), + libraryTarget: 'commonjs', + devtoolModuleFilenameTemplate: '../[resource-path]' + }, + resolve: { + mainFields: ['module', 'main'], + extensions: ['.ts', '.js'], // support ts-files and js-files + alias: {}, + fallback: { + path: require.resolve('path-browserify'), + }, + }, + module: { + rules: [ + { + test: /\.ts$/, + exclude: /node_modules/, + use: [ + { + loader: 'ts-loader', + }, + ], + }, + ], + }, + externals: { + vscode: 'commonjs vscode', // ignored because it doesn't exist + }, + performance: { + hints: false, + }, + devtool: 'nosources-source-map', +}; + /** @type WebpackConfig */ const browserServerConfig = { context: path.join(__dirname, 'server'), @@ -122,4 +166,66 @@ const browserServerConfig = { devtool: 'nosources-source-map', }; -module.exports = [browserClientConfig, browserServerConfig]; +/** @type WebpackConfig */ +const nodeServerConfig = { + context: path.join(__dirname, 'server'), + mode: 'none', + target: 'node', // web extensions run in a webworker context + entry: { + nodeServerMain: './src/browserServerMain.ts', + }, + output: { + filename: '[name].js', + path: path.join(__dirname, 'server', 'dist'), + libraryTarget: 'var', + library: 'serverExportVar', + devtoolModuleFilenameTemplate: '../[resource-path]' + }, + resolve: { + mainFields: ['module', 'main'], + extensions: ['.ts', '.js'], // support ts-files and js-files + alias: {}, + fallback: { + // Webpack 5 no longer polyfills Node.js core modules automatically. + // see https://webpack.js.org/configuration/resolve/#resolvefallback + // for the list of Node.js core module polyfills. + assert: require.resolve('assert'), + process: false, + module: false, + }, + }, + module: { + rules: [ + { + test: /_framework/, + exclude: /node_modules/, + use: { + loader: path.resolve('loader.mjs'), + options: { + }, + } + }, + { + test: /\.ts$/, + exclude: /node_modules/, + use: [ + { + loader: 'ts-loader', + }, + ], + }, + ], + }, + plugins: [ + ], + externals: { + vscode: 'commonjs vscode', // ignored because it doesn't exist + }, + performance: { + hints: false, + }, + devtool: 'nosources-source-map', +}; + + +module.exports = [browserClientConfig, nodeClientConfig, browserServerConfig, nodeServerConfig];