When Error.captureStackTrace evaluates a JavaScript constructorOpt (a getter,
a call, or this.constructor with a constructor getter), V8 has already
evaluated the target. The lowering kept the target in a local only when its
expression was not a plain read, so a constructorOpt that assigned the target
variable made the capture install the stack on the new value. The target is
now always kept in a local before the constructorOpt runs.
Inside a class constructor, Error.captureStackTrace(this, this.constructor) now reads this.constructor before the capture when the class or a base class declares a constructor getter, as V8 evaluates the argument: the getter runs and its exception propagates.
- Error.captureStackTrace in JavaScript discarded a constructorOpt it
does not recognize (a getter, a call), so its side effects and
exceptions did not happen. It now evaluates after the target and
before the capture, as V8 evaluates the call's arguments; the target is
held in a local when evaluating it twice would not be safe.
- Capturing on an error replaced its saved stack without the checks V8
makes when it defines `stack`. A frozen, sealed or non-extensible error
now throws "Cannot define property stack, object is not extensible",
and one whose `stack` is non-configurable throws "Cannot redefine
property: stack"; both keep their stack.
Corpus 6874 checks the evaluation order and a constructorOpt that
throws.