remove internal scripts
This commit is contained in:
8
bench.ce
8
bench.ce
@@ -3,7 +3,7 @@ var pkg = use('package')
|
||||
var fd = use('fd')
|
||||
var time = use('time')
|
||||
var json = use('json')
|
||||
var utf8 = use('utf8')
|
||||
var blob = use('blob')
|
||||
var os = use('os')
|
||||
var testlib = use('internal/testlib')
|
||||
var math = use('math/radians')
|
||||
@@ -524,7 +524,7 @@ log.console(`Benchmarks: ${total_benches} total`)
|
||||
|
||||
// Generate reports
|
||||
function generate_reports() {
|
||||
var timestamp = number.floor(time.number()).toString()
|
||||
var timestamp = text(number.floor(time.number()))
|
||||
var report_dir = shop.get_reports_dir() + '/bench_' + timestamp
|
||||
testlib.ensure_dir(report_dir)
|
||||
|
||||
@@ -578,7 +578,7 @@ Total benchmarks: ${total_benches}
|
||||
}
|
||||
|
||||
testlib.ensure_dir(report_dir)
|
||||
fd.slurpwrite(`${report_dir}/bench.txt`, utf8.encode(txt_report))
|
||||
fd.slurpwrite(`${report_dir}/bench.txt`, stone(new blob(txt_report)))
|
||||
log.console(`Report written to ${report_dir}/bench.txt`)
|
||||
|
||||
// Generate JSON per package
|
||||
@@ -595,7 +595,7 @@ Total benchmarks: ${total_benches}
|
||||
}
|
||||
|
||||
var json_path = `${report_dir}/${pkg_res.package.replace(/\//g, '_')}.json`
|
||||
fd.slurpwrite(json_path, utf8.encode(json.encode(pkg_benches)))
|
||||
fd.slurpwrite(json_path, stone(new blob(json.encode(pkg_benches))))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
4
build.cm
4
build.cm
@@ -8,7 +8,7 @@
|
||||
|
||||
var fd = use('fd')
|
||||
var crypto = use('crypto')
|
||||
var utf8 = use('utf8')
|
||||
var blob = use('blob')
|
||||
var os = use('os')
|
||||
var toolchains = use('toolchains')
|
||||
var shop = use('internal/shop')
|
||||
@@ -73,7 +73,7 @@ Build.detect_host_target = function() {
|
||||
// ============================================================================
|
||||
|
||||
function content_hash(str) {
|
||||
return text(crypto.blake2(utf8.encode(str)), 'h')
|
||||
return text(crypto.blake2(new blob(str)), 'h')
|
||||
}
|
||||
|
||||
function get_build_dir() {
|
||||
|
||||
@@ -28,18 +28,6 @@ function use_embed(name) {
|
||||
return load_internal(`js_${name}_use`)
|
||||
}
|
||||
|
||||
globalThis.meme = function(obj, ...mixins) {
|
||||
var result = _ObjectCreate(obj)
|
||||
|
||||
array.for(mixins, mix => {
|
||||
if (is_object(mix)) {
|
||||
for (var key in mix)
|
||||
result[key] = mix[key]
|
||||
}
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
globalThis.logical = function(val1)
|
||||
{
|
||||
if (val1 == 0 || val1 == false || val1 == "false" || val1 == null)
|
||||
@@ -49,7 +37,6 @@ globalThis.logical = function(val1)
|
||||
return null;
|
||||
}
|
||||
|
||||
var utf8 = use_embed('utf8')
|
||||
var js = use_embed('js')
|
||||
var fd = use_embed('fd')
|
||||
|
||||
@@ -69,13 +56,6 @@ if (!fd.is_dir(core_path)) {
|
||||
var use_cache = {}
|
||||
use_cache['core/os'] = os
|
||||
|
||||
var _Symbol = Symbol
|
||||
|
||||
globalThis.key = function()
|
||||
{
|
||||
return _Symbol()
|
||||
}
|
||||
|
||||
// Load a core module from the file system
|
||||
function use_core(path) {
|
||||
var cache_key = 'core/' + path
|
||||
@@ -89,7 +69,7 @@ function use_core(path) {
|
||||
|
||||
if (fd.is_file(file_path)) {
|
||||
var script_blob = fd.slurp(file_path)
|
||||
var script = utf8.decode(script_blob)
|
||||
var script = text(script_blob)
|
||||
var mod = `(function setup_module(use){${script}})`
|
||||
var fn = js.eval('core:' + path, mod)
|
||||
var result = fn.call(sym, use_core);
|
||||
@@ -104,13 +84,6 @@ function use_core(path) {
|
||||
var blob = use_core('blob')
|
||||
|
||||
// Capture Object and Array methods before they're deleted
|
||||
var _Object = Object
|
||||
var _ObjectKeys = Object.keys
|
||||
var _ObjectIsFrozen = Object.isFrozen
|
||||
var _ObjectDefineProperty = Object.defineProperty
|
||||
var _ObjectGetPrototypeOf = Object.getPrototypeOf
|
||||
var _ObjectCreate = Object.create
|
||||
|
||||
Object.prototype.toString = function()
|
||||
{
|
||||
return json.encode(this)
|
||||
@@ -125,41 +98,9 @@ var actor_mod = use_core('actor')
|
||||
var wota = use_core('wota')
|
||||
var nota = use_core('nota')
|
||||
|
||||
// Global utility functions (use already-captured references)
|
||||
var _keys = _ObjectKeys
|
||||
var _getPrototypeOf = _ObjectGetPrototypeOf
|
||||
var _create = _ObjectCreate
|
||||
|
||||
globalThis.reverse = function(value) {
|
||||
if (_isArray(value)) {
|
||||
var result = []
|
||||
for (var i = value.length - 1; i >= 0; i--) {
|
||||
result.push(value[i])
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// For blobs, would need blob module support
|
||||
if (isa(value, blob)) {
|
||||
// Simplified: return null for now, would need proper blob reversal
|
||||
return null
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
globalThis.isa = function(value, master) {
|
||||
if (master == null) return false
|
||||
|
||||
// isa(value, array) - check if object has all keys
|
||||
if (_isArray(master)) {
|
||||
if (typeof value != 'object' || value == null) return false
|
||||
for (var i = 0; i < master.length; i++) {
|
||||
if (!(master[i] in value)) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// isa(value, function) - check if function.prototype is in chain
|
||||
if (typeof master == 'function') {
|
||||
// Special type checks
|
||||
@@ -196,55 +137,9 @@ globalThis.isa = function(value, master) {
|
||||
return false
|
||||
}
|
||||
|
||||
globalThis.proto = function(obj) {
|
||||
if (!isa(obj, object)) return null
|
||||
var p = _getPrototypeOf(obj)
|
||||
if (p == _Object.prototype) return null
|
||||
return p
|
||||
}
|
||||
|
||||
globalThis.splat = function(obj) {
|
||||
if (typeof obj != 'object' || obj == null) return null
|
||||
|
||||
var result = {}
|
||||
var current = obj
|
||||
|
||||
// Walk prototype chain and collect text keys
|
||||
while (current != null) {
|
||||
var keys = _keys(current)
|
||||
for (var i = 0; i < keys.length; i++) {
|
||||
var k = keys[i]
|
||||
if (!(k in result)) {
|
||||
var val = current[k]
|
||||
// Only include serializable types
|
||||
if (typeof val == 'object' || typeof val == 'number' ||
|
||||
typeof val == 'string' || typeof val == 'boolean') {
|
||||
result[k] = val
|
||||
}
|
||||
}
|
||||
}
|
||||
current = _getPrototypeOf(current)
|
||||
}
|
||||
|
||||
// Call to_data if present
|
||||
if (typeof obj.to_data == 'function') {
|
||||
var extra = obj.to_data(result)
|
||||
if (typeof extra == 'object' && extra != null) {
|
||||
var extraKeys = _keys(extra)
|
||||
for (var i = 0; i < extraKeys.length; i++) {
|
||||
result[extraKeys[i]] = extra[extraKeys[i]]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
var ENETSERVICE = 0.1
|
||||
var REPLYTIMEOUT = 60 // seconds before replies are ignored
|
||||
|
||||
globalThis.pi = 3.14159265358979323846264338327950288419716939937510
|
||||
|
||||
function caller_data(depth = 0)
|
||||
{
|
||||
var file = "nofile"
|
||||
@@ -453,7 +348,7 @@ function guid(bits = 256)
|
||||
return text(guid,'h')
|
||||
}
|
||||
|
||||
var HEADER = _Symbol()
|
||||
var HEADER = key()
|
||||
|
||||
// takes a function input value that will eventually be called with the current time in number form.
|
||||
$_.clock = function(fn) {
|
||||
@@ -771,7 +666,6 @@ function turn(msg)
|
||||
}
|
||||
|
||||
//log.console(`FIXME: need to get main from config, not just set to true`)
|
||||
//log.console(`FIXME: remove global access (ie globalThis.use)`)
|
||||
//log.console(`FIXME: add freeze/unfreeze at this level, so we can do it (but scripts cannot)`)
|
||||
actor_mod.register_actor(_cell.id, turn, true, config.ar_timer)
|
||||
|
||||
@@ -911,69 +805,11 @@ if (!locator) {
|
||||
if (!locator)
|
||||
throw new Error(`Main program ${_cell.args.program} could not be found`)
|
||||
|
||||
// Hide JavaScript built-ins - make them inaccessible
|
||||
// Store references we need internally before deleting
|
||||
var _Array = Array
|
||||
var _String = String
|
||||
var _Math = Math
|
||||
var _Function = Function
|
||||
|
||||
var _JSON = JSON
|
||||
|
||||
// juicing these before Math is gone
|
||||
|
||||
use_core('math/radians')
|
||||
use_core('math/cycles')
|
||||
use_core('math/degrees')
|
||||
|
||||
// Delete from globalThis
|
||||
delete globalThis.Object
|
||||
delete globalThis.Math
|
||||
delete globalThis.Number
|
||||
delete globalThis.String
|
||||
delete globalThis.Array
|
||||
delete globalThis.Boolean
|
||||
delete globalThis.Date
|
||||
delete globalThis.Function
|
||||
delete globalThis.Reflect
|
||||
delete globalThis.Proxy
|
||||
delete globalThis.WeakMap
|
||||
delete globalThis.WeakSet
|
||||
delete globalThis.WeakRef
|
||||
delete globalThis.BigInt
|
||||
delete globalThis.Symbol
|
||||
//delete globalThis.Map
|
||||
//delete globalThis.Set
|
||||
delete globalThis.Promise
|
||||
delete globalThis.ArrayBuffer
|
||||
delete globalThis.DataView
|
||||
delete globalThis.Int8Array
|
||||
delete globalThis.Uint8Array
|
||||
delete globalThis.Uint8ClampedArray
|
||||
delete globalThis.Int16Array
|
||||
delete globalThis.Uint16Array
|
||||
delete globalThis.Int32Array
|
||||
delete globalThis.Uint32Array
|
||||
delete globalThis.Float32Array
|
||||
delete globalThis.Float64Array
|
||||
delete globalThis.BigInt64Array
|
||||
delete globalThis.BigUint64Array
|
||||
delete globalThis.eval
|
||||
delete globalThis.parseInt
|
||||
delete globalThis.parseFloat
|
||||
delete globalThis.isNaN
|
||||
delete globalThis.isFinite
|
||||
delete globalThis.decodeURI
|
||||
delete globalThis.decodeURIComponent
|
||||
delete globalThis.encodeURI
|
||||
delete globalThis.encodeURIComponent
|
||||
delete globalThis.escape
|
||||
delete globalThis.unescape
|
||||
delete globalThis.Intl
|
||||
delete globalThis.RegExp
|
||||
|
||||
stone(globalThis)
|
||||
|
||||
var rads = use_core("math/radians")
|
||||
log.console(rads)
|
||||
|
||||
$_.clock(_ => {
|
||||
// Get capabilities for the main program
|
||||
var file_info = shop.file_info ? shop.file_info(locator.path) : null
|
||||
|
||||
@@ -6,7 +6,6 @@ var miniz = use('miniz')
|
||||
var time = use('time')
|
||||
var js = use('js')
|
||||
var crypto = use('crypto')
|
||||
var utf8 = use('utf8')
|
||||
var blob = use('blob')
|
||||
var pkg_tools = use('package')
|
||||
var os = use('os')
|
||||
@@ -277,7 +276,7 @@ Shop.load_lock = function() {
|
||||
// Save lock.toml configuration (to global shop)
|
||||
Shop.save_lock = function(lock) {
|
||||
var path = global_shop_path + '/lock.toml'
|
||||
fd.slurpwrite(path, utf8.encode(toml.encode(lock)));
|
||||
fd.slurpwrite(path, stone(new blob(toml.encode(lock))));
|
||||
}
|
||||
|
||||
|
||||
@@ -415,7 +414,7 @@ function resolve_mod_fn(path, pkg) {
|
||||
var content = text(fd.slurp(path))
|
||||
var script = script_form(path, content, file_pkg, inject);
|
||||
|
||||
var obj = pull_from_cache(utf8.encode(script))
|
||||
var obj = pull_from_cache(stone(new blob(script)))
|
||||
if (obj) {
|
||||
var fn = js.compile_unblob(obj)
|
||||
return js.eval_compile(fn)
|
||||
@@ -427,7 +426,7 @@ function resolve_mod_fn(path, pkg) {
|
||||
|
||||
var fn = js.compile(compile_name, script)
|
||||
|
||||
put_into_cache(utf8.encode(script), js.compile_blob(fn))
|
||||
put_into_cache(stone(new blob(script)), js.compile_blob(fn))
|
||||
|
||||
return js.eval_compile(fn)
|
||||
}
|
||||
@@ -608,7 +607,8 @@ Shop.open_package_dylib = function(pkg) {
|
||||
}
|
||||
|
||||
// If no package context, only check core internal symbols
|
||||
if (!package_context) {
|
||||
if (!package_context || package_context == 'core') {
|
||||
path = path.replace('/', '_')
|
||||
var core_sym = `js_${path}_use`
|
||||
if (os.internal_exists(core_sym)) {
|
||||
return {
|
||||
|
||||
4
link.cm
4
link.cm
@@ -3,7 +3,7 @@
|
||||
|
||||
var toml = use('toml')
|
||||
var fd = use('fd')
|
||||
var utf8 = use('utf8')
|
||||
var blob = use('blob')
|
||||
var os = use('os')
|
||||
|
||||
var global_shop_path = os.global_shop_path
|
||||
@@ -81,7 +81,7 @@ Link.save = function(links) {
|
||||
link_cache = links
|
||||
var cfg = { links: links }
|
||||
var path = get_links_path()
|
||||
fd.slurpwrite(path, utf8.encode(toml.encode(cfg)))
|
||||
fd.slurpwrite(path, new blob(toml.encode(cfg)))
|
||||
}
|
||||
|
||||
Link.add = function(canonical, target, shop) {
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
var cycles = {}
|
||||
var Math_obj = Math
|
||||
|
||||
cycles.arc_cosine = function(x) { return Math_obj.acos(x) / (2 * pi) }
|
||||
cycles.arc_sine = function(x) { return Math_obj.asin(x) / (2 * pi) }
|
||||
cycles.arc_tangent = function(x) { return Math_obj.atan(x) / (2 * pi) }
|
||||
cycles.cosine = function(x) { return Math_obj.cos(x * 2 * pi) }
|
||||
cycles.e = Math_obj.E
|
||||
cycles.ln = function(x) { return Math_obj.log(x) }
|
||||
cycles.log = function(x) { return Math_obj.log10(x) }
|
||||
cycles.log2 = function(x) { return Math_obj.log2(x) }
|
||||
cycles.power = function(x, y) { return Math_obj.pow(x, y) }
|
||||
cycles.root = function(x, y) { return Math_obj.pow(x, 1 / y) }
|
||||
cycles.sine = function(x) { return Math_obj.sin(x * 2 * pi) }
|
||||
cycles.sqrt = function(x) { return Math_obj.sqrt(x) }
|
||||
cycles.tangent = function(x) { return Math_obj.tan(x * 2 * pi) }
|
||||
|
||||
return cycles
|
||||
@@ -1,21 +0,0 @@
|
||||
var degrees = {}
|
||||
var Math_obj = Math
|
||||
|
||||
var deg2rad = pi / 180
|
||||
var rad2deg = 180 / pi
|
||||
|
||||
return {
|
||||
arc_cosine: function(x) { return Math_obj.acos(x) * rad2deg },
|
||||
arc_sine: function(x) { return Math_obj.asin(x) * rad2deg },
|
||||
arc_tangent: function(x) { return Math_obj.atan(x) * rad2deg },
|
||||
cosine: function(x) { return Math_obj.cos(x * deg2rad) },
|
||||
e: Math_obj.E,
|
||||
ln: function(x) { return Math_obj.log(x) },
|
||||
log: function(x) { return Math_obj.log10(x) },
|
||||
log2: function(x) { return Math_obj.log2(x) },
|
||||
power: function(x, y) { return Math_obj.pow(x, y) },
|
||||
root: function(x, y) { return Math_obj.pow(x, 1/y) },
|
||||
sine: function(x) { return Math_obj.sin(x * deg2rad) },
|
||||
sqrt: function(x) { return Math_obj.sqrt(x) },
|
||||
tangent: function(x) { return Math_obj.tan(x * deg2rad) }
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
var Math = globalThis.Math
|
||||
|
||||
return {
|
||||
arc_cosine: Math.acos,
|
||||
arc_sine: Math.asin,
|
||||
arc_tangent: Math.atan,
|
||||
cosine: Math.cos,
|
||||
e: Math.E,
|
||||
ln: Math.log,
|
||||
log: Math.log10,
|
||||
log2: Math.log2,
|
||||
power: Math.pow,
|
||||
root: function(x, n) { return Math.pow(x, 1/n) },
|
||||
sine: Math.sin,
|
||||
sqrt: Math.sqrt,
|
||||
tangent: Math.tan
|
||||
}
|
||||
@@ -57,7 +57,6 @@ scripts = [
|
||||
'wildstar.c',
|
||||
'fit.c',
|
||||
'crypto.c',
|
||||
'utf8.c',
|
||||
'internal/kim.c',
|
||||
'time.c',
|
||||
'internal/nota.c',
|
||||
@@ -68,7 +67,6 @@ scripts = [
|
||||
'net/enet.c',
|
||||
'wildstar.c',
|
||||
'archive/miniz.c',
|
||||
'internal/json.c',
|
||||
]
|
||||
|
||||
foreach file: scripts
|
||||
|
||||
696
source/quickjs.c
696
source/quickjs.c
@@ -1928,7 +1928,6 @@ JSContext *JS_NewContext(JSRuntime *rt)
|
||||
JS_AddIntrinsicEval(ctx);
|
||||
JS_AddIntrinsicStringNormalize(ctx);
|
||||
JS_AddIntrinsicRegExp(ctx);
|
||||
JS_AddIntrinsicJSON(ctx);
|
||||
JS_AddIntrinsicMapSet(ctx);
|
||||
|
||||
return ctx;
|
||||
@@ -26385,7 +26384,6 @@ static JSValue JS_EvalObject(JSContext *ctx, JSValueConst this_obj,
|
||||
ret = JS_EvalInternal(ctx, this_obj, str, len, "<input>", flags, scope_idx);
|
||||
JS_FreeCString(ctx, str);
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
JSValue JS_EvalThis(JSContext *ctx, JSValueConst this_obj,
|
||||
@@ -39499,6 +39497,19 @@ static JSValue js_blob_constructor(JSContext *ctx, JSValueConst new_target,
|
||||
}
|
||||
bd = blob_new_from_blob(src, (size_t)from, (size_t)to);
|
||||
}
|
||||
/* blob(text) - create blob from UTF-8 string */
|
||||
else if (argc == 1 && (JS_VALUE_GET_TAG(argv[0]) == JS_TAG_STRING || JS_VALUE_GET_TAG(argv[0]) == JS_TAG_STRING_ROPE)) {
|
||||
const char *str = JS_ToCString(ctx, argv[0]);
|
||||
if (!str)
|
||||
return JS_EXCEPTION;
|
||||
size_t len = strlen(str);
|
||||
bd = blob_new(len * 8);
|
||||
if (bd) {
|
||||
memcpy(bd->data, str, len);
|
||||
bd->length = len * 8;
|
||||
}
|
||||
JS_FreeCString(ctx, str);
|
||||
}
|
||||
else {
|
||||
return JS_ThrowTypeError(ctx, "blob constructor: invalid arguments");
|
||||
}
|
||||
@@ -40057,6 +40068,230 @@ static const JSCFunctionListEntry js_cell_stone_funcs[] = {
|
||||
JS_CFUNC_DEF("p", 1, js_cell_stone_p),
|
||||
};
|
||||
|
||||
/* ============================================================================
|
||||
* key() function - create a unique symbol
|
||||
* ============================================================================ */
|
||||
|
||||
static JSValue js_cell_key(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
return JS_NewSymbol(ctx, JS_ATOM_NULL, JS_ATOM_TYPE_SYMBOL);
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
* reverse() function - reverse an array
|
||||
* ============================================================================ */
|
||||
|
||||
static JSValue js_cell_reverse(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
if (argc < 1)
|
||||
return JS_NULL;
|
||||
|
||||
JSValue value = argv[0];
|
||||
|
||||
/* Handle arrays */
|
||||
if (JS_IsArray(ctx, value)) {
|
||||
JSValue length_val = JS_GetPropertyStr(ctx, value, "length");
|
||||
int64_t len;
|
||||
if (JS_ToInt64(ctx, &len, length_val) < 0) {
|
||||
JS_FreeValue(ctx, length_val);
|
||||
return JS_NULL;
|
||||
}
|
||||
JS_FreeValue(ctx, length_val);
|
||||
|
||||
JSValue result = JS_NewArray(ctx);
|
||||
for (int64_t i = len - 1, j = 0; i >= 0; i--, j++) {
|
||||
JSValue elem = JS_GetPropertyInt64(ctx, value, i);
|
||||
JS_SetPropertyInt64(ctx, result, j, elem);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Handle blobs */
|
||||
blob *bd = js_get_blob(ctx, value);
|
||||
if (bd) {
|
||||
/* Blobs need proper blob reversal support - return null for now */
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
* proto() function - get prototype of an object
|
||||
* ============================================================================ */
|
||||
|
||||
static JSValue js_cell_proto(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
if (argc < 1)
|
||||
return JS_NULL;
|
||||
|
||||
JSValue obj = argv[0];
|
||||
if (!JS_IsObject(obj))
|
||||
return JS_NULL;
|
||||
|
||||
JSValue proto = JS_GetPrototype(ctx, obj);
|
||||
if (JS_IsException(proto))
|
||||
return JS_NULL;
|
||||
|
||||
/* If prototype is Object.prototype, return null */
|
||||
if (JS_IsObject(proto)) {
|
||||
JSValue obj_proto = JS_GetPropertyStr(ctx, ctx->class_proto[JS_CLASS_OBJECT], "");
|
||||
if (JS_VALUE_GET_OBJ(proto) == JS_VALUE_GET_OBJ(ctx->class_proto[JS_CLASS_OBJECT])) {
|
||||
JS_FreeValue(ctx, proto);
|
||||
JS_FreeValue(ctx, obj_proto);
|
||||
return JS_NULL;
|
||||
}
|
||||
JS_FreeValue(ctx, obj_proto);
|
||||
}
|
||||
|
||||
return proto;
|
||||
}
|
||||
|
||||
static JSValue js_cell_meme(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
JSValue proto = JS_NULL;
|
||||
if (argc > 0 && !JS_IsNull(argv[0]))
|
||||
proto = argv[0];
|
||||
|
||||
JSValue result = JS_NewObjectProto(ctx, proto);
|
||||
if (JS_IsException(result))
|
||||
return result;
|
||||
|
||||
/* Apply mixins */
|
||||
for (int i = 1; i < argc; i++) {
|
||||
JSValue mix = argv[i];
|
||||
if (!JS_IsObject(mix) || JS_IsNull(mix) || JS_IsArray(ctx, mix))
|
||||
continue;
|
||||
|
||||
JSPropertyEnum *tab;
|
||||
uint32_t len;
|
||||
|
||||
if (JS_GetOwnPropertyNames(ctx, &tab, &len, mix,
|
||||
JS_GPN_STRING_MASK | JS_GPN_ENUM_ONLY) < 0) {
|
||||
JS_FreeValue(ctx, result);
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
|
||||
for (uint32_t j = 0; j < len; j++) {
|
||||
JSValue val = JS_GetProperty(ctx, mix, tab[j].atom);
|
||||
if (JS_IsException(val)) {
|
||||
for (uint32_t k = j; k < len; k++)
|
||||
JS_FreeAtom(ctx, tab[k].atom);
|
||||
js_free(ctx, tab);
|
||||
JS_FreeValue(ctx, result);
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
JS_SetProperty(ctx, result, tab[j].atom, val);
|
||||
JS_FreeAtom(ctx, tab[j].atom);
|
||||
}
|
||||
js_free(ctx, tab);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
* splat() function - flatten object with prototype chain
|
||||
* ============================================================================ */
|
||||
|
||||
static JSValue js_cell_splat(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
if (argc < 1)
|
||||
return JS_NULL;
|
||||
|
||||
JSValue obj = argv[0];
|
||||
if (!JS_IsObject(obj) || JS_IsNull(obj))
|
||||
return JS_NULL;
|
||||
|
||||
JSValue result = JS_NewObject(ctx);
|
||||
if (JS_IsException(result))
|
||||
return JS_EXCEPTION;
|
||||
|
||||
JSValue current = JS_DupValue(ctx, obj);
|
||||
|
||||
/* Walk prototype chain and collect text keys */
|
||||
while (!JS_IsNull(current)) {
|
||||
JSPropertyEnum *tab;
|
||||
uint32_t len;
|
||||
|
||||
if (JS_GetOwnPropertyNames(ctx, &tab, &len, current,
|
||||
JS_GPN_STRING_MASK | JS_GPN_ENUM_ONLY) < 0) {
|
||||
JS_FreeValue(ctx, current);
|
||||
JS_FreeValue(ctx, result);
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
JSAtom atom = tab[i].atom;
|
||||
/* Check if property not already in result */
|
||||
int has = JS_HasProperty(ctx, result, atom);
|
||||
if (has < 0) {
|
||||
for (uint32_t j = i; j < len; j++)
|
||||
JS_FreeAtom(ctx, tab[j].atom);
|
||||
js_free(ctx, tab);
|
||||
JS_FreeValue(ctx, current);
|
||||
JS_FreeValue(ctx, result);
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
if (!has) {
|
||||
JSValue val = JS_GetProperty(ctx, current, atom);
|
||||
if (JS_IsException(val)) {
|
||||
for (uint32_t j = i; j < len; j++)
|
||||
JS_FreeAtom(ctx, tab[j].atom);
|
||||
js_free(ctx, tab);
|
||||
JS_FreeValue(ctx, current);
|
||||
JS_FreeValue(ctx, result);
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
/* Only include serializable types */
|
||||
int tag = JS_VALUE_GET_TAG(val);
|
||||
if (JS_IsObject(val) || JS_IsNumber(val) ||
|
||||
tag == JS_TAG_STRING || tag == JS_TAG_STRING_ROPE ||
|
||||
tag == JS_TAG_BOOL) {
|
||||
JS_SetProperty(ctx, result, atom, val);
|
||||
} else {
|
||||
JS_FreeValue(ctx, val);
|
||||
}
|
||||
}
|
||||
JS_FreeAtom(ctx, tab[i].atom);
|
||||
}
|
||||
js_free(ctx, tab);
|
||||
|
||||
JSValue next = JS_GetPrototype(ctx, current);
|
||||
JS_FreeValue(ctx, current);
|
||||
current = next;
|
||||
}
|
||||
|
||||
/* Call to_data if present */
|
||||
JSValue to_data = JS_GetPropertyStr(ctx, obj, "to_data");
|
||||
if (JS_IsFunction(ctx, to_data)) {
|
||||
JSValue args[1] = { result };
|
||||
JSValue extra = JS_Call(ctx, to_data, obj, 1, args);
|
||||
if (!JS_IsException(extra) && JS_IsObject(extra)) {
|
||||
JSPropertyEnum *tab;
|
||||
uint32_t len;
|
||||
if (JS_GetOwnPropertyNames(ctx, &tab, &len, extra,
|
||||
JS_GPN_STRING_MASK | JS_GPN_ENUM_ONLY) >= 0) {
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
JSValue val = JS_GetProperty(ctx, extra, tab[i].atom);
|
||||
JS_SetProperty(ctx, result, tab[i].atom, val);
|
||||
JS_FreeAtom(ctx, tab[i].atom);
|
||||
}
|
||||
js_free(ctx, tab);
|
||||
}
|
||||
}
|
||||
JS_FreeValue(ctx, extra);
|
||||
}
|
||||
JS_FreeValue(ctx, to_data);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
* length() function
|
||||
* ============================================================================ */
|
||||
@@ -40291,20 +40526,6 @@ static JSValue js_cell_is_proto(JSContext *ctx, JSValueConst this_val,
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
* Cell Script Global Function Registration
|
||||
* ============================================================================ */
|
||||
|
||||
static const JSCFunctionListEntry js_global_funcs[] = {
|
||||
JS_CFUNC_DEF("parseInt", 2, js_parseInt ),
|
||||
JS_CFUNC_DEF("parseFloat", 1, js_parseFloat ),
|
||||
JS_CFUNC_DEF("isNaN", 1, js_global_isNaN ),
|
||||
JS_CFUNC_DEF("isFinite", 1, js_global_isFinite ),
|
||||
JS_PROP_DOUBLE_DEF("Infinity", 1.0 / 0.0, 0 ),
|
||||
JS_PROP_DOUBLE_DEF("NaN", NAN, 0 ),
|
||||
JS_PROP_STRING_DEF("[Symbol.toStringTag]", "global", JS_PROP_CONFIGURABLE ),
|
||||
};
|
||||
|
||||
/* eval */
|
||||
|
||||
void JS_AddIntrinsicEval(JSContext *ctx)
|
||||
@@ -40474,12 +40695,6 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
|
||||
js_array_iterator_proto_funcs,
|
||||
countof(js_array_iterator_proto_funcs));
|
||||
|
||||
/* parseFloat and parseInteger must be defined before Number
|
||||
because of the Number.parseFloat and Number.parseInteger
|
||||
aliases */
|
||||
JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_global_funcs,
|
||||
countof(js_global_funcs));
|
||||
|
||||
/* String */
|
||||
ctx->class_proto[JS_CLASS_STRING] = JS_NewObjectProtoClass(ctx, ctx->class_proto[JS_CLASS_OBJECT],
|
||||
JS_CLASS_STRING);
|
||||
@@ -40496,10 +40711,6 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
|
||||
js_string_iterator_proto_funcs,
|
||||
countof(js_string_iterator_proto_funcs));
|
||||
|
||||
/* Math: create as autoinit object */
|
||||
js_random_init(ctx);
|
||||
JS_SetPropertyFunctionList(ctx, ctx->global_obj, js_math_obj, countof(js_math_obj));
|
||||
|
||||
/* ES6 Symbol */
|
||||
ctx->class_proto[JS_CLASS_SYMBOL] = JS_NewObject(ctx);
|
||||
JS_SetPropertyFunctionList(ctx, ctx->class_proto[JS_CLASS_SYMBOL], js_symbol_proto_funcs,
|
||||
@@ -40518,11 +40729,6 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
|
||||
}
|
||||
|
||||
/* global properties */
|
||||
ctx->eval_obj = JS_NewCFunction(ctx, js_global_eval, "eval", 1);
|
||||
JS_DefinePropertyValue(ctx, ctx->global_obj, JS_ATOM_eval,
|
||||
JS_DupValue(ctx, ctx->eval_obj),
|
||||
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
|
||||
|
||||
JS_DefinePropertyValue(ctx, ctx->global_obj, JS_ATOM_globalThis,
|
||||
JS_DupValue(ctx, ctx->global_obj),
|
||||
JS_PROP_CONFIGURABLE | JS_PROP_WRITABLE);
|
||||
@@ -40620,6 +40826,36 @@ void JS_AddIntrinsicBaseObjects(JSContext *ctx)
|
||||
JS_DefinePropertyValueStr(ctx, ctx->global_obj, "is_proto",
|
||||
JS_NewCFunction(ctx, js_cell_is_proto, "is_proto", 2),
|
||||
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
|
||||
|
||||
/* key() - create a unique symbol */
|
||||
JS_DefinePropertyValueStr(ctx, ctx->global_obj, "key",
|
||||
JS_NewCFunction(ctx, js_cell_key, "key", 0),
|
||||
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
|
||||
|
||||
/* reverse() - reverse an array */
|
||||
JS_DefinePropertyValueStr(ctx, ctx->global_obj, "reverse",
|
||||
JS_NewCFunction(ctx, js_cell_reverse, "reverse", 1),
|
||||
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
|
||||
|
||||
/* proto() - get prototype of an object */
|
||||
JS_DefinePropertyValueStr(ctx, ctx->global_obj, "proto",
|
||||
JS_NewCFunction(ctx, js_cell_proto, "proto", 1),
|
||||
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
|
||||
|
||||
/* splat() - flatten object with prototype chain */
|
||||
JS_DefinePropertyValueStr(ctx, ctx->global_obj, "splat",
|
||||
JS_NewCFunction(ctx, js_cell_splat, "splat", 1),
|
||||
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
|
||||
|
||||
/* splat() - flatten object with prototype chain */
|
||||
JS_DefinePropertyValueStr(ctx, ctx->global_obj, "meme",
|
||||
JS_NewCFunction(ctx, js_cell_meme, "meme", 1),
|
||||
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
|
||||
|
||||
/* pi - mathematical constant */
|
||||
JS_DefinePropertyValueStr(ctx, ctx->global_obj, "pi",
|
||||
JS_NewFloat64(ctx, 3.14159265358979323846264338327950288419716939937510),
|
||||
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41295,6 +41531,404 @@ void *js_debugger_val_address(JSContext *ctx, JSValue val) {
|
||||
return JS_VALUE_GET_PTR(val);
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
* Cell Script Module: json
|
||||
* Provides json.encode() and json.decode() using pure C implementation
|
||||
* ============================================================================ */
|
||||
|
||||
static JSValue js_cell_json_encode(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
if (argc < 1)
|
||||
return JS_ThrowTypeError(ctx, "json.encode requires at least 1 argument");
|
||||
|
||||
JSValue replacer = argc > 1 ? argv[1] : JS_NULL;
|
||||
JSValue space = argc > 2 ? argv[2] : JS_NewInt32(ctx, 1);
|
||||
JSValue result = JS_JSONStringify(ctx, argv[0], replacer, space);
|
||||
if (argc <= 2)
|
||||
JS_FreeValue(ctx, space);
|
||||
return result;
|
||||
}
|
||||
|
||||
static JSValue js_cell_json_decode(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
if (argc < 1)
|
||||
return JS_ThrowTypeError(ctx, "json.decode requires at least 1 argument");
|
||||
|
||||
int tag = JS_VALUE_GET_TAG(argv[0]);
|
||||
if (tag != JS_TAG_STRING && tag != JS_TAG_STRING_ROPE) {
|
||||
JSValue err = JS_NewError(ctx);
|
||||
JS_DefinePropertyValueStr(ctx, err, "message",
|
||||
JS_NewString(ctx, "couldn't parse text: not a string"),
|
||||
JS_PROP_WRITABLE | JS_PROP_CONFIGURABLE);
|
||||
return JS_Throw(ctx, err);
|
||||
}
|
||||
|
||||
const char *str = JS_ToCString(ctx, argv[0]);
|
||||
if (!str)
|
||||
return JS_EXCEPTION;
|
||||
|
||||
size_t len = strlen(str);
|
||||
JSValue result = JS_ParseJSON(ctx, str, len, "<json>");
|
||||
JS_FreeCString(ctx, str);
|
||||
|
||||
/* Apply reviver if provided */
|
||||
if (argc > 1 && JS_IsFunction(ctx, argv[1]) && !JS_IsException(result)) {
|
||||
/* Create wrapper object to pass to reviver */
|
||||
JSValue wrapper = JS_NewObject(ctx);
|
||||
JS_DefinePropertyValueStr(ctx, wrapper, "", result, JS_PROP_C_W_E);
|
||||
|
||||
JSValue holder = wrapper;
|
||||
JSAtom key = JS_NewAtom(ctx, "");
|
||||
JSValue args[2] = { JS_AtomToString(ctx, key), JS_GetProperty(ctx, holder, key) };
|
||||
JSValue final = JS_Call(ctx, argv[1], holder, 2, args);
|
||||
JS_FreeValue(ctx, args[0]);
|
||||
JS_FreeValue(ctx, args[1]);
|
||||
JS_FreeAtom(ctx, key);
|
||||
JS_FreeValue(ctx, wrapper);
|
||||
result = final;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static const JSCFunctionListEntry js_cell_json_funcs[] = {
|
||||
JS_CFUNC_DEF("encode", 1, js_cell_json_encode),
|
||||
JS_CFUNC_DEF("decode", 1, js_cell_json_decode),
|
||||
};
|
||||
|
||||
JSValue js_json_use(JSContext *ctx)
|
||||
{
|
||||
JSValue obj = JS_NewObject(ctx);
|
||||
JS_SetPropertyFunctionList(ctx, obj, js_cell_json_funcs, countof(js_cell_json_funcs));
|
||||
return obj;
|
||||
}
|
||||
|
||||
static JSValue js_math_e(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
double power = 1.0;
|
||||
if (argc > 0 && !JS_IsNull(argv[0])) {
|
||||
if (JS_ToFloat64(ctx, &power, argv[0]) < 0)
|
||||
return JS_EXCEPTION;
|
||||
}
|
||||
return JS_NewFloat64(ctx, exp(power));
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
* Cell Script Module: math/radians
|
||||
* Provides trigonometric and math functions using radians
|
||||
* ============================================================================ */
|
||||
|
||||
static JSValue js_math_rad_arc_cosine(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
double x;
|
||||
if (JS_ToFloat64(ctx, &x, argv[0]) < 0)
|
||||
return JS_EXCEPTION;
|
||||
return JS_NewFloat64(ctx, acos(x));
|
||||
}
|
||||
|
||||
static JSValue js_math_rad_arc_sine(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
double x;
|
||||
if (JS_ToFloat64(ctx, &x, argv[0]) < 0)
|
||||
return JS_EXCEPTION;
|
||||
return JS_NewFloat64(ctx, asin(x));
|
||||
}
|
||||
|
||||
static JSValue js_math_rad_arc_tangent(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
double x;
|
||||
if (JS_ToFloat64(ctx, &x, argv[0]) < 0)
|
||||
return JS_EXCEPTION;
|
||||
return JS_NewFloat64(ctx, atan(x));
|
||||
}
|
||||
|
||||
static JSValue js_math_rad_cosine(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
double x;
|
||||
if (JS_ToFloat64(ctx, &x, argv[0]) < 0)
|
||||
return JS_EXCEPTION;
|
||||
return JS_NewFloat64(ctx, cos(x));
|
||||
}
|
||||
|
||||
static JSValue js_math_rad_sine(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
double x;
|
||||
if (JS_ToFloat64(ctx, &x, argv[0]) < 0)
|
||||
return JS_EXCEPTION;
|
||||
return JS_NewFloat64(ctx, sin(x));
|
||||
}
|
||||
|
||||
static JSValue js_math_rad_tangent(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
double x;
|
||||
if (JS_ToFloat64(ctx, &x, argv[0]) < 0)
|
||||
return JS_EXCEPTION;
|
||||
return JS_NewFloat64(ctx, tan(x));
|
||||
}
|
||||
|
||||
static JSValue js_math_ln(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
double x;
|
||||
if (JS_ToFloat64(ctx, &x, argv[0]) < 0)
|
||||
return JS_EXCEPTION;
|
||||
return JS_NewFloat64(ctx, log(x));
|
||||
}
|
||||
|
||||
static JSValue js_math_log10(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
double x;
|
||||
if (JS_ToFloat64(ctx, &x, argv[0]) < 0)
|
||||
return JS_EXCEPTION;
|
||||
return JS_NewFloat64(ctx, log10(x));
|
||||
}
|
||||
|
||||
static JSValue js_math_log2(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
double x;
|
||||
if (JS_ToFloat64(ctx, &x, argv[0]) < 0)
|
||||
return JS_EXCEPTION;
|
||||
return JS_NewFloat64(ctx, log2(x));
|
||||
}
|
||||
|
||||
static JSValue js_math_power(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
double x, y;
|
||||
if (argc < 2)
|
||||
return JS_NULL;
|
||||
if (JS_ToFloat64(ctx, &x, argv[0]) < 0)
|
||||
return JS_EXCEPTION;
|
||||
if (JS_ToFloat64(ctx, &y, argv[1]) < 0)
|
||||
return JS_EXCEPTION;
|
||||
return JS_NewFloat64(ctx, pow(x, y));
|
||||
}
|
||||
|
||||
static JSValue js_math_root(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
double x, n;
|
||||
if (argc < 2)
|
||||
return JS_NULL;
|
||||
if (JS_ToFloat64(ctx, &x, argv[0]) < 0)
|
||||
return JS_EXCEPTION;
|
||||
if (JS_ToFloat64(ctx, &n, argv[1]) < 0)
|
||||
return JS_EXCEPTION;
|
||||
return JS_NewFloat64(ctx, pow(x, 1.0 / n));
|
||||
}
|
||||
|
||||
static JSValue js_math_sqrt(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
double x;
|
||||
if (JS_ToFloat64(ctx, &x, argv[0]) < 0)
|
||||
return JS_EXCEPTION;
|
||||
return JS_NewFloat64(ctx, sqrt(x));
|
||||
}
|
||||
|
||||
static const JSCFunctionListEntry js_math_radians_funcs[] = {
|
||||
JS_CFUNC_DEF("arc_cosine", 1, js_math_rad_arc_cosine),
|
||||
JS_CFUNC_DEF("arc_sine", 1, js_math_rad_arc_sine),
|
||||
JS_CFUNC_DEF("arc_tangent", 1, js_math_rad_arc_tangent),
|
||||
JS_CFUNC_DEF("cosine", 1, js_math_rad_cosine),
|
||||
JS_CFUNC_DEF("sine", 1, js_math_rad_sine),
|
||||
JS_CFUNC_DEF("tangent", 1, js_math_rad_tangent),
|
||||
JS_CFUNC_DEF("ln", 1, js_math_ln),
|
||||
JS_CFUNC_DEF("log", 1, js_math_log10),
|
||||
JS_CFUNC_DEF("log2", 1, js_math_log2),
|
||||
JS_CFUNC_DEF("power", 2, js_math_power),
|
||||
JS_CFUNC_DEF("root", 2, js_math_root),
|
||||
JS_CFUNC_DEF("sqrt", 1, js_math_sqrt),
|
||||
JS_CFUNC_DEF("e", 1, js_math_e)
|
||||
};
|
||||
|
||||
JSValue js_math_radians_use(JSContext *ctx)
|
||||
{
|
||||
JSValue obj = JS_NewObject(ctx);
|
||||
JS_SetPropertyFunctionList(ctx, obj, js_math_radians_funcs, countof(js_math_radians_funcs));
|
||||
return obj;
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
* Cell Script Module: math/degrees
|
||||
* Provides trigonometric and math functions using degrees
|
||||
* ============================================================================ */
|
||||
|
||||
#define DEG2RAD (3.14159265358979323846264338327950288419716939937510 / 180.0)
|
||||
#define RAD2DEG (180.0 / 3.14159265358979323846264338327950288419716939937510)
|
||||
|
||||
static JSValue js_math_deg_arc_cosine(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
double x;
|
||||
if (JS_ToFloat64(ctx, &x, argv[0]) < 0)
|
||||
return JS_EXCEPTION;
|
||||
return JS_NewFloat64(ctx, acos(x) * RAD2DEG);
|
||||
}
|
||||
|
||||
static JSValue js_math_deg_arc_sine(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
double x;
|
||||
if (JS_ToFloat64(ctx, &x, argv[0]) < 0)
|
||||
return JS_EXCEPTION;
|
||||
return JS_NewFloat64(ctx, asin(x) * RAD2DEG);
|
||||
}
|
||||
|
||||
static JSValue js_math_deg_arc_tangent(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
double x;
|
||||
if (JS_ToFloat64(ctx, &x, argv[0]) < 0)
|
||||
return JS_EXCEPTION;
|
||||
return JS_NewFloat64(ctx, atan(x) * RAD2DEG);
|
||||
}
|
||||
|
||||
static JSValue js_math_deg_cosine(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
double x;
|
||||
if (JS_ToFloat64(ctx, &x, argv[0]) < 0)
|
||||
return JS_EXCEPTION;
|
||||
return JS_NewFloat64(ctx, cos(x * DEG2RAD));
|
||||
}
|
||||
|
||||
static JSValue js_math_deg_sine(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
double x;
|
||||
if (JS_ToFloat64(ctx, &x, argv[0]) < 0)
|
||||
return JS_EXCEPTION;
|
||||
return JS_NewFloat64(ctx, sin(x * DEG2RAD));
|
||||
}
|
||||
|
||||
static JSValue js_math_deg_tangent(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
double x;
|
||||
if (JS_ToFloat64(ctx, &x, argv[0]) < 0)
|
||||
return JS_EXCEPTION;
|
||||
return JS_NewFloat64(ctx, tan(x * DEG2RAD));
|
||||
}
|
||||
|
||||
static const JSCFunctionListEntry js_math_degrees_funcs[] = {
|
||||
JS_CFUNC_DEF("arc_cosine", 1, js_math_deg_arc_cosine),
|
||||
JS_CFUNC_DEF("arc_sine", 1, js_math_deg_arc_sine),
|
||||
JS_CFUNC_DEF("arc_tangent", 1, js_math_deg_arc_tangent),
|
||||
JS_CFUNC_DEF("cosine", 1, js_math_deg_cosine),
|
||||
JS_CFUNC_DEF("sine", 1, js_math_deg_sine),
|
||||
JS_CFUNC_DEF("tangent", 1, js_math_deg_tangent),
|
||||
JS_CFUNC_DEF("ln", 1, js_math_ln),
|
||||
JS_CFUNC_DEF("log", 1, js_math_log10),
|
||||
JS_CFUNC_DEF("log2", 1, js_math_log2),
|
||||
JS_CFUNC_DEF("power", 2, js_math_power),
|
||||
JS_CFUNC_DEF("root", 2, js_math_root),
|
||||
JS_CFUNC_DEF("sqrt", 1, js_math_sqrt),
|
||||
JS_CFUNC_DEF("e", 1, js_math_e)
|
||||
};
|
||||
|
||||
JSValue js_math_degrees_use(JSContext *ctx)
|
||||
{
|
||||
JSValue obj = JS_NewObject(ctx);
|
||||
JS_SetPropertyFunctionList(ctx, obj, js_math_degrees_funcs, countof(js_math_degrees_funcs));
|
||||
return obj;
|
||||
}
|
||||
|
||||
/* ============================================================================
|
||||
* Cell Script Module: math/cycles
|
||||
* Provides trigonometric and math functions using cycles (0-1 = full rotation)
|
||||
* ============================================================================ */
|
||||
|
||||
#define TWOPI (2.0 * 3.14159265358979323846264338327950288419716939937510)
|
||||
|
||||
static JSValue js_math_cyc_arc_cosine(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
double x;
|
||||
if (JS_ToFloat64(ctx, &x, argv[0]) < 0)
|
||||
return JS_EXCEPTION;
|
||||
return JS_NewFloat64(ctx, acos(x) / TWOPI);
|
||||
}
|
||||
|
||||
static JSValue js_math_cyc_arc_sine(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
double x;
|
||||
if (JS_ToFloat64(ctx, &x, argv[0]) < 0)
|
||||
return JS_EXCEPTION;
|
||||
return JS_NewFloat64(ctx, asin(x) / TWOPI);
|
||||
}
|
||||
|
||||
static JSValue js_math_cyc_arc_tangent(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
double x;
|
||||
if (JS_ToFloat64(ctx, &x, argv[0]) < 0)
|
||||
return JS_EXCEPTION;
|
||||
return JS_NewFloat64(ctx, atan(x) / TWOPI);
|
||||
}
|
||||
|
||||
static JSValue js_math_cyc_cosine(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
double x;
|
||||
if (JS_ToFloat64(ctx, &x, argv[0]) < 0)
|
||||
return JS_EXCEPTION;
|
||||
return JS_NewFloat64(ctx, cos(x * TWOPI));
|
||||
}
|
||||
|
||||
static JSValue js_math_cyc_sine(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
double x;
|
||||
if (JS_ToFloat64(ctx, &x, argv[0]) < 0)
|
||||
return JS_EXCEPTION;
|
||||
return JS_NewFloat64(ctx, sin(x * TWOPI));
|
||||
}
|
||||
|
||||
static JSValue js_math_cyc_tangent(JSContext *ctx, JSValueConst this_val,
|
||||
int argc, JSValueConst *argv)
|
||||
{
|
||||
double x;
|
||||
if (JS_ToFloat64(ctx, &x, argv[0]) < 0)
|
||||
return JS_EXCEPTION;
|
||||
return JS_NewFloat64(ctx, tan(x * TWOPI));
|
||||
}
|
||||
|
||||
static const JSCFunctionListEntry js_math_cycles_funcs[] = {
|
||||
JS_CFUNC_DEF("arc_cosine", 1, js_math_cyc_arc_cosine),
|
||||
JS_CFUNC_DEF("arc_sine", 1, js_math_cyc_arc_sine),
|
||||
JS_CFUNC_DEF("arc_tangent", 1, js_math_cyc_arc_tangent),
|
||||
JS_CFUNC_DEF("cosine", 1, js_math_cyc_cosine),
|
||||
JS_CFUNC_DEF("sine", 1, js_math_cyc_sine),
|
||||
JS_CFUNC_DEF("tangent", 1, js_math_cyc_tangent),
|
||||
JS_CFUNC_DEF("ln", 1, js_math_ln),
|
||||
JS_CFUNC_DEF("log", 1, js_math_log10),
|
||||
JS_CFUNC_DEF("log2", 1, js_math_log2),
|
||||
JS_CFUNC_DEF("power", 2, js_math_power),
|
||||
JS_CFUNC_DEF("root", 2, js_math_root),
|
||||
JS_CFUNC_DEF("sqrt", 1, js_math_sqrt),
|
||||
JS_CFUNC_DEF("e", 1, js_math_e)
|
||||
};
|
||||
|
||||
JSValue js_math_cycles_use(JSContext *ctx)
|
||||
{
|
||||
JSValue obj = JS_NewObject(ctx);
|
||||
JS_SetPropertyFunctionList(ctx, obj, js_math_cycles_funcs, countof(js_math_cycles_funcs));
|
||||
return obj;
|
||||
}
|
||||
|
||||
JSContext *JS_GetContext(JSRuntime *rt) {
|
||||
return rt->js;
|
||||
}
|
||||
|
||||
6
test.ce
6
test.ce
@@ -3,7 +3,7 @@ var pkg = use('package')
|
||||
var fd = use('fd')
|
||||
var time = use('time')
|
||||
var json = use('json')
|
||||
var utf8 = use('utf8')
|
||||
var blob = use('blob')
|
||||
|
||||
if (!args) args = []
|
||||
|
||||
@@ -628,7 +628,7 @@ Total: ${totals.total}, Passed: ${totals.passed}, Failed: ${totals.failed}
|
||||
}
|
||||
}
|
||||
ensure_dir(report_dir)
|
||||
fd.slurpwrite(`${report_dir}/test.txt`, utf8.encode(txt_report))
|
||||
fd.slurpwrite(`${report_dir}/test.txt`, stone(new blob(txt_report)))
|
||||
log.console(`Report written to ${report_dir}/test.txt`)
|
||||
|
||||
// Generate JSON per package
|
||||
@@ -645,7 +645,7 @@ Total: ${totals.total}, Passed: ${totals.passed}, Failed: ${totals.failed}
|
||||
}
|
||||
|
||||
var json_path = `${report_dir}/${pkg_res.package.replace(/\//g, '_')}.json`
|
||||
fd.slurpwrite(json_path, utf8.encode(json.encode(pkg_tests)))
|
||||
fd.slurpwrite(json_path, stone(new blob(json.encode(pkg_tests))))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
var blob = use('blob');
|
||||
var utf8 = use('utf8');
|
||||
|
||||
return {
|
||||
test_blob_to_text: function() {
|
||||
// Test blob to text conversion
|
||||
var test_string = "Hello, 世界! 🌍";
|
||||
var encoded_blob = utf8.encode(test_string);
|
||||
var decoded_text = text(encoded_blob);
|
||||
if (test_string != decoded_text) throw "Blob to text failed"
|
||||
},
|
||||
|
||||
test_codepoints_to_text: function() {
|
||||
// Test array of codepoints conversion
|
||||
var test_string = "Hello, 世界! 🌍";
|
||||
var codepoints = [72, 101, 108, 108, 111, 44, 32, 19990, 30028, 33, 32, 127757];
|
||||
var from_codepoints = text(codepoints);
|
||||
if (from_codepoints != test_string) throw "Codepoints to text failed"
|
||||
},
|
||||
|
||||
test_array_separator: function() {
|
||||
// Test array with separator
|
||||
var words = ["Hello", "world", "from", "text"];
|
||||
var joined = text(words, " ");
|
||||
if (joined != "Hello world from text") throw "Array with separator failed"
|
||||
},
|
||||
|
||||
test_mixed_array: function() {
|
||||
// Test mixed array with codepoints
|
||||
var mixed = [72, "ello", 32, "world"];
|
||||
var mixed_result = text(mixed, "");
|
||||
if (mixed_result != "Hello world") throw "Mixed array test failed"
|
||||
},
|
||||
}
|
||||
210
utf8.c
210
utf8.c
@@ -1,210 +0,0 @@
|
||||
#include "cell.h"
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "kim.h"
|
||||
|
||||
// Get codepoints from a UTF-8 string
|
||||
JSC_CCALL(utf8_codepoints,
|
||||
const char *str = JS_ToCString(js, argv[0]);
|
||||
if (!str) return JS_EXCEPTION;
|
||||
|
||||
JSValue arr = JS_NewArray(js);
|
||||
int idx = 0;
|
||||
|
||||
char *ptr = (char*)str;
|
||||
while (*ptr) {
|
||||
int codepoint = decode_utf8(&ptr);
|
||||
JS_SetPropertyUint32(js, arr, idx++, JS_NewInt32(js, codepoint));
|
||||
}
|
||||
|
||||
JS_FreeCString(js, str);
|
||||
ret = arr;
|
||||
)
|
||||
|
||||
// Create UTF-8 string from codepoints
|
||||
JSC_CCALL(utf8_from_codepoints,
|
||||
int len = JS_ArrayLength(js, argv[0]);
|
||||
|
||||
// Allocate buffer (worst case: 4 bytes per codepoint + null)
|
||||
char *buffer = malloc(len * 4 + 1);
|
||||
char *ptr = buffer;
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
JSValue val = JS_GetPropertyUint32(js, argv[0], i);
|
||||
int codepoint;
|
||||
JS_ToInt32(js, &codepoint, val);
|
||||
JS_FreeValue(js, val);
|
||||
|
||||
encode_utf8(&ptr, codepoint);
|
||||
}
|
||||
|
||||
*ptr = '\0';
|
||||
ret = JS_NewString(js, buffer);
|
||||
free(buffer);
|
||||
)
|
||||
|
||||
// Count UTF-8 characters (runes) in a string
|
||||
JSC_SCALL(utf8_length,
|
||||
int count = utf8_count(str);
|
||||
ret = JS_NewInt32(js, count);
|
||||
)
|
||||
|
||||
// Validate UTF-8 string
|
||||
JSC_SCALL(utf8_validate,
|
||||
char *ptr = (char*)str;
|
||||
int valid = 1;
|
||||
|
||||
while (*ptr) {
|
||||
int start_pos = ptr - str;
|
||||
int codepoint = decode_utf8(&ptr);
|
||||
|
||||
// Check for invalid sequences
|
||||
if (codepoint < 0 || codepoint > 0x10FFFF ||
|
||||
(codepoint >= 0xD800 && codepoint <= 0xDFFF)) {
|
||||
valid = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
// Check for overlong encodings
|
||||
int bytes_used = ptr - (str + start_pos);
|
||||
if ((codepoint <= 0x7F && bytes_used != 1) ||
|
||||
(codepoint <= 0x7FF && bytes_used != 2) ||
|
||||
(codepoint <= 0xFFFF && bytes_used != 3) ||
|
||||
(codepoint <= 0x10FFFF && bytes_used != 4)) {
|
||||
valid = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ret = JS_NewBool(js, valid);
|
||||
)
|
||||
|
||||
// Get byte length of UTF-8 string
|
||||
JSC_SCALL(utf8_byte_length,
|
||||
ret = JS_NewInt32(js, strlen(str));
|
||||
)
|
||||
|
||||
// Encode string to UTF-8 bytes
|
||||
JSC_SCALL(utf8_encode,
|
||||
size_t len = strlen(str);
|
||||
ret = js_new_blob_stoned_copy(js, str, len);
|
||||
)
|
||||
|
||||
// Decode UTF-8 bytes to string
|
||||
JSC_CCALL(utf8_decode,
|
||||
size_t len;
|
||||
void *data = js_get_blob_data(js, &len, argv[0]);
|
||||
if (data == (void*)-1) return JS_EXCEPTION;
|
||||
if (!data || len == 0) return JS_ThrowTypeError(js, "No data present in blob");
|
||||
|
||||
// Create null-terminated string
|
||||
char *str = malloc(len + 1);
|
||||
memcpy(str, data, len);
|
||||
str[len] = '\0';
|
||||
|
||||
ret = JS_NewString(js, str);
|
||||
free(str);
|
||||
)
|
||||
|
||||
// Slice UTF-8 string by character indices (not byte indices)
|
||||
JSC_CCALL(utf8_slice,
|
||||
const char *str = JS_ToCString(js, argv[0]);
|
||||
if (!str) return JS_EXCEPTION;
|
||||
|
||||
int start = 0;
|
||||
int end = utf8_count(str);
|
||||
|
||||
if (argc > 1) JS_ToInt32(js, &start, argv[1]);
|
||||
if (argc > 2) JS_ToInt32(js, &end, argv[2]);
|
||||
|
||||
// Handle negative indices
|
||||
int total = end;
|
||||
if (start < 0) start = total + start;
|
||||
if (end < 0) end = total + end;
|
||||
|
||||
// Clamp values
|
||||
if (start < 0) start = 0;
|
||||
if (end > total) end = total;
|
||||
if (start >= end) {
|
||||
JS_FreeCString(js, str);
|
||||
return JS_NewString(js, "");
|
||||
}
|
||||
|
||||
// Find start position
|
||||
char *ptr = (char*)str;
|
||||
for (int i = 0; i < start && *ptr; i++) {
|
||||
decode_utf8(&ptr);
|
||||
}
|
||||
char *start_ptr = ptr;
|
||||
|
||||
// Find end position
|
||||
for (int i = start; i < end && *ptr; i++) {
|
||||
decode_utf8(&ptr);
|
||||
}
|
||||
|
||||
// Create substring
|
||||
size_t slice_len = ptr - start_ptr;
|
||||
char *slice = malloc(slice_len + 1);
|
||||
memcpy(slice, start_ptr, slice_len);
|
||||
slice[slice_len] = '\0';
|
||||
|
||||
ret = JS_NewString(js, slice);
|
||||
free(slice);
|
||||
JS_FreeCString(js, str);
|
||||
)
|
||||
|
||||
// Get character at index
|
||||
JSC_CCALL(utf8_char_at,
|
||||
const char *str = JS_ToCString(js, argv[0]);
|
||||
if (!str) return JS_EXCEPTION;
|
||||
|
||||
int index;
|
||||
JS_ToInt32(js, &index, argv[1]);
|
||||
|
||||
char *ptr = (char*)str;
|
||||
int count = 0;
|
||||
|
||||
// Skip to index
|
||||
while (*ptr && count < index) {
|
||||
decode_utf8(&ptr);
|
||||
count++;
|
||||
}
|
||||
|
||||
if (!*ptr || count != index) {
|
||||
JS_FreeCString(js, str);
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
// Get the character
|
||||
char *char_start = ptr;
|
||||
decode_utf8(&ptr);
|
||||
|
||||
size_t char_len = ptr - char_start;
|
||||
char *result = malloc(char_len + 1);
|
||||
memcpy(result, char_start, char_len);
|
||||
result[char_len] = '\0';
|
||||
|
||||
ret = JS_NewString(js, result);
|
||||
free(result);
|
||||
JS_FreeCString(js, str);
|
||||
)
|
||||
|
||||
static const JSCFunctionListEntry js_utf8_funcs[] = {
|
||||
MIST_FUNC_DEF(utf8, codepoints, 1),
|
||||
MIST_FUNC_DEF(utf8, from_codepoints, 1),
|
||||
MIST_FUNC_DEF(utf8, length, 1),
|
||||
MIST_FUNC_DEF(utf8, validate, 1),
|
||||
MIST_FUNC_DEF(utf8, byte_length, 1),
|
||||
MIST_FUNC_DEF(utf8, encode, 1),
|
||||
MIST_FUNC_DEF(utf8, decode, 1),
|
||||
MIST_FUNC_DEF(utf8, slice, 3),
|
||||
MIST_FUNC_DEF(utf8, char_at, 2),
|
||||
};
|
||||
|
||||
JSValue js_utf8_use(JSContext *js)
|
||||
{
|
||||
JSValue mod = JS_NewObject(js);
|
||||
JS_SetPropertyFunctionList(js, mod, js_utf8_funcs, countof(js_utf8_funcs));
|
||||
return mod;
|
||||
}
|
||||
Reference in New Issue
Block a user