quickjs 0.17.0.rc1 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +102 -3
- data/ext/quickjsrb/quickjsrb.c +357 -25
- data/ext/quickjsrb/quickjsrb.h +39 -7
- data/ext/quickjsrb/vendor/polyfill-intl-en.min.js +4 -4
- data/lib/quickjs/version.rb +1 -1
- data/lib/quickjs.rb +19 -5
- data/polyfills/package-lock.json +110 -110
- data/polyfills/package.json +1 -1
- data/sig/quickjs.rbs +14 -2
- metadata +1 -1
data/ext/quickjsrb/quickjsrb.h
CHANGED
|
@@ -57,6 +57,16 @@ typedef struct VMData
|
|
|
57
57
|
VALUE log_listener;
|
|
58
58
|
VALUE alive_objects;
|
|
59
59
|
VALUE module_loader;
|
|
60
|
+
VALUE on_unhandled_rejection;
|
|
61
|
+
// Memoize (specifier, importer) → canonical so the user's loader Proc
|
|
62
|
+
// runs at most once per distinct pair across the VM's lifetime. Without
|
|
63
|
+
// this, QuickJS calls normalize on every import statement — including
|
|
64
|
+
// duplicates within the same file — and we'd re-invoke the user proc.
|
|
65
|
+
VALUE module_resolution_cache;
|
|
66
|
+
// Carries `code` from the normalize-phase Proc call to the load-phase
|
|
67
|
+
// JS_Eval that follows. Keyed by canonical; populated when the user's
|
|
68
|
+
// loader returns either a raw source String or `{ code:, as: }`.
|
|
69
|
+
VALUE module_source_cache;
|
|
60
70
|
JSValue j_file_proxy_creator;
|
|
61
71
|
// Once the runtime has hit JS-level "out of memory", the QuickJS heap is in
|
|
62
72
|
// a fragile state where further evaluation can trigger a use-after-free in
|
|
@@ -64,21 +74,33 @@ typedef struct VMData
|
|
|
64
74
|
// Trip this flag so subsequent eval_code/call calls refuse cleanly with a
|
|
65
75
|
// Ruby exception instead of risking a process crash.
|
|
66
76
|
bool oom_poisoned;
|
|
77
|
+
// Set by VM#dispose! to release the multi-MB JS heap before Ruby GC sees
|
|
78
|
+
// enough pressure to collect the wrapper. Doubles as a double-free guard
|
|
79
|
+
// for the dfree handler.
|
|
80
|
+
bool disposed;
|
|
67
81
|
} VMData;
|
|
68
82
|
|
|
83
|
+
static void vm_teardown_context(JSContext *ctx)
|
|
84
|
+
{
|
|
85
|
+
JSRuntime *runtime = JS_GetRuntime(ctx);
|
|
86
|
+
JS_SetInterruptHandler(runtime, NULL, NULL);
|
|
87
|
+
js_std_free_handlers(runtime);
|
|
88
|
+
JS_FreeContext(ctx);
|
|
89
|
+
JS_FreeRuntime(runtime);
|
|
90
|
+
}
|
|
91
|
+
|
|
69
92
|
static void vm_free(void *ptr)
|
|
70
93
|
{
|
|
71
94
|
VMData *data = (VMData *)ptr;
|
|
72
95
|
free(data->eval_time);
|
|
73
96
|
|
|
74
|
-
if (!
|
|
75
|
-
|
|
97
|
+
if (!data->disposed)
|
|
98
|
+
{
|
|
99
|
+
if (!JS_IsUndefined(data->j_file_proxy_creator))
|
|
100
|
+
JS_FreeValue(data->context, data->j_file_proxy_creator);
|
|
76
101
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
js_std_free_handlers(runtime);
|
|
80
|
-
JS_FreeContext(data->context);
|
|
81
|
-
JS_FreeRuntime(runtime);
|
|
102
|
+
vm_teardown_context(data->context);
|
|
103
|
+
}
|
|
82
104
|
|
|
83
105
|
xfree(ptr);
|
|
84
106
|
}
|
|
@@ -95,6 +117,9 @@ static void vm_mark(void *ptr)
|
|
|
95
117
|
rb_gc_mark_movable(data->log_listener);
|
|
96
118
|
rb_gc_mark_movable(data->alive_objects);
|
|
97
119
|
rb_gc_mark_movable(data->module_loader);
|
|
120
|
+
rb_gc_mark_movable(data->on_unhandled_rejection);
|
|
121
|
+
rb_gc_mark_movable(data->module_resolution_cache);
|
|
122
|
+
rb_gc_mark_movable(data->module_source_cache);
|
|
98
123
|
}
|
|
99
124
|
|
|
100
125
|
static void vm_compact(void *ptr)
|
|
@@ -104,6 +129,9 @@ static void vm_compact(void *ptr)
|
|
|
104
129
|
data->log_listener = rb_gc_location(data->log_listener);
|
|
105
130
|
data->alive_objects = rb_gc_location(data->alive_objects);
|
|
106
131
|
data->module_loader = rb_gc_location(data->module_loader);
|
|
132
|
+
data->on_unhandled_rejection = rb_gc_location(data->on_unhandled_rejection);
|
|
133
|
+
data->module_resolution_cache = rb_gc_location(data->module_resolution_cache);
|
|
134
|
+
data->module_source_cache = rb_gc_location(data->module_source_cache);
|
|
107
135
|
}
|
|
108
136
|
|
|
109
137
|
static const rb_data_type_t vm_type = {
|
|
@@ -137,8 +165,12 @@ static VALUE vm_alloc(VALUE r_self)
|
|
|
137
165
|
data->log_listener = Qnil;
|
|
138
166
|
data->alive_objects = rb_hash_new();
|
|
139
167
|
data->module_loader = Qnil;
|
|
168
|
+
data->on_unhandled_rejection = Qnil;
|
|
169
|
+
data->module_resolution_cache = rb_hash_new();
|
|
170
|
+
data->module_source_cache = rb_hash_new();
|
|
140
171
|
data->j_file_proxy_creator = JS_UNDEFINED;
|
|
141
172
|
data->oom_poisoned = false;
|
|
173
|
+
data->disposed = false;
|
|
142
174
|
|
|
143
175
|
EvalTime *eval_time = malloc(sizeof(EvalTime));
|
|
144
176
|
data->eval_time = eval_time;
|