crossrealm.gno
4.87 Kb · 209 lines
1package crossrealm
2
3import (
4 "chain/runtime"
5 "chain/runtime/unsafe"
6
7 "gno.land/p/demo/tests/p_crossrealm"
8 "gno.land/p/nt/ownable/v0"
9 "gno.land/p/nt/ufmt/v0"
10)
11
12type LocalStruct struct {
13 A int
14}
15
16func (ls *LocalStruct) String() string {
17 return ufmt.Sprintf("LocalStruct{%d}", ls.A)
18}
19
20// local is saved locally in this realm
21var local *LocalStruct
22
23func init() {
24 local = &LocalStruct{A: 123}
25}
26
27// Make1 returns a local object wrapped by a p struct
28func Make1() *p_crossrealm.Container {
29 return &p_crossrealm.Container{
30 A: 1,
31 B: local,
32 }
33}
34
35type Fooer interface {
36 Foo(realm)
37 Bar()
38}
39
40var fooer Fooer
41
42func SetFooer(cur realm, f Fooer) Fooer {
43 fooer = f
44 return fooer
45}
46
47func GetFooer() Fooer {
48 return fooer
49}
50
51func CallFooerFooCur(cur realm) {
52 fooer.Foo(cur)
53}
54
55func CallFooerFooCross(cur realm) {
56 fooer.Foo(cross(cur))
57}
58
59func CallFooerBar() {
60 fooer.Bar()
61}
62
63func CallFooerBarCrossing(cur realm) {
64 fooer.Bar()
65}
66
67type FooerGetter func() Fooer
68
69var fooerGetter FooerGetter
70
71func SetFooerGetter(cur realm, fg FooerGetter) FooerGetter {
72 fooerGetter = fg
73 return fg
74}
75
76func GetFooerGetter() FooerGetter {
77 return fooerGetter
78}
79
80func CallFooerGetterBar() {
81 fooerGetter().Bar()
82}
83
84func CallFooerGetterBarCrossing(cur realm) {
85 fooerGetter().Bar()
86}
87
88func CallFooerGetterFooCur(cur realm) {
89 fooerGetter().Foo(cur)
90}
91
92func CallFooerGetterFooCross(cur realm) {
93 fooerGetter().Foo(cross(cur))
94}
95
96// This is a top function that does switch realms.
97func ExecCrossing(cur realm, cb func() string) string {
98 return cb()
99}
100
101// This is a top function that doesn't switch realms.
102func Exec(cb func() string) string {
103 return cb()
104}
105
106// ------------------------------------
107// SECURITY XXX: Closure and Closure2 below are exported package-level
108// function-typed vars that any foreign realm can set via SetClosure /
109// SetClosure2 and trigger via ExecuteClosure / ExecuteClosureCross.
110// Closure2's signature is `func(realm)`, which means whoever sets it
111// receives a realm value at invocation time — capability-bearing data
112// stored in an exported package var, then handed back to caller-supplied
113// code. THIS IS DELIBERATE VM-PARITY-TEST INFRASTRUCTURE — these vars
114// exist to exercise the VM's handling of stored closures and cross-
115// realm callbacks. DO NOT COPY THIS PATTERN IN PRODUCTION CODE. Real
116// /r/ realms must never expose `func(realm)` (or any function-typed
117// value capable of receiving cur) as an exported package var.
118var Closure func()
119
120func SetClosure(cur realm, f func()) {
121 Closure = f
122}
123
124func ExecuteClosure(cur realm) {
125 Closure()
126}
127
128var Closure2 func(realm)
129
130func SetClosure2(cur realm, f func(realm)) {
131 Closure2 = f
132}
133func ExecuteClosureCross(cur realm) {
134 Closure2(cross(cur))
135}
136
137// Closure3 mirrors Closure but for non-crossing-with-rlm closures —
138// `func(_ int, rlm realm)`. Whoever sets Closure3 receives cur as a
139// plain value (no realm boundary at invocation time), then can cross
140// internally via cross(rlm).
141var Closure3 func(_ int, rlm realm)
142
143func SetClosure3(cur realm, f func(_ int, rlm realm)) {
144 Closure3 = f
145}
146
147func ExecuteClosure3(cur realm) {
148 Closure3(0, cur)
149}
150
151// Closure -> FooUpdate
152func PrintRealms(cur realm) {
153 ufmt.Printf("current realm: %s\n", unsafe.CurrentRealm())
154 ufmt.Printf("previous realm: %s\n", unsafe.PreviousRealm())
155}
156
157// -------------------------------------------------
158var Object any
159
160func SetObject(cur realm, x any) {
161 Object = x
162}
163
164func GetObject() any {
165 return Object
166}
167
168func EntryPoint() (noCros *ownable.Ownable) {
169 println("crossrealm EntryPoint: " + unsafe.PreviousRealm().PkgPath())
170 println("crossrealm EntryPoint: " + unsafe.PreviousRealm().Address())
171 println()
172 return PrevRealmNoCrossing()
173}
174
175// EntryPointWithCrossing is a non-crossing helper that forwards into
176// the (cur realm)-crossing PrevRealmCrossing. Callers pass their own
177// live cur; `cross(rlm)` does the actual cross.
178func EntryPointWithCrossing(_ int, rlm realm) (withCros *ownable.Ownable) {
179 return PrevRealmCrossing(cross(rlm))
180}
181
182func PrevRealmNoCrossing() *ownable.Ownable {
183 println("crossrealm PreviousRealm no crossing: " + unsafe.PreviousRealm().PkgPath())
184 println("crossrealm PreviousRealm no crossing: " + unsafe.PreviousRealm().Address())
185 return ownable.NewWithAddress(unsafe.CurrentRealm().Address())
186}
187
188func PrevRealmCrossing(cur realm) *ownable.Ownable {
189 println("crossrealm PreviousRealm with crossing: " + unsafe.PreviousRealm().PkgPath())
190 println("crossrealm PreviousRealm with crossing: " + unsafe.PreviousRealm().Address())
191 return ownable.NewWithAddress(cur.Address())
192}
193
194func CurRealmNoCrossing() runtime.Realm {
195 return unsafe.CurrentRealm()
196}
197func CurRealmCrossing(cur realm) runtime.Realm {
198 return unsafe.CurrentRealm()
199}
200
201// call the package that returns current realm
202func PkgCurRealmNoCrossing() runtime.Realm {
203 return p_crossrealm.CurrentRealm()
204}
205
206// call the package that returns current realm
207func PkgCurRealmCrossing(cur realm) runtime.Realm {
208 return unsafe.CurrentRealm()
209}