@@ -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,10 +202,33 @@ 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
+ ] ,
210
+ logLevel : "warning" ,
207
211
// legalComments: "none", // If we add copyright headers to the source files, uncomment.
208
212
plugins : [
213
+ {
214
+ name : "no-node-modules" ,
215
+ setup : ( build ) => {
216
+ build . onLoad ( { filter : / [ \\ / ] n o d e _ m o d u l e s [ \\ / ] / } , ( ) => {
217
+ // Ideally, we'd use "--external:./node_modules/*" here, but that doesn't work; we
218
+ // will instead end up with paths to node_modules rather than the package names.
219
+ // Instead, we'll return a load error when we see that we're trying to bundle from
220
+ // node_modules, then explicitly declare which external dependencies we rely on, which
221
+ // ensures that the correct module specifier is kept in the output (the non-wildcard
222
+ // form works properly). It also helps us keep tabs on what external dependencies we
223
+ // may be importing, which is handy.
224
+ //
225
+ // See: https://github.com/evanw/esbuild/issues/1958
226
+ return {
227
+ errors : [ { text : 'Attempted to bundle from node_modules; ensure "external" is set correctly.' } ]
228
+ } ;
229
+ } ) ;
230
+ }
231
+ } ,
209
232
{
210
233
name : "fix-require" ,
211
234
setup : ( build ) => {
@@ -216,36 +239,36 @@ async function runDtsBundler(entrypoint, output) {
216
239
// to be consumable by other bundlers, we need to convert these calls back to
217
240
// require so our imports are visible again.
218
241
//
219
- // Note that this step breaks source maps, but only for lines that reference
220
- // "__require", which is an okay tradeoff for the performance of not running
221
- // the output through transpileModule/babel/etc.
242
+ // The leading spaces are to keep the offsets the same within the files to keep
243
+ // source maps working (though this only really matters for the line the require is on).
222
244
//
223
245
// See: https://github.com/evanw/esbuild/issues/1905
224
246
let contents = await fs . promises . readFile ( outfile , "utf-8" ) ;
225
- contents = contents . replace ( / _ _ r e q u i r e \( / g, "require(" ) ;
247
+ contents = contents . replace ( / _ _ r e q u i r e \( / g, " require(" ) ;
226
248
await fs . promises . writeFile ( outfile , contents ) ;
227
249
} ) ;
228
250
} ,
229
251
}
230
252
]
231
253
} ;
232
254
233
- if ( exportIsTsObject ) {
234
- options . format = "iife" ; // We use an IIFE so we can inject the code below.
255
+ if ( taskOptions . exportIsTsObject ) {
256
+ // These snippets cannot appear in the actual source files, otherwise they will be rewritten
257
+ // to things like exports or requires.
258
+
259
+ // If we are in a CJS context, export the ts namespace.
260
+ let footer = `\nif (typeof module !== "undefined" && module.exports) { module.exports = ts; }` ;
261
+
262
+ if ( taskOptions . setDynamicImport ) {
263
+ // If we are in a server bundle, inject the dynamicImport function.
264
+ // This only works because the web server's "start" function returns;
265
+ // the node server does not, but we don't use this there.
266
+ footer += `\nif (ts.server && ts.server.setDynamicImport) { ts.server.setDynamicImport(id => import(id)); }` ;
267
+ }
268
+
269
+ 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.
235
270
options . globalName = "ts" ; // Name the variable ts, matching our old big bundle and so we can use the code below.
236
- options . footer = {
237
- // These snippets cannot appear in the actual source files, otherwise they will be rewritten
238
- // to things like exports or requires.
239
- js : `
240
- if (typeof module !== "undefined" && module.exports) {
241
- // If we are in a CJS context, export the ts namespace.
242
- module.exports = ts;
243
- }
244
- if (ts.server) {
245
- // If we are in a server bundle, inject the dynamicImport function.
246
- ts.server.dynamicImport = id => import(id);
247
- }`
248
- } ;
271
+ options . footer = { js : footer } ;
249
272
}
250
273
251
274
await esbuild . build ( options ) ;
@@ -282,7 +305,7 @@ const cleanDebugTools = task({
282
305
cleanTasks . push ( cleanDebugTools ) ;
283
306
284
307
285
- const esbuildTsc = esbuildTask ( "./src/tsc/tsc.ts" , "./built/local/tsc.js" , /* exportIsTsObject */ true ) ;
308
+ const esbuildTsc = esbuildTask ( "./src/tsc/tsc.ts" , "./built/local/tsc.js" ) ;
286
309
287
310
export const buildTsc = task ( {
288
311
name : "tsc" ,
@@ -311,7 +334,7 @@ const buildServicesWithTsc = task({
311
334
312
335
// TODO(jakebailey): rename this; no longer "services".
313
336
314
- const esbuildServices = esbuildTask ( "./src/typescript/typescript.ts" , "./built/local/typescript.js" , /* exportIsTsObject */ true ) ;
337
+ const esbuildServices = esbuildTask ( "./src/typescript/typescript.ts" , "./built/local/typescript.js" , { exportIsTsObject : true } ) ;
315
338
316
339
export const buildServices = task ( {
317
340
name : "services" ,
@@ -339,7 +362,7 @@ export const dtsServices = task({
339
362
run : ( ) => runDtsBundler ( "./built/local/typescript/typescript.d.ts" , "./built/local/typescript.d.ts" ) ,
340
363
} ) ;
341
364
342
- const esbuildServer = esbuildTask ( "./src/tsserver/server.ts" , "./built/local/tsserver.js" , /* exportIsTsObject */ true ) ;
365
+ const esbuildServer = esbuildTask ( "./src/tsserver/server.ts" , "./built/local/tsserver.js" , { exportIsTsObject : true , setDynamicImport : true } ) ;
343
366
344
367
export const buildServer = task ( {
345
368
name : "tsserver" ,
@@ -380,7 +403,7 @@ const buildLsslWithTsc = task({
380
403
run : ( ) => buildProject ( "src/tsserverlibrary" ) ,
381
404
} ) ;
382
405
383
- const esbuildLssl = esbuildTask ( "./src/tsserverlibrary/tsserverlibrary.ts" , "./built/local/tsserverlibrary.js" , /* exportIsTsObject */ true ) ;
406
+ const esbuildLssl = esbuildTask ( "./src/tsserverlibrary/tsserverlibrary.ts" , "./built/local/tsserverlibrary.js" , { exportIsTsObject : true } ) ;
384
407
385
408
export const buildLssl = task ( {
386
409
name : "lssl" ,
@@ -414,7 +437,15 @@ export const dts = task({
414
437
415
438
416
439
const testRunner = "./built/local/run.js" ;
417
- const esbuildTests = esbuildTask ( "./src/testRunner/_namespaces/Harness.ts" , testRunner ) ;
440
+ const esbuildTests = esbuildTask ( "./src/testRunner/_namespaces/Harness.ts" , testRunner , {
441
+ external : [
442
+ "chai" ,
443
+ "del" ,
444
+ "diff" ,
445
+ "mocha" ,
446
+ "ms" ,
447
+ ] ,
448
+ } ) ;
418
449
419
450
export const buildTests = task ( {
420
451
name : "tests" ,
0 commit comments