MIRROR: javascript for 🐜's, a tiny runtime with big ambitions
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at type-hints-typescript 656 lines 21 kB view raw
1#ifndef ANT_INTERNAL_H 2#define ANT_INTERNAL_H 3 4#include "ant.h" 5#include "object.h" 6#include "pool.h" 7#include "sugar.h" 8#include "errors.h" 9#include "arena.h" 10#include "descriptors.h" 11#include "esm/loader.h" 12 13#include <assert.h> 14#include <string.h> 15 16// An IEEE 754 double-precision float is a 64-bit value with bits laid out like: 17// 18// 1 Sign bit 19// | 11 Exponent bits 20// | | 52 Mantissa (i.e. fraction) bits 21// | | | 22// S[Exponent-][Mantissa------------------------------------------] 23// 24// A NaN is any value where all exponent bits are set and the mantissa is 25// non-zero. That means there are a *lot* of bit patterns that all represent 26// NaN. NaN tagging takes advantage of this by repurposing those unused 27// patterns to encode non-numeric values. 28// 29// We define a NANBOX_PREFIX as the upper 12 bits all set (0xFFF0...): 30// 31// 1111 1111 1111 0000 0000 0000 ... 0000 32// [sign+exp all 1s ] [mantissa all 0s ] 33// 34// This corresponds to -Infinity in IEEE 754. Any 64-bit value strictly 35// greater than this prefix is a tagged (non-numeric) value. Any value less 36// than or equal to it is an unmodified double — so numeric math is free. 37// 38// For tagged values, we carve the remaining 52 mantissa bits into two fields: 39// 40// 1111 1111 1111 TTTTT DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD 41// [-- prefix ---][type][--------------- 47-bit data --------------------] 42// 43// The 5-bit type tag (bits 51–47) encodes up to 31 distinct types: objects, 44// strings, booleans, undefined, null, functions, closures, errors, etc. 45// The 47-bit data field holds either a heap offset (for heap-resident types 46// like objects and strings) or an immediate value (e.g. 1 for true, 0 for 47// false). 48// 49// Encoding and decoding are simple: 50// 51// mkval(type, data) = PREFIX | (type << 47) | (data & 0x7FFFFFFFFFFF) 52// vtype(v) = is_tagged(v) ? (v >> 47) & 0x1F : T_NUM 53// vdata(v) = v & 0x7FFFFFFFFFFF 54// is_tagged(v) = v > PREFIX 55 56#define NANBOX_TYPE_MASK 0x1F 57#define NANBOX_TYPE_SHIFT 0x2F 58#define NANBOX_HEAP_OFFSET 0x8 59#define NANBOX_PREFIX 0xFFF0000000000000ULL 60#define NANBOX_DATA_MASK 0x00007FFFFFFFFFFFULL 61 62#define JS_ERR_NO_STACK (1 << 8) 63#define JS_TPFLG(t) (1u << (t)) 64 65#define MAX_STRINGIFY_DEPTH 64 66#define MAX_PROTO_CHAIN_DEPTH 256 67#define MAX_MULTIREF_OBJS 128 68#define MAX_DENSE_INITIAL_CAP 8 69 70#define PROTO_WALK_F_OBJECT_ONLY (1u << 0) 71#define PROTO_WALK_F_LOOKUP (1u << 1) 72 73#define ROPE_MAX_DEPTH 4096 74#define ROPE_FLATTEN_THRESHOLD (512 * 1024) 75 76#define STR_BUILDER_TAIL_CAP 256u 77#define STR_HEAP_TAG_MASK 0x3ULL 78#define STR_HEAP_TAG_FLAT 0x0ULL 79#define STR_HEAP_TAG_ROPE 0x1ULL 80#define STR_HEAP_TAG_BUILDER 0x2ULL 81 82#define T_EMPTY (NANBOX_PREFIX | ((ant_value_t)T_SENTINEL << NANBOX_TYPE_SHIFT) | 0xDEADULL) 83#define T_SPECIAL_OBJECT_MASK (JS_TPFLG(T_OBJ) | JS_TPFLG(T_ARR)) 84#define T_NEEDS_PROTO_FALLBACK (JS_TPFLG(T_FUNC) | JS_TPFLG(T_ARR) | JS_TPFLG(T_PROMISE) | JS_TPFLG(T_GENERATOR)) 85#define T_OBJECT_MASK (JS_TPFLG(T_OBJ) | JS_TPFLG(T_ARR) | JS_TPFLG(T_FUNC) | JS_TPFLG(T_PROMISE) | JS_TPFLG(T_GENERATOR)) 86#define T_NON_NUMERIC_MASK (JS_TPFLG(T_STR) | JS_TPFLG(T_ARR) | JS_TPFLG(T_FUNC) | JS_TPFLG(T_CFUNC) | JS_TPFLG(T_OBJ) | JS_TPFLG(T_GENERATOR)) 87 88#define is_non_numeric(v) ((1u << vtype(v)) & T_NON_NUMERIC_MASK) 89#define is_object_type(v) ((1u << vtype(v)) & T_OBJECT_MASK) 90#define is_special_object(v) ((1u << vtype(v)) & T_SPECIAL_OBJECT_MASK) 91 92enum { 93 // heap-resident 94 T_OBJ = 0, 95 T_STR = 1, 96 T_ARR = 2, 97 98 // objects 99 T_FUNC, 100 T_CFUNC, 101 T_PROMISE, 102 T_GENERATOR, 103 104 // primitives 105 T_UNDEF, 106 T_NULL, 107 T_BOOL, 108 T_NUM, 109 T_BIGINT, 110 T_SYMBOL, 111 112 // internal 113 T_ERR, 114 T_TYPEDARRAY, 115 T_NTARG, 116 117 // collections 118 T_MAP, 119 T_SET, 120 T_WEAKMAP, 121 T_WEAKSET, 122 123 T_SENTINEL = NANBOX_TYPE_MASK 124}; 125 126typedef struct { 127 const char *src; 128 const char *filename; 129 ant_offset_t src_len; 130 ant_offset_t off; 131 ant_offset_t span_len; 132 bool valid; 133} js_error_site_t; 134 135struct ant_isolate_t { 136 sv_vm_t *vm; 137 138 ant_module_t *module; 139 ant_object_t *objects; 140 ant_object_t *permanent_objects; 141 142 ant_fixed_arena_t obj_arena; 143 ant_prop_ref_t *prop_refs; 144 145 ant_fixed_arena_t closure_arena; 146 ant_fixed_arena_t upvalue_arena; 147 148 ant_value_t **c_roots; 149 size_t c_root_count; 150 size_t c_root_cap; 151 struct gc_temp_root_scope *temp_roots; 152 153 const char *code; 154 const char *filename; 155 156 #ifdef ANT_JIT 157 void *jit_ctx; 158 #endif 159 160 ant_value_t global; 161 ant_value_t this_val; 162 ant_value_t new_target; 163 ant_value_t current_func; 164 ant_value_t length_str; 165 166 struct { 167 const char *length; 168 const char *buffer; 169 const char *prototype; 170 const char *constructor; 171 const char *name; 172 const char *message; 173 const char *done; 174 const char *value; 175 const char *get; 176 const char *set; 177 const char *arguments; 178 const char *callee; 179 const char *idx[10]; 180 } intern; 181 182 ant_value_t thrown_value; 183 ant_value_t thrown_stack; 184 185 struct { 186 void *base; 187 void *main_base; 188 void *main_lo; 189 size_t limit; 190 } cstk; 191 192 struct { 193 uint64_t counter; 194 struct sym_registry_entry *registry; 195 196 ant_value_t object_proto; 197 ant_value_t array_proto; 198 ant_value_t iterator_proto; 199 ant_value_t array_iterator_proto; 200 ant_value_t string_iterator_proto; 201 ant_value_t generator_proto; 202 ant_value_t async_generator_proto; 203 ant_value_t async_iterator_proto; 204 } sym; 205 206 ant_offset_t max_size; 207 ant_offset_t prop_refs_len; 208 ant_offset_t prop_refs_cap; 209 js_error_site_t errsite; 210 211 struct { 212 ant_pool_t rope; 213 ant_pool_t symbol; 214 ant_pool_t permanent; 215 ant_class_pool_t bigint; 216 ant_string_pool_t string; 217 } pool; 218 219 struct { 220 size_t closures; 221 size_t upvalues; 222 } alloc_bytes; 223 224 size_t gc_last_live; 225 size_t gc_pool_alloc; 226 size_t gc_pool_last_live; 227 228 ant_object_t *objects_old; 229 size_t old_live_count; 230 size_t minor_gc_count; 231 232 ant_object_t **remember_set; 233 size_t remember_set_len; 234 size_t remember_set_cap; 235 236 #ifdef ANT_JIT 237 uint32_t jit_active_depth; 238 #endif 239 240 uint32_t vm_exec_depth; 241 bool microtasks_draining; 242 struct coroutine *active_async_coro; 243 244 struct { 245 ant_value_t *items; 246 size_t len; 247 size_t cap; 248 } pending_rejections; 249 250 struct { 251 uintptr_t *cfunc_ptr; 252 ant_value_t *promoted; 253 uint8_t len; 254 uint8_t cap; 255 } cfunc_promote_cache; 256 257 struct { 258 const ant_cfunc_meta_t **base_meta; 259 const char **name_ptr; 260 ant_value_t *named; 261 uint16_t len; 262 uint16_t cap; 263 } cfunc_name_cache; 264 265 bool owns_mem; 266 bool fatal_error; 267 bool thrown_exists; 268}; 269 270enum { 271 STR_ASCII_UNKNOWN = 0, 272 STR_ASCII_YES = 1, 273 STR_ASCII_NO = 2, 274}; 275 276typedef struct { 277 ant_offset_t len; 278 uint8_t is_ascii; 279 char bytes[]; 280} ant_flat_string_t; 281 282typedef struct ant_builder_chunk { 283 struct ant_builder_chunk *next; 284 ant_value_t value; 285} ant_builder_chunk_t; 286 287typedef struct { 288 ant_offset_t len; 289 ant_builder_chunk_t *head; 290 ant_builder_chunk_t *chunk_tail; 291 ant_value_t cached; 292 uint16_t tail_len; 293 uint8_t ascii_state; 294 char tail[STR_BUILDER_TAIL_CAP]; 295} ant_string_builder_t; 296 297typedef struct { 298 const char *ptr; 299 size_t len; 300 bool needs_free; 301} js_cstr_t; 302 303typedef struct { 304 size_t count; 305 size_t bytes; 306} js_intern_stats_t; 307 308typedef struct { 309 bool has_getter; 310 bool has_setter; 311 bool writable; 312 bool enumerable; 313 bool configurable; 314 ant_value_t getter; 315 ant_value_t setter; 316} prop_meta_t; 317 318typedef enum { 319 PROP_META_STRING = 0, 320 PROP_META_SYMBOL = 1, 321} prop_meta_key_t; 322 323static inline bool is_err(ant_value_t v) { 324 return vtype(v) == T_ERR; 325} 326 327static inline bool is_null(ant_value_t v) { 328 return vtype(v) == T_NULL; 329} 330 331static inline bool is_undefined(ant_value_t v) { 332 return vtype(v) == T_UNDEF; 333} 334 335static inline bool is_empty_slot(ant_value_t v) { 336 return v == T_EMPTY; 337} 338 339static inline bool is_callable(ant_value_t v) { 340 uint8_t t = vtype(v); 341 return t == T_FUNC || t == T_CFUNC; 342} 343 344static inline const ant_cfunc_meta_t *js_as_cfunc_meta(ant_value_t fn_val) { 345 return (const ant_cfunc_meta_t *)(uintptr_t)vdata(fn_val); 346} 347 348static inline ant_cfunc_t js_as_cfunc(ant_value_t fn_val) { 349 const ant_cfunc_meta_t *meta = js_as_cfunc_meta(fn_val); 350 return meta ? meta->fn : NULL; 351} 352 353static inline uint32_t js_cfunc_length(ant_value_t fn_val) { 354 const ant_cfunc_meta_t *meta = js_as_cfunc_meta(fn_val); 355 return meta ? meta->length : 0; 356} 357 358static inline bool js_cfunc_same_entrypoint(ant_value_t fn_val, ant_cfunc_t fn) { 359 const ant_cfunc_meta_t *meta = js_as_cfunc_meta(fn_val); 360 return meta && meta->fn == fn; 361} 362 363size_t uint_to_str(char *buf, size_t bufsize, uint64_t val); 364int extract_array_args(ant_t *js, ant_value_t arr, ant_value_t **out_args); 365 366ant_value_t tov(double d); 367double tod(ant_value_t v); 368double js_to_number(ant_t *js, ant_value_t arg); 369 370bool js_obj_ensure_prop_capacity(ant_object_t *obj, uint32_t needed); 371bool js_obj_ensure_unique_shape(ant_object_t *obj); 372 373ant_value_t js_propref_load(ant_t *js, ant_offset_t handle); 374ant_value_t mkprop(ant_t *js, ant_value_t obj, ant_value_t k, ant_value_t v, uint8_t attrs); 375ant_value_t mkprop_interned(ant_t *js, ant_value_t obj, const char *interned_key, ant_value_t v, uint8_t attrs); 376ant_value_t mkprop_interned_exact(ant_t *js, ant_value_t obj, const char *interned_key, ant_value_t v, uint8_t attrs); 377ant_value_t setprop_cstr(ant_t *js, ant_value_t obj, const char *key, size_t len, ant_value_t v); 378ant_value_t setprop_interned(ant_t *js, ant_value_t obj, const char *key, size_t len, ant_value_t v); 379ant_value_t js_define_property(ant_t *js, ant_value_t obj, ant_value_t prop, ant_value_t descriptor, bool reflect_mode); 380 381// TODO: move into builder.c 382typedef struct { 383 ant_t *js; 384 char *buf; 385 size_t len; 386 size_t n; 387 bool growable; 388 bool inline_mode; 389 bool first; 390 bool closed; 391 bool did_indent; 392} js_inspect_builder_t; 393 394void js_inspect_builder_init_fixed(js_inspect_builder_t *builder, ant_t *js, char *buf, size_t len, size_t initial_n); 395bool js_inspect_builder_init_dynamic(js_inspect_builder_t *builder, ant_t *js, size_t initial_cap); 396void js_inspect_builder_dispose(js_inspect_builder_t *builder); 397bool js_inspect_tagged_header(js_inspect_builder_t *builder, const char *tag, size_t tag_len); 398bool js_inspect_object_body(js_inspect_builder_t *builder, ant_value_t obj); 399bool js_inspect_close(js_inspect_builder_t *builder); 400 401__attribute__((format(printf, 2, 3))) 402bool js_inspect_header(js_inspect_builder_t *builder, const char *fmt, ...); 403 404__attribute__((format(printf, 3, 4))) 405bool js_inspect_header_for(js_inspect_builder_t *builder, ant_value_t obj, const char *fmt, ...); 406 407ant_value_t js_inspect_builder_result(js_inspect_builder_t *builder); 408ant_value_t js_define_own_prop(ant_t *js, ant_value_t obj, const char *key, size_t klen, ant_value_t v); 409ant_value_t js_instance_proto_from_new_target(ant_t *js, ant_value_t fallback_proto); 410 411ant_value_t js_get_module_import_binding(ant_t *js); 412ant_value_t js_builtin_import(ant_t *js, ant_value_t *args, int nargs); 413ant_value_t js_create_import_meta(ant_t *js, const char *filename, bool is_main); 414ant_value_t js_create_module_context(ant_t *js, const char *filename, bool is_main); 415ant_value_t js_create_arguments_object(ant_t *js, ant_value_t callee, sv_frame_t *frame, int argc, int mapped_count, bool is_strict); 416 417void js_arguments_detach(ant_t *js, ant_value_t obj); 418void js_arguments_sync_slot(ant_t *js, ant_value_t obj, uint32_t idx, ant_value_t value); 419 420ant_value_t coerce_to_str(ant_t *js, ant_value_t v); 421ant_value_t coerce_to_str_concat(ant_t *js, ant_value_t v); 422ant_value_t get_ctor_species_value(ant_t *js, ant_value_t ctor); 423 424bool proto_chain_contains(ant_t *js, ant_value_t obj, ant_value_t proto_target); 425bool same_ctor_identity(ant_t *js, ant_value_t a, ant_value_t b); 426 427js_intern_stats_t js_intern_stats(void); 428const char *intern_string(const char *str, size_t len); 429js_cstr_t js_to_cstr(ant_t *js, ant_value_t value, char *stack_buf, size_t stack_size); 430 431ant_value_t lkp_interned_val(ant_t *js, ant_value_t obj, const char *search_intern); 432ant_offset_t lkp_interned(ant_t *js, ant_value_t obj, const char *search_intern, size_t len); 433 434ant_offset_t lkp(ant_t *js, ant_value_t obj, const char *buf, size_t len); 435ant_offset_t lkp_proto(ant_t *js, ant_value_t obj, const char *buf, size_t len); 436 437ant_offset_t lkp_sym(ant_t *js, ant_value_t obj, ant_offset_t sym_off); 438ant_offset_t lkp_sym_proto(ant_t *js, ant_value_t obj, ant_offset_t sym_off); 439 440ant_offset_t vstr(ant_t *js, ant_value_t value, ant_offset_t *len); 441ant_offset_t vstrlen(ant_t *js, ant_value_t value); 442ant_offset_t str_len_fast(ant_t *js, ant_value_t str); 443 444ant_value_t mkval(uint8_t type, uint64_t data); 445ant_value_t mkobj(ant_t *js, ant_offset_t parent); 446ant_value_t js_mkobj_with_inobj_limit(ant_t *js, uint8_t inobj_limit); 447ant_value_t rope_flatten(ant_t *js, ant_value_t rope); 448ant_value_t str_materialize(ant_t *js, ant_value_t value); 449 450ant_value_t js_for_in_keys(ant_t *js, ant_value_t obj); 451ant_value_t js_delete_prop(ant_t *js, ant_value_t obj, const char *key, size_t len); 452ant_value_t js_delete_sym_prop(ant_t *js, ant_value_t obj, ant_value_t sym); 453 454bool is_proxy(ant_value_t obj); 455bool strict_eq_values(ant_t *js, ant_value_t l, ant_value_t r); 456bool js_deep_equal(ant_t *js, ant_value_t a, ant_value_t b, bool strict); 457 458ant_value_t js_proxy_apply(ant_t *js, ant_value_t proxy, ant_value_t this_arg, ant_value_t *args, int argc); 459ant_value_t js_proxy_construct(ant_t *js, ant_value_t proxy, ant_value_t *args, int argc, ant_value_t new_target); 460ant_value_t sv_call_native(ant_t *js, ant_value_t func, ant_value_t this_val, ant_value_t *args, int nargs); 461 462const char *typestr(uint8_t t); 463ant_value_t unwrap_primitive(ant_t *js, ant_value_t val); 464ant_value_t do_string_op(ant_t *js, uint8_t op, ant_value_t l, ant_value_t r); 465ant_value_t js_to_primitive(ant_t *js, ant_value_t value, int hint); 466 467ant_value_t do_instanceof(ant_t *js, ant_value_t l, ant_value_t r); 468ant_value_t do_in(ant_t *js, ant_value_t l, ant_value_t r); 469 470bool js_is_prototype_of(ant_t *js, ant_value_t proto_obj, ant_value_t obj); 471ant_value_t builtin_object_isPrototypeOf(ant_t *js, ant_value_t *args, int nargs); 472ant_value_t builtin_object_freeze(ant_t *js, ant_value_t *args, int nargs); 473 474bool js_is_array_includes_builtin(ant_value_t func); 475ant_value_t js_array_includes_call(ant_t *js, ant_value_t this_val, ant_value_t *args, int nargs); 476ant_value_t builtin_array_includes(ant_t *js, ant_value_t *args, int nargs); 477 478void js_module_eval_ctx_push(ant_t *js, ant_module_t *ctx); 479void js_module_eval_ctx_pop(ant_t *js, ant_module_t *ctx); 480 481bool lookup_prop_meta( 482 ant_t *js, ant_value_t cur_obj, 483 prop_meta_key_t key_kind, 484 const char *key, size_t klen, 485 ant_offset_t sym_off, prop_meta_t *out 486); 487 488static inline ant_value_t js_module_eval_active_ns(ant_t *js) { 489 ant_module_t *ctx = js->module; 490 return ctx ? ctx->module_ns : js_mkundef(); 491} 492 493static inline ant_value_t js_module_eval_active_ctx(ant_t *js) { 494 ant_module_t *ctx = js->module; 495 return ctx ? ctx->module_ctx : js_mkundef(); 496} 497 498static inline ant_value_t js_module_eval_active_import_meta(ant_t *js) { 499 ant_value_t module_ctx = js_module_eval_active_ctx(js); 500 return is_object_type(module_ctx) ? js_get(js, module_ctx, "meta") : js_mkundef(); 501} 502 503static inline const char *js_module_eval_active_filename(ant_t *js) { 504 ant_value_t module_ctx = js_module_eval_active_ctx(js); 505 if (is_object_type(module_ctx)) { 506 ant_value_t filename = js_get(js, module_ctx, "filename"); 507 if (vtype(filename) == T_STR) return js_getstr(js, filename, NULL); 508 } 509 return js->filename; 510} 511 512static inline ant_module_format_t js_module_eval_active_format(ant_t *js) { 513 ant_module_t *ctx = js->module; 514 return ctx ? ctx->format : MODULE_EVAL_FORMAT_UNKNOWN; 515} 516 517static inline bool is_length_key(const char *key, size_t len) { 518 return len == 6 && !memcmp(key, "length", 6); 519} 520 521// TODO: move strings helpers to strings.h 522static inline bool str_is_heap_rope(ant_value_t value) { 523 return vtype(value) == T_STR && ((vdata(value) & STR_HEAP_TAG_MASK) == STR_HEAP_TAG_ROPE); 524} 525 526static inline bool str_is_heap_builder(ant_value_t value) { 527 return vtype(value) == T_STR && ((vdata(value) & STR_HEAP_TAG_MASK) == STR_HEAP_TAG_BUILDER); 528} 529 530static inline ant_rope_heap_t *ant_str_rope_ptr(ant_value_t value) { 531 return (ant_rope_heap_t *)(uintptr_t)(vdata(value) & ~STR_HEAP_TAG_MASK); 532} 533 534static inline ant_string_builder_t *ant_str_builder_ptr(ant_value_t value) { 535 return (ant_string_builder_t *)(uintptr_t)(vdata(value) & ~STR_HEAP_TAG_MASK); 536} 537 538static inline ant_value_t ant_mkrope_value(ant_rope_heap_t *rope) { 539 return mkval(T_STR, ((uintptr_t)rope) | STR_HEAP_TAG_ROPE); 540} 541 542static inline ant_value_t ant_mkbuilder_value(ant_string_builder_t *builder) { 543 return mkval(T_STR, ((uintptr_t)builder) | STR_HEAP_TAG_BUILDER); 544} 545 546static inline int js_brand_id(ant_value_t obj) { 547 if (!is_object_type(obj)) return BRAND_NONE; 548 ant_value_t brand = js_get_slot(obj, SLOT_BRAND); 549 return vtype(brand) == T_NUM ? (int)js_getnum(brand) : BRAND_NONE; 550} 551 552static inline bool js_check_brand(ant_value_t obj, int brand) { 553 return js_brand_id(obj) == brand; 554} 555 556static inline bool lookup_symbol_prop_meta(ant_value_t cur_obj, ant_offset_t sym_off, prop_meta_t *out) { 557 return lookup_prop_meta(NULL, cur_obj, PROP_META_SYMBOL, NULL, 0, sym_off, out); 558} 559 560static inline bool lookup_string_prop_meta(ant_t *js, ant_value_t cur_obj, const char *key, size_t klen, prop_meta_t *out) { 561 return lookup_prop_meta(js, cur_obj, PROP_META_STRING, key, klen, 0, out); 562} 563 564static inline ant_value_t defmethod(ant_t *js, ant_value_t obj, const char *name, size_t len, ant_value_t fn) { 565 const char *interned = intern_string(name, len); 566 if (!interned) return js_mkerr(js, "oom"); 567 568 return mkprop_interned( 569 js, obj, interned, fn, 570 ANT_PROP_ATTR_WRITABLE | ANT_PROP_ATTR_CONFIGURABLE 571 ); 572} 573 574static inline ant_value_t defalias(ant_t *js, ant_value_t obj, const char *name, size_t len, ant_value_t fn) { 575 const char *interned = intern_string(name, len); 576 if (!interned) return js_mkerr(js, "oom"); 577 578 return mkprop_interned_exact( 579 js, obj, interned, fn, 580 ANT_PROP_ATTR_WRITABLE | ANT_PROP_ATTR_CONFIGURABLE 581 ); 582} 583 584static inline ant_flat_string_t *str_flat_from_bytes(const char *str) { 585 return (ant_flat_string_t *)((char *)str - offsetof(ant_flat_string_t, bytes)); 586} 587 588static inline ant_flat_string_t *ant_str_flat_ptr(ant_value_t value) { 589 if (vtype(value) != T_STR) return NULL; 590 if ((vdata(value) & STR_HEAP_TAG_MASK) != STR_HEAP_TAG_FLAT) return NULL; 591 return (ant_flat_string_t *)(uintptr_t)vdata(value); 592} 593 594static inline ant_flat_string_t *large_string_flat_ptr(ant_large_string_alloc_t *alloc) { 595 return alloc ? (ant_flat_string_t *)&alloc->len : NULL; 596} 597 598static inline ant_large_string_alloc_t *large_string_alloc_from_flat(ant_flat_string_t *flat) { 599 return flat ? (ant_large_string_alloc_t *)((char *)flat - offsetof(ant_large_string_alloc_t, len)) : NULL; 600} 601 602static inline uint8_t str_detect_ascii_bytes(const char *str, size_t len) { 603 const unsigned char *s = (const unsigned char *)str; 604 for (size_t i = 0; i < len; i++) { 605 if (s[i] >= 0x80) return STR_ASCII_NO; 606 } 607 return STR_ASCII_YES; 608} 609 610static inline void str_set_ascii_state(const char *str, uint8_t state) { 611 ant_flat_string_t *flat = str_flat_from_bytes(str); 612 flat->is_ascii = state; 613} 614 615static inline bool str_is_ascii(const char *str) { 616 ant_flat_string_t *flat = str_flat_from_bytes(str); 617 if (flat->is_ascii == STR_ASCII_UNKNOWN) { 618 flat->is_ascii = str_detect_ascii_bytes(flat->bytes, (size_t)flat->len); 619 } 620 return flat->is_ascii == STR_ASCII_YES; 621} 622 623static inline void js_set_module_default(ant_t *js, ant_value_t lib, ant_value_t ctor_fn, const char *name) { 624 js_set(js, ctor_fn, name, ctor_fn); 625 js_set(js, lib, name, ctor_fn); 626 js_set(js, lib, "default", ctor_fn); 627 js_set(js, ctor_fn, "default", ctor_fn); 628 js_set_slot_wb(js, lib, SLOT_DEFAULT, ctor_fn); 629} 630 631ant_value_t js_cfunc_promote(ant_t *js, ant_value_t cfunc); 632ant_value_t js_cfunc_expose_named(ant_t *js, ant_value_t cfunc, const char *name, size_t name_len); 633 634static inline ant_value_t js_cfunc_lookup_promoted(ant_t *js, ant_value_t cfunc) { 635 uintptr_t ptr = vdata(cfunc); 636 for (uint8_t i = 0; i < js->cfunc_promote_cache.len; i++) if ( 637 js->cfunc_promote_cache.cfunc_ptr[i] == ptr 638 ) return js->cfunc_promote_cache.promoted[i]; 639 return cfunc; 640} 641 642static inline ant_value_t js_make_ctor(ant_t *js, ant_cfunc_t fn, ant_value_t proto, const char *name, size_t nlen) { 643 ant_value_t obj = js_mkobj(js); 644 js_set_slot(obj, SLOT_CFUNC, js_mkfun_dyn(fn)); 645 js_mkprop_fast(js, obj, "prototype", 9, proto); 646 js_mkprop_fast(js, obj, "name", 4, js_mkstr(js, name, nlen)); 647 js_set_descriptor(js, obj, "name", 4, 0); 648 649 ant_value_t fn_val = js_obj_to_func(obj); 650 js_set(js, proto, "constructor", fn_val); 651 js_set_descriptor(js, proto, "constructor", 11, JS_DESC_W | JS_DESC_C); 652 653 return fn_val; 654} 655 656#endif