Search Apps Documentation Source Content File Folder Download Copy Actions Download State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

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}