0

Code

class Parent {
  constructor() {}
}

class Child extends Parent {
  constructor() {
    super();
  }
}

Background

As I was trying to understand exactly how super() invocations in class constructors work, I followed the following sequence of ECMAScript operations:

  1. new Child() calls ChildConstructor.[[Construct]]
  2. kind is derived (earlier set in 14.5.15), so no new this value is bound
  3. OrdinaryCallEvaluateBody is called, which ends up evaluating the body of the Child class constructor method, where super() is the first statement
  4. super() calls ParentConstructor.[[Construct]], which takes us back to step 3, just with kind as base this time
  5. Since kind is now base, a new this binding is created and bound to the Environment Record of the new function environment created for the Parent constructor
  6. The rest of Parent constructor's body executes, and once done control flows back to Child.[[Construct]] where execution continues from step 11
  7. Finally, Child.[[Construct]] tries to return envRec.GetThisBinding

Question

The Environment Record for the Child constructor, created in step 6 of Child.[[Construct]], has no this binding ([[ThisBindingStatus]] is uninitialized). Thus, when we try to do envRec.GetThisBinding in step 8, we should as far as I can tell, get a ReferenceError (as specified here).

What am I missing here? I can't seem to see why the Child constructor won't throw an error, and indeed if the [[ThisValue]] of the Child constructor is set at all.

Magnus
  • 6,791
  • 8
  • 53
  • 84
  • I'm trying to find those lines in the specification, but all my searches failed. Are those literal quotes or are you paraphrasing? Could you link to the specific section you're asking about? – Barmar Aug 15 '18 at 16:30
  • Thanks for looking at it, @Barmar . The steps above are a much condensed version of what actually happens. There are too many steps to list everything, but I have linked to the important algorithms at keys steps for ease of reference. – Magnus Aug 15 '18 at 16:33

1 Answers1

1

You missed a step in your super() link:

  1. Let newTarget be GetNewTarget().
  2. Assert: Type(newTarget) is Object.
  3. Let func be ? GetSuperConstructor().
  4. Let argList be ArgumentListEvaluation of Arguments.
  5. ReturnIfAbrupt(argList).
  6. Let result be ? Construct(func, argList, newTarget).
  7. Let thisER be GetThisEnvironment( ).
  8. Return ? thisER.BindThisValue(result).

Step 6 calls ParentConstructor.[[Construct]] as you mentioned, but then step 8 will set the this binding in the Child constructor body to the constructed value, so when envRec.GetThisBinding runs at the end off ChildConstructor.[[Construct]], the this binding will be there

loganfsmyth
  • 156,129
  • 30
  • 331
  • 251