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



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
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
# File 'ext/mini_racer_extension/mini_racer_extension.c', line 1978

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



2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
# File 'ext/mini_racer_extension/mini_racer_extension.c', line 2152

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



1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
# File 'ext/mini_racer_extension/mini_racer_extension.c', line 1599

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



1718
1719
1720
1721
# File 'ext/mini_racer_extension/mini_racer_extension.c', line 1718

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

#call_await(*args) ⇒ Object



1723
1724
1725
1726
# File 'ext/mini_racer_extension/mini_racer_extension.c', line 1723

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

#disposeObject



1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
# File 'ext/mini_racer_extension/mini_racer_extension.c', line 1669

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



2144
2145
2146
2147
2148
2149
2150
# File 'ext/mini_racer_extension/mini_racer_extension.c', line 2144

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

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

#eval(*args) ⇒ Object



1756
1757
1758
1759
# File 'ext/mini_racer_extension/mini_racer_extension.c', line 1756

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

#eval_await(*args) ⇒ Object



1761
1762
1763
1764
# File 'ext/mini_racer_extension/mini_racer_extension.c', line 1761

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

#heap_snapshotObject



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

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



1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
# File 'ext/mini_racer_extension/mini_racer_extension.c', line 1766

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



1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
# File 'ext/mini_racer_extension/mini_racer_extension.c', line 1837

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



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

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



1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
# File 'ext/mini_racer_extension/mini_racer_extension.c', line 1826

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



2166
2167
2168
2169
2170
2171
2172
# File 'ext/mini_racer_extension/mini_racer_extension.c', line 2166

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

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

#stopObject



1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
# File 'ext/mini_racer_extension/mini_racer_extension.c', line 1681

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



2114
2115
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
# File 'ext/mini_racer_extension/mini_racer_extension.c', line 2114

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