Exception: MiniRacerCsim::EvalError

Inherits:
Error
  • Object
show all
Defined in:
lib/mini_racer_csim.rb,
ext/mini_racer_csim_extension/mini_racer_csim_extension.c

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args) ⇒ Object



2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
# File 'ext/mini_racer_csim_extension/mini_racer_csim_extension.c', line 2253

static VALUE context_initialize(int argc, VALUE *argv, VALUE self)
{
    VALUE kwargs, a, k, v;
    pthread_attr_t attr;
    const char *cause;
    pthread_t thr;
    Snapshot *ss;
    Context *c;
    char *s;
    int r;

    TypedData_Get_Struct(self, Context, &context_type, c);
    rb_scan_args(argc, argv, ":", &kwargs);
    if (NIL_P(kwargs))
        goto init;
    a = rb_ary_new();
    rb_hash_foreach(kwargs, collect, a);
    while (RARRAY_LENINT(a)) {
        v = rb_ary_pop(a);
        k = rb_ary_pop(a);
        k = rb_sym2str(k);
        s = RSTRING_PTR(k);
        if (!strcmp(s, "ensure_gc_after_idle")) {
            Check_Type(v, T_FIXNUM);
            c->idle_gc = FIX2LONG(v);
            if (c->idle_gc < 0 || c->idle_gc > INT32_MAX)
                rb_raise(rb_eArgError, "bad ensure_gc_after_idle");
        } else if (!strcmp(s, "max_memory")) {
            Check_Type(v, T_FIXNUM);
            c->max_memory = FIX2LONG(v);
            if (c->max_memory < 0 || c->max_memory >= UINT32_MAX)
                rb_raise(rb_eArgError, "bad max_memory");
        } else if (!strcmp(s, "marshal_stack_depth")) { // backcompat, ignored
            Check_Type(v, T_FIXNUM);
        } else if (!strcmp(s, "timeout")) {
            Check_Type(v, T_FIXNUM);
            c->timeout = FIX2LONG(v);
            if (c->timeout < 0 || c->timeout > INT32_MAX)
                rb_raise(rb_eArgError, "bad timeout");
        } else if (!strcmp(s, "snapshot")) {
            if (NIL_P(v))
                continue;
            TypedData_Get_Struct(v, Snapshot, &snapshot_type, ss);
            if (buf_put(&c->snapshot, RSTRING_PTR(ss->blob), RSTRING_LENINT(ss->blob)))
                rb_raise(runtime_error, "out of memory");
        } else if (!strcmp(s, "verbose_exceptions")) {
            c->verbose_exceptions = !(v == Qfalse || v == Qnil);
        } else if (!strcmp(s, "host_namespace")) {
            const char *ns = NULL;
            if (v == Qtrue) {
                ns = "MiniRacer"; // default brand, like Deno's `Deno`
            } else if (v != Qnil && v != Qfalse) {
                Check_Type(v, T_STRING);
                ns = StringValueCStr(v); // raises on embedded NUL
            }
            if (ns && *ns) {
                // The name becomes a global, so require a valid (ASCII) JS
                // identifier; otherwise it would only be reachable through
                // globalThis["..."] rather than as `<name>.method()`.
                for (const char *q = ns; *q; q++) {
                    int ch = (unsigned char)*q;
                    int ident_start = ch == '_' || ch == '$' ||
                        (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');
                    int ident_char = ident_start || (ch >= '0' && ch <= '9');
                    if (!(q == ns ? ident_start : ident_char))
                        rb_raise(rb_eArgError,
                                 "host_namespace must be a valid identifier: %s", ns);
                }
                // store the name plus its NUL terminator
                buf_reset(&c->host_namespace);
                if (buf_put(&c->host_namespace, ns, strlen(ns) + 1))
                    rb_raise(runtime_error, "out of memory");
            }
        } else {
            rb_raise(runtime_error, "bad keyword: %s", s);
        }
    }
init:
    if (single_threaded) {
        v8_once_init();
        c->pst = v8_thread_init(c, c->snapshot.buf, c->snapshot.len, c->max_memory, c->verbose_exceptions,
                                c->host_namespace.len ? (const char *)c->host_namespace.buf : NULL);
    } else {
        cause = "pthread_attr_init";
        if ((r = pthread_attr_init(&attr)))
            goto fail;
        pthread_attr_setstacksize(&attr, 2<<20); // 2 MiB
        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
        // v8 thread takes ownership of |c|
        cause = "pthread_create";
        r = pthread_create(&thr, &attr, v8_thread_start, c);
        pthread_attr_destroy(&attr);
        if (r)
            goto fail;
        rb_thread_call_without_gvl(context_boot_wait, c, NULL, NULL);
    }
    // Deferred to first Context.new so Platform.set_flags! still has effect
    // on the tag (which depends on V8 flags applied during v8_global_init).
    {
        static int version_tag_defined;
        if (!version_tag_defined) {
            VALUE m = rb_const_get(rb_cObject, rb_intern("MiniRacerCsim"));
            rb_define_const(m, "V8_CACHED_DATA_VERSION_TAG",
                            UINT2NUM(v8_cached_data_version_tag()));
            version_tag_defined = 1;
        }
    }
    return Qnil;
fail:
    rb_raise(runtime_error, "Context.initialize: %s: %s", cause, strerror(r));
    return Qnil; // pacify compiler
}

Class Method Details

.load(blob) ⇒ Object



2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
# File 'ext/mini_racer_csim_extension/mini_racer_csim_extension.c', line 2466

static VALUE snapshot_load(VALUE klass, VALUE blob)
{
    Snapshot *ss;
    VALUE self;

    Check_Type(blob, T_STRING);
    self = snapshot_alloc(klass);
    TypedData_Get_Struct(self, Snapshot, &snapshot_type, ss);
    ss->blob = rb_str_dup(blob);
    rb_enc_associate(ss->blob, rb_ascii8bit_encoding());
    ENC_CODERANGE_SET(ss->blob, ENC_CODERANGE_VALID);
    return self;
}

Instance Method Details

#attach(name, proc) ⇒ Object



1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
# File 'ext/mini_racer_csim_extension/mini_racer_csim_extension.c', line 1737

static VALUE context_attach(VALUE self, VALUE name, VALUE proc)
{
    Context *c;
    VALUE e;
    Ser s;

    TypedData_Get_Struct(self, Context, &context_type, c);
    // request is (A)ttach, [name, id] array
    ser_init1(&s, 'A');
    ser_array_begin(&s, 2);
    add_string(&s, name);
    ser_int(&s, RARRAY_LENINT(c->procs));
    ser_array_end(&s, 2);
    rb_ary_push(c->procs, proc);
    // response is an exception or undefined
    e = rendezvous(c, &s.b);
    handle_exception(e);
    return Qnil;
}

#cache_rejected?Boolean

Returns:

  • (Boolean)


2622
2623
2624
2625
2626
2627
# File 'ext/mini_racer_csim_extension/mini_racer_csim_extension.c', line 2622

static VALUE script_cache_rejected_p(VALUE self)
{
    Script *script;
    TypedData_Get_Struct(self, Script, &script_type, script);
    return script->cache_rejected ? Qtrue : Qfalse;
}

#cached_dataObject



2615
2616
2617
2618
2619
2620
# File 'ext/mini_racer_csim_extension/mini_racer_csim_extension.c', line 2615

static VALUE script_cached_data(VALUE self)
{
    Script *script;
    TypedData_Get_Struct(self, Script, &script_type, script);
    return script->cached_data;
}

#call(*args) ⇒ Object



1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
# File 'ext/mini_racer_csim_extension/mini_racer_csim_extension.c', line 1808

static VALUE context_call(int argc, VALUE *argv, VALUE self)
{
    VALUE name, args;
    VALUE a, e;
    Context *c;
    Ser s;

    TypedData_Get_Struct(self, Context, &context_type, c);
    rb_scan_args(argc, argv, "1*", &name, &args);
    Check_Type(name, T_STRING);
    rb_ary_unshift(args, name);
    // request is (C)all, [name, args...] array
    ser_init1(&s, 'C');
    if (serialize(&s, args)) {
        ser_reset(&s);
        rb_raise(runtime_error, "Context.call: %s", s.err);
    }
    // response is [result, err] array
    a = rendezvous(c, &s.b); // takes ownership of |s.b|
    e = rb_ary_pop(a);
    handle_exception(e);
    return rb_ary_pop(a);
}

#compile(*args) ⇒ Object



2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549
# File 'ext/mini_racer_csim_extension/mini_racer_csim_extension.c', line 2493

static VALUE context_compile(int argc, VALUE *argv, VALUE self)
{
    VALUE a, e, source, filename, cached_data, produce_cache, kwargs;
    VALUE script_v, result;
    Script *script;
    Context *c;
    Ser s;

    TypedData_Get_Struct(self, Context, &context_type, c);
    rb_scan_args(argc, argv, "1:", &source, &kwargs);
    Check_Type(source, T_STRING);
    filename = Qnil;
    cached_data = Qnil;
    produce_cache = Qfalse;
    if (!NIL_P(kwargs)) {
        filename = rb_hash_aref(kwargs, ID2SYM(id_filename));
        cached_data = rb_hash_aref(kwargs, ID2SYM(id_cached_data));
        produce_cache = rb_hash_aref(kwargs, ID2SYM(id_produce_cache));
    }
    if (NIL_P(filename))
        filename = rb_str_new_cstr("<compile>");
    Check_Type(filename, T_STRING);
    if (!NIL_P(cached_data)) {
        Check_Type(cached_data, T_STRING);
        // Refuse non-binary encodings so a user reading a cache file without
        // 'rb' mode gets a clear error instead of mangled bytes flowing to V8.
        if (rb_enc_get(cached_data) != rb_ascii8bit_encoding())
            rb_raise(rb_eEncodingError,
                     "cached_data must be ASCII-8BIT (binary), got %s",
                     rb_enc_name(rb_enc_get(cached_data)));
    }
    ser_init1(&s, 'K');
    ser_array_begin(&s, 4);
    add_string(&s, filename);
    add_string(&s, source);
    if (NIL_P(cached_data)) {
        ser_null(&s);
    } else {
        ser_uint8array(&s, (const uint8_t *)RSTRING_PTR(cached_data),
                       RSTRING_LENINT(cached_data));
    }
    ser_bool(&s, RTEST(produce_cache));
    ser_array_end(&s, 4);
    a = rendezvous(c, &s.b);
    e = rb_ary_pop(a);
    handle_exception(e);
    result = rb_ary_pop(a);
    Check_Type(result, T_ARRAY);

    script_v = rb_obj_alloc(script_class); // skip the raising initialize
    TypedData_Get_Struct(script_v, Script, &script_type, script);
    script->context = self;
    script->handle_id = NUM2INT(rb_ary_entry(result, 0));
    script->cached_data = rb_ary_entry(result, 1);
    script->cache_rejected = RTEST(rb_ary_entry(result, 2));
    return script_v;
}

#compile_module(*args) ⇒ Object



2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
# File 'ext/mini_racer_csim_extension/mini_racer_csim_extension.c', line 2657

static VALUE context_compile_module(int argc, VALUE *argv, VALUE self)
{
    VALUE a, e, source, filename, cached_data, produce_cache, kwargs;
    VALUE module_v, result;
    Module *m;
    Context *c;
    Ser s;

    TypedData_Get_Struct(self, Context, &context_type, c);
    if (atomic_load(&c->quit))
        rb_raise(context_disposed_error, "disposed context");
    rb_scan_args(argc, argv, "1:", &source, &kwargs);
    Check_Type(source, T_STRING);
    filename = Qnil;
    cached_data = Qnil;
    produce_cache = Qfalse;
    if (!NIL_P(kwargs)) {
        filename = rb_hash_aref(kwargs, ID2SYM(id_filename));
        cached_data = rb_hash_aref(kwargs, ID2SYM(id_cached_data));
        produce_cache = rb_hash_aref(kwargs, ID2SYM(id_produce_cache));
    }
    if (NIL_P(filename))
        filename = rb_str_new_cstr("<compile_module>");
    Check_Type(filename, T_STRING);
    if (!NIL_P(cached_data)) {
        Check_Type(cached_data, T_STRING);
        // Refuse non-binary encodings so a user reading a cache file without
        // 'rb' mode gets a clear error instead of mangled bytes flowing to V8.
        if (rb_enc_get(cached_data) != rb_ascii8bit_encoding())
            rb_raise(rb_eEncodingError,
                     "cached_data must be ASCII-8BIT (binary), got %s",
                     rb_enc_name(rb_enc_get(cached_data)));
    }
    ser_init1(&s, 'O');
    ser_array_begin(&s, 4);
    add_string(&s, filename);
    add_string(&s, source);
    if (NIL_P(cached_data)) {
        ser_null(&s);
    } else {
        ser_uint8array(&s, (const uint8_t *)RSTRING_PTR(cached_data),
                       RSTRING_LENINT(cached_data));
    }
    ser_bool(&s, RTEST(produce_cache));
    ser_array_end(&s, 4);
    a = rendezvous(c, &s.b);
    e = rb_ary_pop(a);
    handle_exception(e);
    result = rb_ary_pop(a);
    Check_Type(result, T_ARRAY);

    module_v = rb_obj_alloc(module_class); // skip the raising initialize
    TypedData_Get_Struct(module_v, Module, &module_type, m);
    m->context = self;
    m->handle_id = NUM2INT(rb_ary_entry(result, 0));
    m->cached_data = rb_ary_entry(result, 1);
    m->cache_rejected = RTEST(rb_ary_entry(result, 2));
    return module_v;
}

#create_realmObject



2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106
2107
2108
2109
2110
2111
2112
2113
2114
# File 'ext/mini_racer_csim_extension/mini_racer_csim_extension.c', line 2091

static VALUE context_create_realm(VALUE self)
{
    Context *c;
    VALUE a, e, result, realm_v;
    Realm *r;
    Buf b;

    TypedData_Get_Struct(self, Context, &context_type, c);
    if (atomic_load(&c->quit))
        rb_raise(context_disposed_error, "disposed context");
    buf_init(&b);
    buf_putc(&b, 'B');     // (B)uild realm, returns [id, err]
    a = rendezvous(c, &b); // takes ownership of |b|
    e = rb_ary_pop(a);
    handle_exception(e);
    result = rb_ary_pop(a);

    realm_v = rb_obj_alloc(realm_class); // skip the raising initialize
    TypedData_Get_Struct(realm_v, Realm, &realm_type, r);
    r->context = self;
    r->id = NUM2INT(result);
    r->disposed = 0;
    return realm_v;
}

#disposeObject



1786
1787
1788
1789
1790
1791
1792
1793
# File 'ext/mini_racer_csim_extension/mini_racer_csim_extension.c', line 1786

static VALUE context_dispose(VALUE self)
{
    Context *c;

    TypedData_Get_Struct(self, Context, &context_type, c);
    rb_thread_call_without_gvl(context_dispose_do, c, NULL, NULL);
    return Qnil;
}

#disposed?Boolean

Returns:

  • (Boolean)


2650
2651
2652
2653
2654
2655
# File 'ext/mini_racer_csim_extension/mini_racer_csim_extension.c', line 2650

static VALUE script_disposed_p(VALUE self)
{
    Script *script;
    TypedData_Get_Struct(self, Script, &script_type, script);
    return script->disposed ? Qtrue : Qfalse;
}

#dumpObject



2458
2459
2460
2461
2462
2463
2464
# File 'ext/mini_racer_csim_extension/mini_racer_csim_extension.c', line 2458

static VALUE snapshot_dump(VALUE self)
{
    Snapshot *ss;

    TypedData_Get_Struct(self, Snapshot, &snapshot_type, ss);
    return ss->blob;
}

#dynamic_import_resolverObject



3029
3030
3031
3032
3033
3034
# File 'ext/mini_racer_csim_extension/mini_racer_csim_extension.c', line 3029

static VALUE context_get_dynamic_import_resolver(VALUE self)
{
    Context *c;
    TypedData_Get_Struct(self, Context, &context_type, c);
    return c->dynamic_import_resolver;
}

#dynamic_import_resolver=(blk) ⇒ Object



3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
# File 'ext/mini_racer_csim_extension/mini_racer_csim_extension.c', line 3018

static VALUE context_set_dynamic_import_resolver(VALUE self, VALUE blk)
{
    Context *c;
    TypedData_Get_Struct(self, Context, &context_type, c);
    if (!NIL_P(blk) && !rb_respond_to(blk, rb_intern("call")))
        rb_raise(rb_eTypeError,
                 "dynamic_import_resolver must respond to #call or be nil");
    c->dynamic_import_resolver = blk;
    return blk;
}

#eval(*args) ⇒ Object



1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
# File 'ext/mini_racer_csim_extension/mini_racer_csim_extension.c', line 1832

static VALUE context_eval(int argc, VALUE *argv, VALUE self)
{
    VALUE a, e, source, filename, kwargs;
    Context *c;
    Ser s;

    TypedData_Get_Struct(self, Context, &context_type, c);
    filename = Qnil;
    rb_scan_args(argc, argv, "1:", &source, &kwargs);
    Check_Type(source, T_STRING);
    if (!NIL_P(kwargs))
        filename = rb_hash_aref(kwargs, rb_id2sym(rb_intern("filename")));
    if (NIL_P(filename))
        filename = rb_str_new_cstr("<eval>");
    Check_Type(filename, T_STRING);
    // request is (E)val, [filename, source] array
    ser_init1(&s, 'E');
    ser_array_begin(&s, 2);
    add_string(&s, filename);
    add_string(&s, source);
    ser_array_end(&s, 2);
    // response is [result, errname] array
    a = rendezvous(c, &s.b); // takes ownership of |s.b|
    e = rb_ary_pop(a);
    handle_exception(e);
    return rb_ary_pop(a);
}

#evaluateObject



2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
# File 'ext/mini_racer_csim_extension/mini_racer_csim_extension.c', line 2917

static VALUE module_evaluate(VALUE self)
{
    VALUE a, e;
    Module *m;
    Context *c;
    Ser s;

    TypedData_Get_Struct(self, Module, &module_type, m);
    if (m->disposed)
        rb_raise(runtime_error, "disposed module");
    TypedData_Get_Struct(m->context, Context, &context_type, c);
    if (atomic_load(&c->quit))
        rb_raise(context_disposed_error, "disposed context");
    ser_init1(&s, 'V');
    ser_int(&s, m->handle_id);
    a = rendezvous(c, &s.b);
    e = rb_ary_pop(a);
    handle_exception(e);
    return rb_ary_pop(a);
}

#heap_snapshotObject



1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
# File 'ext/mini_racer_csim_extension/mini_racer_csim_extension.c', line 1882

static VALUE context_heap_snapshot(VALUE self)
{
    Buf req, res;
    Context *c;

    TypedData_Get_Struct(self, Context, &context_type, c);
    buf_init(&req);
    buf_putc(&req, 'H');              // (H)eap snapshot, returns plain bytes
    rendezvous_no_des(c, &req, &res); // takes ownership of |req|
    return rb_utf8_str_new((char *)res.buf, res.len);
}

#heap_statsObject



1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
# File 'ext/mini_racer_csim_extension/mini_racer_csim_extension.c', line 1860

static VALUE context_heap_stats(VALUE self)
{
    VALUE a, h, k, v;
    Context *c;
    int i, n;
    Buf b;

    TypedData_Get_Struct(self, Context, &context_type, c);
    buf_init(&b);
    buf_putc(&b, 'S');     // (S)tats, returns object
    h = rendezvous(c, &b); // takes ownership of |b|
    a = rb_ary_new();
    rb_hash_foreach(h, collect, a);
    for (i = 0, n = RARRAY_LENINT(a); i < n; i += 2) {
        k = rb_ary_entry(a, i+0);
        v = rb_ary_entry(a, i+1);
        rb_hash_delete(h, k);
        rb_hash_aset(h, rb_str_intern(k), v); // turn "key" into :key
    }
    return h;
}

#idObject

takes ownership of |req|



1989
1990
1991
1992
1993
1994
# File 'ext/mini_racer_csim_extension/mini_racer_csim_extension.c', line 1989

static VALUE realm_id(VALUE self)
{
    Realm *r;
    TypedData_Get_Struct(self, Realm, &realm_type, r);
    return INT2NUM(r->id);
}

#instantiateObject



2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
# File 'ext/mini_racer_csim_extension/mini_racer_csim_extension.c', line 2798

static VALUE module_instantiate(VALUE self)
{
    VALUE block;
    Module *m;
    Context *c;
    struct instantiate_args ia;

    if (!rb_block_given_p())
        rb_raise(rb_eArgError, "Module#instantiate requires a resolver block");
    block = rb_block_proc();

    TypedData_Get_Struct(self, Module, &module_type, m);
    if (m->disposed)
        rb_raise(runtime_error, "disposed module");
    TypedData_Get_Struct(m->context, Context, &context_type, c);
    if (atomic_load(&c->quit))
        rb_raise(context_disposed_error, "disposed context");

    // Save the previous resolver slot so a re-entrant instantiate from
    // inside this block restores its caller's block on the way out.
    // rb_ensure guarantees restoration even when the resolver block
    // raises (without it, the slot would be left pointing at this call's
    // block and keep it GC-alive until something else overwrites it).
    ia.c = c;
    ia.handle_id = m->handle_id;
    ia.prev_block = c->resolve_block;
    c->resolve_block = block;
    rb_ensure(module_instantiate_body, (VALUE)&ia,
              module_instantiate_restore, (VALUE)&ia);
    return self;
}

#load_module_graph(*args) ⇒ Object

same Module instance instead of being recompiled.



2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
# File 'ext/mini_racer_csim_extension/mini_racer_csim_extension.c', line 2886

static VALUE context_load_module_graph(int argc, VALUE *argv, VALUE self)
{
    VALUE entry_url, kwargs, resolve, fetch_batch;
    Context *c;
    struct load_graph_args la;

    TypedData_Get_Struct(self, Context, &context_type, c);
    if (atomic_load(&c->quit))
        rb_raise(context_disposed_error, "disposed context");
    rb_scan_args(argc, argv, "1:", &entry_url, &kwargs);
    Check_Type(entry_url, T_STRING);
    resolve = fetch_batch = Qnil;
    if (!NIL_P(kwargs)) {
        resolve     = rb_hash_aref(kwargs, ID2SYM(rb_intern("resolve")));
        fetch_batch = rb_hash_aref(kwargs, ID2SYM(rb_intern("fetch_batch")));
    }
    if (!rb_respond_to(resolve, rb_intern("call")))
        rb_raise(rb_eArgError, "load_module_graph requires a resolve: callable");
    if (!rb_respond_to(fetch_batch, rb_intern("call")))
        rb_raise(rb_eArgError, "load_module_graph requires a fetch_batch: callable");

    // Persist the callbacks for the Context's lifetime so dynamic import() can
    // reuse them after this call returns (case A). A later load_module_graph
    // overwrites them; dispose frees them.
    c->graph_resolve_block = resolve;
    c->graph_fetch_block   = fetch_batch;
    la.c = c;
    la.entry_url = entry_url;
    return context_load_module_graph_body((VALUE)&la);
}

#low_memory_notificationObject

takes ownership of |b|



2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
# File 'ext/mini_racer_csim_extension/mini_racer_csim_extension.c', line 2127

static VALUE context_low_memory_notification(VALUE self)
{
    Buf req, res;
    Context *c;

    TypedData_Get_Struct(self, Context, &context_type, c);
    buf_init(&req);
    buf_putc(&req, 'L');              // (L)ow memory notification, returns nothing
    rendezvous_no_des(c, &req, &res); // takes ownership of |req|
    return Qnil;
}

#namespaceObject



2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
# File 'ext/mini_racer_csim_extension/mini_racer_csim_extension.c', line 2938

static VALUE module_namespace(VALUE self)
{
    VALUE a, e;
    Module *m;
    Context *c;
    Ser s;

    TypedData_Get_Struct(self, Module, &module_type, m);
    if (m->disposed)
        rb_raise(runtime_error, "disposed module");
    TypedData_Get_Struct(m->context, Context, &context_type, c);
    if (atomic_load(&c->quit))
        rb_raise(context_disposed_error, "disposed context");
    ser_init1(&s, 'N');
    ser_int(&s, m->handle_id);
    a = rendezvous(c, &s.b);
    e = rb_ary_pop(a);
    handle_exception(e);
    return rb_ary_pop(a);
}

#perform_microtask_checkpointObject



1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
# File 'ext/mini_racer_csim_extension/mini_racer_csim_extension.c', line 1894

static VALUE context_perform_microtask_checkpoint(VALUE self)
{
    Context *c;
    Buf b;

    TypedData_Get_Struct(self, Context, &context_type, c);
    buf_init(&b);
    buf_putc(&b, 'M');        // (M)icrotask checkpoint, returns nil
    return rendezvous(c, &b); // takes ownership of |b|
}

#pump_message_loopObject



2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
# File 'ext/mini_racer_csim_extension/mini_racer_csim_extension.c', line 2116

static VALUE context_pump_message_loop(VALUE self)
{
    Context *c;
    Buf b;

    TypedData_Get_Struct(self, Context, &context_type, c);
    buf_init(&b);
    buf_putc(&b, 'P');        // (P)ump, returns bool
    return rendezvous(c, &b); // takes ownership of |b|
}

#reset_realmObject

and are invalidated by the reset. Refused from within a host callback.



1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
# File 'ext/mini_racer_csim_extension/mini_racer_csim_extension.c', line 1911

static VALUE context_reset_realm(VALUE self)
{
    Context *c;
    VALUE e;
    Buf b;

    TypedData_Get_Struct(self, Context, &context_type, c);
    buf_init(&b);
    buf_putc(&b, 'F');     // (F)resh realm, returns err or undefined
    e = rendezvous(c, &b); // takes ownership of |b|
    handle_exception(e);
    return Qnil;
}

#runObject



2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
# File 'ext/mini_racer_csim_extension/mini_racer_csim_extension.c', line 2594

static VALUE script_run(VALUE self)
{
    VALUE a, e;
    Script *script;
    Context *c;
    Ser s;

    TypedData_Get_Struct(self, Script, &script_type, script);
    if (script->disposed)
        rb_raise(runtime_error, "disposed script");
    TypedData_Get_Struct(script->context, Context, &context_type, c);
    if (atomic_load(&c->quit))
        rb_raise(context_disposed_error, "disposed context");
    ser_init1(&s, 'R');
    ser_int(&s, script->handle_id);
    a = rendezvous(c, &s.b);
    e = rb_ary_pop(a);
    handle_exception(e);
    return rb_ary_pop(a);
}

#sizeObject



2480
2481
2482
2483
2484
2485
2486
# File 'ext/mini_racer_csim_extension/mini_racer_csim_extension.c', line 2480

static VALUE snapshot_size0(VALUE self)
{
    Snapshot *ss;

    TypedData_Get_Struct(self, Snapshot, &snapshot_type, ss);
    return LONG2FIX(RSTRING_LENINT(ss->blob));
}

#statusObject



2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
# File 'ext/mini_racer_csim_extension/mini_racer_csim_extension.c', line 2959

static VALUE module_status(VALUE self)
{
    VALUE a, e, result;
    Module *m;
    Context *c;
    Ser s;

    TypedData_Get_Struct(self, Module, &module_type, m);
    if (m->disposed)
        rb_raise(runtime_error, "disposed module");
    TypedData_Get_Struct(m->context, Context, &context_type, c);
    if (atomic_load(&c->quit))
        rb_raise(context_disposed_error, "disposed context");
    ser_init1(&s, 'U');
    ser_int(&s, m->handle_id);
    a = rendezvous(c, &s.b);
    e = rb_ary_pop(a);
    handle_exception(e);
    result = rb_ary_pop(a);
    // v8_module_status always replies with a String on success; a non-string
    // would mean the v8 thread fell through to the Undefined fail path with
    // a missing error (shouldn't happen, but check defensively rather than
    // crash rb_str_intern on Qnil).
    Check_Type(result, T_STRING);
    return rb_str_intern(result);
}

#stopObject



1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
# File 'ext/mini_racer_csim_extension/mini_racer_csim_extension.c', line 1795

static VALUE context_stop(VALUE self)
{
    Context *c;

    // does not grab |mtx| because Context.stop can be called from another
    // thread and then we deadlock if e.g. the V8 thread busy-loops in JS
    TypedData_Get_Struct(self, Context, &context_type, c);
    if (atomic_load(&c->quit))
        rb_raise(context_disposed_error, "disposed context");
    v8_terminate_execution(c->pst);
    return Qnil;
}

#warmup!(arg) ⇒ Object



2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
# File 'ext/mini_racer_csim_extension/mini_racer_csim_extension.c', line 2427

static VALUE snapshot_warmup(VALUE self, VALUE arg)
{
    VALUE a, e, cv;
    Snapshot *ss;
    Context *c;
    DesCtx d;
    Ser s;

    TypedData_Get_Struct(self, Snapshot, &snapshot_type, ss);
    Check_Type(arg, T_STRING);
    cv = context_alloc(context_class);
    context_initialize(0, NULL, cv);
    TypedData_Get_Struct(cv, Context, &context_type, c);
    // request is (W)armup, [snapshot, "warmup code"]
    ser_init1(&s, 'W');
    ser_array_begin(&s, 2);
    ser_string8(&s, (const uint8_t *)RSTRING_PTR(ss->blob), RSTRING_LENINT(ss->blob));
    add_string(&s, arg);
    ser_array_end(&s, 2);
    // response is [arraybuffer, error]
    DesCtx_init(&d);
    d.transcode_latin1 = 0; // don't mangle snapshot binary data
    a = rendezvous1(c, &s.b, &d);
    e = rb_ary_pop(a);
    context_dispose(cv);
    if (*RSTRING_PTR(e))
        rb_raise(snapshot_error, "%s", RSTRING_PTR(e)+1);
    ss->blob = rb_ary_pop(a);
    return self;
}