-
-
Notifications
You must be signed in to change notification settings - Fork 504
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
Untracked arguments
in function scopes.
#4232
Comments
Since you are heavily invested in the scopes right now, @Dunqing What do you think? |
Funny, I was wondering how we handle I can see 3 options:
Personally, I would tend towards (2) - simple, and avoids perf hit of (1). NB: function f1(x) {
// SyntaxError: Identifier 'x' has already been declared
let x;
}
function f2(arguments) {
// SyntaxError: Identifier 'arguments' has already been declared
let arguments;
}
function f3() {
// No problem
let arguments;
} Also, you can have 2 bindings for function f(x, y = arguments) {
let arguments = 456;
console.log(y[0]); // Logs 123
console.log(arguments); // Logs 456
}
f(123); So we'd need an extra scope for function body. |
I think the option The latter seems like a good thing for performance but I'm afraid it would cause issues later on because javascript is whimsical at times: function f() {
eval("console.log(arguments)");
}
f("a", "b", "c") With the second approach, we still have the same issue of shadowing arguments and generating the wrong code! |
He had to go and bring But even then, I can't actually see how that can go wrong. |
😆
You are right that we shouldn't ever mangle Maybe no sane person uses I might be overthinking this. |
We should add an |
What do you think of this example? // Sloppy mode
function f(x, y = arguments) {
let arguments = 456;
console.log(y[0]); // Logs 123
console.log(arguments); // Logs 456
}
f(123); This demonstrates there can be 2 distinct bindings for |
I was reading the eslint-scope tests today when saw an oddity I couldn't figure. It contains
With these steps, your code would work similarly to this: let arguments = [123];
function f(x, y = arguments) {
let arguments = 456;
console.log(y[0]); // Logs 123
console.log(arguments); // Logs 456
}
f(123); |
Treating // Sloppy mode
let arguments;
function f(x, y = arguments) {
let arguments = 456;
} Here we have 3 bindings for Only solutions I can see are:
(1) is simpler and more conceptually correct, but imposes quite a large penalty. Every function generates 2 scopes, and functions are a common construct, so it will slow down symbol resolution significantly. (3) has been rejected. So I would lean towards (2). |
I personally would prefer to find a way to avoid unnecessary scopes, Can't we declare arguments as a hoisted variable on the function scope? with that, we should be able to redeclare it in the function body. But that's just my preference and I have nothing against your approach here, It just feels wrong to add scopes left and right as a means to simplify stuff. As you said correctness is more important. I'm not a huge fan of premature optimization. I just have a quick question. We are wrapping the whole function in the scope right now. Is this going to change? Is the scope going to be entered after the parameters? |
To clarify, what I'm saying about option (2) above is:
i.e. Handle the weird uncommon edge case as a de-opt. No overhead from extra scope in common case, but maintain complete correctness. |
Actually, it's not as bad as I initially thought. I'm just afraid of something like this. When you are accessing the It also means that there are now some really obscure edge cases with What are your thoughts on this? Even if we do all of these checks doesn't it mean we won't get much performance out of this in the long run(as we start to use scope more and more)? Edit:I've checked the spec and even there, They only create a new lexical environment if strict is false to prevent But maybe I'm missing something here. https://tc39.es/ecma262/multipage/ordinary-and-exotic-objects-behaviours.html#sec-functiondeclarationinstantiation |
I found out how TypeScript handles |
Nice find. I also see tsc defines
|
TS may do it, but it seems like a bad idea to me. Rather confusing, no? |
For the record, I added this to the mangler oxc/crates/oxc_mangler/src/lib.rs Lines 229 to 231 in 0a2f687
|
// Sloppy mode
function outer() {
let arguments = 123;
console.log(arguments);
}
function outer2() {
function arguments() {}
console.log(arguments);
} But not if it's a // Sloppy mode
function outer() {
console.log(arguments); // Logs [1, 2, 3]
var arguments = 456;
console.log(arguments); // Logs 456
}
outer(1, 2, 3);
function outer2() {
console.log(arguments); // Logs [1, 2, 3]
{
function arguments() {}
}
console.log(typeof arguments); // Logs 'function'
}
outer2(1, 2, 3); |
Personally I'm in favour of adding scopes for function bodies anyway for other reasons (#5017), so that'd resolve some of the questions above. |
Related to this: #3374 (comment)
We do not keep track the arguments object in functions, It causes false positives in linters as of now and it can impose more serious limitations or errors in other crates(transformers and minifier come to mind as we might shadow the function arguments by mistake).
The text was updated successfully, but these errors were encountered: