Changeset 270552 in webkit


Ignore:
Timestamp:
Dec 8, 2020 1:02:48 PM (20 months ago)
Author:
Ross Kirsling
Message:

Align %TypedArray% constructor behavior with spec
https://bugs.webkit.org/show_bug.cgi?id=219527

Reviewed by Yusuke Suzuki.

JSTests:

  • test262/expectations.yaml:

Mark 40 test cases as passing.

  • wasm/fuzz/memory.js:
  • wasm/js-api/test_Data.js:

Fix non-conforming typed array usage.

Source/JavaScriptCore:

These should be the last JSC-side corrections for typed array behavior:
namely, fixes for the constructor itself.

Broadly speaking, there are three fixes here:

  1. ArrayBuffer argument (https://tc39.es/ecma262/#sec-initializetypedarrayfromarraybuffer): We need to throw if the input buffer gets detached.
  1. Array-like argument (https://tc39.es/ecma262/#sec-initializetypedarrayfromarraylike): length needs toLength, not toUInt32.
  1. Typed array argument (https://tc39.es/ecma262/#sec-initializetypedarrayfromtypedarray): We need to support the case where the input typed array uses a custom ArrayBuffer. This case is *extremely* strange -- we still create the same type of typed array with a normal ArrayBuffer, but we override the prototype of that ArrayBuffer to inputTypedArray.buffer.constructor[@@species].prototype.
  • JavaScriptCore.xcodeproj/project.pbxproj:
  • runtime/JSArrayBufferConstructor.cpp:
  • runtime/JSArrayBufferPrototype.cpp:

(JSC::arrayBufferSpeciesConstructorSlow): Added.
(JSC::speciesWatchpointIsValid): Moved.

  • runtime/JSArrayBufferPrototype.h:
  • runtime/JSArrayBufferPrototypeInlines.h: Added.
  • runtime/JSGenericTypedArrayViewConstructorInlines.h:

(JSC::constructCustomArrayBufferIfNeeded): Added.
(JSC::constructGenericTypedArrayViewWithArguments):

  • runtime/JSGlobalObject.h:
Location:
trunk
Files:
1 added
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r270524 r270552  
     12020-12-08  Ross Kirsling  <ross.kirsling@sony.com>
     2
     3        Align %TypedArray% constructor behavior with spec
     4        https://bugs.webkit.org/show_bug.cgi?id=219527
     5
     6        Reviewed by Yusuke Suzuki.
     7
     8        * test262/expectations.yaml:
     9        Mark 40 test cases as passing.
     10
     11        * wasm/fuzz/memory.js:
     12        * wasm/js-api/test_Data.js:
     13        Fix non-conforming typed array usage.
     14
    1152020-12-07  Dmitry Bezhetskov  <dbezhetskov@igalia.com>
    216
  • trunk/JSTests/test262/expectations.yaml

    r270487 r270552  
    833833  default: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all (Testing with Float64Array.)'
    834834  strict mode: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all (Testing with Float64Array.)'
    835 test/built-ins/TypedArrayConstructors/ctors/buffer-arg/byteoffset-to-number-detachbuffer.js:
    836   default: 'Test262Error: Expected a TypeError but got a RangeError (Testing with Float64Array.)'
    837   strict mode: 'Test262Error: Expected a TypeError but got a RangeError (Testing with Float64Array.)'
    838 test/built-ins/TypedArrayConstructors/ctors/buffer-arg/detachedbuffer.js:
    839   default: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all (Testing with Float64Array.)'
    840   strict mode: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all (Testing with Float64Array.)'
    841 test/built-ins/TypedArrayConstructors/ctors/buffer-arg/length-to-number-detachbuffer.js:
    842   default: 'Test262Error: Expected a TypeError but got a RangeError (Testing with Float64Array.)'
    843   strict mode: 'Test262Error: Expected a TypeError but got a RangeError (Testing with Float64Array.)'
    844 test/built-ins/TypedArrayConstructors/ctors/object-arg/length-excessive-throws.js:
    845   default: 'Test262Error: Expected a RangeError to be thrown but no exception was thrown at all (Testing with Float64Array.)'
    846   strict mode: 'Test262Error: Expected a RangeError to be thrown but no exception was thrown at all (Testing with Float64Array.)'
    847 test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/detached-when-species-retrieved-different-type.js:
    848   default: 'Test262Error: TypeError thrown for detached source buffer Expected a TypeError to be thrown but no exception was thrown at all (Testing with Float64Array.)'
    849   strict mode: 'Test262Error: TypeError thrown for detached source buffer Expected a TypeError to be thrown but no exception was thrown at all (Testing with Float64Array.)'
    850 test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/detached-when-species-retrieved-same-type.js:
    851   default: 'Test262Error: TypeError thrown for detached source buffer Expected a TypeError to be thrown but no exception was thrown at all (Testing with Float64Array.)'
    852   strict mode: 'Test262Error: TypeError thrown for detached source buffer Expected a TypeError to be thrown but no exception was thrown at all (Testing with Float64Array.)'
    853 test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-access-throws.js:
    854   default: 'Test262Error: Expected a Test262Error to be thrown but no exception was thrown at all (Testing with Float64Array.)'
    855   strict mode: 'Test262Error: Expected a Test262Error to be thrown but no exception was thrown at all (Testing with Float64Array.)'
    856 test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-custom-species-proto-from-ctor-realm.js:
    857   default: 'Test262Error: Expected SameValue(«[object ArrayBuffer]», «[object ArrayBuffer]») to be true (Testing with Float64Array.)'
    858   strict mode: 'Test262Error: Expected SameValue(«[object ArrayBuffer]», «[object ArrayBuffer]») to be true (Testing with Float64Array.)'
    859 test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-custom-species.js:
    860   default: 'Test262Error: Expected SameValue(«[object ArrayBuffer]», «[object Object]») to be true (Testing with Float64Array.)'
    861   strict mode: 'Test262Error: Expected SameValue(«[object ArrayBuffer]», «[object Object]») to be true (Testing with Float64Array.)'
    862 test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-not-object-throws.js:
    863   default: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all (Testing with Float64Array.)'
    864   strict mode: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all (Testing with Float64Array.)'
    865 test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-species-access-throws.js:
    866   default: 'Test262Error: Expected a Test262Error to be thrown but no exception was thrown at all (Testing with Float64Array.)'
    867   strict mode: 'Test262Error: Expected a Test262Error to be thrown but no exception was thrown at all (Testing with Float64Array.)'
    868 test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-species-not-ctor-throws.js:
    869   default: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all (Testing with Float64Array.)'
    870   strict mode: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all (Testing with Float64Array.)'
    871 test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/other-ctor-buffer-ctor-species-prototype-throws.js:
    872   default: 'Test262Error: Expected a Test262Error to be thrown but no exception was thrown at all (Testing with Float64Array.)'
    873   strict mode: 'Test262Error: Expected a Test262Error to be thrown but no exception was thrown at all (Testing with Float64Array.)'
    874 test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-access-throws.js:
    875   default: 'Test262Error: Expected a Test262Error to be thrown but no exception was thrown at all (Testing with Float64Array.)'
    876   strict mode: 'Test262Error: Expected a Test262Error to be thrown but no exception was thrown at all (Testing with Float64Array.)'
    877 test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-custom-proto-from-ctor-realm.js:
    878   default: 'Test262Error: Expected SameValue(«[object ArrayBuffer]», «[object ArrayBuffer]») to be true (Testing with Float64Array.)'
    879   strict mode: 'Test262Error: Expected SameValue(«[object ArrayBuffer]», «[object ArrayBuffer]») to be true (Testing with Float64Array.)'
    880 test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-custom.js:
    881   default: 'Test262Error: Expected SameValue(«[object ArrayBuffer]», «[object Object]») to be true (Testing with Float64Array.)'
    882   strict mode: 'Test262Error: Expected SameValue(«[object ArrayBuffer]», «[object Object]») to be true (Testing with Float64Array.)'
    883 test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-not-ctor.js:
    884   default: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all (Testing with Float64Array.)'
    885   strict mode: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all (Testing with Float64Array.)'
    886 test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-prototype-throws.js:
    887   default: 'Test262Error: Expected a Test262Error to be thrown but no exception was thrown at all (Testing with Float64Array.)'
    888   strict mode: 'Test262Error: Expected a Test262Error to be thrown but no exception was thrown at all (Testing with Float64Array.)'
    889 test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-species-throws.js:
    890   default: 'Test262Error: Expected a Test262Error to be thrown but no exception was thrown at all (Testing with Float64Array.)'
    891   strict mode: 'Test262Error: Expected a Test262Error to be thrown but no exception was thrown at all (Testing with Float64Array.)'
    892 test/built-ins/TypedArrayConstructors/ctors/typedarray-arg/same-ctor-buffer-ctor-value-not-obj-throws.js:
    893   default: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all (Testing with Float64Array.)'
    894   strict mode: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all (Testing with Float64Array.)'
    895835test/built-ins/TypedArrayConstructors/internals/Set/key-is-minus-zero.js:
    896836  default: 'Test262Error: Reflect.set(sample, "-0", 1) must return false Expected SameValue(«true», «false») to be true (Testing with Float64Array.)'
  • trunk/JSTests/wasm/fuzz/memory.js

    r216913 r270552  
    102102            case 'memory': {
    103103                const current = instance.exports.current();
    104                 const buffer = new Uint32Array(instance.exports.memory.buffer);
    105                 assert.eq(buffer.byteLength, current * pageSize);
     104                assert.eq(instance.exports.memory.buffer.byteLength, current * pageSize);
    106105                for (let access = tune.memoryGetCount; current && access; --access) {
    107106                    const address = (Math.random() * (current * pageSize - 4)) | 0;
  • trunk/JSTests/wasm/js-api/test_Data.js

    r235420 r270552  
    133133    const memory = new WebAssembly.Memory(emptyMemory);
    134134    assert.throws(() => new WebAssembly.Instance(module, { imp: { memory: memory } }), WebAssembly.LinkError, `Invalid data segment initialization: segment of 0 bytes memory of 0 bytes, at offset 65536, segment writes outside of memory`);
    135     assertMemoryAllZero(memory);
     135    assert.eq(memory.buffer.byteLength, 0);
    136136})();
    137137
  • trunk/Source/JavaScriptCore/ChangeLog

    r270550 r270552  
     12020-12-08  Ross Kirsling  <ross.kirsling@sony.com>
     2
     3        Align %TypedArray% constructor behavior with spec
     4        https://bugs.webkit.org/show_bug.cgi?id=219527
     5
     6        Reviewed by Yusuke Suzuki.
     7
     8        These should be the last JSC-side corrections for typed array behavior:
     9        namely, fixes for the constructor itself.
     10
     11        Broadly speaking, there are three fixes here:
     12        1. ArrayBuffer argument (https://tc39.es/ecma262/#sec-initializetypedarrayfromarraybuffer):
     13           We need to throw if the input buffer gets detached.
     14
     15        2. Array-like argument (https://tc39.es/ecma262/#sec-initializetypedarrayfromarraylike):
     16           length needs toLength, not toUInt32.
     17
     18        3. Typed array argument (https://tc39.es/ecma262/#sec-initializetypedarrayfromtypedarray):
     19           We need to support the case where the input typed array uses a custom ArrayBuffer.
     20           This case is *extremely* strange -- we still create the same type of typed array with a normal ArrayBuffer,
     21           but we override the prototype of that ArrayBuffer to inputTypedArray.buffer.constructor[@@species].prototype.
     22
     23        * JavaScriptCore.xcodeproj/project.pbxproj:
     24        * runtime/JSArrayBufferConstructor.cpp:
     25        * runtime/JSArrayBufferPrototype.cpp:
     26        (JSC::arrayBufferSpeciesConstructorSlow): Added.
     27        (JSC::speciesWatchpointIsValid): Moved.
     28        * runtime/JSArrayBufferPrototype.h:
     29        * runtime/JSArrayBufferPrototypeInlines.h: Added.
     30        * runtime/JSGenericTypedArrayViewConstructorInlines.h:
     31        (JSC::constructCustomArrayBufferIfNeeded): Added.
     32        (JSC::constructGenericTypedArrayViewWithArguments):
     33        * runtime/JSGlobalObject.h:
     34
    1352020-12-08  Yusuke Suzuki  <ysuzuki@apple.com>
    236
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r270420 r270552  
    13901390                A1D792FF1B43864B004516F5 /* IntlNumberFormatConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = A1D792F91B43864B004516F5 /* IntlNumberFormatConstructor.h */; };
    13911391                A1D793011B43864B004516F5 /* IntlNumberFormatPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = A1D792FB1B43864B004516F5 /* IntlNumberFormatPrototype.h */; };
     1392                A38D250E25800D440042BFDD /* JSArrayBufferPrototypeInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = A38D250D25800D430042BFDD /* JSArrayBufferPrototypeInlines.h */; };
    13921393                A3FF9BC72234749100B1A9AB /* YarrFlags.h in Headers */ = {isa = PBXBuildFile; fileRef = A3FF9BC52234746600B1A9AB /* YarrFlags.h */; settings = {ATTRIBUTES = (Private, ); }; };
    13931394                A503FA1A188E0FB000110F14 /* JavaScriptCallFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = A503FA14188E0FAF00110F14 /* JavaScriptCallFrame.h */; };
     
    43774378                A1FE1EB01C2C537E00A289FF /* DatePrototype.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = DatePrototype.js; sourceTree = "<group>"; };
    43784379                A27958D7FA1142B0AC9E364D /* WasmContextInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WasmContextInlines.h; sourceTree = "<group>"; };
     4380                A38D250D25800D430042BFDD /* JSArrayBufferPrototypeInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSArrayBufferPrototypeInlines.h; sourceTree = "<group>"; };
    43794381                A3AFF92B245A3CF900C9BA3B /* IntlLocale.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IntlLocale.h; sourceTree = "<group>"; };
    43804382                A3AFF92C245A3CFA00C9BA3B /* IntlLocaleConstructor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IntlLocaleConstructor.h; sourceTree = "<group>"; };
     
    74127414                                0F2B66B817B6B5AB00A7AE3F /* JSArrayBufferPrototype.cpp */,
    74137415                                0F2B66B917B6B5AB00A7AE3F /* JSArrayBufferPrototype.h */,
     7416                                A38D250D25800D430042BFDD /* JSArrayBufferPrototypeInlines.h */,
    74147417                                0F2B66BA17B6B5AB00A7AE3F /* JSArrayBufferView.cpp */,
    74157418                                0F2B66BB17B6B5AB00A7AE3F /* JSArrayBufferView.h */,
     
    99519954                                0F2B66E517B6B5AB00A7AE3F /* JSArrayBufferConstructor.h in Headers */,
    99529955                                0F2B66E717B6B5AB00A7AE3F /* JSArrayBufferPrototype.h in Headers */,
     9956                                A38D250E25800D440042BFDD /* JSArrayBufferPrototypeInlines.h in Headers */,
    99539957                                0F2B66E917B6B5AB00A7AE3F /* JSArrayBufferView.h in Headers */,
    99549958                                0F2B66EA17B6B5AB00A7AE3F /* JSArrayBufferViewInlines.h in Headers */,
  • trunk/Source/JavaScriptCore/runtime/JSArrayBufferConstructor.cpp

    r267594 r270552  
    2929#include "BuiltinNames.h"
    3030#include "JSArrayBuffer.h"
     31#include "JSArrayBufferPrototype.h"
    3132#include "JSArrayBufferView.h"
    3233#include "JSCInlines.h"
  • trunk/Source/JavaScriptCore/runtime/JSArrayBufferPrototype.cpp

    r270411 r270552  
    2828
    2929#include "JSArrayBuffer.h"
     30#include "JSArrayBufferPrototypeInlines.h"
    3031#include "JSCInlines.h"
    3132
    3233namespace JSC {
    33 namespace JSArrayBufferPrototypeInternal {
    34 static constexpr bool verbose = false;
    35 };
    3634
    3735static JSC_DECLARE_HOST_FUNCTION(arrayBufferProtoFuncSlice);
     
    4038static JSC_DECLARE_HOST_FUNCTION(sharedArrayBufferProtoGetterFuncByteLength);
    4139
    42 
    43 static ALWAYS_INLINE bool speciesWatchpointIsValid(VM& vm, JSObject* thisObject, ArrayBufferSharingMode mode)
    44 {
    45     JSGlobalObject* globalObject = thisObject->globalObject(vm);
    46     auto* prototype = globalObject->arrayBufferPrototype(mode);
    47 
    48     if (globalObject->arrayBufferSpeciesWatchpointSet(mode).stateOnJSThread() == ClearWatchpoint) {
    49         dataLogLnIf(JSArrayBufferPrototypeInternal::verbose, "Initializing ArrayBuffer species watchpoints for ArrayBuffer.prototype: ", pointerDump(prototype), " with structure: ", pointerDump(prototype->structure(vm)), "\nand ArrayBuffer: ", pointerDump(globalObject->arrayBufferConstructor(mode)), " with structure: ", pointerDump(globalObject->arrayBufferConstructor(mode)->structure(vm)));
    50         globalObject->tryInstallArrayBufferSpeciesWatchpoint(mode);
    51         ASSERT(globalObject->arrayBufferSpeciesWatchpointSet(mode).stateOnJSThread() != ClearWatchpoint);
    52     }
    53 
    54     return !thisObject->hasCustomProperties(vm)
    55         && prototype == thisObject->getPrototypeDirect(vm)
    56         && globalObject->arrayBufferSpeciesWatchpointSet(mode).stateOnJSThread() == IsWatched;
     40Optional<JSValue> arrayBufferSpeciesConstructorSlow(JSGlobalObject* globalObject, JSArrayBuffer* thisObject, ArrayBufferSharingMode mode)
     41{
     42    VM& vm = globalObject->vm();
     43    auto scope = DECLARE_THROW_SCOPE(vm);
     44
     45    bool isValid = speciesWatchpointIsValid(vm, thisObject, mode);
     46    scope.assertNoException();
     47    if (LIKELY(isValid))
     48        return WTF::nullopt;
     49
     50    JSValue constructor = thisObject->get(globalObject, vm.propertyNames->constructor);
     51    RETURN_IF_EXCEPTION(scope, WTF::nullopt);
     52    if (constructor.isConstructor(vm)) {
     53        JSObject* constructorObject = jsCast<JSObject*>(constructor);
     54        JSGlobalObject* globalObjectFromConstructor = constructorObject->globalObject(vm);
     55        bool isArrayBufferConstructorFromAnotherRealm = globalObject != globalObjectFromConstructor
     56            && constructorObject == globalObjectFromConstructor->arrayBufferConstructor(mode);
     57        if (isArrayBufferConstructorFromAnotherRealm)
     58            return WTF::nullopt;
     59    }
     60
     61    if (constructor.isUndefined())
     62        return WTF::nullopt;
     63
     64    if (!constructor.isObject()) {
     65        throwTypeError(globalObject, scope, "constructor property should not be null"_s);
     66        return WTF::nullopt;
     67    }
     68
     69    JSValue species = constructor.get(globalObject, vm.propertyNames->speciesSymbol);
     70    RETURN_IF_EXCEPTION(scope, WTF::nullopt);
     71
     72    return species.isUndefinedOrNull() ? WTF::nullopt : makeOptional(species);
    5773}
    5874
     
    7591    // Fast path in the normal case where the user has not set an own constructor and the ArrayBuffer.prototype.constructor is normal.
    7692    // We need prototype check for subclasses of ArrayBuffer, which are ArrayBuffer objects but have a different prototype by default.
    77     bool isValid = speciesWatchpointIsValid(vm, thisObject, mode);
    78     scope.assertNoException();
    79     if (LIKELY(isValid))
    80         return fastPathResult;
    81 
    82     JSValue constructor = thisObject->get(globalObject, vm.propertyNames->constructor);
     93    Optional<JSValue> species = arrayBufferSpeciesConstructor(globalObject, thisObject, mode);
    8394    RETURN_IF_EXCEPTION(scope, errorResult);
    84     if (constructor.isConstructor(vm)) {
    85         JSObject* constructorObject = jsCast<JSObject*>(constructor);
    86         JSGlobalObject* globalObjectFromConstructor = constructorObject->globalObject(vm);
    87         bool isArrayBufferConstructorFromAnotherRealm = globalObject != globalObjectFromConstructor
    88             && constructorObject == globalObjectFromConstructor->arrayBufferConstructor(mode);
    89         if (isArrayBufferConstructorFromAnotherRealm)
    90             return fastPathResult;
    91     }
    92     if (constructor.isObject()) {
    93         constructor = constructor.get(globalObject, vm.propertyNames->speciesSymbol);
    94         RETURN_IF_EXCEPTION(scope, errorResult);
    95         if (constructor.isNull())
    96             return fastPathResult;
    97     }
    98 
    99     if (constructor.isUndefined())
     95    if (!species)
    10096        return fastPathResult;
    10197
     
    104100    args.append(jsNumber(length));
    105101    ASSERT(!args.hasOverflowed());
    106     JSObject* newObject = construct(globalObject, constructor, args, "Species construction did not get a valid constructor");
     102    JSObject* newObject = construct(globalObject, species.value(), args, "Species construction did not get a valid constructor");
    107103    RETURN_IF_EXCEPTION(scope, errorResult);
    108104
  • trunk/Source/JavaScriptCore/runtime/JSArrayBufferPrototype.h

    r260415 r270552  
    5252};
    5353
     54Optional<JSValue> arrayBufferSpeciesConstructorSlow(JSGlobalObject*, JSArrayBuffer*, ArrayBufferSharingMode);
     55
    5456} // namespace JSC
  • trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewConstructorInlines.h

    r267603 r270552  
    11/*
    22 * Copyright (C) 2013-2020 Apple Inc. All rights reserved.
     3 * Copyright (C) 2020 Sony Interactive Entertainment Inc.
    34 *
    45 * Redistribution and use in source and binary forms, with or without
     
    3031#include "IteratorOperations.h"
    3132#include "JSArrayBuffer.h"
     33#include "JSArrayBufferPrototypeInlines.h"
    3234#include "JSCJSValueInlines.h"
    3335#include "JSDataView.h"
     
    104106}
    105107
     108inline JSArrayBuffer* constructCustomArrayBufferIfNeeded(JSGlobalObject* globalObject, JSArrayBuffer* source)
     109{
     110    VM& vm = globalObject->vm();
     111    auto scope = DECLARE_THROW_SCOPE(vm);
     112
     113    if (source->isShared())
     114        return nullptr;
     115
     116    Optional<JSValue> species = arrayBufferSpeciesConstructor(globalObject, source, ArrayBufferSharingMode::Default);
     117    RETURN_IF_EXCEPTION(scope, nullptr);
     118    if (!species)
     119        return nullptr;
     120
     121    if (!species->isConstructor(vm)) {
     122        throwTypeError(globalObject, scope, "species is not a constructor"_s);
     123        return nullptr;
     124    }
     125
     126    JSValue prototype = species->get(globalObject, vm.propertyNames->prototype);
     127    RETURN_IF_EXCEPTION(scope, nullptr);
     128
     129    auto buffer = ArrayBuffer::tryCreate(source->impl()->byteLength(), 1);
     130    if (!buffer) {
     131        throwOutOfMemoryError(globalObject, scope);
     132        return nullptr;
     133    }
     134
     135    auto result = JSArrayBuffer::create(vm, getFunctionRealm(vm, asObject(species.value()))->arrayBufferStructure(ArrayBufferSharingMode::Default), WTFMove(buffer));
     136    if (prototype.isObject())
     137        result->setPrototypeDirect(vm, prototype);
     138    return result;
     139}
     140
    106141template<typename ViewClass>
    107142inline JSObject* constructGenericTypedArrayViewWithArguments(JSGlobalObject* globalObject, Structure* structure, EncodedJSValue firstArgument, unsigned offset, Optional<unsigned> lengthOpt)
     
    114149    if (JSArrayBuffer* jsBuffer = jsDynamicCast<JSArrayBuffer*>(vm, firstValue)) {
    115150        RefPtr<ArrayBuffer> buffer = jsBuffer->impl();
     151        if (buffer->isDetached()) {
     152            throwTypeError(globalObject, scope, "Buffer is already detached"_s);
     153            return nullptr;
     154        }
     155
    116156        unsigned length = 0;
    117 
    118157        if (lengthOpt)
    119158            length = lengthOpt.value();
     
    141180    if (JSObject* object = jsDynamicCast<JSObject*>(vm, firstValue)) {
    142181        unsigned length;
    143 
    144         if (isTypedView(object->classInfo(vm)->typedArrayStorageType))
    145             length = jsCast<JSArrayBufferView*>(object)->length();
    146         else {
     182        JSArrayBuffer* customBuffer = nullptr;
     183
     184        if (isTypedView(object->classInfo(vm)->typedArrayStorageType)) {
     185            auto* view = jsCast<JSArrayBufferView*>(object);
     186            length = view->length();
     187
     188            customBuffer = constructCustomArrayBufferIfNeeded(globalObject, view->possiblySharedJSBuffer(globalObject));
     189            RETURN_IF_EXCEPTION(scope, nullptr);
     190
     191            if (view->isDetached()) {
     192                throwTypeError(globalObject, scope, "Underlying ArrayBuffer has been detached from the view"_s);
     193                return nullptr;
     194            }
     195        } else {
    147196            // This getPropertySlot operation should not be observed by the Proxy.
    148197            // So we use VMInquiry. And purge the opaque object cases (proxy and namespace object) by isTaintedByOpaqueObject() guard.
     
    174223                JSValue value = lengthSlot.getValue(globalObject, vm.propertyNames->length);
    175224                RETURN_IF_EXCEPTION(scope, nullptr);
    176                 length = value.toUInt32(globalObject);
     225                length = value.toLength(globalObject);
    177226                RETURN_IF_EXCEPTION(scope, nullptr);
    178227            }
    179228        }
    180229
    181        
    182         ViewClass* result = ViewClass::createUninitialized(globalObject, structure, length);
     230        ViewClass* result = customBuffer
     231            ? ViewClass::create(globalObject, structure, customBuffer->impl(), 0, length)
     232            : ViewClass::createUninitialized(globalObject, structure, length);
    183233        EXCEPTION_ASSERT(!!scope.exception() == !result);
    184234        if (UNLIKELY(!result))
    185235            return nullptr;
    186        
     236
    187237        scope.release();
    188238        if (!result->set(globalObject, 0, object, 0, length))
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h

    r269574 r270552  
    3131#include "InternalFunction.h"
    3232#include "JSArray.h"
    33 #include "JSArrayBufferPrototype.h"
    3433#include "JSClassRef.h"
    3534#include "JSGlobalLexicalEnvironment.h"
Note: See TracChangeset for help on using the changeset viewer.