-
Notifications
You must be signed in to change notification settings - Fork 30.7k
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
deps,lib,src: remove dependency on --allow-natives-syntax #20719
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,18 +30,12 @@ const { | |
const { TextDecoder, TextEncoder } = require('internal/encoding'); | ||
const { isBuffer } = require('buffer').Buffer; | ||
|
||
const { | ||
previewMapIterator, | ||
previewSetIterator, | ||
previewWeakMap, | ||
previewWeakSet | ||
} = require('internal/v8'); | ||
|
||
const { | ||
getPromiseDetails, | ||
getProxyDetails, | ||
kPending, | ||
kRejected, | ||
previewEntries | ||
} = process.binding('util'); | ||
|
||
const { internalBinding } = require('internal/bootstrap/loaders'); | ||
|
@@ -915,7 +909,7 @@ function formatMap(ctx, value, recurseTimes, keys) { | |
|
||
function formatWeakSet(ctx, value, recurseTimes, keys) { | ||
const maxArrayLength = Math.max(ctx.maxArrayLength, 0); | ||
const entries = previewWeakSet(value, maxArrayLength + 1); | ||
const entries = previewEntries(value).slice(0, maxArrayLength + 1); | ||
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. This is pretty bad for performance. The same for the other parts. 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. Yeah, especially the lack of a limit is a bit “:confused:”, but on the other hand I don’t think any of these would typically be hot paths. (In particular, I don’t think we need to make |
||
const maxLength = Math.min(maxArrayLength, entries.length); | ||
let output = new Array(maxLength); | ||
for (var i = 0; i < maxLength; ++i) | ||
|
@@ -932,16 +926,14 @@ function formatWeakSet(ctx, value, recurseTimes, keys) { | |
|
||
function formatWeakMap(ctx, value, recurseTimes, keys) { | ||
const maxArrayLength = Math.max(ctx.maxArrayLength, 0); | ||
const entries = previewWeakMap(value, maxArrayLength + 1); | ||
// Entries exist as [key1, val1, key2, val2, ...] | ||
const remainder = entries.length / 2 > maxArrayLength; | ||
const len = entries.length / 2 - (remainder ? 1 : 0); | ||
const entries = previewEntries(value).slice(0, maxArrayLength + 1); | ||
const remainder = entries.length > maxArrayLength; | ||
const len = entries.length - (remainder ? 1 : 0); | ||
const maxLength = Math.min(maxArrayLength, len); | ||
let output = new Array(maxLength); | ||
for (var i = 0; i < len; i++) { | ||
const pos = i * 2; | ||
output[i] = `${formatValue(ctx, entries[pos], recurseTimes)} => ` + | ||
formatValue(ctx, entries[pos + 1], recurseTimes); | ||
output[i] = `${formatValue(ctx, entries[i][0], recurseTimes)} => ` + | ||
formatValue(ctx, entries[i][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). | ||
|
@@ -953,9 +945,9 @@ function formatWeakMap(ctx, value, recurseTimes, keys) { | |
return output; | ||
} | ||
|
||
function formatCollectionIterator(preview, ctx, value, recurseTimes, keys) { | ||
function formatCollectionIterator(ctx, value, recurseTimes, keys) { | ||
const output = []; | ||
for (const entry of preview(value)) { | ||
for (const entry of previewEntries(value)) { | ||
if (ctx.maxArrayLength === output.length) { | ||
output.push('... more items'); | ||
break; | ||
|
@@ -969,13 +961,11 @@ function formatCollectionIterator(preview, ctx, value, recurseTimes, keys) { | |
} | ||
|
||
function formatMapIterator(ctx, value, recurseTimes, keys) { | ||
return formatCollectionIterator(previewMapIterator, ctx, value, recurseTimes, | ||
keys); | ||
return formatCollectionIterator(ctx, value, recurseTimes, keys); | ||
} | ||
|
||
function formatSetIterator(ctx, value, recurseTimes, keys) { | ||
return formatCollectionIterator(previewSetIterator, ctx, value, recurseTimes, | ||
keys); | ||
return formatCollectionIterator(ctx, value, recurseTimes, keys); | ||
} | ||
|
||
function formatPromise(ctx, value, recurseTimes, keys) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -49,6 +49,35 @@ static void GetProxyDetails(const FunctionCallbackInfo<Value>& args) { | |
args.GetReturnValue().Set(ret); | ||
} | ||
|
||
static void PreviewEntries(const FunctionCallbackInfo<Value>& args) { | ||
if (!args[0]->IsObject()) | ||
return; | ||
|
||
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); | ||
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. This check should actually be obsolete. We should realize it one way or the other if the V8 implementation is broken. 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. Right now, if there’s a single extra element at the end, we wouldn’t notice that. Like, yes, obviously that would be a bug in V8, but I don’t think there’s much harm in the extra check? 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 should notice it because this code will only run in case we have a test for this code path and in those tests we actually strictly check the outcome. |
||
|
||
Environment* env = Environment::GetCurrent(args); | ||
Local<Context> context = env->context(); | ||
|
||
Local<Array> pairs = Array::New(env->isolate(), length / 2); | ||
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. do we know the speed impact of this loop being in js vs c++? 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. @devsnek At least I don’t, but I guess the answer is that doing it in JS is a bit faster. But if we’re looking for optimizations, avoiding the 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. Thinking about it: that would not be complicated. It was actually implemented in See https://github.com/nodejs/node/pull/20719/files#diff-3deb3f32958bb937ae05c6f3e4abbdf5L938 for the former implementation. It does not seem to be much difference using this approach, especially since the C++ function here would be smaller. 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. That’s definitely a place where it’s easy to switch – but all other uses expected the array-of-tuples layout.
Yeah, I’d like that as well. Not as a blocker for this PR, though – you can feel freel to hack on this yourself, if you have concrete ideas about how this is going to look in the end? |
||
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); | ||
} | ||
|
||
// Side effect-free stringification that will never throw exceptions. | ||
static void SafeToString(const FunctionCallbackInfo<Value>& args) { | ||
auto context = args.GetIsolate()->GetCurrentContext(); | ||
|
@@ -188,6 +217,7 @@ void Initialize(Local<Object> target, | |
env->SetMethod(target, "getPromiseDetails", GetPromiseDetails); | ||
env->SetMethod(target, "getProxyDetails", GetProxyDetails); | ||
env->SetMethod(target, "safeToString", SafeToString); | ||
env->SetMethod(target, "previewEntries", PreviewEntries); | ||
|
||
env->SetMethod(target, "startSigintWatchdog", StartSigintWatchdog); | ||
env->SetMethod(target, "stopSigintWatchdog", StopSigintWatchdog); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,14 +19,13 @@ | |
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE | ||
// USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
|
||
// Flags: --expose_internals | ||
'use strict'; | ||
const common = require('../common'); | ||
const assert = require('assert'); | ||
const JSStream = process.binding('js_stream').JSStream; | ||
const util = require('util'); | ||
const vm = require('vm'); | ||
const { previewMapIterator } = require('internal/v8'); | ||
const { previewEntries } = process.binding('util'); | ||
|
||
assert.strictEqual(util.inspect(1), '1'); | ||
assert.strictEqual(util.inspect(false), 'false'); | ||
|
@@ -448,7 +447,7 @@ assert.strictEqual(util.inspect(-5e-324), '-5e-324'); | |
{ | ||
const map = new Map(); | ||
map.set(1, 2); | ||
const vals = previewMapIterator(map.entries()); | ||
const vals = previewEntries(map.entries()); | ||
const valsOutput = []; | ||
for (const o of vals) { | ||
valsOutput.push(o); | ||
|
@@ -935,8 +934,7 @@ if (typeof Symbol !== 'undefined') { | |
const aSet = new Set([1, 3]); | ||
assert.strictEqual(util.inspect(aSet.keys()), '[Set Iterator] { 1, 3 }'); | ||
assert.strictEqual(util.inspect(aSet.values()), '[Set Iterator] { 1, 3 }'); | ||
assert.strictEqual(util.inspect(aSet.entries()), | ||
'[Set Iterator] { [ 1, 1 ], [ 3, 3 ] }'); | ||
assert.strictEqual(util.inspect(aSet.entries()), '[Set Iterator] { 1, 3 }'); | ||
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. @nodejs/tsc Would we consider this a semver-major change? I’d prefer not to. If we do, I’d probably want to adjust the V8 CL first. Edit: Would be cool to see as a quick poll: 👎 if you think it is semver-major, 👍 if you think this is fine as a patch change, 😕 if you don’t have an opinion 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 think this is more a kind of bugfix than a breaking change. |
||
// Make sure the iterator doesn't get consumed. | ||
const keys = aSet.keys(); | ||
assert.strictEqual(util.inspect(keys), '[Set Iterator] { 1, 3 }'); | ||
|
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.
can we put them on an internalBinding instead?
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.
Any concrete preferences? The most stable part of
process.binding('util')
(type checking) is runtime-deprecated in Node 10, so we might be able to move the entire util binding tointernalBinding('util')
in Node 11 anyway…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.
whatever gets it done is fine with me, i just want to see process.binding stop existing :)