@@ -25,6 +25,7 @@ import type {
2525 ExpressionNode
2626 FinallyClause
2727 ForStatement
28+ FunctionExpression
2829 IfStatement
2930 IterationStatement
3031 MemberExpression
@@ -1251,13 +1252,7 @@ function processProgram(root: BlockStatement): void
12511252 adjustAtBindings(statements)
12521253
12531254 // REPL wants all top-level variables hoisted to outermost scope
1254- if config.repl
1255- topBlock :=
1256- gatherRecursive(rootIIFE!, .type is 'BlockStatement')[0]
1257- for each [, statement] of topBlock.expressions
1258- if statement is like {type: 'Declaration'}
1259- statement.children.shift() // remove const/let/var
1260- root.expressions.unshift ['', `var ${statement.names.join ','};`]
1255+ processRepl root, rootIIFE if config.repl
12611256
12621257 // Run synchronous versions of async steps in case we're in sync mode
12631258 if getSync()
@@ -1268,8 +1263,34 @@ async function processProgramAsync(root: BlockStatement): Promise<void>
12681263 { expressions: statements } := root
12691264 await processComptime(statements)
12701265
1266+ function processRepl(root: BlockStatement, rootIIFE: ASTNode): void
1267+ topBlock :=
1268+ gatherRecursive(rootIIFE!, .type is "BlockStatement")[0]
1269+ i .= 0
1270+ // Hoist top-level declarations and all var declarations
1271+ for each decl of gatherRecursiveWithinFunction topBlock, .type is "Declaration"
1272+ if decl.parent is topBlock or decl.decl is "var"
1273+ decl.children.shift() // remove const/let/var
1274+ root.expressions.splice i++, 0, ["", `var ${decl.names.join ','};`]
1275+ // Hoist all function declarations, and hoist values when top-level
1276+ for each func of gatherRecursive topBlock, .type is "FunctionExpression"
1277+ if func.name and func.parent?.type is "BlockStatement" // declaration
1278+ if func.parent is topBlock
1279+ // Top-level => hoist to beginning
1280+ replaceNode func, undefined
1281+ root.expressions.splice i++, 0, ["", func]
1282+ func.parent = root
1283+ else
1284+ func.children.unshift func.name, "="
1285+ root.expressions.splice i++, 0, ["", `var ${func.name};`]
1286+ // Hoist top-level class declarations (like `let`)
1287+ for each classExp of gatherRecursiveWithinFunction topBlock, .type is "ClassExpression"
1288+ if classExp.name and classExp.parent is topBlock or classExp.parent is like {type: "ReturnStatement", parent: ^topBlock}
1289+ classExp.children.unshift classExp.name, "="
1290+ root.expressions.splice i++, 0, ["", `var ${classExp.name};`]
1291+
12711292function populateRefs(statements: ASTNode): void {
1272- const refNodes = gatherRecursive(statements, ({ type }) => type is "Ref")
1293+ const refNodes = gatherRecursive(statements, . type is "Ref")
12731294
12741295 if (refNodes.length) {
12751296 // Find all ids within nested scopes
0 commit comments