Skip to content

Commit 2ad7d82

Browse files
Patrick Soquetmkellner
authored andcommitted
XS: do not enumerate deleted properties
1 parent fd0520c commit 2ad7d82

File tree

1 file changed

+72
-67
lines changed

1 file changed

+72
-67
lines changed

xs/sources/xsGlobal.c

Lines changed: 72 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -278,10 +278,8 @@ void fx_Enumerator(txMachine* the)
278278
txSlot* iterator;
279279
txSlot* result;
280280
txSlot* slot;
281-
txSlot* list;
282-
txSlot* item;
283-
txSlot* instance;
284-
txSlot** address;
281+
txSlot* keys;
282+
txSlot* visited;
285283

286284
mxPush(mxEnumeratorFunction);
287285
fxGetID(the, mxID(_prototype));
@@ -293,78 +291,85 @@ void fx_Enumerator(txMachine* the)
293291
slot = fxNextBooleanProperty(the, slot, 0, mxID(_done), XS_DONT_DELETE_FLAG | XS_DONT_SET_FLAG);
294292
slot = fxNextSlotProperty(the, iterator, the->stack, mxID(_result), XS_GET_ONLY);
295293
mxPop();
296-
list = slot->next = fxNewSlot(the);
297-
list->flag = XS_GET_ONLY;
298-
list->ID = mxID(_iterable);
299-
list->kind = mxThis->kind;
300-
list->value = mxThis->value;
301-
if (!mxIsReference(list))
302-
return;
303-
instance = list->value.reference;
304-
item = list;
305-
mxPushUndefined();
306-
result = the->stack;
307-
for (;;) {
308-
txSlot* at = fxNewInstance(the);
309-
mxBehaviorOwnKeys(the, instance, XS_EACH_NAME_FLAG, at);
310-
address = &at->next;
311-
while ((at = *address)) {
312-
if (mxBehaviorGetOwnProperty(the, instance, at->value.at.id, at->value.at.index, result)) {
313-
slot = list->next;
314-
while ((slot)) {
315-
if ((at->value.at.id == slot->value.at.id) && (at->value.at.index == slot->value.at.index))
316-
break;
317-
slot = slot->next;
318-
}
319-
if (slot)
320-
address = &(at->next);
321-
else {
322-
*address = at->next;
323-
item = item->next = at;
324-
item->next = C_NULL;
325-
item->flag = result->flag;
326-
}
327-
}
328-
else
329-
address = &(at->next);
330-
}
331-
mxPop();
332-
if (mxBehaviorGetPrototype(the, instance, result))
333-
instance = result->value.reference;
334-
else
335-
break;
336-
}
294+
295+
slot = slot->next = fxNewSlot(the);
296+
slot->flag = XS_GET_ONLY;
297+
slot->ID = mxID(_iterable);
298+
slot->kind = mxThis->kind;
299+
slot->value = mxThis->value;
300+
if (!mxIsReference(slot))
301+
return;
302+
303+
keys = fxNewInstance(the);
304+
mxBehaviorOwnKeys(the, slot->value.reference, XS_EACH_NAME_FLAG, keys);
305+
slot = slot->next = fxNewSlot(the);
306+
slot->flag = XS_GET_ONLY;
307+
slot->kind = XS_REFERENCE_KIND;
308+
slot->value.reference = keys;
309+
mxPop();
310+
311+
visited = fxNewInstance(the);
312+
slot = slot->next = fxNewSlot(the);
313+
slot->flag = XS_GET_ONLY;
314+
slot->kind = XS_REFERENCE_KIND;
315+
slot->value.reference = visited;
337316
mxPop();
338-
address = &list->next;
339-
while ((slot = *address)) {
340-
if (slot->flag & XS_DONT_ENUM_FLAG) {
341-
*address = slot->next;
342-
}
343-
else {
344-
txID id = slot->value.at.id;
345-
txIndex index = slot->value.at.index;
346-
fxKeyAt(the, id, index, slot);
347-
address = &(slot->next);
348-
}
349-
}
350317
}
351318

352319
void fx_Enumerator_next(txMachine* the)
353320
{
354321
txSlot* iterator = fxGetInstance(the, mxThis);
355322
txSlot* result = iterator->next;
356323
txSlot* iterable = result->next;
357-
txSlot* index = iterable->next;
358-
txSlot* value = result->value.reference->next;
359-
txSlot* done = value->next;
360-
if (index) {
361-
value->kind = index->kind;
362-
value->value = index->value;
363-
iterable->next = index->next;
324+
txSlot* at = C_NULL;
325+
if (mxIsReference(iterable)) {
326+
txSlot* instance = iterable->value.reference;
327+
txSlot* keys = iterable->next;
328+
txSlot* visited = keys->next;
329+
txSlot* slot;
330+
txSlot* former;
331+
332+
keys = keys->value.reference;
333+
visited = visited->value.reference;
334+
335+
mxPushUndefined();
336+
slot = the->stack;
337+
again:
338+
while ((at = keys->next)) {
339+
if (mxBehaviorGetOwnProperty(the, instance, at->value.at.id, at->value.at.index, slot)) {
340+
txSlot** address = &(visited->next);
341+
while ((former = *address)) {
342+
if ((at->value.at.id == former->value.at.id) && (at->value.at.index == former->value.at.index))
343+
break;
344+
address = &(former->next);
345+
}
346+
if (!former) {
347+
*address = at;
348+
keys->next = at->next;
349+
at->next = NULL;
350+
if (!(slot->flag & XS_DONT_ENUM_FLAG)) {
351+
fxKeyAt(the, at->value.at.id, at->value.at.index, result->value.reference->next);
352+
break;
353+
}
354+
}
355+
else
356+
keys->next = at->next;
357+
}
358+
else
359+
keys->next = at->next;
360+
}
361+
if (!at) {
362+
if (mxBehaviorGetPrototype(the, instance, slot)) {
363+
iterable->value.reference = instance = slot->value.reference;
364+
mxBehaviorOwnKeys(the, instance, XS_EACH_NAME_FLAG, keys);
365+
goto again;
366+
}
367+
}
368+
mxPop();
364369
}
365-
else {
366-
value->kind = XS_UNDEFINED_KIND;
367-
done->value.boolean = 1;
370+
if (!at) {
371+
result->value.reference->next->kind = XS_UNDEFINED_KIND;
372+
result->value.reference->next->next->value.boolean = 1;
368373
}
369374
mxResult->kind = result->kind;
370375
mxResult->value = result->value;

0 commit comments

Comments
 (0)