escope icon indicating copy to clipboard operation
escope copied to clipboard

Destructuring results in invalid write reference

Open jbrumwell opened this issue 10 years ago • 4 comments

Given the following code;

const { x = 10 } = {};

The result is two write declarations on variable x the first to 10 and the second to the empty object {}

eslint-const-destruct

jbrumwell avatar Jun 04 '15 16:06 jbrumwell

Yeah, it is by design.

escope makes writable-references for variable-initializers. When it's used together with destructuring and default values, the variable has multiple writable-references for its initializer.

So the Reference object has init property in order to check whether or not the reference is the initializer. And the Reference object has partial property in order to check whether or not the reference writes a part of writeExpr to the variable.

Please see also #65. And https://github.com/eslint/eslint/pull/2639 may help you.

mysticatea avatar Jun 05 '15 04:06 mysticatea

@mysticatea Thank you for responding, given your description of init and partial I would be able to implement the changes in behaviour.

Partial doesn't seem to be operating in the fashion you mention, here are the results for partial and init in two different circumstances;

const { x = 10 } = { y: 15 };

  1. partial=false init=true // given your definition I'd expect this to be true
  2. partial=true init=true // given your definition I'd expect this to be false

const { x = 10 } = { x: 15 };

  1. partial=false init=true // given your definition I'd expect this to be true
  2. partial=true init=true

jbrumwell avatar Jun 05 '15 15:06 jbrumwell

On const { x = 10 } = { y: 15 };, x has two initializers.

  1. x = 10 is not partial.
  2. {x} = {y: 15} is partial. This means x = ({y: 15}).x. A runtime optimizer may remove it. But we can assignment to Object.prototype.x anywhere, so escope cannot decide whether it is undefined.

On const { x = 10 } = { x: 15 };, x has two initializers as almost same as the above. x = 10 exists but it is unreachable. escope does not analyze execution paths.

mysticatea avatar Jun 05 '15 16:06 mysticatea

I may be wrong but I don't think this is incorrect according to the draft. My interpretation of the draft is that it creates a reference from the assignment expression, then declares the value with rhs destructuring if available and if not uses the default value on the assignment expression.

This makes sense because if it didn't you are declaring const twice when destructuring their assignments. This is also the way that babel transforms the code.

// const { x = 10 } = { y: 15 };
"use strict";

var _x = { y: 15 };
var _x$x = _x.x;
var x = _x$x === undefined ? 10 : _x$x;

jbrumwell avatar Jun 05 '15 17:06 jbrumwell