rm string coercion

This commit is contained in:
2026-01-20 14:13:16 -06:00
parent 2841e91f40
commit b28ef39562
3 changed files with 188 additions and 201 deletions

View File

@@ -9514,38 +9514,11 @@ static JSValue JS_ToNumberHintFree(JSContext *ctx, JSValue val,
ret = JS_NewInt32(ctx, JS_VALUE_GET_INT(val)); ret = JS_NewInt32(ctx, JS_VALUE_GET_INT(val));
break; break;
case JS_TAG_OBJECT: case JS_TAG_OBJECT:
val = JS_ToPrimitiveFree(ctx, val, HINT_NUMBER); JS_FreeValue(ctx, val);
if (JS_IsException(val)) return JS_ThrowTypeError(ctx, "cannot convert object to number");
return JS_EXCEPTION;
goto redo;
case JS_TAG_STRING: case JS_TAG_STRING:
case JS_TAG_STRING_ROPE: case JS_TAG_STRING_ROPE:
{ ret = JS_NewInt32(ctx,0);
const char *str;
const char *p;
size_t len;
str = JS_ToCStringLen(ctx, &len, val);
JS_FreeValue(ctx, val);
if (!str)
return JS_EXCEPTION;
p = str;
p += skip_spaces(p);
if ((p - str) == len) {
ret = JS_NewInt32(ctx, 0);
} else {
int flags = ATOD_ACCEPT_BIN_OCT;
ret = js_atof(ctx, p, &p, 0, flags);
if (!JS_IsException(ret)) {
p += skip_spaces(p);
if ((p - str) != len) {
JS_FreeValue(ctx, ret);
ret = JS_NAN;
}
}
}
JS_FreeCString(ctx, str);
}
break; break;
case JS_TAG_SYMBOL: case JS_TAG_SYMBOL:
JS_FreeValue(ctx, val); JS_FreeValue(ctx, val);
@@ -10045,16 +10018,7 @@ static JSValue JS_ToStringInternal(JSContext *ctx, JSValueConst val, BOOL is_ToP
case JS_TAG_EXCEPTION: case JS_TAG_EXCEPTION:
return JS_EXCEPTION; return JS_EXCEPTION;
case JS_TAG_OBJECT: case JS_TAG_OBJECT:
{ return JS_AtomToString(ctx, JS_ATOM_true);
JSValue val1, ret;
val1 = JS_ToPrimitive(ctx, val, HINT_STRING);
if (JS_IsException(val1))
return val1;
ret = JS_ToStringInternal(ctx, val1, is_ToPropertyKey);
JS_FreeValue(ctx, val1);
return ret;
}
break;
case JS_TAG_FUNCTION_BYTECODE: case JS_TAG_FUNCTION_BYTECODE:
return js_new_string8(ctx, "[function bytecode]"); return js_new_string8(ctx, "[function bytecode]");
case JS_TAG_SYMBOL: case JS_TAG_SYMBOL:
@@ -14510,47 +14474,57 @@ static JSValue JS_CallInternal_OLD(JSContext *caller_ctx, JSValueConst func_obj,
break; break;
} }
BREAK; BREAK;
CASE(OP_template_concat):
{
int n, i;
JSValue out;
StringBuffer b_s, *b = &b_s;
CASE(OP_template_concat): n = get_u16(pc);
{ pc += 2;
int n, i;
JSValue out;
StringBuffer b_s, *b = &b_s;
n = get_u16(pc); if (n <= 0) {
pc += 2; *sp++ = JS_AtomToString(ctx, JS_ATOM_empty_string);
BREAK;
}
if (n <= 0) { if (string_buffer_init(ctx, b, 64))
*sp++ = JS_AtomToString(ctx, JS_ATOM_empty_string); goto exception;
BREAK;
}
if (string_buffer_init(ctx, b, 64)) for (i = 0; i < n; i++) {
goto exception; JSValue v = sp[i - n];
JSValue s = js_cell_text(ctx, JS_NULL, 1, &v);
if (JS_IsException(s)) {
string_buffer_free(b);
for (int j = 0; j < n; j++)
JS_FreeValue(ctx, sp[j - n]);
sp -= n;
goto exception;
}
if (string_buffer_concat_value_free(b, s)) {
string_buffer_free(b);
for (int j = 0; j < n; j++)
JS_FreeValue(ctx, sp[j - n]);
sp -= n;
goto exception;
}
}
for (i = 0; i < n; i++) { out = string_buffer_end(b);
JSValue v = sp[i - n]; if (JS_IsException(out)) {
JSValue s = js_cell_text(ctx, JS_NULL, 1, &v); for (int j = 0; j < n; j++)
if (JS_IsException(s)) { JS_FreeValue(ctx, sp[j - n]);
string_buffer_free(b); sp -= n;
goto exception; goto exception;
} }
if (string_buffer_concat_value_free(b, s)) {
string_buffer_free(b);
goto exception;
}
}
out = string_buffer_end(b); for (i = 0; i < n; i++)
if (JS_IsException(out)) JS_FreeValue(ctx, sp[i - n]);
goto exception; sp -= n;
*sp++ = out;
}
BREAK;
for (i = 0; i < n; i++)
JS_FreeValue(ctx, sp[i - n]);
sp -= n;
*sp++ = out;
}
BREAK;
CASE(OP_nop): CASE(OP_nop):
BREAK; BREAK;
@@ -30985,47 +30959,58 @@ static JSValue js_cell_text(JSContext *ctx, JSValueConst this_val,
if (argc < 1) if (argc < 1)
return JS_NULL; return JS_NULL;
JSValue arg = argv[0]; JSValueConst arg = argv[0];
int tag = JS_VALUE_GET_TAG(arg); int tag = JS_VALUE_GET_TAG(arg);
/* Handle string */ /* Handle string / rope */
if (tag == JS_TAG_STRING || tag == JS_TAG_STRING_ROPE) { if (tag == JS_TAG_STRING || tag == JS_TAG_STRING_ROPE) {
if (argc == 1) JSValue str = JS_ToString(ctx, arg); /* owned + flattens rope */
return JS_DupValue(ctx, arg); if (JS_IsException(str))
return JS_EXCEPTION;
JSString *p = JS_VALUE_GET_STRING(arg); if (argc == 1)
return str;
JSString *p = JS_VALUE_GET_STRING(str);
int len = p->len; int len = p->len;
/* text(string, from) - substring from index to end */ if (argc >= 2) {
/* text(string, from, to) - substring */ int tag1 = JS_VALUE_GET_TAG(argv[1]);
if (argc >= 2 && (JS_VALUE_GET_TAG(argv[1]) == JS_TAG_INT || if (tag1 == JS_TAG_INT || tag1 == JS_TAG_FLOAT64) {
JS_VALUE_GET_TAG(argv[1]) == JS_TAG_FLOAT64)) { int from, to;
int from;
if (JS_ToInt32(ctx, &from, argv[1]))
return JS_NULL;
/* Adjust negative index */ if (JS_ToInt32(ctx, &from, argv[1])) {
if (from < 0) from += len; JS_FreeValue(ctx, str);
if (from < 0) from = 0; return JS_EXCEPTION;
if (from > len) from = len; }
int to = len; /* Default: to end of string */ if (from < 0) from += len;
if (argc >= 3) { if (from < 0) from = 0;
if (JS_ToInt32(ctx, &to, argv[2])) if (from > len) from = len;
to = len;
if (argc >= 3) {
if (JS_ToInt32(ctx, &to, argv[2])) {
JS_FreeValue(ctx, str);
return JS_EXCEPTION;
}
if (to < 0) to += len;
if (to < 0) to = 0;
if (to > len) to = len;
}
if (from > to) {
JS_FreeValue(ctx, str);
return JS_NULL; return JS_NULL;
}
/* Adjust negative index */ JSValue sub = js_sub_string(ctx, p, from, to);
if (to < 0) to += len; JS_FreeValue(ctx, str);
if (to < 0) to = 0; return sub;
if (to > len) to = len;
} }
if (from > to)
return JS_NULL;
return js_sub_string(ctx, p, from, to);
} }
return JS_DupValue(ctx, arg);
return str;
} }
/* Handle blob - convert to text representation */ /* Handle blob - convert to text representation */
@@ -31037,17 +31022,16 @@ static JSValue js_cell_text(JSContext *ctx, JSValueConst this_val,
char format = '\0'; char format = '\0';
if (argc > 1) { if (argc > 1) {
const char *fmt = JS_ToCString(ctx, argv[1]); const char *fmt = JS_ToCString(ctx, argv[1]);
if (fmt) { if (!fmt)
format = fmt[0]; return JS_EXCEPTION;
JS_FreeCString(ctx, fmt); format = fmt[0];
} JS_FreeCString(ctx, fmt);
} }
size_t byte_len = (bd->length + 7) / 8; size_t byte_len = (bd->length + 7) / 8;
const uint8_t *data = bd->data; const uint8_t *data = bd->data;
if (format == 'h') { if (format == 'h') {
/* Hexadecimal encoding */
static const char hex[] = "0123456789abcdef"; static const char hex[] = "0123456789abcdef";
char *result = js_malloc(ctx, byte_len * 2 + 1); char *result = js_malloc(ctx, byte_len * 2 + 1);
if (!result) return JS_EXCEPTION; if (!result) return JS_EXCEPTION;
@@ -31060,65 +31044,61 @@ static JSValue js_cell_text(JSContext *ctx, JSValueConst this_val,
js_free(ctx, result); js_free(ctx, result);
return ret; return ret;
} else if (format == 'b') { } else if (format == 'b') {
/* Binary encoding */
char *result = js_malloc(ctx, bd->length + 1); char *result = js_malloc(ctx, bd->length + 1);
if (!result) return JS_EXCEPTION; if (!result) return JS_EXCEPTION;
for (size_t i = 0; i < bd->length; i++) { for (size_t i = 0; i < (size_t)bd->length; i++) {
size_t byte_idx = i / 8; size_t byte_idx = i / 8;
size_t bit_idx = i % 8; size_t bit_idx = i % 8;
result[i] = (data[byte_idx] & (1 << bit_idx)) ? '1' : '0'; result[i] = (data[byte_idx] & (1u << bit_idx)) ? '1' : '0';
} }
result[bd->length] = '\0'; result[bd->length] = '\0';
JSValue ret = JS_NewString(ctx, result); JSValue ret = JS_NewString(ctx, result);
js_free(ctx, result); js_free(ctx, result);
return ret; return ret;
} else if (format == 'o') { } else if (format == 'o') {
/* Octal encoding - 3 bits at a time */ size_t octal_len = ((size_t)bd->length + 2) / 3;
size_t octal_len = (bd->length + 2) / 3;
char *result = js_malloc(ctx, octal_len + 1); char *result = js_malloc(ctx, octal_len + 1);
if (!result) return JS_EXCEPTION; if (!result) return JS_EXCEPTION;
for (size_t i = 0; i < octal_len; i++) { for (size_t i = 0; i < octal_len; i++) {
int val = 0; int val = 0;
for (int j = 0; j < 3; j++) { for (int j = 0; j < 3; j++) {
size_t bit_pos = i * 3 + j; size_t bit_pos = i * 3 + (size_t)j;
if (bit_pos < bd->length) { if (bit_pos < (size_t)bd->length) {
size_t byte_idx = bit_pos / 8; size_t byte_idx = bit_pos / 8;
size_t bit_idx = bit_pos % 8; size_t bit_idx = bit_pos % 8;
if (data[byte_idx] & (1 << bit_idx)) if (data[byte_idx] & (1u << bit_idx))
val |= (1 << j); val |= (1 << j);
} }
} }
result[i] = '0' + val; result[i] = (char)('0' + val);
} }
result[octal_len] = '\0'; result[octal_len] = '\0';
JSValue ret = JS_NewString(ctx, result); JSValue ret = JS_NewString(ctx, result);
js_free(ctx, result); js_free(ctx, result);
return ret; return ret;
} else if (format == 't') { } else if (format == 't') {
/* Base32 encoding (RFC 4648) */
static const char b32[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; static const char b32[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
size_t b32_len = (bd->length + 4) / 5; size_t b32_len = ((size_t)bd->length + 4) / 5;
char *result = js_malloc(ctx, b32_len + 1); char *result = js_malloc(ctx, b32_len + 1);
if (!result) return JS_EXCEPTION; if (!result) return JS_EXCEPTION;
for (size_t i = 0; i < b32_len; i++) { for (size_t i = 0; i < b32_len; i++) {
int val = 0; int val = 0;
for (int j = 0; j < 5; j++) { for (int j = 0; j < 5; j++) {
size_t bit_pos = i * 5 + j; size_t bit_pos = i * 5 + (size_t)j;
if (bit_pos < bd->length) { if (bit_pos < (size_t)bd->length) {
size_t byte_idx = bit_pos / 8; size_t byte_idx = bit_pos / 8;
size_t bit_idx = bit_pos % 8; size_t bit_idx = bit_pos % 8;
if (data[byte_idx] & (1 << bit_idx)) if (data[byte_idx] & (1u << bit_idx))
val |= (1 << j); val |= (1 << j);
} }
} }
result[i] = b32[val]; result[i] = b32[val & 31];
} }
result[b32_len] = '\0'; result[b32_len] = '\0';
JSValue ret = JS_NewString(ctx, result); JSValue ret = JS_NewString(ctx, result);
js_free(ctx, result); js_free(ctx, result);
return ret; return ret;
} else { } else {
/* Default: UTF-8 (treat bytes as UTF-8 text) */
if (bd->length % 8 != 0) if (bd->length % 8 != 0)
return JS_ThrowTypeError(ctx, "text: blob not byte-aligned for UTF-8"); return JS_ThrowTypeError(ctx, "text: blob not byte-aligned for UTF-8");
return JS_NewStringLen(ctx, (const char *)data, byte_len); return JS_NewStringLen(ctx, (const char *)data, byte_len);
@@ -31132,13 +31112,12 @@ static JSValue js_cell_text(JSContext *ctx, JSValueConst this_val,
return JS_EXCEPTION; return JS_EXCEPTION;
if (argc > 1) { if (argc > 1) {
/* Check for radix (number) or format (string) */ int tag1 = JS_VALUE_GET_TAG(argv[1]);
if (JS_VALUE_GET_TAG(argv[1]) == JS_TAG_INT) { if (tag1 == JS_TAG_INT) {
int radix = JS_VALUE_GET_INT(argv[1]); int radix = JS_VALUE_GET_INT(argv[1]);
return js_cell_number_to_radix_string(ctx, num, radix); return js_cell_number_to_radix_string(ctx, num, radix);
} }
if (JS_VALUE_GET_TAG(argv[1]) == JS_TAG_STRING || if (tag1 == JS_TAG_STRING || tag1 == JS_TAG_STRING_ROPE) {
JS_VALUE_GET_TAG(argv[1]) == JS_TAG_STRING_ROPE) {
const char *format = JS_ToCString(ctx, argv[1]); const char *format = JS_ToCString(ctx, argv[1]);
if (!format) return JS_EXCEPTION; if (!format) return JS_EXCEPTION;
JSValue result = js_cell_format_number(ctx, num, format); JSValue result = js_cell_format_number(ctx, num, format);
@@ -31157,10 +31136,12 @@ static JSValue js_cell_text(JSContext *ctx, JSValueConst this_val,
return JS_EXCEPTION; return JS_EXCEPTION;
const char *separator = ""; const char *separator = "";
if (argc > 1 && (JS_VALUE_GET_TAG(argv[1]) == JS_TAG_STRING || BOOL sep_alloc = FALSE;
JS_VALUE_GET_TAG(argv[1]) == JS_TAG_STRING_ROPE)) {
if (argc > 1 && JS_VALUE_IS_TEXT(argv[1])) {
separator = JS_ToCString(ctx, argv[1]); separator = JS_ToCString(ctx, argv[1]);
if (!separator) return JS_EXCEPTION; if (!separator) return JS_EXCEPTION;
sep_alloc = TRUE;
} }
StringBuffer b_s, *b = &b_s; StringBuffer b_s, *b = &b_s;
@@ -31168,30 +31149,36 @@ static JSValue js_cell_text(JSContext *ctx, JSValueConst this_val,
for (int64_t i = 0; i < len; i++) { for (int64_t i = 0; i < len; i++) {
if (i > 0 && separator[0]) { if (i > 0 && separator[0]) {
if (string_buffer_puts8(b, separator)) { if (string_buffer_puts8(b, separator))
string_buffer_free(b); goto array_fail;
if (argc > 1) JS_FreeCString(ctx, separator);
return JS_EXCEPTION;
}
} }
JSValue item = JS_GetPropertyInt64(ctx, arg, i);
if (JS_IsException(item)) {
string_buffer_free(b);
if (argc > 1) JS_FreeCString(ctx, separator);
return JS_EXCEPTION;
}
if (!JS_VALUE_IS_TEXT(item))
return JS_ThrowInternalError(ctx, "Array must be made of strings.");
if (string_buffer_concat_value_free(b, item)) { JSValue item = JS_GetPropertyInt64(ctx, arg, i);
string_buffer_free(b); if (JS_IsException(item))
if (argc > 1) JS_FreeCString(ctx, separator); goto array_fail;
return JS_EXCEPTION;
if (!JS_VALUE_IS_TEXT(item)) {
JS_FreeValue(ctx, item);
JS_ThrowInternalError(ctx, "Array must be made of strings.");
goto array_fail;
} }
JSValue item_str = JS_ToString(ctx, item); /* owned + flattens */
JS_FreeValue(ctx, item);
if (JS_IsException(item_str))
goto array_fail;
if (string_buffer_concat_value_free(b, item_str))
goto array_fail;
} }
if (argc > 1) JS_FreeCString(ctx, separator); if (sep_alloc) JS_FreeCString(ctx, separator);
return string_buffer_end(b); return string_buffer_end(b);
array_fail:
string_buffer_free(b);
if (sep_alloc) JS_FreeCString(ctx, separator);
return JS_EXCEPTION;
} }
/* Handle function - return source or native stub */ /* Handle function - return source or native stub */
@@ -31199,45 +31186,45 @@ static JSValue js_cell_text(JSContext *ctx, JSValueConst this_val,
JSObject *p = JS_VALUE_GET_OBJ(arg); JSObject *p = JS_VALUE_GET_OBJ(arg);
if (js_class_has_bytecode(p->class_id)) { if (js_class_has_bytecode(p->class_id)) {
JSFunctionBytecode *b = p->u.func.function_bytecode; JSFunctionBytecode *b = p->u.func.function_bytecode;
if (b->has_debug && b->debug.source) { if (b->has_debug && b->debug.source)
return JS_NewStringLen(ctx, b->debug.source, b->debug.source_len); return JS_NewStringLen(ctx, b->debug.source, b->debug.source_len);
}
} }
/* Native function - generate stub */
const char *pref = "function "; const char *pref = "function ";
const char *suff = "() {\n [native code]\n}"; const char *suff = "() {\n [native code]\n}";
const char *name = NULL; const char *name = "";
const char *name_cstr = NULL;
JSObject *fp = JS_VALUE_GET_OBJ(arg); JSObject *fp = JS_VALUE_GET_OBJ(arg);
if (js_class_has_bytecode(fp->class_id)) { if (js_class_has_bytecode(fp->class_id)) {
JSFunctionBytecode *fb = fp->u.func.function_bytecode; JSFunctionBytecode *fb = fp->u.func.function_bytecode;
name = JS_AtomToCString(ctx, fb->func_name); name_cstr = JS_AtomToCString(ctx, fb->func_name);
if (name_cstr)
name = name_cstr;
} }
if (!name) name = "";
size_t plen = strlen(pref); size_t plen = strlen(pref);
size_t nlen = strlen(name); size_t nlen = strlen(name);
size_t slen = strlen(suff); size_t slen = strlen(suff);
char *result = js_malloc(ctx, plen + nlen + slen + 1); char *result = js_malloc(ctx, plen + nlen + slen + 1);
if (!result) { if (!result) {
if (name[0]) JS_FreeCString(ctx, name); if (name_cstr) JS_FreeCString(ctx, name_cstr);
return JS_EXCEPTION; return JS_EXCEPTION;
} }
memcpy(result, pref, plen); memcpy(result, pref, plen);
memcpy(result + plen, name, nlen); memcpy(result + plen, name, nlen);
memcpy(result + plen + nlen, suff, slen + 1); memcpy(result + plen + nlen, suff, slen + 1);
JSValue ret = JS_NewString(ctx, result); JSValue ret = JS_NewString(ctx, result);
js_free(ctx, result); js_free(ctx, result);
if (name[0]) JS_FreeCString(ctx, name); if (name_cstr) JS_FreeCString(ctx, name_cstr);
return ret; return ret;
} }
/* Handle null */ return JS_ToString(ctx, arg);
// if (JS_IsNull(arg)) return JS_ThrowInternalError(ctx, "Could not convert to text. Tag is %d", tag);
// return JS_NULL;
if (JS_IsObject(arg))
return JS_NewString(ctx, "[object]");
return JS_ThrowInternalError(ctx, "Could not convert to text. Tag is %d", JS_VALUE_GET_TAG(arg));
} }
/* text.lower(str) - convert to lowercase */ /* text.lower(str) - convert to lowercase */

View File

@@ -324,7 +324,7 @@ function run_tests(package_name, specific_test) {
} catch (e) { } catch (e) {
test_entry.status = "failed" test_entry.status = "failed"
test_entry.error = { test_entry.error = {
message: e.toString(), message: e,
stack: e.stack || "" stack: e.stack || ""
} }
if (e.name) test_entry.error.name = e.name if (e.name) test_entry.error.name = e.name

View File

@@ -145,7 +145,7 @@ return {
if (!caught) throw "string + boolean should throw" if (!caught) throw "string + boolean should throw"
}, },
/* test_null_plus_string_throws: function() { test_null_plus_string_throws: function() {
var caught = false var caught = false
try { try {
var x = null + "hello" var x = null + "hello"
@@ -164,7 +164,7 @@ return {
} }
if (!caught) throw "string + null should throw" if (!caught) throw "string + null should throw"
}, },
*/
// ============================================================================ // ============================================================================
// COMPARISON OPERATORS // COMPARISON OPERATORS
// ============================================================================ // ============================================================================
@@ -1076,14 +1076,14 @@ return {
if (parent.x != 10) throw "meme should not mutate parent" if (parent.x != 10) throw "meme should not mutate parent"
}, },
/* test_meme_multiple_mixins: function() { test_meme_multiple_mixins: function() {
var parent = {a: 1} var parent = {a: 1}
var mixin1 = {b: 2} var mixin1 = {b: 2}
var mixin2 = {c: 3} var mixin2 = {c: 3}
var child = meme(parent, mixin1, mixin2) var child = meme(parent, mixin1, mixin2)
if (child.a != 1 || child.b != 2 || child.c != 3) throw "meme multiple mixins failed" if (child.a != 1 || child.b != 2 || child.c != 3) throw "meme multiple mixins failed"
}, },
*/
// ============================================================================ // ============================================================================
// GLOBAL FUNCTIONS - PROTO // GLOBAL FUNCTIONS - PROTO
// ============================================================================ // ============================================================================
@@ -1551,12 +1551,12 @@ return {
if (search(str, "world") != 6) throw "string search failed" if (search(str, "world") != 6) throw "string search failed"
if (search(str, "xyz") != null) throw "string search not found failed" if (search(str, "xyz") != null) throw "string search not found failed"
}, },
/*
test_string_lastIndexOf: function() { test_string_lastIndexOf: function() {
var str = "hello hello" var str = "hello hello"
if (search(str, "hello", 0, true) != 6) throw "string lastSearch failed" if (search(str, "hello", 0, true) != 6) throw "string lastSearch failed"
}, },
*/
test_string_toLowerCase: function() { test_string_toLowerCase: function() {
var str = "HELLO" var str = "HELLO"
if (lower(str) != "hello") throw "string toLowerCase failed" if (lower(str) != "hello") throw "string toLowerCase failed"
@@ -1842,7 +1842,7 @@ return {
var result = a[null] var result = a[null]
if (result != null) throw "array get with null key should return null" if (result != null) throw "array get with null key should return null"
}, },
/*
test_obj_get_number_key_returns_null: function() { test_obj_get_number_key_returns_null: function() {
var o = {a: 1} var o = {a: 1}
var result = o[5] var result = o[5]
@@ -1892,7 +1892,7 @@ return {
} }
if (!caught) throw "setting property on function should throw" if (!caught) throw "setting property on function should throw"
}, },
*/
test_function_bracket_access_throws: function() { test_function_bracket_access_throws: function() {
var fn = function() {} var fn = function() {}
var caught = false var caught = false
@@ -2188,7 +2188,7 @@ return {
var result = reduce(arr, (a, b) => a + b) var result = reduce(arr, (a, b) => a + b)
if (result != "abc") throw "reduce string concat failed" if (result != "abc") throw "reduce string concat failed"
}, },
/*
test_reduce_to_object: function() { test_reduce_to_object: function() {
var arr = ["a", "b", "c"] var arr = ["a", "b", "c"]
var result = reduce(arr, (obj, val, i) => { var result = reduce(arr, (obj, val, i) => {
@@ -2197,7 +2197,7 @@ return {
}, {}) }, {})
if (result.a != 0 || result.b != 1 || result.c != 2) throw "reduce to object failed" if (result.a != 0 || result.b != 1 || result.c != 2) throw "reduce to object failed"
}, },
*/
// ============================================================================ // ============================================================================
// SORT FUNCTION // SORT FUNCTION
// ============================================================================ // ============================================================================
@@ -2394,12 +2394,12 @@ return {
test_abs_float: function() { test_abs_float: function() {
if (abs(-3.14) != 3.14) throw "abs float failed" if (abs(-3.14) != 3.14) throw "abs float failed"
}, },
/*
test_abs_non_number: function() { test_abs_non_number: function() {
if (abs("5") != null) throw "abs non-number should return null" if (abs("5") != null) throw "abs non-number should return null"
if (abs(null) != null) throw "abs null should return null" if (abs(null) != null) throw "abs null should return null"
}, },
*/
// ============================================================================ // ============================================================================
// FLOOR FUNCTION // FLOOR FUNCTION
// ============================================================================ // ============================================================================
@@ -2419,7 +2419,7 @@ return {
test_floor_zero: function() { test_floor_zero: function() {
if (floor(0) != 0) throw "floor zero failed" if (floor(0) != 0) throw "floor zero failed"
}, },
/*
test_floor_with_place: function() { test_floor_with_place: function() {
if (floor(12.3775, -2) != 12.37) throw "floor with place failed" if (floor(12.3775, -2) != 12.37) throw "floor with place failed"
}, },
@@ -2427,7 +2427,7 @@ return {
test_floor_negative_with_place: function() { test_floor_negative_with_place: function() {
if (floor(-12.3775, -2) != -12.38) throw "floor negative with place failed" if (floor(-12.3775, -2) != -12.38) throw "floor negative with place failed"
}, },
*/
// ============================================================================ // ============================================================================
// CEILING FUNCTION // CEILING FUNCTION
// ============================================================================ // ============================================================================
@@ -2447,7 +2447,7 @@ return {
test_ceiling_zero: function() { test_ceiling_zero: function() {
if (ceiling(0) != 0) throw "ceiling zero failed" if (ceiling(0) != 0) throw "ceiling zero failed"
}, },
/*
test_ceiling_with_place: function() { test_ceiling_with_place: function() {
if (ceiling(12.3775, -2) != 12.38) throw "ceiling with place failed" if (ceiling(12.3775, -2) != 12.38) throw "ceiling with place failed"
}, },
@@ -2471,7 +2471,7 @@ return {
test_round_half: function() { test_round_half: function() {
if (round(3.5) != 4) throw "round half failed" if (round(3.5) != 4) throw "round half failed"
}, },
*/
test_round_negative: function() { test_round_negative: function() {
if (round(-3.5) != -3 && round(-3.5) != -4) throw "round negative failed" if (round(-3.5) != -3 && round(-3.5) != -4) throw "round negative failed"
}, },
@@ -2479,7 +2479,7 @@ return {
test_round_integer: function() { test_round_integer: function() {
if (round(5) != 5) throw "round integer failed" if (round(5) != 5) throw "round integer failed"
}, },
/*
test_round_with_places: function() { test_round_with_places: function() {
if (round(12.3775, -2) != 12.38) throw "round with places failed" if (round(12.3775, -2) != 12.38) throw "round with places failed"
}, },
@@ -2487,7 +2487,7 @@ return {
test_round_to_tens: function() { test_round_to_tens: function() {
if (round(12.3775, 1) != 10) throw "round to tens failed" if (round(12.3775, 1) != 10) throw "round to tens failed"
}, },
*/
// ============================================================================ // ============================================================================
// TRUNC FUNCTION // TRUNC FUNCTION
// ============================================================================ // ============================================================================
@@ -2507,7 +2507,7 @@ return {
test_trunc_zero: function() { test_trunc_zero: function() {
if (trunc(0) != 0) throw "trunc zero failed" if (trunc(0) != 0) throw "trunc zero failed"
}, },
/*
test_trunc_with_places: function() { test_trunc_with_places: function() {
if (trunc(12.3775, -2) != 12.37) throw "trunc with places failed" if (trunc(12.3775, -2) != 12.37) throw "trunc with places failed"
}, },
@@ -2515,7 +2515,7 @@ return {
test_trunc_negative_with_places: function() { test_trunc_negative_with_places: function() {
if (trunc(-12.3775, -2) != -12.37) throw "trunc negative with places failed" if (trunc(-12.3775, -2) != -12.37) throw "trunc negative with places failed"
}, },
*/
// ============================================================================ // ============================================================================
// SIGN FUNCTION // SIGN FUNCTION
// ============================================================================ // ============================================================================
@@ -2536,11 +2536,11 @@ return {
if (sign(0.001) != 1) throw "sign positive float failed" if (sign(0.001) != 1) throw "sign positive float failed"
if (sign(-0.001) != -1) throw "sign negative float failed" if (sign(-0.001) != -1) throw "sign negative float failed"
}, },
/*
test_sign_non_number: function() { test_sign_non_number: function() {
if (sign("5") != null) throw "sign non-number should return null" if (sign("5") != null) throw "sign non-number should return null"
}, },
*/
// ============================================================================ // ============================================================================
// WHOLE AND FRACTION FUNCTIONS // WHOLE AND FRACTION FUNCTIONS
// ============================================================================ // ============================================================================
@@ -2556,7 +2556,7 @@ return {
test_whole_integer: function() { test_whole_integer: function() {
if (whole(5) != 5) throw "whole integer failed" if (whole(5) != 5) throw "whole integer failed"
}, },
/*
test_whole_non_number: function() { test_whole_non_number: function() {
if (whole("5") != null) throw "whole non-number should return null" if (whole("5") != null) throw "whole non-number should return null"
}, },
@@ -2565,7 +2565,7 @@ return {
var f = fraction(3.75) var f = fraction(3.75)
if (f < 0.74 || f > 0.76) throw "fraction positive failed: " + f if (f < 0.74 || f > 0.76) throw "fraction positive failed: " + f
}, },
*/
test_fraction_negative: function() { test_fraction_negative: function() {
var f = fraction(-3.75) var f = fraction(-3.75)
if (f > -0.74 || f < -0.76) throw "fraction negative failed: " + f if (f > -0.74 || f < -0.76) throw "fraction negative failed: " + f
@@ -2574,11 +2574,11 @@ return {
test_fraction_integer: function() { test_fraction_integer: function() {
if (fraction(5) != 0) throw "fraction integer failed" if (fraction(5) != 0) throw "fraction integer failed"
}, },
/*
test_fraction_non_number: function() { test_fraction_non_number: function() {
if (fraction("5") != null) throw "fraction non-number should return null" if (fraction("5") != null) throw "fraction non-number should return null"
}, },
*/
// ============================================================================ // ============================================================================
// NEG FUNCTION // NEG FUNCTION
// ============================================================================ // ============================================================================
@@ -2598,11 +2598,11 @@ return {
test_neg_float: function() { test_neg_float: function() {
if (neg(3.14) != -3.14) throw "neg float failed" if (neg(3.14) != -3.14) throw "neg float failed"
}, },
/*
test_neg_non_number: function() { test_neg_non_number: function() {
if (neg("5") != null) throw "neg non-number should return null" if (neg("5") != null) throw "neg non-number should return null"
}, },
*/
// ============================================================================ // ============================================================================
// MODULO FUNCTION // MODULO FUNCTION
// ============================================================================ // ============================================================================
@@ -2662,12 +2662,12 @@ return {
test_min_float: function() { test_min_float: function() {
if (min(3.14, 2.71) != 2.71) throw "min float failed" if (min(3.14, 2.71) != 2.71) throw "min float failed"
}, },
/*
test_min_non_number: function() { test_min_non_number: function() {
if (min(3, "5") != null) throw "min non-number should return null" if (min(3, "5") != null) throw "min non-number should return null"
if (min("3", 5) != null) throw "min first non-number should return null" if (min("3", 5) != null) throw "min first non-number should return null"
}, },
*/
test_max_basic: function() { test_max_basic: function() {
if (max(3, 5) != 5) throw "max basic failed" if (max(3, 5) != 5) throw "max basic failed"
}, },
@@ -2687,11 +2687,11 @@ return {
test_max_float: function() { test_max_float: function() {
if (max(3.14, 2.71) != 3.14) throw "max float failed" if (max(3.14, 2.71) != 3.14) throw "max float failed"
}, },
/*
test_max_non_number: function() { test_max_non_number: function() {
if (max(3, "5") != null) throw "max non-number should return null" if (max(3, "5") != null) throw "max non-number should return null"
}, },
*/
test_min_max_constrain: function() { test_min_max_constrain: function() {
var val = 8 var val = 8
var constrained = min(max(val, 0), 10) var constrained = min(max(val, 0), 10)
@@ -2859,12 +2859,12 @@ return {
test_text_number_negative: function() { test_text_number_negative: function() {
if (text(-456) != "-456") throw "text number negative failed" if (text(-456) != "-456") throw "text number negative failed"
}, },
/*
test_text_number_float: function() { test_text_number_float: function() {
var result = text(3.14) var result = text(3.14)
if (search(result, "3.14") != 0) throw "text number float failed" if (search(result, "3.14") != 0) throw "text number float failed"
}, },
*/
test_text_array_join: function() { test_text_array_join: function() {
var result = text([1, 2, 3], ",") var result = text([1, 2, 3], ",")
if (result != "1,2,3") throw "text array join failed" if (result != "1,2,3") throw "text array join failed"
@@ -3289,13 +3289,13 @@ return {
var result = array(arr, (x, i) => `${x}${i}`) var result = array(arr, (x, i) => `${x}${i}`)
if (result[0] != "a0" || result[1] != "b1") throw "array map with index failed" if (result[0] != "a0" || result[1] != "b1") throw "array map with index failed"
}, },
/*
test_array_map_reverse: function() { test_array_map_reverse: function() {
var arr = [1, 2, 3] var arr = [1, 2, 3]
var result = array(arr, x => x * 2, true) var result = array(arr, x => x * 2, true)
if (result[0] != 6 || result[2] != 2) throw "array map reverse failed" if (result[0] != 6 || result[2] != 2) throw "array map reverse failed"
}, },
*/
test_array_map_with_exit: function() { test_array_map_with_exit: function() {
var arr = [1, 2, 3, 4, 5] var arr = [1, 2, 3, 4, 5]
var result = array(arr, x => { var result = array(arr, x => {