Destructuring results in invalid write reference
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 {}

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 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 };
- partial=false init=true // given your definition I'd expect this to be true
- partial=true init=true // given your definition I'd expect this to be false
const { x = 10 } = { x: 15 };
- partial=false init=true // given your definition I'd expect this to be true
- partial=true init=true
On const { x = 10 } = { y: 15 };, x has two initializers.
-
x = 10is not partial. -
{x} = {y: 15}is partial. This meansx = ({y: 15}).x. A runtime optimizer may remove it. But we can assignment toObject.prototype.xanywhere, so escope cannot decide whether it isundefined.
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.
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;