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.

add node:assert and node:v8 compat layers

+1063
+227
examples/spec/assert.js
··· 1 + import { test, testThrows, testDeep, summary } from './helpers.js'; 2 + import assert from 'node:assert'; 3 + 4 + console.log('assert.ok\n'); 5 + 6 + let threw = false; 7 + try { assert(false); } catch (e) { threw = true; } 8 + test('assert(false) throws', threw, true); 9 + 10 + threw = false; 11 + try { assert(0); } catch (e) { threw = true; } 12 + test('assert(0) throws', threw, true); 13 + 14 + threw = false; 15 + try { assert(''); } catch (e) { threw = true; } 16 + test('assert("") throws', threw, true); 17 + 18 + threw = false; 19 + try { assert(null); } catch (e) { threw = true; } 20 + test('assert(null) throws', threw, true); 21 + 22 + threw = false; 23 + try { assert(1); } catch (e) { threw = true; } 24 + test('assert(1) does not throw', threw, false); 25 + 26 + threw = false; 27 + try { assert('hello'); } catch (e) { threw = true; } 28 + test('assert("hello") does not throw', threw, false); 29 + 30 + threw = false; 31 + try { assert.ok(false, 'custom message'); } catch (e) { threw = true; } 32 + test('assert.ok with custom message throws', threw, true); 33 + 34 + console.log('\nassert.equal / assert.notEqual\n'); 35 + 36 + threw = false; 37 + try { assert.equal(1, 1); } catch (e) { threw = true; } 38 + test('equal(1, 1) passes', threw, false); 39 + 40 + threw = false; 41 + try { assert.equal(1, '1'); } catch (e) { threw = true; } 42 + test('equal(1, "1") passes (loose)', threw, false); 43 + 44 + threw = false; 45 + try { assert.equal(1, 2); } catch (e) { threw = true; } 46 + test('equal(1, 2) throws', threw, true); 47 + 48 + threw = false; 49 + try { assert.equal(null, undefined); } catch (e) { threw = true; } 50 + test('equal(null, undefined) passes (loose)', threw, false); 51 + 52 + threw = false; 53 + try { assert.notEqual(1, 2); } catch (e) { threw = true; } 54 + test('notEqual(1, 2) passes', threw, false); 55 + 56 + threw = false; 57 + try { assert.notEqual(1, 1); } catch (e) { threw = true; } 58 + test('notEqual(1, 1) throws', threw, true); 59 + 60 + console.log('\nassert.strictEqual / assert.notStrictEqual\n'); 61 + 62 + threw = false; 63 + try { assert.strictEqual(1, 1); } catch (e) { threw = true; } 64 + test('strictEqual(1, 1) passes', threw, false); 65 + 66 + threw = false; 67 + try { assert.strictEqual('a', 'a'); } catch (e) { threw = true; } 68 + test('strictEqual("a", "a") passes', threw, false); 69 + 70 + threw = false; 71 + try { assert.strictEqual(1, '1'); } catch (e) { threw = true; } 72 + test('strictEqual(1, "1") throws', threw, true); 73 + 74 + threw = false; 75 + try { assert.strictEqual(null, undefined); } catch (e) { threw = true; } 76 + test('strictEqual(null, undefined) throws', threw, true); 77 + 78 + threw = false; 79 + try { assert.strictEqual(NaN, NaN); } catch (e) { threw = true; } 80 + test('strictEqual(NaN, NaN) passes', threw, false); 81 + 82 + threw = false; 83 + try { assert.notStrictEqual(1, 2); } catch (e) { threw = true; } 84 + test('notStrictEqual(1, 2) passes', threw, false); 85 + 86 + threw = false; 87 + try { assert.notStrictEqual(1, 1); } catch (e) { threw = true; } 88 + test('notStrictEqual(1, 1) throws', threw, true); 89 + 90 + console.log('\nassert.deepEqual / assert.deepStrictEqual\n'); 91 + 92 + threw = false; 93 + try { assert.deepEqual({ a: 1 }, { a: 1 }); } catch (e) { threw = true; } 94 + test('deepEqual({a:1}, {a:1}) passes', threw, false); 95 + 96 + threw = false; 97 + try { assert.deepEqual([1, 2, 3], [1, 2, 3]); } catch (e) { threw = true; } 98 + test('deepEqual arrays passes', threw, false); 99 + 100 + threw = false; 101 + try { assert.deepEqual({ a: 1 }, { a: 2 }); } catch (e) { threw = true; } 102 + test('deepEqual({a:1}, {a:2}) throws', threw, true); 103 + 104 + threw = false; 105 + try { assert.deepEqual([1, 2], [1, 2, 3]); } catch (e) { threw = true; } 106 + test('deepEqual different length arrays throws', threw, true); 107 + 108 + threw = false; 109 + try { assert.deepStrictEqual({ a: 1 }, { a: 1 }); } catch (e) { threw = true; } 110 + test('deepStrictEqual({a:1}, {a:1}) passes', threw, false); 111 + 112 + threw = false; 113 + try { assert.deepStrictEqual({ a: 1 }, { a: '1' }); } catch (e) { threw = true; } 114 + test('deepStrictEqual({a:1}, {a:"1"}) throws', threw, true); 115 + 116 + threw = false; 117 + try { assert.deepStrictEqual({ a: { b: { c: 42 } } }, { a: { b: { c: 42 } } }); } catch (e) { threw = true; } 118 + test('deepStrictEqual nested objects passes', threw, false); 119 + 120 + threw = false; 121 + try { assert.notDeepEqual({ a: 1 }, { a: 2 }); } catch (e) { threw = true; } 122 + test('notDeepEqual({a:1}, {a:2}) passes', threw, false); 123 + 124 + threw = false; 125 + try { assert.notDeepEqual({ a: 1 }, { a: 1 }); } catch (e) { threw = true; } 126 + test('notDeepEqual({a:1}, {a:1}) throws', threw, true); 127 + 128 + threw = false; 129 + try { assert.notDeepStrictEqual({ a: 1 }, { a: '1' }); } catch (e) { threw = true; } 130 + test('notDeepStrictEqual({a:1}, {a:"1"}) passes', threw, false); 131 + 132 + console.log('\nassert.fail\n'); 133 + 134 + threw = false; 135 + try { assert.fail('boom'); } catch (e) { threw = true; } 136 + test('fail("boom") throws', threw, true); 137 + 138 + threw = false; 139 + try { assert.fail(); } catch (e) { threw = true; } 140 + test('fail() throws', threw, true); 141 + 142 + let failMsg = ''; 143 + try { assert.fail('specific message'); } catch (e) { failMsg = e.message; } 144 + test('fail message is preserved', failMsg, 'specific message'); 145 + 146 + console.log('\nassert.ifError\n'); 147 + 148 + threw = false; 149 + try { assert.ifError(null); } catch (e) { threw = true; } 150 + test('ifError(null) does not throw', threw, false); 151 + 152 + threw = false; 153 + try { assert.ifError(undefined); } catch (e) { threw = true; } 154 + test('ifError(undefined) does not throw', threw, false); 155 + 156 + threw = false; 157 + try { assert.ifError(new Error('oops')); } catch (e) { threw = true; } 158 + test('ifError(Error) throws', threw, true); 159 + 160 + threw = false; 161 + try { assert.ifError('some error'); } catch (e) { threw = true; } 162 + test('ifError(string) throws', threw, true); 163 + 164 + console.log('\nassert.throws / assert.doesNotThrow\n'); 165 + 166 + threw = false; 167 + try { assert.throws(() => { throw new Error('boom'); }); } catch (e) { threw = true; } 168 + test('throws with throwing fn passes', threw, false); 169 + 170 + threw = false; 171 + try { assert.throws(() => {}); } catch (e) { threw = true; } 172 + test('throws with non-throwing fn throws', threw, true); 173 + 174 + threw = false; 175 + try { assert.doesNotThrow(() => {}); } catch (e) { threw = true; } 176 + test('doesNotThrow with non-throwing fn passes', threw, false); 177 + 178 + threw = false; 179 + try { assert.doesNotThrow(() => { throw new Error('oops'); }); } catch (e) { threw = true; } 180 + test('doesNotThrow with throwing fn throws', threw, true); 181 + 182 + console.log('\nassert.match / assert.doesNotMatch\n'); 183 + 184 + threw = false; 185 + try { assert.match('hello world', /hello/); } catch (e) { threw = true; } 186 + test('match passes when pattern matches', threw, false); 187 + 188 + threw = false; 189 + try { assert.match('hello world', /xyz/); } catch (e) { threw = true; } 190 + test('match throws when pattern does not match', threw, true); 191 + 192 + threw = false; 193 + try { assert.doesNotMatch('hello world', /xyz/); } catch (e) { threw = true; } 194 + test('doesNotMatch passes when pattern does not match', threw, false); 195 + 196 + threw = false; 197 + try { assert.doesNotMatch('hello world', /hello/); } catch (e) { threw = true; } 198 + test('doesNotMatch throws when pattern matches', threw, true); 199 + 200 + console.log('\nassert.rejects / assert.doesNotReject\n'); 201 + 202 + let resolved = false; 203 + await assert.rejects(async () => { throw new Error('boom'); }); 204 + resolved = true; 205 + test('rejects resolves when fn rejects', resolved, true); 206 + 207 + resolved = false; 208 + try { await assert.rejects(async () => {}); } catch (e) { resolved = false; } 209 + test('rejects rejects when fn does not reject', resolved, false); 210 + 211 + resolved = false; 212 + await assert.doesNotReject(async () => {}); 213 + resolved = true; 214 + test('doesNotReject resolves when fn does not reject', resolved, true); 215 + 216 + console.log('\nAssertionError\n'); 217 + 218 + test('AssertionError is a constructor', typeof assert.AssertionError, 'function'); 219 + 220 + const ae = new assert.AssertionError({ message: 'test', actual: 1, expected: 2, operator: 'strictEqual' }); 221 + test('AssertionError has name', ae.name, 'AssertionError'); 222 + test('AssertionError has message', ae.message, 'test'); 223 + test('AssertionError has actual', ae.actual, 1); 224 + test('AssertionError has expected', ae.expected, 2); 225 + test('AssertionError has operator', ae.operator, 'strictEqual'); 226 + 227 + summary();
+134
examples/spec/v8.js
··· 1 + import { test, testDeep, summary } from './helpers.js'; 2 + import v8 from 'node:v8'; 3 + 4 + console.log('startupSnapshot\n'); 5 + 6 + test('isBuildingSnapshot is a function', typeof v8.startupSnapshot.isBuildingSnapshot, 'function'); 7 + test('isBuildingSnapshot returns false', v8.startupSnapshot.isBuildingSnapshot(), false); 8 + test('addSerializeCallback is a function', typeof v8.startupSnapshot.addSerializeCallback, 'function'); 9 + test('addDeserializeCallback is a function', typeof v8.startupSnapshot.addDeserializeCallback, 'function'); 10 + test('addSerializeCallback returns undefined', v8.startupSnapshot.addSerializeCallback(() => {}), undefined); 11 + test('addDeserializeCallback returns undefined', v8.startupSnapshot.addDeserializeCallback(() => {}), undefined); 12 + 13 + console.log('\ncachedDataVersionTag\n'); 14 + 15 + test('cachedDataVersionTag is a function', typeof v8.cachedDataVersionTag, 'function'); 16 + const tag = v8.cachedDataVersionTag(); 17 + test('cachedDataVersionTag returns a number', typeof tag, 'number'); 18 + test('cachedDataVersionTag is non-zero', tag !== 0, true); 19 + test('cachedDataVersionTag is stable', v8.cachedDataVersionTag() === v8.cachedDataVersionTag(), true); 20 + 21 + console.log('\ngetHeapStatistics\n'); 22 + 23 + const stats = v8.getHeapStatistics(); 24 + test('getHeapStatistics returns object', typeof stats, 'object'); 25 + 26 + const heapFields = [ 27 + 'total_heap_size', 'total_heap_size_executable', 'total_physical_size', 28 + 'total_available_size', 'total_global_handles_size', 'used_global_handles_size', 29 + 'used_heap_size', 'heap_size_limit', 'malloced_memory', 30 + 'peak_malloced_memory', 'does_zap_garbage', 'number_of_native_contexts', 31 + 'number_of_detached_contexts', 'total_heap_blinded_size' 32 + ]; 33 + for (const field of heapFields) { 34 + test(`getHeapStatistics has ${field}`, typeof stats[field], 'number'); 35 + } 36 + 37 + test('used_heap_size > 0', stats.used_heap_size > 0, true); 38 + test('total_heap_size >= used_heap_size', stats.total_heap_size >= stats.used_heap_size, true); 39 + test('total_physical_size > 0', stats.total_physical_size > 0, true); 40 + test('heap_size_limit > 0', stats.heap_size_limit > 0, true); 41 + test('number_of_native_contexts >= 1', stats.number_of_native_contexts >= 1, true); 42 + 43 + console.log('\ngetHeapSpaceStatistics\n'); 44 + 45 + const spaces = v8.getHeapSpaceStatistics(); 46 + test('getHeapSpaceStatistics returns array', Array.isArray(spaces), true); 47 + test('getHeapSpaceStatistics has spaces', spaces.length >= 1, true); 48 + 49 + const spaceFields = ['space_name', 'space_size', 'space_used_size', 'space_available_size', 'physical_space_size']; 50 + for (const space of spaces) { 51 + test(`space has name`, typeof space.space_name, 'string'); 52 + for (const field of spaceFields) { 53 + test(`${space.space_name} has ${field}`, typeof space[field], field === 'space_name' ? 'string' : 'number'); 54 + } 55 + } 56 + 57 + console.log('\ngetHeapCodeStatistics\n'); 58 + 59 + const code = v8.getHeapCodeStatistics(); 60 + test('getHeapCodeStatistics returns object', typeof code, 'object'); 61 + test('has code_and_metadata_size', typeof code.code_and_metadata_size, 'number'); 62 + test('has bytecode_and_metadata_size', typeof code.bytecode_and_metadata_size, 'number'); 63 + test('has external_script_source_size', typeof code.external_script_source_size, 'number'); 64 + test('has cpu_profiler_metadata_size', typeof code.cpu_profiler_metadata_size, 'number'); 65 + test('code_and_metadata_size >= bytecode_and_metadata_size', code.code_and_metadata_size >= code.bytecode_and_metadata_size, true); 66 + test('external_script_source_size > 0', code.external_script_source_size > 0, true); 67 + 68 + console.log('\nserialize / deserialize\n'); 69 + 70 + const roundtrip = (label, value) => { 71 + const buf = v8.serialize(value); 72 + test(`${label}: serialize returns Uint8Array`, buf instanceof Uint8Array, true); 73 + test(`${label}: buffer is non-empty`, buf.length > 0, true); 74 + const out = v8.deserialize(buf); 75 + test(`${label}: round-trip typeof`, typeof out, typeof value); 76 + return out; 77 + }; 78 + 79 + roundtrip('undefined', undefined); 80 + roundtrip('null', null); 81 + roundtrip('true', true); 82 + roundtrip('false', false); 83 + 84 + const n = roundtrip('integer', 42); 85 + test('integer value preserved', n, 42); 86 + 87 + const f = roundtrip('float', 3.14); 88 + test('float value preserved', Math.abs(f - 3.14) < 1e-10, true); 89 + 90 + const buf = v8.serialize(NaN); 91 + const nan = v8.deserialize(buf); 92 + test('NaN round-trips', Number.isNaN(nan), true); 93 + 94 + const s = roundtrip('string', 'hello world'); 95 + test('string value preserved', s, 'hello world'); 96 + 97 + const empty = roundtrip('empty string', ''); 98 + test('empty string preserved', empty, ''); 99 + 100 + const arr = v8.deserialize(v8.serialize([1, 2, 3])); 101 + test('array round-trips', Array.isArray(arr), true); 102 + test('array length preserved', arr.length, 3); 103 + test('array[0]', arr[0], 1); 104 + test('array[2]', arr[2], 3); 105 + 106 + const obj = v8.deserialize(v8.serialize({ x: 1, y: 'two', z: true })); 107 + test('object round-trips', typeof obj, 'object'); 108 + test('object.x', obj.x, 1); 109 + test('object.y', obj.y, 'two'); 110 + test('object.z', obj.z, true); 111 + 112 + const nested = v8.deserialize(v8.serialize({ a: [1, { b: 2 }], c: null })); 113 + test('nested object.a is array', Array.isArray(nested.a), true); 114 + test('nested object.a[1].b', nested.a[1].b, 2); 115 + test('nested object.c is null', nested.c, null); 116 + 117 + let threw = false; 118 + try { v8.deserialize(new Uint8Array([0x00, 0x00])); } catch (e) { threw = true; } 119 + test('deserialize rejects bad magic', threw, true); 120 + 121 + console.log('\nno-op methods\n'); 122 + 123 + test('setFlagsFromString is a function', typeof v8.setFlagsFromString, 'function'); 124 + test('setFlagsFromString returns undefined', v8.setFlagsFromString('--harmony'), undefined); 125 + test('stopCoverage is a function', typeof v8.stopCoverage, 'function'); 126 + test('stopCoverage returns undefined', v8.stopCoverage(), undefined); 127 + test('takeCoverage is a function', typeof v8.takeCoverage, 'function'); 128 + test('takeCoverage returns undefined', v8.takeCoverage(), undefined); 129 + 130 + console.log('\nconstants\n'); 131 + 132 + test('constants is an object', typeof v8.constants, 'object'); 133 + 134 + summary();
+8
include/modules/assert.h
··· 1 + #ifndef ANT_ASSERT_MODULE_H 2 + #define ANT_ASSERT_MODULE_H 3 + 4 + #include "types.h" 5 + 6 + ant_value_t assert_library(ant_t *js); 7 + 8 + #endif
+8
include/modules/v8.h
··· 1 + #ifndef ANT_V8_MODULE_H 2 + #define ANT_V8_MODULE_H 3 + 4 + #include "types.h" 5 + 6 + ant_value_t v8_library(ant_t *js); 7 + 8 + #endif
+4
src/main.c
··· 68 68 #include "modules/async_hooks.h" 69 69 #include "modules/net.h" 70 70 #include "modules/dns.h" 71 + #include "modules/assert.h" 72 + #include "modules/v8.h" 71 73 #include "modules/worker_threads.h" 72 74 73 75 int js_result = EXIT_SUCCESS; ··· 606 608 ant_standard_library("util", util_library); 607 609 ant_standard_library("net", net_library); 608 610 ant_standard_library("dns", dns_library); 611 + ant_standard_library("assert", assert_library); 609 612 ant_standard_library("module", module_library); 610 613 ant_standard_library("buffer", buffer_library); 611 614 ant_standard_library("path", path_library); ··· 623 626 ant_standard_library("child_process", child_process_library); 624 627 ant_standard_library("worker_threads", worker_threads_library); 625 628 ant_standard_library("async_hooks", async_hooks_library); 629 + ant_standard_library("v8", v8_library); 626 630 627 631 ant_value_t snapshot_result = ant_load_snapshot(js); 628 632 if (vtype(snapshot_result) == T_ERR) {
+304
src/modules/assert.c
··· 1 + #include <math.h> 2 + #include <string.h> 3 + 4 + #include "ant.h" 5 + #include "errors.h" 6 + #include "internal.h" 7 + #include "silver/engine.h" 8 + 9 + static ant_value_t assertion_error(ant_t *js, const char *msg, ant_value_t msg_val) { 10 + if (vtype(msg_val) == T_STR) { 11 + char *s = js_getstr(js, msg_val, NULL); 12 + if (s) return js_mkerr(js, "%s", s); 13 + } 14 + return js_mkerr(js, "%s", msg); 15 + } 16 + 17 + // assert(value, message) / assert.ok 18 + static ant_value_t assert_ok(ant_t *js, ant_value_t *args, int nargs) { 19 + if (nargs < 1 || !js_truthy(js, args[0])) 20 + return assertion_error(js, "The expression evaluated to a falsy value", nargs >= 2 ? args[1] : js_mkundef()); 21 + return js_mkundef(); 22 + } 23 + 24 + // assert.fail(message) 25 + static ant_value_t assert_fail(ant_t *js, ant_value_t *args, int nargs) { 26 + if (nargs >= 1 && vtype(args[0]) == T_STR) { 27 + char *msg = js_getstr(js, args[0], NULL); 28 + if (msg) return js_mkerr(js, "%s", msg); 29 + } 30 + return js_mkerr(js, "Assertion failed"); 31 + } 32 + 33 + // assert.ifError(value) 34 + static ant_value_t assert_if_error(ant_t *js, ant_value_t *args, int nargs) { 35 + if (nargs < 1) return js_mkundef(); 36 + uint8_t t = vtype(args[0]); 37 + if (t == T_NULL || t == T_UNDEF) return js_mkundef(); 38 + if (is_err(args[0])) return args[0]; 39 + char *msg = js_getstr(js, args[0], NULL); 40 + return js_mkerr(js, "ifError got unwanted exception: %s", msg ? msg : "(unknown)"); 41 + } 42 + 43 + // TODO: make into global helper 44 + static bool values_strict_equal(ant_t *js, ant_value_t a, ant_value_t b) { 45 + uint8_t ta = vtype(a), tb = vtype(b); 46 + if (ta != tb) return false; 47 + if (ta == T_NULL || ta == T_UNDEF) return true; 48 + if (ta == T_BOOL) return a == b; 49 + if (ta == T_NUM) { 50 + double na = js_getnum(a), nb = js_getnum(b); 51 + return (na == nb) || (isnan(na) && isnan(nb)); 52 + } 53 + if (ta == T_STR) { 54 + char *sa = js_getstr(js, a, NULL); 55 + char *sb = js_getstr(js, b, NULL); 56 + return sa && sb && strcmp(sa, sb) == 0; 57 + } 58 + return vdata(a) == vdata(b); 59 + } 60 + 61 + // TODO: make into global helper 62 + static bool values_loose_equal(ant_t *js, ant_value_t a, ant_value_t b) { 63 + uint8_t ta = vtype(a), tb = vtype(b); 64 + if (ta == tb) return values_strict_equal(js, a, b); 65 + if ((ta == T_NULL && tb == T_UNDEF) || (ta == T_UNDEF && tb == T_NULL)) return true; 66 + if (ta == T_NUM && tb == T_STR) { 67 + char *sb = js_getstr(js, b, NULL); 68 + return sb && js_getnum(a) == strtod(sb, NULL); 69 + } 70 + if (ta == T_STR && tb == T_NUM) { 71 + char *sa = js_getstr(js, a, NULL); 72 + return sa && strtod(sa, NULL) == js_getnum(b); 73 + } 74 + return false; 75 + } 76 + 77 + // TODO: make into global helper 78 + static bool deep_equal(ant_t *js, ant_value_t a, ant_value_t b, bool strict, int depth) { 79 + if (depth > 64) return false; 80 + uint8_t ta = vtype(a), tb = vtype(b); 81 + 82 + if (ta == T_ARR && tb == T_ARR) { 83 + ant_offset_t la = js_arr_len(js, a), lb = js_arr_len(js, b); 84 + if (la != lb) return false; 85 + for (ant_offset_t i = 0; i < la; i++) { 86 + if (!deep_equal(js, js_arr_get(js, a, i), js_arr_get(js, b, i), strict, depth + 1)) 87 + return false; 88 + } 89 + return true; 90 + } 91 + 92 + if (ta == T_OBJ && tb == T_OBJ) { 93 + if (vdata(a) == vdata(b)) return true; 94 + ant_iter_t iter = js_prop_iter_begin(js, a); 95 + const char *key; size_t key_len; ant_value_t va; 96 + while (js_prop_iter_next(&iter, &key, &key_len, &va)) { 97 + ant_value_t vb = js_get(js, b, key); 98 + if (!deep_equal(js, va, vb, strict, depth + 1)) { 99 + js_prop_iter_end(&iter); 100 + return false; 101 + } 102 + } 103 + js_prop_iter_end(&iter); 104 + ant_iter_t iter2 = js_prop_iter_begin(js, b); 105 + while (js_prop_iter_next(&iter2, &key, &key_len, &va)) { 106 + ant_value_t va2 = js_get(js, a, key); 107 + if (vtype(va2) == T_UNDEF && vtype(va) != T_UNDEF) { 108 + js_prop_iter_end(&iter2); 109 + return false; 110 + } 111 + } 112 + js_prop_iter_end(&iter2); 113 + return true; 114 + } 115 + 116 + return strict ? values_strict_equal(js, a, b) : values_loose_equal(js, a, b); 117 + } 118 + 119 + static ant_value_t assert_equal(ant_t *js, ant_value_t *args, int nargs) { 120 + if (nargs < 2) return js_mkundef(); 121 + if (!values_loose_equal(js, args[0], args[1])) 122 + return assertion_error(js, "Expected values to be equal", nargs >= 3 ? args[2] : js_mkundef()); 123 + return js_mkundef(); 124 + } 125 + 126 + static ant_value_t assert_not_equal(ant_t *js, ant_value_t *args, int nargs) { 127 + if (nargs < 2) return js_mkundef(); 128 + if (values_loose_equal(js, args[0], args[1])) 129 + return assertion_error(js, "Expected values to not be equal", nargs >= 3 ? args[2] : js_mkundef()); 130 + return js_mkundef(); 131 + } 132 + 133 + static ant_value_t assert_strict_equal(ant_t *js, ant_value_t *args, int nargs) { 134 + if (nargs < 2) return js_mkundef(); 135 + if (!values_strict_equal(js, args[0], args[1])) 136 + return assertion_error(js, "Expected values to be strictly equal", nargs >= 3 ? args[2] : js_mkundef()); 137 + return js_mkundef(); 138 + } 139 + 140 + static ant_value_t assert_not_strict_equal(ant_t *js, ant_value_t *args, int nargs) { 141 + if (nargs < 2) return js_mkundef(); 142 + if (values_strict_equal(js, args[0], args[1])) 143 + return assertion_error(js, "Expected values to not be strictly equal", nargs >= 3 ? args[2] : js_mkundef()); 144 + return js_mkundef(); 145 + } 146 + 147 + static ant_value_t assert_deep_equal(ant_t *js, ant_value_t *args, int nargs) { 148 + if (nargs < 2) return js_mkundef(); 149 + if (!deep_equal(js, args[0], args[1], false, 0)) 150 + return assertion_error(js, "Expected values to be deeply equal", nargs >= 3 ? args[2] : js_mkundef()); 151 + return js_mkundef(); 152 + } 153 + 154 + static ant_value_t assert_not_deep_equal(ant_t *js, ant_value_t *args, int nargs) { 155 + if (nargs < 2) return js_mkundef(); 156 + if (deep_equal(js, args[0], args[1], false, 0)) 157 + return assertion_error(js, "Expected values to not be deeply equal", nargs >= 3 ? args[2] : js_mkundef()); 158 + return js_mkundef(); 159 + } 160 + 161 + static ant_value_t assert_deep_strict_equal(ant_t *js, ant_value_t *args, int nargs) { 162 + if (nargs < 2) return js_mkundef(); 163 + if (!deep_equal(js, args[0], args[1], true, 0)) 164 + return assertion_error(js, "Expected values to be deeply strictly equal", nargs >= 3 ? args[2] : js_mkundef()); 165 + return js_mkundef(); 166 + } 167 + 168 + static ant_value_t assert_not_deep_strict_equal(ant_t *js, ant_value_t *args, int nargs) { 169 + if (nargs < 2) return js_mkundef(); 170 + if (deep_equal(js, args[0], args[1], true, 0)) 171 + return assertion_error(js, "Expected values to not be deeply strictly equal", nargs >= 3 ? args[2] : js_mkundef()); 172 + return js_mkundef(); 173 + } 174 + 175 + static ant_value_t assert_throws(ant_t *js, ant_value_t *args, int nargs) { 176 + if (nargs < 1 || vtype(args[0]) != T_FUNC) 177 + return js_mkerr(js, "assert.throws: first argument must be a function"); 178 + ant_value_t result = sv_vm_call(js->vm, js, args[0], js_mkundef(), NULL, 0, NULL, false); 179 + if (!is_err(result)) 180 + return js_mkerr(js, "Missing expected exception"); 181 + return js_mkundef(); 182 + } 183 + 184 + static ant_value_t assert_does_not_throw(ant_t *js, ant_value_t *args, int nargs) { 185 + if (nargs < 1 || vtype(args[0]) != T_FUNC) 186 + return js_mkerr(js, "assert.doesNotThrow: first argument must be a function"); 187 + ant_value_t result = sv_vm_call(js->vm, js, args[0], js_mkundef(), NULL, 0, NULL, false); 188 + if (is_err(result)) 189 + return js_mkerr(js, "Got unwanted exception: %s", js_str(js, result)); 190 + return js_mkundef(); 191 + } 192 + 193 + static bool promise_was_rejected(ant_value_t result) { 194 + if (vtype(result) != T_PROMISE) return false; 195 + ant_object_t *obj = js_obj_ptr(js_as_obj(result)); 196 + return obj && obj->promise_state && obj->promise_state->state == 2; 197 + } 198 + 199 + static bool promise_was_fulfilled(ant_value_t result) { 200 + if (vtype(result) != T_PROMISE) return false; 201 + ant_object_t *obj = js_obj_ptr(js_as_obj(result)); 202 + return obj && obj->promise_state && obj->promise_state->state == 1; 203 + } 204 + 205 + static ant_value_t assert_rejects(ant_t *js, ant_value_t *args, int nargs) { 206 + if (nargs < 1) return js_mkerr(js, "assert.rejects: first argument required"); 207 + ant_value_t promise = js_mkpromise(js); 208 + ant_value_t result = vtype(args[0]) == T_FUNC 209 + ? sv_vm_call(js->vm, js, args[0], js_mkundef(), NULL, 0, NULL, false) 210 + : args[0]; 211 + if (is_err(result) || promise_was_rejected(result)) 212 + js_resolve_promise(js, promise, js_mkundef()); 213 + else 214 + js_reject_promise(js, promise, js_mkerr(js, "Missing expected rejection")); 215 + return promise; 216 + } 217 + 218 + static ant_value_t assert_does_not_reject(ant_t *js, ant_value_t *args, int nargs) { 219 + if (nargs < 1) return js_mkerr(js, "assert.doesNotReject: first argument required"); 220 + ant_value_t promise = js_mkpromise(js); 221 + ant_value_t result = vtype(args[0]) == T_FUNC 222 + ? sv_vm_call(js->vm, js, args[0], js_mkundef(), NULL, 0, NULL, false) 223 + : args[0]; 224 + if (is_err(result) || promise_was_rejected(result)) 225 + js_reject_promise(js, promise, js_mkerr(js, "Got unwanted rejection")); 226 + else 227 + js_resolve_promise(js, promise, js_mkundef()); 228 + return promise; 229 + } 230 + 231 + static ant_value_t assert_match(ant_t *js, ant_value_t *args, int nargs) { 232 + if (nargs < 2) return js_mkundef(); 233 + ant_value_t test_fn = js_getprop_fallback(js, args[1], "test"); 234 + if (vtype(test_fn) != T_FUNC) return js_mkerr(js, "assert.match: second argument must be a RegExp"); 235 + ant_value_t test_args[1] = {args[0]}; 236 + ant_value_t result = sv_vm_call(js->vm, js, test_fn, args[1], test_args, 1, NULL, false); 237 + if (!js_truthy(js, result)) 238 + return assertion_error(js, "Value does not match the regular expression", nargs >= 3 ? args[2] : js_mkundef()); 239 + return js_mkundef(); 240 + } 241 + 242 + static ant_value_t assert_does_not_match(ant_t *js, ant_value_t *args, int nargs) { 243 + if (nargs < 2) return js_mkundef(); 244 + ant_value_t test_fn = js_getprop_fallback(js, args[1], "test"); 245 + if (vtype(test_fn) != T_FUNC) return js_mkerr(js, "assert.doesNotMatch: second argument must be a RegExp"); 246 + ant_value_t test_args[1] = {args[0]}; 247 + ant_value_t result = sv_vm_call(js->vm, js, test_fn, args[1], test_args, 1, NULL, false); 248 + if (js_truthy(js, result)) 249 + return assertion_error(js, "Value matches the regular expression", nargs >= 3 ? args[2] : js_mkundef()); 250 + return js_mkundef(); 251 + } 252 + 253 + static ant_value_t assert_assertion_error_ctor(ant_t *js, ant_value_t *args, int nargs) { 254 + ant_value_t self = js_getthis(js); 255 + js_set(js, self, "name", js_mkstr(js, "AssertionError", 14)); 256 + if (nargs >= 1 && vtype(args[0]) == T_OBJ) { 257 + const char *fields[] = {"message", "actual", "expected", "operator"}; 258 + for (int i = 0; i < 4; i++) { 259 + ant_value_t v = js_get(js, args[0], fields[i]); 260 + if (vtype(v) != T_UNDEF) js_set(js, self, fields[i], v); 261 + } 262 + } 263 + return js_mkundef(); 264 + } 265 + 266 + ant_value_t assert_library(ant_t *js) { 267 + ant_value_t assert_obj = js_mkobj(js); 268 + js_set_slot(assert_obj, SLOT_CFUNC, js_mkfun(assert_ok)); 269 + 270 + js_set(js, assert_obj, "ok", js_mkfun(assert_ok)); 271 + js_set(js, assert_obj, "fail", js_mkfun(assert_fail)); 272 + js_set(js, assert_obj, "ifError", js_mkfun(assert_if_error)); 273 + js_set(js, assert_obj, "equal", js_mkfun(assert_equal)); 274 + js_set(js, assert_obj, "notEqual", js_mkfun(assert_not_equal)); 275 + js_set(js, assert_obj, "strictEqual", js_mkfun(assert_strict_equal)); 276 + js_set(js, assert_obj, "notStrictEqual", js_mkfun(assert_not_strict_equal)); 277 + js_set(js, assert_obj, "deepEqual", js_mkfun(assert_deep_equal)); 278 + js_set(js, assert_obj, "notDeepEqual", js_mkfun(assert_not_deep_equal)); 279 + js_set(js, assert_obj, "deepStrictEqual", js_mkfun(assert_deep_strict_equal)); 280 + js_set(js, assert_obj, "notDeepStrictEqual", js_mkfun(assert_not_deep_strict_equal)); 281 + js_set(js, assert_obj, "throws", js_mkfun(assert_throws)); 282 + js_set(js, assert_obj, "doesNotThrow", js_mkfun(assert_does_not_throw)); 283 + js_set(js, assert_obj, "rejects", js_mkfun(assert_rejects)); 284 + js_set(js, assert_obj, "doesNotReject", js_mkfun(assert_does_not_reject)); 285 + js_set(js, assert_obj, "match", js_mkfun(assert_match)); 286 + js_set(js, assert_obj, "doesNotMatch", js_mkfun(assert_does_not_match)); 287 + 288 + ant_value_t ae_ctor = js_mkobj(js); 289 + ant_value_t ae_proto = js_mkobj(js); 290 + 291 + js_set(js, ae_proto, "name", js_mkstr(js, "AssertionError", 14)); 292 + js_set_slot(ae_ctor, SLOT_CFUNC, js_mkfun(assert_assertion_error_ctor)); 293 + js_mkprop_fast(js, ae_ctor, "prototype", 9, ae_proto); 294 + js_mkprop_fast(js, ae_ctor, "name", 4, js_mkstr(js, "AssertionError", 14)); 295 + 296 + ant_value_t ae_fn = js_obj_to_func(ae_ctor); 297 + js_set(js, ae_proto, "constructor", ae_fn); 298 + js_set(js, assert_obj, "AssertionError", ae_fn); 299 + 300 + ant_value_t lib = js_obj_to_func(assert_obj); 301 + js_set(js, lib, "default", lib); 302 + 303 + return lib; 304 + }
+378
src/modules/v8.c
··· 1 + // stub: functional where possible 2 + 3 + #include <math.h> 4 + #include <stdint.h> 5 + #include <stdlib.h> 6 + #include <string.h> 7 + #include <uv.h> 8 + 9 + #include "arena.h" 10 + #include "errors.h" 11 + #include "internal.h" 12 + #include "modules/buffer.h" 13 + 14 + // serialize / deserialize 15 + // 16 + // wire format: 17 + // [0xAB 0xCD] โ€” magic header (2 bytes) 18 + // <value> โ€” recursively encoded 19 + // 20 + // value tags (1 byte): 21 + // 'U' undefined 22 + // 'N' null 23 + // 'T' true 24 + // 'F' false 25 + // 'Z' NaN 26 + // 'D' double (8 bytes little-endian) 27 + // 'S' string (uint32 length LE + UTF-8 bytes) 28 + // 'A' array (uint32 count LE + <value>โ€ฆ) 29 + // 'O' object (uint32 count LE + (uint32 klen + key bytes + <value>)โ€ฆ) 30 + 31 + #define SER_MAGIC_0 0xAB 32 + #define SER_MAGIC_1 0xCD 33 + 34 + typedef struct { 35 + uint8_t *data; 36 + size_t len; 37 + size_t cap; 38 + } enc_t; 39 + 40 + static bool enc_grow(enc_t *e, size_t need) { 41 + if (e->len + need <= e->cap) return true; 42 + size_t nc = e->cap ? e->cap * 2 : 64; 43 + while (nc < e->len + need) nc *= 2; 44 + uint8_t *p = realloc(e->data, nc); 45 + if (!p) return false; 46 + e->data = p; 47 + e->cap = nc; 48 + return true; 49 + } 50 + 51 + static bool enc_u8(enc_t *e, uint8_t b) { 52 + if (!enc_grow(e, 1)) return false; 53 + e->data[e->len++] = b; 54 + return true; 55 + } 56 + 57 + static bool enc_u32(enc_t *e, uint32_t v) { 58 + if (!enc_grow(e, 4)) return false; 59 + e->data[e->len++] = (uint8_t)(v); 60 + e->data[e->len++] = (uint8_t)(v >> 8); 61 + e->data[e->len++] = (uint8_t)(v >> 16); 62 + e->data[e->len++] = (uint8_t)(v >> 24); 63 + return true; 64 + } 65 + 66 + static bool enc_bytes(enc_t *e, const void *src, size_t n) { 67 + if (!enc_grow(e, n)) return false; 68 + memcpy(e->data + e->len, src, n); 69 + e->len += n; 70 + return true; 71 + } 72 + 73 + static bool ser_val(ant_t *js, enc_t *e, ant_value_t val, int depth) { 74 + if (depth > 64) return false; 75 + uint8_t t = vtype(val); 76 + 77 + if (t == T_UNDEF) return enc_u8(e, 'U'); 78 + if (t == T_NULL) return enc_u8(e, 'N'); 79 + if (t == T_BOOL) return enc_u8(e, (val == js_true) ? 'T' : 'F'); 80 + 81 + if (t == T_NUM) { 82 + double d = js_getnum(val); 83 + if (isnan(d)) return enc_u8(e, 'Z'); 84 + if (!enc_u8(e, 'D')) return false; 85 + return enc_bytes(e, &d, 8); 86 + } 87 + 88 + if (t == T_STR) { 89 + size_t slen; 90 + const char *s = js_getstr(js, val, &slen); 91 + if (!s) { s = ""; slen = 0; } 92 + if (!enc_u8(e, 'S')) return false; 93 + if (!enc_u32(e, (uint32_t)slen)) return false; 94 + return enc_bytes(e, s, slen); 95 + } 96 + 97 + if (t == T_ARR) { 98 + ant_offset_t n = js_arr_len(js, val); 99 + if (!enc_u8(e, 'A')) return false; 100 + if (!enc_u32(e, (uint32_t)n)) return false; 101 + for (ant_offset_t i = 0; i < n; i++) { 102 + if (!ser_val(js, e, js_arr_get(js, val, i), depth + 1)) return false; 103 + } 104 + return true; 105 + } 106 + 107 + if (t == T_OBJ) { 108 + uint32_t count = 0; 109 + ant_iter_t it = js_prop_iter_begin(js, val); 110 + const char *k; size_t klen; ant_value_t v; 111 + while (js_prop_iter_next(&it, &k, &klen, &v)) count++; 112 + js_prop_iter_end(&it); 113 + 114 + if (!enc_u8(e, 'O')) return false; 115 + if (!enc_u32(e, count)) return false; 116 + 117 + it = js_prop_iter_begin(js, val); 118 + while (js_prop_iter_next(&it, &k, &klen, &v)) { 119 + if (!enc_u32(e, (uint32_t)klen) || !enc_bytes(e, k, klen)) { 120 + js_prop_iter_end(&it); 121 + return false; 122 + } 123 + if (!ser_val(js, e, v, depth + 1)) { 124 + js_prop_iter_end(&it); 125 + return false; 126 + } 127 + } 128 + js_prop_iter_end(&it); 129 + return true; 130 + } 131 + 132 + return enc_u8(e, 'U'); 133 + } 134 + 135 + static ant_value_t v8_serialize(ant_t *js, ant_value_t *args, int nargs) { 136 + if (nargs < 1) return js_mkerr(js, "serialize: value required"); 137 + 138 + enc_t e = {0}; 139 + if (!enc_u8(&e, SER_MAGIC_0) || !enc_u8(&e, SER_MAGIC_1)) goto oom; 140 + if (!ser_val(js, &e, args[0], 0)) goto oom; 141 + 142 + ArrayBufferData *ab = create_array_buffer_data(e.len); 143 + if (!ab) goto oom; 144 + memcpy(ab->data, e.data, e.len); 145 + free(e.data); 146 + return create_typed_array(js, TYPED_ARRAY_UINT8, ab, 0, e.len, "Buffer"); 147 + 148 + oom: 149 + free(e.data); 150 + return js_mkerr(js, "serialize: out of memory"); 151 + } 152 + 153 + typedef struct { 154 + const uint8_t *data; 155 + size_t len; 156 + size_t pos; 157 + } dec_t; 158 + 159 + static bool dec_u8(dec_t *d, uint8_t *out) { 160 + if (d->pos >= d->len) return false; 161 + *out = d->data[d->pos++]; 162 + return true; 163 + } 164 + 165 + static bool dec_u32(dec_t *d, uint32_t *out) { 166 + if (d->pos + 4 > d->len) return false; 167 + *out = (uint32_t)d->data[d->pos] 168 + | ((uint32_t)d->data[d->pos+1] << 8) 169 + | ((uint32_t)d->data[d->pos+2] << 16) 170 + | ((uint32_t)d->data[d->pos+3] << 24); 171 + d->pos += 4; 172 + return true; 173 + } 174 + 175 + static ant_value_t des_val(ant_t *js, dec_t *d, int depth) { 176 + if (depth > 64) return js_mkerr(js, "deserialize: maximum depth exceeded"); 177 + 178 + uint8_t tag; 179 + if (!dec_u8(d, &tag)) return js_mkundef(); 180 + 181 + switch (tag) { 182 + case 'U': return js_mkundef(); 183 + case 'N': return js_mknull(); 184 + case 'T': return js_true; 185 + case 'F': return js_false; 186 + case 'Z': return js_mknum((double)NAN); 187 + case 'D': { 188 + if (d->pos + 8 > d->len) return js_mkundef(); 189 + double v; 190 + memcpy(&v, d->data + d->pos, 8); 191 + d->pos += 8; 192 + return js_mknum(v); 193 + } 194 + case 'S': { 195 + uint32_t n; 196 + if (!dec_u32(d, &n) || d->pos + n > d->len) return js_mkundef(); 197 + ant_value_t s = js_mkstr(js, (const char *)(d->data + d->pos), n); 198 + d->pos += n; 199 + return s; 200 + } 201 + case 'A': { 202 + uint32_t n; 203 + if (!dec_u32(d, &n)) return js_mkundef(); 204 + ant_value_t arr = js_mkarr(js); 205 + for (uint32_t i = 0; i < n; i++) { 206 + ant_value_t elem = des_val(js, d, depth + 1); 207 + if (is_err(elem)) return elem; 208 + js_arr_push(js, arr, elem); 209 + } 210 + return arr; 211 + } 212 + case 'O': { 213 + uint32_t n; 214 + if (!dec_u32(d, &n)) return js_mkundef(); 215 + ant_value_t obj = js_mkobj(js); 216 + char kbuf[4096]; 217 + for (uint32_t i = 0; i < n; i++) { 218 + uint32_t klen; 219 + if (!dec_u32(d, &klen) || klen >= sizeof(kbuf) || d->pos + klen > d->len) 220 + break; 221 + memcpy(kbuf, d->data + d->pos, klen); 222 + kbuf[klen] = '\0'; 223 + d->pos += klen; 224 + ant_value_t v = des_val(js, d, depth + 1); 225 + if (is_err(v)) return v; 226 + js_set(js, obj, kbuf, v); 227 + } 228 + return obj; 229 + } 230 + default: 231 + return js_mkundef(); 232 + } 233 + } 234 + 235 + static ant_value_t v8_deserialize(ant_t *js, ant_value_t *args, int nargs) { 236 + if (nargs < 1) return js_mkerr(js, "deserialize: Buffer required"); 237 + 238 + ant_value_t buf_slot = js_get_slot(args[0], SLOT_BUFFER); 239 + TypedArrayData *ta = (TypedArrayData *)js_gettypedarray(buf_slot); 240 + if (!ta || !ta->buffer) return js_mkerr(js, "deserialize: expected a Buffer"); 241 + 242 + const uint8_t *data = ta->buffer->data + ta->byte_offset; 243 + size_t len = ta->byte_length; 244 + 245 + if (len < 2 || data[0] != SER_MAGIC_0 || data[1] != SER_MAGIC_1) 246 + return js_mkerr(js, "deserialize: invalid or incompatible buffer"); 247 + 248 + dec_t d = { .data = data, .len = len, .pos = 2 }; 249 + return des_val(js, &d, 0); 250 + } 251 + 252 + static ant_value_t v8_get_heap_statistics(ant_t *js, ant_value_t *args, int nargs) { 253 + size_t rss = 0; 254 + uv_resident_set_memory(&rss); 255 + 256 + size_t arena_committed = js->obj_arena.committed; 257 + size_t arena_reserved = js->obj_arena.reserved; 258 + size_t arena_live_bytes = js->obj_arena.live_count * js->obj_arena.elem_size; 259 + 260 + size_t pool_live = js->gc_pool_last_live; 261 + size_t pool_alloc = js->gc_pool_alloc; 262 + 263 + size_t closure_live = js->closure_arena.live_count * js->closure_arena.elem_size; 264 + size_t extra_alloc = js->alloc_bytes.closures + js->alloc_bytes.upvalues; 265 + 266 + size_t used_heap = arena_live_bytes + pool_live + closure_live; 267 + size_t total_heap = arena_committed + pool_alloc + extra_alloc; 268 + size_t heap_limit = arena_reserved; 269 + 270 + ant_value_t obj = js_mkobj(js); 271 + js_set(js, obj, "total_heap_size", js_mknum((double)total_heap)); 272 + js_set(js, obj, "total_heap_size_executable", js_mknum(0)); 273 + js_set(js, obj, "total_physical_size", js_mknum((double)rss)); 274 + js_set(js, obj, "total_available_size", js_mknum((double)(heap_limit > used_heap ? heap_limit - used_heap : 0))); 275 + js_set(js, obj, "total_global_handles_size", js_mknum(0)); 276 + js_set(js, obj, "used_global_handles_size", js_mknum(0)); 277 + js_set(js, obj, "used_heap_size", js_mknum((double)used_heap)); 278 + js_set(js, obj, "heap_size_limit", js_mknum((double)heap_limit)); 279 + js_set(js, obj, "malloced_memory", js_mknum((double)extra_alloc)); 280 + js_set(js, obj, "peak_malloced_memory", js_mknum((double)extra_alloc)); 281 + js_set(js, obj, "does_zap_garbage", js_mknum(0)); 282 + js_set(js, obj, "number_of_native_contexts", js_mknum(1)); 283 + js_set(js, obj, "number_of_detached_contexts", js_mknum(0)); 284 + js_set(js, obj, "total_heap_blinded_size", js_mknum(0)); 285 + 286 + return obj; 287 + } 288 + 289 + static ant_value_t v8_get_heap_space_statistics(ant_t *js, ant_value_t *args, int nargs) { 290 + ant_value_t nursery = js_mkobj(js); 291 + size_t arena_committed = js->obj_arena.committed; 292 + size_t arena_live_bytes = js->obj_arena.live_count * js->obj_arena.elem_size; 293 + double arena_available = (double)(arena_committed / 2 > arena_live_bytes / 2 ? arena_committed / 2 - arena_live_bytes / 2 : 0); 294 + 295 + js_set(js, nursery, "space_name", js_mkstr(js, "new_space", 9)); 296 + js_set(js, nursery, "space_size", js_mknum((double)arena_committed / 2)); 297 + js_set(js, nursery, "space_used_size", js_mknum((double)arena_live_bytes / 2)); 298 + js_set(js, nursery, "space_available_size", js_mknum(arena_available)); 299 + js_set(js, nursery, "physical_space_size", js_mknum((double)arena_committed / 2)); 300 + 301 + ant_value_t oldspace = js_mkobj(js); 302 + size_t old_live = js->old_live_count * js->obj_arena.elem_size; 303 + double old_size = (double)(arena_committed / 2 > old_live ? arena_committed / 2 - old_live : 0); 304 + 305 + js_set(js, oldspace, "space_name", js_mkstr(js, "old_space", 9)); 306 + js_set(js, oldspace, "space_size", js_mknum((double)arena_committed / 2)); 307 + js_set(js, oldspace, "space_used_size", js_mknum((double)old_live)); 308 + js_set(js, oldspace, "space_available_size", js_mknum(old_size)); 309 + js_set(js, oldspace, "physical_space_size", js_mknum((double)arena_committed / 2)); 310 + 311 + ant_value_t arr = js_mkarr(js); 312 + js_arr_push(js, arr, nursery); 313 + js_arr_push(js, arr, oldspace); 314 + 315 + return arr; 316 + } 317 + 318 + static ant_value_t v8_noop(ant_t *js, ant_value_t *args, int nargs) { 319 + return js_mkundef(); 320 + } 321 + 322 + static ant_value_t v8_noop_false(ant_t *js, ant_value_t *args, int nargs) { 323 + return js_false; 324 + } 325 + 326 + static ant_value_t v8_write_heap_snapshot(ant_t *js, ant_value_t *args, int nargs) { 327 + return js_mkstr(js, "", 0); 328 + } 329 + 330 + static ant_value_t v8_get_heap_snapshot(ant_t *js, ant_value_t *args, int nargs) { 331 + return js_mkundef(); 332 + } 333 + 334 + static ant_value_t v8_get_heap_code_statistics(ant_t *js, ant_value_t *args, int nargs) { 335 + size_t closure_structs = js->closure_arena.live_count * js->closure_arena.elem_size; 336 + size_t bytecode_alloc = js->alloc_bytes.closures; 337 + 338 + ant_pool_stats_t rope_stats = js_pool_stats(&js->pool.rope); 339 + ant_value_t obj = js_mkobj(js); 340 + 341 + js_set(js, obj, "code_and_metadata_size", js_mknum((double)(closure_structs + bytecode_alloc))); 342 + js_set(js, obj, "bytecode_and_metadata_size", js_mknum((double)bytecode_alloc)); 343 + js_set(js, obj, "external_script_source_size", js_mknum((double)rope_stats.used)); 344 + js_set(js, obj, "cpu_profiler_metadata_size", js_mknum(0)); 345 + 346 + return obj; 347 + } 348 + 349 + static ant_value_t v8_cached_data_version_tag(ant_t *js, ant_value_t *args, int nargs) { 350 + return js_mknum(0xA0A0A0); 351 + } 352 + 353 + ant_value_t v8_library(ant_t *js) { 354 + ant_value_t lib = js_mkobj(js); 355 + 356 + js_set(js, lib, "serialize", js_mkfun(v8_serialize)); 357 + js_set(js, lib, "deserialize", js_mkfun(v8_deserialize)); 358 + js_set(js, lib, "writeHeapSnapshot", js_mkfun(v8_write_heap_snapshot)); 359 + js_set(js, lib, "getHeapSnapshot", js_mkfun(v8_get_heap_snapshot)); 360 + js_set(js, lib, "getHeapStatistics", js_mkfun(v8_get_heap_statistics)); 361 + js_set(js, lib, "getHeapSpaceStatistics", js_mkfun(v8_get_heap_space_statistics)); 362 + js_set(js, lib, "getHeapCodeStatistics", js_mkfun(v8_get_heap_code_statistics)); 363 + js_set(js, lib, "cachedDataVersionTag", js_mkfun(v8_cached_data_version_tag)); 364 + js_set(js, lib, "setFlagsFromString", js_mkfun(v8_noop)); 365 + js_set(js, lib, "stopCoverage", js_mkfun(v8_noop)); 366 + js_set(js, lib, "takeCoverage", js_mkfun(v8_noop)); 367 + js_set(js, lib, "promiseEvents", js_mkfun(v8_noop)); 368 + 369 + ant_value_t snapshot = js_mkobj(js); 370 + js_set(js, snapshot, "isBuildingSnapshot", js_mkfun(v8_noop_false)); 371 + js_set(js, snapshot, "addSerializeCallback", js_mkfun(v8_noop)); 372 + js_set(js, snapshot, "addDeserializeCallback", js_mkfun(v8_noop)); 373 + 374 + js_set(js, lib, "startupSnapshot", snapshot); 375 + js_set(js, lib, "constants", js_mkobj(js)); 376 + 377 + return lib; 378 + }