Search code examples
javascriptnode.jsflatbuffers

flatbuffers is not defined


I'm writing a nodeJs application that uses google flat buffer.

I installed flatc on my macbook pro and compiled the following schema:

namespace MyAlcoholist;

table Drink {
 drink_type_name: string;
 drink_company_name: string;
 drink_brand_name: string;
 drink_flavor_type_name : string;
 liquid_color_type_name : string;
 liquid_color_is_transparent : bool;
 alcohol_vol : float;
 calories_for_100g : uint;
 global_image_id: ulong;
 drink_flavor_id: ulong;
}

table Drinks { drinks:[Drink]; }

root_type Drinks;

the schema file is called drink.fbs and it generated a javascript file called drink_generated.js

I include this file in my nodejs application and add data to it using the following code.. this is my flatBufferUtil.js utility file.

var flatbuffers = require('../js/flatbuffers').flatbuffers;
var builder = new flatbuffers.Builder();

var drinks = require('../fbs/drinks_generated').MyAlcoholist; // Generated by `flatc`.

function drinkArrayToBuffer(drinkArray) {
var drinksVectArray = [];
drinkArray.forEach(function (element, index, array) {
    var drinkObj = element;
    var drinkBrandName = builder.createString(drinkObj.drink_brand_name);
    var drinkCompanyName = builder.createString(drinkObj.drink_company_name);
    var drinkflavorTypeName = builder.createString(drinkObj.drink_flavor_type_name);
    var drinkTypeName = builder.createString(drinkObj.drink_type_name);
    var liquidColorTypeName = builder.createString(drinkObj.liquid_color_type_name);
    drinks.Drink.startDrink(builder);
    drinks.Drink.addAlcoholVol(builder, drinkObj.alcohol_vol);
    drinks.Drink.addCaloriesFor100g(builder,drinkObj.calories_for_100g);
    drinks.Drink.addDrinkBrandName(builder,drinkBrandName);
    drinks.Drink.addDrinkCompanyName(builder,drinkCompanyName);
    drinks.Drink.addDrinkFlavorId(builder,drinkObj.drink_flavor_id);
    drinks.Drink.addDrinkFlavorTypeName(builder, drinkflavorTypeName);
    drinks.Drink.addDrinkTypeName(builder,drinkTypeName);
    drinks.Drink.addGlobalImageId(builder,drinkObj.global_image_id);
    drinks.Drink.addLiquidColorIsTransparent(builder,drinkObj.is_transparent);
    drinks.Drink.addLiquidColorTypeName(builder,liquidColorTypeName);
    var drink = drinks.Drink.endDrink(builder);
    drinksVectArray.push(drink);
})
var drinksVect = drinks.createDrinksVector(builder,drinksVectArray);
builder.finish(drinksVect);
var buf = builder.dataBuffer();
return buf;
}

module.exports.drinkArrayToBuffer=drinkArrayToBuffer;

now when I execute this function it fails with the error flatbuffers is not defined.

I debugged my code and I saw that it files on the following line of code:

    drinks.Drink.addDrinkFlavorId(builder,drinkObj.drink_flavor_id);

if i get inside addDrinkFlavorId function i see this code in drinks_generted.js:

MyAlcoholist.Drink.addDrinkFlavorId = function(builder, drinkFlavorId) {
   builder.addFieldInt64(9, drinkFlavorId, flatbuffers.Long.ZERO);
};

as you can see it uses flatbuffers.Long.ZERO but flatbuffers is not defined in that file at all. the compilation did not provide any errors so what do I miss?


Solution

  • It seems to me like it is a bug... The generated file appears to be meant to exist autonomously from the flatbuffers require. However for the custom flatbuffers.Long class, the default of flatbuffers.Long.ZERO bleeds into the generated file.

    While this isn't a solution per-say, one workaround is to manually add the flatbuffers require to the generated file; it's ugly, but it might be better than being blocked until a more appropriate answer (or fix) comes around.

    // In `drinks_generated.js`
    var flatbuffers = require('../js/flatbuffers').flatbuffers;
    

    Note:

    The drinks.Drink.addDrinkFlavorId() and drinks.Drink.addGlobalImageId() functions expect flatbuffers.Long values to be passed into them, because they were specified as ulong in the schema (fbs file). So you will need to ensure that you are not trying to pass in a simple number type.

    For example:

    var my_long = flatbuffers.Long(100, 0); // low = 100, high = 0
    drinks.Drink.addDrinkFlavorId(builder, my_long);
    

    As a result, another possible workaround is to change the datatype of those fields in the schema to avoid using ulong until it becomes more clear what is going on here.

    P.S. I am pretty sure drinks.createDrinksVector on line 30 of that snippet should be drinks.Drinks.createDrinksVector.