use std::panic;
use webcore::ffi;
pub fn initialize() {
static mut INITIALIZED: bool = false;
unsafe {
if INITIALIZED {
return;
}
INITIALIZED = true;
}
js! { @(no_return)
Module.STDWEB = {};
};
#[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))]
js! { @(no_return)
Module.STDWEB.alloc = _malloc;
Module.STDWEB.dyncall = Runtime.dynCall;
Module.STDWEB.utf8_len = lengthBytesUTF8;
};
#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
js! { @(no_return)
Module.STDWEB.alloc = Module.web_malloc;
Module.STDWEB.dyncall = function( signature, ptr, args ) {
return Module.web_table.get( ptr ).apply( null, args );
};
Module.STDWEB.utf8_len = function utf8_len( str ) {
let len = 0;
for( let i = 0; i < str.length; ++i ) {
let u = str.charCodeAt( i ); if( u >= 0xD800 && u <= 0xDFFF ) {
u = 0x10000 + ((u & 0x3FF) << 10) | (str.charCodeAt( ++i ) & 0x3FF);
}
if( u <= 0x7F ) {
++len;
} else if( u <= 0x7FF ) {
len += 2;
} else if( u <= 0xFFFF ) {
len += 3;
} else if( u <= 0x1FFFFF ) {
len += 4;
} else if( u <= 0x3FFFFFF ) {
len += 5;
} else {
len += 6;
}
}
return len;
};
};
js! { @(no_return)
Module.STDWEB.to_utf8 = function to_utf8( str, addr ) {
for( var i = 0; i < str.length; ++i ) {
var u = str.charCodeAt( i ); if( u >= 0xD800 && u <= 0xDFFF ) {
u = 0x10000 + ((u & 0x3FF) << 10) | (str.charCodeAt( ++i ) & 0x3FF);
}
if( u <= 0x7F ) {
HEAPU8[ addr++ ] = u;
} else if( u <= 0x7FF ) {
HEAPU8[ addr++ ] = 0xC0 | (u >> 6);
HEAPU8[ addr++ ] = 0x80 | (u & 63);
} else if( u <= 0xFFFF ) {
HEAPU8[ addr++ ] = 0xE0 | (u >> 12);
HEAPU8[ addr++ ] = 0x80 | ((u >> 6) & 63);
HEAPU8[ addr++ ] = 0x80 | (u & 63);
} else if( u <= 0x1FFFFF ) {
HEAPU8[ addr++ ] = 0xF0 | (u >> 18);
HEAPU8[ addr++ ] = 0x80 | ((u >> 12) & 63);
HEAPU8[ addr++ ] = 0x80 | ((u >> 6) & 63);
HEAPU8[ addr++ ] = 0x80 | (u & 63);
} else if( u <= 0x3FFFFFF ) {
HEAPU8[ addr++ ] = 0xF8 | (u >> 24);
HEAPU8[ addr++ ] = 0x80 | ((u >> 18) & 63);
HEAPU8[ addr++ ] = 0x80 | ((u >> 12) & 63);
HEAPU8[ addr++ ] = 0x80 | ((u >> 6) & 63);
HEAPU8[ addr++ ] = 0x80 | (u & 63);
} else {
HEAPU8[ addr++ ] = 0xFC | (u >> 30);
HEAPU8[ addr++ ] = 0x80 | ((u >> 24) & 63);
HEAPU8[ addr++ ] = 0x80 | ((u >> 18) & 63);
HEAPU8[ addr++ ] = 0x80 | ((u >> 12) & 63);
HEAPU8[ addr++ ] = 0x80 | ((u >> 6) & 63);
HEAPU8[ addr++ ] = 0x80 | (u & 63);
}
}
};
};
js! { @(no_return)
Module.STDWEB.noop = function() {};
Module.STDWEB.to_js = function to_js( address ) {
var kind = HEAPU8[ address + 12 ];
if( kind === 0 ) {
return undefined;
} else if( kind === 1 ) {
return null;
} else if( kind === 2 ) {
return HEAP32[ address / 4 ];
} else if( kind === 3 ) {
return HEAPF64[ address / 8 ];
} else if( kind === 4 ) {
var pointer = HEAPU32[ address / 4 ];
var length = HEAPU32[ (address + 4) / 4 ];
return Module.STDWEB.to_js_string( pointer, length );
} else if( kind === 5 ) {
return false;
} else if( kind === 6 ) {
return true;
} else if( kind === 7 ) {
var pointer = HEAPU32[ address / 4 ];
var length = HEAPU32[ (address + 4) / 4 ];
var output = [];
for( var i = 0; i < length; ++i ) {
output.push( Module.STDWEB.to_js( pointer + i * 16 ) );
}
return output;
} else if( kind === 8 ) {
var value_array_pointer = HEAPU32[ address / 4 ];
var length = HEAPU32[ (address + 4) / 4 ];
var key_array_pointer = HEAPU32[ (address + 8) / 4 ];
var output = {};
for( var i = 0; i < length; ++i ) {
var key_pointer = HEAPU32[ (key_array_pointer + i * 8) / 4 ];
var key_length = HEAPU32[ (key_array_pointer + 4 + i * 8) / 4 ];
var key = Module.STDWEB.to_js_string( key_pointer, key_length );
var value = Module.STDWEB.to_js( value_array_pointer + i * 16 );
output[ key ] = value;
}
return output;
} else if( kind === 9 || kind === 11 || kind === 12 ) {
return Module.STDWEB.acquire_js_reference( HEAP32[ address / 4 ] );
} else if( kind === 10 ) {
var adapter_pointer = HEAPU32[ address / 4 ];
var pointer = HEAPU32[ (address + 4) / 4 ];
var deallocator_pointer = HEAPU32[ (address + 8) / 4 ];
var output = function() {
if( pointer === 0 ) {
throw new ReferenceError( "Already dropped Rust function called!" );
}
var args = Module.STDWEB.alloc( 16 );
Module.STDWEB.serialize_array( args, arguments );
Module.STDWEB.dyncall( "vii", adapter_pointer, [pointer, args] );
var result = Module.STDWEB.tmp;
Module.STDWEB.tmp = null;
return result;
};
output.drop = function() {
output.drop = Module.STDWEB.noop;
var function_pointer = pointer;
pointer = 0;
Module.STDWEB.dyncall( "vi", deallocator_pointer, [function_pointer] );
};
return output;
} else if( kind === 13 ) {
var adapter_pointer = HEAPU32[ address / 4 ];
var pointer = HEAPU32[ (address + 4) / 4 ];
var deallocator_pointer = HEAPU32[ (address + 8) / 4 ];
var output = function() {
if( pointer === 0 ) {
throw new ReferenceError( "Already called or dropped FnOnce function called!" );
}
output.drop = Module.STDWEB.noop;
var function_pointer = pointer;
pointer = 0;
var args = Module.STDWEB.alloc( 16 );
Module.STDWEB.serialize_array( args, arguments );
Module.STDWEB.dyncall( "vii", adapter_pointer, [function_pointer, args] );
var result = Module.STDWEB.tmp;
Module.STDWEB.tmp = null;
return result;
};
output.drop = function() {
output.drop = Module.STDWEB.noop;
var function_pointer = pointer;
pointer = 0;
Module.STDWEB.dyncall( "vi", deallocator_pointer, [function_pointer] );
};
return output;
} else if( kind === 14 ) {
var pointer = HEAPU32[ address / 4 ];
var length = HEAPU32[ (address + 4) / 4 ];
var array_kind = HEAPU32[ (address + 8) / 4 ];
var pointer_end = pointer + length;
switch( array_kind ) {
case 0:
return HEAPU8.subarray( pointer, pointer_end );
case 1:
return HEAP8.subarray( pointer, pointer_end );
case 2:
return HEAPU16.subarray( pointer, pointer_end );
case 3:
return HEAP16.subarray( pointer, pointer_end );
case 4:
return HEAPU32.subarray( pointer, pointer_end );
case 5:
return HEAP32.subarray( pointer, pointer_end );
case 6:
return HEAPF32.subarray( pointer, pointer_end );
case 7:
return HEAPF64.subarray( pointer, pointer_end );
}
}
};
};
js! { @(no_return)
Module.STDWEB.serialize_object = function serialize_object( address, value ) {
var keys = Object.keys( value );
var length = keys.length;
var key_array_pointer = Module.STDWEB.alloc( length * 8 );
var value_array_pointer = Module.STDWEB.alloc( length * 16 );
HEAPU8[ address + 12 ] = 8;
HEAPU32[ address / 4 ] = value_array_pointer;
HEAPU32[ (address + 4) / 4 ] = length;
HEAPU32[ (address + 8) / 4 ] = key_array_pointer;
for( var i = 0; i < length; ++i ) {
var key = keys[ i ];
var key_length = Module.STDWEB.utf8_len( key );
var key_pointer = Module.STDWEB.alloc( key_length );
Module.STDWEB.to_utf8( key, key_pointer );
var key_address = key_array_pointer + i * 8;
HEAPU32[ key_address / 4 ] = key_pointer;
HEAPU32[ (key_address + 4) / 4 ] = key_length;
Module.STDWEB.from_js( value_array_pointer + i * 16, value[ key ] );
}
};
Module.STDWEB.serialize_array = function serialize_array( address, value ) {
var length = value.length;
var pointer = Module.STDWEB.alloc( length * 16 );
HEAPU8[ address + 12 ] = 7;
HEAPU32[ address / 4 ] = pointer;
HEAPU32[ (address + 4) / 4 ] = length;
for( var i = 0; i < length; ++i ) {
Module.STDWEB.from_js( pointer + i * 16, value[ i ] );
}
};
Module.STDWEB.from_js = function from_js( address, value ) {
var kind = Object.prototype.toString.call( value );
if( kind === "[object String]" ) {
var length = Module.STDWEB.utf8_len( value );
var pointer = 0;
if( length > 0 ) {
pointer = Module.STDWEB.alloc( length );
Module.STDWEB.to_utf8( value, pointer );
}
HEAPU8[ address + 12 ] = 4;
HEAPU32[ address / 4 ] = pointer;
HEAPU32[ (address + 4) / 4 ] = length;
} else if( kind === "[object Number]" ) {
if( value === (value|0) ) {
HEAPU8[ address + 12 ] = 2;
HEAP32[ address / 4 ] = value;
} else {
HEAPU8[ address + 12 ] = 3;
HEAPF64[ address / 8 ] = value;
}
} else if( value === null ) {
HEAPU8[ address + 12 ] = 1;
} else if( value === undefined ) {
HEAPU8[ address + 12 ] = 0;
} else if( value === false ) {
HEAPU8[ address + 12 ] = 5;
} else if( value === true ) {
HEAPU8[ address + 12 ] = 6;
} else {
var refid = Module.STDWEB.acquire_rust_reference( value );
var id = 9;
if( kind === "[object Object]" ) {
id = 11;
} else if( kind === "[object Array]" || kind === "[object Arguments]" ) {
id = 12;
}
HEAPU8[ address + 12 ] = id;
HEAP32[ address / 4 ] = refid;
}
};
};
js! { @(no_return)
Module.STDWEB.to_js_string = function to_js_string( index, length ) {
index = index|0;
length = length|0;
var end = (index|0) + (length|0);
var output = "";
while( index < end ) {
var x = HEAPU8[ index++ ];
if( x < 128 ) {
output += String.fromCharCode( x );
continue;
}
var init = (x & (0x7F >> 2));
var y = 0;
if( index < end ) {
y = HEAPU8[ index++ ];
}
var ch = (init << 6) | (y & 63);
if( x >= 0xE0 ) {
var z = 0;
if( index < end ) {
z = HEAPU8[ index++ ];
}
var y_z = ((y & 63) << 6) | (z & 63);
ch = init << 12 | y_z;
if( x >= 0xF0 ) {
var w = 0;
if( index < end ) {
w = HEAPU8[ index++ ];
}
ch = (init & 7) << 18 | ((y_z << 6) | (w & 63));
}
}
output += String.fromCharCode( ch );
continue;
}
return output;
};
};
js! { @(no_return)
var id_to_ref_map = {};
var id_to_refcount_map = {};
var ref_to_id_map = new WeakMap();
var ref_to_id_symbol_map = {};
var last_refid = 1;
Module.STDWEB.acquire_rust_reference = function( reference ) {
if( reference === undefined || reference === null ) {
return 0;
}
var refid = ref_to_id_map.get( reference );
if( refid === undefined ) {
refid = ref_to_id_symbol_map[ reference ];
}
if( refid === undefined ) {
refid = last_refid++;
if( typeof reference === "symbol" ) {
ref_to_id_symbol_map[ reference ] = refid;
} else {
ref_to_id_map.set( reference, refid );
}
id_to_ref_map[ refid ] = reference;
id_to_refcount_map[ refid ] = 1;
} else {
id_to_refcount_map[ refid ]++;
}
return refid;
};
Module.STDWEB.acquire_js_reference = function( refid ) {
return id_to_ref_map[ refid ];
};
Module.STDWEB.increment_refcount = function( refid ) {
id_to_refcount_map[ refid ]++;
};
Module.STDWEB.decrement_refcount = function( refid ) {
id_to_refcount_map[ refid ]--;
if( id_to_refcount_map[ refid ] === 0 ) {
var reference = id_to_ref_map[ refid ];
delete id_to_ref_map[ refid ];
delete id_to_refcount_map[ refid ];
if( typeof reference === "symbol" ) {
delete ref_to_id_symbol_map[ reference ];
} else {
ref_to_id_map.delete( reference );
}
}
};
}
if cfg!( test ) == false {
panic::set_hook( Box::new( |info| {
__js_raw_asm!( "console.error( 'Encountered a panic!' );" );
if let Some( value ) = info.payload().downcast_ref::< String >() {
__js_raw_asm!( "\
console.error( 'Panic error message:', Module.STDWEB.to_js_string( $0, $1 ) );\
", value.as_ptr(), value.len() );
}
if let Some( location ) = info.location() {
let file = location.file();
__js_raw_asm!( "\
console.error( 'Panic location:', Module.STDWEB.to_js_string( $0, $1 ) + ':' + $2 );\
", file.as_ptr(), file.len(), location.line() );
}
}));
}
}
pub fn event_loop() {
ffi::event_loop();
}