5

I’m watching a talk on JSON hijacking and not 2 minutes in, there is already JavaScript that is unfamiliar to me.

let:let{let:[x=1]}=[alert(1)]

It seems to work on Edge and just alerts 1, but I’ve never come across that let:let syntax. I’m curious, how am I supposed to read this?

5
  • 1
    in real browsers, you could do let:{ let{let:[x=1]}=[alert(1)] } if that helps - first let is a label, second let is an actual let and third let is a property name (sort of) - hmmm, maybe not that simple actually - though, there are errors in the console for edge Commented Apr 2, 2018 at 1:51
  • @JaromandaX oh yeah I closed the window before the error appeared as the code do executes but the error only appears when you close the alert dialog.
    – Ced
    Commented Apr 2, 2018 at 1:58
  • seems Edge allows labels for single statements, real browsers do not - actually, that's not it either ... wow ... odd stuff Commented Apr 2, 2018 at 1:59
  • This doesn’t work in strict mode, since you can’t use let as a label there. Commented Apr 2, 2018 at 1:59
  • Short answer to the title, in certain browsers it would alert 1
    – vol7ron
    Commented Apr 2, 2018 at 3:18

1 Answer 1

6

The video actually says that it uses destructuring assignment and labels.

This code doesn’t appear to work in browser other than Edge; so to make it work in other browsers, it needs to look like this:

let:{let{let:[x=1]}=[alert(1)]}

Why? Let’s look at Firefox’s console:

SyntaxError: lexical declarations can't appear in single-statement context

The “single-statement context” the error is referring to, is the part after let: at the beginning — let{let:[x=1]}=[alert(1)]. In this case, the let before it is a label. No other keywords appear to work as a label:

var: while(false); // => SyntaxError: missing variable name
for: while(false); // => SyntaxError: missing ( after for

However, a few of them work:

yield: while(false);
async: while(false);
await: while(false);

In strict mode however, let and yield would fail as well with SyntaxError: [keyword] is a reserved identifier.

Now, the remaining part of the code uses destructuring:

let {
    let: [x = 1]
  } = [
    alert(1)
  ];

The let inside the { } just signifies an object property, which is totally fine. The following is valid JS:

let object = {
    let: 2,
    var: 1,
    const: "hello",
    while: true,
    throw: Error
  };

alert(1) gets executed, so you see the alert. It evaluates to undefined, so you have:

let {let: [x = 1]} = [undefined];

Now, this is trying to get the let property of [undefined], which itself is undefined. Further, this line is attempting to take the value of that property, and destructure it further into an array (so the value has to be an iterable object) with the variable name x for its first element, with the default value 1. Since [undefined].let is undefined, it can’t be destructured, so the code throws the error:

TypeError: [...].let is undefined


Working destructuring could look like one of these lines:

let {let: [x = 1]} = {let: [alert(1)]}; // x is now 1 (default value, since first element in right-hand side is undefined)
let {let: [x = 1]} = {let: [2]}; // x is now 2 (defined due to right-hand side)

Both don’t throw an error, and the first one assigns 1 to x, because the first element in the array on the right-hand side was undefined.


Part of the confusion may stem from nested destructuring, like these two snippets:

let {a: {b: {c}}} = {a: {b: {c: 3}}}
let {a: {b: {c = 1}}} = {a: {b: {c: 3}}}

Here, no variables a or b are created, only c, which is the identifier not followed by a : on the left-hand side. Property names that are followed by a : basically instruct the assignment to “find this property in the right-hand side value”.

3
  • Ah damn I was pretty close. That part : Now, this is trying to get the let property of [undefined] flew over my head. I learned some things though, not sure if it will be that useful but well it's better than nothing I guess
    – Ced
    Commented Apr 2, 2018 at 2:53
  • The statement was especially confusing because it was actually invalid though
    – Ced
    Commented Apr 2, 2018 at 2:54
  • 1
    @Ced Glad my answer helped. Nested destructuring can sometimes be confusing, but it’s occasionally really helpful and expressive. Make sure to see my latest edit — I fixed a few mixed up terms and clarified some things. Commented Apr 2, 2018 at 3:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.