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

src: log warning on process.binding('natives') #2741

Closed

Conversation

bnoordhuis
Copy link
Member

This is used by old versions of graceful-fs but will stop working in the
not too distant future. Print a warning so people know to upgrade.

CI: https://ci.nodejs.org/job/node-test-pull-request/268/

// graceful-fs < 4 evals process.binding('natives').fs, which prohibits
// using internal modules in that module. Encourage people to upgrade.
fprintf(stderr, "(node) process.binding('natives') is deprecated.\n");
fprintf(stderr, "(node) If you use graceful-fs < 4, please update.\n");
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we really say this in the warning?

Copy link
Member Author

Choose a reason for hiding this comment

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

It's the sole reason for this PR.

Copy link
Contributor

Choose a reason for hiding this comment

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

We don't know if other modules do the same. Why should we care only about graceful-fs?

Copy link
Member Author

Choose a reason for hiding this comment

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

Because it's probably the most used offender. The only other projects I could find with Github's (admittedly terrible) code search is an sys / util shim (which does seem to get copied around a lot, there's that.)

Copy link
Member

Choose a reason for hiding this comment

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

While I dislike calling out a specific module here, graceful-fs is really heavily used and is causing specific problems here. Perhaps the compromise is to leave the note in but put a //TODO: Remove by v6 or similar in there just to mark it as a temporary message?

Copy link
Member

Choose a reason for hiding this comment

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

+1 @rvagg

@brycebaril
Copy link
Contributor

graceful-fs is likely the most-common but definitely not the only thing:

http://searchnod.es/#!binding(%22natives%22)/1

node::Utf8Value name(env->isolate(), frame->GetScriptName());
fprintf(stderr, "(node) at %s:%d\n", *name, frame->GetLineNumber());
}
fflush(stderr);
Copy link
Contributor

Choose a reason for hiding this comment

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

stderr is not buffered right? Should we really flush it?

Copy link
Member Author

Choose a reason for hiding this comment

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

libc I/O can be buffered, that's why the fflush() is there.

@mscdex mscdex added the c++ Issues and PRs that require attention from people who are familiar with C++. label Sep 8, 2015
@brendanashworth
Copy link
Contributor

This kind of kicks the can down the road with process.binding, right? Is there any feasible way we can do this with internal modules?

@vkurchatkin
Copy link
Contributor

I have an idea how we can deprecate public access to process.binding

@bnoordhuis
Copy link
Member Author

For background, the reason for this PR is that I want to pre-compile our JS code using the V8 extras infrastructure. At that point process.binding('natives') can be removed if it weren't for modules like graceful-fs.

@Fishrock123
Copy link
Contributor

I think I'm ok with this. Making guarantees about our source being exposed at run-time is a ludicrous idea.

@jasnell
Copy link
Member

jasnell commented Sep 25, 2015

LGTM.

@bnoordhuis
Copy link
Member Author

Thanks @jasnell. I plan to merge this early next week so if anyone has strong feelings, now is the time to speak up.

@Fishrock123
Copy link
Contributor

I have strong feelings about this being a good idea. 👍

@vkurchatkin
Copy link
Contributor

@bnoordhuis I propose to use #2768 for this. It's not necessary to deprecate whole process.binding right away, but we can use introduced hooks to deprecate natives in javascript. Also someone could just replace natives with $natives to suppress warning. This is not possible with #2768

@bnoordhuis
Copy link
Member Author

Fine by me, as long as it gets done. Closing.

@ChALkeR
Copy link
Member

ChALkeR commented Aug 24, 2016

@bnoordhuis It looks like it was actually never done, and #2768 was closed a few days ago.

Perhaps we should reopen this?

@bnoordhuis bnoordhuis reopened this Aug 25, 2016
@jasnell
Copy link
Member

jasnell commented Aug 25, 2016

If this goes forward it should be updated to make use of the emitWarning() API.

This is used by old versions of graceful-fs but will stop working in
the not too distant future.  Print a warning so people know to upgrade.
@bnoordhuis bnoordhuis force-pushed the warn-on-process-binding-natives branch from 6eab98e to 35a62c5 Compare August 25, 2016 19:22
@bnoordhuis
Copy link
Member Author

Rebased. Added a second commit that takes a different approach: check if the topmost JS frame is a builtin script.

If this goes forward it should be updated to make use of the emitWarning() API.

Why? We don't do that for other warnings in C++ code either.

fprintf(stderr,
"(node:%d) process.binding('natives') is deprecated.\n", pid);
fprintf(stderr,
"(node:%d) If you use graceful-fs < 4, please update.\n", pid);
Copy link
Member

@ChALkeR ChALkeR Aug 25, 2016

Choose a reason for hiding this comment

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

Do recent versions of graceful-fs@3 still trigger this? It was updated just recently.
Update: they do, I verified that.

Copy link
Member

Choose a reason for hiding this comment

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

Another question: do we need to specifically note graceful-fs here? It's not the only package that uses process.binding('natives'), and that could lead people away from the actual issue.

Copy link
Member Author

Choose a reason for hiding this comment

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

Flashback: #2741 (comment)

Copy link
Member

@ChALkeR ChALkeR Aug 25, 2016

Choose a reason for hiding this comment

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

@bnoordhuis yes, but see the list at #2741 (comment), that wasn't considered back then.

Also, graceful-fs@2 and graceful-fs@3 usage significantly decreased in past months.

Copy link
Member Author

Choose a reason for hiding this comment

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

I guess I could check if the caller is graceful-fs and customize the error based on that but meh. I have to be selective with my time in the next few weeks so I'm probably not going to expend too much effort on this PR.

Copy link
Member

Choose a reason for hiding this comment

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

If you don't have the time to work on it, I am willing to take it over.

@jasnell
Copy link
Member

jasnell commented Aug 25, 2016

Why? We don't do that for other warnings in C++ code either.

So that it can be consistently handled as a runtime deprecation just like any other deprecation warning we print. As illustrated by #8270, it's pretty trivial and has the built-in benefit of working with --throw-deprecation.

Update ... for instance, with the patch as it is currently:

$ ./node --throw-deprecation
> const n = process.binding('natives')
(node:39039) process.binding('natives') is deprecated.
(node:39039) If you use graceful-fs < 4, please update.
(node:39039)    at repl:1
(node:39039)    at vm.js:22
(node:39039)    at vm.js:96
(node:39039)    at vm.js:21
(node:39039)    at repl.js:313
(node:39039)    at domain.js:280
(node:39039)    at domain.js:293
(node:39039)    at repl.js:504
(node:39039)    at events.js:101
(node:39039)    at events.js:188
(node:39039)    at readline.js:232
(node:39039)    at readline.js:572
undefined
>

Using emitWarning(), the warning would obey the --trace-deprecation and --throw-deprecation command line flags without any additional effort, and this PR could be simplified (without the extraneous (node:pid} outputs as well.

@ChALkeR
Copy link
Member

ChALkeR commented Aug 25, 2016

I found 268 lines in 147 packages using process.binding('natives'): https://gist.github.com/ChALkeR/d8c9ff68869a1d86a3d702ce5c6d3a0a.

  • 103 lines of that are require(process.binding('natives').util ? 'util' : 'sys') with syntaxical differences.
  • 32 lines of the remaining are inside tests.
  • Without that — there are 133 files in 114 packages.

auto caller_script_id = GetCallerScriptId(env->isolate());
if (!IsInternalScriptId(env, caller_script_id)) {
// graceful-fs < 4 evals process.binding('natives').fs, which prohibits
// using internal modules in that module. Encourage people to upgrade.
Copy link
Member

@ChALkeR ChALkeR Aug 25, 2016

Choose a reason for hiding this comment

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

which prohibits using internal modules in that module.

This is not accurate any more, they evaded that, and it now reevalutes internal modules with more dark magic, internal API usage, and relying on implementation details.

@bnoordhuis
Copy link
Member Author

Is this intentional?

Yes. Please be specific if you think there is something unintentional in there.

@ChALkeR
Copy link
Member

ChALkeR commented Aug 25, 2016

@bnoordhuis Ok, I meant that the warning looks like too heavy to me, and most of those is cosumed by lines that do not bring much value (i.e. at module.js:…).

@ChALkeR
Copy link
Member

ChALkeR commented Aug 25, 2016

Btw, one more thing: 4 packages actually assign to process.binding('natives')[something], and they succeed in that. That happens inside tests only, though.

Could we stop that, like now, without waiting for a whole major release cycle? This shouldn't get misused even more.

@vkurchatkin
Copy link
Contributor

Could we stop that, like now, without waiting for a whole major release cycle?

That would be nice, making props non-writable and non-configurable should be enough

@jasnell
Copy link
Member

jasnell commented Aug 25, 2016

Could we stop that

+1 ... especially if we know we can do it without breaking non-test code.

@bnoordhuis
Copy link
Member Author

I meant that the warning looks like too heavy to me, and most of those is cosumed by lines that do not bring much value (i.e. at module.js:…).

I added the stack trace based on prior experience that if you don't, people are going to complain it's impossible to find out what is causing the warning.

@ChALkeR
Copy link
Member

ChALkeR commented Aug 25, 2016

I added the stack trace based on prior experience that if you don't, people are going to complain it's impossible to find out what is causing the warning.

Makes sense. But could we strip out lines that match \s(internal/)?module\.js:? Those are pointing to internal files, if I understand things correctly.

@bnoordhuis
Copy link
Member Author

Added a commit that does that (but in a better way than pattern matching strings.)

@ChALkeR
Copy link
Member

ChALkeR commented Aug 26, 2016

@bnoordhuis Thanks!

Upd: yes, the warning looks good now.

@ChALkeR
Copy link
Member

ChALkeR commented Aug 26, 2016

@bnoordhuis Sorry, I have another warning message stylistic question. How much extra code would it be to print the If you use graceful-fs < 4, please update. line only for those cases where graceful-fs is present in the backtrace? That would remove possible confusion for those users that get this warning for reasons other than graceful-fs.

Upd: e.g. webpack does that on it's own, without graceful-fs. I can't guarantee that that exact code is commonly triggered, but webpack has almost 2 millon downloads per month. It's not an argument against this PR (the fix for webpack is straightforward), it's an argument for not confusing those users with graceful-fs specific mesages.

Btw — is this semver-patch or semver-major?

@jasnell
Copy link
Member

jasnell commented Aug 26, 2016

I'm -1 on this as is given that it is printed as a deprecation but does not properly follow the --trace-deprecation and --throw-deprecation command line flags. The behavior is inconsistent when it simply needn't be.

@ChALkeR
Copy link
Member

ChALkeR commented Aug 26, 2016

@jasnell, would you change your mind if this would follow the command-line flags?

@jasnell
Copy link
Member

jasnell commented Aug 26, 2016

Yep... see #2741 (comment)

@jasnell
Copy link
Member

jasnell commented Aug 26, 2016

However, please keep in mind that the new fix for graceful-fs uses the natives module which uses process.binding('natives'), which is what has allowed us to get past the fs re-evaluation issue.

@ChALkeR
Copy link
Member

ChALkeR commented Aug 26, 2016

@jasnell, older graceful-fs@3 versions used process.binding('natives') likewise, nothing has changed on that part. Btw, graceful-fs@4 should be fine, and most users have already upgraded to that.

@jasnell
Copy link
Member

jasnell commented Aug 26, 2016

Yep, just wanted to make sure it was noted.

@bnoordhuis
Copy link
Member Author

I'm -1 on this as is given that it is printed as a deprecation but does not properly follow the --trace-deprecation and --throw-deprecation command line flags. The behavior is inconsistent when it simply needn't be.

The JS API has no way to do the internal stack frame filtering that @ChALkeR requested, and besides, other deprecation warnings from C++ (e.g. deprecated Template::Set usage) don't use it either.

I could argue the PR in its current shape is more consistent with existing practices than it would be if I included your suggestion.

@jasnell
Copy link
Member

jasnell commented Aug 27, 2016

At the very least --throw-deprecation and --trace-deprecation should be supported here in order for it to be a proper runtime deprecation... regardless of whether it uses emitWarning().

@jasnell jasnell added the semver-major PRs that contain breaking changes and should be released in the next major version. label Aug 27, 2016
@ChALkeR
Copy link
Member

ChALkeR commented Aug 27, 2016

@bnoordhuis

The JS API has no way to do the internal stack frame filtering that @ChALkeR requested

Just a note: I would be fine with not filtering if printing the trace would be behind a flag. I don't have any specific opinion on printing from js vs printing from the C++ side here at the moment, though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++ Issues and PRs that require attention from people who are familiar with C++. semver-major PRs that contain breaking changes and should be released in the next major version.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants