+ DECLARE_INFO;
+
+private:
+ Root* m_root;
+};
+
+class ElementHandleOwner : public WeakHandleOwner {
+public:
+ virtual bool isReachableFromOpaqueRoots(Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor)
+ {
+ Element* element = jsCast<Element*>(handle.slot()->asCell());
+ return visitor.containsOpaqueRoot(element->root());
+ }
+};
+
+class Masquerader : public JSNonFinalObject {
+public:
+ Masquerader(VM& vm, Structure* structure)
+ : Base(vm, structure)
+ {
+ }
+
+ typedef JSNonFinalObject Base;
+
+ static Masquerader* create(VM& vm, JSGlobalObject* globalObject)
+ {
+ globalObject->masqueradesAsUndefinedWatchpoint()->fireAll();
+ Structure* structure = createStructure(vm, globalObject, jsNull());
+ Masquerader* result = new (NotNull, allocateCell<Masquerader>(vm.heap, sizeof(Masquerader))) Masquerader(vm, structure);
+ result->finishCreation(vm);
+ return result;
+ }
+
+ static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+ {
+ return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
+ }
+
+ DECLARE_INFO;
+
+protected:
+ static const unsigned StructureFlags = JSC::MasqueradesAsUndefined | Base::StructureFlags;
+};
+
+class Root : public JSDestructibleObject {
+public:
+ Root(VM& vm, Structure* structure)
+ : Base(vm, structure)
+ {
+ }
+
+ Element* element()
+ {
+ return m_element.get();
+ }
+
+ void setElement(Element* element)
+ {
+ Weak<Element> newElement(element, Element::handleOwner());
+ m_element.swap(newElement);
+ }
+
+ static Root* create(VM& vm, JSGlobalObject* globalObject)
+ {
+ Structure* structure = createStructure(vm, globalObject, jsNull());
+ Root* root = new (NotNull, allocateCell<Root>(vm.heap, sizeof(Root))) Root(vm, structure);
+ root->finishCreation(vm);
+ return root;
+ }
+
+ typedef JSDestructibleObject Base;
+
+ DECLARE_INFO;
+ static const bool needsDestruction = true;
+
+ static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+ {
+ return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
+ }
+
+ static void visitChildren(JSCell* thisObject, SlotVisitor& visitor)
+ {
+ Base::visitChildren(thisObject, visitor);
+ visitor.addOpaqueRoot(thisObject);
+ }
+
+private:
+ Weak<Element> m_element;
+};
+
+class ImpureGetter : public JSNonFinalObject {
+public:
+ ImpureGetter(VM& vm, Structure* structure)
+ : Base(vm, structure)
+ {
+ }
+
+ DECLARE_INFO;
+ typedef JSNonFinalObject Base;
+
+ static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+ {
+ return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
+ }
+
+ static ImpureGetter* create(VM& vm, Structure* structure, JSObject* delegate)
+ {
+ ImpureGetter* getter = new (NotNull, allocateCell<ImpureGetter>(vm.heap, sizeof(ImpureGetter))) ImpureGetter(vm, structure);
+ getter->finishCreation(vm, delegate);
+ return getter;
+ }
+
+ void finishCreation(VM& vm, JSObject* delegate)
+ {
+ Base::finishCreation(vm);
+ if (delegate)
+ m_delegate.set(vm, this, delegate);
+ }
+
+ static const unsigned StructureFlags = JSC::HasImpureGetOwnPropertySlot | JSC::OverridesGetOwnPropertySlot | JSC::OverridesVisitChildren | Base::StructureFlags;
+
+ static bool getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName name, PropertySlot& slot)
+ {
+ ImpureGetter* thisObject = jsCast<ImpureGetter*>(object);
+
+ if (thisObject->m_delegate && thisObject->m_delegate->getPropertySlot(exec, name, slot))
+ return true;
+
+ return Base::getOwnPropertySlot(object, exec, name, slot);
+ }
+
+ static void visitChildren(JSCell* cell, SlotVisitor& visitor)
+ {
+ Base::visitChildren(cell, visitor);
+ ImpureGetter* thisObject = jsCast<ImpureGetter*>(cell);
+ visitor.append(&thisObject->m_delegate);
+ }
+
+ void setDelegate(VM& vm, JSObject* delegate)
+ {
+ m_delegate.set(vm, this, delegate);
+ }
+
+private:
+ 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();
+#if !COMPILER(CLANG)
+ return true;
+#endif
+ }
+
+ 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()
+{
+ static ElementHandleOwner* owner = 0;
+ if (!owner)
+ owner = new ElementHandleOwner();
+ return owner;
+}
+
+void Element::finishCreation(VM& vm)
+{
+ Base::finishCreation(vm);
+ m_root->setElement(this);
+}
+
+}
+
+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*);
+
+static EncodedJSValue JSC_HOST_CALL functionSetElementRoot(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionCreateRoot(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionCreateElement(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionGetElement(ExecState*);