Skip to content

Commit b11177d

Browse files
authored
Migrate to esbuild for compilation (#9203)
1 parent d992405 commit b11177d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+210
-441
lines changed

.eslintrc-no-types.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"ignorePatterns": [
1111
"logs/",
1212
"node_modules/",
13-
".*-dist/",
13+
"dist/",
1414
"data/**/learnsets.ts",
1515
"tools/set-import/importer.js",
1616
"tools/set-import/sets",

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ tools/modlog/converter.js
2323
*.tsbuildinfo
2424
**/sourceMaps
2525

26+
!test/**/*.js
27+
tools/modlog/**/*.js
28+
tools/set-import/*.js
29+
2630
# visual studio live share
2731
.vs
2832

build

+5-9
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,15 @@ function shell(cmd) {
2222

2323
// Check to make sure the most recently added or updated dependency is installed at the correct version
2424
try {
25-
var sucraseVersion = require('sucrase').getVersion().split('.');
26-
if (
27-
parseInt(sucraseVersion[0]) < 3 ||
28-
(parseInt(sucraseVersion[0]) === 3 && parseInt(sucraseVersion[1]) < 15)
29-
) {
30-
throw new Error("Sucrase version too old");
25+
var version = require('esbuild').version.split('.');
26+
if (parseInt(version[1]) < 16) {
27+
throw new Error("esbuild version too old");
3128
}
3229
} catch (e) {
3330
console.log('Installing dependencies...');
34-
shell('npm install' + (decl ? '' : ' --production'));
35-
force = true;
31+
shell('npm install');
3632
}
37-
// for some reason, sucrase won't be requirable until a tick has passed
33+
// for some reason, esbuild won't be requirable until a tick has passed
3834
// see https://stackoverflow.com/questions/53270058/node-cant-find-certain-modules-after-synchronous-install
3935
setImmediate(() => {
4036
require('./tools/build-utils').transpile(force, decl);

lib/crashlogger.ts

+4-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@ import * as path from 'path';
1313

1414
const CRASH_EMAIL_THROTTLE = 5 * 60 * 1000; // 5 minutes
1515

16-
const logPath = path.resolve(__dirname, '../logs/errors.txt');
16+
const logPath = path.resolve(
17+
// not sure why this is necessary, but in Windows testing it was
18+
__dirname, '../', __dirname.includes(`${path.sep}dist${path.sep}`) ? '..' : '', 'logs/errors.txt'
19+
);
1720
let lastCrashLog = 0;
1821
let transport: any;
1922

lib/fs.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@ import * as fs from 'fs';
2525
import * as pathModule from 'path';
2626
import {ReadStream, WriteStream} from './streams';
2727

28-
const ROOT_PATH = pathModule.resolve(__dirname, '..');
28+
// not sure why it's necessary to use path.sep, but testing with Windows showed it was
29+
const DIST = `${pathModule.sep}dist${pathModule.sep}`;
30+
// account for pwd/dist/lib
31+
const ROOT_PATH = pathModule.resolve(__dirname, __dirname.includes(DIST) ? '..' : '', '..');
2932

3033
interface PendingUpdate {
3134
isWriting: boolean; // true: waiting on a call to FS.write, false: waiting on a throttle
@@ -517,5 +520,5 @@ function getFs(path: string) {
517520
}
518521

519522
export const FS = Object.assign(getFs, {
520-
FileReadStream, FSPath,
523+
FileReadStream, FSPath, ROOT_PATH,
521524
});

lib/process-manager.ts

+5-7
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,11 @@ import * as child_process from 'child_process';
1313
import * as cluster from 'cluster';
1414
import * as path from 'path';
1515
import * as Streams from './streams';
16+
import {FS} from './fs';
1617

1718
type ChildProcess = child_process.ChildProcess;
1819
type Worker = cluster.Worker;
1920

20-
const ROOT_DIR = path.resolve(__dirname, '..');
21-
2221
export const processManagers: ProcessManager[] = [];
2322

2423
export function exec(args: string, execOptions?: child_process.ExecOptions): Promise<{stderr: string, stdout: string}>;
@@ -112,7 +111,7 @@ export class QueryProcessWrapper<T, U> implements ProcessWrapper {
112111
file: string;
113112

114113
constructor(file: string, messageCallback?: (message: string) => any) {
115-
this.process = child_process.fork(file, [], {cwd: ROOT_DIR, execArgv: ['-r', 'ts-node/register']});
114+
this.process = child_process.fork(file, [], {cwd: FS.ROOT_PATH});
116115
this.taskId = 0;
117116
this.file = file;
118117
this.pendingTasks = new Map();
@@ -231,7 +230,7 @@ export class StreamProcessWrapper implements ProcessWrapper {
231230
messageCallback?: (message: string) => any;
232231

233232
constructor(file: string, messageCallback?: (message: string) => any) {
234-
this.process = child_process.fork(file, [], {cwd: ROOT_DIR, execArgv: ['-r', 'ts-node/register']});
233+
this.process = child_process.fork(file, [], {cwd: FS.ROOT_PATH});
235234
this.messageCallback = messageCallback;
236235

237236
this.process.on('message', (message: string) => {
@@ -370,7 +369,7 @@ export class RawProcessWrapper implements ProcessWrapper, StreamWorker {
370369
this.process = cluster.fork(env);
371370
this.workerid = this.process.id;
372371
} else {
373-
this.process = child_process.fork(file, [], {cwd: ROOT_DIR, env, execArgv: ['-r', 'ts-node/register']}) as any;
372+
this.process = child_process.fork(file, [], {cwd: FS.ROOT_PATH, env}) as any;
374373
}
375374

376375
this.process.on('message', (message: string) => {
@@ -721,8 +720,7 @@ export class RawProcessManager extends ProcessManager<RawProcessWrapper> {
721720
cluster.setupMaster({
722721
exec: this.filename,
723722
// @ts-ignore TODO: update type definition
724-
cwd: ROOT_DIR,
725-
execArgv: ['-r', 'ts-node/register'],
723+
cwd: FS.ROOT_PATH,
726724
});
727725
}
728726

lib/repl.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import * as net from 'net';
1313
import * as path from 'path';
1414
import * as repl from 'repl';
1515
import {crashlogger} from './crashlogger';
16+
import {FS} from './fs';
1617
declare const Config: any;
1718

1819
export const Repl = new class {
@@ -72,7 +73,9 @@ export const Repl = new class {
7273

7374
if (filename === 'app') {
7475
// Clean up old REPL sockets.
75-
const directory = path.dirname(path.resolve(__dirname, '..', config.replsocketprefix || 'logs/repl', 'app'));
76+
const directory = path.dirname(
77+
path.resolve(FS.ROOT_PATH, config.replsocketprefix || 'logs/repl', 'app')
78+
);
7679
let files;
7780
try {
7881
files = fs.readdirSync(directory);
@@ -108,7 +111,7 @@ export const Repl = new class {
108111
socket.on('error', () => socket.destroy());
109112
});
110113

111-
const pathname = path.resolve(__dirname, '..', Config.replsocketprefix || 'logs/repl', filename);
114+
const pathname = path.resolve(FS.ROOT_PATH, Config.replsocketprefix || 'logs/repl', filename);
112115
try {
113116
server.listen(pathname, () => {
114117
fs.chmodSync(pathname, Config.replsocketmode || 0o600);

package.json

+5-6
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,13 @@
22
"name": "pokemon-showdown",
33
"description": "The server for the Pokémon Showdown battle simulator",
44
"version": "0.11.7",
5-
"main": ".sim-dist/index.js",
5+
"main": "dist/sim/index.js",
66
"dependencies": {
7-
"@swc/core": "1.2.205",
7+
"esbuild": "^0.16.10",
88
"preact": "^10.5.15",
99
"preact-render-to-string": "^5.1.19",
1010
"probe-image-size": "^5.0.0",
11-
"sockjs": "^0.3.21",
12-
"ts-node": "^10.0.0"
11+
"sockjs": "^0.3.21"
1312
},
1413
"optionalDependencies": {
1514
"better-sqlite3": "^7.6.2",
@@ -69,7 +68,7 @@
6968
"devDependencies": {
7069
"@types/better-sqlite3": "^7.6.2",
7170
"@types/cloud-env": "^0.2.2",
72-
"@types/node": "^14.17.12",
71+
"@types/node": "^14.18.35",
7372
"@types/node-static": "^0.7.7",
7473
"@types/nodemailer": "^6.4.4",
7574
"@types/pg": "^8.6.5",
@@ -79,6 +78,6 @@
7978
"eslint": "^8.5.0",
8079
"mocha": "^8.2.0",
8180
"smogon": "^1.4.5",
82-
"typescript": "^4.5.2"
81+
"typescript": "^4.9.4"
8382
}
8483
}

pokemon-showdown

+39-71
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
#!/usr/bin/env node
2+
'use strict';
3+
// no-var is disabled since this is supposed to support old versions of node
4+
// block scoped var is just because idk what the fuck is going on there since it wasn't
5+
// failing before
6+
/* eslint-disable block-scoped-var, no-var, no-redeclare*/
27

38
// Before running, ensure that the Typescript files have been compiled.
49
//
510
// Simply doing `require('../build')` here doesn't work because the `replace`
611
// step of the build is asynchronous and we can't wait for it to finish easily
712
// unless we shell out and use `execSync`. However, the heuristic of simply
8-
// checking for the presence of './.sim-dist/dex' to determine whether a build
13+
// checking for the presence of './dist/sim/dex' to determine whether a build
914
// is required is somewhat risky as it only is valid from a clean repository -
1015
// if you make edits or have previous build artifacts lying around, this
1116
// script could potentially be missing additional sources or the compiled output
@@ -16,10 +21,9 @@
1621
// of interfacing with the simulator from non-JS languages. Otherwise we error
1722
// on the side of caution and run `node build` to ensure we're always running
1823
// with the latest code.
19-
var built = false;
24+
var fs = require('fs');
2025
function build() {
2126
require('child_process').execSync('node build', {stdio: 'inherit', cwd: __dirname});
22-
built = true;
2327
}
2428

2529
function readTeam(stream) {
@@ -29,46 +33,8 @@ function readTeam(stream) {
2933
});
3034
}
3135

32-
33-
function installDependencies() {
34-
console.log(`Installing dependencies...`);
35-
require('child_process').execSync('npm install --production', {stdio: 'inherit'});
36-
}
37-
38-
function registerTSNode() {
39-
require('ts-node').register({project: './tsconfig.json', files: true, transpileOnly: true, transpiler: 'ts-node/transpilers/swc-experimental'});
40-
}
41-
42-
// enable require()ing TypeScript files
43-
function setupTSNode() {
44-
try {
45-
registerTSNode();
46-
} catch (e) {
47-
installDependencies();
48-
registerTSNode();
49-
}
50-
}
51-
52-
function ensureSucraseIsInstalled() {
53-
try {
54-
const sucraseVersion = require('sucrase').getVersion().split('.');
55-
if (
56-
parseInt(sucraseVersion[0]) < 3 ||
57-
(parseInt(sucraseVersion[0]) === 3 && parseInt(sucraseVersion[1]) < 12)
58-
) {
59-
throw new Error("Sucrase version too old");
60-
}
61-
} catch (e) {
62-
installDependencies();
63-
}
64-
}
65-
66-
function sucraseBuild() {
67-
ensureSucraseIsInstalled();
68-
try {
69-
require.resolve('./.sim-dist/dex');
70-
} catch (err) {
71-
if (err.code !== 'MODULE_NOT_FOUND') throw err; // should never happen
36+
function ensureBuilt() {
37+
if (!fs.existsSync('./dist')) {
7238
build();
7339
}
7440
}
@@ -80,9 +46,10 @@ if (!process.argv[2] || /^[0-9]+$/.test(process.argv[2])) {
8046
// when launching with this file the same way app.js normally allows, e.g. to
8147
// host on port 9000:
8248
// $ ./pokemon-showdown 9000
83-
setupTSNode();
84-
require('module')._load('./server', module, true);
85-
} else switch (process.argv[2]) {
49+
build();
50+
require('module')._load('./dist/server/index.js', module, true);
51+
} else {
52+
switch (process.argv[2]) {
8653
case 'help':
8754
case 'h':
8855
case '?':
@@ -109,7 +76,7 @@ if (!process.argv[2] || /^[0-9]+$/.test(process.argv[2])) {
10976
console.log('pokemon-showdown simulate-battle');
11077
console.log('');
11178
console.log(' Simulates a battle, taking input to stdin and writing output to stdout');
112-
console.log(' Protocol is documented in ./.sim-dist/README.md');
79+
console.log(' Protocol is documented in ./dist/sim/README.md');
11380
console.log('');
11481
console.log('pokemon-showdown json-team');
11582
console.log('');
@@ -128,27 +95,27 @@ if (!process.argv[2] || /^[0-9]+$/.test(process.argv[2])) {
12895
console.log(' Displays this reference');
12996
break;
13097
case 'start':
131-
{
132-
process.argv.splice(2, 1);
133-
setupTSNode();
134-
require('module')._load('./server', module, true);
135-
break;
136-
}
98+
{
99+
process.argv.splice(2, 1);
100+
build();
101+
require('module')._load('./dist/server/index.js', module, true);
102+
break;
103+
}
137104
case 'generate-team':
138105
{
139-
sucraseBuild();
140-
var Teams = require('./.sim-dist/teams').Teams;
106+
ensureBuilt();
107+
var Teams = require('./dist/sim/teams.js').Teams;
141108
var seed = process.argv[4] ? process.argv[4].split(',').map(Number) : undefined;
142109
console.log(Teams.pack(Teams.generate(process.argv[3], {seed})));
143110
}
144111
break;
145112
case 'validate-team':
146113
{
147-
sucraseBuild();
148-
var Teams = require('./.sim-dist/teams').Teams;
149-
var TeamValidator = require('./.sim-dist/team-validator').TeamValidator;
114+
ensureBuilt();
115+
var Teams = require('./dist/sim/teams.js').Teams;
116+
var TeamValidator = require('./dist/sim/team-validator.js').TeamValidator;
150117
var validator = TeamValidator.get(process.argv[3]);
151-
var Streams = require('./.lib-dist/streams');
118+
var Streams = require('./dist/lib/streams.js');
152119
var stdin = Streams.stdin();
153120

154121
readTeam(stdin).then(function (textTeam) {
@@ -169,9 +136,9 @@ if (!process.argv[2] || /^[0-9]+$/.test(process.argv[2])) {
169136
break;
170137
case 'simulate-battle':
171138
{
172-
sucraseBuild();
173-
var BattleTextStream = require('./.sim-dist/battle-stream').BattleTextStream;
174-
var Streams = require('./.lib-dist/streams');
139+
build();
140+
var BattleTextStream = require('./dist/sim/battle-stream.js').BattleTextStream;
141+
var Streams = require('./dist/lib/streams');
175142
var stdin = Streams.stdin();
176143
var stdout = Streams.stdout();
177144

@@ -221,9 +188,9 @@ if (!process.argv[2] || /^[0-9]+$/.test(process.argv[2])) {
221188
case 'unpack-team':
222189
case 'json-team':
223190
{
224-
sucraseBuild();
225-
var Teams = require('./.sim-dist/teams').Teams;
226-
var Streams = require('./.lib-dist/streams');
191+
build();
192+
var Teams = require('./dist/sim/teams').Teams;
193+
var Streams = require('./dist/lib/streams');
227194
var stdin = Streams.stdin();
228195

229196
readTeam(stdin).then(function (team) {
@@ -240,9 +207,9 @@ if (!process.argv[2] || /^[0-9]+$/.test(process.argv[2])) {
240207
break;
241208
case 'pack-team':
242209
{
243-
sucraseBuild();
244-
var Teams = require('./.sim-dist/teams').Teams;
245-
var Streams = require('./.lib-dist/streams');
210+
build();
211+
var Teams = require('./dist/sim/teams').Teams;
212+
var Streams = require('./dist/lib/streams');
246213
var stdin = Streams.stdin();
247214

248215
readTeam(stdin).then(function (team) {
@@ -259,9 +226,9 @@ if (!process.argv[2] || /^[0-9]+$/.test(process.argv[2])) {
259226
break;
260227
case 'export-team':
261228
{
262-
sucraseBuild();
263-
var Teams = require('./.sim-dist/teams').Teams;
264-
var Streams = require('./.lib-dist/streams');
229+
build();
230+
var Teams = require('./dist/sim/teams').Teams;
231+
var Streams = require('./dist/lib/streams');
265232
var stdin = Streams.stdin();
266233

267234
readTeam(stdin).then(function (team) {
@@ -280,4 +247,5 @@ if (!process.argv[2] || /^[0-9]+$/.test(process.argv[2])) {
280247
console.error('Unrecognized command: ' + process.argv[2]);
281248
console.error('Use `pokemon-showdown help` for help');
282249
process.exit(1);
250+
}
283251
}

0 commit comments

Comments
 (0)