From c4349275a7d196ed2a278991100eb5de55819a25 Mon Sep 17 00:00:00 2001 From: buke Date: Fri, 22 May 2026 14:45:46 +0800 Subject: [PATCH] feat(runtime): align raw context AToB intrinsic - add an AToB option to raw-context intrinsic selection - wire JS_AddIntrinsicAToB into applyIntrinsics and AllIntrinsics - cover raw-context AToB behavior and failure hooks in runtime tests --- runtime.go | 12 ++++++++++-- runtime_test.go | 27 ++++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/runtime.go b/runtime.go index 422bde9..38e8032 100644 --- a/runtime.go +++ b/runtime.go @@ -152,6 +152,7 @@ type IntrinsicSet struct { WeakRef bool Performance bool DOMException bool + AToB bool } // IntrinsicOption modifies IntrinsicSet. @@ -184,6 +185,7 @@ func AllIntrinsics() IntrinsicSet { WeakRef: true, Performance: true, DOMException: true, + AToB: true, } } @@ -257,9 +259,14 @@ func WithDOMException(enabled bool) IntrinsicOption { return func(s *IntrinsicSet) { s.DOMException = enabled } } +// WithAToB toggles atob/btoa intrinsic injection. +func WithAToB(enabled bool) IntrinsicOption { + return func(s *IntrinsicSet) { s.AToB = enabled } +} + func normalizeIntrinsicSet(set IntrinsicSet) IntrinsicSet { if set.Date || set.Eval || set.RegExp || set.JSON || set.Proxy || set.MapSet || - set.TypedArrays || set.Promise || set.BigInt || set.WeakRef || set.Performance || set.DOMException { + set.TypedArrays || set.Promise || set.BigInt || set.WeakRef || set.Performance || set.DOMException || set.AToB { set.BaseObjects = true } return set @@ -1052,7 +1059,8 @@ func applyIntrinsics(ctxRef *C.JSContext, set IntrinsicSet) bool { applyStep("BigInt", set.BigInt, func() C.int { return C.JS_AddIntrinsicBigInt(ctxRef) }) && applyStep("WeakRef", set.WeakRef, func() C.int { return C.JS_AddIntrinsicWeakRef(ctxRef) }) && applyStep("Performance", set.Performance, func() C.int { return C.JS_AddPerformance(ctxRef) }) && - applyStep("DOMException", set.DOMException, func() C.int { return C.JS_AddIntrinsicDOMException(ctxRef) }) + applyStep("DOMException", set.DOMException, func() C.int { return C.JS_AddIntrinsicDOMException(ctxRef) }) && + applyStep("AToB", set.AToB, func() C.int { return C.JS_AddIntrinsicAToB(ctxRef) }) } // BootstrapStdOS registers std/os modules for the context. diff --git a/runtime_test.go b/runtime_test.go index ec5086d..ffe4562 100644 --- a/runtime_test.go +++ b/runtime_test.go @@ -164,12 +164,28 @@ func TestRuntimeDiagnosticsAndRawContext(t *testing.T) { require.NotNil(t, withEvalCtx) defer withEvalCtx.Close() + missingAToB := withEvalCtx.Eval(`typeof atob === "undefined" && typeof btoa === "undefined"`) + require.NotNil(t, missingAToB) + defer missingAToB.Free() + require.False(t, missingAToB.IsException()) + require.True(t, missingAToB.ToBool()) + evalResult := withEvalCtx.Eval(`1 + 1`) require.NotNil(t, evalResult) defer evalResult.Free() require.False(t, evalResult.IsException()) require.EqualValues(t, 2, evalResult.ToInt32()) + withAToBCtx := rt.NewContextRaw(NewIntrinsicSet(WithEval(true), WithAToB(true))) + require.NotNil(t, withAToBCtx) + defer withAToBCtx.Close() + + atobResult := withAToBCtx.Eval(`typeof atob === "function" && typeof btoa === "function" && atob("Zm9v") === "foo" && btoa("bar") === "YmFy"`) + require.NotNil(t, atobResult) + defer atobResult.Free() + require.False(t, atobResult.IsException()) + require.True(t, atobResult.ToBool()) + all := AllIntrinsics() require.True(t, all.BaseObjects) require.True(t, all.Date) @@ -177,12 +193,14 @@ func TestRuntimeDiagnosticsAndRawContext(t *testing.T) { require.True(t, all.JSON) require.True(t, all.RegExp) require.True(t, all.DOMException) + require.True(t, all.AToB) - selected := NewIntrinsicSet(WithPromise(true), WithJSON(true), WithEval(true)) + selected := NewIntrinsicSet(WithPromise(true), WithJSON(true), WithEval(true), WithAToB(true)) require.True(t, selected.BaseObjects) require.True(t, selected.Promise) require.True(t, selected.JSON) require.True(t, selected.Eval) + require.True(t, selected.AToB) } func TestRuntimeStage3CoveragePaths(t *testing.T) { @@ -204,6 +222,7 @@ func TestRuntimeStage3CoveragePaths(t *testing.T) { WithWeakRef(true), WithPerformance(true), WithDOMException(true), + WithAToB(true), ) require.True(t, full.BaseObjects) require.True(t, full.Date) @@ -218,6 +237,7 @@ func TestRuntimeStage3CoveragePaths(t *testing.T) { require.True(t, full.WeakRef) require.True(t, full.Performance) require.True(t, full.DOMException) + require.True(t, full.AToB) rtIntrinsics := NewRuntime() ctx := rtIntrinsics.NewContextRaw(full) @@ -1180,6 +1200,11 @@ func TestRuntimeNewContextRawApplyIntrinsicsFailureHook(t *testing.T) { ctx = rt.NewContextRaw(NewIntrinsicSet(WithDate(true))) require.Nil(t, ctx) + restoreStepAToB := forceRuntimeApplyIntrinsicStepFailureForTest("AToB") + defer restoreStepAToB() + ctx = rt.NewContextRaw(NewIntrinsicSet(WithAToB(true))) + require.Nil(t, ctx) + restoreNoop := forceRuntimeApplyIntrinsicsFailureForTest(false) defer restoreNoop() restorePassNoop := forceRuntimeApplyIntrinsicsPassthroughHookForTest(false)