Skip to content

Commit

Permalink
lint-fix
Browse files Browse the repository at this point in the history
  • Loading branch information
cspotcode committed Feb 22, 2022
1 parent a28a3be commit a35462b
Show file tree
Hide file tree
Showing 6 changed files with 149 additions and 61 deletions.
107 changes: 85 additions & 22 deletions src/bin.ts
Expand Up @@ -59,15 +59,15 @@ export interface BootstrapState {

/** @internal */
export function bootstrap(state: BootstrapState) {
if(!state.phase2Result) {
if (!state.phase2Result) {
state.phase2Result = phase2(state);
if(state.shouldUseChildProcess && !state.isInChildProcess) {
if (state.shouldUseChildProcess && !state.isInChildProcess) {
return callInChild(state);
}
}
if(!state.phase3Result) {
if (!state.phase3Result) {
state.phase3Result = phase3(state);
if(state.shouldUseChildProcess && !state.isInChildProcess) {
if (state.shouldUseChildProcess && !state.isInChildProcess) {
return callInChild(state);
}
}
Expand Down Expand Up @@ -206,19 +206,47 @@ function parseArgv(argv: string[], entrypointArgs: Record<string, any>) {
'--scopeDir': scopeDir = undefined,
'--noExperimentalReplAwait': noExperimentalReplAwait,
'--esm': esm,
_: restArgs
_: restArgs,
} = args;
return {
restArgs,
cwdArg, help, scriptMode, cwdMode, version, showConfig, argsRequire, code, print, interactive, files, compiler,
compilerOptions, project, ignoreDiagnostics, ignore, transpileOnly, typeCheck, transpiler, swc, compilerHost,
pretty, skipProject, skipIgnore, preferTsExts, logError, emit, scope, scopeDir, noExperimentalReplAwait,
esm
cwdArg,
help,
scriptMode,
cwdMode,
version,
showConfig,
argsRequire,
code,
print,
interactive,
files,
compiler,
compilerOptions,
project,
ignoreDiagnostics,
ignore,
transpileOnly,
typeCheck,
transpiler,
swc,
compilerHost,
pretty,
skipProject,
skipIgnore,
preferTsExts,
logError,
emit,
scope,
scopeDir,
noExperimentalReplAwait,
esm,
};
}

function phase2(payload: BootstrapState) {
const {help, version, code, interactive, cwdArg, restArgs, esm} = payload.parseArgvResult;
const { help, version, code, interactive, cwdArg, restArgs, esm } =
payload.parseArgvResult;

if (help) {
console.log(`
Expand Down Expand Up @@ -282,17 +310,44 @@ Options:
/** Unresolved. May point to a symlink, not realpath. May be missing file extension */
const scriptPath = executeEntrypoint ? resolve(cwd, restArgs[0]) : undefined;

if(esm) payload.shouldUseChildProcess = true;
return {executeEval, executeEntrypoint, executeRepl, executeStdin, cwd, scriptPath};
if (esm) payload.shouldUseChildProcess = true;
return {
executeEval,
executeEntrypoint,
executeRepl,
executeStdin,
cwd,
scriptPath,
};
}

function phase3(payload: BootstrapState) {
const {
emit, files, pretty, transpileOnly, transpiler, noExperimentalReplAwait, typeCheck, swc, compilerHost, ignore,
preferTsExts, logError, scriptMode, cwdMode, project, skipProject, skipIgnore, compiler, ignoreDiagnostics,
compilerOptions, argsRequire, scope, scopeDir
emit,
files,
pretty,
transpileOnly,
transpiler,
noExperimentalReplAwait,
typeCheck,
swc,
compilerHost,
ignore,
preferTsExts,
logError,
scriptMode,
cwdMode,
project,
skipProject,
skipIgnore,
compiler,
ignoreDiagnostics,
compilerOptions,
argsRequire,
scope,
scopeDir,
} = payload.parseArgvResult;
const {cwd, scriptPath} = payload.phase2Result!;
const { cwd, scriptPath } = payload.phase2Result!;

// const configWeAlreadyParsed = getConfig({
const configWeAlreadyParsed = create({
Expand Down Expand Up @@ -322,18 +377,26 @@ function phase3(payload: BootstrapState) {
fileExists: undefined,
scope,
scopeDir,
// });
// });
}).options;

// attach new locals to the payload
if(configWeAlreadyParsed.esm) payload.shouldUseChildProcess = true;
return {configWeAlreadyParsed};
if (configWeAlreadyParsed.esm) payload.shouldUseChildProcess = true;
return { configWeAlreadyParsed };
}

function phase4(payload: BootstrapState) {
const {version, showConfig, restArgs, code, print} = payload.parseArgvResult;
const {executeEval, cwd, executeStdin, executeRepl, executeEntrypoint, scriptPath} = payload.phase2Result!;
const {configWeAlreadyParsed} = payload.phase3Result!;
const { version, showConfig, restArgs, code, print } =
payload.parseArgvResult;
const {
executeEval,
cwd,
executeStdin,
executeRepl,
executeEntrypoint,
scriptPath,
} = payload.phase2Result!;
const { configWeAlreadyParsed } = payload.phase3Result!;
/**
* <repl>, [stdin], and [eval] are all essentially virtual files that do not exist on disc and are backed by a REPL
* service to handle eval-ing of code.
Expand Down
11 changes: 8 additions & 3 deletions src/child/child-entrypoint.ts
@@ -1,10 +1,15 @@
import {BootstrapState, bootstrap} from '../bin';
import { BootstrapState, bootstrap } from '../bin';

const environmentVariableName = process.argv[2];
const base64Payload = process.env[environmentVariableName]!;
delete process.env[environmentVariableName];
const payload = JSON.parse(Buffer.from(base64Payload, 'base64').toString()) as BootstrapState;
console.dir({payloadSize: base64Payload.length, payload: JSON.stringify(payload)});
const payload = JSON.parse(
Buffer.from(base64Payload, 'base64').toString()
) as BootstrapState;
console.dir({
payloadSize: base64Payload.length,
payload: JSON.stringify(payload),
});
payload.isInChildProcess = true;

bootstrap(payload);
15 changes: 9 additions & 6 deletions src/child/child-loader.ts
Expand Up @@ -2,13 +2,15 @@
// Also export a binder function that allows re-binding where the stubs
// delegate.

import type { NodeLoaderHooksAPI1, NodeLoaderHooksAPI2 } from "..";
import { filterHooksByAPIVersion } from "../esm";
import type { NodeLoaderHooksAPI1, NodeLoaderHooksAPI2 } from '..';
import { filterHooksByAPIVersion } from '../esm';

let hooks: NodeLoaderHooksAPI1 & NodeLoaderHooksAPI2;

/** @internal */
export function lateBindHooks(_hooks: NodeLoaderHooksAPI1 | NodeLoaderHooksAPI2) {
export function lateBindHooks(
_hooks: NodeLoaderHooksAPI1 | NodeLoaderHooksAPI2
) {
hooks = _hooks as NodeLoaderHooksAPI1 & NodeLoaderHooksAPI2;
}

Expand All @@ -24,8 +26,9 @@ const proxy: NodeLoaderHooksAPI1 & NodeLoaderHooksAPI2 = {
},
transformSource(...args: Parameters<NodeLoaderHooksAPI1['transformSource']>) {
return hooks.transformSource(...args);
}
}
},
};

/** @internal */
export const {resolve, load, getFormat, transformSource} = filterHooksByAPIVersion(proxy) as NodeLoaderHooksAPI1 & NodeLoaderHooksAPI2;
export const { resolve, load, getFormat, transformSource } =
filterHooksByAPIVersion(proxy) as NodeLoaderHooksAPI1 & NodeLoaderHooksAPI2;
8 changes: 6 additions & 2 deletions src/child/child-require.ts
Expand Up @@ -6,7 +6,7 @@ const _process = process as any as EventEmitterInternals;
// Not shown here: Additional logic to correctly interact with process's events, either using this direct manipulation, or via the API

let originalOnWarning: Function | undefined;
if(Array.isArray(_process._events.warning)) {
if (Array.isArray(_process._events.warning)) {
originalOnWarning = _process._events.warning[0];
_process._events.warning[0] = onWarning;
} else {
Expand All @@ -17,7 +17,11 @@ if(Array.isArray(_process._events.warning)) {
const messageMatch = /--(?:experimental-)?loader\b/;
function onWarning(this: any, warning: Error, ...rest: any[]) {
// Suppress warning about how `--loader` is experimental
if(warning?.name === 'ExperimentalWarning' && messageMatch.test(warning?.message)) return;
if (
warning?.name === 'ExperimentalWarning' &&
messageMatch.test(warning?.message)
)
return;
// Will be undefined if `--no-warnings`
return originalOnWarning?.call(this, warning, ...rest);
}
50 changes: 28 additions & 22 deletions src/child/spawn-child.ts
@@ -1,35 +1,41 @@
import type { BootstrapState } from "../bin";
import {spawn} from 'child_process';
import * as fs from "fs";
import type { BootstrapState } from '../bin';
import { spawn } from 'child_process';
import * as fs from 'fs';

const passFirstXFds = 100;
const stdio: number[] = [];
for(let i = 0; i < passFirstXFds; i++) {
for (let i = 0; i < passFirstXFds; i++) {
stdio[i] = i;
}

/** @internal */
export function callInChild(state: BootstrapState) {
let envVarName: string = 'TS_NODE_BOOTSTRAP';
for(let i = 0; i < Number.MAX_SAFE_INTEGER; i++) {
for (let i = 0; i < Number.MAX_SAFE_INTEGER; i++) {
envVarName = `TS_NODE_BOOTSTRAP_${i}`;
if(process.env[envVarName] === undefined) break;
if (process.env[envVarName] === undefined) break;
}
const child = spawn(process.execPath, [
'--require',
require.resolve('./child-require.js'),
'--loader',
require.resolve('../../child-loader.mjs'),
require.resolve('./child-entrypoint.js'),
envVarName
], {
env: {
...process.env,
[envVarName!]: Buffer.from(JSON.stringify(state), 'utf8').toString('base64')
},
stdio,
argv0: process.argv0
});
const child = spawn(
process.execPath,
[
'--require',
require.resolve('./child-require.js'),
'--loader',
require.resolve('../../child-loader.mjs'),
require.resolve('./child-entrypoint.js'),
envVarName,
],
{
env: {
...process.env,
[envVarName!]: Buffer.from(JSON.stringify(state), 'utf8').toString(
'base64'
),
},
stdio,
argv0: process.argv0,
}
);
child.on('error', (error) => {
console.error(error);
process.exit(1);
Expand All @@ -50,7 +56,7 @@ export function callInChild(state: BootstrapState) {
process.kill(child.pid, 'SIGTERM');
}
// Close all (well, a lot of) FDs in parent to avoid keeping them open.
for(let fd = 0; fd < 100; fd++) {
for (let fd = 0; fd < 100; fd++) {
fs.close(fd, () => {});
}
}
19 changes: 13 additions & 6 deletions src/esm.ts
Expand Up @@ -104,13 +104,15 @@ export interface NodeImportAssertions {
// TODO: When the new API is backported to v12, v14, update these version checks accordingly.
const newHooksAPI =
versionGteLt(process.versions.node, '17.0.0') ||
versionGteLt(process.versions.node, '16.12.0', '17.0.0') ||
versionGteLt(process.versions.node, '14.999.999', '15.0.0') ||
versionGteLt(process.versions.node, '12.999.999', '13.0.0');
versionGteLt(process.versions.node, '16.12.0', '17.0.0') ||
versionGteLt(process.versions.node, '14.999.999', '15.0.0') ||
versionGteLt(process.versions.node, '12.999.999', '13.0.0');

/** @internal */
export function filterHooksByAPIVersion(hooks: NodeLoaderHooksAPI1 & NodeLoaderHooksAPI2): NodeLoaderHooksAPI1 | NodeLoaderHooksAPI2 {
const {getFormat, load, resolve, transformSource} = hooks;
export function filterHooksByAPIVersion(
hooks: NodeLoaderHooksAPI1 & NodeLoaderHooksAPI2
): NodeLoaderHooksAPI1 | NodeLoaderHooksAPI2 {
const { getFormat, load, resolve, transformSource } = hooks;
// Explicit return type to avoid TS's non-ideal inferred type
const hooksAPI: NodeLoaderHooksAPI1 | NodeLoaderHooksAPI2 = newHooksAPI
? { resolve, load, getFormat: undefined, transformSource: undefined }
Expand All @@ -135,7 +137,12 @@ export function createEsmHooks(tsNodeService: Service) {
preferTsExts: tsNodeService.options.preferTsExts,
});

const hooksAPI = filterHooksByAPIVersion({resolve, load, getFormat, transformSource});
const hooksAPI = filterHooksByAPIVersion({
resolve,
load,
getFormat,
transformSource,
});

function isFileUrlOrNodeStyleSpecifier(parsed: UrlWithStringQuery) {
// We only understand file:// URLs, but in node, the specifier can be a node-style `./foo` or `foo`
Expand Down

0 comments on commit a35462b

Please sign in to comment.