diff --git a/src/compilerEs/fan/ast/JsExpr.fan b/src/compilerEs/fan/ast/JsExpr.fan index a1847ca84..61c566752 100644 --- a/src/compilerEs/fan/ast/JsExpr.fan +++ b/src/compilerEs/fan/ast/JsExpr.fan @@ -267,6 +267,20 @@ class JsExpr : JsNode leave := x.leave isAssign := x.assignTarget != null + // convert binary expressions testing for equivalence to + // synthetic str "_once_" to undefined + if (lhs.expr is FieldExpr) + { + fe := (FieldExpr)lhs.expr + if (rhs.expr.id === ExprId.strLiteral && + symbol == "===" && rhs.expr->val == "_once_") + { + lhs.write + js.w(" ${symbol} undefined", loc) + return + } + } + if (isAssign && lhs.expr is FieldExpr) { fe := (FieldExpr)lhs.expr diff --git a/src/compilerEs/fan/ast/JsNode.fan b/src/compilerEs/fan/ast/JsNode.fan index 3d010e3bb..d02b958c1 100644 --- a/src/compilerEs/fan/ast/JsNode.fan +++ b/src/compilerEs/fan/ast/JsNode.fan @@ -247,10 +247,11 @@ abstract class JsNode "sys::Str": true ] - Void writeBlock(Block? block) + Void writeBlock(Block? block, |Stmt->Bool|? filter := null) { if (block == null) return block.stmts.each |stmt| { + if (filter?.call(stmt) ?: false) return writeStmt(stmt) js.wl(";") } diff --git a/src/compilerEs/fan/ast/JsType.fan b/src/compilerEs/fan/ast/JsType.fan index 35ec6dbef..79081770d 100644 --- a/src/compilerEs/fan/ast/JsType.fan +++ b/src/compilerEs/fan/ast/JsType.fan @@ -146,7 +146,7 @@ class JsType : JsNode if (instanceInit != null) { plugin.curMethod = instanceInit - writeBlock(instanceInit.code) + writeBlock(instanceInit.code) |stmt| { stmt.isOnceFieldInit ? true : false } plugin.curMethod = null } js.unindent @@ -235,6 +235,9 @@ class JsType : JsNode private static Str fieldDefVal(FieldDef f) { + // once fields are initialized to undefined + if (f.isOnce) return "undefined" + defVal := "null" fieldType := f.fieldType if (!fieldType.isNullable) @@ -269,6 +272,13 @@ class JsType : JsNode // we generate our own special version of this if (f.parent.isEnum && accessName == "vals") return + // special handling for static once fields + if (f.isOnce) + { + js.wl("static ${accessName}(it) { if (it === undefined) return ${target}.${privName}; else ${target}.${privName} = it; }").nl + return + } + js.wl("static ${accessName}() {").indent fieldAccess := "${target}.${privName}" @@ -388,7 +398,9 @@ class JsType : JsNode } // method body - writeBlock(m.code) + |Stmt s->Bool|? filter := null + if (m.isStatic) filter = |Stmt s->Bool| { s.isOnceFieldInit ? true : false } + writeBlock(m.code, filter) } js.unindent