Skip to content

Commit 8364526

Browse files
committed
Prevent closures from being returned over the bounary
1 parent 69acb4e commit 8364526

12 files changed

+638
-61
lines changed

src/compiler.ts

+18
Original file line numberDiff line numberDiff line change
@@ -2745,6 +2745,24 @@ export class Compiler extends DiagnosticEmitter {
27452745
// Remember that this flow returns
27462746
flow.set(FlowFlags.RETURNS | FlowFlags.TERMINATES);
27472747

2748+
// Prevent returning a closure in an exported function, since interop with closures is
2749+
// not yet supported
2750+
var returnSignature = returnType.signatureReference;
2751+
if (returnSignature !== null && flow.parentFunction.is(CommonFlags.EXPORT)) {
2752+
var returnValueLocalIndex = flow.getTempLocal(returnType).index;
2753+
var nativeReturnType = returnType.toNativeType();
2754+
expr = module.flatten([
2755+
module.local_set(returnValueLocalIndex, expr),
2756+
this.ifClosure(
2757+
module.local_get(returnValueLocalIndex, nativeReturnType),
2758+
this.makeAbort(null, statement), // TODO: throw
2759+
module.nop()
2760+
),
2761+
module.local_get(returnValueLocalIndex, nativeReturnType)
2762+
], nativeReturnType)
2763+
}
2764+
2765+
27482766
// If the last statement anyway, make it the block's return value
27492767
if (isLastInBody && expr != 0 && returnType != Type.void) {
27502768
if (!stmts.length) return expr;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"asc_flags": [
3+
"--runtime none"
4+
],
5+
"skipInstantiate": true
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
(module
2+
(type $none_=>_none (func))
3+
(type $i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32)))
4+
(type $none_=>_i32 (func (result i32)))
5+
(import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32)))
6+
(memory $0 1)
7+
(data (i32.const 1024) "<\00\00\00\01\00\00\00\01\00\00\00<\00\00\00c\00l\00o\00s\00u\00r\00e\00-\00l\00i\00m\00i\00t\00a\00t\00i\00o\00n\00s\00-\00r\00u\00n\00t\00i\00m\00e\00.\00t\00s")
8+
(global $~lib/rt/stub/offset (mut i32) (i32.const 0))
9+
(export "memory" (memory $0))
10+
(export "exportedClosureReturns" (func $closure-limitations-runtime/exportedClosureReturns))
11+
(start $~start)
12+
(func $closure-limitations-runtime/exportedClosureReturns (result i32)
13+
(local $0 i32)
14+
(local $1 i32)
15+
(local $2 i32)
16+
(local $3 i32)
17+
global.get $~lib/rt/stub/offset
18+
i32.const 16
19+
i32.add
20+
local.tee $0
21+
i32.const 16
22+
i32.add
23+
local.tee $1
24+
memory.size
25+
local.tee $3
26+
i32.const 16
27+
i32.shl
28+
local.tee $2
29+
i32.gt_u
30+
if
31+
local.get $3
32+
local.get $1
33+
local.get $2
34+
i32.sub
35+
i32.const 65535
36+
i32.add
37+
i32.const -65536
38+
i32.and
39+
i32.const 16
40+
i32.shr_u
41+
local.tee $2
42+
local.get $3
43+
local.get $2
44+
i32.gt_s
45+
select
46+
memory.grow
47+
i32.const 0
48+
i32.lt_s
49+
if
50+
local.get $2
51+
memory.grow
52+
i32.const 0
53+
i32.lt_s
54+
if
55+
unreachable
56+
end
57+
end
58+
end
59+
local.get $1
60+
global.set $~lib/rt/stub/offset
61+
local.get $0
62+
i32.const 16
63+
i32.sub
64+
local.tee $1
65+
i32.const 16
66+
i32.store
67+
local.get $1
68+
i32.const 1
69+
i32.store offset=4
70+
local.get $1
71+
i32.const 3
72+
i32.store offset=8
73+
local.get $1
74+
i32.const 4
75+
i32.store offset=12
76+
local.get $0
77+
i32.const 1
78+
i32.store
79+
local.get $0
80+
i32.const 0
81+
i32.store offset=4
82+
local.get $0
83+
i32.const 4
84+
i32.shr_s
85+
i32.const -2147483648
86+
i32.or
87+
local.tee $0
88+
i32.const -2147483648
89+
i32.and
90+
i32.const -2147483648
91+
i32.eq
92+
if
93+
i32.const 0
94+
i32.const 1040
95+
i32.const 3
96+
i32.const 3
97+
call $~lib/builtins/abort
98+
unreachable
99+
end
100+
local.get $0
101+
)
102+
(func $~start
103+
i32.const 1104
104+
global.set $~lib/rt/stub/offset
105+
call $closure-limitations-runtime/exportedClosureReturns
106+
drop
107+
)
108+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export function exportedClosureReturns(): (value: i32) => i32 {
2+
var $local0 = 0;
3+
return function inner(value: i32) {
4+
return $local0;
5+
};
6+
}
7+
exportedClosureReturns();

0 commit comments

Comments
 (0)