This repository has been archived by the owner on Aug 18, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 33
/
context.c
120 lines (99 loc) · 3.49 KB
/
context.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#include "context.h"
#include "conversions.h"
#include "global.h"
#include "extensions.h"
#include "idhash.h"
#include "jsdbgapi.h"
// callback for JS_SetErrorReporter
static void report_js_error(JSContext* js, const char* message, JSErrorReport* UNUSED(report))
{
// first we find ourselves
VALUE self = (VALUE)JS_GetContextPrivate(js);
// then we find our bridge
JohnsonContext* context;
Data_Get_Struct(self, JohnsonContext, context);
// NOTE: SpiderMonkey REALLY doesn't like being interrupted. If we
// jump over to Ruby and raise here, segfaults and such ensue.
// Instead, we store the exception (if any) and the error message
// on the context. They're dealt with in the if (!ok) block of evaluate().
strncpy(context->msg, message, MAX_EXCEPTION_MESSAGE_SIZE);
JS_GetPendingException(context->js, &context->ex);
}
// callback for JS_SetBranchCallback
static JSBool branch_callback(JSContext* js, JSScript* UNUSED(script))
{
static unsigned long branch_counter = 0;
if( ++branch_counter % 0x1000 == 0 )
JS_MaybeGC( js );
return JS_TRUE;
}
/*
* call-seq:
* native_initialize(options={})
*
* Initializes the native spidermonkey values.
*/
static VALUE
initialize_native(VALUE self, VALUE rb_runtime, VALUE UNUSED(options))
{
JohnsonContext* context;
JohnsonRuntime* runtime;
Data_Get_Struct(self, JohnsonContext, context);
Data_Get_Struct(rb_runtime, JohnsonRuntime, runtime);
if ((context->js = JS_NewContext(runtime->js, 8192L)))
{
// See if the runtime already has a shared global object.
JSObject* global = runtime->global;
// If it does, use it. If not,
if (!global)
// create one of our global objects.
global = johnson_create_global_object(context->js);
// Manually set the context's global object.
JS_SetGlobalObject(context->js, global);
JS_SetErrorReporter(context->js, report_js_error);
JS_SetBranchCallback(context->js, branch_callback);
JS_SetContextPrivate(context->js, (void *)self);
JS_SetOptions(context->js, JS_GetOptions(context->js)
#ifdef JSOPTION_DONT_REPORT_UNCAUGHT
| JSOPTION_DONT_REPORT_UNCAUGHT
#endif
#ifdef JSOPTION_VAROBJFIX
| JSOPTION_VAROBJFIX
#endif
// #ifdef JSOPTION_XML
// | JSOPTION_XML
// #endif
);
// Success.
return init_spidermonkey_extensions(context, self);
}
if (context->js) JS_DestroyContext(context->js);
rb_raise(rb_eRuntimeError, "Failed to initialize SpiderMonkey context");
}
///////////////////////////////////////////////////////////////////////////
//// INFRASTRUCTURE BELOW HERE ////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
static VALUE allocate(VALUE klass)
{
JohnsonContext* context = calloc(1L, sizeof(JohnsonContext));
return Data_Wrap_Struct(klass, 0, 0, context);
}
void init_Johnson_SpiderMonkey_Context(VALUE spidermonkey)
{
/* HACK: These comments are *only* to make RDoc happy.
VALUE johnson = rb_define_module("Johnson");
VALUE spidermonkey = rb_define_module_under(johnson, "SpiderMonkey");
*/
/* This is the private context used for SpiderMonkey. */
VALUE context = rb_define_class_under(spidermonkey, "Context", rb_cObject);
rb_define_alloc_func(context, allocate);
rb_define_private_method(context, "initialize_native", initialize_native, 2);
}
VALUE Johnson_SpiderMonkey_JSLandProxy()
{
return rb_eval_string("Johnson::SpiderMonkey::JSLandProxy");
}
VALUE Johnson_Prototyper()
{
return rb_eval_string("Johnson::Prototyper");
}