@@ -4,9 +4,9 @@ const myModule = require("../index");
4
4
// Obtain the runtime helpers for
5
5
const {
6
6
// memory management
7
- __allocString , __allocArray ,
7
+ __newString , __newArray ,
8
8
// garbage collection
9
- __retain , __release ,
9
+ __pin , __unpin ,
10
10
// and interop
11
11
__getString, __getArray, __getArrayView
12
12
} = myModule ;
@@ -15,40 +15,34 @@ const {
15
15
{
16
16
console . log ( "Example 1:" ) ;
17
17
18
- // Obtain a pointer to our string in the module's memory. Note that `return`ing
19
- // a string, or any other object, from WebAssembly to JavaScript automatically
20
- // retains a reference for us, the caller, to release when we are done with it.
21
- const ptr = myModule . getHello ( ) ;
18
+ // Obtain a pointer to our string in the module's memory.
19
+ const ptr = __pin ( myModule . getHello ( ) ) ;
22
20
23
21
// Print its contents
24
22
console . log ( " " + __getString ( ptr ) ) ;
25
23
26
- __release ( ptr ) ; // we are done with the returned string but
27
- // it might still be alive in WebAssembly
24
+ __unpin ( ptr ) ; // it is ok if the string becomes garbage collected now
28
25
}
29
26
30
27
// Test for Example 2: Passing a string from JavaScript to WebAssembly.
31
28
{
32
29
console . log ( "Example 2:" ) ;
33
30
34
- // Allocate a string in the module's memory and retain a reference to our allocation
35
- const ptr = __retain ( __allocString ( "Hello world (I am a JavaScript string)" ) ) ;
31
+ // Allocate a string in the module's memory and pin it externally
32
+ const ptr = __pin ( __newString ( "Hello world (I am a JavaScript string)" ) ) ;
36
33
37
34
// Pass it to our WebAssembly export, which is going to print it using our custom console
38
35
myModule . sayHello ( ptr ) ;
39
36
40
- __release ( ptr ) ; // we are done with the allocated string but
41
- // it might still be alive in WebAssembly
37
+ __unpin ( ptr ) ; // it is ok if the string becomes garbage collected now
42
38
}
43
39
44
40
// Test for Example 4: Passing an array from WebAssembly to JavaScript.
45
41
{
46
42
console . log ( "Example 4:" ) ;
47
43
48
- // Obtain a pointer to our array in the module's memory. Note that `return`ing
49
- // an object from WebAssembly to JavaScript automatically retains a reference
50
- // for us, the caller, to release when we are done with it.
51
- const ptr = myModule . getMyArray ( 10 ) ;
44
+ // Obtain a pointer to our array in the module's memory.
45
+ const ptr = __pin ( myModule . getMyArray ( 10 ) ) ;
52
46
53
47
// Obtain a live view on it
54
48
const view = __getArrayView ( ptr ) ;
@@ -58,7 +52,7 @@ const {
58
52
const copy = __getArray ( ptr ) ;
59
53
console . log ( " " + copy + " (copy)" ) ;
60
54
61
- __release ( ptr ) ; // we are done with the array
55
+ __unpin ( ptr ) ; // it is ok if the array becomes garbage collected now
62
56
}
63
57
64
58
// Test for Example 5: Passing an array from JavaScript to WebAssembly.
@@ -68,7 +62,7 @@ const {
68
62
// Allocate a new array in WebAssembly memory and get a view on it. Note that
69
63
// we have to specify the runtime id of the array type we want to allocate, so
70
64
// we export its id (`idof<Int32Array>`) from the module to do so.
71
- const ptr = __retain ( __allocArray ( myModule . Int32Array_ID , [ 1 , 2 , 3 ] ) ) ;
65
+ const ptr = __pin ( __newArray ( myModule . Int32Array_ID , [ 1 , 2 , 3 ] ) ) ;
72
66
const view = __getArrayView ( ptr ) ;
73
67
const copy = __getArray ( ptr ) ;
74
68
@@ -82,27 +76,27 @@ const {
82
76
// The initial copy remains unchanged and is not linked to `ptr`
83
77
console . log ( " Unmodified copy: " + copy ) ;
84
78
85
- __release ( ptr ) ; // we are done with our allocated array but
86
- // it might still be alive in WebAssembly
79
+ __unpin ( ptr ) ; // it is ok if the array becomes garbage collected now
87
80
}
88
81
89
82
// Test for Example 6: WebAssembly arrays of WebAssembly strings.
90
83
{
91
84
console . log ( "Example 6:" ) ;
92
85
93
86
// Allocate a new array, but this time its elements are pointers to strings.
94
- // Note: Allocating an array of strings or other objects will automatically
95
- // take care of retaining references to its elements, but the array itself
96
- // must be dealt with as usual.
97
- const inPtr = __retain ( __allocArray ( myModule . ArrayOfStrings_ID , [ "hello" , "world" ] . map ( __allocString ) ) ) ;
87
+ const elemPtrs = [ "hello" , "world" ] . map ( v => __pin ( __newString ( v ) ) ) ;
88
+ const inPtr = __pin ( __newArray ( myModule . ArrayOfStrings_ID , elemPtrs ) ) ;
89
+
90
+ // The array keeps its values alive from now on
91
+ elemPtrs . forEach ( __unpin ) ;
98
92
99
93
// Provide our array of lowercase strings to WebAssembly, and obtain the new
100
94
// array of uppercase strings before printing it.
101
- const outPtr = myModule . capitalize ( inPtr ) ;
95
+ const outPtr = __pin ( myModule . capitalize ( inPtr ) ) ;
102
96
console . log ( " Uppercased: " + __getArray ( outPtr ) . map ( __getString ) ) ;
103
97
104
- __release ( inPtr ) ; // release our allocation and release
105
- __release ( outPtr ) ; // the return value. you know the drill!
98
+ __unpin ( inPtr ) ; // it is ok if the arrays becomes garbage collected now
99
+ __unpin ( outPtr ) ;
106
100
107
101
// Note that Example 6 is not an especially efficient use case and one would
108
102
// typically rather avoid the overhead and do this in JavaScript directly.
@@ -114,57 +108,62 @@ const {
114
108
115
109
// Create a new player. Note that the loader makes a nice object structure
116
110
// of our exports, here a class `Player` within the `Game` namespace. So
117
- // let's call the `Player` constructor (this is also an allocation) :
111
+ // let's call the `Player` constructor:
118
112
let player ;
119
113
{
120
- const namePtr = __retain ( __allocString ( "Gordon Freeman" ) ) ;
114
+ const namePtr = __pin ( __newString ( "Gordon Freeman" ) ) ;
121
115
player = new myModule . Game . Player ( namePtr ) ;
122
- __release ( namePtr ) ;
116
+ __pin ( player ) ;
117
+ __unpin ( namePtr ) ;
118
+ // Pro tip: Pinning is optional in this exact case
123
119
}
124
120
125
121
// Let's see how our player looks now by calling toString
126
122
{
127
- const strPtr = player . toString ( ) ;
123
+ const strPtr = __pin ( player . toString ( ) ) ;
128
124
console . log ( " Player (new): " + __getString ( strPtr ) ) ;
129
- __release ( strPtr ) ;
125
+ __unpin ( strPtr ) ;
126
+ // Pro tip: Pinning is optional in this exact case
130
127
}
131
128
132
129
// Move them and log again
133
130
{
134
131
player . move ( 10 , 20 ) ;
135
- const strPtr = player . toString ( ) ;
132
+ const strPtr = __pin ( player . toString ( ) ) ;
136
133
console . log ( " Player (moved): " + __getString ( strPtr ) ) ;
137
- __release ( strPtr ) ;
134
+ __unpin ( strPtr ) ;
135
+ // Pro tip: Pinning is optional in this exact case
138
136
}
139
137
140
138
// Obtaining just the position. Note that we can `wrap` any pointer with
141
139
// the matching class within the object structure made by the loader, and
142
140
// that a position's x and y properties are just basic values, not objects,
143
141
// so tracking references does not apply to them.
144
142
{
145
- const positionPtr = player . position ; // implicit getter, retained for us
143
+ const positionPtr = __pin ( player . position ) ;
146
144
const position = myModule . Game . Position . wrap ( positionPtr ) ;
147
145
console . log ( " Position (wrapped): " + position . x + "/" + position . y ) ;
148
146
149
147
position . x -= 100 ;
150
148
position . y += 200 ;
151
149
152
- const strPtr = position . toString ( ) ;
150
+ const strPtr = __pin ( position . toString ( ) ) ;
153
151
console . log ( " Position (moved): " + __getString ( strPtr ) ) ;
154
- __release ( strPtr ) ;
152
+ __unpin ( strPtr ) ;
155
153
156
- __release ( positionPtr ) ;
154
+ __unpin ( positionPtr ) ;
157
155
}
158
156
159
157
// Finish 'em
160
158
{
161
159
player . kill ( ) ;
162
- const strPtr = player . toString ( ) ;
160
+ const strPtr = __pin ( player . toString ( ) ) ;
163
161
console . log ( " Player (finished): " + __getString ( strPtr ) ) ;
164
- __release ( strPtr ) ; // we are done with the returned object
162
+ __unpin ( strPtr ) ;
163
+ // Pro tip: Pinning is optional in this exact case
165
164
}
166
165
167
- __release ( player ) ; // a tidy house, a tidy mind.
166
+ __unpin ( player ) ; // a tidy house, a tidy mind.
168
167
}
169
168
170
169
// Interested in all the details? https://docs.assemblyscript.org/details :)
0 commit comments