// ECMA 15.2.2 static ALWAYS_INLINE JSObject* constructObject(ExecState* exec, const ArgList& args) { JSValue arg = args.at(0); if (arg.isUndefinedOrNull()) return new (exec) JSObject(exec->lexicalGlobalObject()->emptyObjectStructure()); return arg.toObject(exec); }
static PassRefPtr<PositionOptions> createPositionOptions(ExecState* exec, JSValue value) { // Create default options. RefPtr<PositionOptions> options = PositionOptions::create(); // Argument is optional (hence undefined is allowed), and null is allowed. if (value.isUndefinedOrNull()) { // Use default options. return options.release(); } // Given the above test, this will always yield an object. JSObject* object = value.toObject(exec); // Create the dictionary wrapper from the initializer object. JSDictionary dictionary(exec, object); if (!dictionary.tryGetProperty("enableHighAccuracy", options.get(), setEnableHighAccuracy)) return 0; if (!dictionary.tryGetProperty("timeout", options.get(), setTimeout)) return 0; if (!dictionary.tryGetProperty("maximumAge", options.get(), setMaximumAge)) return 0; return options.release(); }
static std::error_code getTypeFlags(ExecState& exec, const JSValue& typeValue, ResourceFlags& flags, uint16_t (*stringToType)(const String&)) { VM& vm = exec.vm(); auto scope = DECLARE_THROW_SCOPE(vm); if (!typeValue.isObject()) return { }; const JSObject* object = typeValue.toObject(&exec); ASSERT(!scope.exception()); if (!isJSArray(object)) return ContentExtensionError::JSONInvalidTriggerFlagsArray; const JSArray* array = jsCast<const JSArray*>(object); unsigned length = array->length(); for (unsigned i = 0; i < length; ++i) { const JSValue value = array->getIndex(&exec, i); if (scope.exception() || !value) return ContentExtensionError::JSONInvalidObjectInTriggerFlagsArray; String name = value.toWTFString(&exec); uint16_t type = stringToType(name); if (!type) return ContentExtensionError::JSONInvalidStringInTriggerFlagsArray; flags |= type; } return { }; }
EncodedJSValue JSC_HOST_CALL objectProtoFuncToString(ExecState* exec) { VM& vm = exec->vm(); JSValue thisValue = exec->thisValue().toThis(exec, StrictMode); if (thisValue.isUndefinedOrNull()) return JSValue::encode(thisValue.isUndefined() ? vm.smallStrings.undefinedObjectString() : vm.smallStrings.nullObjectString()); JSObject* thisObject = thisValue.toObject(exec); JSValue stringTag = thisObject->get(exec, exec->propertyNames().toStringTagSymbol); if (stringTag.isString()) { JSRopeString::RopeBuilder<RecordOverflow> ropeBuilder(vm); ropeBuilder.append(vm.smallStrings.objectStringStart()); ropeBuilder.append(jsCast<JSString*>(stringTag)); ropeBuilder.append(vm.smallStrings.singleCharacterString(']')); if(ropeBuilder.hasOverflowed()) return JSValue::encode(throwOutOfMemoryError(exec)); return JSValue::encode(ropeBuilder.release()); } JSString* result = thisObject->structure(vm)->objectToStringValue(); if (!result) { RefPtr<StringImpl> newString = WTF::tryMakeString("[object ", thisObject->methodTable(exec->vm())->className(thisObject), "]"); if (!newString) return JSValue::encode(throwOutOfMemoryError(exec)); result = jsNontrivialString(&vm, newString.release()); thisObject->structure(vm)->setObjectToStringValue(vm, result); } return JSValue::encode(result); }
template<> EncodedJSValue JSC_HOST_CALL JSTestEventConstructorConstructor::construct(ExecState* state) { auto* jsConstructor = jsCast<JSTestEventConstructorConstructor*>(state->callee()); if (!jsConstructor->scriptExecutionContext()) return throwVMError(state, createReferenceError(state, "Constructor associated execution context is unavailable")); if (UNLIKELY(state->argumentCount() < 1)) return throwVMError(state, createNotEnoughArgumentsError(state)); AtomicString eventType = state->argument(0).toString(state)->toAtomicString(state); if (UNLIKELY(state->hadException())) return JSValue::encode(jsUndefined()); TestEventConstructorInit eventInit; JSValue initializerValue = state->argument(1); if (!initializerValue.isUndefinedOrNull()) { // Given the above test, this will always yield an object. JSObject* initializerObject = initializerValue.toObject(state); ASSERT(!state->hadException()); // Create the dictionary wrapper from the initializer object. JSDictionary dictionary(state, initializerObject); // Attempt to fill in the EventInit. if (!fillTestEventConstructorInit(eventInit, dictionary)) return JSValue::encode(jsUndefined()); } Ref<TestEventConstructor> event = TestEventConstructor::createForBindings(eventType, eventInit); return JSValue::encode(toJS(state, jsConstructor->globalObject(), event)); }
// ECMA 15.2.2 static ALWAYS_INLINE JSObject* constructObject(ExecState* exec, const ArgList& args) { JSValue* arg = args.at(exec, 0); if (arg->isUndefinedOrNull()) return new (exec) JSObject(exec->lexicalGlobalObject()->objectPrototype()); return arg->toObject(exec); }
EncodedJSValue JSC_HOST_CALL JSKeyboardEventConstructor::constructJSKeyboardEvent(ExecState* exec) { JSKeyboardEventConstructor* jsConstructor = jsCast<JSKeyboardEventConstructor*>(exec->callee()); ScriptExecutionContext* executionContext = jsConstructor->scriptExecutionContext(); if (!executionContext) return throwVMError(exec, createReferenceError(exec, "Constructor associated execution context is unavailable")); AtomicString eventType = exec->argument(0).toString(exec)->value(exec); if (exec->hadException()) return JSValue::encode(jsUndefined()); KeyboardEventInit eventInit; JSValue initializerValue = exec->argument(1); if (!initializerValue.isUndefinedOrNull()) { // Given the above test, this will always yield an object. JSObject* initializerObject = initializerValue.toObject(exec); // Create the dictionary wrapper from the initializer object. JSDictionary dictionary(exec, initializerObject); // Attempt to fill in the EventInit. if (!fillKeyboardEventInit(eventInit, dictionary)) return JSValue::encode(jsUndefined()); } RefPtr<KeyboardEvent> event = KeyboardEvent::create(eventType, eventInit); return JSValue::encode(toJS(exec, jsConstructor->globalObject(), event.get())); }
EncodedJSValue JSC_HOST_CALL objectProtoFuncHasOwnProperty(ExecState* exec) { JSValue thisValue = exec->thisValue().toThis(exec, StrictMode); auto propertyName = exec->argument(0).toPropertyKey(exec); if (exec->hadException()) return JSValue::encode(jsUndefined()); return JSValue::encode(jsBoolean(thisValue.toObject(exec)->hasOwnProperty(exec, propertyName))); }
double valueToDate(ExecState* exec, JSValue value) { if (value.isNumber()) return value.asNumber(); if (!value.inherits(DateInstance::info())) return std::numeric_limits<double>::quiet_NaN(); return static_cast<DateInstance*>(value.toObject(exec))->internalNumber(); }
static std::error_code loadEncodedRules(ExecState& exec, const String& rules, Vector<ContentExtensionRule>& ruleList) { VM& vm = exec.vm(); auto scope = DECLARE_THROW_SCOPE(vm); // FIXME: JSONParse should require callbacks instead of an ExecState. const JSValue decodedRules = JSONParse(&exec, rules); if (scope.exception() || !decodedRules) return ContentExtensionError::JSONInvalid; if (!decodedRules.isObject()) return ContentExtensionError::JSONTopLevelStructureNotAnObject; const JSObject* topLevelObject = decodedRules.toObject(&exec); if (!topLevelObject || scope.exception()) return ContentExtensionError::JSONTopLevelStructureNotAnObject; if (!isJSArray(topLevelObject)) return ContentExtensionError::JSONTopLevelStructureNotAnArray; const JSArray* topLevelArray = jsCast<const JSArray*>(topLevelObject); Vector<ContentExtensionRule> localRuleList; unsigned length = topLevelArray->length(); const unsigned maxRuleCount = 50000; if (length > maxRuleCount) return ContentExtensionError::JSONTooManyRules; for (unsigned i = 0; i < length; ++i) { const JSValue value = topLevelArray->getIndex(&exec, i); if (scope.exception() || !value) return ContentExtensionError::JSONInvalidObjectInTopLevelArray; const JSObject* ruleObject = value.toObject(&exec); if (!ruleObject || scope.exception()) return ContentExtensionError::JSONInvalidRule; auto error = loadRule(exec, *ruleObject, localRuleList); if (error) return error; } ruleList = WTFMove(localRuleList); return { }; }
static ALWAYS_INLINE JSObject* constructObject(ExecState* exec) { JSGlobalObject* globalObject = exec->callee()->globalObject(); ArgList args(exec); JSValue arg = args.at(0); if (arg.isUndefinedOrNull()) return constructEmptyObject(exec, globalObject->objectPrototype()); return arg.toObject(exec, globalObject); }
JSObject* BalRuntimeObjectImp::construct(ExecState* exec, const ArgList& args) { // ECMA 15.2.2.1 (?) CallData callData; CallType callType = getCallData(callData); JSValue* val = call(exec, this, callType, callData, this, args); if (!val || val->type() == NullType || val->type() == UndefinedType) return new (exec) JSObject(exec->lexicalGlobalObject()->objectPrototype()->prototype()); else return val->toObject(exec); }
void reportException(ExecState* exec, JSValue exception, CachedScript* cachedScript) { if (isTerminatedExecutionException(exception)) return; Interpreter::ErrorHandlingMode mode(exec); RefPtr<ScriptCallStack> callStack(createScriptCallStackFromException(exec, exception, ScriptCallStack::maxCallStackSizeToCapture)); exec->clearException(); exec->clearSupplementaryExceptionInfo(); JSDOMGlobalObject* globalObject = jsCast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()); if (JSDOMWindow* window = jsDynamicCast<JSDOMWindow*>(globalObject)) { if (!window->impl()->isCurrentlyDisplayedInFrame()) return; } int lineNumber = 0; int columnNumber = 0; String exceptionSourceURL; if (callStack->size()) { const ScriptCallFrame& frame = callStack->at(0); lineNumber = frame.lineNumber(); columnNumber = frame.columnNumber(); exceptionSourceURL = frame.sourceURL(); } else { // There may not be an exceptionStack for a <script> SyntaxError. Fallback to getting at least the line and sourceURL from the exception. JSObject* exceptionObject = exception.toObject(exec); JSValue lineValue = exceptionObject->getDirect(exec->vm(), Identifier(exec, "line")); lineNumber = lineValue && lineValue.isNumber() ? int(lineValue.toNumber(exec)) : 0; JSValue columnValue = exceptionObject->getDirect(exec->vm(), Identifier(exec, "column")); columnNumber = columnValue && columnValue.isNumber() ? int(columnValue.toNumber(exec)) : 0; JSValue sourceURLValue = exceptionObject->getDirect(exec->vm(), Identifier(exec, "sourceURL")); exceptionSourceURL = sourceURLValue && sourceURLValue.isString() ? sourceURLValue.toString(exec)->value(exec) : ASCIILiteral("undefined"); } String errorMessage; if (ExceptionBase* exceptionBase = toExceptionBase(exception)) errorMessage = exceptionBase->message() + ": " + exceptionBase->description(); else { // FIXME: <http://webkit.org/b/115087> Web Inspector: WebCore::reportException should not evaluate JavaScript handling exceptions // If this is a custon exception object, call toString on it to try and get a nice string representation for the exception. errorMessage = exception.toString(exec)->value(exec); exec->clearException(); exec->clearSupplementaryExceptionInfo(); } ScriptExecutionContext* scriptExecutionContext = globalObject->scriptExecutionContext(); scriptExecutionContext->reportException(errorMessage, lineNumber, columnNumber, exceptionSourceURL, callStack->size() ? callStack : 0, cachedScript); }
EXPORT JSObjectRef JSValueToObject(JSContextRef ctx, JSValueRef value, JSValueRef* exception) { JSLock lock; ExecState* exec = toJS(ctx); JSValue* jsValue = toJS(value); JSObjectRef objectRef = toRef(jsValue->toObject(exec)); if (exec->hadException()) { if (exception) *exception = toRef(exec->exception()); exec->clearException(); objectRef = 0; } return objectRef; }
JSObjectRef JSValueToObject(JSContextRef ctx, JSValueRef value, JSValueRef* exception) { if (!ctx) { ASSERT_NOT_REACHED(); return 0; } ExecState* exec = toJS(ctx); JSLockHolder locker(exec); JSValue jsValue = toJS(exec, value); JSObjectRef objectRef = toRef(jsValue.toObject(exec)); if (handleExceptionIfNeeded(exec, exception) == ExceptionStatus::DidThrow) objectRef = 0; return objectRef; }
JSObjectRef JSValueToObject(JSContextRef ctx, JSValueRef value, JSValueRef* exception) { ExecState* exec = toJS(ctx); APIEntryShim entryShim(exec); JSValue jsValue = toJS(exec, value); JSObjectRef objectRef = toRef(jsValue.toObject(exec)); if (exec->hadException()) { if (exception) *exception = toRef(exec, exec->exception()); exec->clearException(); objectRef = 0; } return objectRef; }
JSObjectRef JSValueToObject(JSContextRef ctx, JSValueRef value, JSValueRef* exception) { ExecState* exec = toJS(ctx); exec->globalData().heap.registerThread(); JSLock lock(exec); JSValue jsValue = toJS(exec, value); JSObjectRef objectRef = toRef(jsValue.toObject(exec)); if (exec->hadException()) { if (exception) *exception = toRef(exec, exec->exception()); exec->clearException(); objectRef = 0; } return objectRef; }
JSValue InjectedScriptHost::jsWrapper(ExecState* exec, JSGlobalObject* globalObject) { auto key = std::make_pair(exec, globalObject); auto it = m_wrappers.find(key); if (it != m_wrappers.end()) return it->value.get(); JSValue jsValue = toJS(exec, globalObject, this); if (!jsValue.isObject()) return jsValue; JSObject* jsObject = jsValue.toObject(exec, globalObject); Strong<JSObject> wrapper(exec->vm(), jsObject); m_wrappers.add(key, wrapper); return jsValue; }
// ECMA 15.2.2 JSObject* ObjectObjectImp::construct(ExecState* exec, const List& args) { JSValue* arg = args[0]; switch (arg->type()) { case StringType: case BooleanType: case NumberType: case ObjectType: return arg->toObject(exec); case NullType: case UndefinedType: return new JSObject(exec->lexicalInterpreter()->builtinObjectPrototype()); default: //### ASSERT_NOT_REACHED(); return 0; } }
EncodedJSValue JSC_HOST_CALL objectProtoFuncIsPrototypeOf(ExecState* exec) { JSValue thisValue = exec->thisValue().toThis(exec, StrictMode); JSObject* thisObj = thisValue.toObject(exec); if (!exec->argument(0).isObject()) return JSValue::encode(jsBoolean(false)); JSValue v = asObject(exec->argument(0))->prototype(); while (true) { if (!v.isObject()) return JSValue::encode(jsBoolean(false)); if (v == thisObj) return JSValue::encode(jsBoolean(true)); v = asObject(v)->prototype(); } }
void reportException(ExecState* exec, JSValue exception) { UString errorMessage = exception.toString(exec); JSObject* exceptionObject = exception.toObject(exec); int lineNumber = exceptionObject->get(exec, Identifier(exec, "line")).toInt32(exec); UString exceptionSourceURL = exceptionObject->get(exec, Identifier(exec, "sourceURL")).toString(exec); exec->clearException(); ScriptExecutionContext* scriptExecutionContext = static_cast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())->scriptExecutionContext(); ASSERT(scriptExecutionContext); // Crash data indicates null-dereference crashes at this point in the Safari 4 Public Beta. // It's harmless to return here without reporting the exception to the log and the debugger in this case. if (!scriptExecutionContext) return; scriptExecutionContext->reportException(errorMessage, lineNumber, exceptionSourceURL); }
EncodedJSValue JSC_HOST_CALL objectProtoFuncToString(ExecState* exec) { JSValue thisValue = exec->hostThisValue().toThis(exec, StrictMode); if (thisValue.isUndefinedOrNull()) return JSValue::encode(jsNontrivialString(exec, String(thisValue.isUndefined() ? ASCIILiteral("[object Undefined]") : ASCIILiteral("[object Null]")))); JSObject* thisObject = thisValue.toObject(exec); JSString* result = thisObject->structure()->objectToStringValue(); if (!result) { RefPtr<StringImpl> newString = WTF::tryMakeString("[object ", thisObject->methodTable()->className(thisObject), "]"); if (!newString) return JSValue::encode(throwOutOfMemoryError(exec)); result = jsNontrivialString(exec, newString.release()); thisObject->structure()->setObjectToStringValue(exec->vm(), thisObject, result); } return JSValue::encode(result); }
EncodedJSValue JSC_HOST_CALL objectProtoFuncToString(ExecState* exec) { VM& vm = exec->vm(); JSValue thisValue = exec->thisValue().toThis(exec, StrictMode); if (thisValue.isUndefinedOrNull()) return JSValue::encode(thisValue.isUndefined() ? vm.smallStrings.undefinedObjectString() : vm.smallStrings.nullObjectString()); JSObject* thisObject = thisValue.toObject(exec); JSString* result = thisObject->structure(vm)->objectToStringValue(); if (!result) { RefPtr<StringImpl> newString = WTF::tryMakeString("[object ", thisObject->methodTable(exec->vm())->className(thisObject), "]"); if (!newString) return JSValue::encode(throwOutOfMemoryError(exec)); result = jsNontrivialString(&vm, newString.release()); thisObject->structure(vm)->setObjectToStringValue(vm, result); } return JSValue::encode(result); }
static void get3DContextAttributes(ExecState* exec, RefPtr<CanvasContextAttributes>& attrs) { JSValue initializerValue = exec->argument(1); if (initializerValue.isUndefinedOrNull()) return; JSObject* initializerObject = initializerValue.toObject(exec); JSDictionary dictionary(exec, initializerObject); GraphicsContext3D::Attributes graphicsAttrs; dictionary.tryGetProperty("alpha", graphicsAttrs.alpha); dictionary.tryGetProperty("depth", graphicsAttrs.depth); dictionary.tryGetProperty("stencil", graphicsAttrs.stencil); dictionary.tryGetProperty("antialias", graphicsAttrs.antialias); dictionary.tryGetProperty("premultipliedAlpha", graphicsAttrs.premultipliedAlpha); dictionary.tryGetProperty("preserveDrawingBuffer", graphicsAttrs.preserveDrawingBuffer); attrs = WebGLContextAttributes::create(graphicsAttrs); }
bool UserObjectImp::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot) { if (!fJSUserObject) return false; CFStringRef cfPropName = IdentifierToCFString(propertyName); JSUserObject *jsResult = fJSUserObject->CopyProperty(cfPropName); ReleaseCFType(cfPropName); if (jsResult) { slot.setCustom(this, userObjectGetter); jsResult->Release(); return true; } else { JSValue *kjsValue = toPrimitive(exec); if (kjsValue->type() != NullType && kjsValue->type() != UndefinedType) { JSObject *kjsObject = kjsValue->toObject(exec); if (kjsObject->getPropertySlot(exec, propertyName, slot)) return true; } } return JSObject::getOwnPropertySlot(exec, propertyName, slot); }
static RefPtr<DeviceMotionData::RotationRate> readRotationRateArgument(JSValue value, ExecState& state) { if (value.isUndefinedOrNull()) return nullptr; // Given the above test, this will always yield an object. JSObject* object = value.toObject(&state); JSValue alphaValue = object->get(&state, Identifier::fromString(&state, "alpha")); if (state.hadException()) return nullptr; bool canProvideAlpha = !alphaValue.isUndefinedOrNull(); double alpha = alphaValue.toNumber(&state); if (state.hadException()) return nullptr; JSValue betaValue = object->get(&state, Identifier::fromString(&state, "beta")); if (state.hadException()) return nullptr; bool canProvideBeta = !betaValue.isUndefinedOrNull(); double beta = betaValue.toNumber(&state); if (state.hadException()) return nullptr; JSValue gammaValue = object->get(&state, Identifier::fromString(&state, "gamma")); if (state.hadException()) return nullptr; bool canProvideGamma = !gammaValue.isUndefinedOrNull(); double gamma = gammaValue.toNumber(&state); if (state.hadException()) return nullptr; if (!canProvideAlpha && !canProvideBeta && !canProvideGamma) return nullptr; return DeviceMotionData::RotationRate::create(canProvideAlpha, alpha, canProvideBeta, beta, canProvideGamma, gamma); }
static RefPtr<DeviceMotionData::Acceleration> readAccelerationArgument(JSValue value, ExecState& state) { if (value.isUndefinedOrNull()) return nullptr; // Given the above test, this will always yield an object. JSObject* object = value.toObject(&state); JSValue xValue = object->get(&state, Identifier::fromString(&state, "x")); if (state.hadException()) return nullptr; bool canProvideX = !xValue.isUndefinedOrNull(); double x = xValue.toNumber(&state); if (state.hadException()) return nullptr; JSValue yValue = object->get(&state, Identifier::fromString(&state, "y")); if (state.hadException()) return nullptr; bool canProvideY = !yValue.isUndefinedOrNull(); double y = yValue.toNumber(&state); if (state.hadException()) return nullptr; JSValue zValue = object->get(&state, Identifier::fromString(&state, "z")); if (state.hadException()) return nullptr; bool canProvideZ = !zValue.isUndefinedOrNull(); double z = zValue.toNumber(&state); if (state.hadException()) return nullptr; if (!canProvideX && !canProvideY && !canProvideZ) return nullptr; return DeviceMotionData::Acceleration::create(canProvideX, x, canProvideY, y, canProvideZ, z); }
static EncodedJSValue JSC_HOST_CALL callIntlDateTimeFormat(ExecState* state) { // 12.1.2 Intl.DateTimeFormat ([locales [, options]]) (ECMA-402 2.0) // 1. If NewTarget is undefined, let newTarget be the active function object, else let newTarget be NewTarget. // NewTarget is always undefined when called as a function. VM& vm = state->vm(); IntlDateTimeFormatConstructor* callee = jsCast<IntlDateTimeFormatConstructor*>(state->callee()); // FIXME: Workaround to provide compatibility with ECMA-402 1.0 call/apply patterns. JSValue thisValue = state->thisValue(); IntlDateTimeFormat* dateTimeFormat = jsDynamicCast<IntlDateTimeFormat*>(thisValue); if (!dateTimeFormat) { JSValue prototype = callee->getDirect(vm, vm.propertyNames->prototype); if (JSObject::defaultHasInstance(state, thisValue, prototype)) { JSObject* thisObject = thisValue.toObject(state); if (state->hadException()) return JSValue::encode(jsUndefined()); dateTimeFormat = IntlDateTimeFormat::create(vm, callee); dateTimeFormat->initializeDateTimeFormat(*state, state->argument(0), state->argument(1)); if (state->hadException()) return JSValue::encode(jsUndefined()); thisObject->putDirect(vm, vm.propertyNames->intlSubstituteValuePrivateName, dateTimeFormat); return JSValue::encode(thisValue); } } // 2. Let dateTimeFormat be OrdinaryCreateFromConstructor(newTarget, %DateTimeFormatPrototype%). // 3. ReturnIfAbrupt(dateTimeFormat). dateTimeFormat = IntlDateTimeFormat::create(vm, callee); // 4. Return InitializeDateTimeFormat(dateTimeFormat, locales, options). dateTimeFormat->initializeDateTimeFormat(*state, state->argument(0), state->argument(1)); return JSValue::encode(dateTimeFormat); }
JSObjectRef JSValueToObject(JSContextRef ctx, JSValueRef value, JSValueRef* exception) { if (!ctx) { ASSERT_NOT_REACHED(); return 0; } ExecState* exec = toJS(ctx); JSLockHolder locker(exec); JSValue jsValue = toJS(exec, value); JSObjectRef objectRef = toRef(jsValue.toObject(exec)); if (exec->hadException()) { JSValue exceptionValue = exec->exception(); if (exception) *exception = toRef(exec, exceptionValue); exec->clearException(); #if ENABLE(REMOTE_INSPECTOR) exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue); #endif objectRef = 0; } return objectRef; }
//-------------------------------------------------------------------------- // 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; }