browserify / browserify/static-eval

Differences in `ReturnStatement` evaluations

Offen
#39 0 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen
Vorherrschende Sprache
JavaScript
Sterne
177
Forks
27
PR-Merge-Kennzahlen
Keine gemergten PRs in 30 T.

Beschreibung

Why does the following work:
```js
[1, 2].map(function(x) { return x + 1 })
```
But not the following:
```js
[{a: 1}, {a: 2}].map(function(x) { return x["a"] })
```

Since `.map()` does not seem to be an issue, and member expressions of course aren’t, I’m not sure why this fails. The actual error is `TypeError: Cannot read properties of null (reading 'a')`

The inner function ASTs are respectively:
```js
ReturnStatement {
type: 'ReturnStatement',
argument: BinaryExpression {
type: 'BinaryExpression',
operator: '+',
left: Identifier { type: 'Identifier', name: 'x' },
right: Literal { type: 'Literal', value: 1, raw: '1' }
}
}
```
And:
```js
ReturnStatement {
type: 'ReturnStatement',
argument: ComputedMemberExpression {
type: 'MemberExpression',
computed: true,
object: Identifier { type: 'Identifier', name: 'x' },
property: Literal { type: 'Literal', value: 'a', raw: '"a"' }
}
}
```

Statically evaluating a MemberExpression is not harder than a BinaryExpression, is it?

After looking at the code, it seems to me that in both cases the `x` statement is statically evaluated to `null`. In the `BinaryExpression` code, the binary evaluation returns `null + 1` which is `1`, and you then allow and execute the function.

However since `null["a"]` raises an error, the function is not allowed and executed. However `x["a"]` is knowable statically (it is either the property or `undefined` if it’s absent − if you call `evaluate('x["b"]', {x: {a: 1}})`, you get `undefined`, not an error), so the function should execute in this case as well.

There is a simple workaround which is to return `(x || {a: ""})["a"]` instead of `x["a"]`, this avoids throwing an error by ensuring there is a fallback value to `x.a` if `x` is undefined.

Beitragsleitfaden

Für dieses Repository ist kein Beitragsleitfaden indexiert

Rechercherichtung

Beginne mit dem Evaluationspfad von ReturnStatement und vergleiche, wie Argumente von BinaryExpression und MemberExpression behandelt werden. Reproduziere beide map-Callbacks und das Beispiel evaluate('x[\"b\"]', {x: {a: 1}}), und überprüfe anschließend, dass statisch bekannte Member-Zugriffe den Callback nicht fälschlicherweise zurückweisen, während echter Null-Zugriff weiterhin korrekt funktioniert.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
javascript
Bereich
tooling
Issue-Typ
Bug
Schwierigkeit
3/5
Geschätzter Aufwand
1-2 Tage
Aktivitätsstatus
Veraltet
Klarheit
Größtenteils klar
Anfängerfreundlichkeit
35/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.