Skip to content

Commit dba8ca0

Browse files
authored
Remove remaining uses of eval in the JS compiler (#21423)
Use `vm.runInCurrentContext` instead. We already use this in the preprocessor, but not we also use it for macro expansion and loading of the compiler code itself. This change should facilitate future changes to the JS compiler, such as changing the compiler itself to use JS modules.
1 parent 92eebb5 commit dba8ca0

File tree

5 files changed

+22
-25
lines changed

5 files changed

+22
-25
lines changed

src/compiler.mjs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ globalThis.read = (filename) => {
4545
};
4646

4747
function load(f) {
48-
(0, eval)(read(f) + '//# sourceURL=' + find(f));
49-
};
48+
vm.runInThisContext(read(f), { filename: find(f) });
49+
}
5050

5151
// Basic utilities
5252
load('utility.js');

src/jsifier.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ function shouldPreprocess(fileName) {
105105
function getIncludeFile(fileName, needsPreprocess) {
106106
let result = `// include: ${fileName}\n`;
107107
if (needsPreprocess) {
108-
result += processMacros(preprocess(fileName));
108+
result += processMacros(preprocess(fileName), fileName);
109109
} else {
110110
result += read(fileName);
111111
}

src/modules.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ globalThis.LibraryManager = {
233233
}
234234
currentFile = filename;
235235
try {
236-
processed = processMacros(preprocess(filename));
236+
processed = processMacros(preprocess(filename), filename);
237237
vm.runInThisContext(processed, { filename: filename.replace(/\.\w+$/, '.preprocessed$&') });
238238
} catch (e) {
239239
error(`failure to execute js library "${filename}":`);

src/parseTools.js

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,20 @@
99
*/
1010

1111
globalThis.FOUR_GB = 4 * 1024 * 1024 * 1024;
12+
globalThis.WASM_PAGE_SIZE = 64 * 1024;
13+
1214
const FLOAT_TYPES = new Set(['float', 'double']);
1315

1416
// Does simple 'macro' substitution, using Django-like syntax,
1517
// {{{ code }}} will be replaced with |eval(code)|.
1618
// NOTE: Be careful with that ret check. If ret is |0|, |ret ? ret.toString() : ''| would result in ''!
17-
function processMacros(text) {
19+
function processMacros(text, filename) {
1820
// The `?` here in makes the regex non-greedy so it matches with the closest
1921
// set of closing braces.
2022
// `[\s\S]` works like `.` but include newline.
2123
return text.replace(/{{{([\s\S]+?)}}}/g, (_, str) => {
22-
try {
23-
const ret = eval(str);
24-
return ret !== null ? ret.toString() : '';
25-
} catch (ex) {
26-
ex.stack = `In the following macro:\n\n${str}\n\n${ex.stack}`;
27-
throw ex;
28-
}
24+
const ret = vm.runInThisContext(str, { filename: filename });
25+
return ret !== null ? ret.toString() : '';
2926
});
3027
}
3128

@@ -180,21 +177,21 @@ function needsQuoting(ident) {
180177
globalThis.POINTER_SIZE = MEMORY64 ? 8 : 4;
181178
globalThis.POINTER_MAX = MEMORY64 ? 'Number.MAX_SAFE_INTEGER' : '0xFFFFFFFF';
182179
globalThis.STACK_ALIGN = 16;
183-
const POINTER_BITS = POINTER_SIZE * 8;
184-
const POINTER_TYPE = `u${POINTER_BITS}`;
185-
const POINTER_JS_TYPE = MEMORY64 ? "'bigint'" : "'number'";
186-
const POINTER_SHIFT = MEMORY64 ? '3' : '2';
187-
const POINTER_HEAP = MEMORY64 ? 'HEAP64' : 'HEAP32';
188-
const LONG_TYPE = `i${POINTER_BITS}`;
180+
globalThis.POINTER_BITS = POINTER_SIZE * 8;
181+
globalThis.POINTER_TYPE = `u${POINTER_BITS}`;
182+
globalThis.POINTER_JS_TYPE = MEMORY64 ? "'bigint'" : "'number'";
183+
globalThis.POINTER_SHIFT = MEMORY64 ? '3' : '2';
184+
globalThis.POINTER_HEAP = MEMORY64 ? 'HEAP64' : 'HEAP32';
185+
globalThis.LONG_TYPE = `i${POINTER_BITS}`;
189186

190-
const SIZE_TYPE = POINTER_TYPE;
187+
globalThis.SIZE_TYPE = POINTER_TYPE;
191188

192189

193190
// Similar to POINTER_TYPE, but this is the actual wasm type that is
194191
// used in practice, while POINTER_TYPE is the more refined internal
195192
// type (that is unsigned, where as core wasm does not have unsigned
196193
// types).
197-
const POINTER_WASM_TYPE = `i${POINTER_BITS}`;
194+
globalThis.POINTER_WASM_TYPE = `i${POINTER_BITS}`;
198195

199196
function isPointerType(type) {
200197
return type[type.length - 1] == '*';
@@ -699,9 +696,6 @@ function makeRetainedCompilerSettings() {
699696
return ret;
700697
}
701698

702-
// In wasm, the heap size must be a multiple of 64KiB.
703-
const WASM_PAGE_SIZE = 65536;
704-
705699
// Receives a function as text, and a function that constructs a modified
706700
// function, to which we pass the parsed-out arguments, body, and possible
707701
// "async" prefix of the input function. Returns the output of that function.

tools/preprocessor.mjs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ global.read = (filename) => {
5252
};
5353

5454
global.load = (f) => {
55-
(0, eval)(read(f) + '//# sourceURL=' + find(f));
55+
vm.runInThisContext(read(f), { filename: find(f) });
5656
};
5757

5858
assert(args.length >= 2);
@@ -65,5 +65,8 @@ load('utility.js');
6565
load('modules.js');
6666
load('parseTools.js');
6767

68-
const output = expandMacros ? processMacros(preprocess(inputFile)) : preprocess(inputFile);
68+
let output = preprocess(inputFile);
69+
if (expandMacros) {
70+
output = processMacros(output, inputFile)
71+
}
6972
process.stdout.write(output);

0 commit comments

Comments
 (0)