Skip to content
This repository has been archived by the owner on Jan 25, 2022. It is now read-only.

Editorial: Fix another IterableWeakMap leak #216

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

ExE-Boss
Copy link

@ExE-Boss ExE-Boss commented Jan 10, 2021

Fixes: #213

This would cause the #refSet to possibly contain dead references and lead to a key/value pair being yielded multiple times.

const m = new IterableWeakMap();
const a = { [Symbol.toStringTag]: "A" };
const b = { [Symbol.toStringTag]: "B" };
m.set(a, 1);
m.set(b, 2);
m.set(a, 3);

for (const { 0: key, 1: value } of m) {
	// This would previously log:
	// [object A] 3
	// [object B] 2
	// [object A] 3
	console.log(key, value);
}

It also applies some fixes so that new IterableWeakMap() doesn’t throw a TypeError, because undefined is not iterable and makes IterableWeakMap.length === WeakMap.length.

Comment on lines +246 to 252
constructor(iterable = null) {
if (iterable !== null) {
for (const { 0: key, 1: value } of iterable) {
this.set(key, value);
}
}
}
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using object destructuring approximates the AddEntriesFromIterable abstract operation more closely.

Comment on lines 303 to 313
*keys() {
for (const [key, value] of this) {
for (const { 0: key } of this) {
yield key;
}
}

*values() {
for (const [key, value] of this) {
for (const { 1: value } of this) {
yield value;
}
}
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using object destructuring doesn’t require an inner iteration of the key/value pair.

this.set(key, value);
constructor(iterable = null) {
if (iterable !== null) {
for (const { 0: key, 1: value } of iterable) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if leaks are a concern, for..of is not an available option. Perhaps Array.from()?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the constructor, Array.from is no different when it comes to iterables.


Also, if it’s invoked as:

new IterableWeakMap([[a, 1], [b, 2]])

then that’s no different from:

new WeakMap([[a, 1], [b, 2]])

which also performs for...of‑like iteration

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On arraylikes, Array.from doesn’t invoke the iterator protocol, so it’s actually robust for the common case.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ljharb
Array.from prefers using the iterator protocol: https://tc39.es/ecma262/#sec-array.from

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, you’re right, i was thinking only of a missing Symbol.iterator i suppose.

in that case there’s no pragmatic way to use a robust iteration mechanism in the readme (altho https://npmjs.com/iterate-value does exist) so this can be resolved.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Iterable WeakMap implementation in README is incorrect?
2 participants