Boolean
The Boolean constructor in SSJS — coercion via Boolean(value) returns a primitive but classifies negative numbers and empty arrays as falsy, and boxed new Boolean() objects carry several Jint quirks.
The ECMAScript Boolean constructor works in SSJS, but the SFMC Jint engine deviates from the specification in several places. Boolean(value) returns a genuine primitive boolean, yet it classifies negative numbers and empty arrays as falsy, and the primitive it returns carries no methods (there is no auto-boxing). The boxed new Boolean(value) form is worse: it stringifies with a capitalized first letter (True / False), a boxed false is falsy, and .valueOf() does not unwrap to a primitive. Prefer the function-call form Boolean(value) (or !!value), and compare values explicitly rather than relying on truthiness.
Status legend
| Icon | Meaning |
|---|---|
| ✅ Works | Available and behaves as expected |
| ⚠️ Partial | Available but with a documented caveat or bug |
| ❌ Missing | Not available (or undefined) — use the workaround |
Members
| Member | ES | Status | Notes |
|---|---|---|---|
Boolean(value) |
ES3 | ⚠️ Partial | Returns a primitive boolean, but negative numbers and [] coerce to false |
new Boolean(value) |
ES3 | ⚠️ Partial | Boxed object; capitalized True/False, falsy when boxing false |
Boolean.prototype |
ES3 | ✅ Works | toString / valueOf present; .call() on a primitive gives the spec form |
<boxed>.valueOf() |
ES3 | ⚠️ Partial | Does not unwrap — returns the boxed object itself |
<boxed>.toString() |
ES3 | ⚠️ Partial | Returns capitalized "True"/"False" instead of lowercase |
Boolean(value) — coercion
(ES3) — ⚠️ Partial. Called as a plain function, Boolean(value) returns a primitive boolean (typeof is "boolean"). The classification is correct for the common cases, but the engine treats a number as truthy only when it is greater than zero, so every negative number is falsy. An empty array is also falsy, because objects are coerced through ToPrimitive first.
Boolean(1); // true
Boolean(0); // false
Boolean(""); // false
Boolean("x"); // true
Boolean("0"); // true
Boolean(null); // false
typeof Boolean(1); // "boolean"
// SFMC deviations:
Boolean(-1); // false in SFMC (spec: true)
Boolean(-0.5); // false in SFMC (spec: true)
Boolean([]); // false in SFMC (spec: true)
Boolean([0]); // true
The primitive returned has no methods — there is no auto-boxing, so calling .toString() or .valueOf() on it throws Object expected. Use String(...) instead, or call through the prototype (see Boolean.prototype).
var b = Boolean(1);
b.toString(); // throws: Object expected: toString
String(b); // "true" — use this
true.toString(); // "true" — a literal does work
Three deviations. (1) The engine coerces a number with the rule n > 0, so Boolean(-1) is false where MDN specifies true. (2) Boolean([]) is false; MDN specifies every object — including an empty array — is truthy. (3) The returned primitive is not auto-boxed, so Boolean(1).toString() throws instead of returning "true". Compare numbers explicitly (n !== 0), test arrays with .length, and use String(value) for stringification.
Show test script
<script runat="server">
Platform.Load("core", "1.1.5");
/*
* Chapter: Boolean(value) — coercion
*
* Proves:
* 1. Boolean(value) returns a PRIMITIVE boolean (typeof "boolean").
* 2. The truthy / falsy classification for each documented input.
* 3. Boolean(v), !!v and `if (v)` agree with each other.
* 4. DEVIATIONS from the ECMAScript spec, each marked "DEV":
* - negative numbers are FALSY (engine rule is `n > 0`, not `n !== 0`)
* - an empty array [] is FALSY (spec: every object is truthy)
* - the primitive result carries no methods: .toString() / .valueOf()
* throw "Object expected" instead of auto-boxing
*
* EXPECTED OUTPUT: every line starts with PASS. A FAIL means the runtime no
* longer matches the documented claim and the page must be revised.
*/
function assert(id, actual, expected) {
var got;
try { got = String(actual); } catch (ex) { got = "THREW: " + ex.message; }
Platform.Response.Write((got === String(expected) ? "PASS " : "FAIL ") + id + " -> [" + got + "]\n");
}
function assertThrows(id, fn) {
var threw = false, msg = "";
try { fn(); } catch (ex) { threw = true; msg = ex.message; }
Platform.Response.Write((threw ? "PASS " : "FAIL ") + id + " -> " + (threw ? "threw: " + msg : "did NOT throw") + "\n");
}
function branch(v) { if (v) { return "truthy"; } return "falsy"; }
/* 1. The result is a primitive boolean, never an object. */
var a = Boolean(1);
assert("typeof Boolean(1) is boolean", typeof a, "boolean");
assert("Boolean(1) === true", Boolean(1) === true, "true");
assert("Boolean(0) === false", Boolean(0) === false, "true");
/* 2. Truthy inputs. */
assert("Boolean(true)", Boolean(true), "true");
assert("Boolean(2.5)", Boolean(2.5), "true");
assert("Boolean('x')", Boolean("x"), "true");
assert("Boolean('0')", Boolean("0"), "true");
assert("Boolean('false')", Boolean("false"), "true");
var obj = {};
assert("Boolean({})", Boolean(obj), "true");
/* 3. Falsy inputs that match the spec. */
assert("Boolean(false)", Boolean(false), "false");
assert("Boolean(0)", Boolean(0), "false");
assert("Boolean('')", Boolean(""), "false");
assert("Boolean(null)", Boolean(null), "false");
var undef;
assert("Boolean(undefined)", Boolean(undef), "false");
assert("Boolean(NaN)", Boolean(NaN), "false");
/* 4. DEVIATION — negative numbers are falsy. The engine rule is (n > 0). */
var neg1 = -1;
assert("DEV Boolean(-1) is false (spec: true)", Boolean(neg1), "false");
var neg2 = -0.5;
assert("DEV Boolean(-0.5) is false (spec: true)", Boolean(neg2), "false");
var neg3 = 0 - 3;
assert("DEV Boolean(0-3) is false (spec: true)", Boolean(neg3), "false");
assert("DEV if(-1) is falsy (spec: truthy)", branch(neg1), "falsy");
assert("rule check: -1 > 0", neg1 > 0, "false");
assert("rule check: 1 > 0", 1 > 0, "true");
/* 5. DEVIATION — an empty array is falsy; objects are coerced via ToPrimitive. */
var arr0 = [];
assert("DEV Boolean([]) is false (spec: true)", Boolean(arr0), "false");
assert("DEV if([]) is falsy (spec: truthy)", branch(arr0), "falsy");
var arr1 = [0];
assert("Boolean([0]) is true", Boolean(arr1), "true");
assert("String([]) is the empty string", String(arr0), "");
/* 6. Boolean(v), !!v and if(v) agree. */
assert("!!1 matches Boolean(1)", !!1, String(Boolean(1)));
assert("!!0 matches Boolean(0)", !!0, String(Boolean(0)));
assert("!!'' matches Boolean('')", !!"", String(Boolean("")));
assert("if(1) truthy", branch(1), "truthy");
assert("if(0) falsy", branch(0), "falsy");
assert("if('') falsy", branch(""), "falsy");
assert("if('x') truthy", branch("x"), "truthy");
/* 7. DEVIATION — no auto-boxing: the primitive result has no methods. */
assertThrows("DEV Boolean(1).toString() throws (spec: 'true')", function () { var t = Boolean(1); return t.toString(); });
assertThrows("DEV Boolean(1).valueOf() throws (spec: true)", function () { var t = Boolean(1); return t.valueOf(); });
var lit = true;
assert("literal true.toString() works and is lowercase", lit.toString(), "true");
assert("String(Boolean(true)) is 'true'", String(Boolean(true)), "true");
assert("String(Boolean(false)) is 'false'", String(Boolean(false)), "false");
</script>
new Boolean(value) — boxed object
(ES3) — ⚠️ Partial. new Boolean(value) creates a boxed Boolean object (typeof is "object"), but almost every observable behaviour deviates from the specification: the string form is capitalized, a boxed false is falsy (in standard JavaScript every object is truthy), .valueOf() returns the boxed object rather than the wrapped primitive, and instanceof Boolean is false. Avoid this form entirely — use Boolean(value) or !!value.
var b = new Boolean(false);
typeof b; // "object"
String(new Boolean(true)); // "True" in SFMC (spec: "true")
String(new Boolean(false)); // "False" in SFMC (spec: "false")
if (b) { /* NOT entered */ } // falsy in SFMC (spec: truthy — it is an object)
!!b; // false in SFMC (spec: true)
typeof b.valueOf(); // "object" in SFMC (spec: "boolean")
b.valueOf() === b; // true in SFMC — valueOf does not unwrap
b instanceof Boolean; // false in SFMC (spec: true)
b.constructor === Boolean; // true
MDN specifies a boxed Boolean stringifies to lowercase "true"/"false"; the SFMC Jint engine capitalizes the first letter ("True"/"False"). Prefer the primitive coercion form Boolean(value) or !!value.
Show test script — capitalized stringification
<script runat="server">
Platform.Load("core", "1.1.5");
/*
* Differs-from-docs claim: a boxed Boolean stringifies with a CAPITALIZED
* first letter in the SFMC Jint engine.
*
* MDN / ECMAScript: String(new Boolean(true)) === "true"
* SFMC Jint: String(new Boolean(true)) === "True"
*
* Proves both halves of the claim:
* 1. Every stringification path of a boxed Boolean capitalizes — String(),
* implicit "" + x concatenation, and an explicit .toString() call.
* 2. The recommended workarounds — Boolean(value), !!value, and a primitive
* literal — all produce the correct lowercase spec form.
*
* EXPECTED OUTPUT: every line starts with PASS.
*/
function assert(id, actual, expected) {
var got;
try { got = String(actual); } catch (ex) { got = "THREW: " + ex.message; }
Platform.Response.Write((got === String(expected) ? "PASS " : "FAIL ") + id + " -> [" + got + "]\n");
}
/* 1. Every boxed stringification path capitalizes. */
var t = new Boolean(true);
var f = new Boolean(false);
assert("DEV String(new Boolean(true)) is 'True' not 'true'", String(t), "True");
assert("DEV String(new Boolean(false)) is 'False' not 'false'", String(f), "False");
assert("DEV '' + new Boolean(true) is 'True'", "" + t, "True");
assert("DEV new Boolean(true).toString() is 'True'", t.toString(), "True");
/* 2. The workarounds produce the correct lowercase form. */
assert("workaround String(Boolean(true)) is 'true'", String(Boolean(true)), "true");
assert("workaround String(!!1) is 'true'", String(!!1), "true");
assert("workaround String(Boolean(false)) is 'false'", String(Boolean(false)), "false");
var lit = true;
assert("primitive literal true.toString() is 'true'", lit.toString(), "true");
</script>
Beyond stringification, a boxed Boolean also breaks three other MDN guarantees: new Boolean(false) is falsy in a condition (MDN: every object is truthy), .valueOf() returns the boxed object instead of the wrapped primitive, and instanceof Boolean is false. There is no reliable way to unwrap a boxed Boolean — do not create one.
Show test script
<script runat="server">
Platform.Load("core", "1.1.5");
/*
* Chapter: new Boolean(value) — boxed object
*
* Proves:
* 1. new Boolean(value) produces an object (typeof "object").
* 2. DEVIATIONS from the ECMAScript spec, each marked "DEV":
* - stringification is CAPITALIZED: "True" / "False" (spec: lowercase)
* - a boxed false is FALSY (spec: every object is truthy)
* - .valueOf() does NOT unwrap — it returns the boxed object itself
* - `instanceof Boolean` is false even though .constructor matches
*
* EXPECTED OUTPUT: every line starts with PASS.
*/
function assert(id, actual, expected) {
var got;
try { got = String(actual); } catch (ex) { got = "THREW: " + ex.message; }
Platform.Response.Write((got === String(expected) ? "PASS " : "FAIL ") + id + " -> [" + got + "]\n");
}
function branch(v) { if (v) { return "truthy"; } return "falsy"; }
/* 1. It really is an object. */
var t = new Boolean(true);
assert("typeof new Boolean(true) is object", typeof t, "object");
var f = new Boolean(false);
assert("typeof new Boolean(false) is object", typeof f, "object");
/* 2. DEVIATION — capitalized string form. */
assert("DEV String(new Boolean(true)) is 'True' (spec: 'true')", String(t), "True");
assert("DEV String(new Boolean(false)) is 'False' (spec: 'false')", String(f), "False");
assert("DEV new Boolean(true).toString() is 'True' (spec: 'true')", t.toString(), "True");
assert("DEV new Boolean(false).toString() is 'False' (spec: 'false')", f.toString(), "False");
/* 3. DEVIATION — a boxed false is falsy here; in the spec every object is truthy. */
assert("DEV if(new Boolean(false)) is falsy (spec: truthy)", branch(f), "falsy");
assert("if(new Boolean(true)) is truthy", branch(t), "truthy");
assert("DEV !!new Boolean(false) is false (spec: true)", !!f, "false");
assert("DEV Boolean(new Boolean(false)) is false (spec: true)", Boolean(f), "false");
/* 4. DEVIATION — valueOf() does not unwrap to a primitive. */
var v = f.valueOf();
assert("DEV typeof boxed.valueOf() is object (spec: boolean)", typeof v, "object");
assert("DEV boxed.valueOf() === boxed (spec: false)", v === f, "true");
assert("DEV boxed.valueOf() === false is false (spec: true)", v === false, "false");
assert("boxed.valueOf() == false is true (loose compare)", v == false, "true");
/* 5. DEVIATION — instanceof fails although the constructor matches. */
assert("DEV new Boolean(true) instanceof Boolean is false (spec: true)", t instanceof Boolean, "false");
assert("new Boolean(true).constructor === Boolean", t.constructor === Boolean, "true");
/* 6. No-argument form. */
var n = new Boolean();
assert("typeof new Boolean() is object", typeof n, "object");
assert("String(new Boolean()) is 'False'", String(n), "False");
</script>
Boolean.prototype
(ES3) — ✅ Works. Boolean.prototype exists and exposes toString, valueOf, and constructor. Because a primitive boolean is not auto-boxed in this engine, calling these through .call() is the reliable way to invoke them on a primitive — and doing so returns the correct lowercase spec form.
typeof Boolean.prototype; // "object"
typeof Boolean.prototype.toString; // "function"
typeof Boolean.prototype.valueOf; // "function"
Boolean.prototype.toString.call(true); // "true" (correct, lowercase)
Boolean.prototype.toString.call(Boolean(1)); // "true" (works where .toString() throws)
Boolean.prototype.valueOf.call(true); // true
// but on a boxed instance the capitalization quirk still applies:
Boolean.prototype.toString.call(new Boolean(true)); // "True" (spec: "true")
Show test script
<script runat="server">
Platform.Load("core", "1.1.5");
/*
* Chapter: Boolean.prototype
*
* Proves:
* 1. Boolean is a function and Boolean.prototype is an object.
* 2. toString / valueOf / constructor exist on the prototype.
* 3. Calling them with .call() on a PRIMITIVE works and returns the correct
* lowercase spec form — this is the reliable escape hatch, because a
* primitive boolean has no methods of its own (see the coercion chapter).
* 4. DEVIATION marked "DEV": .call() on a BOXED instance returns the
* capitalized "True" / "False" instead of the spec's lowercase.
*
* EXPECTED OUTPUT: every line starts with PASS.
*/
function assert(id, actual, expected) {
var got;
try { got = String(actual); } catch (ex) { got = "THREW: " + ex.message; }
Platform.Response.Write((got === String(expected) ? "PASS " : "FAIL ") + id + " -> [" + got + "]\n");
}
/* 1 + 2. Shape of the prototype. */
assert("typeof Boolean is function", typeof Boolean, "function");
assert("typeof Boolean.prototype is object", typeof Boolean.prototype, "object");
assert("typeof Boolean.prototype.toString is function", typeof Boolean.prototype.toString, "function");
assert("typeof Boolean.prototype.valueOf is function", typeof Boolean.prototype.valueOf, "function");
assert("typeof Boolean.prototype.constructor is function", typeof Boolean.prototype.constructor, "function");
/* 3. .call() on primitives returns the lowercase spec form. */
assert("toString.call(true) is 'true'", Boolean.prototype.toString.call(true), "true");
assert("toString.call(false) is 'false'", Boolean.prototype.toString.call(false), "false");
var c = Boolean(1);
assert("toString.call(Boolean(1)) is 'true'", Boolean.prototype.toString.call(c), "true");
assert("valueOf.call(true) is true", Boolean.prototype.valueOf.call(true), "true");
/* 4. DEVIATION — the boxed instance still capitalizes. */
var box = new Boolean(true);
assert("DEV toString.call(new Boolean(true)) is 'True' (spec: 'true')", Boolean.prototype.toString.call(box), "True");
</script>