mirror of
https://github.com/hanzoai/esbuild.git
synced 2026-09-24 16:58:50 +00:00
465 lines
14 KiB
JavaScript
465 lines
14 KiB
JavaScript
const { removeRecursiveSync } = require('./esbuild')
|
|
const child_process = require('child_process')
|
|
const path = require('path')
|
|
const fs = require('fs')
|
|
|
|
const tsconfigJson = {
|
|
compilerOptions: {
|
|
module: 'CommonJS',
|
|
strict: true,
|
|
},
|
|
}
|
|
|
|
const testsWithoutErrors = {
|
|
emptyBuildRequire: `
|
|
export {}
|
|
import esbuild = require('esbuild')
|
|
esbuild.buildSync({})
|
|
esbuild.build({})
|
|
`,
|
|
emptyBuildImport: `
|
|
import * as esbuild from 'esbuild'
|
|
esbuild.buildSync({})
|
|
esbuild.build({})
|
|
`,
|
|
emptyTransformRequire: `
|
|
export {}
|
|
import esbuild = require('esbuild')
|
|
esbuild.transformSync('')
|
|
esbuild.transformSync('', {})
|
|
esbuild.transform('')
|
|
esbuild.transform('', {})
|
|
`,
|
|
emptyTransformImport: `
|
|
import * as esbuild from 'esbuild'
|
|
esbuild.transformSync('')
|
|
esbuild.transformSync('', {})
|
|
esbuild.transform('')
|
|
esbuild.transform('', {})
|
|
`,
|
|
|
|
mangleCache: `
|
|
import * as esbuild from 'esbuild'
|
|
esbuild.buildSync({ mangleCache: {} }).mangleCache['x']
|
|
esbuild.build({ mangleCache: {} })
|
|
.then(result => result.mangleCache['x'])
|
|
esbuild.transformSync('', { mangleCache: {} }).mangleCache['x']
|
|
esbuild.transform('', { mangleCache: {} })
|
|
.then(result => result.mangleCache['x'])
|
|
`,
|
|
legalCommentsExternal: `
|
|
import * as esbuild from 'esbuild'
|
|
esbuild.transformSync('', { legalComments: 'external' }).legalComments.length
|
|
esbuild.transform('', { legalComments: 'external' })
|
|
.then(result => result.legalComments.length)
|
|
`,
|
|
writeFalseOutputFiles: `
|
|
import * as esbuild from 'esbuild'
|
|
esbuild.buildSync({ write: false }).outputFiles[0]
|
|
esbuild.build({ write: false })
|
|
.then(result => result.outputFiles[0])
|
|
`,
|
|
metafileTrue: `
|
|
import {build, buildSync, analyzeMetafile} from 'esbuild';
|
|
analyzeMetafile(buildSync({ metafile: true }).metafile)
|
|
build({ metafile: true })
|
|
.then(result => analyzeMetafile(result.metafile))
|
|
`,
|
|
|
|
contextMangleCache: `
|
|
import * as esbuild from 'esbuild'
|
|
esbuild.context({ mangleCache: {} })
|
|
.then(context => context.rebuild())
|
|
.then(result => result.mangleCache['x'])
|
|
`,
|
|
contextWriteFalseOutputFiles: `
|
|
import * as esbuild from 'esbuild'
|
|
esbuild.context({ write: false })
|
|
.then(context => context.rebuild())
|
|
.then(result => result.outputFiles[0])
|
|
`,
|
|
contextMetafileTrue: `
|
|
import {context, analyzeMetafile} from 'esbuild';
|
|
context({ metafile: true })
|
|
.then(context => context.rebuild())
|
|
.then(result => analyzeMetafile(result.metafile))
|
|
`,
|
|
|
|
allOptionsTransform: `
|
|
export {}
|
|
import {transform} from 'esbuild'
|
|
transform('', {
|
|
sourcemap: true,
|
|
format: 'iife',
|
|
globalName: '',
|
|
target: 'esnext',
|
|
minify: true,
|
|
minifyWhitespace: true,
|
|
minifyIdentifiers: true,
|
|
minifySyntax: true,
|
|
charset: 'utf8',
|
|
jsxFactory: '',
|
|
jsxFragment: '',
|
|
define: { 'x': 'y' },
|
|
pure: ['x'],
|
|
color: true,
|
|
logLevel: 'info',
|
|
logLimit: 0,
|
|
tsconfigRaw: {
|
|
compilerOptions: {
|
|
jsxFactory: '',
|
|
jsxFragmentFactory: '',
|
|
useDefineForClassFields: true,
|
|
importsNotUsedAsValues: 'preserve',
|
|
preserveValueImports: true,
|
|
},
|
|
},
|
|
sourcefile: '',
|
|
loader: 'ts',
|
|
}).then(result => {
|
|
let code: string = result.code;
|
|
let map: string = result.map;
|
|
for (let msg of result.warnings) {
|
|
let text: string = msg.text
|
|
if (msg.location !== null) {
|
|
let file: string = msg.location.file;
|
|
let namespace: string = msg.location.namespace;
|
|
let line: number = msg.location.line;
|
|
let column: number = msg.location.column;
|
|
let length: number = msg.location.length;
|
|
let lineText: string = msg.location.lineText;
|
|
}
|
|
}
|
|
})
|
|
`,
|
|
allOptionsBuild: `
|
|
export {}
|
|
import {build} from 'esbuild'
|
|
build({
|
|
sourcemap: true,
|
|
format: 'iife',
|
|
globalName: '',
|
|
target: 'esnext',
|
|
minify: true,
|
|
minifyWhitespace: true,
|
|
minifyIdentifiers: true,
|
|
minifySyntax: true,
|
|
charset: 'utf8',
|
|
jsxFactory: '',
|
|
jsxFragment: '',
|
|
define: { 'x': 'y' },
|
|
pure: ['x'],
|
|
color: true,
|
|
logLevel: 'info',
|
|
logLimit: 0,
|
|
bundle: true,
|
|
splitting: true,
|
|
outfile: '',
|
|
metafile: true,
|
|
outdir: '',
|
|
outbase: '',
|
|
platform: 'node',
|
|
external: ['x'],
|
|
loader: { 'x': 'ts' },
|
|
resolveExtensions: ['x'],
|
|
mainFields: ['x'],
|
|
write: true,
|
|
tsconfig: 'x',
|
|
outExtension: { 'x': 'y' },
|
|
publicPath: 'x',
|
|
inject: ['x'],
|
|
entryPoints: ['x'],
|
|
stdin: {
|
|
contents: '',
|
|
resolveDir: '',
|
|
sourcefile: '',
|
|
loader: 'ts',
|
|
},
|
|
plugins: [
|
|
{
|
|
name: 'x',
|
|
setup(build) {
|
|
build.onStart(() => {})
|
|
build.onStart(async () => {})
|
|
build.onStart(() => ({ warnings: [{text: '', location: {file: '', line: 0}}] }))
|
|
build.onStart(async () => ({ warnings: [{text: '', location: {file: '', line: 0}}] }))
|
|
build.onEnd(result => {})
|
|
build.onEnd(async result => {})
|
|
build.onLoad({filter: /./}, () => undefined)
|
|
build.onResolve({filter: /./, namespace: ''}, args => {
|
|
let path: string = args.path;
|
|
let importer: string = args.importer;
|
|
let namespace: string = args.namespace;
|
|
let resolveDir: string = args.resolveDir;
|
|
if (Math.random()) return
|
|
if (Math.random()) return {}
|
|
return {
|
|
pluginName: '',
|
|
errors: [
|
|
{},
|
|
{text: ''},
|
|
{text: '', location: {}},
|
|
{location: {file: '', line: 0}},
|
|
{location: {file: '', namespace: '', line: 0, column: 0, length: 0, lineText: ''}},
|
|
],
|
|
warnings: [
|
|
{},
|
|
{text: ''},
|
|
{text: '', location: {}},
|
|
{location: {file: '', line: 0}},
|
|
{location: {file: '', namespace: '', line: 0, column: 0, length: 0, lineText: ''}},
|
|
],
|
|
path: '',
|
|
external: true,
|
|
namespace: '',
|
|
suffix: '',
|
|
}
|
|
})
|
|
build.onLoad({filter: /./, namespace: ''}, args => {
|
|
let path: string = args.path;
|
|
let namespace: string = args.namespace;
|
|
let suffix: string = args.suffix;
|
|
if (Math.random()) return
|
|
if (Math.random()) return {}
|
|
return {
|
|
pluginName: '',
|
|
errors: [
|
|
{},
|
|
{text: ''},
|
|
{text: '', location: {}},
|
|
{location: {file: '', line: 0}},
|
|
{location: {file: '', namespace: '', line: 0, column: 0, length: 0, lineText: ''}},
|
|
],
|
|
warnings: [
|
|
{},
|
|
{text: ''},
|
|
{text: '', location: {}},
|
|
{location: {file: '', line: 0}},
|
|
{location: {file: '', namespace: '', line: 0, column: 0, length: 0, lineText: ''}},
|
|
],
|
|
contents: '',
|
|
resolveDir: '',
|
|
loader: 'ts',
|
|
}
|
|
})
|
|
},
|
|
}
|
|
],
|
|
}).then(result => {
|
|
if (result.outputFiles !== undefined) {
|
|
for (let file of result.outputFiles) {
|
|
let path: string = file.path
|
|
let bytes: Uint8Array = file.contents
|
|
}
|
|
}
|
|
for (let msg of result.warnings) {
|
|
let text: string = msg.text
|
|
if (msg.location !== null) {
|
|
let file: string = msg.location.file;
|
|
let namespace: string = msg.location.namespace;
|
|
let line: number = msg.location.line;
|
|
let column: number = msg.location.column;
|
|
let length: number = msg.location.length;
|
|
let lineText: string = msg.location.lineText;
|
|
}
|
|
}
|
|
})
|
|
`,
|
|
objectEntryPointBuild: `
|
|
export {}
|
|
import {build} from 'esbuild'
|
|
build({
|
|
entryPoints: { x: 'x', y: 'z' },
|
|
})
|
|
`,
|
|
mixedEntryPointBuild: `
|
|
export {}
|
|
import {build} from 'esbuild'
|
|
build({
|
|
entryPoints: ['x', { in: 'y', out: 'z' }],
|
|
})
|
|
`,
|
|
}
|
|
|
|
const testsWithErrors = {
|
|
badBuildRequire_invalidOption: `
|
|
export {}
|
|
import esbuild = require('esbuild')
|
|
esbuild.build({ invalidOption: true })
|
|
`,
|
|
badBuildSyncRequire_invalidOption: `
|
|
export {}
|
|
import esbuild = require('esbuild')
|
|
esbuild.buildSync({ invalidOption: true })
|
|
`,
|
|
badBuildImport_invalidOption: `
|
|
import * as esbuild from 'esbuild'
|
|
esbuild.build({ invalidOption: true })
|
|
`,
|
|
badBuildSyncImport_invalidOption: `
|
|
import * as esbuild from 'esbuild'
|
|
esbuild.build({ invalidOption: true })
|
|
`,
|
|
badTransformRequire_invalidOption: `
|
|
export {}
|
|
import esbuild = require('esbuild')
|
|
esbuild.transform('', { invalidOption: true })
|
|
`,
|
|
badTransformSyncRequire_invalidOption: `
|
|
export {}
|
|
import esbuild = require('esbuild')
|
|
esbuild.transformSync('', { invalidOption: true })
|
|
`,
|
|
badTransformImport_invalidOption: `
|
|
import * as esbuild from 'esbuild'
|
|
esbuild.transform('', { invalidOption: true })
|
|
`,
|
|
badTransformSyncImport_invalidOption: `
|
|
import * as esbuild from 'esbuild'
|
|
esbuild.transformSync('', { invalidOption: true })
|
|
`,
|
|
|
|
// mangleCache
|
|
mangleCacheBuild_undefined: `
|
|
import * as esbuild from 'esbuild'
|
|
esbuild.build({}).then(result => result.mangleCache['x'])
|
|
`,
|
|
mangleCacheBuildSync_undefined: `
|
|
import * as esbuild from 'esbuild'
|
|
esbuild.buildSync({}).mangleCache['x']
|
|
`,
|
|
mangleCacheTransform_undefined: `
|
|
import * as esbuild from 'esbuild'
|
|
esbuild.transform('', {}).then(result => result.mangleCache['x'])
|
|
`,
|
|
mangleCacheTransformSync_undefined: `
|
|
import * as esbuild from 'esbuild'
|
|
esbuild.transformSync('', {}).mangleCache['x']
|
|
`,
|
|
|
|
// legalComments
|
|
legalCommentsTransform_undefined: `
|
|
import * as esbuild from 'esbuild'
|
|
esbuild.transform('', { legalComments: 'eof' }).then(result => result.legalComments.length)
|
|
`,
|
|
legalCommentsTransformSync_undefined: `
|
|
import * as esbuild from 'esbuild'
|
|
esbuild.transformSync('', { legalComments: 'eof' }).legalComments.length
|
|
`,
|
|
|
|
// outputFiles
|
|
outputFilesBuild_undefined: `
|
|
import * as esbuild from 'esbuild'
|
|
esbuild.build({}).then(result => result.outputFiles[0])
|
|
`,
|
|
outputFilesBuildSync_undefined: `
|
|
import * as esbuild from 'esbuild'
|
|
esbuild.buildSync({}).outputFiles[0]
|
|
`,
|
|
outputFilesWriteTrueBuild_undefined: `
|
|
import * as esbuild from 'esbuild'
|
|
esbuild.build({ write: true }).then(result => result.outputFiles[0])
|
|
`,
|
|
outputFilesWriteTrueBuildSync_undefined: `
|
|
import * as esbuild from 'esbuild'
|
|
esbuild.buildSync({ write: true }).outputFiles[0]
|
|
`,
|
|
|
|
// metafile
|
|
metafileBuild_undefined: `
|
|
import * as esbuild from 'esbuild'
|
|
esbuild.build({}).then(result => esbuild.analyzeMetafile(result.metafile))
|
|
`,
|
|
metafileBuildSync_undefined: `
|
|
import * as esbuild from 'esbuild'
|
|
esbuild.analyzeMetafile(esbuild.buildSync({}).metafile)
|
|
`,
|
|
metafileFalseBuild_undefined: `
|
|
import * as esbuild from 'esbuild'
|
|
esbuild.build({ metafile: false }).then(result => esbuild.analyzeMetafile(result.metafile))
|
|
`,
|
|
metafileFalseBuildSync_undefined: `
|
|
import * as esbuild from 'esbuild'
|
|
esbuild.analyzeMetafile(esbuild.buildSync({ metafile: false }).metafile)
|
|
`,
|
|
}
|
|
|
|
async function main() {
|
|
let testDir = path.join(__dirname, '.ts-types-test')
|
|
removeRecursiveSync(testDir)
|
|
fs.mkdirSync(testDir, { recursive: true })
|
|
|
|
const types = fs.readFileSync(path.join(__dirname, '..', 'lib', 'shared', 'types.ts'), 'utf8')
|
|
const tsc = path.join(__dirname, 'node_modules', 'typescript', 'lib', 'tsc.js')
|
|
const esbuild_d_ts = path.join(testDir, 'node_modules', 'esbuild', 'index.d.ts')
|
|
fs.mkdirSync(path.dirname(esbuild_d_ts), { recursive: true })
|
|
fs.writeFileSync(esbuild_d_ts, types)
|
|
let allTestsPassed = true
|
|
|
|
// Check tests without errors
|
|
if (allTestsPassed) {
|
|
const dir = path.join(testDir, 'without-errors')
|
|
fs.mkdirSync(dir, { recursive: true })
|
|
fs.writeFileSync(path.join(dir, 'tsconfig.json'), JSON.stringify(tsconfigJson))
|
|
for (const name in testsWithoutErrors) {
|
|
const input = path.join(dir, name + '.ts')
|
|
fs.writeFileSync(input, testsWithoutErrors[name])
|
|
}
|
|
allTestsPassed &&= await new Promise(resolve => {
|
|
const child = child_process.spawn('node', [tsc, '--project', '.'], { cwd: dir, stdio: 'inherit' })
|
|
child.on('close', exitCode => resolve(exitCode === 0))
|
|
})
|
|
}
|
|
|
|
// Check tests with errors
|
|
if (allTestsPassed) {
|
|
const dir = path.join(testDir, 'with-errors')
|
|
fs.mkdirSync(dir, { recursive: true })
|
|
fs.writeFileSync(path.join(dir, 'tsconfig.json'), JSON.stringify(tsconfigJson))
|
|
for (const name in testsWithErrors) {
|
|
const input = path.join(dir, name.split('_')[0] + '.ts')
|
|
fs.writeFileSync(input, testsWithErrors[name])
|
|
}
|
|
try {
|
|
child_process.execFileSync('node', [tsc, '--project', '.'], { cwd: dir })
|
|
throw new Error('Expected an error to be generated')
|
|
} catch (err) {
|
|
const stdout = err.stdout.toString()
|
|
const lines = stdout.split('\n')
|
|
next: for (const name in testsWithErrors) {
|
|
const fileName = name.split('_')[0]
|
|
const expectedText = name.split('_')[1]
|
|
for (const line of lines) {
|
|
if (line.includes(fileName)) {
|
|
if (line.includes(expectedText)) {
|
|
console.log(`\x1B[32mSUCCESS:\x1B[0m ${line}`)
|
|
} else {
|
|
console.log(`\x1B[31mFAILURE: ${line}\x1B[0m`)
|
|
allTestsPassed = false
|
|
}
|
|
continue next
|
|
}
|
|
}
|
|
console.log(`\x1B[31mFAILURE:\x1B[0m ${name}: Could not find expected error in output from "tsc":`)
|
|
process.stdout.write(stdout)
|
|
allTestsPassed = false
|
|
break next
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!allTestsPassed) {
|
|
console.error(`❌ typescript type tests failed`)
|
|
process.exit(1)
|
|
} else {
|
|
console.log(`✅ typescript type tests passed`)
|
|
removeRecursiveSync(testDir)
|
|
}
|
|
}
|
|
|
|
main().catch(e => {
|
|
setTimeout(() => {
|
|
throw e
|
|
})
|
|
})
|