Fix render-expr in eval position: wrap result in raw-html
The spec's eval-list calls render-expr for HTML tags/components in eval position but returned a plain string. When that string was later passed through _arender (e.g. as a component keyword arg), it got HTML-escaped. Fix in eval.sx: wrap render-expr result in make-raw-html so the value carries the raw-html type through any evaluator boundary. Also add is_render_expr check in async_eval_ref.py as belt-and-suspenders for the same issue in the async wrapper. This fixes the streaming demo where suspense placeholder divs were displayed as escaped text instead of real DOM elements. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -87,9 +87,19 @@ async def _async_eval(expr, env, ctx):
|
||||
args, kwargs = await _parse_io_args(expr[1:], env, ctx)
|
||||
return await execute_io(head.name, args, kwargs, ctx)
|
||||
|
||||
# Check if this is a render expression (HTML tag, component, fragment)
|
||||
# so we can wrap the result in _RawHTML to prevent double-escaping.
|
||||
# The sync evaluator returns plain strings from render_list_to_html;
|
||||
# the async renderer would HTML-escape those without this wrapper.
|
||||
is_render = isinstance(expr, list) and sx_ref.is_render_expr(expr)
|
||||
|
||||
# For everything else, use the sync transpiled evaluator
|
||||
result = sx_ref.eval_expr(expr, env)
|
||||
return sx_ref.trampoline(result)
|
||||
result = sx_ref.trampoline(result)
|
||||
|
||||
if is_render and isinstance(result, str):
|
||||
return _RawHTML(result)
|
||||
return result
|
||||
|
||||
|
||||
async def _parse_io_args(exprs, env, ctx):
|
||||
@@ -124,6 +134,9 @@ async def _arender(expr, env, ctx):
|
||||
return ""
|
||||
if isinstance(expr, _RawHTML):
|
||||
return expr.html
|
||||
# Also handle sx_ref._RawHTML from the sync evaluator
|
||||
if isinstance(expr, sx_ref._RawHTML):
|
||||
return expr.html
|
||||
if isinstance(expr, str):
|
||||
return escape_text(expr)
|
||||
if isinstance(expr, (int, float)):
|
||||
|
||||
Reference in New Issue
Block a user