fix blob
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
sdl_video = "main"
|
||||
[dependencies]
|
||||
extramath = "https://gitea.pockle.world/john/extramath@master"
|
||||
extramath = "gitea.pockle.world/john/extramath@master"
|
||||
[system]
|
||||
ar_timer = 60
|
||||
actor_memory = 0
|
||||
|
||||
2
Makefile
2
Makefile
@@ -11,7 +11,7 @@ release: FORCE
|
||||
meson install -C build_release
|
||||
|
||||
sanitize: FORCE
|
||||
meson setup -Db_sanitize=address -Db_sanitize=memory -Db_sanitize=leak -Db_sanitize=undefined build_sani
|
||||
meson setup -Db_sanitize=address -Db_sanitize=memory -Db_sanitize=leak build_sani
|
||||
meson install -C build_sani
|
||||
|
||||
thread: FORCE
|
||||
|
||||
27
scripts/fd.c
27
scripts/fd.c
@@ -223,10 +223,36 @@ JSC_SCALL(fd_mv,
|
||||
}
|
||||
)
|
||||
|
||||
JSC_SCALL(fd_symlink,
|
||||
if (argc < 2)
|
||||
ret = JS_ThrowTypeError(js, "fd.symlink requires 2 arguments: target and link path");
|
||||
else if (!JS_IsString(argv[1]))
|
||||
ret = JS_ThrowTypeError(js, "second argument must be a string (link path)");
|
||||
else {
|
||||
const char *link_path = JS_ToCString(js, argv[1]);
|
||||
#ifdef _WIN32
|
||||
if (!CreateSymbolicLinkA(link_path, str, SYMBOLIC_LINK_FLAG_DIRECTORY)) {
|
||||
// Try file
|
||||
if (!CreateSymbolicLinkA(link_path, str, 0)) {
|
||||
ret = JS_ThrowInternalError(js, "could not create symlink %s -> %s: %lu", link_path, str, GetLastError());
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (symlink(str, link_path) != 0)
|
||||
ret = JS_ThrowInternalError(js, "could not create symlink %s -> %s: %s", link_path, str, strerror(errno));
|
||||
#endif
|
||||
JS_FreeCString(js, link_path);
|
||||
}
|
||||
)
|
||||
|
||||
// Helper function for recursive removal
|
||||
static int remove_recursive(const char *path) {
|
||||
struct stat st;
|
||||
#ifdef _WIN32
|
||||
if (stat(path, &st) != 0)
|
||||
#else
|
||||
if (lstat(path, &st) != 0)
|
||||
#endif
|
||||
return -1;
|
||||
|
||||
if (S_ISDIR(st.st_mode)) {
|
||||
@@ -565,6 +591,7 @@ static const JSCFunctionListEntry js_fd_funcs[] = {
|
||||
MIST_FUNC_DEF(fd, is_file, 1),
|
||||
MIST_FUNC_DEF(fd, is_dir, 1),
|
||||
MIST_FUNC_DEF(fd, enumerate, 2),
|
||||
MIST_FUNC_DEF(fd, symlink, 2),
|
||||
};
|
||||
|
||||
JSValue js_fd_use(JSContext *js) {
|
||||
|
||||
58
scripts/os.c
58
scripts/os.c
@@ -383,6 +383,7 @@ static JSValue js_os_dylib_symbol(JSContext *js, JSValue self, int argc, JSValue
|
||||
error_msg = dl_error;
|
||||
}
|
||||
#endif
|
||||
return JS_ThrowReferenceError(js, "Failed to load symbol: %s", error_msg);
|
||||
return JS_NULL;
|
||||
}
|
||||
|
||||
@@ -390,6 +391,34 @@ static JSValue js_os_dylib_symbol(JSContext *js, JSValue self, int argc, JSValue
|
||||
return symbol(js);
|
||||
}
|
||||
|
||||
static JSValue js_os_dylib_has_symbol(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
{
|
||||
if (argc < 2) {
|
||||
return JS_ThrowTypeError(js, "dylib_has_symbol requires dylib object and symbol name");
|
||||
}
|
||||
|
||||
void *handle = JS_GetOpaque(argv[0], js_dylib_class_id);
|
||||
if (!handle) {
|
||||
return JS_ThrowTypeError(js, "First argument must be a dylib object");
|
||||
}
|
||||
|
||||
const char *symbol_name = JS_ToCString(js, argv[1]);
|
||||
if (!symbol_name) {
|
||||
return JS_ThrowTypeError(js, "symbol name must be a string");
|
||||
}
|
||||
|
||||
void *symbol;
|
||||
#ifdef _WIN32
|
||||
symbol = (void*)GetProcAddress((HMODULE)handle, symbol_name);
|
||||
#else
|
||||
symbol = dlsym(handle, symbol_name);
|
||||
#endif
|
||||
|
||||
JS_FreeCString(js, symbol_name);
|
||||
|
||||
return JS_NewBool(js, symbol != NULL);
|
||||
}
|
||||
|
||||
JSC_CCALL(os_print,
|
||||
size_t len;
|
||||
const char *str = JS_ToCStringLen(js, &len, argv[0]);
|
||||
@@ -427,6 +456,33 @@ static JSValue js_os_load_internal(JSContext *js, JSValue self, int argc, JSValu
|
||||
return symbol(js);
|
||||
}
|
||||
|
||||
static JSValue js_os_internal_exists(JSContext *js, JSValue self, int argc, JSValue *argv)
|
||||
{
|
||||
void *handle;
|
||||
#ifdef _WIN32
|
||||
handle = GetModuleHandle(NULL);
|
||||
#else
|
||||
handle = dlopen(NULL, RTLD_LAZY);
|
||||
#endif
|
||||
if (argc < 1)
|
||||
return JS_ThrowTypeError(js, "internal_exists requires a symbol name");
|
||||
|
||||
const char *symbol_name = JS_ToCString(js, argv[0]);
|
||||
if (!symbol_name)
|
||||
return JS_ThrowTypeError(js, "symbol name must be a string");
|
||||
|
||||
void *symbol;
|
||||
#if defined(_WIN32)
|
||||
symbol = (void*)GetProcAddress((HMODULE)handle, symbol_name);
|
||||
#else
|
||||
symbol = dlsym(handle, symbol_name);
|
||||
#endif
|
||||
|
||||
JS_FreeCString(js, symbol_name);
|
||||
|
||||
return JS_NewBool(js, symbol != NULL);
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
// ------- Windows: use BCryptGenRandom -------
|
||||
int randombytes(void *buf, size_t n) {
|
||||
@@ -494,7 +550,9 @@ static const JSCFunctionListEntry js_os_funcs[] = {
|
||||
MIST_FUNC_DEF(os, sleep, 1),
|
||||
MIST_FUNC_DEF(os, dylib_open, 1),
|
||||
MIST_FUNC_DEF(os, dylib_symbol, 2),
|
||||
MIST_FUNC_DEF(os, dylib_has_symbol, 2),
|
||||
MIST_FUNC_DEF(os, load_internal, 1),
|
||||
MIST_FUNC_DEF(os, internal_exists, 1),
|
||||
MIST_FUNC_DEF(os, print, 1),
|
||||
MIST_FUNC_DEF(os, random, 0),
|
||||
};
|
||||
|
||||
@@ -1,49 +1,29 @@
|
||||
// cell replace <alias> <path> - Add or update a replace directive for a dependency
|
||||
// cell replace [package] [path]
|
||||
// replace a package with a local directory
|
||||
|
||||
var fd = use('fd')
|
||||
var shop = use('shop')
|
||||
|
||||
if (args.length < 2) {
|
||||
log.console("Usage: cell replace <alias> <path>")
|
||||
log.console("Examples:")
|
||||
log.console(" cell replace prosperon ../prosperon")
|
||||
log.console(" cell replace extramath ../my-fork-of-extramath")
|
||||
log.console("Usage: cell replace <package> <path>")
|
||||
log.console(" cell replace <package> --remove")
|
||||
$_.stop()
|
||||
return
|
||||
}
|
||||
|
||||
var alias = args[0]
|
||||
var pkg = args[0]
|
||||
var path = args[1]
|
||||
|
||||
// Initialize shop if needed
|
||||
if (!fd.stat('.cell/cell.toml').isFile) {
|
||||
log.console("No cell.toml found. Initializing...")
|
||||
shop.init()
|
||||
if (path == '--remove') {
|
||||
if (shop.remove_replacement(pkg)) {
|
||||
log.console("Replacement removed.")
|
||||
} else {
|
||||
log.console("Failed to remove replacement.")
|
||||
}
|
||||
|
||||
// Load current config
|
||||
var config = shop.load_config()
|
||||
if (!config) {
|
||||
log.error("Failed to load cell.toml")
|
||||
$_.stop()
|
||||
return
|
||||
} else {
|
||||
if (shop.add_replacement(pkg, path)) {
|
||||
log.console("Replacement added.")
|
||||
} else {
|
||||
log.console("Failed to add replacement.")
|
||||
}
|
||||
|
||||
// Check if the alias exists in dependencies
|
||||
if (!config.dependencies || !config.dependencies[alias]) {
|
||||
log.console("Warning: '" + alias + "' is not in dependencies. Adding replace anyway.")
|
||||
}
|
||||
|
||||
// Ensure replace section exists
|
||||
if (!config.replace) {
|
||||
config.replace = {}
|
||||
}
|
||||
|
||||
// Add or update the replace directive
|
||||
config.replace[alias] = path
|
||||
shop.save_config(config)
|
||||
|
||||
log.console("Added replace directive: " + alias + " = " + path)
|
||||
log.console("Run 'cell build' to apply changes")
|
||||
|
||||
$_.stop()
|
||||
197
scripts/shop.cm
197
scripts/shop.cm
@@ -348,11 +348,6 @@ Shop.get_module_dir = function(alias) {
|
||||
return null
|
||||
}
|
||||
|
||||
// Check if replaced
|
||||
if (config.replace && config.replace[alias]) {
|
||||
return config.replace[alias]
|
||||
}
|
||||
|
||||
var pkg = config.dependencies[alias]
|
||||
var parsed = Shop.parse_package(pkg)
|
||||
if (!parsed) return null
|
||||
@@ -568,19 +563,19 @@ function resolve_locator(path, ext, ctx)
|
||||
return null;
|
||||
}
|
||||
|
||||
function resolve_c_symbol(path, package_ctx)
|
||||
function resolve_c_symbol(path, package_context)
|
||||
{
|
||||
var local_path = package_ctx ? package_ctx : 'local'
|
||||
var local_path = package_context ? package_context : 'local'
|
||||
var local_sym_base = path.replace(/\//g, '_').replace(/-/g, '_').replace(/\./g, '_')
|
||||
var local
|
||||
|
||||
if (!package_ctx) {
|
||||
if (!package_context) {
|
||||
local = `js_local_${local_sym_base}_use`
|
||||
} else {
|
||||
local = `js_${local_path.replace(/\//g, '_').replace(/-/g, '_').replace(/\./g, '_')}_${local_sym_base}_use`
|
||||
}
|
||||
|
||||
var build_dir = get_build_dir(package_ctx)
|
||||
var build_dir = get_build_dir(package_context)
|
||||
var local_dl_name = build_dir + '/cellmod' + dylib_ext
|
||||
|
||||
if (fd.is_file(local_dl_name)) {
|
||||
@@ -588,19 +583,25 @@ function resolve_c_symbol(path, package_ctx)
|
||||
open_dls[local_dl_name] = os.dylib_open(local_dl_name);
|
||||
|
||||
if (open_dls[local_dl_name]) {
|
||||
var local_addr = os.dylib_symbol(open_dls[local_dl_name], local);
|
||||
if (local_addr) return {symbol: local_addr, scope: SCOPE_LOCAL};
|
||||
if (os.dylib_has_symbol(open_dls[local_dl_name], local))
|
||||
return {
|
||||
symbol: function() { return os.dylib_symbol(open_dls[local_dl_name], local); },
|
||||
scope: SCOPE_LOCAL
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Try static linking fallback
|
||||
var static_local_addr = os.load_internal(local);
|
||||
if (static_local_addr) return {symbol: static_local_addr, scope: SCOPE_LOCAL};
|
||||
if (os.internal_exists(local))
|
||||
return {
|
||||
symbol: function() { return os.load_internal(local); },
|
||||
scope: SCOPE_LOCAL
|
||||
};
|
||||
|
||||
// If 'path' has a package alias (e.g. 'prosperon/sprite'), try to resolve it
|
||||
var pkg_alias = get_import_package(path)
|
||||
if (pkg_alias) {
|
||||
var canon_pkg = get_normalized_package(path, package_ctx)
|
||||
var canon_pkg = get_normalized_package(path, package_context)
|
||||
if (canon_pkg) {
|
||||
var build_dir = get_build_dir(canon_pkg)
|
||||
var dl_path = build_dir + '/cellmod' + dylib_ext
|
||||
@@ -613,20 +614,30 @@ function resolve_c_symbol(path, package_ctx)
|
||||
if (fd.is_file(dl_path)) {
|
||||
if (!open_dls[dl_path]) open_dls[dl_path] = os.dylib_open(dl_path)
|
||||
if (open_dls[dl_path]) {
|
||||
var addr = os.dylib_symbol(open_dls[dl_path], sym_name)
|
||||
if (addr) return {symbol: addr, scope: SCOPE_PACKAGE, package: canon_pkg}
|
||||
if (os.dylib_has_symbol(open_dls[dl_path], sym_name))
|
||||
return {
|
||||
symbol: function() { return os.dylib_symbol(open_dls[dl_path], sym_name) },
|
||||
scope: SCOPE_PACKAGE,
|
||||
package: canon_pkg
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var static_package_addr = os.load_internal(sym_name);
|
||||
if (static_package_addr)
|
||||
return {symbol:static_package_addr, scope: SCOPE_PACKAGE, package: canon_pkg};
|
||||
if (os.internal_exists(sym_name))
|
||||
return {
|
||||
symbol: function() { return os.load_internal(sym_name) },
|
||||
scope: SCOPE_PACKAGE,
|
||||
package: canon_pkg
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
var core_addr = os.load_internal(`js_${path.replace(/\//g, '_')}_use`);
|
||||
if (core_addr)
|
||||
return {symbol:core_addr, scope: SCOPE_CORE};
|
||||
var core_sym = `js_${path.replace(/\//g, '_')}_use`;
|
||||
if (os.internal_exists(core_sym))
|
||||
return {
|
||||
symbol: function() { return os.load_internal(core_sym); },
|
||||
scope: SCOPE_CORE
|
||||
};
|
||||
|
||||
return null
|
||||
}
|
||||
@@ -650,11 +661,11 @@ Shop.use = function(path, package_context) {
|
||||
return use_cache[cache_key]
|
||||
|
||||
if (c_resolve.scope < mod_resolve.scope)
|
||||
use_cache[cache_key] = c_resolve.symbol
|
||||
use_cache[cache_key] = c_resolve.symbol()
|
||||
else if (mod_resolve.scope < c_resolve.scope)
|
||||
use_cache[cache_key] = mod_resolve.symbol.call()
|
||||
else
|
||||
use_cache[cache_key] = mod_resolve.symbol.call(c_resolve.symbol)
|
||||
use_cache[cache_key] = mod_resolve.symbol.call(c_resolve.symbol())
|
||||
|
||||
return use_cache[cache_key]
|
||||
}
|
||||
@@ -671,23 +682,11 @@ function get_cache_path(pkg, commit) {
|
||||
}
|
||||
|
||||
function rm_recursive(path) {
|
||||
var st = fd.stat(path)
|
||||
if (!st) return
|
||||
|
||||
if (!st.isDirectory) {
|
||||
fd.unlink(path)
|
||||
return
|
||||
try {
|
||||
fd.rm(path)
|
||||
} catch (e) {
|
||||
log.error("Failed to remove " + path + ": " + e)
|
||||
}
|
||||
|
||||
var list = fd.readdir(path)
|
||||
if (list) {
|
||||
for (var i = 0; i < list.length; i++) {
|
||||
var item = list[i]
|
||||
if (item == '.' || item == '..') continue
|
||||
rm_recursive(path + "/" + item)
|
||||
}
|
||||
}
|
||||
fd.rmdir(path)
|
||||
}
|
||||
|
||||
function get_all_files(dir, prefix, results) {
|
||||
@@ -745,9 +744,8 @@ function verify_zip_contents(zip, target_dir) {
|
||||
|
||||
// Check for extra files
|
||||
var existing_files = get_all_files(target_dir)
|
||||
for (var i = 0; i < existing_files.length; i++) {
|
||||
for (var i = 0; i < existing_files.length; i++)
|
||||
if (!expected_files[existing_files[i]]) return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
@@ -944,42 +942,27 @@ Shop.get = function(pkg, alias) {
|
||||
return true
|
||||
}
|
||||
|
||||
// High-level: Update a specific package or all packages
|
||||
// Like `bun update` or `bun update <pkg>`
|
||||
Shop.update_all = function(alias) {
|
||||
Shop.fetch = function(package)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// High-level: Update a specific package
|
||||
// Like `bun update <pkg>`
|
||||
Shop.update = function(pkg) {
|
||||
var config = Shop.load_config()
|
||||
if (!config || !config.dependencies) {
|
||||
log.console("No dependencies to update.")
|
||||
return
|
||||
}
|
||||
|
||||
var lock = Shop.load_lock()
|
||||
var queue = []
|
||||
var processed = {}
|
||||
|
||||
// Initialize queue
|
||||
if (alias) {
|
||||
if (config.dependencies[alias]) {
|
||||
queue.push(config.dependencies[alias])
|
||||
} else {
|
||||
log.error("Dependency not found: " + alias)
|
||||
return
|
||||
// Check if replaced
|
||||
if (config.replace && config.replace[pkg]) {
|
||||
log.console("Skipping update for replaced package " + pkg)
|
||||
Shop.update(config.replace[pkg])
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
for (var k in config.dependencies) {
|
||||
queue.push(config.dependencies[k])
|
||||
}
|
||||
}
|
||||
|
||||
while (queue.length > 0) {
|
||||
var pkg = queue.shift()
|
||||
if (processed[pkg]) continue
|
||||
processed[pkg] = true
|
||||
|
||||
// Find existing lock info
|
||||
var lock_info = lock[pkg]
|
||||
var local_hash = lock_info ? lock_info.commit : null
|
||||
var local_zip_hash = lock_info ? lock_info.zip_hash : null
|
||||
|
||||
var api_url = Shop.get_api_url(pkg)
|
||||
var remote_hash = null
|
||||
@@ -994,23 +977,25 @@ Shop.update_all = function(alias) {
|
||||
}
|
||||
}
|
||||
|
||||
var target_hash = remote_hash || local_hash
|
||||
var target_hash = remote_hash
|
||||
if (!target_hash) {
|
||||
log.error("Could not resolve commit for " + pkg)
|
||||
continue
|
||||
log.error("Could not resolve remote commit for " + pkg)
|
||||
return false
|
||||
}
|
||||
|
||||
var is_update = remote_hash && local_hash && (remote_hash != local_hash)
|
||||
if (is_update) {
|
||||
log.console("Updating " + pkg + " " + local_hash.substring(0,8) + " -> " + remote_hash.substring(0,8))
|
||||
if (local_hash && remote_hash == local_hash) {
|
||||
log.console(alias + " is already up to date.")
|
||||
return true
|
||||
}
|
||||
|
||||
if (local_hash) {
|
||||
log.console("Updating " + alias + " " + local_hash.substring(0,8) + " -> " + remote_hash.substring(0,8))
|
||||
} else {
|
||||
log.console("Checking " + pkg + "...")
|
||||
log.console("Installing " + alias + "...")
|
||||
}
|
||||
|
||||
// Install/Verify
|
||||
// If updating, we pass null as local_zip_hash to force fresh download/check
|
||||
// If verifying, we pass local_zip_hash
|
||||
var result = install_from_package(pkg, target_hash, is_update ? null : local_zip_hash)
|
||||
// Install with fresh download (no zip hash to force redownload)
|
||||
var result = install_from_package(pkg, target_hash, null)
|
||||
|
||||
if (result) {
|
||||
// Update lock
|
||||
@@ -1020,24 +1005,13 @@ Shop.update_all = function(alias) {
|
||||
zip_hash: result.zip_hash,
|
||||
updated: time.number()
|
||||
}
|
||||
|
||||
// Read package config to find dependencies
|
||||
var parsed = Shop.parse_package(pkg)
|
||||
var pkg_config = Shop.load_config(parsed.path)
|
||||
|
||||
if (pkg_config && pkg_config.dependencies) {
|
||||
for (var k in pkg_config.dependencies) {
|
||||
var dep_pkg = pkg_config.dependencies[k]
|
||||
if (!processed[dep_pkg]) {
|
||||
queue.push(dep_pkg)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Shop.save_lock(lock)
|
||||
log.console("Update complete.")
|
||||
log.console("Updated " + alias + ".")
|
||||
return true
|
||||
}
|
||||
|
||||
log.error("Failed to update " + alias)
|
||||
return false
|
||||
}
|
||||
|
||||
// High-level: Remove a package and clean up
|
||||
@@ -1077,6 +1051,33 @@ Shop.remove = function(alias) {
|
||||
return true
|
||||
}
|
||||
|
||||
Shop.add_replacement = function(alias, replacement) {
|
||||
var config = Shop.load_config()
|
||||
if (!config) config = {}
|
||||
if (!config.replace) config.replace = {}
|
||||
|
||||
config.replace[alias] = replacement
|
||||
Shop.save_config(config)
|
||||
|
||||
log.console("Added replacement: " + alias + " = " + replacement)
|
||||
return true
|
||||
}
|
||||
|
||||
Shop.remove_replacement = function(alias) {
|
||||
var config = Shop.load_config()
|
||||
if (!config || !config.replace || !config.replace[alias]) {
|
||||
log.error("No replacement found for " + alias)
|
||||
return false
|
||||
}
|
||||
|
||||
delete config.replace[alias]
|
||||
Shop.save_config(config)
|
||||
|
||||
log.console("Removed replacement for " + alias)
|
||||
log.console("Run 'cell update " + alias + "' to restore the package.")
|
||||
return true
|
||||
}
|
||||
|
||||
// Install all dependencies from config (like `bun install`)
|
||||
Shop.install_all = function() {
|
||||
Shop.init()
|
||||
|
||||
@@ -4,14 +4,14 @@ var shop = use('shop')
|
||||
|
||||
var alias = args.length > 0 ? args[0] : null
|
||||
|
||||
log.console("Checking for updates...")
|
||||
shop.update_all(alias)
|
||||
|
||||
var packages = shop.list_packages()
|
||||
|
||||
log.console(packages)
|
||||
log.console("Checking for updates...")
|
||||
|
||||
for (var pack of packages)
|
||||
for (var pack of packages) {
|
||||
log.console("Updating " + pack)
|
||||
shop.update(pack)
|
||||
shop.build_package(pack)
|
||||
}
|
||||
|
||||
$_.stop()
|
||||
@@ -221,7 +221,6 @@ static int blob_copy_bits(blob *dest, const void *src, size_t from, size_t to) {
|
||||
blob *blob_new(size_t capacity) {
|
||||
if (capacity < 0) capacity = 0;
|
||||
blob *b = calloc(1, sizeof(blob));
|
||||
printf("allocating blob %p size %zu\n", b, capacity);
|
||||
if (!b) return NULL;
|
||||
if (blob_ensure_capacity(b, capacity) < 0) {
|
||||
free(b);
|
||||
@@ -264,7 +263,6 @@ blob *blob_new_with_fill(size_t length_bits, int logical_value) {
|
||||
|
||||
void blob_destroy(blob *b) {
|
||||
if (!b) return;
|
||||
printf("destroying blob %p, data %p, length %zu, capacity %zu\n", b, b->data, b->length, b->capacity);
|
||||
if (b->data) {
|
||||
free(b->data);
|
||||
b->data = NULL;
|
||||
|
||||
@@ -102,7 +102,8 @@ JSValue js_##ID##_get_##ENTRY (JSContext *js, JSValue self) { \
|
||||
#define QJSCLASS(TYPE, ...)\
|
||||
JSClassID js_##TYPE##_id;\
|
||||
static void js_##TYPE##_finalizer(JSRuntime *rt, JSValue val){\
|
||||
TYPE *n = JS_GetOpaque(val, js_##TYPE##_id);\
|
||||
JSContext *js = JS_GetContext(rt);\
|
||||
TYPE *n = JS_GetOpaque2(js, val, js_##TYPE##_id); \
|
||||
TYPE##_free(rt,n);}\
|
||||
static JSClassDef js_##TYPE##_class = {\
|
||||
.class_name = #TYPE,\
|
||||
|
||||
@@ -10,10 +10,7 @@
|
||||
// Free function for blob
|
||||
void blob_free(JSRuntime *rt, blob *b)
|
||||
{
|
||||
if (b) {
|
||||
printf("destroying blob %p blob data %p, length %zu\n", b, b->data, b->length);
|
||||
blob_destroy(b);
|
||||
}
|
||||
// blob_destroy(b);
|
||||
}
|
||||
|
||||
// Use QJSCLASS macro to generate class boilerplate
|
||||
@@ -122,15 +119,7 @@ static JSValue js_blob_constructor(JSContext *ctx, JSValueConst new_target,
|
||||
return JS_ThrowOutOfMemory(ctx);
|
||||
}
|
||||
|
||||
JSValue ret = blob2js(ctx, bd);
|
||||
printf("created blob %p blob data %p, length %zu\n", bd, bd->data, bd->length);
|
||||
// Ensure the returned object's prototype is set correctly for instanceof
|
||||
JSValue ctor_proto = JS_GetPropertyStr(ctx, new_target, "prototype");
|
||||
if (!JS_IsException(ctor_proto)) {
|
||||
JS_SetPrototype(ctx, ret, ctor_proto);
|
||||
}
|
||||
JS_FreeValue(ctx, ctor_proto);
|
||||
return ret;
|
||||
return blob2js(ctx, bd);
|
||||
}
|
||||
|
||||
// blob.write_bit(logical)
|
||||
@@ -323,8 +312,6 @@ static JSValue js_blob_read_blob(JSContext *ctx, JSValueConst this_val,
|
||||
return JS_ThrowOutOfMemory(ctx);
|
||||
}
|
||||
|
||||
printf("stoned copy blob %p blob data %p, length %" PRId64 "\n", new_bd, new_bd->data, new_bd->length);
|
||||
|
||||
return blob2js(ctx, new_bd);
|
||||
}
|
||||
|
||||
@@ -518,7 +505,6 @@ JSValue js_blob_use(JSContext *js) {
|
||||
// Explicitly set the prototype property to ensure instanceof works
|
||||
JS_SetPropertyStr(js, ctor, "__prototype__", JS_DupValue(js, proto));
|
||||
JS_FreeValue(js, proto);
|
||||
|
||||
return ctor;
|
||||
}
|
||||
|
||||
@@ -529,8 +515,6 @@ JSValue js_new_blob_stoned_copy(JSContext *js, void *data, size_t bytes)
|
||||
b->length = bytes * 8; // Set the actual length in bits
|
||||
blob_make_stone(b);
|
||||
|
||||
printf("stoned copy blob %p blob data %p, length %" PRId64 "\n", b, b->data, b->length);
|
||||
|
||||
return blob2js(js, b);
|
||||
}
|
||||
|
||||
@@ -547,7 +531,13 @@ void *js_get_blob_data(JSContext *js, size_t *size, JSValue v)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (b->length % 8 != 0) {
|
||||
JS_ThrowReferenceError(js, "attempted to read data from a non-byte aligned blob");
|
||||
return -1;
|
||||
}
|
||||
|
||||
*size = (b->length + 7) / 8; // Return actual byte size based on bit length
|
||||
|
||||
return b->data;
|
||||
}
|
||||
|
||||
@@ -556,11 +546,26 @@ void *js_get_blob_data_bits(JSContext *js, size_t *bits, JSValue v)
|
||||
blob *b = js2blob(js, v);
|
||||
if (!b) {
|
||||
JS_ThrowReferenceError(js, "get_blob_data_bits: not called on a blob");
|
||||
return NULL;
|
||||
return -1;
|
||||
}
|
||||
if (!b->is_stone) {
|
||||
JS_ThrowReferenceError(js, "attempted to read data from a non-stone blob");
|
||||
return NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!b->data) {
|
||||
JS_ThrowReferenceError(js, "attempted to read data from an empty blob");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (b->length % 8 != 0) {
|
||||
JS_ThrowReferenceError(js, "attempted to read data from a non-byte aligned blob");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (b->length == 0) {
|
||||
JS_ThrowReferenceError(js, "attempted to read data from an empty blob");
|
||||
return -1;
|
||||
}
|
||||
|
||||
*bits = b->length;
|
||||
|
||||
@@ -240,6 +240,7 @@ struct JSRuntime {
|
||||
int shape_hash_count; /* number of hashed shapes */
|
||||
JSShape **shape_hash;
|
||||
void *user_opaque;
|
||||
JSContext *js;
|
||||
};
|
||||
|
||||
struct JSClass {
|
||||
@@ -1576,6 +1577,7 @@ void JS_FreeRuntime(JSRuntime *rt)
|
||||
|
||||
JSContext *JS_NewContextRaw(JSRuntime *rt)
|
||||
{
|
||||
assert(!rt->js);
|
||||
JSContext *ctx;
|
||||
int i;
|
||||
|
||||
@@ -1599,6 +1601,7 @@ JSContext *JS_NewContextRaw(JSRuntime *rt)
|
||||
ctx->regexp_ctor = JS_NULL;
|
||||
|
||||
JS_AddIntrinsicBasicObjects(ctx);
|
||||
rt->js = ctx;
|
||||
return ctx;
|
||||
}
|
||||
|
||||
@@ -37481,3 +37484,11 @@ JSValue js_debugger_closure_variables(JSContext *ctx, JSValue fn) {
|
||||
done:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void *js_debugger_val_address(JSContext *ctx, JSValue val) {
|
||||
return JS_VALUE_GET_PTR(val);
|
||||
}
|
||||
|
||||
JSContext *JS_GetContext(JSRuntime *rt) {
|
||||
return rt->js;
|
||||
}
|
||||
@@ -362,6 +362,7 @@ JS_BOOL JS_IsLiveObject(JSRuntime *rt, JSValueConst obj);
|
||||
JSContext *JS_NewContext(JSRuntime *rt);
|
||||
void JS_FreeContext(JSContext *s);
|
||||
JSContext *JS_DupContext(JSContext *ctx);
|
||||
JSContext *JS_GetContext(JSRuntime *rt);
|
||||
void *JS_GetContextOpaque(JSContext *ctx);
|
||||
void JS_SetContextOpaque(JSContext *ctx, void *opaque);
|
||||
JSRuntime *JS_GetRuntime(JSContext *ctx);
|
||||
@@ -990,6 +991,7 @@ JSValue js_debugger_local_variables(JSContext *ctx, int stack_index);
|
||||
JSValue js_debugger_build_backtrace(JSContext *ctx, const uint8_t *cur_pc);
|
||||
JSValue js_debugger_fn_info(JSContext *ctx, JSValue fn);
|
||||
JSValue js_debugger_fn_bytecode(JSContext *js, JSValue fn);
|
||||
void *js_debugger_val_address(JSContext *js, JSValue val);
|
||||
|
||||
#undef js_unlikely
|
||||
#undef js_force_inline
|
||||
|
||||
Reference in New Issue
Block a user