VytPil
VytPil

Reputation: 126

Javascript code output differs when ran from node.js shell and from a file

I have this strange behavior of node.js. Basically the title says it all, I would only like to add, that this wasn't the case before, with the exactly the same code. I suspect that this started to happen after I ran sudo chown -R $USER /usr/local/lib/node_modules because I wanted to install typescript and got writing permissions error, however I cannot be 100% sure. Interestingly enough my test passes, and eventually everything works fine and the result is correct, but I don't know why my console.log() outputs are different. What I get when I put code in node shell and console.log it is a concatenated string from recursive calls. When I run code from a file, I only get the string from the first call. Here's my code:

const fields = {
    0: "D:0:0:0:1:20:9",
    1: "D:1:0:22:1:95:9",
    2: "D:2:0:117:1:27:9"
};

function getRequiredFields(key, trailing=false) {
    // key is a number
    if (typeof trailing !== "boolean") {
        throw new Error("<trailing> must be of type 'boolean'. Default is false");
    }

    if (typeof key === "number" && !fields[key]) {
        throw new Error("Field is not defined: <key> must be in range [0, 9]");
    }

    if (typeof key !== "number") {
        throw new Error("<key> must be a number");
    }

    const lastByte = trailing ? "\r" : "";

    if (key === 0) {
        return fields[key] + lastByte;
    } else {
        return getRequiredFields(key-1) + "\r" + fields[key] + lastByte;
    }
};

console.log(getRequiredKeys(2, true));

and here's my test (mocha+chai):

describe("Expects a positive number to build required fields, the optional 2nd argument puts a trailing carriage return if true, default is false", () => {
    it("Returns a combined string for required fields", () => {
        expect(getRequiredFields(2)).to.be.a("string");
        expect(getRequiredFields(2, true)).to.equal("D:0:0:0:1:20:9\rD:1:0:22:1:95:9\rD:2:0:117:1:27:9\r");
        expect(getRequiredFields(2, false)).to.equal("D:0:0:0:1:20:9\rD:1:0:22:1:95:9\rD:2:0:117:1:27:9");
    });
    it("Throws an error if <trailing> is not a boolean", () => {
        expect(getRequiredFields.bind(this, 10, "foo")).to.throw("<trailing> must be of type 'boolean'");
    });
    it("Throws an error if <key> is higher than 9", () => {
        expect(getRequiredFields.bind(this, 10, true)).to.throw("Field is not defined: <key> must be in range [0, 9]");
    });
    it("Throws an error if <key> is NaN", () => {
        expect(getRequiredFields.bind(this, "f", false)).to.throw("<key> must be a number");
    });
});

Upvotes: 1

Views: 74

Answers (1)

apple apple
apple apple

Reputation: 10604

The reason is the control character \r (carriage return), which move the cursor to the leftmost point, so the further characters overwrite existing ones. Since this only effect output, the real content of the string is not effected, so all thing should be fine.

If you intended to use newline, you should use \n instead (or require('os').EOL for OS-specific one).


You can also try out the following, which would output 789456 or 123456789 depend on the enviroment.

console.log('123456\r789')

Upvotes: 1

Related Questions