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

repl: fix declaring a variable with the name util #38141

Merged

Conversation

EladKeyshawn
Copy link

@EladKeyshawn EladKeyshawn commented Apr 7, 2021

Fixes: #38139

@nodejs-github-bot nodejs-github-bot added needs-ci PRs that need a full CI run. repl Issues and PRs related to the REPL subsystem. labels Apr 7, 2021
@EladKeyshawn
Copy link
Author

From issue #38139

Copy link
Contributor

@aduh95 aduh95 left a comment

Choose a reason for hiding this comment

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

Hi! Thanks for sending the PR. Would it be possible to add tests to make sure this is fixing the issue?

lib/internal/repl/utils.js Outdated Show resolved Hide resolved
@EladKeyshawn
Copy link
Author

@aduh95 I'll try to do it thanks

@EladKeyshawn
Copy link
Author

Hi! Thanks for sending the PR. Would it be possible to add tests to make sure this is fixing the issue?

How would you suggest to test this? run the same commands and check no error is printed to screen OR do more of unit test to the specific preview function?

@aduh95
Copy link
Contributor

aduh95 commented Apr 9, 2021

You can add a test case in test/parallel/test-repl-history-navigation.js:

  {
    env: { NODE_REPL_HISTORY: defaultHistoryPath },
    test: [ 'const util = {}', ENTER,
            'ut', RIGHT, ENTER],
    expected: [],
    clean: false
  },

You need to also add a line to make sure the warning is gone at the top of the file:

process.on('warning', common.mustNotCall());

Make sure this fails on current Node.js version, and passes with your PR:

$ ./tools/test.py test/parallel/test-repl-history-navigation.js
[00:00|% 100|+   1|-   0]: Done
$ node test/parallel/test-repl-history-navigation.js || echo 'All good, we expect this to fail'
All good, we expect this to fail

@EladKeyshawn
Copy link
Author

EladKeyshawn commented Apr 9, 2021

You can add a test case in test/parallel/test-repl-history-navigation.js:

  {
    env: { NODE_REPL_HISTORY: defaultHistoryPath },
    test: [ 'const util = {}', ENTER,
            'ut', RIGHT, ENTER],
    expected: [],
    clean: false
  },

You need to also add a line to make sure the warning is gone at the top of the file:

process.on('warning', common.mustNotCall());

Make sure this fails on current Node.js version, and passes with your PR:

$ ./tools/test.py test/parallel/test-repl-history-navigation.js
[00:00|% 100|+   1|-   0]: Done
$ node test/parallel/test-repl-history-navigation.js || echo 'All good, we expect this to fail'
All good, we expect this to fail

@aduh95 Done! Thanks for the guidance 😄

@BridgeAR BridgeAR changed the title Suggested fix for issue #38139 - Node REPL can't handle declaring a variable with the name util repl: fix declaring a variable with the name util Apr 10, 2021
test/parallel/test-repl-history-navigation.js Outdated Show resolved Hide resolved
test/parallel/test-repl-history-navigation.js Outdated Show resolved Hide resolved
test/parallel/test-repl-history-navigation.js Outdated Show resolved Hide resolved
test/parallel/test-repl-history-navigation.js Outdated Show resolved Hide resolved
test/parallel/test-repl-history-navigation.js Outdated Show resolved Hide resolved
test/parallel/test-repl-history-navigation.js Outdated Show resolved Hide resolved
@benjamingr
Copy link
Member

I... don't understand this fix?

Doesn't this just fix the error being shown (cannot read property length) instead of the underlying cause (the repl assuming util is available in the global namespace)?

I would strongly prefer a fix that fixes the underlying issue and not the "cosmetic" one. Namely changing code doing something like:

session.post('Runtime.callFunctionOn', {
            functionDeclaration: `(v) => util.inspect(v, ${inspectOptions})`,
            objectId: result.objectId,
            arguments: [result]
          }

To not rely on the global util (either by requireing it, "hiding" it as a non-completed global, or passing it to Runtime.evaluate)

Copy link
Member

@benjamingr benjamingr left a comment

Choose a reason for hiding this comment

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

Requesting changes to make sure this doesn't land before everyone is on the same page regarding the kind of fix this needs @nodejs/repl

(Thank you for working on this @EladKeyshawn !)

@Linkgoron
Copy link
Member

Linkgoron commented Apr 10, 2021

To not rely on the global util (either by requireing it, "hiding" it as a non-completed global, or passing it to Runtime.evaluate)

I think it makes sense to change that relevant code from util.inspect to require('util').inspect at least (in addition to the undefined fix, so that doing const require = {} won't break the code). The change would change the "bad" word to require, but I think that it's much less likely to be used.

test/parallel/test-repl-history-navigation.js Outdated Show resolved Hide resolved
test/parallel/test-repl-history-navigation.js Outdated Show resolved Hide resolved
test/parallel/test-repl-history-navigation.js Outdated Show resolved Hide resolved
@aduh95
Copy link
Contributor

aduh95 commented Apr 10, 2021

I think it makes sense to change that relevant code from util.inspect to require('util').inspect at least (in addition to the undefined fix, so that doing const require = {} won't break the code). The change would change the "bad" word to require, but I think that it's much less likely to be used.

That shouldn't be an issue, require is not on the global scope. actually it is, the function still inherits from the REPL scope.

@aduh95
Copy link
Contributor

aduh95 commented Apr 10, 2021

@benjamingr I arrive at the same conclusion as @Linkgoron, we need to rely on either util or require being unchanged –unless there's a way to use dynamic import? Maybe what we can do is to use (v) => Reflect.getOwnPropertyDescriptor(globalThis, 'util').get().inspect(v, ${inspectOptions}), which would fail only if the global util property is re-defined, and wouldn't be "exploitable" unless the user goes all the way of defining a credible mock:

> const util = {}
undefined
> util
{}
> globalThis.util = { inspect() { return console.log(arguments) } }
{ inspect: [Function: inspect] }
> util
{}
> Reflect.defineProperty(globalThis, 'util', { get() { return {inspect(){ console.log(arguments) }}}})
true
> ut[Arguments] {
  '0': {},
  '1': {
    showHidden: false,
    depth: 1,
    colors: false,
    customInspect: true,
    showProxy: true,
    maxArrayLength: 100,
    maxStringLength: 10000,
    breakLength: Infinity,
    compact: true,
    sorted: false,
    getters: false
  }
}

@aduh95
Copy link
Contributor

aduh95 commented Apr 11, 2021

@EladKeyshawn can you please update the code at

session.post('Runtime.callFunctionOn', {
functionDeclaration: `(v) => util.inspect(v, ${inspectOptions})`,
objectId: result.objectId,
arguments: [result]
}, (error, preview) => {
with my above suggestion? It would be nice to also add a test case fro when globalThis.util is re-assigned.

@EladKeyshawn
Copy link
Author

@EladKeyshawn can you please update the code at

session.post('Runtime.callFunctionOn', {
functionDeclaration: `(v) => util.inspect(v, ${inspectOptions})`,
objectId: result.objectId,
arguments: [result]
}, (error, preview) => {
with my above suggestion? It would be nice to also add a test case fro when globalThis.util is re-assigned.

No problem :) I'm on it

@benjamingr benjamingr self-requested a review April 11, 2021 12:41
Copy link
Member

@benjamingr benjamingr left a comment

Choose a reason for hiding this comment

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

LGTM with green CI

@EladKeyshawn
Copy link
Author

with my above suggestion? It would be nice to also add a test case fro when globalThis.util is re-assigned.

If globalThis is reassigned we're back with the same problem. Do we count on the fact that it's unlikely to happen? anyways my original patch solves the Cannot read property 'length' of undefined warning in this case anyways.

@EladKeyshawn
Copy link
Author

@aduh95 Can you explain why the last tests pass the expected output but are not marked as called, I believe obviously repl.once('closed'... is not triggered but is that normal?

@aduh95
Copy link
Contributor

aduh95 commented Apr 11, 2021

If globalThis is reassigned we're back with the same problem. Do we count on the fact that it's unlikely to happen?

Right, I think it's fine to fail when globalThis is overwritten, I don't think there is a way around it. I'd say it's possibly less likely to happen than util.

Can you explain why the last tests pass the expected output but are not marked as called, I believe obviously repl.once('closed'... is not triggered but is that normal?

I'm not sure I understand what you mean, I'd expect the closed event to be emitted for each test case. What make you think it's not triggered?

@EladKeyshawn
Copy link
Author

@benjamingr @aduh95 What's blocking this?

@aduh95 aduh95 added the author ready PRs that have at least one approval, no pending requests for changes, and a CI started. label Apr 15, 2021
@nodejs-github-bot

This comment has been minimized.

@nodejs-github-bot

This comment has been minimized.

@nodejs-github-bot

This comment has been minimized.

@nodejs-github-bot
Copy link
Collaborator

@nodejs-github-bot
Copy link
Collaborator

@aduh95
Copy link
Contributor

aduh95 commented Apr 17, 2021

test-repl-history-navigation is consistently failing on ubuntu1804_sharedlibs_withoutintl_x64 and ubuntu1804_sharedlibs_withoutssl_x64 jobs.

@aduh95 aduh95 removed the author ready PRs that have at least one approval, no pending requests for changes, and a CI started. label Apr 17, 2021
@EladKeyshawn
Copy link
Author

test-repl-history-navigation is consistently failing on ubuntu1804_sharedlibs_withoutintl_x64 and ubuntu1804_sharedlibs_withoutssl_x64 jobs.

Do you have any idea what could cause this? for me on OSx it works.

Copy link
Contributor

@aduh95 aduh95 left a comment

Choose a reason for hiding this comment

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

One way of working around this would be to disable the output checks when Intl or crypto is missing.

env: { NODE_REPL_HISTORY: defaultHistoryPath },
test: ['const util = {}', ENTER,
'ut', RIGHT, ENTER],
expected: [
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
expected: [
expected: common.hasIntl && common.hasCrypto ? [

Copy link
Author

@EladKeyshawn EladKeyshawn Apr 17, 2021

Choose a reason for hiding this comment

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

Can I ask why do these requirements affect the console output? :)

Copy link
Contributor

Choose a reason for hiding this comment

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

No clue! If you'd like to investigate that, you can compile node with ./configure --without-intl on your local machine.

test/parallel/test-repl-history-navigation.js Outdated Show resolved Hide resolved
test/parallel/test-repl-history-navigation.js Outdated Show resolved Hide resolved
test/parallel/test-repl-history-navigation.js Outdated Show resolved Hide resolved
@nodejs-github-bot
Copy link
Collaborator

benjamingr pushed a commit that referenced this pull request Apr 18, 2021
PR-URL: #38141
Fixes: #38139
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
@benjamingr
Copy link
Member

Landed in b2baa3d 🎉

@benjamingr benjamingr closed this Apr 18, 2021
@benjamingr benjamingr reopened this Apr 18, 2021
@benjamingr
Copy link
Member

I had to revert because of lint failures. I will land this manually.

@aduh95
Copy link
Contributor

aduh95 commented Apr 18, 2021

@benjamingr I have this ready to land on my local machine, do you want me to push?

@benjamingr
Copy link
Member

benjamingr commented Apr 18, 2021

@aduh95 yes please, thanks :) I want to investigate what's went wrong and I don't want to hold this PR up just for my root-cause check

The REPL no longer relies on `util` being a reference to the `util` core
module. It still relies on `globalThis` refering to the global object,
but no longer emits warnings when it's overwritten by the user.

PR-URL: nodejs#38141
Fixes: nodejs#38139
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
@aduh95 aduh95 force-pushed the eladkeyshawn-repl-redeclare-util-bricks branch from 770a015 to d666964 Compare April 18, 2021 14:14
@aduh95 aduh95 merged commit d666964 into nodejs:master Apr 18, 2021
@aduh95
Copy link
Contributor

aduh95 commented Apr 18, 2021

Landed in d666964 :)

@EladKeyshawn
Copy link
Author

Thanks 😊

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs-ci PRs that need a full CI run. repl Issues and PRs related to the REPL subsystem.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

The Node REPL can't handle declaring a variable with the name util
8 participants