├── .gitattributes ├── .gitignore ├── README.md ├── cloudfunctions └── login │ └── index.js ├── demo.jpg ├── miniprogram ├── app.js ├── app.json ├── app.wxss ├── demo.js ├── demo.wasm ├── hello.js ├── load.js ├── pages │ └── index │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ ├── index.wxss │ │ └── user-unlogin.png └── style │ └── guide.wxss └── project.config.json /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows 2 | [Dd]esktop.ini 3 | Thumbs.db 4 | $RECYCLE.BIN/ 5 | 6 | # macOS 7 | .DS_Store 8 | .fseventsd 9 | .Spotlight-V100 10 | .TemporaryItems 11 | .Trashes 12 | 13 | # Node.js 14 | node_modules/ 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # miniprogram-rust-wasm 2 | 3 | Rust+Webassembly开发微信小程序 4 | 5 | 在iPhone7 和 小米8 Android 8.1.0成功运行 6 | 7 | 启动代码在miniprogram/app.js中 8 | 9 | hello.js和hello.wasm 是 https://github.com/koute/stdweb/tree/master/examples/minimal编译得到的 10 | 11 | demo.js和demo.wasm 是 https://github.com/koute/stdweb/tree/master/examples/hasher编译得到的 12 | 13 | 编译: cargo web build --target=wasm32-unknown-unknown --release 14 | 15 | hello.js和demo.js在代码中经过改动适配微信小程序 16 | 17 | stdweb的安装教程在这里https://crates.io/crates/stdweb 18 | 19 | 运行截图: 20 | 21 | -------------------------------------------------------------------------------- /cloudfunctions/login/index.js: -------------------------------------------------------------------------------- 1 | // 云函数模板 2 | // 部署:在 cloud-functions/login 文件夹右击选择 “上传并部署” 3 | 4 | /** 5 | * 这个示例将经自动鉴权过的小程序用户 openid 返回给小程序端 6 | * 7 | * event 参数包含 8 | * - 小程序端调用传入的 data 9 | * - 经过微信鉴权直接可信的用户唯一标识 openid 10 | * 11 | */ 12 | exports.main = (event, context) => { 13 | console.log(event) 14 | console.log(context) 15 | 16 | // 可执行其他自定义逻辑 17 | // console.log 的内容可以在云开发云函数调用日志查看 18 | 19 | return { 20 | openid: event.userInfo.openId, 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /demo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planet0104/miniprogram-rust-wasm/6ad99a41e262b9648a2f5bea74a35c10436d8945/demo.jpg -------------------------------------------------------------------------------- /miniprogram/app.js: -------------------------------------------------------------------------------- 1 | // hello.js是测试HelloWorld的例子 2 | // require("hello.js"); 3 | //app.js 4 | App({ 5 | onLaunch: function () { 6 | // demo.js是crate-type = ["cdylib"] 7 | var Rust = require("demo.js"); 8 | 9 | Rust.then(function (demo) { 10 | let name = "Rust"; 11 | let hash = demo.sha1(name); 12 | wx.showModal({ 13 | title: 'SHA1测试', 14 | content: "\"" + name + "\"的SHA1是" + hash, 15 | }); 16 | }); 17 | } 18 | }) 19 | -------------------------------------------------------------------------------- /miniprogram/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "pages": [ 3 | "pages/index/index" 4 | ], 5 | "window": { 6 | "backgroundColor": "#F6F6F6", 7 | "backgroundTextStyle": "light", 8 | "navigationBarBackgroundColor": "#F6F6F6", 9 | "navigationBarTitleText": "懒人字典", 10 | "navigationBarTextStyle": "black" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /miniprogram/app.wxss: -------------------------------------------------------------------------------- 1 | /**app.wxss**/ 2 | .container { 3 | display: flex; 4 | flex-direction: column; 5 | align-items: center; 6 | box-sizing: border-box; 7 | } 8 | -------------------------------------------------------------------------------- /miniprogram/demo.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | if( typeof Rust === "undefined" ) { 4 | var Rust = {}; 5 | } 6 | 7 | (function( root, factory ) { 8 | if( typeof define === "function" && define.amd ) { 9 | define( [], factory ); 10 | } else if( typeof module === "object" && module.exports ) { 11 | module.exports = factory(); 12 | } else { 13 | Rust.demo = factory(); 14 | } 15 | }( this, function() { 16 | return (function( module_factory ) { 17 | var instance = module_factory(); 18 | 19 | if( typeof window === "undefined" && typeof process === "object" ) { 20 | var fs = require( "fs" ); 21 | var path = require( "path" ); 22 | var wasm_path = path.join( __dirname, "demo.wasm" ); 23 | var buffer = fs.readFileSync( wasm_path ); 24 | var mod = new WebAssembly.Module( buffer ); 25 | var wasm_instance = new WebAssembly.Instance( mod, instance.imports ); 26 | return instance.initialize( wasm_instance ); 27 | } else { 28 | 29 | //微信小程序不支持fetch,这里改造以下 30 | var loadFile = new Promise(function (resolve, reject) { 31 | let fsm = wx.getFileSystemManager(); 32 | fsm.readFile({ 33 | filePath: "demo.wasm", 34 | success: function (res) { 35 | resolve(res.data); 36 | }, 37 | fail: function(err){ 38 | reject(err); 39 | } 40 | }); 41 | }); 42 | 43 | //wasm文件在真机上传时会丢掉 44 | //用wx.request请求demo.wasm时,在本地正常,真机调试wasm解析会报错, 45 | //所以这里改成请求base64内容,然后转换成arrayBuffer 46 | // var loadFile = new Promise(function (resolve, reject) { 47 | // wx.request({ 48 | // url: 'https://planet0104.github.io/demo.wasm.txt', 49 | // responseType: "text", 50 | // success: function (res) { 51 | // const arrayBuffer = wx.base64ToArrayBuffer(res.data); 52 | // resolve(arrayBuffer); 53 | // }, 54 | // fail: (res) => { 55 | // reject(res); 56 | // } 57 | // })}); 58 | 59 | var wasm_instance = loadFile.then(function (bytes) { return WebAssembly.compile(bytes); }) 60 | .then(function (mod) { return WebAssembly.instantiate(mod, instance.imports) }); 61 | 62 | return wasm_instance 63 | .then( function( wasm_instance ) { 64 | var exports = instance.initialize( wasm_instance ); 65 | console.log( "Finished loading Rust wasm module 'demo'" ); 66 | return exports; 67 | }) 68 | .catch( function( error ) { 69 | console.log( "Error loading Rust wasm module 'demo':", error ); 70 | throw error; 71 | }); 72 | } 73 | }( function() { 74 | var Module = {}; 75 | 76 | Module.STDWEB_PRIVATE = {}; 77 | 78 | // This is based on code from Emscripten's preamble.js. 79 | Module.STDWEB_PRIVATE.to_utf8 = function to_utf8( str, addr ) { 80 | for( var i = 0; i < str.length; ++i ) { 81 | // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! So decode UTF16->UTF32->UTF8. 82 | // See http://unicode.org/faq/utf_bom.html#utf16-3 83 | // For UTF8 byte structure, see http://en.wikipedia.org/wiki/UTF-8#Description and https://www.ietf.org/rfc/rfc2279.txt and https://tools.ietf.org/html/rfc3629 84 | var u = str.charCodeAt( i ); // possibly a lead surrogate 85 | if( u >= 0xD800 && u <= 0xDFFF ) { 86 | u = 0x10000 + ((u & 0x3FF) << 10) | (str.charCodeAt( ++i ) & 0x3FF); 87 | } 88 | 89 | if( u <= 0x7F ) { 90 | HEAPU8[ addr++ ] = u; 91 | } else if( u <= 0x7FF ) { 92 | HEAPU8[ addr++ ] = 0xC0 | (u >> 6); 93 | HEAPU8[ addr++ ] = 0x80 | (u & 63); 94 | } else if( u <= 0xFFFF ) { 95 | HEAPU8[ addr++ ] = 0xE0 | (u >> 12); 96 | HEAPU8[ addr++ ] = 0x80 | ((u >> 6) & 63); 97 | HEAPU8[ addr++ ] = 0x80 | (u & 63); 98 | } else if( u <= 0x1FFFFF ) { 99 | HEAPU8[ addr++ ] = 0xF0 | (u >> 18); 100 | HEAPU8[ addr++ ] = 0x80 | ((u >> 12) & 63); 101 | HEAPU8[ addr++ ] = 0x80 | ((u >> 6) & 63); 102 | HEAPU8[ addr++ ] = 0x80 | (u & 63); 103 | } else if( u <= 0x3FFFFFF ) { 104 | HEAPU8[ addr++ ] = 0xF8 | (u >> 24); 105 | HEAPU8[ addr++ ] = 0x80 | ((u >> 18) & 63); 106 | HEAPU8[ addr++ ] = 0x80 | ((u >> 12) & 63); 107 | HEAPU8[ addr++ ] = 0x80 | ((u >> 6) & 63); 108 | HEAPU8[ addr++ ] = 0x80 | (u & 63); 109 | } else { 110 | HEAPU8[ addr++ ] = 0xFC | (u >> 30); 111 | HEAPU8[ addr++ ] = 0x80 | ((u >> 24) & 63); 112 | HEAPU8[ addr++ ] = 0x80 | ((u >> 18) & 63); 113 | HEAPU8[ addr++ ] = 0x80 | ((u >> 12) & 63); 114 | HEAPU8[ addr++ ] = 0x80 | ((u >> 6) & 63); 115 | HEAPU8[ addr++ ] = 0x80 | (u & 63); 116 | } 117 | } 118 | }; 119 | 120 | Module.STDWEB_PRIVATE.noop = function() {}; 121 | Module.STDWEB_PRIVATE.to_js = function to_js( address ) { 122 | var kind = HEAPU8[ address + 12 ]; 123 | if( kind === 0 ) { 124 | return undefined; 125 | } else if( kind === 1 ) { 126 | return null; 127 | } else if( kind === 2 ) { 128 | return HEAP32[ address / 4 ]; 129 | } else if( kind === 3 ) { 130 | return HEAPF64[ address / 8 ]; 131 | } else if( kind === 4 ) { 132 | var pointer = HEAPU32[ address / 4 ]; 133 | var length = HEAPU32[ (address + 4) / 4 ]; 134 | return Module.STDWEB_PRIVATE.to_js_string( pointer, length ); 135 | } else if( kind === 5 ) { 136 | return false; 137 | } else if( kind === 6 ) { 138 | return true; 139 | } else if( kind === 7 ) { 140 | var pointer = Module.STDWEB_PRIVATE.arena + HEAPU32[ address / 4 ]; 141 | var length = HEAPU32[ (address + 4) / 4 ]; 142 | var output = []; 143 | for( var i = 0; i < length; ++i ) { 144 | output.push( Module.STDWEB_PRIVATE.to_js( pointer + i * 16 ) ); 145 | } 146 | return output; 147 | } else if( kind === 8 ) { 148 | var arena = Module.STDWEB_PRIVATE.arena; 149 | var value_array_pointer = arena + HEAPU32[ address / 4 ]; 150 | var length = HEAPU32[ (address + 4) / 4 ]; 151 | var key_array_pointer = arena + HEAPU32[ (address + 8) / 4 ]; 152 | var output = {}; 153 | for( var i = 0; i < length; ++i ) { 154 | var key_pointer = HEAPU32[ (key_array_pointer + i * 8) / 4 ]; 155 | var key_length = HEAPU32[ (key_array_pointer + 4 + i * 8) / 4 ]; 156 | var key = Module.STDWEB_PRIVATE.to_js_string( key_pointer, key_length ); 157 | var value = Module.STDWEB_PRIVATE.to_js( value_array_pointer + i * 16 ); 158 | output[ key ] = value; 159 | } 160 | return output; 161 | } else if( kind === 9 ) { 162 | return Module.STDWEB_PRIVATE.acquire_js_reference( HEAP32[ address / 4 ] ); 163 | } else if( kind === 10 || kind === 12 || kind === 13 ) { 164 | var adapter_pointer = HEAPU32[ address / 4 ]; 165 | var pointer = HEAPU32[ (address + 4) / 4 ]; 166 | var deallocator_pointer = HEAPU32[ (address + 8) / 4 ]; 167 | var num_ongoing_calls = 0; 168 | var drop_queued = false; 169 | var output = function() { 170 | if( pointer === 0 || drop_queued === true ) { 171 | if (kind === 10) { 172 | throw new ReferenceError( "Already dropped Rust function called!" ); 173 | } else if (kind === 12) { 174 | throw new ReferenceError( "Already dropped FnMut function called!" ); 175 | } else { 176 | throw new ReferenceError( "Already called or dropped FnOnce function called!" ); 177 | } 178 | } 179 | 180 | var function_pointer = pointer; 181 | if (kind === 13) { 182 | output.drop = Module.STDWEB_PRIVATE.noop; 183 | pointer = 0; 184 | } 185 | 186 | if (num_ongoing_calls !== 0) { 187 | if (kind === 12 || kind === 13) { 188 | throw new ReferenceError( "FnMut function called multiple times concurrently!" ); 189 | } 190 | } 191 | 192 | var args = Module.STDWEB_PRIVATE.alloc( 16 ); 193 | Module.STDWEB_PRIVATE.serialize_array( args, arguments ); 194 | 195 | try { 196 | num_ongoing_calls += 1; 197 | Module.STDWEB_PRIVATE.dyncall( "vii", adapter_pointer, [function_pointer, args] ); 198 | var result = Module.STDWEB_PRIVATE.tmp; 199 | Module.STDWEB_PRIVATE.tmp = null; 200 | } finally { 201 | num_ongoing_calls -= 1; 202 | } 203 | 204 | if( drop_queued === true && num_ongoing_calls === 0 ) { 205 | output.drop(); 206 | } 207 | 208 | return result; 209 | }; 210 | 211 | output.drop = function() { 212 | if (num_ongoing_calls !== 0) { 213 | drop_queued = true; 214 | return; 215 | } 216 | 217 | output.drop = Module.STDWEB_PRIVATE.noop; 218 | var function_pointer = pointer; 219 | pointer = 0; 220 | 221 | if (function_pointer != 0) { 222 | Module.STDWEB_PRIVATE.dyncall( "vi", deallocator_pointer, [function_pointer] ); 223 | } 224 | }; 225 | 226 | return output; 227 | } else if( kind === 14 ) { 228 | var pointer = HEAPU32[ address / 4 ]; 229 | var length = HEAPU32[ (address + 4) / 4 ]; 230 | var array_kind = HEAPU32[ (address + 8) / 4 ]; 231 | var pointer_end = pointer + length; 232 | 233 | switch( array_kind ) { 234 | case 0: 235 | return HEAPU8.subarray( pointer, pointer_end ); 236 | case 1: 237 | return HEAP8.subarray( pointer, pointer_end ); 238 | case 2: 239 | return HEAPU16.subarray( pointer, pointer_end ); 240 | case 3: 241 | return HEAP16.subarray( pointer, pointer_end ); 242 | case 4: 243 | return HEAPU32.subarray( pointer, pointer_end ); 244 | case 5: 245 | return HEAP32.subarray( pointer, pointer_end ); 246 | case 6: 247 | return HEAPF32.subarray( pointer, pointer_end ); 248 | case 7: 249 | return HEAPF64.subarray( pointer, pointer_end ); 250 | } 251 | } else if( kind === 15 ) { 252 | return Module.STDWEB_PRIVATE.get_raw_value( HEAPU32[ address / 4 ] ); 253 | } 254 | }; 255 | 256 | Module.STDWEB_PRIVATE.serialize_object = function serialize_object( address, value ) { 257 | var keys = Object.keys( value ); 258 | var length = keys.length; 259 | var key_array_pointer = Module.STDWEB_PRIVATE.alloc( length * 8 ); 260 | var value_array_pointer = Module.STDWEB_PRIVATE.alloc( length * 16 ); 261 | HEAPU8[ address + 12 ] = 8; 262 | HEAPU32[ address / 4 ] = value_array_pointer; 263 | HEAPU32[ (address + 4) / 4 ] = length; 264 | HEAPU32[ (address + 8) / 4 ] = key_array_pointer; 265 | for( var i = 0; i < length; ++i ) { 266 | var key = keys[ i ]; 267 | var key_length = Module.STDWEB_PRIVATE.utf8_len( key ); 268 | var key_pointer = Module.STDWEB_PRIVATE.alloc( key_length ); 269 | Module.STDWEB_PRIVATE.to_utf8( key, key_pointer ); 270 | 271 | var key_address = key_array_pointer + i * 8; 272 | HEAPU32[ key_address / 4 ] = key_pointer; 273 | HEAPU32[ (key_address + 4) / 4 ] = key_length; 274 | 275 | Module.STDWEB_PRIVATE.from_js( value_array_pointer + i * 16, value[ key ] ); 276 | } 277 | }; 278 | 279 | Module.STDWEB_PRIVATE.serialize_array = function serialize_array( address, value ) { 280 | var length = value.length; 281 | var pointer = Module.STDWEB_PRIVATE.alloc( length * 16 ); 282 | HEAPU8[ address + 12 ] = 7; 283 | HEAPU32[ address / 4 ] = pointer; 284 | HEAPU32[ (address + 4) / 4 ] = length; 285 | for( var i = 0; i < length; ++i ) { 286 | Module.STDWEB_PRIVATE.from_js( pointer + i * 16, value[ i ] ); 287 | } 288 | }; 289 | 290 | Module.STDWEB_PRIVATE.from_js = function from_js( address, value ) { 291 | var kind = Object.prototype.toString.call( value ); 292 | if( kind === "[object String]" ) { 293 | var length = Module.STDWEB_PRIVATE.utf8_len( value ); 294 | var pointer = 0; 295 | if( length > 0 ) { 296 | pointer = Module.STDWEB_PRIVATE.alloc( length ); 297 | Module.STDWEB_PRIVATE.to_utf8( value, pointer ); 298 | } 299 | HEAPU8[ address + 12 ] = 4; 300 | HEAPU32[ address / 4 ] = pointer; 301 | HEAPU32[ (address + 4) / 4 ] = length; 302 | } else if( kind === "[object Number]" ) { 303 | if( value === (value|0) ) { 304 | HEAPU8[ address + 12 ] = 2; 305 | HEAP32[ address / 4 ] = value; 306 | } else { 307 | HEAPU8[ address + 12 ] = 3; 308 | HEAPF64[ address / 8 ] = value; 309 | } 310 | } else if( value === null ) { 311 | HEAPU8[ address + 12 ] = 1; 312 | } else if( value === undefined ) { 313 | HEAPU8[ address + 12 ] = 0; 314 | } else if( value === false ) { 315 | HEAPU8[ address + 12 ] = 5; 316 | } else if( value === true ) { 317 | HEAPU8[ address + 12 ] = 6; 318 | } else if( kind === "[object Symbol]" ) { 319 | var id = Module.STDWEB_PRIVATE.register_raw_value( value ); 320 | HEAPU8[ address + 12 ] = 15; 321 | HEAP32[ address / 4 ] = id; 322 | } else { 323 | var refid = Module.STDWEB_PRIVATE.acquire_rust_reference( value ); 324 | HEAPU8[ address + 12 ] = 9; 325 | HEAP32[ address / 4 ] = refid; 326 | } 327 | }; 328 | 329 | // This is ported from Rust's stdlib; it's faster than 330 | // the string conversion from Emscripten. 331 | Module.STDWEB_PRIVATE.to_js_string = function to_js_string( index, length ) { 332 | index = index|0; 333 | length = length|0; 334 | var end = (index|0) + (length|0); 335 | var output = ""; 336 | while( index < end ) { 337 | var x = HEAPU8[ index++ ]; 338 | if( x < 128 ) { 339 | output += String.fromCharCode( x ); 340 | continue; 341 | } 342 | var init = (x & (0x7F >> 2)); 343 | var y = 0; 344 | if( index < end ) { 345 | y = HEAPU8[ index++ ]; 346 | } 347 | var ch = (init << 6) | (y & 63); 348 | if( x >= 0xE0 ) { 349 | var z = 0; 350 | if( index < end ) { 351 | z = HEAPU8[ index++ ]; 352 | } 353 | var y_z = ((y & 63) << 6) | (z & 63); 354 | ch = init << 12 | y_z; 355 | if( x >= 0xF0 ) { 356 | var w = 0; 357 | if( index < end ) { 358 | w = HEAPU8[ index++ ]; 359 | } 360 | ch = (init & 7) << 18 | ((y_z << 6) | (w & 63)); 361 | 362 | output += String.fromCharCode( 0xD7C0 + (ch >> 10) ); 363 | ch = 0xDC00 + (ch & 0x3FF); 364 | } 365 | } 366 | output += String.fromCharCode( ch ); 367 | continue; 368 | } 369 | return output; 370 | }; 371 | 372 | Module.STDWEB_PRIVATE.id_to_ref_map = {}; 373 | Module.STDWEB_PRIVATE.id_to_refcount_map = {}; 374 | Module.STDWEB_PRIVATE.ref_to_id_map = new WeakMap(); 375 | // Not all types can be stored in a WeakMap 376 | Module.STDWEB_PRIVATE.ref_to_id_map_fallback = new Map(); 377 | Module.STDWEB_PRIVATE.last_refid = 1; 378 | 379 | Module.STDWEB_PRIVATE.id_to_raw_value_map = {}; 380 | Module.STDWEB_PRIVATE.last_raw_value_id = 1; 381 | 382 | Module.STDWEB_PRIVATE.acquire_rust_reference = function( reference ) { 383 | if( reference === undefined || reference === null ) { 384 | return 0; 385 | } 386 | 387 | var id_to_refcount_map = Module.STDWEB_PRIVATE.id_to_refcount_map; 388 | var id_to_ref_map = Module.STDWEB_PRIVATE.id_to_ref_map; 389 | var ref_to_id_map = Module.STDWEB_PRIVATE.ref_to_id_map; 390 | var ref_to_id_map_fallback = Module.STDWEB_PRIVATE.ref_to_id_map_fallback; 391 | 392 | var refid = ref_to_id_map.get( reference ); 393 | if( refid === undefined ) { 394 | refid = ref_to_id_map_fallback.get( reference ); 395 | } 396 | if( refid === undefined ) { 397 | refid = Module.STDWEB_PRIVATE.last_refid++; 398 | try { 399 | ref_to_id_map.set( reference, refid ); 400 | } catch (e) { 401 | ref_to_id_map_fallback.set( reference, refid ); 402 | } 403 | } 404 | 405 | if( refid in id_to_ref_map ) { 406 | id_to_refcount_map[ refid ]++; 407 | } else { 408 | id_to_ref_map[ refid ] = reference; 409 | id_to_refcount_map[ refid ] = 1; 410 | } 411 | 412 | return refid; 413 | }; 414 | 415 | Module.STDWEB_PRIVATE.acquire_js_reference = function( refid ) { 416 | return Module.STDWEB_PRIVATE.id_to_ref_map[ refid ]; 417 | }; 418 | 419 | Module.STDWEB_PRIVATE.increment_refcount = function( refid ) { 420 | Module.STDWEB_PRIVATE.id_to_refcount_map[ refid ]++; 421 | }; 422 | 423 | Module.STDWEB_PRIVATE.decrement_refcount = function( refid ) { 424 | var id_to_refcount_map = Module.STDWEB_PRIVATE.id_to_refcount_map; 425 | if( 0 == --id_to_refcount_map[ refid ] ) { 426 | var id_to_ref_map = Module.STDWEB_PRIVATE.id_to_ref_map; 427 | var ref_to_id_map_fallback = Module.STDWEB_PRIVATE.ref_to_id_map_fallback; 428 | var reference = id_to_ref_map[ refid ]; 429 | delete id_to_ref_map[ refid ]; 430 | delete id_to_refcount_map[ refid ]; 431 | ref_to_id_map_fallback.delete(reference); 432 | } 433 | }; 434 | 435 | Module.STDWEB_PRIVATE.register_raw_value = function( value ) { 436 | var id = Module.STDWEB_PRIVATE.last_raw_value_id++; 437 | Module.STDWEB_PRIVATE.id_to_raw_value_map[ id ] = value; 438 | return id; 439 | }; 440 | 441 | Module.STDWEB_PRIVATE.unregister_raw_value = function( id ) { 442 | delete Module.STDWEB_PRIVATE.id_to_raw_value_map[ id ]; 443 | }; 444 | 445 | Module.STDWEB_PRIVATE.get_raw_value = function( id ) { 446 | return Module.STDWEB_PRIVATE.id_to_raw_value_map[ id ]; 447 | }; 448 | 449 | Module.STDWEB_PRIVATE.alloc = function alloc( size ) { 450 | return Module.web_malloc( size ); 451 | }; 452 | 453 | Module.STDWEB_PRIVATE.dyncall = function( signature, ptr, args ) { 454 | return Module.web_table.get( ptr ).apply( null, args ); 455 | }; 456 | 457 | // This is based on code from Emscripten's preamble.js. 458 | Module.STDWEB_PRIVATE.utf8_len = function utf8_len( str ) { 459 | var len = 0; 460 | for( var i = 0; i < str.length; ++i ) { 461 | // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! So decode UTF16->UTF32->UTF8. 462 | // See http://unicode.org/faq/utf_bom.html#utf16-3 463 | var u = str.charCodeAt( i ); // possibly a lead surrogate 464 | if( u >= 0xD800 && u <= 0xDFFF ) { 465 | u = 0x10000 + ((u & 0x3FF) << 10) | (str.charCodeAt( ++i ) & 0x3FF); 466 | } 467 | 468 | if( u <= 0x7F ) { 469 | ++len; 470 | } else if( u <= 0x7FF ) { 471 | len += 2; 472 | } else if( u <= 0xFFFF ) { 473 | len += 3; 474 | } else if( u <= 0x1FFFFF ) { 475 | len += 4; 476 | } else if( u <= 0x3FFFFFF ) { 477 | len += 5; 478 | } else { 479 | len += 6; 480 | } 481 | } 482 | return len; 483 | }; 484 | 485 | Module.STDWEB_PRIVATE.prepare_any_arg = function( value ) { 486 | var arg = Module.STDWEB_PRIVATE.alloc( 16 ); 487 | Module.STDWEB_PRIVATE.from_js( arg, value ); 488 | return arg; 489 | }; 490 | 491 | Module.STDWEB_PRIVATE.acquire_tmp = function( dummy ) { 492 | var value = Module.STDWEB_PRIVATE.tmp; 493 | Module.STDWEB_PRIVATE.tmp = null; 494 | return value; 495 | }; 496 | 497 | 498 | 499 | var HEAP8 = null; 500 | var HEAP16 = null; 501 | var HEAP32 = null; 502 | var HEAPU8 = null; 503 | var HEAPU16 = null; 504 | var HEAPU32 = null; 505 | var HEAPF32 = null; 506 | var HEAPF64 = null; 507 | 508 | Object.defineProperty( Module, 'exports', { value: {} } ); 509 | 510 | function __web_on_grow() { 511 | var buffer = Module.instance.exports.memory.buffer; 512 | HEAP8 = new Int8Array( buffer ); 513 | HEAP16 = new Int16Array( buffer ); 514 | HEAP32 = new Int32Array( buffer ); 515 | HEAPU8 = new Uint8Array( buffer ); 516 | HEAPU16 = new Uint16Array( buffer ); 517 | HEAPU32 = new Uint32Array( buffer ); 518 | HEAPF32 = new Float32Array( buffer ); 519 | HEAPF64 = new Float64Array( buffer ); 520 | } 521 | 522 | return { 523 | imports: { 524 | env: { 525 | "__extjs_db0226ae1bbecd407e9880ee28ddc70fc3322d9c": function($0) { 526 | $0 = Module.STDWEB_PRIVATE.to_js($0);Module.STDWEB_PRIVATE.unregister_raw_value (($0)); 527 | }, 528 | "__extjs_ff5103e6cc179d13b4c7a785bdce2708fd559fc0": function($0) { 529 | Module.STDWEB_PRIVATE.tmp = Module.STDWEB_PRIVATE.to_js( $0 ); 530 | }, 531 | "__extjs_80d6d56760c65e49b7be8b6b01c1ea861b046bf0": function($0) { 532 | Module.STDWEB_PRIVATE.decrement_refcount( $0 ); 533 | }, 534 | "__web_on_grow": __web_on_grow 535 | } 536 | }, 537 | initialize: function( instance ) { 538 | Object.defineProperty( Module, 'instance', { value: instance } ); 539 | Object.defineProperty( Module, 'web_malloc', { value: Module.instance.exports.__web_malloc } ); 540 | Object.defineProperty( Module, 'web_free', { value: Module.instance.exports.__web_free } ); 541 | Object.defineProperty( Module, 'web_table', { value: Module.instance.exports.__web_table } ); 542 | 543 | Module.exports.sha1 = function sha1(string) { 544 | return Module.STDWEB_PRIVATE.acquire_tmp(Module.instance.exports.sha1(Module.STDWEB_PRIVATE.prepare_any_arg(string))); 545 | } 546 | ; 547 | __web_on_grow(); 548 | 549 | 550 | return Module.exports; 551 | } 552 | }; 553 | } 554 | )); 555 | })); 556 | -------------------------------------------------------------------------------- /miniprogram/demo.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planet0104/miniprogram-rust-wasm/6ad99a41e262b9648a2f5bea74a35c10436d8945/miniprogram/demo.wasm -------------------------------------------------------------------------------- /miniprogram/hello.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | if (typeof Rust === "undefined") { 4 | var Rust = {}; 5 | } 6 | 7 | (function (root, factory) { 8 | if (typeof define === "function" && define.amd) { 9 | define([], factory); 10 | } else if (typeof module === "object" && module.exports) { 11 | module.exports = factory(); 12 | } else { 13 | Rust.hello = factory(); 14 | } 15 | }(this, function () { 16 | return (function (module_factory) { 17 | var instance = module_factory(); 18 | 19 | if (typeof window === "undefined" && typeof process === "object") { 20 | var fs = require("fs"); 21 | var path = require("path"); 22 | var wasm_path = path.join(__dirname, "hello.wasm"); 23 | var buffer = fs.readFileSync(wasm_path); 24 | var mod = new WebAssembly.Module(buffer); 25 | var wasm_instance = new WebAssembly.Instance(mod, instance.imports); 26 | return instance.initialize(wasm_instance); 27 | } else { 28 | var loadFile = new Promise(function (resolve, reject) { 29 | wx.request({ 30 | url: 'https://planet0104.github.io/hello.wasm.txt', 31 | responseType: "text", 32 | success: function (res) { 33 | const arrayBuffer = wx.base64ToArrayBuffer(res.data); 34 | resolve(arrayBuffer); 35 | }, 36 | fail: (res) => { 37 | reject(res); 38 | } 39 | }) 40 | }); 41 | //var file = fetch("hello.wasm", { credentials: "same-origin" }); 42 | 43 | var wasm_instance = loadFile 44 | .then(function (bytes) { return WebAssembly.compile(bytes); }) 45 | .then(function (mod) { return WebAssembly.instantiate(mod, instance.imports) }); 46 | 47 | return wasm_instance 48 | .then(function (wasm_instance) { 49 | var exports = instance.initialize(wasm_instance); 50 | console.log("Finished loading Rust wasm module 'hello'"); 51 | return exports; 52 | }) 53 | .catch(function (error) { 54 | console.log("Error loading Rust wasm module 'hello':", error); 55 | throw error; 56 | }); 57 | } 58 | }(function () { 59 | var Module = {}; 60 | 61 | Module.STDWEB_PRIVATE = {}; 62 | 63 | // This is based on code from Emscripten's preamble.js. 64 | Module.STDWEB_PRIVATE.to_utf8 = function to_utf8(str, addr) { 65 | for (var i = 0; i < str.length; ++i) { 66 | // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! So decode UTF16->UTF32->UTF8. 67 | // See http://unicode.org/faq/utf_bom.html#utf16-3 68 | // For UTF8 byte structure, see http://en.wikipedia.org/wiki/UTF-8#Description and https://www.ietf.org/rfc/rfc2279.txt and https://tools.ietf.org/html/rfc3629 69 | var u = str.charCodeAt(i); // possibly a lead surrogate 70 | if (u >= 0xD800 && u <= 0xDFFF) { 71 | u = 0x10000 + ((u & 0x3FF) << 10) | (str.charCodeAt(++i) & 0x3FF); 72 | } 73 | 74 | if (u <= 0x7F) { 75 | HEAPU8[addr++] = u; 76 | } else if (u <= 0x7FF) { 77 | HEAPU8[addr++] = 0xC0 | (u >> 6); 78 | HEAPU8[addr++] = 0x80 | (u & 63); 79 | } else if (u <= 0xFFFF) { 80 | HEAPU8[addr++] = 0xE0 | (u >> 12); 81 | HEAPU8[addr++] = 0x80 | ((u >> 6) & 63); 82 | HEAPU8[addr++] = 0x80 | (u & 63); 83 | } else if (u <= 0x1FFFFF) { 84 | HEAPU8[addr++] = 0xF0 | (u >> 18); 85 | HEAPU8[addr++] = 0x80 | ((u >> 12) & 63); 86 | HEAPU8[addr++] = 0x80 | ((u >> 6) & 63); 87 | HEAPU8[addr++] = 0x80 | (u & 63); 88 | } else if (u <= 0x3FFFFFF) { 89 | HEAPU8[addr++] = 0xF8 | (u >> 24); 90 | HEAPU8[addr++] = 0x80 | ((u >> 18) & 63); 91 | HEAPU8[addr++] = 0x80 | ((u >> 12) & 63); 92 | HEAPU8[addr++] = 0x80 | ((u >> 6) & 63); 93 | HEAPU8[addr++] = 0x80 | (u & 63); 94 | } else { 95 | HEAPU8[addr++] = 0xFC | (u >> 30); 96 | HEAPU8[addr++] = 0x80 | ((u >> 24) & 63); 97 | HEAPU8[addr++] = 0x80 | ((u >> 18) & 63); 98 | HEAPU8[addr++] = 0x80 | ((u >> 12) & 63); 99 | HEAPU8[addr++] = 0x80 | ((u >> 6) & 63); 100 | HEAPU8[addr++] = 0x80 | (u & 63); 101 | } 102 | } 103 | }; 104 | 105 | Module.STDWEB_PRIVATE.noop = function () { }; 106 | Module.STDWEB_PRIVATE.to_js = function to_js(address) { 107 | var kind = HEAPU8[address + 12]; 108 | if (kind === 0) { 109 | return undefined; 110 | } else if (kind === 1) { 111 | return null; 112 | } else if (kind === 2) { 113 | return HEAP32[address / 4]; 114 | } else if (kind === 3) { 115 | return HEAPF64[address / 8]; 116 | } else if (kind === 4) { 117 | var pointer = HEAPU32[address / 4]; 118 | var length = HEAPU32[(address + 4) / 4]; 119 | return Module.STDWEB_PRIVATE.to_js_string(pointer, length); 120 | } else if (kind === 5) { 121 | return false; 122 | } else if (kind === 6) { 123 | return true; 124 | } else if (kind === 7) { 125 | var pointer = Module.STDWEB_PRIVATE.arena + HEAPU32[address / 4]; 126 | var length = HEAPU32[(address + 4) / 4]; 127 | var output = []; 128 | for (var i = 0; i < length; ++i) { 129 | output.push(Module.STDWEB_PRIVATE.to_js(pointer + i * 16)); 130 | } 131 | return output; 132 | } else if (kind === 8) { 133 | var arena = Module.STDWEB_PRIVATE.arena; 134 | var value_array_pointer = arena + HEAPU32[address / 4]; 135 | var length = HEAPU32[(address + 4) / 4]; 136 | var key_array_pointer = arena + HEAPU32[(address + 8) / 4]; 137 | var output = {}; 138 | for (var i = 0; i < length; ++i) { 139 | var key_pointer = HEAPU32[(key_array_pointer + i * 8) / 4]; 140 | var key_length = HEAPU32[(key_array_pointer + 4 + i * 8) / 4]; 141 | var key = Module.STDWEB_PRIVATE.to_js_string(key_pointer, key_length); 142 | var value = Module.STDWEB_PRIVATE.to_js(value_array_pointer + i * 16); 143 | output[key] = value; 144 | } 145 | return output; 146 | } else if (kind === 9) { 147 | return Module.STDWEB_PRIVATE.acquire_js_reference(HEAP32[address / 4]); 148 | } else if (kind === 10 || kind === 12 || kind === 13) { 149 | var adapter_pointer = HEAPU32[address / 4]; 150 | var pointer = HEAPU32[(address + 4) / 4]; 151 | var deallocator_pointer = HEAPU32[(address + 8) / 4]; 152 | var num_ongoing_calls = 0; 153 | var drop_queued = false; 154 | var output = function () { 155 | if (pointer === 0 || drop_queued === true) { 156 | if (kind === 10) { 157 | throw new ReferenceError("Already dropped Rust function called!"); 158 | } else if (kind === 12) { 159 | throw new ReferenceError("Already dropped FnMut function called!"); 160 | } else { 161 | throw new ReferenceError("Already called or dropped FnOnce function called!"); 162 | } 163 | } 164 | 165 | var function_pointer = pointer; 166 | if (kind === 13) { 167 | output.drop = Module.STDWEB_PRIVATE.noop; 168 | pointer = 0; 169 | } 170 | 171 | if (num_ongoing_calls !== 0) { 172 | if (kind === 12 || kind === 13) { 173 | throw new ReferenceError("FnMut function called multiple times concurrently!"); 174 | } 175 | } 176 | 177 | var args = Module.STDWEB_PRIVATE.alloc(16); 178 | Module.STDWEB_PRIVATE.serialize_array(args, arguments); 179 | 180 | try { 181 | num_ongoing_calls += 1; 182 | Module.STDWEB_PRIVATE.dyncall("vii", adapter_pointer, [function_pointer, args]); 183 | var result = Module.STDWEB_PRIVATE.tmp; 184 | Module.STDWEB_PRIVATE.tmp = null; 185 | } finally { 186 | num_ongoing_calls -= 1; 187 | } 188 | 189 | if (drop_queued === true && num_ongoing_calls === 0) { 190 | output.drop(); 191 | } 192 | 193 | return result; 194 | }; 195 | 196 | output.drop = function () { 197 | if (num_ongoing_calls !== 0) { 198 | drop_queued = true; 199 | return; 200 | } 201 | 202 | output.drop = Module.STDWEB_PRIVATE.noop; 203 | var function_pointer = pointer; 204 | pointer = 0; 205 | 206 | if (function_pointer != 0) { 207 | Module.STDWEB_PRIVATE.dyncall("vi", deallocator_pointer, [function_pointer]); 208 | } 209 | }; 210 | 211 | return output; 212 | } else if (kind === 14) { 213 | var pointer = HEAPU32[address / 4]; 214 | var length = HEAPU32[(address + 4) / 4]; 215 | var array_kind = HEAPU32[(address + 8) / 4]; 216 | var pointer_end = pointer + length; 217 | 218 | switch (array_kind) { 219 | case 0: 220 | return HEAPU8.subarray(pointer, pointer_end); 221 | case 1: 222 | return HEAP8.subarray(pointer, pointer_end); 223 | case 2: 224 | return HEAPU16.subarray(pointer, pointer_end); 225 | case 3: 226 | return HEAP16.subarray(pointer, pointer_end); 227 | case 4: 228 | return HEAPU32.subarray(pointer, pointer_end); 229 | case 5: 230 | return HEAP32.subarray(pointer, pointer_end); 231 | case 6: 232 | return HEAPF32.subarray(pointer, pointer_end); 233 | case 7: 234 | return HEAPF64.subarray(pointer, pointer_end); 235 | } 236 | } else if (kind === 15) { 237 | return Module.STDWEB_PRIVATE.get_raw_value(HEAPU32[address / 4]); 238 | } 239 | }; 240 | 241 | Module.STDWEB_PRIVATE.serialize_object = function serialize_object(address, value) { 242 | var keys = Object.keys(value); 243 | var length = keys.length; 244 | var key_array_pointer = Module.STDWEB_PRIVATE.alloc(length * 8); 245 | var value_array_pointer = Module.STDWEB_PRIVATE.alloc(length * 16); 246 | HEAPU8[address + 12] = 8; 247 | HEAPU32[address / 4] = value_array_pointer; 248 | HEAPU32[(address + 4) / 4] = length; 249 | HEAPU32[(address + 8) / 4] = key_array_pointer; 250 | for (var i = 0; i < length; ++i) { 251 | var key = keys[i]; 252 | var key_length = Module.STDWEB_PRIVATE.utf8_len(key); 253 | var key_pointer = Module.STDWEB_PRIVATE.alloc(key_length); 254 | Module.STDWEB_PRIVATE.to_utf8(key, key_pointer); 255 | 256 | var key_address = key_array_pointer + i * 8; 257 | HEAPU32[key_address / 4] = key_pointer; 258 | HEAPU32[(key_address + 4) / 4] = key_length; 259 | 260 | Module.STDWEB_PRIVATE.from_js(value_array_pointer + i * 16, value[key]); 261 | } 262 | }; 263 | 264 | Module.STDWEB_PRIVATE.serialize_array = function serialize_array(address, value) { 265 | var length = value.length; 266 | var pointer = Module.STDWEB_PRIVATE.alloc(length * 16); 267 | HEAPU8[address + 12] = 7; 268 | HEAPU32[address / 4] = pointer; 269 | HEAPU32[(address + 4) / 4] = length; 270 | for (var i = 0; i < length; ++i) { 271 | Module.STDWEB_PRIVATE.from_js(pointer + i * 16, value[i]); 272 | } 273 | }; 274 | 275 | Module.STDWEB_PRIVATE.from_js = function from_js(address, value) { 276 | var kind = Object.prototype.toString.call(value); 277 | if (kind === "[object String]") { 278 | var length = Module.STDWEB_PRIVATE.utf8_len(value); 279 | var pointer = 0; 280 | if (length > 0) { 281 | pointer = Module.STDWEB_PRIVATE.alloc(length); 282 | Module.STDWEB_PRIVATE.to_utf8(value, pointer); 283 | } 284 | HEAPU8[address + 12] = 4; 285 | HEAPU32[address / 4] = pointer; 286 | HEAPU32[(address + 4) / 4] = length; 287 | } else if (kind === "[object Number]") { 288 | if (value === (value | 0)) { 289 | HEAPU8[address + 12] = 2; 290 | HEAP32[address / 4] = value; 291 | } else { 292 | HEAPU8[address + 12] = 3; 293 | HEAPF64[address / 8] = value; 294 | } 295 | } else if (value === null) { 296 | HEAPU8[address + 12] = 1; 297 | } else if (value === undefined) { 298 | HEAPU8[address + 12] = 0; 299 | } else if (value === false) { 300 | HEAPU8[address + 12] = 5; 301 | } else if (value === true) { 302 | HEAPU8[address + 12] = 6; 303 | } else if (kind === "[object Symbol]") { 304 | var id = Module.STDWEB_PRIVATE.register_raw_value(value); 305 | HEAPU8[address + 12] = 15; 306 | HEAP32[address / 4] = id; 307 | } else { 308 | var refid = Module.STDWEB_PRIVATE.acquire_rust_reference(value); 309 | HEAPU8[address + 12] = 9; 310 | HEAP32[address / 4] = refid; 311 | } 312 | }; 313 | 314 | // This is ported from Rust's stdlib; it's faster than 315 | // the string conversion from Emscripten. 316 | Module.STDWEB_PRIVATE.to_js_string = function to_js_string(index, length) { 317 | index = index | 0; 318 | length = length | 0; 319 | var end = (index | 0) + (length | 0); 320 | var output = ""; 321 | while (index < end) { 322 | var x = HEAPU8[index++]; 323 | if (x < 128) { 324 | output += String.fromCharCode(x); 325 | continue; 326 | } 327 | var init = (x & (0x7F >> 2)); 328 | var y = 0; 329 | if (index < end) { 330 | y = HEAPU8[index++]; 331 | } 332 | var ch = (init << 6) | (y & 63); 333 | if (x >= 0xE0) { 334 | var z = 0; 335 | if (index < end) { 336 | z = HEAPU8[index++]; 337 | } 338 | var y_z = ((y & 63) << 6) | (z & 63); 339 | ch = init << 12 | y_z; 340 | if (x >= 0xF0) { 341 | var w = 0; 342 | if (index < end) { 343 | w = HEAPU8[index++]; 344 | } 345 | ch = (init & 7) << 18 | ((y_z << 6) | (w & 63)); 346 | 347 | output += String.fromCharCode(0xD7C0 + (ch >> 10)); 348 | ch = 0xDC00 + (ch & 0x3FF); 349 | } 350 | } 351 | output += String.fromCharCode(ch); 352 | continue; 353 | } 354 | return output; 355 | }; 356 | 357 | Module.STDWEB_PRIVATE.id_to_ref_map = {}; 358 | Module.STDWEB_PRIVATE.id_to_refcount_map = {}; 359 | Module.STDWEB_PRIVATE.ref_to_id_map = new WeakMap(); 360 | // Not all types can be stored in a WeakMap 361 | Module.STDWEB_PRIVATE.ref_to_id_map_fallback = new Map(); 362 | Module.STDWEB_PRIVATE.last_refid = 1; 363 | 364 | Module.STDWEB_PRIVATE.id_to_raw_value_map = {}; 365 | Module.STDWEB_PRIVATE.last_raw_value_id = 1; 366 | 367 | Module.STDWEB_PRIVATE.acquire_rust_reference = function (reference) { 368 | if (reference === undefined || reference === null) { 369 | return 0; 370 | } 371 | 372 | var id_to_refcount_map = Module.STDWEB_PRIVATE.id_to_refcount_map; 373 | var id_to_ref_map = Module.STDWEB_PRIVATE.id_to_ref_map; 374 | var ref_to_id_map = Module.STDWEB_PRIVATE.ref_to_id_map; 375 | var ref_to_id_map_fallback = Module.STDWEB_PRIVATE.ref_to_id_map_fallback; 376 | 377 | var refid = ref_to_id_map.get(reference); 378 | if (refid === undefined) { 379 | refid = ref_to_id_map_fallback.get(reference); 380 | } 381 | if (refid === undefined) { 382 | refid = Module.STDWEB_PRIVATE.last_refid++; 383 | try { 384 | ref_to_id_map.set(reference, refid); 385 | } catch (e) { 386 | ref_to_id_map_fallback.set(reference, refid); 387 | } 388 | } 389 | 390 | if (refid in id_to_ref_map) { 391 | id_to_refcount_map[refid]++; 392 | } else { 393 | id_to_ref_map[refid] = reference; 394 | id_to_refcount_map[refid] = 1; 395 | } 396 | 397 | return refid; 398 | }; 399 | 400 | Module.STDWEB_PRIVATE.acquire_js_reference = function (refid) { 401 | return Module.STDWEB_PRIVATE.id_to_ref_map[refid]; 402 | }; 403 | 404 | Module.STDWEB_PRIVATE.increment_refcount = function (refid) { 405 | Module.STDWEB_PRIVATE.id_to_refcount_map[refid]++; 406 | }; 407 | 408 | Module.STDWEB_PRIVATE.decrement_refcount = function (refid) { 409 | var id_to_refcount_map = Module.STDWEB_PRIVATE.id_to_refcount_map; 410 | if (0 == --id_to_refcount_map[refid]) { 411 | var id_to_ref_map = Module.STDWEB_PRIVATE.id_to_ref_map; 412 | var ref_to_id_map_fallback = Module.STDWEB_PRIVATE.ref_to_id_map_fallback; 413 | var reference = id_to_ref_map[refid]; 414 | delete id_to_ref_map[refid]; 415 | delete id_to_refcount_map[refid]; 416 | ref_to_id_map_fallback.delete(reference); 417 | } 418 | }; 419 | 420 | Module.STDWEB_PRIVATE.register_raw_value = function (value) { 421 | var id = Module.STDWEB_PRIVATE.last_raw_value_id++; 422 | Module.STDWEB_PRIVATE.id_to_raw_value_map[id] = value; 423 | return id; 424 | }; 425 | 426 | Module.STDWEB_PRIVATE.unregister_raw_value = function (id) { 427 | delete Module.STDWEB_PRIVATE.id_to_raw_value_map[id]; 428 | }; 429 | 430 | Module.STDWEB_PRIVATE.get_raw_value = function (id) { 431 | return Module.STDWEB_PRIVATE.id_to_raw_value_map[id]; 432 | }; 433 | 434 | Module.STDWEB_PRIVATE.alloc = function alloc(size) { 435 | return Module.web_malloc(size); 436 | }; 437 | 438 | Module.STDWEB_PRIVATE.dyncall = function (signature, ptr, args) { 439 | return Module.web_table.get(ptr).apply(null, args); 440 | }; 441 | 442 | // This is based on code from Emscripten's preamble.js. 443 | Module.STDWEB_PRIVATE.utf8_len = function utf8_len(str) { 444 | var len = 0; 445 | for (var i = 0; i < str.length; ++i) { 446 | // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! So decode UTF16->UTF32->UTF8. 447 | // See http://unicode.org/faq/utf_bom.html#utf16-3 448 | var u = str.charCodeAt(i); // possibly a lead surrogate 449 | if (u >= 0xD800 && u <= 0xDFFF) { 450 | u = 0x10000 + ((u & 0x3FF) << 10) | (str.charCodeAt(++i) & 0x3FF); 451 | } 452 | 453 | if (u <= 0x7F) { 454 | ++len; 455 | } else if (u <= 0x7FF) { 456 | len += 2; 457 | } else if (u <= 0xFFFF) { 458 | len += 3; 459 | } else if (u <= 0x1FFFFF) { 460 | len += 4; 461 | } else if (u <= 0x3FFFFFF) { 462 | len += 5; 463 | } else { 464 | len += 6; 465 | } 466 | } 467 | return len; 468 | }; 469 | 470 | Module.STDWEB_PRIVATE.prepare_any_arg = function (value) { 471 | var arg = Module.STDWEB_PRIVATE.alloc(16); 472 | Module.STDWEB_PRIVATE.from_js(arg, value); 473 | return arg; 474 | }; 475 | 476 | Module.STDWEB_PRIVATE.acquire_tmp = function (dummy) { 477 | var value = Module.STDWEB_PRIVATE.tmp; 478 | Module.STDWEB_PRIVATE.tmp = null; 479 | return value; 480 | }; 481 | 482 | 483 | 484 | var HEAP8 = null; 485 | var HEAP16 = null; 486 | var HEAP32 = null; 487 | var HEAPU8 = null; 488 | var HEAPU16 = null; 489 | var HEAPU32 = null; 490 | var HEAPF32 = null; 491 | var HEAPF64 = null; 492 | 493 | Object.defineProperty(Module, 'exports', { value: {} }); 494 | 495 | function __web_on_grow() { 496 | var buffer = Module.instance.exports.memory.buffer; 497 | HEAP8 = new Int8Array(buffer); 498 | HEAP16 = new Int16Array(buffer); 499 | HEAP32 = new Int32Array(buffer); 500 | HEAPU8 = new Uint8Array(buffer); 501 | HEAPU16 = new Uint16Array(buffer); 502 | HEAPU32 = new Uint32Array(buffer); 503 | HEAPF32 = new Float32Array(buffer); 504 | HEAPF64 = new Float64Array(buffer); 505 | } 506 | 507 | return { 508 | imports: { 509 | env: { 510 | "__extjs_76a96b3bedea65a1b66a69d567c207919128318e": function ($0, $1) { 511 | $1 = Module.STDWEB_PRIVATE.to_js($1); Module.STDWEB_PRIVATE.from_js($0, (function () { 512 | wx.showModal({ 513 | title: '提示', 514 | content: ($1), 515 | success: function (res) { 516 | if (res.confirm) { 517 | console.log('用户点击确定') 518 | } else if (res.cancel) { 519 | console.log('用户点击取消') 520 | } 521 | } 522 | }); 523 | })()); 524 | }, 525 | "__extjs_80d6d56760c65e49b7be8b6b01c1ea861b046bf0": function ($0) { 526 | Module.STDWEB_PRIVATE.decrement_refcount($0); 527 | }, 528 | "__extjs_97495987af1720d8a9a923fa4683a7b683e3acd6": function ($0, $1) { 529 | console.error('Panic error message:', Module.STDWEB_PRIVATE.to_js_string($0, $1)); 530 | }, 531 | "__extjs_dc2fd915bd92f9e9c6a3bd15174f1414eee3dbaf": function () { 532 | console.error('Encountered a panic!'); 533 | }, 534 | "__extjs_72fc447820458c720c68d0d8e078ede631edd723": function ($0, $1, $2) { 535 | console.error('Panic location:', Module.STDWEB_PRIVATE.to_js_string($0, $1) + ':' + $2); 536 | }, 537 | "__extjs_db0226ae1bbecd407e9880ee28ddc70fc3322d9c": function ($0) { 538 | $0 = Module.STDWEB_PRIVATE.to_js($0); Module.STDWEB_PRIVATE.unregister_raw_value(($0)); 539 | }, 540 | "__web_on_grow": __web_on_grow 541 | } 542 | }, 543 | initialize: function (instance) { 544 | Object.defineProperty(Module, 'instance', { value: instance }); 545 | Object.defineProperty(Module, 'web_malloc', { value: Module.instance.exports.__web_malloc }); 546 | Object.defineProperty(Module, 'web_free', { value: Module.instance.exports.__web_free }); 547 | Object.defineProperty(Module, 'web_table', { value: Module.instance.exports.__web_table }); 548 | 549 | 550 | __web_on_grow(); 551 | Module.instance.exports.main(); 552 | 553 | return Module.exports; 554 | } 555 | }; 556 | } 557 | )); 558 | })); 559 | -------------------------------------------------------------------------------- /miniprogram/load.js: -------------------------------------------------------------------------------- 1 | 2 | var Module = {}; 3 | var __cargo_web = {}; 4 | Object.defineProperty(Module, 'canvas', { 5 | get: function () { 6 | return null; 7 | } 8 | }); 9 | 10 | if (typeof Rust === "undefined") { 11 | var Rust = {}; 12 | } 13 | 14 | (function (root, factory) { 15 | if (typeof define === "function" && define.amd) { 16 | define([], factory); 17 | } else if (typeof module === "object" && module.exports) { 18 | module.exports = factory(); 19 | } else { 20 | Rust.demo = factory(); 21 | } 22 | }(this, function () { 23 | return (function (module_factory) { 24 | var instance = module_factory(); 25 | 26 | let fsm = wx.getFileSystemManager(); 27 | let file = fsm.readFile({ 28 | filePath: "/static/demo.wasm", 29 | success: function (res) { 30 | var wasm_instance = WebAssembly.compile(res.data) 31 | .then(function (mod) { return WebAssembly.instantiate(mod, instance.imports) }); 32 | 33 | return wasm_instance 34 | .then(function (wasm_instance) { 35 | var exports = instance.initialize(wasm_instance); 36 | console.log("Finished loading Rust wasm module 'demo'"); 37 | return exports; 38 | }) 39 | .catch(function (error) { 40 | console.log("Error loading Rust wasm module 'demo':", error); 41 | throw error; 42 | }); 43 | } 44 | }); 45 | }(function () { 46 | var Module = {}; 47 | 48 | Module.STDWEB_PRIVATE = {}; 49 | 50 | // This is based on code from Emscripten's preamble.js. 51 | Module.STDWEB_PRIVATE.to_utf8 = function to_utf8(str, addr) { 52 | for (var i = 0; i < str.length; ++i) { 53 | // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! So decode UTF16->UTF32->UTF8. 54 | // See http://unicode.org/faq/utf_bom.html#utf16-3 55 | // For UTF8 byte structure, see http://en.wikipedia.org/wiki/UTF-8#Description and https://www.ietf.org/rfc/rfc2279.txt and https://tools.ietf.org/html/rfc3629 56 | var u = str.charCodeAt(i); // possibly a lead surrogate 57 | if (u >= 0xD800 && u <= 0xDFFF) { 58 | u = 0x10000 + ((u & 0x3FF) << 10) | (str.charCodeAt(++i) & 0x3FF); 59 | } 60 | 61 | if (u <= 0x7F) { 62 | HEAPU8[addr++] = u; 63 | } else if (u <= 0x7FF) { 64 | HEAPU8[addr++] = 0xC0 | (u >> 6); 65 | HEAPU8[addr++] = 0x80 | (u & 63); 66 | } else if (u <= 0xFFFF) { 67 | HEAPU8[addr++] = 0xE0 | (u >> 12); 68 | HEAPU8[addr++] = 0x80 | ((u >> 6) & 63); 69 | HEAPU8[addr++] = 0x80 | (u & 63); 70 | } else if (u <= 0x1FFFFF) { 71 | HEAPU8[addr++] = 0xF0 | (u >> 18); 72 | HEAPU8[addr++] = 0x80 | ((u >> 12) & 63); 73 | HEAPU8[addr++] = 0x80 | ((u >> 6) & 63); 74 | HEAPU8[addr++] = 0x80 | (u & 63); 75 | } else if (u <= 0x3FFFFFF) { 76 | HEAPU8[addr++] = 0xF8 | (u >> 24); 77 | HEAPU8[addr++] = 0x80 | ((u >> 18) & 63); 78 | HEAPU8[addr++] = 0x80 | ((u >> 12) & 63); 79 | HEAPU8[addr++] = 0x80 | ((u >> 6) & 63); 80 | HEAPU8[addr++] = 0x80 | (u & 63); 81 | } else { 82 | HEAPU8[addr++] = 0xFC | (u >> 30); 83 | HEAPU8[addr++] = 0x80 | ((u >> 24) & 63); 84 | HEAPU8[addr++] = 0x80 | ((u >> 18) & 63); 85 | HEAPU8[addr++] = 0x80 | ((u >> 12) & 63); 86 | HEAPU8[addr++] = 0x80 | ((u >> 6) & 63); 87 | HEAPU8[addr++] = 0x80 | (u & 63); 88 | } 89 | } 90 | }; 91 | 92 | Module.STDWEB_PRIVATE.noop = function () { }; 93 | Module.STDWEB_PRIVATE.to_js = function to_js(address) { 94 | var kind = HEAPU8[address + 12]; 95 | if (kind === 0) { 96 | return undefined; 97 | } else if (kind === 1) { 98 | return null; 99 | } else if (kind === 2) { 100 | return HEAP32[address / 4]; 101 | } else if (kind === 3) { 102 | return HEAPF64[address / 8]; 103 | } else if (kind === 4) { 104 | var pointer = HEAPU32[address / 4]; 105 | var length = HEAPU32[(address + 4) / 4]; 106 | return Module.STDWEB_PRIVATE.to_js_string(pointer, length); 107 | } else if (kind === 5) { 108 | return false; 109 | } else if (kind === 6) { 110 | return true; 111 | } else if (kind === 7) { 112 | var pointer = Module.STDWEB_PRIVATE.arena + HEAPU32[address / 4]; 113 | var length = HEAPU32[(address + 4) / 4]; 114 | var output = []; 115 | for (var i = 0; i < length; ++i) { 116 | output.push(Module.STDWEB_PRIVATE.to_js(pointer + i * 16)); 117 | } 118 | return output; 119 | } else if (kind === 8) { 120 | var arena = Module.STDWEB_PRIVATE.arena; 121 | var value_array_pointer = arena + HEAPU32[address / 4]; 122 | var length = HEAPU32[(address + 4) / 4]; 123 | var key_array_pointer = arena + HEAPU32[(address + 8) / 4]; 124 | var output = {}; 125 | for (var i = 0; i < length; ++i) { 126 | var key_pointer = HEAPU32[(key_array_pointer + i * 8) / 4]; 127 | var key_length = HEAPU32[(key_array_pointer + 4 + i * 8) / 4]; 128 | var key = Module.STDWEB_PRIVATE.to_js_string(key_pointer, key_length); 129 | var value = Module.STDWEB_PRIVATE.to_js(value_array_pointer + i * 16); 130 | output[key] = value; 131 | } 132 | return output; 133 | } else if (kind === 9) { 134 | return Module.STDWEB_PRIVATE.acquire_js_reference(HEAP32[address / 4]); 135 | } else if (kind === 10 || kind === 12 || kind === 13) { 136 | var adapter_pointer = HEAPU32[address / 4]; 137 | var pointer = HEAPU32[(address + 4) / 4]; 138 | var deallocator_pointer = HEAPU32[(address + 8) / 4]; 139 | var num_ongoing_calls = 0; 140 | var drop_queued = false; 141 | var output = function () { 142 | if (pointer === 0 || drop_queued === true) { 143 | if (kind === 10) { 144 | throw new ReferenceError("Already dropped Rust function called!"); 145 | } else if (kind === 12) { 146 | throw new ReferenceError("Already dropped FnMut function called!"); 147 | } else { 148 | throw new ReferenceError("Already called or dropped FnOnce function called!"); 149 | } 150 | } 151 | 152 | var function_pointer = pointer; 153 | if (kind === 13) { 154 | output.drop = Module.STDWEB_PRIVATE.noop; 155 | pointer = 0; 156 | } 157 | 158 | if (num_ongoing_calls !== 0) { 159 | if (kind === 12 || kind === 13) { 160 | throw new ReferenceError("FnMut function called multiple times concurrently!"); 161 | } 162 | } 163 | 164 | var args = Module.STDWEB_PRIVATE.alloc(16); 165 | Module.STDWEB_PRIVATE.serialize_array(args, arguments); 166 | 167 | try { 168 | num_ongoing_calls += 1; 169 | Module.STDWEB_PRIVATE.dyncall("vii", adapter_pointer, [function_pointer, args]); 170 | var result = Module.STDWEB_PRIVATE.tmp; 171 | Module.STDWEB_PRIVATE.tmp = null; 172 | } finally { 173 | num_ongoing_calls -= 1; 174 | } 175 | 176 | if (drop_queued === true && num_ongoing_calls === 0) { 177 | output.drop(); 178 | } 179 | 180 | return result; 181 | }; 182 | 183 | output.drop = function () { 184 | if (num_ongoing_calls !== 0) { 185 | drop_queued = true; 186 | return; 187 | } 188 | 189 | output.drop = Module.STDWEB_PRIVATE.noop; 190 | var function_pointer = pointer; 191 | pointer = 0; 192 | 193 | if (function_pointer != 0) { 194 | Module.STDWEB_PRIVATE.dyncall("vi", deallocator_pointer, [function_pointer]); 195 | } 196 | }; 197 | 198 | return output; 199 | } else if (kind === 14) { 200 | var pointer = HEAPU32[address / 4]; 201 | var length = HEAPU32[(address + 4) / 4]; 202 | var array_kind = HEAPU32[(address + 8) / 4]; 203 | var pointer_end = pointer + length; 204 | 205 | switch (array_kind) { 206 | case 0: 207 | return HEAPU8.subarray(pointer, pointer_end); 208 | case 1: 209 | return HEAP8.subarray(pointer, pointer_end); 210 | case 2: 211 | return HEAPU16.subarray(pointer, pointer_end); 212 | case 3: 213 | return HEAP16.subarray(pointer, pointer_end); 214 | case 4: 215 | return HEAPU32.subarray(pointer, pointer_end); 216 | case 5: 217 | return HEAP32.subarray(pointer, pointer_end); 218 | case 6: 219 | return HEAPF32.subarray(pointer, pointer_end); 220 | case 7: 221 | return HEAPF64.subarray(pointer, pointer_end); 222 | } 223 | } else if (kind === 15) { 224 | return Module.STDWEB_PRIVATE.get_raw_value(HEAPU32[address / 4]); 225 | } 226 | }; 227 | 228 | Module.STDWEB_PRIVATE.serialize_object = function serialize_object(address, value) { 229 | var keys = Object.keys(value); 230 | var length = keys.length; 231 | var key_array_pointer = Module.STDWEB_PRIVATE.alloc(length * 8); 232 | var value_array_pointer = Module.STDWEB_PRIVATE.alloc(length * 16); 233 | HEAPU8[address + 12] = 8; 234 | HEAPU32[address / 4] = value_array_pointer; 235 | HEAPU32[(address + 4) / 4] = length; 236 | HEAPU32[(address + 8) / 4] = key_array_pointer; 237 | for (var i = 0; i < length; ++i) { 238 | var key = keys[i]; 239 | var key_length = Module.STDWEB_PRIVATE.utf8_len(key); 240 | var key_pointer = Module.STDWEB_PRIVATE.alloc(key_length); 241 | Module.STDWEB_PRIVATE.to_utf8(key, key_pointer); 242 | 243 | var key_address = key_array_pointer + i * 8; 244 | HEAPU32[key_address / 4] = key_pointer; 245 | HEAPU32[(key_address + 4) / 4] = key_length; 246 | 247 | Module.STDWEB_PRIVATE.from_js(value_array_pointer + i * 16, value[key]); 248 | } 249 | }; 250 | 251 | Module.STDWEB_PRIVATE.serialize_array = function serialize_array(address, value) { 252 | var length = value.length; 253 | var pointer = Module.STDWEB_PRIVATE.alloc(length * 16); 254 | HEAPU8[address + 12] = 7; 255 | HEAPU32[address / 4] = pointer; 256 | HEAPU32[(address + 4) / 4] = length; 257 | for (var i = 0; i < length; ++i) { 258 | Module.STDWEB_PRIVATE.from_js(pointer + i * 16, value[i]); 259 | } 260 | }; 261 | 262 | Module.STDWEB_PRIVATE.from_js = function from_js(address, value) { 263 | var kind = Object.prototype.toString.call(value); 264 | if (kind === "[object String]") { 265 | var length = Module.STDWEB_PRIVATE.utf8_len(value); 266 | var pointer = 0; 267 | if (length > 0) { 268 | pointer = Module.STDWEB_PRIVATE.alloc(length); 269 | Module.STDWEB_PRIVATE.to_utf8(value, pointer); 270 | } 271 | HEAPU8[address + 12] = 4; 272 | HEAPU32[address / 4] = pointer; 273 | HEAPU32[(address + 4) / 4] = length; 274 | } else if (kind === "[object Number]") { 275 | if (value === (value | 0)) { 276 | HEAPU8[address + 12] = 2; 277 | HEAP32[address / 4] = value; 278 | } else { 279 | HEAPU8[address + 12] = 3; 280 | HEAPF64[address / 8] = value; 281 | } 282 | } else if (value === null) { 283 | HEAPU8[address + 12] = 1; 284 | } else if (value === undefined) { 285 | HEAPU8[address + 12] = 0; 286 | } else if (value === false) { 287 | HEAPU8[address + 12] = 5; 288 | } else if (value === true) { 289 | HEAPU8[address + 12] = 6; 290 | } else if (kind === "[object Symbol]") { 291 | var id = Module.STDWEB_PRIVATE.register_raw_value(value); 292 | HEAPU8[address + 12] = 15; 293 | HEAP32[address / 4] = id; 294 | } else { 295 | var refid = Module.STDWEB_PRIVATE.acquire_rust_reference(value); 296 | HEAPU8[address + 12] = 9; 297 | HEAP32[address / 4] = refid; 298 | } 299 | }; 300 | 301 | // This is ported from Rust's stdlib; it's faster than 302 | // the string conversion from Emscripten. 303 | Module.STDWEB_PRIVATE.to_js_string = function to_js_string(index, length) { 304 | index = index | 0; 305 | length = length | 0; 306 | var end = (index | 0) + (length | 0); 307 | var output = ""; 308 | while (index < end) { 309 | var x = HEAPU8[index++]; 310 | if (x < 128) { 311 | output += String.fromCharCode(x); 312 | continue; 313 | } 314 | var init = (x & (0x7F >> 2)); 315 | var y = 0; 316 | if (index < end) { 317 | y = HEAPU8[index++]; 318 | } 319 | var ch = (init << 6) | (y & 63); 320 | if (x >= 0xE0) { 321 | var z = 0; 322 | if (index < end) { 323 | z = HEAPU8[index++]; 324 | } 325 | var y_z = ((y & 63) << 6) | (z & 63); 326 | ch = init << 12 | y_z; 327 | if (x >= 0xF0) { 328 | var w = 0; 329 | if (index < end) { 330 | w = HEAPU8[index++]; 331 | } 332 | ch = (init & 7) << 18 | ((y_z << 6) | (w & 63)); 333 | 334 | output += String.fromCharCode(0xD7C0 + (ch >> 10)); 335 | ch = 0xDC00 + (ch & 0x3FF); 336 | } 337 | } 338 | output += String.fromCharCode(ch); 339 | continue; 340 | } 341 | return output; 342 | }; 343 | 344 | Module.STDWEB_PRIVATE.id_to_ref_map = {}; 345 | Module.STDWEB_PRIVATE.id_to_refcount_map = {}; 346 | Module.STDWEB_PRIVATE.ref_to_id_map = new WeakMap(); 347 | // Not all types can be stored in a WeakMap 348 | Module.STDWEB_PRIVATE.ref_to_id_map_fallback = new Map(); 349 | Module.STDWEB_PRIVATE.last_refid = 1; 350 | 351 | Module.STDWEB_PRIVATE.id_to_raw_value_map = {}; 352 | Module.STDWEB_PRIVATE.last_raw_value_id = 1; 353 | 354 | Module.STDWEB_PRIVATE.acquire_rust_reference = function (reference) { 355 | if (reference === undefined || reference === null) { 356 | return 0; 357 | } 358 | 359 | var id_to_refcount_map = Module.STDWEB_PRIVATE.id_to_refcount_map; 360 | var id_to_ref_map = Module.STDWEB_PRIVATE.id_to_ref_map; 361 | var ref_to_id_map = Module.STDWEB_PRIVATE.ref_to_id_map; 362 | var ref_to_id_map_fallback = Module.STDWEB_PRIVATE.ref_to_id_map_fallback; 363 | 364 | var refid = ref_to_id_map.get(reference); 365 | if (refid === undefined) { 366 | refid = ref_to_id_map_fallback.get(reference); 367 | } 368 | if (refid === undefined) { 369 | refid = Module.STDWEB_PRIVATE.last_refid++; 370 | try { 371 | ref_to_id_map.set(reference, refid); 372 | } catch (e) { 373 | ref_to_id_map_fallback.set(reference, refid); 374 | } 375 | } 376 | 377 | if (refid in id_to_ref_map) { 378 | id_to_refcount_map[refid]++; 379 | } else { 380 | id_to_ref_map[refid] = reference; 381 | id_to_refcount_map[refid] = 1; 382 | } 383 | 384 | return refid; 385 | }; 386 | 387 | Module.STDWEB_PRIVATE.acquire_js_reference = function (refid) { 388 | return Module.STDWEB_PRIVATE.id_to_ref_map[refid]; 389 | }; 390 | 391 | Module.STDWEB_PRIVATE.increment_refcount = function (refid) { 392 | Module.STDWEB_PRIVATE.id_to_refcount_map[refid]++; 393 | }; 394 | 395 | Module.STDWEB_PRIVATE.decrement_refcount = function (refid) { 396 | var id_to_refcount_map = Module.STDWEB_PRIVATE.id_to_refcount_map; 397 | if (0 == --id_to_refcount_map[refid]) { 398 | var id_to_ref_map = Module.STDWEB_PRIVATE.id_to_ref_map; 399 | var ref_to_id_map_fallback = Module.STDWEB_PRIVATE.ref_to_id_map_fallback; 400 | var reference = id_to_ref_map[refid]; 401 | delete id_to_ref_map[refid]; 402 | delete id_to_refcount_map[refid]; 403 | ref_to_id_map_fallback.delete(reference); 404 | } 405 | }; 406 | 407 | Module.STDWEB_PRIVATE.register_raw_value = function (value) { 408 | var id = Module.STDWEB_PRIVATE.last_raw_value_id++; 409 | Module.STDWEB_PRIVATE.id_to_raw_value_map[id] = value; 410 | return id; 411 | }; 412 | 413 | Module.STDWEB_PRIVATE.unregister_raw_value = function (id) { 414 | delete Module.STDWEB_PRIVATE.id_to_raw_value_map[id]; 415 | }; 416 | 417 | Module.STDWEB_PRIVATE.get_raw_value = function (id) { 418 | return Module.STDWEB_PRIVATE.id_to_raw_value_map[id]; 419 | }; 420 | 421 | Module.STDWEB_PRIVATE.alloc = function alloc(size) { 422 | return Module.web_malloc(size); 423 | }; 424 | 425 | Module.STDWEB_PRIVATE.dyncall = function (signature, ptr, args) { 426 | return Module.web_table.get(ptr).apply(null, args); 427 | }; 428 | 429 | // This is based on code from Emscripten's preamble.js. 430 | Module.STDWEB_PRIVATE.utf8_len = function utf8_len(str) { 431 | var len = 0; 432 | for (var i = 0; i < str.length; ++i) { 433 | // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! So decode UTF16->UTF32->UTF8. 434 | // See http://unicode.org/faq/utf_bom.html#utf16-3 435 | var u = str.charCodeAt(i); // possibly a lead surrogate 436 | if (u >= 0xD800 && u <= 0xDFFF) { 437 | u = 0x10000 + ((u & 0x3FF) << 10) | (str.charCodeAt(++i) & 0x3FF); 438 | } 439 | 440 | if (u <= 0x7F) { 441 | ++len; 442 | } else if (u <= 0x7FF) { 443 | len += 2; 444 | } else if (u <= 0xFFFF) { 445 | len += 3; 446 | } else if (u <= 0x1FFFFF) { 447 | len += 4; 448 | } else if (u <= 0x3FFFFFF) { 449 | len += 5; 450 | } else { 451 | len += 6; 452 | } 453 | } 454 | return len; 455 | }; 456 | 457 | Module.STDWEB_PRIVATE.prepare_any_arg = function (value) { 458 | var arg = Module.STDWEB_PRIVATE.alloc(16); 459 | Module.STDWEB_PRIVATE.from_js(arg, value); 460 | return arg; 461 | }; 462 | 463 | Module.STDWEB_PRIVATE.acquire_tmp = function (dummy) { 464 | var value = Module.STDWEB_PRIVATE.tmp; 465 | Module.STDWEB_PRIVATE.tmp = null; 466 | return value; 467 | }; 468 | 469 | 470 | 471 | var HEAP8 = null; 472 | var HEAP16 = null; 473 | var HEAP32 = null; 474 | var HEAPU8 = null; 475 | var HEAPU16 = null; 476 | var HEAPU32 = null; 477 | var HEAPF32 = null; 478 | var HEAPF64 = null; 479 | 480 | Object.defineProperty(Module, 'exports', { value: {} }); 481 | 482 | function __web_on_grow() { 483 | var buffer = Module.instance.exports.memory.buffer; 484 | HEAP8 = new Int8Array(buffer); 485 | HEAP16 = new Int16Array(buffer); 486 | HEAP32 = new Int32Array(buffer); 487 | HEAPU8 = new Uint8Array(buffer); 488 | HEAPU16 = new Uint16Array(buffer); 489 | HEAPU32 = new Uint32Array(buffer); 490 | HEAPF32 = new Float32Array(buffer); 491 | HEAPF64 = new Float64Array(buffer); 492 | } 493 | 494 | return { 495 | imports: { 496 | env: { 497 | "__extjs_80d6d56760c65e49b7be8b6b01c1ea861b046bf0": function ($0) { 498 | Module.STDWEB_PRIVATE.decrement_refcount($0); 499 | }, 500 | "__extjs_72fc447820458c720c68d0d8e078ede631edd723": function ($0, $1, $2) { 501 | console.error('Panic location:', Module.STDWEB_PRIVATE.to_js_string($0, $1) + ':' + $2); 502 | }, 503 | "__extjs_97495987af1720d8a9a923fa4683a7b683e3acd6": function ($0, $1) { 504 | console.error('Panic error message:', Module.STDWEB_PRIVATE.to_js_string($0, $1)); 505 | }, 506 | "__extjs_76a96b3bedea65a1b66a69d567c207919128318e": function ($0, $1) { 507 | $1 = Module.STDWEB_PRIVATE.to_js($1); Module.STDWEB_PRIVATE.from_js($0, (function () { 508 | wx.showModal({ 509 | title: '提示', 510 | content: ($1), 511 | success: function (res) { 512 | console.log(res) 513 | if (res.confirm) { 514 | console.log('用户点击了确定') 515 | } else { 516 | console.log('用户点击了取消') 517 | } 518 | } 519 | }); 520 | //alert(($1)); 521 | })()); 522 | }, 523 | "__extjs_db0226ae1bbecd407e9880ee28ddc70fc3322d9c": function ($0) { 524 | $0 = Module.STDWEB_PRIVATE.to_js($0); Module.STDWEB_PRIVATE.unregister_raw_value(($0)); 525 | }, 526 | "__extjs_dc2fd915bd92f9e9c6a3bd15174f1414eee3dbaf": function () { 527 | console.error('Encountered a panic!'); 528 | }, 529 | "__web_on_grow": __web_on_grow 530 | } 531 | }, 532 | initialize: function (instance) { 533 | Object.defineProperty(Module, 'instance', { value: instance }); 534 | Object.defineProperty(Module, 'web_malloc', { value: Module.instance.exports.__web_malloc }); 535 | Object.defineProperty(Module, 'web_free', { value: Module.instance.exports.__web_free }); 536 | Object.defineProperty(Module, 'web_table', { value: Module.instance.exports.__web_table }); 537 | 538 | 539 | __web_on_grow(); 540 | Module.instance.exports.main(); 541 | 542 | return Module.exports; 543 | } 544 | }; 545 | } 546 | )); 547 | })); -------------------------------------------------------------------------------- /miniprogram/pages/index/index.js: -------------------------------------------------------------------------------- 1 | //index.js 2 | const app = getApp() 3 | 4 | Page({ 5 | data: { 6 | avatarUrl: './user-unlogin.png', 7 | userInfo: {}, 8 | logged: false, 9 | takeSession: false, 10 | requestResult: '' 11 | }, 12 | 13 | onLoad: function() { 14 | if (!wx.cloud) { 15 | wx.redirectTo({ 16 | url: '../chooseLib/chooseLib', 17 | }) 18 | return 19 | } 20 | 21 | // 获取用户信息 22 | wx.getSetting({ 23 | success: res => { 24 | if (res.authSetting['scope.userInfo']) { 25 | // 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框 26 | wx.getUserInfo({ 27 | success: res => { 28 | this.setData({ 29 | avatarUrl: res.userInfo.avatarUrl, 30 | userInfo: res.userInfo 31 | }) 32 | } 33 | }) 34 | } 35 | } 36 | }) 37 | }, 38 | 39 | onGetUserInfo: function(e) { 40 | if (!this.logged && e.detail.userInfo) { 41 | this.setData({ 42 | logged: true, 43 | avatarUrl: e.detail.userInfo.avatarUrl, 44 | userInfo: e.detail.userInfo 45 | }) 46 | } 47 | }, 48 | 49 | onGetOpenid: function() { 50 | // 调用云函数 51 | wx.cloud.callFunction({ 52 | name: 'login', 53 | data: {}, 54 | success: res => { 55 | console.log('[云函数] [login] user openid: ', res.result.openid) 56 | app.globalData.openid = res.result.openid 57 | wx.navigateTo({ 58 | url: '../userConsole/userConsole', 59 | }) 60 | }, 61 | fail: err => { 62 | console.error('[云函数] [login] 调用失败', err) 63 | wx.navigateTo({ 64 | url: '../deployFunctions/deployFunctions', 65 | }) 66 | } 67 | }) 68 | }, 69 | 70 | // 上传图片 71 | doUpload: function () { 72 | // 选择图片 73 | wx.chooseImage({ 74 | count: 1, 75 | sizeType: ['compressed'], 76 | sourceType: ['album', 'camera'], 77 | success: function (res) { 78 | 79 | wx.showLoading({ 80 | title: '上传中', 81 | }) 82 | 83 | const filePath = res.tempFilePaths[0] 84 | 85 | // 上传图片 86 | const cloudPath = 'my-image' + filePath.match(/\.[^.]+?$/)[0] 87 | wx.cloud.uploadFile({ 88 | cloudPath, 89 | filePath, 90 | success: res => { 91 | console.log('[上传文件] 成功:', res) 92 | 93 | app.globalData.fileID = res.fileID 94 | app.globalData.cloudPath = cloudPath 95 | app.globalData.imagePath = filePath 96 | 97 | wx.navigateTo({ 98 | url: '../storageConsole/storageConsole' 99 | }) 100 | }, 101 | fail: e => { 102 | console.error('[上传文件] 失败:', e) 103 | wx.showToast({ 104 | icon: 'none', 105 | title: '上传失败', 106 | }) 107 | }, 108 | complete: () => { 109 | wx.hideLoading() 110 | } 111 | }) 112 | 113 | }, 114 | fail: e => { 115 | console.error(e) 116 | } 117 | }) 118 | }, 119 | 120 | }) 121 | -------------------------------------------------------------------------------- /miniprogram/pages/index/index.json: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /miniprogram/pages/index/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | Webassembly 3 | 4 | -------------------------------------------------------------------------------- /miniprogram/pages/index/index.wxss: -------------------------------------------------------------------------------- 1 | /**index.wxss**/ 2 | 3 | page { 4 | background: #f6f6f6; 5 | display: flex; 6 | flex-direction: column; 7 | justify-content: flex-start; 8 | } 9 | 10 | .userinfo, .uploader, .tunnel { 11 | margin-top: 40rpx; 12 | height: 140rpx; 13 | width: 100%; 14 | background: #fff; 15 | border: 1px solid rgba(0, 0, 0, 0.1); 16 | border-left: none; 17 | border-right: none; 18 | display: flex; 19 | flex-direction: row; 20 | align-items: center; 21 | transition: all 300ms ease; 22 | } 23 | 24 | .userinfo-avatar { 25 | width: 100rpx; 26 | height: 100rpx; 27 | margin: 20rpx; 28 | border-radius: 50%; 29 | background-size: cover; 30 | background-color: white; 31 | } 32 | 33 | .userinfo-avatar:after { 34 | border: none; 35 | } 36 | 37 | .userinfo-nickname { 38 | font-size: 32rpx; 39 | color: #007aff; 40 | background-color: white; 41 | background-size: cover; 42 | } 43 | 44 | .userinfo-nickname::after { 45 | border: none; 46 | } 47 | 48 | .uploader, .tunnel { 49 | height: auto; 50 | padding: 0 0 0 40rpx; 51 | flex-direction: column; 52 | align-items: flex-start; 53 | box-sizing: border-box; 54 | } 55 | 56 | .uploader-text, .tunnel-text { 57 | width: 100%; 58 | line-height: 52px; 59 | font-size: 34rpx; 60 | color: #007aff; 61 | } 62 | 63 | .uploader-container { 64 | width: 100%; 65 | height: 400rpx; 66 | padding: 20rpx 20rpx 20rpx 0; 67 | display: flex; 68 | align-content: center; 69 | justify-content: center; 70 | box-sizing: border-box; 71 | border-top: 1px solid rgba(0, 0, 0, 0.1); 72 | } 73 | 74 | .uploader-image { 75 | width: 100%; 76 | height: 360rpx; 77 | } 78 | 79 | .tunnel { 80 | padding: 0 0 0 40rpx; 81 | } 82 | 83 | .tunnel-text { 84 | position: relative; 85 | color: #222; 86 | display: flex; 87 | flex-direction: row; 88 | align-content: center; 89 | justify-content: space-between; 90 | box-sizing: border-box; 91 | border-top: 1px solid rgba(0, 0, 0, 0.1); 92 | } 93 | 94 | .tunnel-text:first-child { 95 | border-top: none; 96 | } 97 | 98 | .tunnel-switch { 99 | position: absolute; 100 | right: 20rpx; 101 | top: -2rpx; 102 | } 103 | 104 | .disable { 105 | color: #888; 106 | } 107 | 108 | .service { 109 | position: fixed; 110 | right: 40rpx; 111 | bottom: 40rpx; 112 | width: 140rpx; 113 | height: 140rpx; 114 | border-radius: 50%; 115 | background: linear-gradient(#007aff, #0063ce); 116 | box-shadow: 0 5px 10px rgba(0, 0, 0, 0.3); 117 | display: flex; 118 | align-content: center; 119 | justify-content: center; 120 | transition: all 300ms ease; 121 | } 122 | 123 | .service-button { 124 | position: absolute; 125 | top: 40rpx; 126 | } 127 | 128 | .service:active { 129 | box-shadow: none; 130 | } 131 | 132 | .request-text { 133 | padding: 20rpx 0; 134 | font-size: 24rpx; 135 | line-height: 36rpx; 136 | word-break: break-all; 137 | } 138 | -------------------------------------------------------------------------------- /miniprogram/pages/index/user-unlogin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/planet0104/miniprogram-rust-wasm/6ad99a41e262b9648a2f5bea74a35c10436d8945/miniprogram/pages/index/user-unlogin.png -------------------------------------------------------------------------------- /miniprogram/style/guide.wxss: -------------------------------------------------------------------------------- 1 | page { 2 | background: #f6f6f6; 3 | display: flex; 4 | flex-direction: column; 5 | justify-content: flex-start; 6 | } 7 | 8 | .list { 9 | margin-top: 40rpx; 10 | height: auto; 11 | width: 100%; 12 | background: #fff; 13 | padding: 0 40rpx; 14 | border: 1px solid rgba(0, 0, 0, 0.1); 15 | border-left: none; 16 | border-right: none; 17 | transition: all 300ms ease; 18 | display: flex; 19 | flex-direction: column; 20 | align-items: flex-start; 21 | box-sizing: border-box; 22 | } 23 | 24 | .list-item { 25 | width: 100%; 26 | padding: 0; 27 | line-height: 104rpx; 28 | font-size: 34rpx; 29 | color: #007aff; 30 | border-top: 1px solid rgba(0, 0, 0, 0.1); 31 | display: flex; 32 | flex-direction: row; 33 | align-content: center; 34 | justify-content: space-between; 35 | box-sizing: border-box; 36 | } 37 | 38 | .list-item:first-child { 39 | border-top: none; 40 | } 41 | 42 | .list-item image { 43 | max-width: 100%; 44 | max-height: 20vh; 45 | margin: 20rpx 0; 46 | } 47 | 48 | .request-text { 49 | color: #222; 50 | padding: 20rpx 0; 51 | font-size: 24rpx; 52 | line-height: 36rpx; 53 | word-break: break-all; 54 | } 55 | 56 | .guide { 57 | width: 100%; 58 | padding: 40rpx; 59 | box-sizing: border-box; 60 | display: flex; 61 | flex-direction: column; 62 | } 63 | 64 | .guide .headline { 65 | font-size: 34rpx; 66 | font-weight: bold; 67 | color: #555; 68 | line-height: 40rpx; 69 | } 70 | 71 | .guide .p { 72 | margin-top: 20rpx; 73 | font-size: 28rpx; 74 | line-height: 36rpx; 75 | color: #666; 76 | } 77 | 78 | .guide .code { 79 | margin-top: 20rpx; 80 | font-size: 28rpx; 81 | line-height: 36rpx; 82 | color: #666; 83 | background: white; 84 | white-space: pre; 85 | } 86 | 87 | .guide .code-dark { 88 | margin-top: 20rpx; 89 | background: rgba(0, 0, 0, 0.8); 90 | padding: 20rpx; 91 | font-size: 28rpx; 92 | line-height: 36rpx; 93 | border-radius: 6rpx; 94 | color: #fff; 95 | white-space: pre 96 | } 97 | 98 | .guide image { 99 | max-width: 100%; 100 | } 101 | 102 | .guide .image1 { 103 | margin-top: 20rpx; 104 | max-width: 100%; 105 | width: 356px; 106 | height: 47px; 107 | } 108 | 109 | .guide .image2 { 110 | margin-top: 20rpx; 111 | width: 264px; 112 | height: 100px; 113 | } 114 | 115 | .guide .flat-image { 116 | height: 100px; 117 | } 118 | 119 | .guide .code-image { 120 | max-width: 100%; 121 | } 122 | 123 | .guide .copyBtn { 124 | width: 180rpx; 125 | font-size: 20rpx; 126 | margin-top: 16rpx; 127 | margin-left: 0; 128 | } 129 | 130 | .guide .nav { 131 | margin-top: 50rpx; 132 | display: flex; 133 | flex-direction: row; 134 | align-content: space-between; 135 | } 136 | 137 | .guide .nav .prev { 138 | margin-left: unset; 139 | } 140 | 141 | .guide .nav .next { 142 | margin-right: unset; 143 | } 144 | 145 | -------------------------------------------------------------------------------- /project.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "项目配置文件", 3 | "packOptions": { 4 | "ignore": [] 5 | }, 6 | "setting": { 7 | "urlCheck": true, 8 | "es6": true, 9 | "postcss": true, 10 | "minified": true, 11 | "newFeature": true 12 | }, 13 | "compileType": "miniprogram", 14 | "libVersion": "2.2.5", 15 | "appid": "wx6c68f8045539a828", 16 | "projectname": "lazydict", 17 | "miniprogramRoot": "miniprogram/", 18 | "cloudfunctionRoot": "cloudfunctions/", 19 | "debugOptions": { 20 | "hidedInDevtools": [] 21 | }, 22 | "scripts": {}, 23 | "condition": { 24 | "search": { 25 | "current": -1, 26 | "list": [] 27 | }, 28 | "conversation": { 29 | "current": -1, 30 | "list": [] 31 | }, 32 | "plugin": { 33 | "current": -1, 34 | "list": [] 35 | }, 36 | "game": { 37 | "list": [] 38 | }, 39 | "miniprogram": { 40 | "current": -1, 41 | "list": [ 42 | { 43 | "id": -1, 44 | "name": "db guide", 45 | "pathName": "pages/databaseGuide/databaseGuide", 46 | "query": "" 47 | } 48 | ] 49 | } 50 | } 51 | } --------------------------------------------------------------------------------