bool pluginElementCustomPut(ExecState* exec, PropertyName propertyName, JSValue value, JSHTMLElement* element, PutPropertySlot& slot, bool& putResult) { JSObject* scriptObject = pluginScriptObject(exec, element); if (!scriptObject) return false; if (!scriptObject->hasProperty(exec, propertyName)) return false; putResult = scriptObject->methodTable()->put(scriptObject, exec, propertyName, value, slot); return true; }
bool runtimeObjectCustomPut(ExecState* exec, const Identifier& propertyName, JSValue value, JSHTMLElement* element, PutPropertySlot& slot) { JSObject* scriptObject = pluginScriptObject(exec, element); if (!scriptObject) return 0; if (!scriptObject->hasProperty(exec, propertyName)) return false; scriptObject->methodTable()->put(scriptObject, exec, propertyName, value, slot); return true; }
bool JSObjectHasProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName) { ExecState* exec = toJS(ctx); exec->globalData().heap.registerThread(); JSLock lock(exec); JSObject* jsObject = toJS(object); return jsObject->hasProperty(exec, propertyName->identifier(&exec->globalData())); }
bool runtimeObjectCustomGetOwnPropertySlot(ExecState* exec, PropertyName propertyName, PropertySlot& slot, JSHTMLElement* element) { JSObject* scriptObject = pluginScriptObject(exec, element); if (!scriptObject) return false; if (!scriptObject->hasProperty(exec, propertyName)) return false; slot.setCustom(element, runtimeObjectPropertyGetter); return true; }
JSValue VM::throwException(ExecState* exec, JSValue error) { if (Options::breakOnThrow()) { dataLog("In call frame ", RawPointer(exec), " for code block ", *exec->codeBlock(), "\n"); CRASH(); } ASSERT(exec == topCallFrame || exec == exec->lexicalGlobalObject()->globalExec() || exec == exec->vmEntryGlobalObject()->globalExec()); Vector<StackFrame> stackTrace; interpreter->getStackTrace(stackTrace); m_exceptionStack = RefCountedArray<StackFrame>(stackTrace); m_exception = error; if (stackTrace.isEmpty() || !error.isObject()) return error; JSObject* exception = asObject(error); StackFrame stackFrame; for (unsigned i = 0 ; i < stackTrace.size(); ++i) { stackFrame = stackTrace.at(i); if (stackFrame.bytecodeOffset) break; } if (!hasErrorInfo(exec, exception)) { // FIXME: We should only really be adding these properties to VM generated exceptions, // but the inspector currently requires these for all thrown objects. unsigned line; unsigned column; stackFrame.computeLineAndColumn(line, column); exception->putDirect(*this, Identifier(this, "line"), jsNumber(line), ReadOnly | DontDelete); exception->putDirect(*this, Identifier(this, "column"), jsNumber(column), ReadOnly | DontDelete); if (!stackFrame.sourceURL.isEmpty()) exception->putDirect(*this, Identifier(this, "sourceURL"), jsString(this, stackFrame.sourceURL), ReadOnly | DontDelete); } if (exception->isErrorInstance() && static_cast<ErrorInstance*>(exception)->appendSourceToMessage()) { FindFirstCallerFrameWithCodeblockFunctor functor(exec); topCallFrame->iterate(functor); CallFrame* callFrame = functor.foundCallFrame(); unsigned stackIndex = functor.index(); if (callFrame && callFrame->codeBlock()) { stackFrame = stackTrace.at(stackIndex); appendSourceToError(callFrame, static_cast<ErrorInstance*>(exception), stackFrame.bytecodeOffset); } } if (exception->hasProperty(exec, this->propertyNames->stack)) return error; exception->putDirect(*this, propertyNames->stack, interpreter->stackTraceAsString(topCallFrame, stackTrace), DontEnum); return error; }
bool JSObjectHasProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName) { if (!ctx) { ASSERT_NOT_REACHED(); return false; } ExecState* exec = toJS(ctx); APIEntryShim entryShim(exec); JSObject* jsObject = toJS(object); return jsObject->hasProperty(exec, propertyName->identifier(&exec->vm())); }
bool JSObjectHasProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName) { if (!ctx) { ASSERT_NOT_REACHED(); return false; } ExecState* exec = toJS(ctx); VM& vm = exec->vm(); JSLockHolder locker(vm); JSObject* jsObject = toJS(object); return jsObject->hasProperty(exec, propertyName->identifier(&vm)); }
JSValue JSScope::resolve(ExecState* exec, JSScope* scope, const Identifier& ident) { ScopeChainIterator end = scope->end(); ScopeChainIterator it = scope->begin(); while (1) { JSObject* object = it.get(); if (++it == end) // Global scope. return object; if (object->hasProperty(exec, ident)) return object; } }
JSObject* JSScope::resolve(ExecState* exec, JSScope* scope, const Identifier& ident) { VM& vm = exec->vm(); auto throwScope = DECLARE_THROW_SCOPE(vm); ScopeChainIterator end = scope->end(); ScopeChainIterator it = scope->begin(); while (1) { JSScope* scope = it.scope(); JSObject* object = it.get(); // Global scope. if (++it == end) { JSScope* globalScopeExtension = scope->globalObject(vm)->globalScopeExtension(); if (UNLIKELY(globalScopeExtension)) { bool hasProperty = object->hasProperty(exec, ident); RETURN_IF_EXCEPTION(throwScope, nullptr); if (hasProperty) return object; JSObject* extensionScopeObject = JSScope::objectAtScope(globalScopeExtension); hasProperty = extensionScopeObject->hasProperty(exec, ident); RETURN_IF_EXCEPTION(throwScope, nullptr); if (hasProperty) return extensionScopeObject; } return object; } bool hasProperty = object->hasProperty(exec, ident); RETURN_IF_EXCEPTION(throwScope, nullptr); if (hasProperty) { bool unscopable = isUnscopable(exec, scope, object, ident); ASSERT(!throwScope.exception() || !unscopable); if (!unscopable) return object; } } }
JSValue VM::throwException(ExecState* exec, JSValue error) { ASSERT(exec == topCallFrame || exec == exec->lexicalGlobalObject()->globalExec() || exec == exec->dynamicGlobalObject()->globalExec()); Vector<StackFrame> stackTrace; interpreter->getStackTrace(stackTrace); m_exceptionStack = RefCountedArray<StackFrame>(stackTrace); m_exception = error; if (stackTrace.isEmpty() || !error.isObject()) return error; JSObject* exception = asObject(error); StackFrame stackFrame; for (unsigned i = 0 ; i < stackTrace.size(); ++i) { stackFrame = stackTrace.at(i); if (stackFrame.bytecodeOffset) break; } unsigned bytecodeOffset = stackFrame.bytecodeOffset; if (!hasErrorInfo(exec, exception)) { // FIXME: We should only really be adding these properties to VM generated exceptions, // but the inspector currently requires these for all thrown objects. unsigned line; unsigned column; stackFrame.computeLineAndColumn(line, column); exception->putDirect(*this, Identifier(this, "line"), jsNumber(line), ReadOnly | DontDelete); exception->putDirect(*this, Identifier(this, "column"), jsNumber(column), ReadOnly | DontDelete); if (!stackFrame.sourceURL.isEmpty()) exception->putDirect(*this, Identifier(this, "sourceURL"), jsString(this, stackFrame.sourceURL), ReadOnly | DontDelete); } if (exception->isErrorInstance() && static_cast<ErrorInstance*>(exception)->appendSourceToMessage()) { unsigned stackIndex = 0; CallFrame* callFrame; for (callFrame = exec; callFrame && !callFrame->codeBlock(); callFrame = callFrame->callerFrame()->removeHostCallFrameFlag()) stackIndex++; if (callFrame && callFrame->codeBlock()) { stackFrame = stackTrace.at(stackIndex); bytecodeOffset = stackFrame.bytecodeOffset; appendSourceToError(callFrame, static_cast<ErrorInstance*>(exception), bytecodeOffset); } } if (exception->hasProperty(exec, this->propertyNames->stack)) return error; exception->putDirect(*this, propertyNames->stack, interpreter->stackTraceAsString(topCallFrame, stackTrace), DontEnum); return error; }
bool runtimeObjectCustomGetOwnPropertyDescriptor(ExecState* exec, PropertyName propertyName, PropertyDescriptor& descriptor, JSHTMLElement* element) { JSObject* scriptObject = pluginScriptObject(exec, element); if (!scriptObject) return false; if (!scriptObject->hasProperty(exec, propertyName)) return false; PropertySlot slot(element); slot.setCustom(element, runtimeObjectPropertyGetter); // While we don't know what the plugin allows, we do know that we prevent // enumeration or deletion of properties, so we mark plugin properties // as DontEnum | DontDelete descriptor.setDescriptor(slot.getValue(exec, propertyName), DontEnum | DontDelete); return true; }
static EncodedJSValue JSC_HOST_CALL constructJSWebAssemblyTable(ExecState* exec) { VM& vm = exec->vm(); auto throwScope = DECLARE_THROW_SCOPE(vm); JSObject* memoryDescriptor; { JSValue argument = exec->argument(0); if (!argument.isObject()) return JSValue::encode(throwException(exec, throwScope, createTypeError(exec, ASCIILiteral("WebAssembly.Table expects its first argument to be an object")))); memoryDescriptor = jsCast<JSObject*>(argument); } { Identifier elementIdent = Identifier::fromString(&vm, "element"); JSValue elementValue = memoryDescriptor->get(exec, elementIdent); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); String elementString = elementValue.toWTFString(exec); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); if (elementString != "anyfunc") return JSValue::encode(throwException(exec, throwScope, createTypeError(exec, ASCIILiteral("WebAssembly.Table expects its 'element' field to be the string 'anyfunc'")))); } Identifier initialIdent = Identifier::fromString(&vm, "initial"); JSValue initialSizeValue = memoryDescriptor->get(exec, initialIdent); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); uint32_t initial = toNonWrappingUint32(exec, initialSizeValue); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); std::optional<uint32_t> maximum; Identifier maximumIdent = Identifier::fromString(&vm, "maximum"); bool hasProperty = memoryDescriptor->hasProperty(exec, maximumIdent); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); if (hasProperty) { JSValue maxSizeValue = memoryDescriptor->get(exec, maximumIdent); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); maximum = toNonWrappingUint32(exec, maxSizeValue); RETURN_IF_EXCEPTION(throwScope, encodedJSValue()); if (initial > *maximum) { return JSValue::encode(throwException(exec, throwScope, createRangeError(exec, ASCIILiteral("'maximum' property must be greater than or equal to the 'initial' property")))); } } throwScope.release(); return JSValue::encode(JSWebAssemblyTable::create(exec, vm, exec->lexicalGlobalObject()->WebAssemblyTableStructure(), initial, maximum)); }
JSObject* JSScope::resolve(ExecState* exec, JSScope* scope, const Identifier& ident) { ScopeChainIterator end = scope->end(); ScopeChainIterator it = scope->begin(); while (1) { JSScope* scope = it.scope(); JSObject* object = it.get(); if (++it == end) // Global scope. return object; if (object->hasProperty(exec, ident)) { if (!isUnscopable(exec, scope, object, ident)) return object; ASSERT_WITH_MESSAGE(!exec->hadException(), "When an exception occurs, the result of isUnscopable becomes false"); } } }
void JSObjectSetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSPropertyAttributes attributes, JSValueRef* exception) { JSLock lock; ExecState* exec = toJS(ctx); JSObject* jsObject = toJS(object); Identifier name(exec, toJS(propertyName)); JSValue* jsValue = toJS(value); if (attributes && !jsObject->hasProperty(exec, name)) jsObject->putWithAttributes(exec, name, jsValue, attributes); else jsObject->put(exec, name, jsValue); if (exec->hadException()) { if (exception) *exception = toRef(exec->exception()); exec->clearException(); } }
bool JSObjectHasPropertyForKey(JSContextRef ctx, JSObjectRef object, JSValueRef key, JSValueRef* exception) { if (!ctx) { ASSERT_NOT_REACHED(); return false; } ExecState* exec = toJS(ctx); VM& vm = exec->vm(); JSLockHolder locker(vm); auto scope = DECLARE_CATCH_SCOPE(vm); JSObject* jsObject = toJS(object); Identifier ident = toJS(exec, key).toPropertyKey(exec); if (handleExceptionIfNeeded(scope, exec, exception) == ExceptionStatus::DidThrow) return false; bool result = jsObject->hasProperty(exec, ident); handleExceptionIfNeeded(scope, exec, exception); return result; }
void JSObjectSetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSPropertyAttributes attributes, JSValueRef* exception) { ExecState* exec = toJS(ctx); APIEntryShim entryShim(exec); JSObject* jsObject = toJS(object); Identifier name(propertyName->identifier(&exec->globalData())); JSValue jsValue = toJS(exec, value); if (attributes && !jsObject->hasProperty(exec, name)) jsObject->methodTable()->putDirectVirtual(jsObject, exec, name, jsValue, attributes); else { PutPropertySlot slot; jsObject->methodTable()->put(jsObject, exec, name, jsValue, slot); } if (exec->hadException()) { if (exception) *exception = toRef(exec, exec->exception()); exec->clearException(); } }
JSValue JSHTMLCanvasElement::getContext(ExecState* exec) { HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(impl()); const UString& contextId = exec->argument(0).toString(exec)->value(exec); RefPtr<CanvasContextAttributes> attrs; #if ENABLE(WEBGL) if (contextId == "experimental-webgl" || contextId == "webkit-3d") { attrs = WebGLContextAttributes::create(); WebGLContextAttributes* webGLAttrs = static_cast<WebGLContextAttributes*>(attrs.get()); if (exec->argumentCount() > 1 && exec->argument(1).isObject()) { JSObject* jsAttrs = exec->argument(1).getObject(); Identifier alpha(exec, "alpha"); if (jsAttrs->hasProperty(exec, alpha)) webGLAttrs->setAlpha(jsAttrs->get(exec, alpha).toBoolean(exec)); Identifier depth(exec, "depth"); if (jsAttrs->hasProperty(exec, depth)) webGLAttrs->setDepth(jsAttrs->get(exec, depth).toBoolean(exec)); Identifier stencil(exec, "stencil"); if (jsAttrs->hasProperty(exec, stencil)) webGLAttrs->setStencil(jsAttrs->get(exec, stencil).toBoolean(exec)); Identifier antialias(exec, "antialias"); if (jsAttrs->hasProperty(exec, antialias)) webGLAttrs->setAntialias(jsAttrs->get(exec, antialias).toBoolean(exec)); Identifier premultipliedAlpha(exec, "premultipliedAlpha"); if (jsAttrs->hasProperty(exec, premultipliedAlpha)) webGLAttrs->setPremultipliedAlpha(jsAttrs->get(exec, premultipliedAlpha).toBoolean(exec)); Identifier preserveDrawingBuffer(exec, "preserveDrawingBuffer"); if (jsAttrs->hasProperty(exec, preserveDrawingBuffer)) webGLAttrs->setPreserveDrawingBuffer(jsAttrs->get(exec, preserveDrawingBuffer).toBoolean(exec)); } } #endif CanvasRenderingContext* context = canvas->getContext(ustringToString(contextId), attrs.get()); if (!context) return jsNull(); JSValue jsValue = toJS(exec, globalObject(), WTF::getPtr(context)); #if ENABLE(WEBGL) if (context->is3d() && InspectorInstrumentation::hasFrontends()) { ScriptObject glContext(exec, jsValue.getObject()); ScriptObject wrapped = InspectorInstrumentation::wrapWebGLRenderingContextForInstrumentation(canvas->document(), glContext); if (!wrapped.hasNoValue()) return wrapped.jsValue(); } #endif return jsValue; }
void JSObjectSetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSPropertyAttributes attributes, JSValueRef* exception) { if (!ctx) { ASSERT_NOT_REACHED(); return; } ExecState* exec = toJS(ctx); JSLockHolder locker(exec); JSObject* jsObject = toJS(object); Identifier name(propertyName->identifier(&exec->vm())); JSValue jsValue = toJS(exec, value); if (attributes && !jsObject->hasProperty(exec, name)) { PropertyDescriptor desc(jsValue, attributes); jsObject->methodTable()->defineOwnProperty(jsObject, exec, name, desc, false); } else { PutPropertySlot slot(jsObject); jsObject->methodTable()->put(jsObject, exec, name, jsValue, slot); } handleExceptionIfNeeded(exec, exception); }
void JSObjectSetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSPropertyAttributes attributes, JSValueRef* exception) { ExecState* exec = toJS(ctx); exec->globalData().heap->registerThread(); JSLock lock(exec); JSObject* jsObject = toJS(object); Identifier name(propertyName->identifier(exec)); JSValue* jsValue = toJS(value); if (attributes && !jsObject->hasProperty(exec, name)) jsObject->putWithAttributes(exec, name, jsValue, attributes); else { PutPropertySlot slot; jsObject->put(exec, name, jsValue, slot); } if (exec->hadException()) { if (exception) *exception = toRef(exec->exception()); exec->clearException(); } }
//-------------------------------------------------------------------------- // KJSValueToCFTypeInternal //-------------------------------------------------------------------------- // Caller is responsible for releasing the returned CFTypeRef CFTypeRef KJSValueToCFTypeInternal(JSValue inValue, ExecState *exec, ObjectImpList* inImps) { if (!inValue) return 0; CFTypeRef result = 0; JSGlueAPIEntry entry; if (inValue.isBoolean()) { result = inValue.toBoolean(exec) ? kCFBooleanTrue : kCFBooleanFalse; RetainCFType(result); return result; } if (inValue.isString()) { UString uString = inValue.toString(exec); result = UStringToCFString(uString); return result; } if (inValue.isNumber()) { double number1 = inValue.toNumber(exec); double number2 = (double)inValue.toInteger(exec); if (number1 == number2) { int intValue = (int)number2; result = CFNumberCreate(0, kCFNumberIntType, &intValue); } else { result = CFNumberCreate(0, kCFNumberDoubleType, &number1); } return result; } if (inValue.isObject()) { if (inValue.inherits(&UserObjectImp::info)) { UserObjectImp* userObjectImp = static_cast<UserObjectImp *>(asObject(inValue)); JSUserObject* ptr = userObjectImp->GetJSUserObject(); if (ptr) { result = ptr->CopyCFValue(); } } else { JSObject *object = inValue.toObject(exec); UInt8 isArray = false; // if two objects reference each JSObject* imp = object; ObjectImpList* temp = inImps; while (temp) { if (imp == temp->imp) { return CFRetain(GetCFNull()); } temp = temp->next; } ObjectImpList imps; imps.next = inImps; imps.imp = imp; //[...] HACK since we do not have access to the class info we use class name instead #if 0 if (object->inherits(&ArrayInstanceImp::info)) #else if (object->className() == "Array") #endif { isArray = true; JSGlueGlobalObject* globalObject = static_cast<JSGlueGlobalObject*>(exec->dynamicGlobalObject()); if (globalObject && (globalObject->Flags() & kJSFlagConvertAssociativeArray)) { PropertyNameArray propNames(exec); object->getPropertyNames(exec, propNames); PropertyNameArray::const_iterator iter = propNames.begin(); PropertyNameArray::const_iterator end = propNames.end(); while(iter != end && isArray) { Identifier propName = *iter; UString ustr = propName.ustring(); const UniChar* uniChars = (const UniChar*)ustr.characters(); int size = ustr.length(); while (size--) { if (uniChars[size] < '0' || uniChars[size] > '9') { isArray = false; break; } } iter++; } } } if (isArray) { // This is an KJS array unsigned int length = object->get(exec, Identifier(exec, "length")).toUInt32(exec); result = CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks); if (result) { for (unsigned i = 0; i < length; i++) { CFTypeRef cfValue = KJSValueToCFTypeInternal(object->get(exec, i), exec, &imps); CFArrayAppendValue((CFMutableArrayRef)result, cfValue); ReleaseCFType(cfValue); } } } else { // Not an array, just treat it like a dictionary which contains (property name, property value) pairs PropertyNameArray propNames(exec); object->getPropertyNames(exec, propNames); { result = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if (result) { PropertyNameArray::const_iterator iter = propNames.begin(); PropertyNameArray::const_iterator end = propNames.end(); while(iter != end) { Identifier propName = *iter; if (object->hasProperty(exec, propName)) { CFStringRef cfKey = IdentifierToCFString(propName); CFTypeRef cfValue = KJSValueToCFTypeInternal(object->get(exec, propName), exec, &imps); if (cfKey && cfValue) { CFDictionaryAddValue((CFMutableDictionaryRef)result, cfKey, cfValue); } ReleaseCFType(cfKey); ReleaseCFType(cfValue); } iter++; } } } } } return result; } if (inValue.isUndefinedOrNull()) { result = RetainCFType(GetCFNull()); return result; } ASSERT_NOT_REACHED(); return 0; }