Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

util: correctly inspect Map/Set Iterators #3119

Merged
merged 2 commits into from
Oct 6, 2015

Conversation

evanlucas
Copy link
Contributor

Currently, inspecting new Map().keys() or other iterators will return an empty object.

I am opening more for discussion of how we want (if at all) to address not being able to inspect map and set iterators. I first had first attempting using Debug.MakeMirror but the performance of doing it this way was about 10x better.

Related: #3107

@Fishrock123 Fishrock123 added the util Issues and PRs related to the built-in util module. label Sep 29, 2015
@@ -486,6 +494,16 @@ function formatMap(ctx, value, recurseTimes, visibleKeys, keys) {
return output;
}

function formatIterator(ctx, value, recurseTimes, visibleKeys, keys) {
var output = [];
for (let o of value) {
Copy link
Contributor

Choose a reason for hiding this comment

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

This will consume iterator entirely and make it useless

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For Maps and Sets?

Copy link
Contributor

Choose a reason for hiding this comment

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

If you print an iterator, python just prints the type of iterator. May be we should do the same. Otherwise we'll exhaust the iterator as vkurchatkin pointed out.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah yea, I see what you mean.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So I guess that means that we will have to use Debug.MakeMirror and fetch the values?

Copy link
Member

Choose a reason for hiding this comment

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

Yes.

static void IsMapOrSetIterator(const FunctionCallbackInfo<Value>& args) {
CHECK_EQ(1, args.Length());
args.GetReturnValue().Set(args[0]->IsSetIterator()
|| args[0]->IsMapIterator());
Copy link
Contributor

Choose a reason for hiding this comment

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

Style nit. Or operator should be in the previous line.

Copy link
Member

Choose a reason for hiding this comment

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

@thefourtheye Do we have an eslint rule for that, btw?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

make lint passes with both. Be happy to change if that is the preferred way though

static void IsMapOrSetIterator(const FunctionCallbackInfo<Value>& args) {
CHECK_EQ(1, args.Length());
args.GetReturnValue().Set(args[0]->IsSetIterator() ||
args[0]->IsMapIterator());
Copy link
Member

Choose a reason for hiding this comment

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

Doesn't it fit on one line? It works out to exactly 80 characters, doesn't it?

@evanlucas
Copy link
Contributor Author

Updated to use Debug.MakeMirror. It also takes advantage of using IteratorMirror.preview which does not change the backing iterator state.

@@ -486,6 +502,18 @@ function formatMap(ctx, value, recurseTimes, visibleKeys, keys) {
return output;
}

function formatCollectionIterator(ctx, value, recurseTimes, visibleKeys, keys) {
Debug = Debug || require('vm').runInDebugContext('Debug');
Copy link
Member

Choose a reason for hiding this comment

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

Can you rebase and use ensureDebugIsInitialized() here?

@evanlucas
Copy link
Contributor Author

Updated to utilize v8::Value::IsMapIterator and v8::Value::IsSetIterator

@@ -3,6 +3,7 @@
const uv = process.binding('uv');
const Buffer = require('buffer').Buffer;
const internalUtil = require('internal/util');
const Util = process.binding('util');
Copy link
Member

Choose a reason for hiding this comment

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

Can you name this binding? That's more in line with other source files.

@bnoordhuis
Copy link
Member

Mostly LGTM. I think the constructor.name === 'Array' check should come with regression tests of its own.

@evanlucas evanlucas force-pushed the iterators branch 3 times, most recently from 66169e3 to c7d7eab Compare October 5, 2015 21:38
@evanlucas
Copy link
Contributor Author

Alright, broke out the constructor.name === 'Array' check into it's own commit with a test. Is that single test sufficient or should I add more? Honestly, the only other way I've been able to reproduce it is from the map/set iterators

@evanlucas
Copy link
Contributor Author

@bnoordhuis
Copy link
Member

LGTM

In the event an Array is created in a Debug context, the constructor
will be Array, but !== Array. This adds a check
constructor.name === 'Array' to handle edge cases like that.

PR-URL: nodejs#3119
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Previously, a MapIterator or SetIterator would
not be inspected properly. This change makes it possible
to inspect them by creating a Debug Mirror and previewing
the iterators to not consume the actual iterator that
we are trying to inspect.

This change also adds a node_util binding that uses
v8's Value::IsSetIterator and Value::IsMapIterator
to verify that the values passed in are actual iterators.

Fixes: nodejs#3107
PR-URL: nodejs#3119
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
@evanlucas evanlucas closed this Oct 6, 2015
@evanlucas evanlucas deleted the iterators branch October 6, 2015 01:28
@evanlucas evanlucas merged commit 8853388 into nodejs:master Oct 6, 2015
@evanlucas
Copy link
Contributor Author

Thanks! Landed in 089d688 and 8853388

@jasnell jasnell mentioned this pull request Oct 8, 2015
29 tasks
evanlucas added a commit that referenced this pull request Oct 8, 2015
In the event an Array is created in a Debug context, the constructor
will be Array, but !== Array. This adds a check
constructor.name === 'Array' to handle edge cases like that.

PR-URL: #3119
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
evanlucas added a commit that referenced this pull request Oct 8, 2015
Previously, a MapIterator or SetIterator would
not be inspected properly. This change makes it possible
to inspect them by creating a Debug Mirror and previewing
the iterators to not consume the actual iterator that
we are trying to inspect.

This change also adds a node_util binding that uses
v8's Value::IsSetIterator and Value::IsMapIterator
to verify that the values passed in are actual iterators.

Fixes: #3107
PR-URL: #3119
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
util Issues and PRs related to the built-in util module.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants