mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-11-08 08:44:37 +08:00
Release path module members through the object core's accessors
The exit-time cleanup of the path module objects swapped each member value out of the object's storage by reading v.obj.slots and v.obj.entries directly. It now goes through scr_dyn_obj_count and a new scr_dyn.h accessor, scr_dyn_obj_exchange_value_at, which stores a value at an index without reading the keys, so the cleanup still runs after the exit-time layout reset.
This commit is contained in:
@@ -770,6 +770,17 @@ static inline __attribute__((always_inline)) ScrDynProp scr_dyn_obj_prop_at(cons
|
||||
e->accessor, e->writable, e->enumerable, e->configurable};
|
||||
}
|
||||
|
||||
/* Stores `value` (moved) as the value of data property i and returns the
|
||||
* previous value (owned by the caller). Reads no keys and does not follow
|
||||
* the layout pointer, so exit-time teardown can use it after the layouts
|
||||
* are freed. */
|
||||
static inline ScrDyn *scr_dyn_obj_exchange_value_at(ScrDyn *o, size_t i, ScrDyn *value) {
|
||||
ScrDyn **slot = o->v.obj.layout ? &o->v.obj.slots[i] : &o->v.obj.entries[i].value;
|
||||
ScrDyn *previous = *slot;
|
||||
*slot = value;
|
||||
return previous;
|
||||
}
|
||||
|
||||
/* The index of own property `key`, or SIZE_MAX. A linear scan in
|
||||
* dictionary mode: for code that looks up options and headers, not for hot
|
||||
* property reads. */
|
||||
|
||||
@@ -368,18 +368,14 @@ static void scr_builtin_release(void *handle) {
|
||||
static void scr_builtin_cleanup(void) {
|
||||
/* An exports object can hold itself and the other path family
|
||||
* (path.posix.posix, path.posix.win32): its member values are released
|
||||
* first, so the objects are freed. The values are swapped out of the
|
||||
* object's own storage, without reading its keys: the exit-time layout
|
||||
* first, so the objects are freed. The values are swapped out without
|
||||
* reading the keys (scr_dyn_obj_exchange_value_at): the exit-time layout
|
||||
* reset can run before this and free the layout the keys live in. */
|
||||
for (ScrBuiltinModule *module = scr_builtin_modules; module; module = module->next) {
|
||||
if (!module->object) continue;
|
||||
ScrDyn *exports = module->exports;
|
||||
for (size_t i = 0; i < exports->v.obj.len; i++) {
|
||||
ScrDyn **slot = exports->v.obj.layout ? &exports->v.obj.slots[i] : &exports->v.obj.entries[i].value;
|
||||
ScrDyn *value = *slot;
|
||||
*slot = scr_dyn_retain(scr_dyn_undefined());
|
||||
scr_dyn_release(value);
|
||||
}
|
||||
for (size_t i = 0; i < scr_dyn_obj_count(exports); i++)
|
||||
scr_dyn_release(scr_dyn_obj_exchange_value_at(exports, i, scr_dyn_retain(scr_dyn_undefined())));
|
||||
}
|
||||
while (scr_builtin_modules) {
|
||||
ScrBuiltinModule *module = scr_builtin_modules;
|
||||
|
||||
Reference in New Issue
Block a user