@@ -31,8 +31,8 @@ function getCopyrightHeader() {
31
31
const cleanTasks = [ ] ;
32
32
33
33
34
- // TODO(jakebailey): This is really gross. Waiting on https://github.com/microsoft/TypeScript/issues/25613,
35
- // or at least control over noEmit / emitDeclarationOnly in build mode.
34
+ // TODO(jakebailey): This is really gross. If the build is cancelled (i.e. Ctrl+C), the modification will persist.
35
+ // Waiting on: https://github.com/microsoft/TypeScript/issues/51164
36
36
let currentlyBuilding = 0 ;
37
37
let oldTsconfigBase ;
38
38
@@ -180,18 +180,18 @@ async function runDtsBundler(entrypoint, output) {
180
180
}
181
181
182
182
/**
183
+ * @typedef {{
184
+ external?: string[];
185
+ exportIsTsObject?: boolean;
186
+ setDynamicImport?: boolean;
187
+ }} ESBuildTaskOptions
183
188
* @param {string } entrypoint
184
189
* @param {string } outfile
185
- * @param {boolean } exportIsTsObject True if this file exports the TS object and should have relevant code injected.
190
+ * @param {ESBuildTaskOptions | undefined } [taskOptions]
186
191
*/
187
- function esbuildTask ( entrypoint , outfile , exportIsTsObject = false ) {
192
+ function esbuildTask ( entrypoint , outfile , taskOptions = { } ) {
188
193
return {
189
194
build : async ( ) => {
190
- // Note: we do not use --minify, as that would hide function names from user backtraces
191
- // (we don't ship our sourcemaps), and would break consumers like monaco which modify
192
- // typescript.js for their own needs. Also, using --sourcesContent=false doesn't help,
193
- // as even though it's a smaller source map that could be shipped to users for better
194
- // stack traces via names, the maps are bigger than the actual source files themselves.
195
195
/** @type {esbuild.BuildOptions } */
196
196
const options = {
197
197
entryPoints : [ entrypoint ] ,
@@ -202,14 +202,37 @@ async function runDtsBundler(entrypoint, output) {
202
202
target : "es2018" , // Covers Node 10.
203
203
format : "cjs" ,
204
204
sourcemap : "linked" ,
205
- external : [ "./node_modules/*" ] ,
206
- conditions : [ "require" ] ,
205
+ sourcesContent : false ,
206
+ external : [
207
+ ...( taskOptions . external ?? [ ] ) ,
208
+ "source-map-support" ,
209
+ ] ,
207
210
supported : {
208
211
// "const-and-let": false, // https://github.com/evanw/esbuild/issues/297
209
212
"object-rest-spread" : false , // Performance enhancement, see: https://github.com/evanw/esbuild/releases/tag/v0.14.46
210
213
} ,
214
+ logLevel : "warning" ,
211
215
// legalComments: "none", // If we add copyright headers to the source files, uncomment.
212
216
plugins : [
217
+ {
218
+ name : "no-node-modules" ,
219
+ setup : ( build ) => {
220
+ build . onLoad ( { filter : / [ \\ / ] n o d e _ m o d u l e s [ \\ / ] / } , ( ) => {
221
+ // Ideally, we'd use "--external:./node_modules/*" here, but that doesn't work; we
222
+ // will instead end up with paths to node_modules rather than the package names.
223
+ // Instead, we'll return a load error when we see that we're trying to bundle from
224
+ // node_modules, then explicitly declare which external dependencies we rely on, which
225
+ // ensures that the correct module specifier is kept in the output (the non-wildcard
226
+ // form works properly). It also helps us keep tabs on what external dependencies we
227
+ // may be importing, which is handy.
228
+ //
229
+ // See: https://github.com/evanw/esbuild/issues/1958
230
+ return {
231
+ errors : [ { text : 'Attempted to bundle from node_modules; ensure "external" is set correctly.' } ]
232
+ } ;
233
+ } ) ;
234
+ }
235
+ } ,
213
236
{
214
237
name : "fix-require" ,
215
238
setup : ( build ) => {
@@ -220,36 +243,36 @@ async function runDtsBundler(entrypoint, output) {
220
243
// to be consumable by other bundlers, we need to convert these calls back to
221
244
// require so our imports are visible again.
222
245
//
223
- // Note that this step breaks source maps, but only for lines that reference
224
- // "__require", which is an okay tradeoff for the performance of not running
225
- // the output through transpileModule/babel/etc.
246
+ // The leading spaces are to keep the offsets the same within the files to keep
247
+ // source maps working (though this only really matters for the line the require is on).
226
248
//
227
249
// See: https://github.com/evanw/esbuild/issues/1905
228
250
let contents = await fs . promises . readFile ( outfile , "utf-8" ) ;
229
- contents = contents . replace ( / _ _ r e q u i r e \( / g, "require(" ) ;
251
+ contents = contents . replace ( / _ _ r e q u i r e \( / g, " require(" ) ;
230
252
await fs . promises . writeFile ( outfile , contents ) ;
231
253
} ) ;
232
254
} ,
233
255
}
234
256
]
235
257
} ;
236
258
237
- if ( exportIsTsObject ) {
238
- options . format = "iife" ; // We use an IIFE so we can inject the code below.
259
+ if ( taskOptions . exportIsTsObject ) {
260
+ // These snippets cannot appear in the actual source files, otherwise they will be rewritten
261
+ // to things like exports or requires.
262
+
263
+ // If we are in a CJS context, export the ts namespace.
264
+ let footer = `\nif (typeof module !== "undefined" && module.exports) { module.exports = ts; }` ;
265
+
266
+ if ( taskOptions . setDynamicImport ) {
267
+ // If we are in a server bundle, inject the dynamicImport function.
268
+ // This only works because the web server's "start" function returns;
269
+ // the node server does not, but we don't use this there.
270
+ footer += `\nif (ts.server && ts.server.setDynamicImport) { ts.server.setDynamicImport(id => import(id)); }` ;
271
+ }
272
+
273
+ options . format = "iife" ; // We use an IIFE so we can inject the footer, and so that "ts" is global if not loaded as a module.
239
274
options . globalName = "ts" ; // Name the variable ts, matching our old big bundle and so we can use the code below.
240
- options . footer = {
241
- // These snippets cannot appear in the actual source files, otherwise they will be rewritten
242
- // to things like exports or requires.
243
- js : `
244
- if (typeof module !== "undefined" && module.exports) {
245
- // If we are in a CJS context, export the ts namespace.
246
- module.exports = ts;
247
- }
248
- if (ts.server) {
249
- // If we are in a server bundle, inject the dynamicImport function.
250
- ts.server.dynamicImport = id => import(id);
251
- }`
252
- } ;
275
+ options . footer = { js : footer } ;
253
276
}
254
277
255
278
await esbuild . build ( options ) ;
@@ -286,7 +309,7 @@ const cleanDebugTools = task({
286
309
cleanTasks . push ( cleanDebugTools ) ;
287
310
288
311
289
- const esbuildTsc = esbuildTask ( "./src/tsc/tsc.ts" , "./built/local/tsc.js" , /* exportIsTsObject */ true ) ;
312
+ const esbuildTsc = esbuildTask ( "./src/tsc/tsc.ts" , "./built/local/tsc.js" ) ;
290
313
291
314
export const buildTsc = task ( {
292
315
name : "tsc" ,
@@ -315,7 +338,7 @@ const buildServicesWithTsc = task({
315
338
316
339
// TODO(jakebailey): rename this; no longer "services".
317
340
318
- const esbuildServices = esbuildTask ( "./src/typescript/typescript.ts" , "./built/local/typescript.js" , /* exportIsTsObject */ true ) ;
341
+ const esbuildServices = esbuildTask ( "./src/typescript/typescript.ts" , "./built/local/typescript.js" , { exportIsTsObject : true } ) ;
319
342
320
343
export const buildServices = task ( {
321
344
name : "services" ,
@@ -343,7 +366,7 @@ export const dtsServices = task({
343
366
run : ( ) => runDtsBundler ( "./built/local/typescript/typescript.d.ts" , "./built/local/typescript.d.ts" ) ,
344
367
} ) ;
345
368
346
- const esbuildServer = esbuildTask ( "./src/tsserver/server.ts" , "./built/local/tsserver.js" , /* exportIsTsObject */ true ) ;
369
+ const esbuildServer = esbuildTask ( "./src/tsserver/server.ts" , "./built/local/tsserver.js" , { exportIsTsObject : true , setDynamicImport : true } ) ;
347
370
348
371
export const buildServer = task ( {
349
372
name : "tsserver" ,
@@ -384,7 +407,7 @@ const buildLsslWithTsc = task({
384
407
run : ( ) => buildProject ( "src/tsserverlibrary" ) ,
385
408
} ) ;
386
409
387
- const esbuildLssl = esbuildTask ( "./src/tsserverlibrary/tsserverlibrary.ts" , "./built/local/tsserverlibrary.js" , /* exportIsTsObject */ true ) ;
410
+ const esbuildLssl = esbuildTask ( "./src/tsserverlibrary/tsserverlibrary.ts" , "./built/local/tsserverlibrary.js" , { exportIsTsObject : true } ) ;
388
411
389
412
export const buildLssl = task ( {
390
413
name : "lssl" ,
@@ -418,7 +441,15 @@ export const dts = task({
418
441
419
442
420
443
const testRunner = "./built/local/run.js" ;
421
- const esbuildTests = esbuildTask ( "./src/testRunner/_namespaces/Harness.ts" , testRunner ) ;
444
+ const esbuildTests = esbuildTask ( "./src/testRunner/_namespaces/Harness.ts" , testRunner , {
445
+ external : [
446
+ "chai" ,
447
+ "del" ,
448
+ "diff" ,
449
+ "mocha" ,
450
+ "ms" ,
451
+ ] ,
452
+ } ) ;
422
453
423
454
export const buildTests = task ( {
424
455
name : "tests" ,
0 commit comments