Fix Non-future-proof Invocations Of Emscripten DynCalls
Introduction
The Emscripten plugin for Unity has been updated to use a new syntax for invoking dynCalls, which is more future-proof and compatible with newer Emscripten versions. This article will guide you through the changes and provide a step-by-step solution to fix non-future-proof invocations of Emscripten dynCalls.
Problem Statement
Two problems exist with .jslib
files in the project:
- The code will override the Emscripten system
Runtime
object. (fortunately Unity today does not use any Emscripten constructs that would refer to theRuntime
namespace, but that is not guaranteed) - The code invoking dynCalls is not compatible with future Emscripten versions (3.1.38 and newer), because legacy dynCall() functions in new Emscripten versions require declaring a
__deps
directive (which was not present).
Solution
To fix both these issues, the following diff can be applied:
diff --git a/Assets/Thirdweb/Plugins/ThreadingPatcher/Plugins/SystemThreadingTimer.jslib b/Assets/Thirdweb/Plugins/ThreadingPatcher/Plugins/SystemThreadingTimer.jslib
index 5c75db8..af011ec 100644
--- a/Assets/Thirdweb/Plugins/ThreadingPatcher/Plugins/SystemThreadingTimer.jslib
+++ b/Assets/Thirdweb/Plugins/ThreadingPatcher/Plugins/SystemThreadingTimer.jslib
@@ -15,7 +15,7 @@ var SystemThreadingTimerLib = {
setTimeout(function()
{
if (id === vars.currentCallbackId)
- Runtime.dynCall('v', vars.callback);
+ {{{ makeDynCall("v", "vars.callback") }}}();
},
interval);
}
diff --git a/Assets/Thirdweb/Plugins/WalletConnectUnity/com.walletconnect.core/Runtime/External/NativeWebSocket/WebSocket.jslib b/Assets/Thirdweb/Plugins/WalletConnectUnity/com.walletconnect.core/Runtime/External/NativeWebSocket/WebSocket.jslib
index 052f213..4fbe458 100644
--- a/Assets/Thirdweb/Plugins/WalletConnectUnity/com.walletconnect.core/Runtime/External/NativeWebSocket/WebSocket.jslib
+++ b/Assets/Thirdweb/Plugins/WalletConnectUnity/com.walletconnect.core/Runtime/External/NativeWebSocket/WebSocket.jslib
@@ -150,7 +150,7 @@ var LibraryWebSocket = {
console.log("[JSLIB WebSocket] Connected.");
if (webSocketState.onOpen)
- Module.dynCall_vi(webSocketState.onOpen, instanceId);
+ {{{ makeDynCall("vi", "webSocketState.onOpen") }}}(instanceId);
};
@@ -170,7 +170,7 @@ var LibraryWebSocket = {
HEAPU8.set(dataBuffer, buffer);
try {
- Module.dynCall_viii(webSocketState.onMessage, instanceId, buffer, dataBuffer.length);
+ {{{ makeDynCall("viii", "webSocketState.onMessage") }}}(instanceId, buffer, dataBuffer.length);
} finally {
_free(buffer);
}
@@ -182,7 +182,7 @@ var LibraryWebSocket = {
HEAPU8.set(dataBuffer, buffer);
try {
- Module.dynCall_viii(webSocketState.onMessage, instanceId, buffer, dataBuffer.length);
+ {{{ makeDynCall("viii", "webSocketState.onMessage") }}}(instanceId, buffer, dataBuffer.length);
} finally {
_free(buffer);
}
@@ -204,7 +204,7 @@ var LibraryWebSocket = {
stringToUTF8(msg, buffer, length);
try {
- Module.dynCall_vii(webSocketState.onError, instanceId, buffer);
+ {{{ makeDynCall("vii", "webSocketState.onError") }}}(instanceId, buffer);
} finally {
_free(buffer);
}
@@ -219,7 +219,7 @@ var LibraryWebSocket = {
console.log("[JSLIB WebSocket] Closed.");
if (webSocketState.onClose)
- Module.dynCall_vii(webSocketState.onClose, instanceId, ev.code);
+ {{{ makeDynCall("vii", "webSocketState.onClose") }}}(instanceId, ev.code);
delete instance.ws;
diff --git a/Assets/Thirdweb/Plugins/WebGLInputCopy/WebGLInput/Mobile/WebGLInputMobile.jslib b/Assets/Thirdweb/Plugins/WebGLInputCopy/WebGLInput/Mobile/WebGLInputMobile.jslib
index c3fc619..8fdfde3 100644
--- a/Assets/Thirdweb/Plugins/WebGLInputCopy/WebGLInput/Mobile/WebGLInputMobile.jslib
+++ b/Assets/Thirdweb/Plugins/WebGLInputCopy/WebGLInput/Mobile/WebGLInputMobile.jslib
@@ -6,7 +6,7 @@ var WebGLInputMobile = {
document.body.addEventListener("touchend", function () {
document.body.removeEventListener("touchend", arguments.callee);
- Runtime.dynCall("vi", touchend, [id]);
+ {{{ makeDynCall("vi", "touchend") }}}(id);
});
return id;
@@ -14,7 +14,7 @@ var WebGLInputMobile = {
WebGLInputMobileOnFocusOut: function (id, focusout) {
document.body.addEventListener("focusout", function () {
document.body.removeEventListener("focusout", arguments.callee);
- Runtime.dynCall("vi", focusout, [id]);
+ {{{ makeDynCall("vi", "focusout") }}}(id);
});
},
}
diff --git a/Assets/Thirdweb/Plugins/WebGLInputCopy/WebGLInput/WebGLInput.jslib b/Assets/Thirdweb/Plugins/WebGLInputCopy/WebGLInput/WebGLInput.jslib
index a17092d..62055cb 100644
--- a/Assets/Thirdweb/Plugins/WebGLInputCopy/WebGLInput/WebGLInput.jslib
+++ b/Assets/Thirdweb/Plugins/WebGLInputCopy/WebGLInput/WebGLInput.jslib
@@ -1,19 +1,6 @@
var WebGLInput = {
$instances: [],
WebGLInputInit : function() {
- // use WebAssembly.Table : makeDynCall
- // when enable. dynCall is undefined
- if(typeof dynCall === "undefined")
- {
- // make Runtime.dynCall to undefined
- Runtime = { dynCall : undefined }
- }
- else
- {
- // Remove the `Runtime` object from "v1.37.27: 12/24/2017"
- // if Runtime not defined. create and add functon!!
- if(typeof Runtime === "undefined") Runtime = { dynCall : dynCall }
- }
},
WebGLInputCreate: function (canvasId, x, y, width, height, fontsize, text, placeholder, isMultiLine, isPassword, isHidden, isMobile) {
@@ -112,7 +99,7 @@ var WebGLInput = {
input.setSelectionRange(start + 1, start + 1);
input.oninput(); // call oninput to exe ValueChange function!!
} else {
- (!!Runtime.dynCall) ? Runtime.dynCall("vii", cb, [id, e.shiftKey ? -1 : 1]) : {{{ makeDynCall("vii", "cb") }}}(id, e.shiftKey ? -1 : 1);
+ {{{ makeDynCall("vii", "cb") }}}(id, e.shiftKey ? -1 : 1);
}
}
});
@@ -124,13 +111,13 @@ var WebGLInput = {
WebGLInputOnFocus: function (id, cb) {
var input = instances[id];
input.onfocus = function () {
- (!!Runtime.dynCall) ? Runtime.dynCall("vi", cb, [id]) : {{{ makeDynCall("vi", "cb") }}}(id);
+ {{{ makeDynCall("vi", "cb") }}}(id);
};
},
WebGLInputOnBlur: function (id, cb) {
var input = instances[id];
input.onblur = function () {
- (!!Runtime.dynCall) ? Runtime.dynCall("vi", cb, [id]) : {{{ makeDynCall("vi", "cb") }}}(id);
+ {{{ makeDynCall("vi", "cb") }}}(id);
};
},
WebGLInputIsFocus: function (id) {
@@ -143,7 +130,7 @@ var WebGLInput = {
var bufferSize = lengthBytesUTF8(returnStr) + 1;
var buffer = _malloc(bufferSize);
stringToUTF8(returnStr, buffer, bufferSize);
- (!!Runtime.dynCall) ? Runtime.dynCall("vii", cb, [id, buffer]) : {{{ makeDynCall("vii", "cb") }}}(id, buffer);
+ {{{ makeDynCall("vii", "cb") }}}(id, buffer);
};
},
WebGLInputOnEditEnd:function(id, cb){
@@ -153,7 +140,7 @@ var WebGLInput = {
var<br/>
**Fix non-future-proof invocations of Emscripten dynCalls: Q&A**
===========================================================
**Q: What is the problem with the current invocations of Emscripten dynCalls?**
--------------------------------------------------------------------------------
A: The current invocations of Emscripten dynCalls are not future-proof and are not compatible with newer Emscripten versions (3.1.38 and newer). This is because legacy dynCall() functions in new Emscripten versions require declaring a `__deps` directive, which was not present in the current invocations.
**Q: What is the solution to fix the non-future-proof invocations of Emscripten dynCalls?**
--------------------------------------------------------------------------------
A: The solution is to use the new syntax for invoking dynCalls, which is more future-proof and compatible with newer Emscripten versions. This can be achieved by replacing the current invocations with the new syntax, which uses the `{{{ makeDynCall('signature', 'functionCallback') }}}` function.
**Q: What is the new syntax for invoking dynCalls?**
------------------------------------------------
A: The new syntax for invoking dynCalls is as follows:
```javascript
{{{ makeDynCall('signature', 'functionCallback') }}}(...args);
Where signature
is the signature of the function being called, and functionCallback
is the name of the function being called.
Q: How do I apply the changes to my project?
A: To apply the changes to your project, you need to replace the current invocations of Emscripten dynCalls with the new syntax. This can be done by searching for the current invocations in your project and replacing them with the new syntax.
Q: What are the benefits of using the new syntax for invoking dynCalls?
A: The benefits of using the new syntax for invoking dynCalls are:
- It is more future-proof and compatible with newer Emscripten versions.
- It provides better performance and efficiency.
- It is easier to use and understand.
Q: Are there any potential issues or limitations with using the new syntax for invoking dynCalls?
A: Yes, there are potential issues or limitations with using the new syntax for invoking dynCalls. These include:
- The new syntax may not be compatible with older Emscripten versions.
- The new syntax may require additional changes to your project.
- The new syntax may have different performance characteristics than the current invocations.
Q: How do I ensure that my project is compatible with the new syntax for invoking dynCalls?
A: To ensure that your project is compatible with the new syntax for invoking dynCalls, you should:
- Test your project with the new syntax to ensure that it works correctly.
- Verify that your project is compatible with the new syntax by checking for any errors or warnings.
- Make any necessary changes to your project to ensure that it is compatible with the new syntax.
Q: What is the recommended approach for updating my project to use the new syntax for invoking dynCalls?
A: The recommended approach for updating your project to use the new syntax for invoking dynCalls is to:
- Start by testing your project with the new syntax to ensure that it works correctly.
- Gradually update your project to use the new syntax, starting with the most critical components.
- Verify that your project is compatible with the new syntax by checking for any errors or warnings.
- Make any necessary changes to your project to ensure that it is compatible with the new syntax.