quickjs 0.17.0 → 0.19.0.pre1

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.
@@ -14,8 +14,6 @@
14
14
  #include <string.h>
15
15
  #include <time.h>
16
16
 
17
- extern const uint32_t qjsc_polyfill_intl_en_min_size;
18
- extern const uint8_t qjsc_polyfill_intl_en_min;
19
17
  extern const uint32_t qjsc_polyfill_file_min_size;
20
18
  extern const uint8_t qjsc_polyfill_file_min;
21
19
  extern const uint32_t qjsc_polyfill_encoding_min_size;
@@ -57,6 +55,16 @@ typedef struct VMData
57
55
  VALUE log_listener;
58
56
  VALUE alive_objects;
59
57
  VALUE module_loader;
58
+ VALUE on_unhandled_rejection;
59
+ // Memoize (specifier, importer) → canonical so the user's loader Proc
60
+ // runs at most once per distinct pair across the VM's lifetime. Without
61
+ // this, QuickJS calls normalize on every import statement — including
62
+ // duplicates within the same file — and we'd re-invoke the user proc.
63
+ VALUE module_resolution_cache;
64
+ // Carries `code` from the normalize-phase Proc call to the load-phase
65
+ // JS_Eval that follows. Keyed by canonical; populated when the user's
66
+ // loader returns either a raw source String or `{ code:, as: }`.
67
+ VALUE module_source_cache;
60
68
  JSValue j_file_proxy_creator;
61
69
  // Once the runtime has hit JS-level "out of memory", the QuickJS heap is in
62
70
  // a fragile state where further evaluation can trigger a use-after-free in
@@ -64,21 +72,33 @@ typedef struct VMData
64
72
  // Trip this flag so subsequent eval_code/call calls refuse cleanly with a
65
73
  // Ruby exception instead of risking a process crash.
66
74
  bool oom_poisoned;
75
+ // Set by VM#dispose! to release the multi-MB JS heap before Ruby GC sees
76
+ // enough pressure to collect the wrapper. Doubles as a double-free guard
77
+ // for the dfree handler.
78
+ bool disposed;
67
79
  } VMData;
68
80
 
81
+ static void vm_teardown_context(JSContext *ctx)
82
+ {
83
+ JSRuntime *runtime = JS_GetRuntime(ctx);
84
+ JS_SetInterruptHandler(runtime, NULL, NULL);
85
+ js_std_free_handlers(runtime);
86
+ JS_FreeContext(ctx);
87
+ JS_FreeRuntime(runtime);
88
+ }
89
+
69
90
  static void vm_free(void *ptr)
70
91
  {
71
92
  VMData *data = (VMData *)ptr;
72
93
  free(data->eval_time);
73
94
 
74
- if (!JS_IsUndefined(data->j_file_proxy_creator))
75
- JS_FreeValue(data->context, data->j_file_proxy_creator);
95
+ if (!data->disposed)
96
+ {
97
+ if (!JS_IsUndefined(data->j_file_proxy_creator))
98
+ JS_FreeValue(data->context, data->j_file_proxy_creator);
76
99
 
77
- JSRuntime *runtime = JS_GetRuntime(data->context);
78
- JS_SetInterruptHandler(runtime, NULL, NULL);
79
- js_std_free_handlers(runtime);
80
- JS_FreeContext(data->context);
81
- JS_FreeRuntime(runtime);
100
+ vm_teardown_context(data->context);
101
+ }
82
102
 
83
103
  xfree(ptr);
84
104
  }
@@ -95,6 +115,9 @@ static void vm_mark(void *ptr)
95
115
  rb_gc_mark_movable(data->log_listener);
96
116
  rb_gc_mark_movable(data->alive_objects);
97
117
  rb_gc_mark_movable(data->module_loader);
118
+ rb_gc_mark_movable(data->on_unhandled_rejection);
119
+ rb_gc_mark_movable(data->module_resolution_cache);
120
+ rb_gc_mark_movable(data->module_source_cache);
98
121
  }
99
122
 
100
123
  static void vm_compact(void *ptr)
@@ -104,6 +127,9 @@ static void vm_compact(void *ptr)
104
127
  data->log_listener = rb_gc_location(data->log_listener);
105
128
  data->alive_objects = rb_gc_location(data->alive_objects);
106
129
  data->module_loader = rb_gc_location(data->module_loader);
130
+ data->on_unhandled_rejection = rb_gc_location(data->on_unhandled_rejection);
131
+ data->module_resolution_cache = rb_gc_location(data->module_resolution_cache);
132
+ data->module_source_cache = rb_gc_location(data->module_source_cache);
107
133
  }
108
134
 
109
135
  static const rb_data_type_t vm_type = {
@@ -137,8 +163,12 @@ static VALUE vm_alloc(VALUE r_self)
137
163
  data->log_listener = Qnil;
138
164
  data->alive_objects = rb_hash_new();
139
165
  data->module_loader = Qnil;
166
+ data->on_unhandled_rejection = Qnil;
167
+ data->module_resolution_cache = rb_hash_new();
168
+ data->module_source_cache = rb_hash_new();
140
169
  data->j_file_proxy_creator = JS_UNDEFINED;
141
170
  data->oom_poisoned = false;
171
+ data->disposed = false;
142
172
 
143
173
  EvalTime *eval_time = malloc(sizeof(EvalTime));
144
174
  data->eval_time = eval_time;