ecma262 icon indicating copy to clipboard operation
ecma262 copied to clipboard

Setting [[SourceText]] after ClassDefinitionEvaluation

Open bathos opened this issue 3 years ago • 3 comments

Given the following example in light of the evaluation steps for ClassExpression : class ClassTail:

try {
  void class { static { throw this; } }
} catch (f) {
  f.toString(); 
}

Those steps abruptly return at the first step. The [[SourceText]] slot will be present on f, but it will hold no value. The value would only be set if the second step had been reached (“Set value.[[SourceText]] to the source text matched by ClassExpression”).

The steps for %Function.prototype.toString% do account for this possibility. The step which would potentially return [[SourceText]] is qualified to only do so if its value “is a sequence of Unicode code points,” so because it isn’t, we’d just continue to the next steps, which are:

  1. If func is a built-in function object, return an implementation-defined String source code representation of func. The representation must have the syntax of a NativeFunction [...]
  2. If Type(func) is Object and IsCallable(func) is true, return an implementation-defined String source code representation of func. The representation must have the syntax of a NativeFunction [...]
  3. Throw a TypeError exception.

In this specific case, f is a “built-in function” (via step 14.b of ClassDefinitionEvaluation), so step 3 applies. This is only true because there’s no explicit constructor, but regardless of whether we were to exit at step 3 or 4 here, the requirement that the string returned should match NativeFunction still applies.

V8 and Spidermonkey do not exhibit this behavior. Instead they behave as though step 2 of the eval steps for ClassExpression : class ClassTail had been reached and return the 'class { static { throw this; } }' String.

This also isn’t unique to the case of an abrupt step 1; it could as easily be that step 2 is reached but that user code evaluated during ClassDefinitionEvaluation calls F.p.toString when it would not have been set yet, e.g.

void class { static { console.log(this.toString()); } };

Is this a specification error, an implementation error, or a misinterpretation on my part?

bathos avatar Feb 22 '22 14:02 bathos

Huh, yup, I think that's a bug in the spec. Setting [[SourceText]] after ClassDefinitionEvaluation was fine prior to static blocks being added (since computed method names in the class body can't refer to it until it's finished evaluating), and become wrong with the merge of that PR. We'll need to pass the source text into ClassDefinitionEvaluation so we can set it earlier.

bakkot avatar Feb 22 '22 19:02 bakkot

I think it likely predated that PR because static field initializers can also reference the constructor.

bathos avatar Feb 22 '22 21:02 bathos

Oh, sure, same deal there.

bakkot avatar Feb 22 '22 21:02 bakkot