+ return JSValue::encode(jsString(exec, builder.toString()));
+}
+
+EncodedJSValue JSC_HOST_CALL globalFuncThrowTypeError(ExecState* exec)
+{
+ return throwVMTypeError(exec);
+}
+
+class GlobalFuncProtoGetterFunctor {
+public:
+ GlobalFuncProtoGetterFunctor(JSObject* thisObject)
+ : m_hasSkippedFirstFrame(false)
+ , m_thisObject(thisObject)
+ , m_result(JSValue::encode(jsUndefined()))
+ {
+ }
+
+ EncodedJSValue result() { return m_result; }
+
+ StackVisitor::Status operator()(StackVisitor& visitor)
+ {
+ if (!m_hasSkippedFirstFrame) {
+ m_hasSkippedFirstFrame = true;
+ return StackVisitor::Continue;
+ }
+
+ if (m_thisObject->allowsAccessFrom(visitor->callFrame()))
+ m_result = JSValue::encode(m_thisObject->prototype());
+
+ return StackVisitor::Done;
+ }
+
+private:
+ bool m_hasSkippedFirstFrame;
+ JSObject* m_thisObject;
+ EncodedJSValue m_result;
+};
+
+EncodedJSValue JSC_HOST_CALL globalFuncProtoGetter(ExecState* exec)
+{
+ if (exec->thisValue().isUndefinedOrNull())
+ return throwVMError(exec, createTypeError(exec, "Can't convert undefined or null to object"));
+
+ JSObject* thisObject = jsDynamicCast<JSObject*>(exec->thisValue().toThis(exec, NotStrictMode));
+
+ if (!thisObject)
+ return JSValue::encode(exec->thisValue().synthesizePrototype(exec));
+
+ GlobalFuncProtoGetterFunctor functor(thisObject);
+ exec->iterate(functor);
+ return functor.result();
+}
+
+class GlobalFuncProtoSetterFunctor {
+public:
+ GlobalFuncProtoSetterFunctor(JSObject* thisObject)
+ : m_hasSkippedFirstFrame(false)
+ , m_allowsAccess(false)
+ , m_thisObject(thisObject)
+ {
+ }
+
+ bool allowsAccess() const { return m_allowsAccess; }
+
+ StackVisitor::Status operator()(StackVisitor& visitor)
+ {
+ if (!m_hasSkippedFirstFrame) {
+ m_hasSkippedFirstFrame = true;
+ return StackVisitor::Continue;
+ }
+
+ m_allowsAccess = m_thisObject->allowsAccessFrom(visitor->callFrame());
+ return StackVisitor::Done;
+ }
+
+private:
+ bool m_hasSkippedFirstFrame;
+ bool m_allowsAccess;
+ JSObject* m_thisObject;
+};
+
+bool checkProtoSetterAccessAllowed(ExecState* exec, JSObject* object)
+{
+ GlobalFuncProtoSetterFunctor functor(object);
+ exec->iterate(functor);
+ return functor.allowsAccess();
+}
+
+EncodedJSValue JSC_HOST_CALL globalFuncProtoSetter(ExecState* exec)
+{
+ if (exec->thisValue().isUndefinedOrNull())
+ return throwVMError(exec, createTypeError(exec, "Can't convert undefined or null to object"));
+
+ JSValue value = exec->argument(0);
+
+ JSObject* thisObject = jsDynamicCast<JSObject*>(exec->thisValue().toThis(exec, NotStrictMode));
+
+ // Setting __proto__ of a primitive should have no effect.
+ if (!thisObject)
+ return JSValue::encode(jsUndefined());
+
+ if (!checkProtoSetterAccessAllowed(exec, thisObject))
+ return JSValue::encode(jsUndefined());
+
+ // Setting __proto__ to a non-object, non-null value is silently ignored to match Mozilla.
+ if (!value.isObject() && !value.isNull())
+ return JSValue::encode(jsUndefined());
+
+ if (!thisObject->isExtensible())
+ return throwVMError(exec, createTypeError(exec, StrictModeReadonlyPropertyWriteError));
+
+ if (!thisObject->setPrototypeWithCycleCheck(exec, value))
+ exec->vm().throwException(exec, createError(exec, ASCIILiteral("cyclic __proto__ value")));
+ return JSValue::encode(jsUndefined());
+}
+
+EncodedJSValue JSC_HOST_CALL globalFuncBuiltinLog(ExecState* exec)
+{
+ dataLog(exec->argument(0).toWTFString(exec), "\n");
+ return JSValue::encode(jsUndefined());