| 136 | |
| 137 | global.Go = class { |
| 138 | constructor() { |
| 139 | this._callbackTimeouts = new Map(); |
| 140 | this._nextCallbackTimeoutID = 1; |
| 141 | |
| 142 | const mem = () => { |
| 143 | // The buffer may change when requesting more memory. |
| 144 | return new DataView(this._inst.exports.memory.buffer); |
| 145 | } |
| 146 | |
| 147 | const unboxValue = (v_ref) => { |
| 148 | reinterpretBuf.setBigInt64(0, v_ref, true); |
| 149 | const f = reinterpretBuf.getFloat64(0, true); |
| 150 | if (f === 0) { |
| 151 | return undefined; |
| 152 | } |
| 153 | if (!isNaN(f)) { |
| 154 | return f; |
| 155 | } |
| 156 | |
| 157 | const id = v_ref & 0xffffffffn; |
| 158 | return this._values[id]; |
| 159 | } |
| 160 | |
| 161 | |
| 162 | const loadValue = (addr) => { |
| 163 | let v_ref = mem().getBigUint64(addr, true); |
| 164 | return unboxValue(v_ref); |
| 165 | } |
| 166 | |
| 167 | const boxValue = (v) => { |
| 168 | const nanHead = 0x7FF80000n; |
| 169 | |
| 170 | if (typeof v === "number") { |
| 171 | if (isNaN(v)) { |
| 172 | return nanHead << 32n; |
| 173 | } |
| 174 | if (v === 0) { |
| 175 | return (nanHead << 32n) | 1n; |
| 176 | } |
| 177 | reinterpretBuf.setFloat64(0, v, true); |
| 178 | return reinterpretBuf.getBigInt64(0, true); |
| 179 | } |
| 180 | |
| 181 | switch (v) { |
| 182 | case undefined: |
| 183 | return 0n; |
| 184 | case null: |
| 185 | return (nanHead << 32n) | 2n; |
| 186 | case true: |
| 187 | return (nanHead << 32n) | 3n; |
| 188 | case false: |
| 189 | return (nanHead << 32n) | 4n; |
| 190 | } |
| 191 | |
| 192 | let id = this._ids.get(v); |
| 193 | if (id === undefined) { |
| 194 | id = this._idPool.pop(); |
| 195 | if (id === undefined) { |