Exception: MiniRacer::EvalError

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

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args) ⇒ Object



1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
# File 'ext/mini_racer_extension/mini_racer_extension.c', line 1953

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 {
            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);
    } 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;
        barrier_wait(&c->early_init);
        barrier_wait(&c->late_init);
    }
    return Qnil;
fail:
    rb_raise(runtime_error, "Context.initialize: %s: %s", cause, strerror(r));
    return Qnil; // pacify compiler
}

Class Method Details

.load(blob) ⇒ Object



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

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



1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
# File 'ext/mini_racer_extension/mini_racer_extension.c', line 1574

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

    TypedData_Get_Struct(self, Context, &context_type, c);
    id = RARRAY_LEN(c->procs);
    if (id > INT32_MAX)
        rb_raise(runtime_error, "too many callbacks");
    // request is (A)ttach, [name, id] array
    ser_init1(&s, 'A');
    ser_array_begin(&s, 2);
    add_string(&s, name);
    ser_int(&s, id);
    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;
}

#call(*args) ⇒ Object



1693
1694
1695
1696
# File 'ext/mini_racer_extension/mini_racer_extension.c', line 1693

static VALUE context_call(int argc, VALUE *argv, VALUE self)
{
    return context_call_common(argc, argv, self, 'C');
}

#call_await(*args) ⇒ Object



1698
1699
1700
1701
# File 'ext/mini_racer_extension/mini_racer_extension.c', line 1698

static VALUE context_call_await(int argc, VALUE *argv, VALUE self)
{
    return context_call_common(argc, argv, self, 'D');
}

#disposeObject



1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
# File 'ext/mini_racer_extension/mini_racer_extension.c', line 1644

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

    TypedData_Get_Struct(self, Context, &context_type, c);
    r = rb_thread_call_without_gvl(context_dispose_do, c, terminate_ubf, c);
    if (r)
        rb_raise(runtime_error, "context dispose: %s", strerror((int)(intptr_t)r));
    return Qnil;
}

#dumpObject



2119
2120
2121
2122
2123
2124
2125
# File 'ext/mini_racer_extension/mini_racer_extension.c', line 2119

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

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

#eval(*args) ⇒ Object



1731
1732
1733
1734
# File 'ext/mini_racer_extension/mini_racer_extension.c', line 1731

static VALUE context_eval(int argc, VALUE *argv, VALUE self)
{
    return context_eval_common(argc, argv, self, 'E');
}

#eval_await(*args) ⇒ Object



1736
1737
1738
1739
# File 'ext/mini_racer_extension/mini_racer_extension.c', line 1736

static VALUE context_eval_await(int argc, VALUE *argv, VALUE self)
{
    return context_eval_common(argc, argv, self, 'F');
}

#heap_snapshotObject



1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
# File 'ext/mini_racer_extension/mini_racer_extension.c', line 1777

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_ensure(heap_snapshot_to_str, (VALUE)&res,
                     buf_reset_ensure, (VALUE)&res);
}

#heap_statsObject



1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
# File 'ext/mini_racer_extension/mini_racer_extension.c', line 1741

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;
}

#low_memory_notificationObject



1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
# File 'ext/mini_racer_extension/mini_racer_extension.c', line 1812

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|
    buf_reset(&res);
    return Qnil;
}

#perform_microtask_checkpointObject



1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
# File 'ext/mini_racer_extension/mini_racer_extension.c', line 1790

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



1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
# File 'ext/mini_racer_extension/mini_racer_extension.c', line 1801

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|
}

#sizeObject



2141
2142
2143
2144
2145
2146
2147
# File 'ext/mini_racer_extension/mini_racer_extension.c', line 2141

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

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

#stopObject



1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
# File 'ext/mini_racer_extension/mini_racer_extension.c', line 1656

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



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

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);
    raise_exception_with_message(snapshot_error, e);
    ss->blob = rb_ary_pop(a);
    return self;
}