Modified: trunk/Source/_javascript_Core/jsc.cpp (171389 => 171390)
--- trunk/Source/_javascript_Core/jsc.cpp 2014-07-23 04:04:33 UTC (rev 171389)
+++ trunk/Source/_javascript_Core/jsc.cpp 2014-07-23 04:18:35 UTC (rev 171390)
@@ -22,6 +22,7 @@
#include "config.h"
+#include "ArrayPrototype.h"
#include "ButterflyInlines.h"
#include "BytecodeGenerator.h"
#include "Completion.h"
@@ -114,6 +115,7 @@
class ElementHandleOwner;
class Masuqerader;
class Root;
+class RuntimeArray;
class Element : public JSNonFinalObject {
public:
@@ -293,10 +295,117 @@
WriteBarrier<JSObject> m_delegate;
};
+class RuntimeArray : public JSArray {
+public:
+ typedef JSArray Base;
+
+ static RuntimeArray* create(ExecState* exec)
+ {
+ VM& vm = exec->vm();
+ JSGlobalObject* globalObject = exec->lexicalGlobalObject();
+ Structure* structure = createStructure(vm, globalObject, createPrototype(vm, globalObject));
+ RuntimeArray* runtimeArray = new (NotNull, allocateCell<RuntimeArray>(*exec->heap())) RuntimeArray(exec, structure);
+ runtimeArray->finishCreation(exec);
+ vm.heap.addFinalizer(runtimeArray, destroy);
+ return runtimeArray;
+ }
+
+ ~RuntimeArray() { }
+
+ static void destroy(JSCell* cell)
+ {
+ static_cast<RuntimeArray*>(cell)->RuntimeArray::~RuntimeArray();
+ }
+
+ static const bool needsDestruction = false;
+
+ static bool getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
+ {
+ RuntimeArray* thisObject = jsCast<RuntimeArray*>(object);
+ if (propertyName == exec->propertyNames().length) {
+ slot.setCacheableCustom(thisObject, DontDelete | ReadOnly | DontEnum, thisObject->lengthGetter);
+ return true;
+ }
+
+ unsigned index = propertyName.asIndex();
+ if (index < thisObject->getLength()) {
+ ASSERT(index != PropertyName::NotAnIndex);
+ slot.setValue(thisObject, DontDelete | DontEnum, jsNumber(thisObject->m_vector[index]));
+ return true;
+ }
+
+ return JSObject::getOwnPropertySlot(thisObject, exec, propertyName, slot);
+ }
+
+ static bool getOwnPropertySlotByIndex(JSObject* object, ExecState* exec, unsigned index, PropertySlot& slot)
+ {
+ RuntimeArray* thisObject = jsCast<RuntimeArray*>(object);
+ if (index < thisObject->getLength()) {
+ slot.setValue(thisObject, DontDelete | DontEnum, jsNumber(thisObject->m_vector[index]));
+ return true;
+ }
+
+ return JSObject::getOwnPropertySlotByIndex(thisObject, exec, index, slot);
+ }
+
+ static NO_RETURN_DUE_TO_CRASH void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&)
+ {
+ RELEASE_ASSERT_NOT_REACHED();
+ }
+
+ static NO_RETURN_DUE_TO_CRASH bool deleteProperty(JSCell*, ExecState*, PropertyName)
+ {
+ RELEASE_ASSERT_NOT_REACHED();
+ }
+
+ unsigned getLength() const { return m_vector.size(); }
+
+ DECLARE_INFO;
+
+ static ArrayPrototype* createPrototype(VM&, JSGlobalObject* globalObject)
+ {
+ return globalObject->arrayPrototype();
+ }
+
+ static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+ {
+ return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info(), ArrayClass);
+ }
+
+protected:
+ void finishCreation(ExecState* exec)
+ {
+ Base::finishCreation(exec->vm());
+ ASSERT(inherits(info()));
+
+ for (size_t i = 0; i < exec->argumentCount(); i++)
+ m_vector.append(exec->argument(i).toInt32(exec));
+ }
+
+ static const unsigned StructureFlags = OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | OverridesGetPropertyNames | JSArray::StructureFlags;
+
+private:
+ RuntimeArray(ExecState* exec, Structure* structure)
+ : JSArray(exec->vm(), structure, 0)
+ {
+ }
+
+ static EncodedJSValue lengthGetter(ExecState* exec, JSObject*, EncodedJSValue thisValue, PropertyName)
+ {
+ RuntimeArray* thisObject = jsDynamicCast<RuntimeArray*>(JSValue::decode(thisValue));
+ if (!thisObject)
+ return throwVMTypeError(exec);
+ return JSValue::encode(jsNumber(thisObject->getLength()));
+ }
+
+ Vector<int> m_vector;
+};
+
const ClassInfo Element::s_info = { "Element", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(Element) };
const ClassInfo Masquerader::s_info = { "Masquerader", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(Masquerader) };
const ClassInfo Root::s_info = { "Root", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(Root) };
const ClassInfo ImpureGetter::s_info = { "ImpureGetter", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(ImpureGetter) };
+const ClassInfo RuntimeArray::s_info = { "RuntimeArray", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(RuntimeArray) };
ElementHandleOwner* Element::handleOwner()
{
@@ -317,6 +426,7 @@
static bool fillBufferWithContentsOfFile(const String& fileName, Vector<char>& buffer);
static EncodedJSValue JSC_HOST_CALL functionCreateProxy(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionCreateRuntimeArray(ExecState*);
static EncodedJSValue JSC_HOST_CALL functionCreateImpureGetter(ExecState*);
static EncodedJSValue JSC_HOST_CALL functionSetImpureGetterDelegate(ExecState*);
@@ -502,6 +612,7 @@
addFunction(vm, "makeMasquerader", functionMakeMasquerader, 0);
addFunction(vm, "createProxy", functionCreateProxy, 1);
+ addFunction(vm, "createRuntimeArray", functionCreateRuntimeArray, 0);
addFunction(vm, "createImpureGetter", functionCreateImpureGetter, 1);
addFunction(vm, "setImpureGetterDelegate", functionSetImpureGetterDelegate, 2);
@@ -675,6 +786,13 @@
return JSValue::encode(proxy);
}
+EncodedJSValue JSC_HOST_CALL functionCreateRuntimeArray(ExecState* exec)
+{
+ JSLockHolder lock(exec);
+ RuntimeArray* array = RuntimeArray::create(exec);
+ return JSValue::encode(array);
+}
+
EncodedJSValue JSC_HOST_CALL functionCreateImpureGetter(ExecState* exec)
{
JSLockHolder lock(exec);
Modified: trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp (171389 => 171390)
--- trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp 2014-07-23 04:04:33 UTC (rev 171389)
+++ trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp 2014-07-23 04:18:35 UTC (rev 171390)
@@ -159,6 +159,8 @@
static ALWAYS_INLINE unsigned getLength(ExecState* exec, JSObject* obj)
{
+ if (isJSArray(obj))
+ return jsCast<JSArray*>(obj)->length();
return obj->get(exec, exec->propertyNames().length).toUInt32(exec);
}
@@ -412,6 +414,8 @@
for (; k < length; k++) {
JSValue element = thisObj->get(exec, k);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
if (!element.isUndefinedOrNull())
stringJoiner.append(element.toWTFStringInline(exec));
else
@@ -429,9 +433,11 @@
Checked<unsigned, RecordOverflow> finalArraySize = 0;
for (size_t i = 0;;) {
- if (JSArray* currentArray = jsDynamicCast<JSArray*>(curArg))
- finalArraySize += currentArray->length();
- else
+ if (JSArray* currentArray = jsDynamicCast<JSArray*>(curArg)) {
+ finalArraySize += getLength(exec, currentArray);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
+ } else
finalArraySize++;
if (i == argCount)
break;
@@ -450,7 +456,9 @@
unsigned n = 0;
for (size_t i = 0;;) {
if (JSArray* currentArray = jsDynamicCast<JSArray*>(curArg)) {
- unsigned length = currentArray->length();
+ unsigned length = getLength(exec, currentArray);
+ if (exec->hadException())
+ return JSValue::encode(jsUndefined());
for (unsigned k = 0; k < length; ++k) {
JSValue v = getProperty(exec, currentArray, k);
if (exec->hadException())