fix tests; add comprehensive tests for functions and fix bugs in the mach VM regarding them.
This commit is contained in:
136
source/runtime.c
136
source/runtime.c
@@ -11503,15 +11503,20 @@ static JSValue js_cell_is_upper (JSContext *ctx, JSValue this_val, int argc, JSV
|
||||
return JS_NewBool (ctx, c >= 'A' && c <= 'Z');
|
||||
}
|
||||
|
||||
/* is_whitespace(val) - check if value is a single whitespace character */
|
||||
/* is_whitespace(val) - check if all characters are whitespace (non-empty) */
|
||||
static JSValue js_cell_is_whitespace (JSContext *ctx, JSValue this_val, int argc, JSValue *argv) {
|
||||
if (argc < 1) return JS_FALSE;
|
||||
JSValue val = argv[0];
|
||||
if (!JS_IsText (val)) return JS_FALSE;
|
||||
if (js_string_value_len (val) != 1) return JS_FALSE;
|
||||
uint32_t c = js_string_value_get (val, 0);
|
||||
return JS_NewBool (ctx, c == ' ' || c == '\t' || c == '\n'
|
||||
|| c == '\r' || c == '\f' || c == '\v');
|
||||
int len = js_string_value_len (val);
|
||||
if (len == 0) return JS_FALSE;
|
||||
for (int i = 0; i < len; i++) {
|
||||
uint32_t c = js_string_value_get (val, i);
|
||||
if (!(c == ' ' || c == '\t' || c == '\n'
|
||||
|| c == '\r' || c == '\f' || c == '\v'))
|
||||
return JS_FALSE;
|
||||
}
|
||||
return JS_TRUE;
|
||||
}
|
||||
|
||||
/* is_proto(val, master) - check if val has master in prototype chain */
|
||||
@@ -11571,6 +11576,47 @@ static JSValue js_cell_logical(JSContext *ctx, JSValue this_val, int argc, JSVal
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
/* realloc wrapper for unicode_normalize */
|
||||
static void *normalize_realloc(void *opaque, void *ptr, size_t size) {
|
||||
(void)opaque;
|
||||
if (size == 0) {
|
||||
pjs_free(ptr);
|
||||
return NULL;
|
||||
}
|
||||
return pjs_realloc(ptr, size);
|
||||
}
|
||||
|
||||
/* normalize(text) — NFC normalization */
|
||||
static JSValue js_cell_normalize(JSContext *ctx, JSValue this_val, int argc, JSValue *argv) {
|
||||
if (argc < 1) return JS_NULL;
|
||||
JSValue val = argv[0];
|
||||
if (!JS_IsText(val)) return JS_NULL;
|
||||
int len = js_string_value_len(val);
|
||||
if (len == 0) return JS_NewString(ctx, "");
|
||||
uint32_t *src = pjs_malloc(len * sizeof(uint32_t));
|
||||
if (!src) return JS_EXCEPTION;
|
||||
for (int i = 0; i < len; i++)
|
||||
src[i] = js_string_value_get(val, i);
|
||||
uint32_t *dst = NULL;
|
||||
int dst_len = unicode_normalize(&dst, src, len, UNICODE_NFC, NULL,
|
||||
normalize_realloc);
|
||||
pjs_free(src);
|
||||
if (dst_len < 0) {
|
||||
pjs_free(dst);
|
||||
return JS_NULL;
|
||||
}
|
||||
JSText *str = js_alloc_string(ctx, dst_len);
|
||||
if (!str) {
|
||||
pjs_free(dst);
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
for (int i = 0; i < dst_len; i++)
|
||||
string_put(str, i, dst[i]);
|
||||
str->length = dst_len;
|
||||
pjs_free(dst);
|
||||
return pretext_end(ctx, str);
|
||||
}
|
||||
|
||||
/* starts_with(str, prefix) — search(str, prefix) == 0 */
|
||||
static JSValue js_cell_starts_with(JSContext *ctx, JSValue this_val, int argc, JSValue *argv) {
|
||||
if (argc < 2) return JS_NULL;
|
||||
@@ -11616,6 +11662,85 @@ static JSValue js_cell_some(JSContext *ctx, JSValue this_val, int argc, JSValue
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/* C API: Type-check wrappers for sensory functions */
|
||||
JS_BOOL JS_IsDigit (JSContext *ctx, JSValue val) {
|
||||
JSValue r = js_cell_is_digit (ctx, JS_NULL, 1, &val);
|
||||
return JS_VALUE_GET_BOOL (r);
|
||||
}
|
||||
|
||||
JS_BOOL JS_IsLetter (JSContext *ctx, JSValue val) {
|
||||
JSValue r = js_cell_is_letter (ctx, JS_NULL, 1, &val);
|
||||
return JS_VALUE_GET_BOOL (r);
|
||||
}
|
||||
|
||||
JS_BOOL JS_IsLower (JSContext *ctx, JSValue val) {
|
||||
JSValue r = js_cell_is_lower (ctx, JS_NULL, 1, &val);
|
||||
return JS_VALUE_GET_BOOL (r);
|
||||
}
|
||||
|
||||
JS_BOOL JS_IsUpper (JSContext *ctx, JSValue val) {
|
||||
JSValue r = js_cell_is_upper (ctx, JS_NULL, 1, &val);
|
||||
return JS_VALUE_GET_BOOL (r);
|
||||
}
|
||||
|
||||
JS_BOOL JS_IsWhitespace (JSContext *ctx, JSValue val) {
|
||||
JSValue r = js_cell_is_whitespace (ctx, JS_NULL, 1, &val);
|
||||
return JS_VALUE_GET_BOOL (r);
|
||||
}
|
||||
|
||||
JS_BOOL JS_IsCharacter (JSContext *ctx, JSValue val) {
|
||||
JSValue r = js_cell_is_character (ctx, JS_NULL, 1, &val);
|
||||
return JS_VALUE_GET_BOOL (r);
|
||||
}
|
||||
|
||||
JS_BOOL JS_IsFit (JSContext *ctx, JSValue val) {
|
||||
JSValue r = js_cell_is_fit (ctx, JS_NULL, 1, &val);
|
||||
return JS_VALUE_GET_BOOL (r);
|
||||
}
|
||||
|
||||
JS_BOOL JS_IsData (JSValue val) {
|
||||
return !JS_IsNull (val) && !JS_IsFunction (val);
|
||||
}
|
||||
|
||||
JS_BOOL JS_IsActor (JSContext *ctx, JSValue val) {
|
||||
JSValue r = js_cell_is_actor (ctx, JS_NULL, 1, &val);
|
||||
return JS_VALUE_GET_BOOL (r);
|
||||
}
|
||||
|
||||
/* C API: logical(val) */
|
||||
JSValue JS_CellLogical (JSContext *ctx, JSValue val) {
|
||||
return js_cell_logical (ctx, JS_NULL, 1, &val);
|
||||
}
|
||||
|
||||
/* C API: every(arr, pred) */
|
||||
JSValue JS_CellEvery (JSContext *ctx, JSValue arr, JSValue pred) {
|
||||
JSValue argv[2] = { arr, pred };
|
||||
return js_cell_every (ctx, JS_NULL, 2, argv);
|
||||
}
|
||||
|
||||
/* C API: some(arr, pred) */
|
||||
JSValue JS_CellSome (JSContext *ctx, JSValue arr, JSValue pred) {
|
||||
JSValue argv[2] = { arr, pred };
|
||||
return js_cell_some (ctx, JS_NULL, 2, argv);
|
||||
}
|
||||
|
||||
/* C API: starts_with(text, prefix) */
|
||||
JSValue JS_CellStartsWith (JSContext *ctx, JSValue text, JSValue prefix) {
|
||||
JSValue argv[2] = { text, prefix };
|
||||
return js_cell_starts_with (ctx, JS_NULL, 2, argv);
|
||||
}
|
||||
|
||||
/* C API: ends_with(text, suffix) */
|
||||
JSValue JS_CellEndsWith (JSContext *ctx, JSValue text, JSValue suffix) {
|
||||
JSValue argv[2] = { text, suffix };
|
||||
return js_cell_ends_with (ctx, JS_NULL, 2, argv);
|
||||
}
|
||||
|
||||
/* C API: normalize(text) */
|
||||
JSValue JS_CellNormalize (JSContext *ctx, JSValue text) {
|
||||
return js_cell_normalize (ctx, JS_NULL, 1, &text);
|
||||
}
|
||||
|
||||
static void js_set_global_cfunc(JSContext *ctx, const char *name, JSCFunction *func, int length) {
|
||||
JSGCRef ref;
|
||||
JS_PushGCRef(ctx, &ref);
|
||||
@@ -11740,6 +11865,7 @@ static void JS_AddIntrinsicBaseObjects (JSContext *ctx) {
|
||||
js_set_global_cfunc(ctx, "ends_with", js_cell_ends_with, 2);
|
||||
js_set_global_cfunc(ctx, "every", js_cell_every, 2);
|
||||
js_set_global_cfunc(ctx, "some", js_cell_some, 2);
|
||||
js_set_global_cfunc(ctx, "normalize", js_cell_normalize, 1);
|
||||
|
||||
/* fn record with apply property */
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user