diff --git a/build.cm b/build.cm index 4b744de9..50837db0 100644 --- a/build.cm +++ b/build.cm @@ -28,7 +28,7 @@ function get_local_dir() { // Replace sigils in a string // Currently supports: $LOCAL -> .cell/local full path function replace_sigils(str) { - return str.replaceAll('$LOCAL', get_local_dir()) + return replace(str, '$LOCAL', get_local_dir()) } // Replace sigils in an array of flags diff --git a/internal/engine.cm b/internal/engine.cm index 7c44284b..0b15504e 100644 --- a/internal/engine.cm +++ b/internal/engine.cm @@ -54,6 +54,7 @@ globalThis.ends_with = function(str, suffix) { } var js = use_embed('js') +os.print(js) var fd = use_embed('fd') // Get the shop path from HOME environment @@ -78,7 +79,7 @@ function use_core(path) { if (use_cache[cache_key]) return use_cache[cache_key]; - var sym = use_embed(path.replaceAll('/','_')) + var sym = use_embed(replace(path, '/', '_')) // Core scripts are in packages/core/ var file_path = core_path + '/' + path + MOD_EXT diff --git a/internal/shop.cm b/internal/shop.cm index 27a98058..40e4a864 100644 --- a/internal/shop.cm +++ b/internal/shop.cm @@ -247,13 +247,13 @@ function safe_package_path(pkg) // For absolute paths, replace / with _ to create a valid directory name // Also replace @ with _ if (pkg && starts_with(pkg, '/')) - return pkg.replaceAll('/', '_').replaceAll('@', '_') - return pkg.replaceAll('@', '_') + return replace(replace(pkg, '/', '_'), '@', '_') + return replace(pkg, '@', '_') } function package_cache_path(pkg) { - return global_shop_path + '/cache/' + pkg.replaceAll('/', '_').replaceAll('@', '_') + return global_shop_path + '/cache/' + replace(replace(pkg, '/', '_'), '@', '_') } function get_shared_lib_path() @@ -519,15 +519,15 @@ function resolve_locator(path, ctx) // Uses the same format as Shop.c_symbol_for_file // Symbol names are based on canonical package names, not link targets function make_c_symbol(pkg, file) { - var pkg_safe = pkg.replace(/\//g, '_').replace(/\./g, '_').replace(/-/g, '_') - var file_safe = file.replace(/\//g, '_').replace(/\./g, '_').replace(/-/g, '_') + var pkg_safe = replace(replace(replace(pkg, '/', '_'), '.', '_'), '-', '_') + var file_safe = replace(replace(replace(file, '/', '_'), '.', '_'), '-', '_') return 'js_' + pkg_safe + '_' + file_safe + '_use' } // Get the library path for a package in .cell/lib // Library names are based on canonical package names, not link targets function get_lib_path(pkg) { - var lib_name = pkg.replace(/\//g, '_').replace(/\./g, '_').replace(/-/g, '_') + var lib_name = replace(replace(replace(pkg, '/', '_'), '.', '_'), '-', '_') return global_shop_path + '/lib/' + lib_name + dylib_ext } @@ -615,7 +615,7 @@ function resolve_c_symbol(path, package_context) { // If no package context, only check core internal symbols if (!package_context || package_context == 'core') { - path = path.replaceAll('/', '_') + path = replace(path, '/', '_') var core_sym = `js_${path}_use` if (os.internal_exists(core_sym)) { return { @@ -684,7 +684,7 @@ function resolve_c_symbol(path, package_context) { } // 3. Check core internal symbols (core is never a dynamic library) - var core_sym = `js_${path.replaceAll('/', '_')}_use` + var core_sym = `js_${replace(path, '/', '_')}_use` if (os.internal_exists(core_sym)) { return { symbol: function() { return os.load_internal(core_sym) }, @@ -846,7 +846,7 @@ Shop.resolve_locator = resolve_locator // Get cache path for a package and commit function get_cache_path(pkg, commit) { - return global_shop_path + '/cache/' + pkg.replaceAll('@','_').replaceAll('/','_') + '_' + commit + '.zip' + return global_shop_path + '/cache/' + replace(replace(pkg, '@','_'), '/','_') + '_' + commit + '.zip' } function get_package_abs_dir(package) @@ -1250,22 +1250,22 @@ Shop.get_package_dir = function(pkg) { // e.g., c_symbol_for_file('gitea.pockle.world/john/prosperon', 'sprite.c') // -> 'js_gitea_pockle_world_john_prosperon_sprite_use' Shop.c_symbol_for_file = function(pkg, file) { - var pkg_safe = pkg.replaceAll(/\//g, '_').replaceAll(/\./g, '_').replaceAll(/-/g, '_') - var file_safe = text(file, 0, file.lastIndexOf('.')).replaceAll(/\//g, '_').replaceAll(/\./g, '_').replaceAll(/-/g, '_') + var pkg_safe = replace(replace(replace(pkg, '/', '_'), '.', '_'), '-', '_') + var file_safe = replace(replace(text(file, 0, file.lastIndexOf('.')), '/', '_'), '.', '_') return 'js_' + pkg_safe + '_' + file_safe + '_use' } // Generate C symbol prefix for a package // e.g., c_symbol_prefix('gitea.pockle.world/john/prosperon') -> 'js_gitea_pockle_world_john_prosperon_' Shop.c_symbol_prefix = function(pkg) { - var pkg_safe = pkg.replaceAll(/\//g, '_').replaceAll(/\./g, '_').replaceAll(/-/g, '_') + var pkg_safe = replace(replace(replace(pkg, '/', '_'), '.', '_'), '-', '_') return 'js_' + pkg_safe + '_' } // Get the library name for a package (without extension) // e.g., 'gitea.pockle.world/john/prosperon' -> 'gitea_pockle_world_john_prosperon' Shop.lib_name_for_package = function(pkg) { - return pkg.replaceAll(/\//g, '_').replaceAll(/\./g, '_').replaceAll(/-/g, '_') + return replace(replace(replace(pkg, '/', '_'), '.', '_'), '-', '_') } // Returns { ok: bool, results: [{pkg, ok, error}] } diff --git a/link.cm b/link.cm index c025e637..c6a4cce9 100644 --- a/link.cm +++ b/link.cm @@ -22,8 +22,8 @@ function get_packages_dir() { function safe_package_path(pkg) { // For absolute paths, replace / with _ to create a valid directory name if (pkg && starts_with(pkg, '/')) - return pkg.replaceAll('/', '_').replaceAll('@', '_') - return pkg.replaceAll('@', '_') + return replace(replace(pkg, '/', '_'), '@', '_') + return replace(pkg, '@', '_') } function get_package_abs_dir(package) { diff --git a/package.cm b/package.cm index 1072f2c2..1b22989d 100644 --- a/package.cm +++ b/package.cm @@ -12,8 +12,8 @@ var link = use('link') function safe_package_path(pkg) { if (!pkg) return pkg if (starts_with(pkg, '/')) - return pkg.replaceAll('/', '_').replaceAll('@', '_') - return pkg.replaceAll('@', '_') + return replace(replace(pkg, '/', '_'), '@', '_') + return replace(pkg, '@', '_') } function get_path(name) @@ -33,11 +33,11 @@ function get_path(name) if (starts_with(link_target, '/')) return link_target // Otherwise it's another package name, resolve that - return os.global_shop_path + '/packages/' + link_target.replaceAll('@', '_') + return os.global_shop_path + '/packages/' + replace(replace(link_target, '/', '_'), '@', '_') } // Remote packages use nested directories, so don't transform slashes - return os.global_shop_path + '/packages/' + name.replaceAll('@', '_') + return os.global_shop_path + '/packages/' + replace(name, '@', '_') } package.load_config = function(name) @@ -261,13 +261,13 @@ package.get_flags = function(name, flag_type, target) { // Base flags if (config.compilation && config.compilation[flag_type]) { var base = config.compilation[flag_type] - flags = flags.concat(filter(array(base, /\s+/), function(f) { return f.length > 0 })) + flags = array(flags, filter(array(base, /\s+/), function(f) { return f.length > 0 })) } // Target-specific flags if (target && config.compilation && config.compilation[target] && config.compilation[target][flag_type]) { var target_flags = config.compilation[target][flag_type] - flags = flags.concat(filter(array(target_flags, /\s+/), function(f) { return f.length > 0 })) + flags = array(flags, filter(array(target_flags, /\s+/), function(f) { return f.length > 0 })) } return flags diff --git a/source/quickjs.c b/source/quickjs.c index 88d28492..c9687628 100644 --- a/source/quickjs.c +++ b/source/quickjs.c @@ -29592,72 +29592,6 @@ static int JS_isConcatSpreadable(JSContext *ctx, JSValueConst obj) return JS_IsArray(ctx, obj); } -static JSValue js_array_concat(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSValue obj, arr, val; - JSValueConst e; - int64_t len, k, n; - int i, res; - - arr = JS_NULL; - obj = JS_ToObject(ctx, this_val); - if (JS_IsException(obj)) - goto exception; - - arr = JS_ArraySpeciesCreate(ctx, obj, JS_NewInt32(ctx, 0)); - if (JS_IsException(arr)) - goto exception; - n = 0; - for (i = -1; i < argc; i++) { - if (i < 0) - e = obj; - else - e = argv[i]; - - res = JS_isConcatSpreadable(ctx, e); - if (res < 0) - goto exception; - if (res) { - if (js_get_length64(ctx, &len, e)) - goto exception; - if (n + len > MAX_SAFE_INTEGER) { - JS_ThrowTypeError(ctx, "Array loo long"); - goto exception; - } - for (k = 0; k < len; k++, n++) { - res = JS_TryGetPropertyInt64(ctx, e, k, &val); - if (res < 0) - goto exception; - if (res) { - if (JS_DefinePropertyValueInt64(ctx, arr, n, val, - JS_PROP_C_W_E | JS_PROP_THROW) < 0) - goto exception; - } - } - } else { - if (n >= MAX_SAFE_INTEGER) { - JS_ThrowTypeError(ctx, "Array loo long"); - goto exception; - } - if (JS_DefinePropertyValueInt64(ctx, arr, n, JS_DupValue(ctx, e), - JS_PROP_C_W_E | JS_PROP_THROW) < 0) - goto exception; - n++; - } - } - if (JS_SetProperty(ctx, arr, JS_ATOM_length, JS_NewInt64(ctx, n)) < 0) - goto exception; - - JS_FreeValue(ctx, obj); - return arr; - -exception: - JS_FreeValue(ctx, arr); - JS_FreeValue(ctx, obj); - return JS_EXCEPTION; -} - static JSValue js_array_includes(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { @@ -29990,50 +29924,6 @@ fail: return -1; } -static JSValue js_array_flatten(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv, int map) -{ - JSValue obj, arr; - JSValueConst mapperFunction, thisArg; - int64_t sourceLen; - int depthNum; - - arr = JS_NULL; - obj = JS_ToObject(ctx, this_val); - if (js_get_length64(ctx, &sourceLen, obj)) - goto exception; - - depthNum = 1; - mapperFunction = JS_NULL; - thisArg = JS_NULL; - if (map) { - mapperFunction = argv[0]; - if (argc > 1) { - thisArg = argv[1]; - } - if (check_function(ctx, mapperFunction)) - goto exception; - } else { - if (argc > 0 && !JS_IsNull(argv[0])) { - if (JS_ToInt32Sat(ctx, &depthNum, argv[0]) < 0) - goto exception; - } - } - arr = JS_ArraySpeciesCreate(ctx, obj, JS_NewInt32(ctx, 0)); - if (JS_IsException(arr)) - goto exception; - if (JS_FlattenIntoArray(ctx, arr, obj, sourceLen, 0, depthNum, - mapperFunction, thisArg) < 0) - goto exception; - JS_FreeValue(ctx, obj); - return arr; - -exception: - JS_FreeValue(ctx, obj); - JS_FreeValue(ctx, arr); - return JS_EXCEPTION; -} - typedef struct JSArrayIteratorData { JSValue obj; JSIteratorKindEnum kind; @@ -30177,7 +30067,6 @@ static const JSCFunctionListEntry js_iterator_proto_funcs[] = { }; static const JSCFunctionListEntry js_array_proto_funcs[] = { - JS_CFUNC_DEF("concat", 1, js_array_concat ), JS_CFUNC_DEF("toString", 0, js_array_toString ), JS_CFUNC_MAGIC_DEF("pop", 0, js_array_pop, 0 ), JS_CFUNC_MAGIC_DEF("push", 1, js_array_push, 0 ), @@ -30185,8 +30074,6 @@ static const JSCFunctionListEntry js_array_proto_funcs[] = { JS_CFUNC_MAGIC_DEF("unshift", 1, js_array_push, 1 ), JS_CFUNC_MAGIC_DEF("slice", 2, js_array_slice, 0 ), JS_CFUNC_MAGIC_DEF("splice", 2, js_array_slice, 1 ), - JS_CFUNC_MAGIC_DEF("flatMap", 1, js_array_flatten, 1 ), - JS_CFUNC_MAGIC_DEF("flat", 0, js_array_flatten, 0 ), JS_CFUNC_MAGIC_DEF("values", 0, js_create_array_iterator, JS_ITERATOR_KIND_VALUE ), JS_ALIAS_DEF("[Symbol.iterator]", "values" ), JS_CFUNC_MAGIC_DEF("keys", 0, js_create_array_iterator, JS_ITERATOR_KIND_KEY ), @@ -30336,24 +30223,6 @@ static JSValue js_thisStringValue(JSContext *ctx, JSValueConst this_val) return JS_ThrowTypeError(ctx, "not a string"); } -static JSValue js_string_concat(JSContext *ctx, JSValueConst this_val, - int argc, JSValueConst *argv) -{ - JSValue r; - int i; - - /* XXX: Use more efficient method */ - /* XXX: This method is OK if r has a single refcount */ - /* XXX: should use string_buffer? */ - r = JS_ToStringCheckObject(ctx, this_val); - for (i = 0; i < argc; i++) { - if (JS_IsException(r)) - break; - r = JS_ConcatString(ctx, r, JS_DupValue(ctx, argv[i])); - } - return r; -} - static int string_cmp(JSString *p1, JSString *p2, int x1, int x2, int len) { int i, c1, c2; @@ -30801,59 +30670,6 @@ exception: return JS_EXCEPTION; } -/* return 0 if before the first char */ -static int string_prevc(JSString *p, int *pidx) -{ - int idx, c, c1; - - idx = *pidx; - if (idx <= 0) - return 0; - idx--; - if (p->is_wide_char) { - c = p->u.str16[idx]; - if (is_lo_surrogate(c) && idx > 0) { - c1 = p->u.str16[idx - 1]; - if (is_hi_surrogate(c1)) { - c = from_surrogate(c1, c); - idx--; - } - } - } else { - c = p->u.str8[idx]; - } - *pidx = idx; - return c; -} - -static BOOL test_final_sigma(JSString *p, int sigma_pos) -{ - int k, c1; - - /* before C: skip case ignorable chars and check there is - a cased letter */ - k = sigma_pos; - for(;;) { - c1 = string_prevc(p, &k); - if (!lre_is_case_ignorable(c1)) - break; - } - if (!lre_is_cased(c1)) - return FALSE; - - /* after C: skip case ignorable chars and check there is - no cased letter */ - k = sigma_pos + 1; - for(;;) { - if (k >= p->len) - return TRUE; - c1 = string_getc(p, &k); - if (!lre_is_case_ignorable(c1)) - break; - } - return !lre_is_cased(c1); -} - /* also used for String.prototype.valueOf */ static JSValue js_string_toString(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) @@ -30901,7 +30717,6 @@ static JSValue js_string_iterator_next(JSContext *ctx, JSValueConst this_val, static const JSCFunctionListEntry js_string_proto_funcs[] = { JS_PROP_INT32_DEF("length", 0, JS_PROP_CONFIGURABLE ), - JS_CFUNC_DEF("concat", 1, js_string_concat ), JS_CFUNC_MAGIC_DEF("indexOf", 1, js_string_indexOf, 0 ), JS_CFUNC_MAGIC_DEF("lastIndexOf", 1, js_string_indexOf, 1 ), JS_CFUNC_MAGIC_DEF("match", 1, js_string_match, JS_ATOM_Symbol_match ), diff --git a/tests/suite.cm b/tests/suite.cm index bc91f30c..3e61ae6a 100644 --- a/tests/suite.cm +++ b/tests/suite.cm @@ -1528,7 +1528,7 @@ return { test_array_concat: function() { var arr1 = [1, 2] var arr2 = [3, 4] - var combined = arr1.concat(arr2) + var combined = array(arr1, arr2) if (length(combined) != 4) throw "array concat length failed" if (combined[2] != 3) throw "array concat values failed" }, @@ -1592,12 +1592,6 @@ return { if (parts[1] != "b") throw "string split values failed" }, - test_string_replace: function() { - var str = "hello world" - var replaced = str.replace("world", "universe") - if (replaced != "hello universe") throw "string replace failed" - }, - test_string_match: function() { var str = "hello123" var hasNumbers = /\d/.test(str) @@ -3422,12 +3416,6 @@ return { if (some(arr, x => x > 5)) throw "array some no match failed" }, - test_array_flat: function() { - var arr = [1, [2, 3], [4, [5]]] - var flat = arr.flat() - if (flat[0] != 1 || flat[1] != 2 || flat[2] != 3) throw "array flat failed" - }, - // ============================================================================ // LOGICAL FUNCTION // ============================================================================ diff --git a/time.cm b/time.cm index a49f0b7b..bf7d72e1 100644 --- a/time.cm +++ b/time.cm @@ -162,41 +162,41 @@ function time_text(num = now(), /* am/pm */ if (search(fmt, "a") != null) { - if (rec.hour >= 13) { rec.hour -= 12; fmt = fmt.replaceAll("a", "PM"); } - else if (rec.hour == 12) { fmt = fmt.replaceAll("a", "PM"); } - else if (rec.hour == 0) { rec.hour = 12; fmt = fmt.replaceAll("a", "AM"); } - else fmt = fmt.replaceAll("a", "AM"); + if (rec.hour >= 13) { rec.hour -= 12; fmt = replace(fmt, "a", "PM"); } + else if (rec.hour == 12) { fmt = replace(fmt, "a", "PM"); } + else if (rec.hour == 0) { rec.hour = 12; fmt = replace(fmt, "a", "AM"); } + else fmt = replace(fmt, "a", "AM"); } /* BCE/CE */ var year = rec.year > 0 ? rec.year : rec.year - 1; if (search(fmt, "c") != null) { - if (year < 0) { year = abs(year); fmt = fmt.replaceAll("c", "BC"); } - else fmt = fmt.replaceAll("c", "AD"); + if (year < 0) { year = abs(year); fmt = replace(fmt, "c", "BC"); } + else fmt = replace(fmt, "c", "AD"); } /* substitutions */ var full_offset = zone + (dst ? 1 : 0); - fmt = fmt.replaceAll("yyyy", text(year, "i4")) - fmt = fmt.replaceAll("y", year); - fmt = fmt.replaceAll("eee", rec.yday + 1); - fmt = fmt.replaceAll("dd", text(rec.day, "i2")) - fmt = fmt.replaceAll("d", rec.day); - fmt = fmt.replaceAll("hh", text(rec.hour, "i2")); - fmt = fmt.replaceAll("h", rec.hour); - fmt = fmt.replaceAll("nn", text(rec.minute, "i2")); - fmt = fmt.replaceAll("n", rec.minute); - fmt = fmt.replaceAll("ss", text(rec.second, "i2")); - fmt = fmt.replaceAll("s", rec.second); - fmt = fmt.replaceAll("x", dst ? "DST" : ""); /* new */ - fmt = fmt.replaceAll("z", (full_offset >= 0 ? "+" : "") + text(full_offset)); + fmt = replace(fmt, "yyyy", text(year, "i4")) + fmt = replace(fmt, "y", year); + fmt = replace(fmt, "eee", rec.yday + 1); + fmt = replace(fmt, "dd", text(rec.day, "i2")) + fmt = replace(fmt, "d", rec.day); + fmt = replace(fmt, "hh", text(rec.hour, "i2")); + fmt = replace(fmt, "h", rec.hour); + fmt = replace(fmt, "nn", text(rec.minute, "i2")); + fmt = replace(fmt, "n", rec.minute); + fmt = replace(fmt, "ss", text(rec.second, "i2")); + fmt = replace(fmt, "s", rec.second); + fmt = replace(fmt, "x", dst ? "DST" : ""); /* new */ + fmt = replace(fmt, "z", (full_offset >= 0 ? "+" : "") + text(full_offset)); fmt = fmt.replaceAll(/mm[^bB]/g, rec.month + 1); fmt = fmt.replaceAll(/m[^bB]/g, rec.month + 1); fmt = fmt.replaceAll(/v[^bB]/g, rec.weekday); - fmt = fmt.replaceAll("mb", text(time.monthstr[rec.month], 0, 3)); - fmt = fmt.replaceAll("mB", time.monthstr[rec.month]); - fmt = fmt.replaceAll("vB", time.weekdays[rec.weekday]); - fmt = fmt.replaceAll("vb", text(time.weekdays[rec.weekday], 0, 3)); + fmt = replace(fmt, "mb", text(time.monthstr[rec.month], 0, 3)); + fmt = replace(fmt, "mB", time.monthstr[rec.month]); + fmt = replace(fmt, "vB", time.weekdays[rec.weekday]); + fmt = replace(fmt, "vb", text(time.weekdays[rec.weekday], 0, 3)); return fmt; } diff --git a/toml.cm b/toml.cm index c6bde1d2..e7f1531c 100644 --- a/toml.cm +++ b/toml.cm @@ -1,7 +1,5 @@ // Simple TOML parser for cell modules // Supports basic TOML features needed for the module system -// -// Avoids regex .replace(/.../g, ...) so no global-regex state issues. function toml_unescape(s) { if (!is_text(s)) return null