aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/closure-externs.js60
-rw-r--r--src/deps_info.json3
-rw-r--r--src/embind/embind.js154
-rw-r--r--src/embind/emval.js156
-rw-r--r--src/headlessCanvas.js4
-rw-r--r--src/intertyper.js10
-rw-r--r--src/jsifier.js16
-rw-r--r--src/library.js446
-rw-r--r--src/library_browser.js231
-rw-r--r--src/library_egl.js6
-rw-r--r--src/library_fs.js151
-rw-r--r--src/library_gc.js2
-rw-r--r--src/library_gl.js7
-rw-r--r--src/library_glfw.js237
-rw-r--r--src/library_glut.js5
-rw-r--r--src/library_html5.js79
-rw-r--r--src/library_openal.js36
-rw-r--r--src/library_sdl.js445
-rw-r--r--src/library_sockfs.js38
-rw-r--r--src/modules.js1
-rw-r--r--src/parseTools.js10
-rw-r--r--src/postamble.js16
-rw-r--r--src/preamble.js23
-rw-r--r--src/relooper/README.markdown14
-rw-r--r--src/relooper/README.md12
-rw-r--r--src/relooper/Relooper.cpp169
-rw-r--r--src/relooper/Relooper.h22
-rw-r--r--src/relooper/test.cpp123
-rw-r--r--src/relooper/test.txt65
-rw-r--r--src/runtime.js27
-rw-r--r--src/settings.js34
-rw-r--r--src/shell.html1664
-rw-r--r--src/shell.js6
-rw-r--r--src/shell_minimal.html11
-rw-r--r--src/struct_info.json29
35 files changed, 2805 insertions, 1507 deletions
diff --git a/src/closure-externs.js b/src/closure-externs.js
index a82aa669..fe6d84aa 100644
--- a/src/closure-externs.js
+++ b/src/closure-externs.js
@@ -108,3 +108,63 @@ var flags = {};
flags.binary;
+/**
+ * @fileoverview Definitions for W3C's Gamepad specification.
+ * @see http://www.w3.org/TR/gamepad/
+ * @externs
+ */
+
+/**
+ * @typedef {{id: string, index: number, timestamp: number, axes: Array.<number>, buttons: Array.<number>}}
+ */
+var Gamepad;
+
+/**
+* @type {Array.<number>}
+*/
+Gamepad.buttons;
+
+/**
+* @type {Array.<number>}
+*/
+Gamepad.axes;
+
+/**
+* @type {number}
+*/
+Gamepad.index;
+
+/**
+* @type {string}
+*/
+Gamepad.id;
+
+/**
+* @type {number}
+*/
+Gamepad.timestamp;
+
+/**
+ * @return {Array.<Gamepad>}
+ */
+navigator.getGamepads = function() {};
+
+/**
+ * @return {Array.<Gamepad>}
+ */
+navigator.webkitGetGamepads = function() {};
+
+/**
+ * @return {Array.<Gamepad>}
+ */
+navigator.webkitGamepads = function() {};
+
+/**
+ * @return {Array.<Gamepad>}
+ */
+navigator.mozGamepads = function() {};
+
+/**
+ * @return {Array.<Gamepad>}
+ */
+navigator.gamepads = function() {};
diff --git a/src/deps_info.json b/src/deps_info.json
index b38ffd00..029a20e1 100644
--- a/src/deps_info.json
+++ b/src/deps_info.json
@@ -2,6 +2,7 @@
"uuid_compare": ["memcmp"],
"SDL_Init": ["malloc", "free"],
"SDL_GL_GetProcAddress": ["emscripten_GetProcAddress"],
- "eglGetProcAddress": ["emscripten_GetProcAddress"]
+ "eglGetProcAddress": ["emscripten_GetProcAddress"],
+ "emscripten_GetProcAddress": ["strstr"]
}
diff --git a/src/embind/embind.js b/src/embind/embind.js
index f0cd0c74..6ec07cd9 100644
--- a/src/embind/embind.js
+++ b/src/embind/embind.js
@@ -1,6 +1,6 @@
/*global Module*/
/*global _malloc, _free, _memcpy*/
-/*global FUNCTION_TABLE, HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32*/
+/*global FUNCTION_TABLE, HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64*/
/*global readLatin1String*/
/*global __emval_register, _emval_handle_array, __emval_decref*/
/*global ___getTypeName*/
@@ -35,7 +35,7 @@ function throwUnboundTypeError(message, types) {
seen[type] = true;
}
types.forEach(visit);
-
+
throw new UnboundTypeError(message + ': ' + unboundTypes.map(getTypeName).join([', ']));
}
@@ -55,7 +55,7 @@ function ensureOverloadTable(proto, methodName, humanName) {
// Move the previous function into the overload table.
proto[methodName].overloadTable = [];
proto[methodName].overloadTable[prevFunc.argCount] = prevFunc;
- }
+ }
}
/* Registers a symbol (function, class, enum, ...) as part of the Module JS object so that
@@ -72,7 +72,7 @@ function exposePublicSymbol(name, value, numArguments) {
if (undefined === numArguments || (undefined !== Module[name].overloadTable && undefined !== Module[name].overloadTable[numArguments])) {
throwBindingError("Cannot register public name '" + name + "' twice");
}
-
+
// We are exposing a function with the same name as an existing function. Create an overload table and a function selector
// that routes between the two.
ensureOverloadTable(Module, name, name);
@@ -164,6 +164,10 @@ var typeDependencies = {};
var registeredPointers = {};
function registerType(rawType, registeredInstance) {
+ if (!('argPackAdvance' in registeredInstance)) {
+ throw new TypeError('registerType registeredInstance requires argPackAdvance');
+ }
+
var name = registeredInstance.name;
if (!rawType) {
throwBindingError('type "' + name + '" must have a positive integer typeid pointer');
@@ -268,6 +272,7 @@ function __embind_register_void(rawType, name) {
name = readLatin1String(name);
registerType(rawType, {
name: name,
+ 'argPackAdvance': 0,
'fromWireType': function() {
return undefined;
},
@@ -278,7 +283,9 @@ function __embind_register_void(rawType, name) {
});
}
-function __embind_register_bool(rawType, name, trueValue, falseValue) {
+function __embind_register_bool(rawType, name, size, trueValue, falseValue) {
+ var shift = getShiftFromSize(size);
+
name = readLatin1String(name);
registerType(rawType, {
name: name,
@@ -290,21 +297,80 @@ function __embind_register_bool(rawType, name, trueValue, falseValue) {
'toWireType': function(destructors, o) {
return o ? trueValue : falseValue;
},
+ 'argPackAdvance': 8,
+ 'readValueFromPointer': function(pointer) {
+ // TODO: if heap is fixed (like in asm.js) this could be executed outside
+ var heap;
+ if (size === 1) {
+ heap = HEAP8;
+ } else if (size === 2) {
+ heap = HEAP16;
+ } else if (size === 4) {
+ heap = HEAP32;
+ } else {
+ throw new TypeError("Unknown boolean type size: " + name);
+ }
+ return this['fromWireType'](heap[pointer >> shift]);
+ },
destructorFunction: null, // This type does not need a destructor
});
}
+function getShiftFromSize(size) {
+ switch (size) {
+ case 1: return 0;
+ case 2: return 1;
+ case 4: return 2;
+ case 8: return 3;
+ default:
+ throw new TypeError('Unknown type size: ' + size);
+ }
+}
+
+function integerReadValueFromPointer(name, shift, signed) {
+ switch (shift) {
+ case 0: return function(pointer) {
+ var heap = signed ? HEAP8 : HEAPU8;
+ return this['fromWireType'](heap[pointer]);
+ };
+ case 1: return function(pointer) {
+ var heap = signed ? HEAP16 : HEAPU16;
+ return this['fromWireType'](heap[pointer >> 1]);
+ };
+ case 2: return function(pointer) {
+ var heap = signed ? HEAP32 : HEAPU32;
+ return this['fromWireType'](heap[pointer >> 2]);
+ };
+ default:
+ throw new TypeError("Unknown integer type: " + name);
+ }
+}
+
+function floatReadValueFromPointer(name, shift) {
+ switch (shift) {
+ case 2: return function(pointer) {
+ return this['fromWireType'](HEAPF32[pointer >> 2]);
+ };
+ case 3: return function(pointer) {
+ return this['fromWireType'](HEAPF64[pointer >> 3]);
+ };
+ default:
+ throw new TypeError("Unknown float type: " + name);
+ }
+}
+
// When converting a number from JS to C++ side, the valid range of the number is
// [minRange, maxRange], inclusive.
-function __embind_register_integer(primitiveType, name, minRange, maxRange) {
+function __embind_register_integer(primitiveType, name, size, minRange, maxRange) {
name = readLatin1String(name);
if (maxRange === -1) { // LLVM doesn't have signed and unsigned 32-bit types, so u32 literals come out as 'i32 -1'. Always treat those as max u32.
maxRange = 4294967295;
}
+
+ var shift = getShiftFromSize(size);
+
registerType(primitiveType, {
name: name,
- minRange: minRange,
- maxRange: maxRange,
'fromWireType': function(value) {
return value;
},
@@ -319,11 +385,16 @@ function __embind_register_integer(primitiveType, name, minRange, maxRange) {
}
return value | 0;
},
+ 'argPackAdvance': 8,
+ 'readValueFromPointer': integerReadValueFromPointer(name, shift, minRange !== 0),
destructorFunction: null, // This type does not need a destructor
});
}
-function __embind_register_float(rawType, name) {
+
+
+function __embind_register_float(rawType, name, size) {
+ var shift = getShiftFromSize(size);
name = readLatin1String(name);
registerType(rawType, {
name: name,
@@ -338,10 +409,17 @@ function __embind_register_float(rawType, name) {
}
return value;
},
+ 'argPackAdvance': 8,
+ 'readValueFromPointer': floatReadValueFromPointer(name, shift),
destructorFunction: null, // This type does not need a destructor
});
}
+// For types whose wire types are 32-bit pointers.
+function simpleReadValueFromPointer(pointer) {
+ return this['fromWireType'](HEAPU32[pointer >> 2]);
+}
+
function __embind_register_std_string(rawType, name) {
name = readLatin1String(name);
registerType(rawType, {
@@ -394,6 +472,8 @@ function __embind_register_std_string(rawType, name) {
}
return ptr;
},
+ 'argPackAdvance': 8,
+ 'readValueFromPointer': simpleReadValueFromPointer,
destructorFunction: function(ptr) { _free(ptr); },
});
}
@@ -434,6 +514,8 @@ function __embind_register_std_wstring(rawType, charSize, name) {
}
return ptr;
},
+ 'argPackAdvance': 8,
+ 'readValueFromPointer': simpleReadValueFromPointer,
destructorFunction: function(ptr) { _free(ptr); },
});
}
@@ -450,6 +532,8 @@ function __embind_register_emval(rawType, name) {
'toWireType': function(destructors, value) {
return __emval_register(value);
},
+ 'argPackAdvance': 8,
+ 'readValueFromPointer': simpleReadValueFromPointer,
destructorFunction: null, // This type does not need a destructor
});
}
@@ -463,7 +547,7 @@ function __embind_register_memory_view(rawType, name) {
Int32Array,
Uint32Array,
Float32Array,
- Float64Array,
+ Float64Array,
];
name = readLatin1String(name);
@@ -476,6 +560,10 @@ function __embind_register_memory_view(rawType, name) {
var TA = typeMapping[type];
return new TA(HEAP8.buffer, data, size);
},
+ 'argPackAdvance': 16,
+ 'readValueFromPointer': function(ptr) {
+ return this['fromWireType'](ptr);
+ },
});
}
@@ -531,7 +619,7 @@ function craftInvokerFunction(humanName, argTypes, classType, cppInvokerFunc, cp
if (argCount < 2) {
throwBindingError("argTypes array size mismatch! Must at least get return value and 'this' types!");
}
-
+
var isClassMethodFunc = (argTypes[1] !== null && classType !== null);
if (!isClassMethodFunc && !FUNCTION_TABLE[cppTargetFunc]) {
@@ -560,7 +648,7 @@ function craftInvokerFunction(humanName, argTypes, classType, cppInvokerFunc, cp
// Determine if we need to use a dynamic stack to store the destructors for the function parameters.
// TODO: Remove this completely once all function invokers are being dynamically generated.
var needsDestructorStack = false;
-
+
for(var i = 1; i < argTypes.length; ++i) { // Skip return value at index 0 - it's not deleted here.
if (argTypes[i] !== null && argTypes[i].destructorFunction === undefined) { // The type does not define a destructor function - must use dynamic stack
needsDestructorStack = true;
@@ -595,7 +683,7 @@ function craftInvokerFunction(humanName, argTypes, classType, cppInvokerFunc, cp
invokerFnBody +=
(returns?"var rv = ":"") + "invoker(fn"+(argsListWired.length>0?", ":"")+argsListWired+");\n";
-
+
if (needsDestructorStack) {
invokerFnBody += "runDestructors(destructors);\n";
} else {
@@ -608,7 +696,7 @@ function craftInvokerFunction(humanName, argTypes, classType, cppInvokerFunc, cp
}
}
}
-
+
if (returns) {
invokerFnBody += "return retType.fromWireType(rv);\n";
}
@@ -676,7 +764,7 @@ function __embind_finalize_value_array(rawTupleType) {
var rawConstructor = reg.rawConstructor;
var rawDestructor = reg.rawDestructor;
-
+
whenDependentTypesAreResolved([rawTupleType], elementTypes, function(elementTypes) {
elements.forEach(function(elt, i) {
var getterReturnType = elementTypes[i];
@@ -718,6 +806,8 @@ function __embind_finalize_value_array(rawTupleType) {
}
return ptr;
},
+ 'argPackAdvance': 8,
+ 'readValueFromPointer': simpleReadValueFromPointer,
destructorFunction: rawDestructor,
}];
});
@@ -819,6 +909,8 @@ function __embind_finalize_value_object(structType) {
}
return ptr;
},
+ 'argPackAdvance': 8,
+ 'readValueFromPointer': simpleReadValueFromPointer,
destructorFunction: rawDestructor,
}];
});
@@ -860,7 +952,7 @@ var genericPointerToWireType = function(destructors, handle) {
if (undefined === handle.$$.smartPtr) {
throwBindingError('Passing raw pointer to smart pointer is illegal');
}
-
+
switch (this.sharingPolicy) {
case 0: // NONE
// no upcasting
@@ -870,11 +962,11 @@ var genericPointerToWireType = function(destructors, handle) {
throwBindingError('Cannot convert argument of type ' + (handle.$$.smartPtrType ? handle.$$.smartPtrType.name : handle.$$.ptrType.name) + ' to parameter type ' + this.name);
}
break;
-
+
case 1: // INTRUSIVE
ptr = handle.$$.smartPtr;
break;
-
+
case 2: // BY_EMVAL
if (handle.$$.smartPtrType === this) {
ptr = handle.$$.smartPtr;
@@ -891,7 +983,7 @@ var genericPointerToWireType = function(destructors, handle) {
}
}
break;
-
+
default:
throwBindingError('Unsupporting sharing policy');
}
@@ -985,7 +1077,7 @@ function RegisteredPointer(
this['toWireType'] = genericPointerToWireType;
// Here we must leave this.destructorFunction undefined, since whether genericPointerToWireType returns
// a pointer that needs to be freed up is runtime-dependent, and cannot be evaluated at registration time.
- // TODO: Create an alternative mechanism that allows removing the use of var destructors = []; array in
+ // TODO: Create an alternative mechanism that allows removing the use of var destructors = []; array in
// craftInvokerFunction altogether.
}
}
@@ -1003,6 +1095,9 @@ RegisteredPointer.prototype.destructor = function(ptr) {
}
};
+RegisteredPointer.prototype['argPackAdvance'] = 8;
+RegisteredPointer.prototype['readValueFromPointer'] = simpleReadValueFromPointer;
+
RegisteredPointer.prototype['fromWireType'] = function(ptr) {
// ptr is a raw pointer (or a raw smartpointer)
@@ -1110,7 +1205,7 @@ ClassHandle.prototype['isAliasOf'] = function(other) {
right = rightClass.upcast(right);
rightClass = rightClass.baseClass;
}
-
+
return leftClass === rightClass && left === right;
};
@@ -1195,7 +1290,7 @@ Module['setDelayFunction'] = function setDelayFunction(fn) {
delayFunction(flushPendingDeletes);
}
};
-
+
function RegisteredClass(
name,
constructor,
@@ -1298,7 +1393,7 @@ function __embind_register_class(
true,
false,
false);
-
+
var pointerConverter = new RegisteredPointer(
name + '*',
registeredClass,
@@ -1360,10 +1455,10 @@ function __embind_register_class_constructor(
for (var i = 1; i < argCount; ++i) {
args[i] = argTypes[i]['toWireType'](destructors, arguments[i - 1]);
}
-
+
var ptr = invoker.apply(null, args);
runDestructors(destructors);
-
+
return argTypes[0]['fromWireType'](ptr);
};
return [];
@@ -1447,7 +1542,7 @@ function __embind_register_class_function(
}
whenDependentTypesAreResolved([], rawArgTypes, function(argTypes) {
-
+
var memberFunction = craftInvokerFunction(humanName, argTypes, classType, rawInvoker, context);
// Replace the initial unbound-handler-stub function with the appropriate member function, now that all types
@@ -1627,8 +1722,11 @@ function __embind_register_smart_ptr(
function __embind_register_enum(
rawType,
- name
+ name,
+ size,
+ isSigned
) {
+ var shift = getShiftFromSize(size);
name = readLatin1String(name);
function constructor() {
@@ -1644,6 +1742,8 @@ function __embind_register_enum(
'toWireType': function(destructors, c) {
return c.value;
},
+ 'argPackAdvance': 8,
+ 'readValueFromPointer': integerReadValueFromPointer(name, shift, isSigned),
destructorFunction: null,
});
exposePublicSymbol(name, constructor);
diff --git a/src/embind/emval.js b/src/embind/emval.js
index 039f1d61..4007701a 100644
--- a/src/embind/emval.js
+++ b/src/embind/emval.js
@@ -55,6 +55,7 @@ function requireHandle(handle) {
if (!handle) {
throwBindingError('Cannot use deleted val. handle = ' + handle);
}
+ return _emval_handle_array[handle].value;
}
function __emval_register(value) {
@@ -105,9 +106,9 @@ function __emval_new_cstring(v) {
return __emval_register(getStringOrSymbol(v));
}
-function __emval_take_value(type, v) {
+function __emval_take_value(type, argv) {
type = requireRegisteredType(type, '_emval_take_value');
- v = type['fromWireType'](v);
+ var v = type['readValueFromPointer'](argv);
return __emval_register(v);
}
@@ -116,70 +117,51 @@ var __newers = {}; // arity -> function
function craftEmvalAllocator(argCount) {
/*This function returns a new function that looks like this:
- function emval_allocator_3(handle, argTypes, arg0Wired, arg1Wired, arg2Wired) {
+ function emval_allocator_3(constructor, argTypes, args) {
var argType0 = requireRegisteredType(HEAP32[(argTypes >> 2)], "parameter 0");
- var arg0 = argType0.fromWireType(arg0Wired);
+ var arg0 = argType0.readValueFromPointer(args);
var argType1 = requireRegisteredType(HEAP32[(argTypes >> 2) + 1], "parameter 1");
- var arg1 = argType1.fromWireType(arg1Wired);
+ var arg1 = argType1.readValueFromPointer(args + 8);
var argType2 = requireRegisteredType(HEAP32[(argTypes >> 2) + 2], "parameter 2");
- var arg2 = argType2.fromWireType(arg2Wired);
- var constructor = _emval_handle_array[handle].value;
- var emval = new constructor(arg0, arg1, arg2);
- return emval;
+ var arg2 = argType2.readValueFromPointer(args + 16);
+ var obj = new constructor(arg0, arg1, arg2);
+ return __emval_register(obj);
} */
- var args1 = ["requireRegisteredType", "HEAP32", "_emval_handle_array", "__emval_register"];
- var args2 = [requireRegisteredType, HEAP32, _emval_handle_array, __emval_register];
-
var argsList = "";
- var argsListWired = "";
for(var i = 0; i < argCount; ++i) {
argsList += (i!==0?", ":"")+"arg"+i; // 'arg0, arg1, ..., argn'
- argsListWired += ", arg"+i+"Wired"; // ', arg0Wired, arg1Wired, ..., argnWired'
}
- var invokerFnBody =
- "return function emval_allocator_"+argCount+"(handle, argTypes " + argsListWired + ") {\n";
+ var functionBody =
+ "return function emval_allocator_"+argCount+"(constructor, argTypes, args) {\n";
for(var i = 0; i < argCount; ++i) {
- invokerFnBody +=
+ functionBody +=
"var argType"+i+" = requireRegisteredType(HEAP32[(argTypes >> 2) + "+i+"], \"parameter "+i+"\");\n" +
- "var arg"+i+" = argType"+i+".fromWireType(arg"+i+"Wired);\n";
+ "var arg"+i+" = argType"+i+".readValueFromPointer(args);\n" +
+ "args += argType"+i+".argPackAdvance;\n";
}
- invokerFnBody +=
- "var constructor = _emval_handle_array[handle].value;\n" +
+ functionBody +=
"var obj = new constructor("+argsList+");\n" +
"return __emval_register(obj);\n" +
"}\n";
- args1.push(invokerFnBody);
- var invokerFunction = new_(Function, args1).apply(null, args2);
- return invokerFunction;
+ /*jshint evil:true*/
+ return (new Function("requireRegisteredType", "HEAP32", "__emval_register", functionBody))(
+ requireRegisteredType, HEAP32, __emval_register);
}
-function __emval_new(handle, argCount, argTypes) {
- requireHandle(handle);
-
+function __emval_new(handle, argCount, argTypes, args) {
+ handle = requireHandle(handle);
+
var newer = __newers[argCount];
if (!newer) {
newer = craftEmvalAllocator(argCount);
__newers[argCount] = newer;
}
- if (argCount === 0) {
- return newer(handle, argTypes);
- } else if (argCount === 1) {
- return newer(handle, argTypes, arguments[3]);
- } else if (argCount === 2) {
- return newer(handle, argTypes, arguments[3], arguments[4]);
- } else if (argCount === 3) {
- return newer(handle, argTypes, arguments[3], arguments[4], arguments[5]);
- } else if (argCount === 4) {
- return newer(handle, argTypes, arguments[3], arguments[4], arguments[5], arguments[6]);
- } else {
- // This is a slow path! (.apply and .splice are slow), so a few specializations are present above.
- return newer.apply(null, arguments.splice(1));
- }
+ return newer(handle, argTypes, args);
}
// appease jshint (technically this code uses eval)
@@ -196,46 +178,39 @@ function __emval_get_module_property(name) {
}
function __emval_get_property(handle, key) {
- requireHandle(handle);
- return __emval_register(_emval_handle_array[handle].value[_emval_handle_array[key].value]);
+ handle = requireHandle(handle);
+ key = requireHandle(key);
+ return __emval_register(handle[key]);
}
function __emval_set_property(handle, key, value) {
- requireHandle(handle);
- _emval_handle_array[handle].value[_emval_handle_array[key].value] = _emval_handle_array[value].value;
+ handle = requireHandle(handle);
+ key = requireHandle(key);
+ value = requireHandle(value);
+ handle[key] = value;
}
function __emval_as(handle, returnType, destructorsRef) {
- requireHandle(handle);
+ handle = requireHandle(handle);
returnType = requireRegisteredType(returnType, 'emval::as');
var destructors = [];
var rd = __emval_register(destructors);
HEAP32[destructorsRef >> 2] = rd;
- return returnType['toWireType'](destructors, _emval_handle_array[handle].value);
+ return returnType['toWireType'](destructors, handle);
}
-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);
+function __emval_call(handle, argCount, argTypes, argv) {
+ handle = requireHandle(handle);
var types = lookupTypes(argCount, argTypes);
var args = new Array(argCount);
for (var i = 0; i < argCount; ++i) {
- args[i] = types[i]['fromWireType'](arguments[3 + i]);
+ var type = types[i];
+ args[i] = type['readValueFromPointer'](argv);
+ argv += type.argPackAdvance;
}
- var fn = _emval_handle_array[handle].value;
- var rv = fn.apply(undefined, args);
+ var rv = handle.apply(undefined, args);
return __emval_register(rv);
}
@@ -255,44 +230,59 @@ function allocateDestructors(destructorsRef) {
return destructors;
}
+// Leave id 0 undefined. It's not a big deal, but might be confusing
+// to have null be a valid method caller.
+var methodCallers = [undefined];
+
+function addMethodCaller(caller) {
+ var id = methodCallers.length;
+ methodCallers.push(caller);
+ return id;
+}
+
function __emval_get_method_caller(argCount, argTypes) {
var types = lookupTypes(argCount, argTypes);
var retType = types[0];
var signatureName = retType.name + "_$" + types.slice(1).map(function (t) { return t.name; }).join("_") + "$";
- var args1 = ["addFunction", "createNamedFunction", "requireHandle", "getStringOrSymbol", "_emval_handle_array", "retType", "allocateDestructors"];
- var args2 = [Runtime.addFunction, createNamedFunction, requireHandle, getStringOrSymbol, _emval_handle_array, retType, allocateDestructors];
+ var params = ["retType"];
+ var args = [retType];
var argsList = ""; // 'arg0, arg1, arg2, ... , argN'
- var argsListWired = ""; // 'arg0Wired, ..., argNWired'
for (var i = 0; i < argCount - 1; ++i) {
argsList += (i !== 0 ? ", " : "") + "arg" + i;
- argsListWired += ", arg" + i + "Wired";
- args1.push("argType" + i);
- args2.push(types[1 + i]);
+ params.push("argType" + i);
+ args.push(types[1 + i]);
}
- var invokerFnBody =
- "return addFunction(createNamedFunction('" + signatureName + "', function (handle, name, destructorsRef" + argsListWired + ") {\n" +
- " requireHandle(handle);\n" +
- " name = getStringOrSymbol(name);\n";
+ var functionBody =
+ "return function (handle, name, destructors, args) {\n";
for (var i = 0; i < argCount - 1; ++i) {
- invokerFnBody += " var arg" + i + " = argType" + i + ".fromWireType(arg" + i + "Wired);\n";
+ functionBody +=
+ " var arg" + i + " = argType" + i + ".readValueFromPointer(args);\n" +
+ " args += argType" + i + ".argPackAdvance;\n";
}
- invokerFnBody +=
- " var obj = _emval_handle_array[handle].value;\n" +
- " var rv = obj[name](" + argsList + ");\n" +
- " return retType.toWireType(allocateDestructors(destructorsRef), rv);\n" +
- "}));\n";
-
- args1.push(invokerFnBody);
- var invokerFunction = new_(Function, args1).apply(null, args2);
- return invokerFunction;
+ functionBody +=
+ " var rv = handle[name](" + argsList + ");\n" +
+ " return retType.toWireType(destructors, rv);\n" +
+ "};\n";
+
+ params.push(functionBody);
+ var invokerFunction = new_(Function, params).apply(null, args);
+ return addMethodCaller(createNamedFunction(signatureName, invokerFunction));
+}
+
+function __emval_call_method(caller, handle, methodName, destructorsRef, args) {
+ caller = methodCallers[caller];
+ handle = requireHandle(handle);
+ methodName = getStringOrSymbol(methodName);
+ return caller(handle, methodName, allocateDestructors(destructorsRef), args);
}
function __emval_has_function(handle, name) {
+ handle = requireHandle(handle);
name = getStringOrSymbol(name);
- return _emval_handle_array[handle].value[name] instanceof Function;
+ return handle[name] instanceof Function;
}
diff --git a/src/headlessCanvas.js b/src/headlessCanvas.js
index 4bd17a7b..1eefe48e 100644
--- a/src/headlessCanvas.js
+++ b/src/headlessCan