Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 36.4k
console,util: avoid pair array generation in C++#20831
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
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -344,17 +344,26 @@ Console.prototype.table = function(tabularData, properties) { | ||
| const getIndexArray = (length) => ArrayFrom({ length }, (_, i) => inspect(i)); | ||
| const mapIter = isMapIterator(tabularData); | ||
| let isKeyValue = false; | ||
| if (mapIter) | ||
| tabularData = previewEntries(tabularData); | ||
| [ tabularData, isKeyValue ] = previewEntries(tabularData); | ||
| if (mapIter || isMap(tabularData)) { | ||
| if (isKeyValue || isMap(tabularData)) { | ||
| const keys = []; | ||
| const values = []; | ||
| let length = 0; | ||
| for (const [k, v] of tabularData) { | ||
| keys.push(inspect(k)); | ||
| values.push(inspect(v)); | ||
| length++; | ||
| if (mapIter) { | ||
| for (let i = 0; i < tabularData.length / 2; ++i) { | ||
| keys.push(inspect(tabularData[i * 2])); | ||
| values.push(inspect(tabularData[i * 2 + 1])); | ||
| length++; | ||
| } | ||
| } else { | ||
| for (const [k, v] of tabularData) { | ||
| keys.push(inspect(k)); | ||
| values.push(inspect(v)); | ||
| length++; | ||
| } | ||
| } | ||
| return final([ | ||
| iterKey, keyKey, valuesKey | ||
| @@ -367,9 +376,9 @@ Console.prototype.table = function(tabularData, properties) { | ||
| const setIter = isSetIterator(tabularData); | ||
| if (setIter) | ||
| tabularData = previewEntries(tabularData); | ||
| [ tabularData ] = previewEntries(tabularData); | ||
Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we make it | ||
| const setlike = setIter || isSet(tabularData); | ||
| const setlike = setIter || (mapIter && !isKeyValue) || isSet(tabularData); | ||
| ||
| if (setlike) { | ||
| const values = []; | ||
| let length = 0; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -906,7 +906,7 @@ function formatMap(ctx, value, recurseTimes, keys) { | ||
| function formatWeakSet(ctx, value, recurseTimes, keys) { | ||
| const maxArrayLength = Math.max(ctx.maxArrayLength, 0); | ||
| const entries = previewEntries(value).slice(0, maxArrayLength + 1); | ||
| const [ entries ] = previewEntries(value).slice(0, maxArrayLength + 1); | ||
| const maxLength = Math.min(maxArrayLength, entries.length); | ||
| let output = new Array(maxLength); | ||
| for (var i = 0; i < maxLength; ++i) | ||
| @@ -923,14 +923,16 @@ function formatWeakSet(ctx, value, recurseTimes, keys) { | ||
| function formatWeakMap(ctx, value, recurseTimes, keys) { | ||
| const maxArrayLength = Math.max(ctx.maxArrayLength, 0); | ||
| const entries = previewEntries(value).slice(0, maxArrayLength + 1); | ||
| const remainder = entries.length > maxArrayLength; | ||
| const len = entries.length - (remainder ? 1 : 0); | ||
| const [ entries ] = previewEntries(value).slice(0, (maxArrayLength + 1) * 2); | ||
Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: we don't usually put spaces inside of Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The slice is actually unnecessary overhead. The limitation is done below and this has no effect (there are just two entries returned). | ||
| // Entries exist as [key1, val1, key2, val2, ...] | ||
| const remainder = entries.length / 2 > maxArrayLength; | ||
| const len = entries.length / 2 - (remainder ? 1 : 0); | ||
| const maxLength = Math.min(maxArrayLength, len); | ||
| let output = new Array(maxLength); | ||
| for (var i = 0; i < len; i++) { | ||
| output[i] = `${formatValue(ctx, entries[i][0], recurseTimes)} => ` + | ||
| formatValue(ctx, entries[i][1], recurseTimes); | ||
| for (var i = 0; i < maxLength; i++) { | ||
| const pos = i * 2; | ||
| output[i] = `${formatValue(ctx, entries[pos], recurseTimes)} => ` + | ||
| formatValue(ctx, entries[pos + 1], recurseTimes); | ||
| } | ||
| // Sort all entries to have a halfway reliable output (if more entries than | ||
| // retrieved ones exist, we can not reliably return the same output). | ||
| @@ -942,9 +944,19 @@ function formatWeakMap(ctx, value, recurseTimes, keys) { | ||
| return output; | ||
| } | ||
| function zip2(list) { | ||
| const ret = Array(list.length / 2); | ||
| for (let i = 0; i < ret.length; ++i) | ||
| ret[i] = [list[2 * i], list[2 * i + 1]]; | ||
| return ret; | ||
| } | ||
Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could use the same pattern as in weak maps instead of first zipping this. This step is just overhead (even though the result is nicer to read). MemberAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, but it gets pretty tricky to do that, at least for me… we are passing the individual pair arrays to (Extreme edge case: Calling Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not sure in what way this should have any influence on the | ||
| function formatCollectionIterator(ctx, value, recurseTimes, keys) { | ||
| const output = []; | ||
| for (const entry of previewEntries(value)) { | ||
| let [ entries, isKeyValue ] = previewEntries(value); | ||
| if (isKeyValue) | ||
| entries = zip2(entries); | ||
| for (const entry of entries) { | ||
| if (ctx.maxArrayLength === output.length) { | ||
| output.push('... more items'); | ||
| break; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -53,29 +53,16 @@ static void PreviewEntries(const FunctionCallbackInfo<Value>& args) { | ||
| if (!args[0]->IsObject()) | ||
| return; | ||
| Environment* env = Environment::GetCurrent(args); | ||
| bool is_key_value; | ||
| Local<Array> entries; | ||
| if (!args[0].As<Object>()->PreviewEntries(&is_key_value).ToLocal(&entries)) | ||
| return; | ||
| if (!is_key_value) | ||
| return args.GetReturnValue().Set(entries); | ||
| uint32_t length = entries->Length(); | ||
| CHECK_EQ(length % 2, 0); | ||
| Environment* env = Environment::GetCurrent(args); | ||
| Local<Context> context = env->context(); | ||
| Local<Array> pairs = Array::New(env->isolate(), length / 2); | ||
| for (uint32_t i = 0; i < length / 2; i++) { | ||
| Local<Array> pair = Array::New(env->isolate(), 2); | ||
| pair->Set(context, 0, entries->Get(context, i * 2).ToLocalChecked()) | ||
| .FromJust(); | ||
| pair->Set(context, 1, entries->Get(context, i * 2 + 1).ToLocalChecked()) | ||
| .FromJust(); | ||
| pairs->Set(context, i, pair).FromJust(); | ||
| } | ||
| args.GetReturnValue().Set(pairs); | ||
| Local<Array> ret = Array::New(env->isolate(), 2); | ||
| ret->Set(env->context(), 0, entries).FromJust(); | ||
| ret->Set(env->context(), 1, v8::Boolean::New(env->isolate(), is_key_value)) | ||
| .FromJust(); | ||
| return args.GetReturnValue().Set(ret); | ||
Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We do not need the information about the key value pairs as we already have that when calling this function. The JS side has to be adjusted to the way it worked before to accomplish that. MemberAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Not for Map iterators, and I’m not aware of how we could know that in advance. Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The way this was done before in JS allowed this. We just pretty much have to revert the JS changes from the former PR. MemberAuthor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @BridgeAR Not really? When we had the V8 builtins available, we could only tell them apart because some Map iterators gave us pairs and others didn’t, but if we want to avoid pair creation, then we need this. Concrete example: This is necessary to distinguish
| ||
| } | ||
| // Side effect-free stringification that will never throw exceptions. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -447,13 +447,13 @@ assert.strictEqual(util.inspect(-5e-324), '-5e-324'); | ||
| { | ||
| const map = new Map(); | ||
| map.set(1, 2); | ||
| const vals = previewEntries(map.entries()); | ||
| const [ vals ] = previewEntries(map.entries()); | ||
Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might be a good idea for us to test | ||
| const valsOutput = []; | ||
| for (const o of vals) { | ||
| valsOutput.push(o); | ||
| } | ||
| assert.strictEqual(util.inspect(valsOutput), '[ [ 1, 2 ] ]'); | ||
| assert.strictEqual(util.inspect(valsOutput), '[ 1, 2 ]'); | ||
| } | ||
| // Test for other constructors in different context. | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The syntax makes me go 😬
Let's make it
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that leading semi isn't really node style, but i agree to brackets + wrapping in parens