Skip to content

Bug: DevTools calls arbitrary generators which may be stateful #19726

Closed
@gaearon

Description

@gaearon
function foo*() {
  yield 1;
  yield 2;
}

let gen = foo()

Currently if you put gen into state or props and then open this component in DevTools, it will consume that generator while trying to format it. So gen.next() will give you { done: true } next time you call it.

This happens here:

case 'iterator':
const name = data.constructor.name;
if (showFormattedValue) {
// TRICKY
// Don't use [...spread] syntax for this purpose.
// This project uses @babel/plugin-transform-spread in "loose" mode which only works with Array values.
// Other types (e.g. typed arrays, Sets) will not spread correctly.
const array = Array.from(data);

I think that maybe we should treat iterables differently if they return themselves as an iterator. Since that means they're likely stateful and it's not ok to iterate over them.

We detect iterables here (DevTools terminology is wrong btw, it should be iterable rather than iterator):

} else if (typeof data[Symbol.iterator] === 'function') {
return 'iterator';

I think maybe we could split this into iterable and opaque_iterable, and make sure none of the codepaths attempt to traverse opaque_iterable or pass it to something that would consume it (e.g. Array.from).

We could detect it based on data[Symbol.iterator]() === data — that clearly signals the iterable is its own iterator (which is the case for generators), and therefore it's not OK for DevTools to consume it.

Maybe some other heuristic could work. But overall, the goal is that Map and friends is still being iterated over, but an arbitrary generator is not.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions