summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/runtime/JSDataView.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/runtime/JSDataView.cpp')
-rw-r--r--Source/JavaScriptCore/runtime/JSDataView.cpp116
1 files changed, 98 insertions, 18 deletions
diff --git a/Source/JavaScriptCore/runtime/JSDataView.cpp b/Source/JavaScriptCore/runtime/JSDataView.cpp
index 77640cdaf..1f67fbdca 100644
--- a/Source/JavaScriptCore/runtime/JSDataView.cpp
+++ b/Source/JavaScriptCore/runtime/JSDataView.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -29,12 +29,13 @@
#include "ArrayBufferView.h"
#include "DataView.h"
#include "Error.h"
-#include "Operations.h"
+#include "JSCInlines.h"
+#include "TypeError.h"
namespace JSC {
const ClassInfo JSDataView::s_info = {
- "DataView", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JSDataView)};
+ "DataView", &Base::s_info, 0, CREATE_METHOD_TABLE(JSDataView)};
JSDataView::JSDataView(VM& vm, ConstructionContext& context, ArrayBuffer* buffer)
: Base(vm, context)
@@ -43,18 +44,23 @@ JSDataView::JSDataView(VM& vm, ConstructionContext& context, ArrayBuffer* buffer
}
JSDataView* JSDataView::create(
- ExecState* exec, Structure* structure, PassRefPtr<ArrayBuffer> passedBuffer,
+ ExecState* exec, Structure* structure, RefPtr<ArrayBuffer>&& buffer,
unsigned byteOffset, unsigned byteLength)
{
- RefPtr<ArrayBuffer> buffer = passedBuffer;
- if (!ArrayBufferView::verifySubRange<uint8_t>(buffer, byteOffset, byteLength)) {
- throwVMError(
- exec, createRangeError(exec, "Byte offset and length out of range of buffer"));
- return 0;
- }
VM& vm = exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ ASSERT(buffer);
+ if (!ArrayBufferView::verifySubRangeLength(*buffer, byteOffset, byteLength, sizeof(uint8_t))) {
+ throwVMError(exec, scope, createRangeError(exec, ASCIILiteral("Length out of range of buffer")));
+ return nullptr;
+ }
+ if (!ArrayBufferView::verifyByteOffsetAlignment(byteOffset, sizeof(uint8_t))) {
+ throwException(exec, scope, createRangeError(exec, ASCIILiteral("Byte offset is not aligned")));
+ return nullptr;
+ }
ConstructionContext context(
- structure, buffer, byteOffset, byteLength, ConstructionContext::DataView);
+ structure, buffer.copyRef(), byteOffset, byteLength, ConstructionContext::DataView);
ASSERT(context);
JSDataView* result =
new (NotNull, allocateCell<JSDataView>(vm.heap)) JSDataView(vm, context, buffer.get());
@@ -74,15 +80,26 @@ JSDataView* JSDataView::create(ExecState*, Structure*, unsigned)
return 0;
}
-bool JSDataView::set(ExecState*, JSObject*, unsigned, unsigned)
+bool JSDataView::set(ExecState*, unsigned, JSObject*, unsigned, unsigned)
{
UNREACHABLE_FOR_PLATFORM();
return false;
}
-PassRefPtr<DataView> JSDataView::typedImpl()
+bool JSDataView::setIndex(ExecState*, unsigned, JSValue)
{
- return DataView::create(buffer(), byteOffset(), length());
+ UNREACHABLE_FOR_PLATFORM();
+ return false;
+}
+
+RefPtr<DataView> JSDataView::possiblySharedTypedImpl()
+{
+ return DataView::create(possiblySharedBuffer(), byteOffset(), length());
+}
+
+RefPtr<DataView> JSDataView::unsharedTypedImpl()
+{
+ return DataView::create(unsharedBuffer(), byteOffset(), length());
}
bool JSDataView::getOwnPropertySlot(
@@ -93,27 +110,90 @@ bool JSDataView::getOwnPropertySlot(
slot.setValue(thisObject, DontEnum | ReadOnly, jsNumber(thisObject->m_length));
return true;
}
-
+ if (propertyName == exec->propertyNames().byteOffset) {
+ slot.setValue(thisObject, DontEnum | ReadOnly, jsNumber(thisObject->byteOffset()));
+ return true;
+ }
+
return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
}
+bool JSDataView::put(
+ JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value,
+ PutPropertySlot& slot)
+{
+ VM& vm = exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ JSDataView* thisObject = jsCast<JSDataView*>(cell);
+
+ if (UNLIKELY(isThisValueAltered(slot, thisObject))) {
+ scope.release();
+ return ordinarySetSlow(exec, thisObject, propertyName, value, slot.thisValue(), slot.isStrictMode());
+ }
+
+ if (propertyName == vm.propertyNames->byteLength
+ || propertyName == vm.propertyNames->byteOffset)
+ return typeError(exec, scope, slot.isStrictMode(), ASCIILiteral("Attempting to write to read-only typed array property."));
+
+ scope.release();
+ return Base::put(thisObject, exec, propertyName, value, slot);
+}
+
+bool JSDataView::defineOwnProperty(
+ JSObject* object, ExecState* exec, PropertyName propertyName,
+ const PropertyDescriptor& descriptor, bool shouldThrow)
+{
+ VM& vm = exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ JSDataView* thisObject = jsCast<JSDataView*>(object);
+ if (propertyName == vm.propertyNames->byteLength
+ || propertyName == vm.propertyNames->byteOffset)
+ return typeError(exec, scope, shouldThrow, ASCIILiteral("Attempting to define read-only typed array property."));
+
+ return Base::defineOwnProperty(thisObject, exec, propertyName, descriptor, shouldThrow);
+}
+
+bool JSDataView::deleteProperty(
+ JSCell* cell, ExecState* exec, PropertyName propertyName)
+{
+ JSDataView* thisObject = jsCast<JSDataView*>(cell);
+ if (propertyName == exec->propertyNames().byteLength
+ || propertyName == exec->propertyNames().byteOffset)
+ return false;
+
+ return Base::deleteProperty(thisObject, exec, propertyName);
+}
+
+void JSDataView::getOwnNonIndexPropertyNames(
+ JSObject* object, ExecState* exec, PropertyNameArray& array, EnumerationMode mode)
+{
+ JSDataView* thisObject = jsCast<JSDataView*>(object);
+
+ if (mode.includeDontEnumProperties()) {
+ array.add(exec->propertyNames().byteOffset);
+ array.add(exec->propertyNames().byteLength);
+ }
+
+ Base::getOwnNonIndexPropertyNames(thisObject, exec, array, mode);
+}
+
ArrayBuffer* JSDataView::slowDownAndWasteMemory(JSArrayBufferView*)
{
UNREACHABLE_FOR_PLATFORM();
return 0;
}
-PassRefPtr<ArrayBufferView> JSDataView::getTypedArrayImpl(JSArrayBufferView* object)
+RefPtr<ArrayBufferView> JSDataView::getTypedArrayImpl(JSArrayBufferView* object)
{
JSDataView* thisObject = jsCast<JSDataView*>(object);
- return thisObject->typedImpl();
+ return thisObject->possiblySharedTypedImpl();
}
Structure* JSDataView::createStructure(
VM& vm, JSGlobalObject* globalObject, JSValue prototype)
{
return Structure::create(
- vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info(),
+ vm, globalObject, prototype, TypeInfo(DataViewType, StructureFlags), info(),
NonArray);
}