Search code examples
javascriptnode.jsnw.jsliquidfun

Using liquidfun.js within nw.js


I am writing an application that uses two components that appear to be conflicting with each other.

liquidfun.js and node.js/NW.js

I am using liquidfun to do a fluid simulation. I am using window.get() in NW.js to set the window zoom level. Each works without the other.

Here is the error when I run both simultaneously.

Uncaught ReferenceError: module is not defined      liquidfun.js:3
Uncaught TypeError: undefined is not a function      liquidfun.js:1443

I suspect that node has some function property that shared the name "module" with something in the liquidfun library.

How do I prevent NW.js from processing the liquidfun script?

Additional Information:

The pages are being served from a xampp server on the same computer so I have to use "node-remote" to set the zoom level.

EDIT:

HTML that is loaded by nw.js

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>html5canvas</title>


<script src="libs/liquidfun.js"></script>
<script>
    var gui = require('nw.gui');
    win = gui.Window.get();
    win.zoomLevel =[-10];

</script>
</head>

<body onload="init();" style="background-color:#D4D4D4">
            <canvas id="canvas" width="2160" height="3840" style="background-color:#B1D1B1"></canvas>

</body>
<script>
    var world = null;
    var gravity = new b2Vec2();
    function init(){

        world = new b2World(gravity);

    }
</script>

NW.js Package.json

{

    "main": "main.html",
    "name": "Fun Editor",
    "node-remote" : "127.0.0.1"

}

The result of this is the module error mentioned in original post. When node-remote is removed liquid fun reports loading succesfully. There is another error without node-remote

UncaughtReferenceError: require is not defined    (program):1 

Solution

  • The problem is that liquidfun first evaluates the evironment it's running on and since require is defined, it expects module and exports to be so as well. As a particularity of nw.js this won't be true. So you need to require your library like this instead:

    <script>
        var lf      = require("./libs/liquidfun.js");
        var world   = null;
        var gravity = new lf.b2Vec2();
    
        function init(){
            world = new lf.b2World(gravity);
        }
    </script>
    

    Now, while this will do for almost all cases, won't help on it's own in this case since liquidfun doesn't seem to be exporting the necessary classes (I'm not familiar with this library so there might be a way of doing so). Following this answer, you could just add the necessary exports at the end of the library:

    module.exports = {
        b2Vec2         : b2Vec2,
        b2BodyDef      : b2BodyDef,
        b2PolygonShape : b2PolygonShape,
        b2FixtureDef   : b2FixtureDef,
        b2World        : b2World,
        b2_dynamicBody : b2_dynamicBody,
        setWorld       : function(_world){ world=_world;   }
    };
    

    Another way of approaching this (since you need to edit liquidfun.js anyway) would be tricking the library into running in regular web mode. You can accomplish this by replacing this bit in the first line:

    ...process==="object"&&typeof require==="function";...
    

    with this:

    ...process==="object"&&false;...
    

    You can then use the library as expected:

    <script src="libs/liquidfun.js"></script>
    <script>
        var world   = null;
        var gravity = new b2Vec2();
        function init(){
            world = new b2World(gravity);
        }
    </script>
    

    Needless to say, both solutions are a bit "hacky" and not quite optimal.