30ReturnedValue SharedArrayBufferCtor::virtualCallAsConstructor(
const FunctionObject *f,
const Value *argv,
int argc,
const Value *newTarget)
33 if (newTarget->isUndefined())
34 return scope.engine->throwTypeError();
36 const double len = argc ? argv[0].toInteger() : 0;
37 if (scope.hasException())
38 return Encode::undefined();
39 if (len < 0 || len >= std::numeric_limits<
int>::max())
40 return scope.engine->throwRangeError(QStringLiteral(
"SharedArrayBuffer: Invalid length."));
42 Scoped<SharedArrayBuffer> a(
43 scope, scope.engine->memoryManager->allocate<SharedArrayBuffer>(size_t(len)));
44 if (scope.hasException())
45 return Encode::undefined();
47 return a->asReturnedValue();
56ReturnedValue ArrayBufferCtor::virtualCallAsConstructor(
const FunctionObject *f,
const Value *argv,
int argc,
const Value *newTarget)
58 ExecutionEngine *v4 = f->engine();
61 ScopedValue l(scope, argc ? argv[0] : Value::undefinedValue());
62 double dl = l->toInteger();
64 return Encode::undefined();
65 uint len = (uint)qBound(0., dl, (
double)UINT_MAX);
67 return v4->throwRangeError(QLatin1String(
"ArrayBuffer constructor: invalid length"));
69 Scoped<ArrayBuffer> a(scope, v4->newArrayBuffer(len));
70 if (newTarget->heapObject() != f->heapObject() && newTarget->isFunctionObject()) {
71 const FunctionObject *nt =
static_cast<
const FunctionObject *>(newTarget);
72 ScopedObject o(scope, nt->protoProperty());
76 if (scope.hasException())
77 return Encode::undefined();
79 return a->asReturnedValue();
95void Heap::SharedArrayBuffer::init(size_t length)
98 std::pair<QTypedArrayData<
char> *,
char *> pair;
99 if (length < UINT_MAX)
100 pair = QTypedArrayData<
char>::allocate(length + 1);
102 new (&arrayDataPointerStorage) QArrayDataPointer<
char>();
103 internalClass->engine->throwRangeError(QStringLiteral(
"ArrayBuffer: out of memory"));
106 auto data =
new (&arrayDataPointerStorage) QArrayDataPointer<
char>{
107 pair.first, pair.second, qsizetype(length) };
110 memset(data->data(), 0, length + 1);
138void SharedArrayBufferPrototype::init(ExecutionEngine *engine, Object *ctor)
141 ScopedObject o(scope);
142 ctor->defineReadonlyConfigurableProperty(engine->id_length(), Value::fromInt32(1));
143 ctor->defineReadonlyProperty(engine->id_prototype(), (o =
this));
144 ctor->addSymbolSpecies();
146 defineDefaultProperty(engine->id_constructor(), (o = ctor));
147 defineAccessorProperty(QStringLiteral(
"byteLength"), method_get_byteLength,
nullptr);
148 defineDefaultProperty(QStringLiteral(
"slice"), method_slice, 2);
149 ScopedString name(scope, engine->newString(QStringLiteral(
"SharedArrayBuffer")));
150 defineReadonlyConfigurableProperty(scope.engine->symbol_toStringTag(), name);
153ReturnedValue SharedArrayBufferPrototype::method_get_byteLength(
const FunctionObject *b,
const Value *thisObject,
const Value *,
int)
155 const SharedArrayBuffer *a = thisObject->as<SharedArrayBuffer>();
156 if (!a || a->hasDetachedArrayData() || !a->isSharedArrayBuffer())
157 return b->engine()->throwTypeError();
159 return Encode(a->arrayDataLength());
167ReturnedValue SharedArrayBufferPrototype::slice(
const FunctionObject *b,
const Value *thisObject,
const Value *argv,
int argc,
bool shared)
170 const SharedArrayBuffer *a = thisObject->as<SharedArrayBuffer>();
171 if (!a || a->hasDetachedArrayData() || (a->isSharedArrayBuffer() != shared))
172 return scope.engine->throwTypeError();
174 const uint aDataLength = a->arrayDataLength();
176 double start = argc > 0 ? argv[0].toInteger() : 0;
177 double end = (argc < 2 || argv[1].isUndefined()) ? aDataLength : argv[1].toInteger();
178 if (scope.hasException())
179 return QV4::Encode::undefined();
181 double first = (start < 0) ? qMax(aDataLength + start, 0.) : qMin(start,
double(aDataLength));
182 double final = (end < 0) ? qMax(aDataLength + end, 0.) : qMin(end,
double(aDataLength));
184 const FunctionObject *constructor = a->speciesConstructor(scope, shared ? scope.engine->sharedArrayBufferCtor() : scope.engine->arrayBufferCtor());
186 return scope.engine->throwTypeError();
188 double newLen = qMax(final - first, 0.);
189 ScopedValue argument(scope, QV4::Encode(newLen));
190 QV4::Scoped<SharedArrayBuffer> newBuffer(scope, constructor->callAsConstructor(argument, 1));
191 if (!newBuffer || newBuffer->arrayDataLength() < newLen ||
192 newBuffer->hasDetachedArrayData() || (newBuffer->isSharedArrayBuffer() != shared) ||
193 newBuffer->sameValue(*a) ||
194 a->hasDetachedArrayData())
195 return scope.engine->throwTypeError();
197 memcpy(newBuffer->arrayData(), a->constArrayData() + (uint)first, newLen);
198 return newBuffer->asReturnedValue();
202void ArrayBufferPrototype::init(ExecutionEngine *engine, Object *ctor)
205 ScopedObject o(scope);
206 ctor->defineReadonlyConfigurableProperty(engine->id_length(), Value::fromInt32(1));
207 ctor->defineReadonlyProperty(engine->id_prototype(), (o =
this));
208 ctor->defineDefaultProperty(QStringLiteral(
"isView"), ArrayBufferCtor::method_isView, 1);
209 ctor->addSymbolSpecies();
211 defineDefaultProperty(engine->id_constructor(), (o = ctor));
212 defineAccessorProperty(QStringLiteral(
"byteLength"), method_get_byteLength,
nullptr);
213 defineDefaultProperty(QStringLiteral(
"slice"), method_slice, 2);
214 defineDefaultProperty(QStringLiteral(
"toString"), method_toString, 0);
215 ScopedString name(scope, engine->newString(QStringLiteral(
"ArrayBuffer")));
216 defineReadonlyConfigurableProperty(scope.engine->symbol_toStringTag(), name);
219ReturnedValue ArrayBufferPrototype::method_get_byteLength(
const FunctionObject *f,
const Value *thisObject,
const Value *,
int)
221 const ArrayBuffer *a = thisObject->as<ArrayBuffer>();
222 if (!a || a->isSharedArrayBuffer())
223 return f->engine()->throwTypeError();
225 if (a->hasDetachedArrayData())
228 return Encode(a->arrayDataLength());