11// @ts -check
2- import path from "path" ;
3- import fs from "fs" ;
2+ import { CancelToken } from "@esfx/canceltoken" ;
3+ import chalk from "chalk" ;
4+ import chokidar from "chokidar" ;
45import del from "del" ;
5- import { task } from "hereby" ;
6+ import esbuild from "esbuild" ;
7+ import { EventEmitter } from "events" ;
8+ import fs from "fs" ;
9+ import fsExtra from "fs-extra" ;
610import _glob from "glob" ;
11+ import { task } from "hereby" ;
12+ import path from "path" ;
713import util from "util" ;
8- import chalk from "chalk" ;
9- import { Debouncer , Deferred , exec , getDiffTool , getDirSize , memoize , needsUpdate , readJson } from "./scripts/build/utils.mjs" ;
10- import { localBaseline , localRwcBaseline , refBaseline , refRwcBaseline , runConsoleTests } from "./scripts/build/tests.mjs" ;
11- import { buildProject , cleanProject , watchProject } from "./scripts/build/projects.mjs" ;
14+
1215import { localizationDirectories } from "./scripts/build/localization.mjs" ;
1316import cmdLineOptions from "./scripts/build/options.mjs" ;
14- import esbuild from "esbuild" ;
15- import chokidar from "chokidar" ;
16- import { EventEmitter } from "events" ;
17- import { CancelToken } from "@esfx/canceltoken" ;
17+ import { buildProject , cleanProject , watchProject } from "./scripts/build/projects.mjs" ;
18+ import { localBaseline , localRwcBaseline , refBaseline , refRwcBaseline , runConsoleTests } from "./scripts/build/tests.mjs" ;
19+ import { Debouncer , Deferred , exec , getDiffTool , getDirSize , memoize , needsUpdate , readJson } from "./scripts/build/utils.mjs" ;
1820
1921const glob = util . promisify ( _glob ) ;
2022
@@ -58,10 +60,7 @@ export const generateLibs = task({
5860
5961 for ( const source of lib . sources ) {
6062 const contents = await fs . promises . readFile ( source , "utf-8" ) ;
61- // TODO(jakebailey): "\n\n" is for compatibility with our current tests; our test baselines
62- // are sensitive to the positions of things in the lib files. Eventually remove this,
63- // or remove lib.d.ts line numbers from our baselines.
64- output += "\n\n" + contents . replace ( / \r \n / g, "\n" ) ;
63+ output += "\n" + contents . replace ( / \r \n / g, "\n" ) ;
6564 }
6665
6766 await fs . promises . writeFile ( lib . target , output ) ;
@@ -160,10 +159,9 @@ async function runDtsBundler(entrypoint, output) {
160159 * @param {BundlerTaskOptions } [taskOptions]
161160 *
162161 * @typedef BundlerTaskOptions
163- * @property {string[] } [external]
164162 * @property {boolean } [exportIsTsObject]
165163 * @property {boolean } [treeShaking]
166- * @property {esbuild.WatchMode } [watchMode ]
164+ * @property {() => void } [onWatchRebuild ]
167165 */
168166function createBundler ( entrypoint , outfile , taskOptions = { } ) {
169167 const getOptions = memoize ( async ( ) => {
@@ -179,53 +177,9 @@ function createBundler(entrypoint, outfile, taskOptions = {}) {
179177 sourcemap : "linked" ,
180178 sourcesContent : false ,
181179 treeShaking : taskOptions . treeShaking ,
182- external : [
183- ...( taskOptions . external ?? [ ] ) ,
184- "source-map-support" ,
185- ] ,
180+ packages : "external" ,
186181 logLevel : "warning" ,
187182 // legalComments: "none", // If we add copyright headers to the source files, uncomment.
188- plugins : [
189- {
190- name : "no-node-modules" ,
191- setup : ( build ) => {
192- build . onLoad ( { filter : / [ \\ / ] n o d e _ m o d u l e s [ \\ / ] / } , ( ) => {
193- // Ideally, we'd use "--external:./node_modules/*" here, but that doesn't work; we
194- // will instead end up with paths to node_modules rather than the package names.
195- // Instead, we'll return a load error when we see that we're trying to bundle from
196- // node_modules, then explicitly declare which external dependencies we rely on, which
197- // ensures that the correct module specifier is kept in the output (the non-wildcard
198- // form works properly). It also helps us keep tabs on what external dependencies we
199- // may be importing, which is handy.
200- //
201- // See: https://github.com/evanw/esbuild/issues/1958
202- return {
203- errors : [ { text : 'Attempted to bundle from node_modules; ensure "external" is set correctly.' } ]
204- } ;
205- } ) ;
206- }
207- } ,
208- {
209- name : "fix-require" ,
210- setup : ( build ) => {
211- build . onEnd ( async ( ) => {
212- // esbuild converts calls to "require" to "__require"; this function
213- // calls the real require if it exists, or throws if it does not (rather than
214- // throwing an error like "require not defined"). But, since we want typescript
215- // to be consumable by other bundlers, we need to convert these calls back to
216- // require so our imports are visible again.
217- //
218- // The leading spaces are to keep the offsets the same within the files to keep
219- // source maps working (though this only really matters for the line the require is on).
220- //
221- // See: https://github.com/evanw/esbuild/issues/1905
222- let contents = await fs . promises . readFile ( outfile , "utf-8" ) ;
223- contents = contents . replace ( / _ _ r e q u i r e \( / g, " require(" ) ;
224- await fs . promises . writeFile ( outfile , contents ) ;
225- } ) ;
226- } ,
227- }
228- ]
229183 } ;
230184
231185 if ( taskOptions . exportIsTsObject ) {
@@ -235,14 +189,61 @@ function createBundler(entrypoint, outfile, taskOptions = {}) {
235189 options . globalName = "ts" ;
236190 // If we are in a CJS context, export the ts namespace.
237191 options . footer = { js : `\nif (typeof module !== "undefined" && module.exports) { module.exports = ts; }` } ;
192+
193+ // esbuild converts calls to "require" to "__require"; this function
194+ // calls the real require if it exists, or throws if it does not (rather than
195+ // throwing an error like "require not defined"). But, since we want typescript
196+ // to be consumable by other bundlers, we need to convert these calls back to
197+ // require so our imports are visible again.
198+ //
199+ // The leading spaces are to keep the offsets the same within the files to keep
200+ // source maps working (though this only really matters for the line the require is on).
201+ //
202+ // See: https://github.com/evanw/esbuild/issues/1905
203+ options . define = { require : "$$require" } ;
204+ options . plugins = [
205+ {
206+ name : "fix-require" ,
207+ setup : ( build ) => {
208+ build . onEnd ( async ( ) => {
209+ let contents = await fs . promises . readFile ( outfile , "utf-8" ) ;
210+ contents = contents . replace ( / \$ \$ r e q u i r e / g, " require" ) ;
211+ await fs . promises . writeFile ( outfile , contents ) ;
212+ } ) ;
213+ } ,
214+ }
215+ ] ;
238216 }
239217
240218 return options ;
241219 } ) ;
242220
243221 return {
244222 build : async ( ) => esbuild . build ( await getOptions ( ) ) ,
245- watch : async ( ) => esbuild . build ( { ...await getOptions ( ) , watch : taskOptions . watchMode ?? true , logLevel : "info" } ) ,
223+ watch : async ( ) => {
224+ /** @type {esbuild.BuildOptions } */
225+ const options = { ...await getOptions ( ) , logLevel : "info" } ;
226+ if ( taskOptions . onWatchRebuild ) {
227+ const onRebuild = taskOptions . onWatchRebuild ;
228+ options . plugins = ( options . plugins ?. slice ( 0 ) ?? [ ] ) . concat ( [ {
229+ name : "watch" ,
230+ setup : ( build ) => {
231+ let firstBuild = true ;
232+ build . onEnd ( ( ) => {
233+ if ( firstBuild ) {
234+ firstBuild = false ;
235+ }
236+ else {
237+ onRebuild ( ) ;
238+ }
239+ } ) ;
240+ }
241+ } ] ) ;
242+ }
243+
244+ const ctx = await esbuild . context ( options ) ;
245+ ctx . watch ( ) ;
246+ } ,
246247 } ;
247248}
248249
@@ -448,18 +449,8 @@ const { main: tests, watch: watchTests } = entrypointBuildTask({
448449 bundlerOptions : {
449450 // Ensure we never drop any dead code, which might be helpful while debugging.
450451 treeShaking : false ,
451- // These are directly imported via import statements and should not be bundled.
452- external : [
453- "chai" ,
454- "del" ,
455- "diff" ,
456- "mocha" ,
457- "ms" ,
458- ] ,
459- watchMode : {
460- onRebuild ( ) {
461- watchTestsEmitter . emit ( "rebuild" ) ;
462- }
452+ onWatchRebuild ( ) {
453+ watchTestsEmitter . emit ( "rebuild" ) ;
463454 }
464455 } ,
465456} ) ;
@@ -524,6 +515,7 @@ const { main: watchGuard, watch: watchWatchGuard } = entrypointBuildTask({
524515export const generateTypesMap = task ( {
525516 name : "generate-types-map" ,
526517 run : async ( ) => {
518+ await fs . promises . mkdir ( "./built/local" , { recursive : true } ) ;
527519 const source = "src/server/typesMap.json" ;
528520 const target = "built/local/typesMap.json" ;
529521 const contents = await fs . promises . readFile ( source , "utf-8" ) ;
@@ -849,13 +841,6 @@ export const lkg = task({
849841 dependencies : [ produceLKG ] ,
850842} ) ;
851843
852- export const generateSpec = task ( {
853- name : "generate-spec" ,
854- description : "Generates a Markdown version of the Language Specification" ,
855- hiddenFromTaskList : true ,
856- run : ( ) => exec ( "cscript" , [ "//nologo" , "scripts/word2md.mjs" , path . resolve ( "doc/TypeScript Language Specification - ARCHIVED.docx" ) , path . resolve ( "doc/spec-ARCHIVED.md" ) ] ) ,
857- } ) ;
858-
859844export const cleanBuilt = task ( {
860845 name : "clean-built" ,
861846 hiddenFromTaskList : true ,
@@ -892,3 +877,14 @@ export const help = task({
892877 hiddenFromTaskList : true ,
893878 run : ( ) => exec ( "hereby" , [ "--tasks" ] , { hidePrompt : true } ) ,
894879} ) ;
880+
881+ export const bumpLkgToNightly = task ( {
882+ name : "bump-lkg-to-nightly" ,
883+ description : "Bumps typescript in package.json to the latest nightly and copies it to LKG." ,
884+ run : async ( ) => {
885+ await exec ( "npm" , [ "install" , "--save-dev" , "--save-exact" , "typescript@next" ] ) ;
886+ await fs . promises . rm ( "lib" , { recursive : true , force : true } ) ;
887+ await fsExtra . copy ( "node_modules/typescript/lib" , "lib" ) ;
888+ await fs . promises . writeFile ( "lib/.gitattributes" , "* text eol=lf" ) ;
889+ }
890+ } ) ;
0 commit comments