• Timothy Gu's avatar
    [builtins] Clean up the use of class_name / ES5 [[Class]] · 29c1eab9
    Timothy Gu authored
    Before ES2015, the ES spec had a [[Class]] internal slot for all
    objects, which Object.prototype.toString() would use to figure the
    returned string. Post-ES2015, the [[Class]] slot was removed in spec for
    all objects, with the @@toStringTag well-known symbol the proper way to
    change Object.prototype.toString() output.
    
    At the time, spec-identical handling without the use of [[Class]] was
    implemented in V8 for all objects other than API objects, where issues
    with the Web IDL spec [1] prevented Blink, and hence V8, to totally
    migrate to @@toStringTag. However, since 2016 [2] Blink has been setting
    @@toStringTag on API class prototypes to manage the
    Object.prototype.toString() output, so the legacy [[Class]] handling in
    V8 has not been necessary for the past couple of years.
    
    This CL removes the remaining legacy [[Class]] handling in
    Object.prototype.toString(), JSReceiver::class_name(), and
    GetConstructorName(). However, it does not remove the class_name field
    in FunctionTemplateInfo, as it is still used for the `name` property of
    created functions.
    
    This CL also cleans up other places in the codebase that still reference
    [[Class]].
    
    This change should have minimal impact on web-compatibility. For the
    change to be observable, a script must do one of the following:
    
    1. delete APIConstructor.prototype[Symbol.toStringTag];
    2. Object.setPrototypeOf(apiObject, somethingElse);
    
    Before this CL, these changes will not change the apiObject.toString()
    output. But after this CL, they will make apiObject.toString() show
    "[object Object]" (in the first case) or the @@toStringTag of the other
    prototype (in the latter case).
    
    However, both are deemed unlikely. @@toStringTag is not well-known
    feature of JavaScript, nor does it get tampered much on API
    constructors. In the second case, setting the prototype of an API object
    would effectly render the object useless, as all its methods (including
    property getters/setters) would no longer be accessible.
    
    Currently, @@toStringTag-based API object branding is not yet
    implemented by other browsers. This V8 bug in particular has been an
    impediment to standardizing toString behavior. Fixing this bug will
    unblock [3] and lead to a better Web IDL spec, and better toString()
    compatibility for all.
    
    [1]: https://www.w3.org/Bugs/Public/show_bug.cgi?id=28244
    [2]: https://crrev.com/909c0d7d5a53c8526ded351683c65ea7d17531d4
    [3]: https://github.com/heycam/webidl/pull/357
    
    Bug: chromium:793406
    Cq-Include-Trybots: luci.chromium.try:linux-rel
    Change-Id: Iceded24e37afa2646ec385d5018909f55b177f93
    Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2146996
    Commit-Queue: Timothy Gu <timothygu@chromium.org>
    Reviewed-by: 's avatarToon Verwaest <verwaest@chromium.org>
    Cr-Commit-Position: refs/heads/master@{#67327}
    29c1eab9
js-objects.h 60.2 KB