/*global Module*/ /*global HEAP32*/ /*global readLatin1String, writeStringToMemory*/ /*global requireRegisteredType, throwBindingError*/ var _emval_handle_array = [{}]; // reserve zero var _emval_free_list = []; // Public JS API /** @expose */ Module.count_emval_handles = function() { var count = 0; for (var i = 1; i < _emval_handle_array.length; ++i) { if (_emval_handle_array[i] !== undefined) { ++count; } } return count; }; /** @expose */ Module.get_first_emval = function() { for (var i = 1; i < _emval_handle_array.length; ++i) { if (_emval_handle_array[i] !== undefined) { return _emval_handle_array[i]; } } return null; }; // Private C++ API var _emval_symbols = {}; // address -> string function __emval_register_symbol(address) { _emval_symbols[address] = readLatin1String(address); } function getStringOrSymbol(address) { var symbol = _emval_symbols[address]; if (symbol === undefined) { return readLatin1String(address); } else { return symbol; } } function requireHandle(handle) { if (!handle) { throwBindingError('Cannot use deleted val. handle = ' + handle); } } function __emval_register(value) { var handle = _emval_free_list.length ? _emval_free_list.pop() : _emval_handle_array.length; _emval_handle_array[handle] = {refcount: 1, value: value}; return handle; } function __emval_incref(handle) { if (handle) { _emval_handle_array[handle].refcount += 1; } } function __emval_decref(handle) { if (handle && 0 === --_emval_handle_array[handle].refcount) { delete _emval_handle_array[handle]; _emval_free_list.push(handle); var actual_length = _emval_handle_array.length; while (actual_length > 0 && _emval_handle_array[actual_length - 1] === undefined) { --actual_length; } _emval_handle_array.length = actual_length; } } function __emval_new_array() { return __emval_register([]); } function __emval_new_object() { return __emval_register({}); } function __emval_undefined() { return __emval_register(undefined); } function __emval_null() { return __emval_register(null); } function __emval_new_cstring(v) { return __emval_register(getStringOrSymbol(v)); } function __emval_take_value(type, v) { type = requireRegisteredType(type, '_emval_take_value'); v = type.fromWireType(v); return __emval_register(v); } var __newers = {}; // arity -> function function __emval_new(handle, argCount, argTypes) { requireHandle(handle); var args = parseParameters( argCount, argTypes, Array.prototype.slice.call(arguments, 3)); // Alas, we are forced to use operator new until WebKit enables // constructing typed arrays without new. // In WebKit, Uint8Array(10) throws an error. // In every other browser, it's identical to new Uint8Array(10). var newer = __newers[argCount]; if (!newer) { var parameters = new Array(argCount); for (var i = 0; i < argCount; ++i) { parameters[i] = 'a' + i; } /*jshint evil:true*/ newer = __newers[argCount] = new Function( ['c'].concat(parameters), "return new c(" + parameters.join(',') + ");"); } var constructor = _emval_handle_array[handle].value; var obj = newer.apply(undefined, [constructor].concat(args)); /* // implement what amounts to operator new function dummy(){} dummy.prototype = constructor.prototype; var obj = new constructor; var rv = constructor.apply(obj, args); if (typeof rv === 'object') { obj = rv; } */ return __emval_register(obj); } // appease jshint (technically this code uses eval) var global = (function(){return Function;})()('return this')(); function __emval_get_global(name) { name = getStringOrSymbol(name); return __emval_register(global[name]); } function __emval_get_module_property(name) { name = getStringOrSymbol(name); return __emval_register(Module[name]); } function __emval_get_property(handle, key) { requireHandle(handle); return __emval_register(_emval_handle_array[handle].value[_emval_handle_array[key].value]); } function __emval_set_property(handle, key, value) { requireHandle(handle); _emval_handle_array[handle].value[_emval_handle_array[key].value] = _emval_handle_array[value].value; } function __emval_as(handle, returnType) { requireHandle(handle); returnType = requireRegisteredType(returnType, 'emval::as'); var destructors = []; // caller owns destructing return returnType.toWireType(destructors, _emval_handle_array[handle].value); } function parseParameters(argCount, argTypes, argWireTypes) { var a = new Array(argCount); for (var i = 0; i < argCount; ++i) { var argType = requireRegisteredType( HEAP32[(argTypes >> 2) + i], "parameter " + i); a[i] = argType.fromWireType(argWireTypes[i]); } return a; } function __emval_call(handle, argCount, argTypes) { requireHandle(handle); var fn = _emval_handle_array[handle].value; var args = parseParameters( argCount, argTypes, Array.prototype.slice.call(arguments, 3)); var rv = fn.apply(undefined, args); return __emval_register(rv); } function __emval_call_method(handle, name, argCount, argTypes) { requireHandle(handle); name = getStringOrSymbol(name); var args = parseParameters( argCount, argTypes, Array.prototype.slice.call(arguments, 4)); var obj = _emval_handle_array[handle].value; var rv = obj[name].apply(obj, args); return __emval_register(rv); } function __emval_call_void_method(handle, name, argCount, argTypes) { requireHandle(handle); name = getStringOrSymbol(name); var args = parseParameters( argCount, argTypes, Array.prototype.slice.call(arguments, 4)); var obj = _emval_handle_array[handle].value; obj[name].apply(obj, args); } function __emval_has_function(handle, name) { name = getStringOrSymbol(name); return _emval_handle_array[handle].value[name] instanceof Function; }