diff --git a/scripts/createPlaygroundBuild.js b/scripts/createPlaygroundBuild.js index 8fbee8ce8a6..31fe5af92dd 100644 --- a/scripts/createPlaygroundBuild.js +++ b/scripts/createPlaygroundBuild.js @@ -1,5 +1,10 @@ +/* eslint-disable */ // @ts-check +/** Run via: + node scripts/createPlaygroundBuild.js + */ + // This script does two things: // // - Listens to changes to the built version of TypeScript (via a filewatcher on `built/local/typescriptServices.js`) @@ -20,11 +25,12 @@ const fs = require('fs'); const child_process = require('child_process'); const http = require('http'); const url = require('url'); +const nodeFetch = require("node-fetch").default function updateTSDist() { // This code is a direct port of a script from monaco-typescript // https://github.com/microsoft/monaco-typescript/blob/master/scripts/importTypescript.js - // Currently based on 778ace1 on Apr 25 2020 + // Currently based on cc8da6b on June 6 2021 const generatedNote = `// // **NOTE**: Do not edit directly! This file is generated using \`npm run import-typescript\` @@ -42,8 +48,10 @@ function updateTSDist() { } importLibs(); - const npmLsOutput = JSON.parse(child_process.execSync("npm ls typescript --depth=0 --json=true").toString()); - const typeScriptDependencyVersion = npmLsOutput.dependencies.typescript.version; + const npmLsOutput = JSON.parse( + child_process.execSync('npm ls typescript --depth=0 --json=true').toString() + ); + const typeScriptDependencyVersion = npmLsOutput.version; fs.writeFileSync( path.join(TYPESCRIPT_LIB_DESTINATION, 'typescriptServicesMetadata.ts'), @@ -51,42 +59,68 @@ function updateTSDist() { export const typescriptVersion = "${typeScriptDependencyVersion}";\n` ); - var tsServices = fs.readFileSync(path.join(TYPESCRIPT_LIB_SOURCE, 'typescriptServices.js')).toString(); + let tsServices = fs + .readFileSync(path.join(TYPESCRIPT_LIB_SOURCE, 'typescriptServices.js')) + .toString(); // Ensure we never run into the node system... // (this also removes require calls that trick webpack into shimming those modules...) - tsServices = ( - tsServices.replace(/\n ts\.sys =([^]*)\n \}\)\(\);/m, `\n // MONACOCHANGE\n ts.sys = undefined;\n // END MONACOCHANGE`) + tsServices = tsServices.replace( + /\n ts\.sys =([^]*)\n \}\)\(\);/m, + `\n // MONACOCHANGE\n ts.sys = undefined;\n // END MONACOCHANGE` ); // Eliminate more require() calls... - tsServices = tsServices.replace(/^( +)etwModule = require\(.*$/m, '$1// MONACOCHANGE\n$1etwModule = undefined;\n$1// END MONACOCHANGE'); - tsServices = tsServices.replace(/^( +)var result = ts\.sys\.require\(.*$/m, '$1// MONACOCHANGE\n$1var result = undefined;\n$1// END MONACOCHANGE'); + tsServices = tsServices.replace( + /^( +)etwModule = require\(.*$/m, + '$1// MONACOCHANGE\n$1etwModule = undefined;\n$1// END MONACOCHANGE' + ); + tsServices = tsServices.replace( + /^( +)var result = ts\.sys\.require\(.*$/m, + '$1// MONACOCHANGE\n$1var result = undefined;\n$1// END MONACOCHANGE' + ); + tsServices = tsServices.replace( + /^( +)fs = require\("fs"\);$/m, + '$1// MONACOCHANGE\n$1fs = undefined;\n$1// END MONACOCHANGE' + ); + tsServices = tsServices.replace( + /^( +)debugger;$/m, + '$1// MONACOCHANGE\n$1// debugger;\n$1// END MONACOCHANGE' + ); + tsServices = tsServices.replace( + /= require\("perf_hooks"\)/m, + '/* MONACOCHANGE */= {}/* END MONACOCHANGE */' + ); // Flag any new require calls (outside comments) so they can be corrected preemptively. // To avoid missing cases (or using an even more complex regex), temporarily remove comments // about require() and then check for lines actually calling require(). // \/[*/] matches the start of a comment (single or multi-line). // ^\s+\*[^/] matches (presumably) a later line of a multi-line comment. - const tsServicesNoCommentedRequire = tsServices.replace(/(\/[*/]|^\s+\*[^/]).*\brequire\(.*/gm, ''); - const linesWithRequire = tsServicesNoCommentedRequire.match(/^.*?\brequire\(.*$/gm) + const tsServicesNoCommentedRequire = tsServices.replace( + /(\/[*/]|^\s+\*[^/]).*\brequire\(.*/gm, + '' + ); + const linesWithRequire = tsServicesNoCommentedRequire.match(/^.*?\brequire\(.*$/gm); // Allow error messages to include references to require() in their strings - const runtimeRequires = linesWithRequire && linesWithRequire.filter(l => !l.includes(": diag(")) + const runtimeRequires = + linesWithRequire && + linesWithRequire.filter((l) => !l.includes(': diag(') && !l.includes('ts.DiagnosticCategory')); - if (runtimeRequires && runtimeRequires.length) { - console.error('Found new require() calls on the following lines. These should be removed to avoid breaking webpack builds.\n'); - console.error(linesWithRequire.join('\n')); + if (runtimeRequires && runtimeRequires.length && linesWithRequire) { + console.error( + 'Found new require() calls on the following lines. These should be removed to avoid breaking webpack builds.\n' + ); + console.error( + runtimeRequires.map((r) => `${r} (${tsServicesNoCommentedRequire.indexOf(r)})`).join('\n') + ); process.exit(1); } - // Make sure process.args don't get called in the browser, this - // should only happen in TS 2.6.2 - const beforeProcess = `ts.perfLogger.logInfoEvent("Starting TypeScript v" + ts.versionMajorMinor + " with command line: " + JSON.stringify(process.argv));` - const afterProcess = `// MONACOCHANGE\n ts.perfLogger.logInfoEvent("Starting TypeScript v" + ts.versionMajorMinor + " with command line: " + JSON.stringify([]));\n// END MONACOCHANGE` - tsServices = tsServices.replace(beforeProcess, afterProcess); - - var tsServices_amd = generatedNote + tsServices + + const tsServices_amd = + generatedNote + + tsServices + ` // MONACOCHANGE // Defining the entire module name because r.js has an issue and cannot bundle this file @@ -94,9 +128,14 @@ function updateTSDist() { define("vs/language/typescript/lib/typescriptServices", [], function() { return ts; }); // END MONACOCHANGE `; - fs.writeFileSync(path.join(TYPESCRIPT_LIB_DESTINATION, 'typescriptServices-amd.js'), tsServices_amd); + fs.writeFileSync( + path.join(TYPESCRIPT_LIB_DESTINATION, 'typescriptServices-amd.js'), + stripSourceMaps(tsServices_amd) + ); - var tsServices_esm = generatedNote + tsServices + + const tsServices_esm = + generatedNote + + tsServices + ` // MONACOCHANGE export var createClassifier = ts.createClassifier; @@ -110,124 +149,57 @@ function updateTSDist() { export var TokenClass = ts.TokenClass; // END MONACOCHANGE `; - fs.writeFileSync(path.join(TYPESCRIPT_LIB_DESTINATION, 'typescriptServices.js'), tsServices_esm); + fs.writeFileSync( + path.join(TYPESCRIPT_LIB_DESTINATION, 'typescriptServices.js'), + stripSourceMaps(tsServices_esm) + ); - var dtsServices = fs.readFileSync(path.join(TYPESCRIPT_LIB_SOURCE, 'typescriptServices.d.ts')).toString(); - dtsServices += - ` + let dtsServices = fs + .readFileSync(path.join(TYPESCRIPT_LIB_SOURCE, 'typescriptServices.d.ts')) + .toString(); + dtsServices += ` // MONACOCHANGE export = ts; // END MONACOCHANGE `; - fs.writeFileSync(path.join(TYPESCRIPT_LIB_DESTINATION, 'typescriptServices.d.ts'), generatedNote + dtsServices); - + fs.writeFileSync( + path.join(TYPESCRIPT_LIB_DESTINATION, 'typescriptServices.d.ts'), + generatedNote + dtsServices + ); })(); function importLibs() { - function getFileName(name) { - return (name === '' ? 'lib.d.ts' : `lib.${name}.d.ts`); - } - function getVariableName(name) { - return (name === '' ? 'lib_dts' : `lib_${name.replace(/\./g, '_')}_dts`); - } function readLibFile(name) { - var srcPath = path.join(TYPESCRIPT_LIB_SOURCE, getFileName(name)); + const srcPath = path.join(TYPESCRIPT_LIB_SOURCE, name); return fs.readFileSync(srcPath).toString(); } - var queue = []; - var in_queue = {}; - - var enqueue = function (name) { - if (in_queue[name]) { - return; - } - in_queue[name] = true; - queue.push(name); - }; - - enqueue(''); - enqueue('es2015'); - - var result = []; - while (queue.length > 0) { - var name = queue.shift(); - var contents = readLibFile(name); - var lines = contents.split(/\r\n|\r|\n/); - - var output = ''; - var writeOutput = function (text) { - if (output.length === 0) { - output = text; - } else { - output += ` + ${text}`; - } - }; - var outputLines = []; - var flushOutputLines = function () { - writeOutput(`"${escapeText(outputLines.join('\n'))}"`); - outputLines = []; - }; - var deps = []; - for (let i = 0; i < lines.length; i++) { - let m = lines[i].match(/\/\/\/\s* 0) { - for (let i = result.length - 1; i >= 0; i--) { - if (result[i].deps.length === 0) { - // emit this node - strResult += `\nexport const ${result[i].name}: string = ${result[i].output};\n`; - - // mark dep as resolved - for (let j = 0; j < result.length; j++) { - for (let k = 0; k < result[j].deps.length; k++) { - if (result[j].deps[k] === result[i].name) { - result[j].deps.splice(k, 1); - break; - } - } - } - - // remove from result - result.splice(i, 1); - break; - } - } + ${generatedNote} + /** Contains all the lib files */ + export const libFileMap: Record = {} + `; + let strIndexResult = `/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + ${generatedNote} + /** Contains all the lib files */ + export const libFileSet: Record = {} + `; + const dtsFiles = fs.readdirSync(TYPESCRIPT_LIB_SOURCE).filter((f) => f.includes('lib.')); + while (dtsFiles.length > 0) { + const name = dtsFiles.shift(); + const output = readLibFile(name).replace(/\r\n/g, '\n'); + strLibResult += `libFileMap['${name}'] = "${escapeText(output)}";\n`; + strIndexResult += `libFileSet['${name}'] = true;\n`; } - strResult += ` - /** This is the DTS which is used when the target is ES6 or below */ - export const lib_es5_bundled_dts = lib_dts; - - /** This is the DTS which is used by default in monaco-typescript, and when the target is 2015 or above */ - export const lib_es2015_bundled_dts = lib_es2015_dts + "" + lib_dom_dts + "" + lib_webworker_importscripts_dts + "" + lib_scripthost_dts + ""; - ` - - var dstPath = path.join(TYPESCRIPT_LIB_DESTINATION, 'lib.ts'); - fs.writeFileSync(dstPath, strResult); + fs.writeFileSync(path.join(TYPESCRIPT_LIB_DESTINATION, 'lib.ts'), strLibResult); + fs.writeFileSync(path.join(TYPESCRIPT_LIB_DESTINATION, 'lib.index.ts'), strIndexResult); } /** @@ -235,19 +207,23 @@ function updateTSDist() { */ function escapeText(text) { // See http://www.javascriptkit.com/jsref/escapesequence.shtml - var _backspace = '\b'.charCodeAt(0); - var _formFeed = '\f'.charCodeAt(0); - var _newLine = '\n'.charCodeAt(0); - var _nullChar = 0; - var _carriageReturn = '\r'.charCodeAt(0); - var _tab = '\t'.charCodeAt(0); - var _verticalTab = '\v'.charCodeAt(0); - var _backslash = '\\'.charCodeAt(0); - var _doubleQuote = '"'.charCodeAt(0); + const _backspace = '\b'.charCodeAt(0); + const _formFeed = '\f'.charCodeAt(0); + const _newLine = '\n'.charCodeAt(0); + const _nullChar = 0; + const _carriageReturn = '\r'.charCodeAt(0); + const _tab = '\t'.charCodeAt(0); + const _verticalTab = '\v'.charCodeAt(0); + const _backslash = '\\'.charCodeAt(0); + const _doubleQuote = '"'.charCodeAt(0); - var startPos = 0, chrCode, replaceWith = null, resultPieces = []; + const len = text.length; + let startPos = 0; + let chrCode; + let replaceWith = null; + let resultPieces = []; - for (var i = 0, len = text.length; i < len; i++) { + for (let i = 0; i < len; i++) { chrCode = text.charCodeAt(i); switch (chrCode) { case _backspace: @@ -288,7 +264,10 @@ function updateTSDist() { resultPieces.push(text.substring(startPos, len)); return resultPieces.join(''); } - + + function stripSourceMaps(str) { + return str.replace(/\/\/# sourceMappingURL[^\n]+/gm, ''); + } /// End of import } @@ -298,7 +277,18 @@ fs.watchFile(services, () =>{ updateTSDist() }) +// We need to re-direct non TSC JS requests back to a real copy of +// monaco, so grab the list of official releases from the TS CDN +// and use the latest stable release, as that is most likely the +// closest version to your dev build +let latestStable = "4.3.2" +nodeFetch('https://typescript.azureedge.net/indexes/releases.json').then(req => req.json()).then(releases => { + latestStable = releases.versions.pop() +}); + http.createServer(function (req, res) { + res.setHeader("Access-Control-Allow-Origin", "*") + const incoming = url.parse(req.url) if (incoming.path.endsWith("typescriptServices.js")) { // Use the built version @@ -308,7 +298,7 @@ http.createServer(function (req, res) { } else { // Redirect to the TS CDN res.writeHead(302, { - 'Location': `https://typescript.azureedge.net/cdn/3.9.2/monaco/${incoming.path}` + 'Location': `https://typescript.azureedge.net/cdn/${latestStable}/monaco${incoming.path}` }); } @@ -317,6 +307,7 @@ http.createServer(function (req, res) { console.log("Starting servers\n") console.log(" - [✓] file watcher: " + services) +updateTSDist() console.log(" - [✓] http server: http://localhost:5615") console.log("\n\nGet started: http://www.staging-typescript.org/play?ts=dev")