Emscripten triggers spurious function calls - javascript

I'm trying to get myself used to emscripten, and I have to admit that my JS is quite rusty. Anyway, as a start, I tried to compile
#include <vector>
extern "C" {
int add(int a, int b){
return a+b;
}
}
with emscripten: em++ test.cpp -sEXPORTED_FUNCTIONS=_add -sEXPORTED_RUNTIME_METHODS=ccall,cwrap. I wrote the following basic HTML page:
<!DOCTYPE html>
<html>
<head>
<script src="a.out.js"></script>
<script>
function run(){
alert("Run!");
var add = cwrap("add", "number", ["number"]);
var result = add(12, 13);
document.getElementById('output').value = result;
}
</script>
</head>
<body>
<button onclick="run();">Run!</button>
<input id="output">
</body>
</html>
The strange thing is than run() is called immediately on loading the page, which firefox unsurprisingly does not like:
Uncaught (in promise) RuntimeError: Aborted(Assertion failed: native function `add` called before runtime initialization)
and is not intended anyway. If I remove the line
<script src="a.out.js"></script>,
then the spurious call to run() disappears. Of course, this renders the page dysfunctional.
How to do it properly?
I am using Firefox 107.0.1 (MacOS) and em++ 3.1.28-git from Homebrew.

Emscripten creates hundreds of variable and function into the global namespace by default, and run is one of them.
MODULARIZE prevents namespace polution.
em++ test.cpp -sEXPORTED_FUNCTIONS=_add -sEXPORTED_RUNTIME_METHODS=ccall,cwrap -sMODULARIZE -s 'EXPORT_NAME="createModule"'
And use that module.
<!DOCTYPE html>
<html>
<head>
<script src="a.out.js"></script>
<script>
var module = null;
var add = null;
createModule().then(m => {
module = m;
add = module.cwrap("add", "number", ["number"]);
});
function run(){
alert("Run!");
var result = add(12, 13);
document.getElementById('output').value = result;
}
</script>
</head>
<body>
<button onclick="run();">Run!</button>
<input id="output">
</body>
</html>

Related

Localhost not loading module

I am using modern Javascript MyClass.js
export default class MyClass {
constructor(x) {
this.val=x? x: "Hello!"
console.log("MyClass:",x)
}
}
at my http://localhost/myfolder/mypage.htm, with the source below,
<!DOCTYPE html>
<html>
<head>
<title>test</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel='shortcut icon' type='image/x-icon' href='./favicon.ico' />
<script type="module" src="./MyClass.js"></script>
<script>
'use strict';
document.addEventListener('DOMContentLoaded', function(){
alert(123)
let x = new MyClass(11);
}, false); //ONLOAD
</script>
</head>
<body> <p>Hello1!</p> </body>
</html>
Why console say "Uncaught ReferenceError: MyClass is not defined"?
PS: this question is a complement for this other about using ES6+ with browser+NodeJs.
NOTE: using UBUNTU ith Apache's Localhost... Some problem with myfolder a symbolic link to real folder? at /var/www/html I used ln -s /home/user/myRealFolder/site myfolder
you need to import the module before using it
<!DOCTYPE html>
<html>
<head>
<title>test</title>
<meta charset="utf-8" />
<script type="module" src="./MyClass.js"></script>
<script type="module" id="m1">
// script module is an "island", not need onload.
'use strict';
import MyClass from './MyClass.js';
let x = new MyClass(11); // we can use here...
console.log("debug m1:", x) // working fine!
window.MyClassRef = MyClass; // "globalizing" class
window.xRef = x // "globalizing" instance
</script>
<script> // NON-module global script
document.addEventListener('DOMContentLoaded',function(){
// only works after all modules loaded:
console.log("debug:", window.xRef) // working fine!
let x = new window.MyClassRef(22); // using class also here,
console.log("debug:", x) // working fine!
}, false); //ONLOAD
</script>
</head>
<body> <p>Hello1!</p> </body>
</html>
There are two ways to use an imported class:
at module scope (script m1): you can use new MyClass(), and can "globalize" instances (e.g. xRef) or the costructor's class (MyClassRef).
at global scope: to work together other libraries or with main script, use a global reference, e.g. new window.MyClassRef().
All this solution relies upon "static import"...
Optional dynamic import
You can use also import with ordinary default <script> (no type="module"), and no "onload", using this solution, instead the last script:
<script>
'use strict';
import('./MyClass.js').then(({default: MyClass}) => {
alert(123) // async block
let x = new MyClass(11);
});
</script>
See dynamic import.

Calling function from external .js file, nothing happens

I have a really basic JavaScript project, I'm just testing out and learning the language. All I want the program to do is launch and call a function inside the external main.js file. At the moment nothing happens on launch.
I have tried copying examples given online but they don't seem to be working for me.
HTML File:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Cex_Program</title>
<link href="css/default.css" rel="stylesheet" />
</head>
<body>
<div>Content goes here!</div>
<script src="js/main.js"></script>
<script>
Main();
</script>
</body>
</html>
JavaScript file:
Content of function is irrelevant, I just want the program flow to enter the function (hit my breakpoint);
// Your code here!
var InfiniteLoop = 1;
var DeltaTime = 0;
function Main()
{
var Day = new Date();
var StartTime = Math.round(new Date() / 1000);
var StartCurrentLoopTime = 0;
var EndCurrentLoopTime = 0;
}
This does work
<!DOCTYPE html>
<html>
<body>
<div>Content goes here!</div>
<script>function Main( str ) { console.log( str ); }</script>
<script>
Main( "Main!" );
</script>
</body>
</html>
So
We can deduce from this that either js/main.js is not being downloaded, the function Main() is inaccessible to a <script> outside it or that Main() simply doesn't function or produce a discernable result.
See this w3schools tutorial about scopes for more details on why Main() might be inaccessible.
Check your browser's console for errors in the case of Main() not functioning.
FireFox: https://developer.mozilla.org/en/docs/Tools/Browser_Console
Chrome: https://developers.google.com/web/tools/chrome-devtools/console/
I will happily update this answer as needed in response to positive feedback.
To test if Main() is accessible
Check if Main() is a global function by finding out if window.hasOwnProperty( "Main" ) before typing to use it.
<!DOCTYPE html>
<html>
<body>
<div>Content goes here!</div>
<script>
( function() {
function Main( str ) { console.log( str ); }
} () );
function Alt( str ) { console.log( str ); }
</script>
<script>
if ( window.hasOwnProperty( "Main" ) ) {
Main( "Main!" );
} else {
console.error( "Main() can't be accessed from here" );
if ( window.hasOwnProperty( "Alt" ) ) {
Alt( "Alt!" );
}
}
</script>
</body>
</html>
I created your setup on my dev machine and loaded the html page. Assuming the files are named correctly on your machine, I can confirm that the code did execute.
A good way to check if JavaScript is running correctly in the browser is to use a debugger:
Google Chrome
Mozilla Firefox
Microsoft Edge/IE
Apple Safari

Javascript immediate function call from external function

I am trying to call the immediate function defined in test1.js on click of the button defined under html file. It always throws error "test is undefined". I am little bit aware that being a immediate function, it calls immediately, and so it returns the "undefined error". But is there any way I can call the immediate function (access methods, properties, etc.) on click of the button?
Thank you in advance.
//test1.js
var test = (function(){
alert(window);
var tmp = 'hello';
}());
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script type="text/javascript" src="test1.js"></script>
<input type="button" id="btn1" value="ClickMe!" />
<script type="text/javascript">
var btn = document.getElementById("btn1");
btn.addEventListener("click",fun1,false);
function fun1(){
alert(test.tmp);
}
</script>
</body>
</html>
You have to modify your code so that the IIFE returns an object with a tmp property. Such as
var test = (function(){
alert(window);
var tmp = 'hello';
return {tmp:tmp};
}());
You need to explicitly return an object containing any data you want made available after you run the IIFE. (Just add the return as I did to the snippet below).
//test1.js
var test = (function(){
alert(window);
// you need to return any values you want accessible
return {
tmp: "hello"
}
}());
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script type="text/javascript" src="test1.js"></script>
<input type="button" id="btn1" value="ClickMe!" />
<script type="text/javascript">
var btn = document.getElementById("btn1");
btn.addEventListener("click",fun1,false);
function fun1(){
alert(test.tmp);
}
</script>
</body>
</html>

cordova 2.0.0 gives Uncaught TypeError: Object 0 has no method 'func'

I have created an application in cordova2.0.0,where i am calling native functions(written in c) from the java script with the help of cordova.
Previously i was doing with phonegap 1.0.0 in which the application is working properly.but when i updated it to cordova 2.0.0, i am getting the error
08-07 15:24:12.527: I/Web Console(855): JSCallback Error: Request failed. at file:///android_asset/www/cordova-2.0.0.js:3698
08-07 15:22:27.815: E/Web Console(855): Uncaught TypeError: Object 0 has no method 'func' at file:///android_asset/www/file.js:359
can any one please help me out in this problem.
code of my .html file:
<!DOCTYPE html>
<head>
<script type="text/javascript" charset="utf-8" src="cordova2.0.0.js"></script>
<script type="text/javascript" charset="utf-8" src="find.js"></script>
<script type="text/javascript">
function js_find(fthisval){
ws_find(socket,js_found);
}
function js_found(retval){
alert(retval);
}
function onBodyLoad(){
document.addEventListener("deviceready",onDeviceReady,false);
}
function onDeviceReady()
{
document.getElementById('d1').style.visibility = "visible";
}
</script>
</head>
<body onload="onBodyLoad()">
<div id="d1" style="visibility:hidden">
<button id="b1" onclick="js_find("ram")">Find it plz</button><br />
</div>
</body>
in find.js:
var Find = function() {};
Find.prototype.func = function(funcname,funcdata) {
return cordova.exec(
null,
null,
'findPlugin',
funcname,
funcdata);
};
window.find = new Find();
function ws_find(name, param, callback){
if(undefined == callback){
var dataArray = [param, param, name];
}
else{
var dataArray = [callback, callback, name, param];
}
alert("Calling plugin function find with \r\n"+dataArray);
return window.find.func("find",dataArray);
}
the line return window.find.func("find",dataArray);was suppossed to call the native java function,but it is giving me the above errors.
Works Fine for me
Tested on Ice-Cream Sandwich and GingerBread (you may require to restructure removing the switch and having whichever option you like)
Try Debugging your version with Alerts to see till where it goes.
Also do you need to return from cordova.exec?
<!DOCTYPE HTML>
<html>
<head>
<title>Cordova</title>
<script type="text/javascript" charset="utf-8" src="cordova-2.0.0.js"></script>
<script type="text/javascript" charset="utf-8">
function callPlugin(type){
switch(type){
case 1:
//Func Ptr
window.echo = function(str, callback) {
cordova.exec(callback, function(err) { callback('Nothing to echo.'); }, "Echo", "echo", [str]);
};
//Func Call
window.echo("echome", function(echoValue){alert(echoValue);} );
break;
case 2:
var MyClass = function (){}; //Prototype
MyClass.prototype.echo = function(str, callback) {
cordova.exec(callback, function(err) { callback('Nothing to echo.'); }, "Echo", "echo", [str]);
};
window.echo = new MyClass();
window.echo.echo("echome2", function(echoValue){alert(echoValue);} );
//OR
//window.echo = new MyClass().echo; //Add Function to Window Object
//window.echo("echome1", function(echoValue){alert(echoValue);} ); //Call Plugin
break;
}
}
</script>
</head>
<body>
<h1>Plugin Test</h1>
<button onclick="callPlugin(1)">Call Plugin by Cordova 2.0.0 Method</button><br />
<button onclick="callPlugin(2)">Call Plugin by Cordova 1.0.0 Method</button><br />
</body>
</html>

javascript error with label

I have a function as follows:
function textNext(element, num) {
document.getElementById("lblContent").innerHTML = "hello";
}
However, the text of the lblContent label won't change when the function is called.
What am I doing wrong?
btw : lblContent is of type asp:Label
Since lblControl is a server side ASP.NET control, you will need to use the control ClientID property in order to use it in javascript:
function textNext(element, num) {
document.getElementById(<"%=lblContent.ClientID%>").innerHTML = "hello";
}
Check the console in your browser for errors. I tried to reproduce your problem in a standard HTML/Javascript environment.
This works for me.
<html>
<head>
<title>Test</title>
<head>
<body>
<div id="lblContent">Previous text</div>
Change text
<script type="text/javascript">
function textNext() {
document.getElementById("lblContent").innerHTML = "Next text";
}
</script>
</body>
</html>

Categories