Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Maximum call stack exceeded when instantiating class inside of a module

My console.log on line 7 prints out fine.

host.js

"use strict";

var engine = require('./engine.js');
var base = require('./base.js');

var player = new base.Avatar();
console.log(player.x);

class PillarGame extends engine.ServerGame {
    connectPlayer(socket) {
        var player = new base.Avatar();
        this.add('players', player);
        console.log("added player");
        //announce
    }   
}

module.exports = {'HostedGame' : PillarGame};

But I get this crash in my server after creating that object and emitting:

        if (obj.hasOwnProperty(key) && _hasBinary(obj[key])) {
                ^

RangeError: Maximum call stack size exceeded
    at Object.hasOwnProperty (native)

Why is this crashing?

base.js has no requires.

Stacktrace:

listening
connected
added player
/Users/quantum/code/online/node_modules/socket.io/node_modules/has-binary-data/index.js:0
(function (exports, require, module, __filename, __dirname) { /*

RangeError: Maximum call stack size exceeded
    at _hasBinary (/Users/quantum/code/online/node_modules/socket.io/node_modules/has-binary-data/index.js:24:22)
    at _hasBinary (/Users/quantum/code/online/node_modules/socket.io/node_modules/has-binary-data/index.js:37:15)
    at _hasBinary (/Users/quantum/code/online/node_modules/socket.io/node_modules/has-binary-data/index.js:47:40)
    at _hasBinary (/Users/quantum/code/online/node_modules/socket.io/node_modules/has-binary-data/index.js:47:40)
    at _hasBinary (/Users/quantum/code/online/node_modules/socket.io/node_modules/has-binary-data/index.js:47:40)
    at _hasBinary (/Users/quantum/code/online/node_modules/socket.io/node_modules/has-binary-data/index.js:37:15)
    at _hasBinary (/Users/quantum/code/online/node_modules/socket.io/node_modules/has-binary-data/index.js:47:40)
    at _hasBinary (/Users/quantum/code/online/node_modules/socket.io/node_modules/has-binary-data/index.js:47:40)
    at _hasBinary (/Users/quantum/code/online/node_modules/socket.io/node_modules/has-binary-data/index.js:47:40)
    at _hasBinary (/Users/quantum/code/online/node_modules/socket.io/node_modules/has-binary-data/index.js:37:15)

server.js, crashes on socket.emit("game.things", game.things);

var express = require('express');
var path = require('path');
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io')(server);
var logic = require('./logic');
var hostedGame = require('./host');

var game = new hostedGame.HostedGame({'sockets' : io.sockets});

app.use(express.static(path.join(__dirname, 'public')));
server.listen(3000, function() {
  console.log('listening');
});


io.on('connection', function(socket) {
  console.log('connected'); //extrac

  game.connectPlayer(socket);

  //console.log("game.things['players']" + game.things['players']);;
  socket.emit("game.things", game.things);

  // socket.on('input', function(data) {
  //   game.input(socket, data);
  // });
});

var loopAsync = function() {
  setTimeout(loop, 10);
  //setImmediate(loop);
}

var now = Date.now();
var last = now;
var dt = 0.00;
var rate = 10;

function loop() {
  now = Date.now();
  var delta = now - last;
  last = now;

  dt = dt + delta;

  if (dt < rate) {
    loopAsync();
    return;
  } else {
    dt -= rate;
    //if dt still > rate, repeat the following while true
    var updates = game.loop();
    //emit things
    io.sockets.emit('player-positions', logic.players);
    //io.to specific player
    loopAsync();
  }

}

loopAsync();

base.js

"use strict";

class Component {
    defaultMaxCharge() {
        return [0];
    }

    constructor(options) {
        options = options || {};
        this.charge = [0];
        if (options['maxCharge']) {
            this.maxCharge = options['maxCharge'];
        } else {
            this.maxCharge = this.defaultMaxCharge();
        }

    }

    loop() {

    }

    getValue(name, hash) {
        return hash;
    }   
}

class Looper extends Component {
    registrationNames() {
        return ['loop'];
    }
}

class Mover extends Looper {
    loop() {
        var velocity = this.thing.getValue('velocity');
        var speed = this.thing.getValue('speed')['speed'];

        var total = Math.abs(velocity.vx) + Math.abs(velocity.vy);
        if (total <= 0) {
            return;
        }

        var xx = velocity.mx / total * this.speedMod();
        var yy = velocity.my / total * this.speedMod();

        this.thing.x = this.thing.x + xx * speed;
        this.thing.y = this.thing.y + yy * speed;
        this.thing.x += velocity.vx;
        this.thing.y += velocity.vy; //announce
    }
}

//input components

class XWalker extends Component {
    constructor(options) {
        super(options);
        this.vx = 0;
    }

    registrationNames() {
        return ['input', 'velocity'];
    }

    getValue(name, hash) {
        if (name == 'velocity') {
            hash.vx = this.vx; //times speed
        }

        return hash;
    }

    processEvent(name, eventer, hash) {
        if (name == 'input') {
            if (hash.left) {
                this.vx = -1;
            } else if (hash.right) {
                this.vx = 1;
            } else {
                this.vx = 0;
            }
        }
    }
}

class YWalker extends Component {
    constructor(options) {
        super(options);
        this.vx = 0;
    }

    registrationNames() {
        return ['input', 'velocity'];
    }

    getValue(name, hash) {
        if (name == 'velocity') {
            hash.vy = this.vy; //times speed
        }

        return hash;
    }

    processEvent(name, eventer, hash) {
        if (name == 'input') {
            if (hash.up) {
                this.vy = -1;
            } else if (hash.down) {
                this.vy = 1;
            } else {
                this.vy = 0;
            }
        }
    }
}

class Thing {
    spawnComponents(options) {
        return [];
    }

    installComponents(options) {
        this.componentRegistrations = {};
        this.components = [];

        var comps = this.spawnComponents(options);
        for (var i = 0; i < comps.length; i++) {
            var component = comps[i];
            component.thing = this;
            this.registerComponent(component);

            this.components.push(component);
        }
    }

    registerComponent(component) {
        for (var i = 0; i < component.registrationNames().length; i++) {
            var eventName = component.registrationNames()[i];
            if (!this.componentRegistrations[eventName]) {
                this.componentRegistrations[eventName] = [];
            }

            this.componentRegistrations[eventName].push(component);
        }
    }

    getValue(name) {
        var registered = this.componentRegistrations[name];
        if (registered) {
            var valueHash = {};
            for (var i = 0; i < registered.length; i++) {
                var component = registered[i];
                valueHash = component.getValue(name, valueHash);
                if (valueHash.stop) {
                    return valueHash;
                }
            }

            return valueHash;
        }
    }

    processEvent(name, eventer, hash) {
        var registered = this.componentRegistrations[name];
        if (registered) {
            for (var i = 0; i < registered.length; i++) {
                var component = registered[i];
                component.processEvent(name, eventer, hash);
            }
        }
    }

    constructor(options) {
        if (options && options['position']) {
            this.x = options['position'].x * this.canvas.width;
            this.y = options['position'].y * this.canvas.height;
        } else {
            this.x = 2.0;
            this.y = 2.0;   
        }

        this.installComponents(options);
        this.active = true;
    }

    loop() {
        for (var i = 0; i < this.components.length; i++) {
            var component = this.components[i];
            component.loop();
        }
    }   

    afterLoop() {

    }

    position() {
        return {'x' : this.x, 'y' : this.y};
    }
}

class Avatar extends Thing {
    spawnComponents(options) {
        return [new Mover(), new XWalker(), new YWalker()];
    }
}

module.exports = {'Component' : Component, 'Thing' : Thing,
'Mover' : Mover, 'Looper' : Looper, 'XWalker' : XWalker, 'YWalker' : YWalker,
'Avatar' : Avatar};
like image 327
quantumpotato Avatar asked Dec 15 '15 00:12

quantumpotato


People also ask

How do I fix error in maximum call stack size exceeded?

The most common source for this error is infinite recursion. You must have a recursive function in your code whose base case is not being met and is, therefore, calling the function again and again until you hit the call stack limit.

What does it mean when it says maximum call stack size exceeded?

The JavaScript RangeError: Maximum call stack size exceeded is an error that occurs when there are too many function calls, or if a function is missing a base case.

How do I fix maximum call stack size exceeded see JavaScript console for details?

The "RangeError: Maximum call stack size exceeded" error occurs when a function is called so many times that the invocations exceed the call stack limit. To solve the error, specify a base case that has to be met to exit the recursion.

What is the limit of a call stack?

Without any local variables, each function call takes up 48 bytes during the execution, and you are limited to less than 1MB for all local function frames. Each boolean and number variable takes 8 bytes of memory.


1 Answers

server.js, crashes on socket.emit("game.things", game.things);

Most likely game.things is an complex object with circular references which socket.io is trying to convert to JSON before emitting out, and failing.

like image 198
laggingreflex Avatar answered Oct 11 '22 05:10

laggingreflex