Inconsistent binding of "this" in inline arrow function within a generator. |
||||
Issue descriptionWhile debugging a LogDog viewer problem ( crbug.com/722541 ), I ran into something weird that seems like it could be a V8 bug. I've created a pretty small repro. The bug is not present in stable Chromium, but appears to be present in canary: Google Chrome 60.0.3100.0 (Official Build) dev (64-bit) Revision f472642fd6c20b63b0f1a2f62564f2aad56f4be3-refs/heads/master@{#471639} OS Linux JavaScript V8 6.0.205 I have a class which includes a member function that invokes a wrapper on a generator function. The generator function, in turn, calls an inline arrow function which references "this". I find that if "this" is referenced in the generator function, the arrow function's "this" is properly bound to the class. However, if the generator function does NOT reference "this", the arrow function's "this" is bound to Window. See attachment for reproduction. (This looks a lot more reasonable in the source TypeScript.)
,
May 17 2017
,
May 17 2017
Looks like a regression from https://chromium.googlesource.com/v8/v8/+/68f0a47b28a96a4966e7b747bfa304b555e726d1, taking a look now.
,
May 17 2017
,
May 17 2017
+marja as this doesn't repro with --no-lazy-inner-functions. It seems like lazy-parsing inner arrow functions just happened to work before, since the "this" variable was always used in generator scopes. And it's already broken for "arguments". I think the short-term fix is to stop treating generators in general as "top level", since they can have "interesting" bindings for both "this" and "arguments". For module scopes, it should still be safe to treat them as "top level", since 'this' is always undefined, and there is no 'arguments' binding.
,
May 17 2017
Minimal test case:
```
function outer() {
function* generator() {
let arrow = () => {
console.log(this, arguments[0]);
};
arrow();
}
generator.call(this, 'world').next();
}
outer.call('hello');
```
It should print `hello world`, but instead prints `[object global] undefined`.
,
May 17 2017
Proposed fix up for review at https://chromium-review.googlesource.com/c/508055/
,
May 18 2017
The following revision refers to this bug: https://chromium.googlesource.com/v8/v8.git/+/0439100a5f1264825a99a90cca7c8dd3311944c1 commit 0439100a5f1264825a99a90cca7c8dd3311944c1 Author: Adam Klein <adamk@chromium.org> Date: Thu May 18 16:24:26 2017 [parser] Stop treating generators as "top level" for preparsing purposes Generators were previously treated as "top level" for preparsing purposes, since all their variables are context-allocated. But doing so isn't quite correct: the allocation of the "arguments" variable for a generator depends on whether it's referenced, and so an inner arrow function which references "arguments" won't properly trigger allocation of "arguments" since the reference will not be noticed in the preparser. The same problem exists for "this" since commit 68f0a47b28a96a4966e7b747bfa304b555e726d1; before that commit, all generators implicitly referenced their "this" argument as part of the desugaring. With that implicit reference gone, "this" falls into the same problem as arguments. This patch restricts the special "top level" treatment to modules, which have only a trivial "this" binding (it's always undefined), and no arguments binding. Moreover, all code inside modules is strict, meaning that unresolved references to "this" will also result in undefined. R=marja@chromium.org Bug: chromium:723132 Change-Id: I814d145fb8f3f1a65abb48e4e35595428d063051 Reviewed-on: https://chromium-review.googlesource.com/508055 Reviewed-by: Marja Hölttä <marja@chromium.org> Commit-Queue: Adam Klein <adamk@chromium.org> Cr-Commit-Position: refs/heads/master@{#45399} [modify] https://crrev.com/0439100a5f1264825a99a90cca7c8dd3311944c1/src/ast/scopes.cc [add] https://crrev.com/0439100a5f1264825a99a90cca7c8dd3311944c1/test/mjsunit/regress/regress-crbug-723132.js
,
May 18 2017
|
||||
►
Sign in to add a comment |
||||
Comment 1 by hpayer@chromium.org
, May 17 2017Status: Available (was: Untriaged)