Skip to content

Commit 237cd67

Browse files
committed
restoreStateで呼び出すevalをrunCodeと同じ仕様にする
1 parent f59d2fc commit 237cd67

File tree

2 files changed

+38
-41
lines changed

2 files changed

+38
-41
lines changed

app/terminal/tests.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ export function defineTests(
5757
ruby: [`${varName} = ${value}`, `puts ${varName}`],
5858
cpp: [null, null],
5959
javascript: [
60-
`var ${varName} = ${value}`,
60+
`const ${varName} = ${value}`,
6161
`console.log(${varName})`,
6262
],
6363
typescript: [null, null],
@@ -109,7 +109,7 @@ export function defineTests(
109109
ruby: [`testVar = 42`, `loop do\nend`, `puts testVar`],
110110
cpp: [null, null, null],
111111
javascript: [
112-
`var testVar = 42`,
112+
`const testVar = 42`,
113113
`while(true) {}`,
114114
`console.log(testVar)`,
115115
],

app/terminal/worker/jsEval.worker.ts

Lines changed: 36 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -37,46 +37,45 @@ async function init({ id }: WorkerRequest["init"]) {
3737
} satisfies WorkerResponse["init"]);
3838
}
3939

40-
async function runCode({ id, payload }: WorkerRequest["runCode"]) {
41-
let { code } = payload;
42-
try {
43-
let result: unknown;
44-
45-
// eval()の中でconst,letを使って変数を作成した場合、
46-
// 次に実行するコマンドはスコープ外扱いでありアクセスできなくなってしまうので、
47-
// varに置き換えている
48-
if (code.trim().startsWith("const ")) {
49-
code = "var " + code.trim().slice(6);
50-
} else if (code.trim().startsWith("let ")) {
51-
code = "var " + code.trim().slice(4);
52-
}
53-
// eval()の中でclassを作成した場合も同様
54-
const classRegExp = /^\s*class\s+(\w+)/;
55-
if (classRegExp.test(code)) {
56-
code = code.replace(classRegExp, "var $1 = class $1");
57-
}
40+
async function replLikeEval(code: string): Promise<unknown> {
41+
// eval()の中でconst,letを使って変数を作成した場合、
42+
// 次に実行するコマンドはスコープ外扱いでありアクセスできなくなってしまうので、
43+
// varに置き換えている
44+
if (code.trim().startsWith("const ")) {
45+
code = "var " + code.trim().slice(6);
46+
} else if (code.trim().startsWith("let ")) {
47+
code = "var " + code.trim().slice(4);
48+
}
49+
// eval()の中でclassを作成した場合も同様
50+
const classRegExp = /^\s*class\s+(\w+)/;
51+
if (classRegExp.test(code)) {
52+
code = code.replace(classRegExp, "var $1 = class $1");
53+
}
5854

59-
if (code.trim().startsWith("{") && code.trim().endsWith("}")) {
60-
// オブジェクトは ( ) で囲わなければならない
61-
try {
62-
result = self.eval(`(${code})`);
63-
} catch (e) {
64-
if (e instanceof SyntaxError) {
65-
// オブジェクトではなくブロックだった場合、再度普通に実行
66-
result = self.eval(code);
67-
} else {
68-
throw e;
69-
}
55+
if (code.trim().startsWith("{") && code.trim().endsWith("}")) {
56+
// オブジェクトは ( ) で囲わなければならない
57+
try {
58+
return self.eval(`(${code})`);
59+
} catch (e) {
60+
if (e instanceof SyntaxError) {
61+
// オブジェクトではなくブロックだった場合、再度普通に実行
62+
return self.eval(code);
63+
} else {
64+
throw e;
7065
}
71-
} else if (/^\s*await\W/.test(code)) {
72-
// promiseをawaitする場合は、promiseの部分だけをevalし、それを外からawaitする
73-
result = await self.eval(code.trim().slice(5));
74-
} else {
75-
// Execute code directly with eval in the worker global scope
76-
// This will preserve variables across calls
77-
result = self.eval(code);
7866
}
67+
} else if (/^\s*await\W/.test(code)) {
68+
// promiseをawaitする場合は、promiseの部分だけをevalし、それを外からawaitする
69+
return await self.eval(code.trim().slice(5));
70+
} else {
71+
return self.eval(code);
72+
}
73+
}
7974

75+
async function runCode({ id, payload }: WorkerRequest["runCode"]) {
76+
const { code } = payload;
77+
try {
78+
const result = await replLikeEval(code);
8079
jsOutput.push({
8180
type: "return",
8281
message: inspect(result),
@@ -110,8 +109,6 @@ function runFile({ id, payload }: WorkerRequest["runFile"]) {
110109
const { name, files } = payload;
111110
// pyodide worker などと異なり、複数ファイルを読み込んでimportのようなことをするのには対応していません。
112111
try {
113-
// Execute code directly with eval in the worker global scope
114-
// This will preserve variables across calls
115112
self.eval(files[name]);
116113
} catch (e) {
117114
originalConsole.log(e);
@@ -183,7 +180,7 @@ async function restoreState({ id, payload }: WorkerRequest["restoreState"]) {
183180

184181
for (const command of commands) {
185182
try {
186-
self.eval(command);
183+
replLikeEval(command);
187184
} catch (e) {
188185
// If restoration fails, we still continue with other commands
189186
originalConsole.error("Failed to restore command:", command, e);

0 commit comments

Comments
 (0)