bool JSObjectSetPrivate(JSObjectRef object, void* data) { JSObject* jsObject = uncheckedToJS(object); VM& vm = *jsObject->vm(); const ClassInfo* classInfo = classInfoPrivate(jsObject); // Get wrapped object if proxied if (classInfo->isSubClassOf(JSProxy::info())) { jsObject = static_cast<JSProxy*>(jsObject)->target(); classInfo = jsObject->classInfo(vm); } if (classInfo->isSubClassOf(JSCallbackObject<JSGlobalObject>::info())) { static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->setPrivate(data); return true; } if (classInfo->isSubClassOf(JSCallbackObject<JSDestructibleObject>::info())) { static_cast<JSCallbackObject<JSDestructibleObject>*>(jsObject)->setPrivate(data); return true; } #if JSC_OBJC_API_ENABLED if (classInfo->isSubClassOf(JSCallbackObject<JSAPIWrapperObject>::info())) { static_cast<JSCallbackObject<JSAPIWrapperObject>*>(jsObject)->setPrivate(data); return true; } #endif return false; }
EncodedJSValue JSC_HOST_CALL functionProtoFuncToString(ExecState* exec) { VM& vm = exec->vm(); auto scope = DECLARE_THROW_SCOPE(vm); JSValue thisValue = exec->thisValue(); if (thisValue.inherits(JSFunction::info())) { JSFunction* function = jsCast<JSFunction*>(thisValue); if (function->isHostOrBuiltinFunction()) { scope.release(); return JSValue::encode(jsMakeNontrivialString(exec, "function ", function->name(vm), "() {\n [native code]\n}")); } FunctionExecutable* executable = function->jsExecutable(); if (executable->isClass()) { StringView classSource = executable->classSource().view(); return JSValue::encode(jsString(exec, classSource.toStringWithoutCopying())); } if (thisValue.inherits(JSAsyncFunction::info())) { String functionHeader = executable->isArrowFunction() ? "async " : "async function "; StringView source = executable->source().provider()->getRange( executable->parametersStartOffset(), executable->parametersStartOffset() + executable->source().length()); return JSValue::encode(jsMakeNontrivialString(exec, functionHeader, function->name(vm), source)); } String functionHeader = executable->isArrowFunction() ? "" : "function "; StringView source = executable->source().provider()->getRange( executable->parametersStartOffset(), executable->parametersStartOffset() + executable->source().length()); scope.release(); return JSValue::encode(jsMakeNontrivialString(exec, functionHeader, function->name(vm), source)); } if (thisValue.inherits(InternalFunction::info())) { InternalFunction* function = asInternalFunction(thisValue); scope.release(); return JSValue::encode(jsMakeNontrivialString(exec, "function ", function->name(), "() {\n [native code]\n}")); } if (thisValue.isObject()) { JSObject* object = asObject(thisValue); if (object->inlineTypeFlags() & TypeOfShouldCallGetCallData) { CallData callData; if (object->methodTable(vm)->getCallData(object, callData) != CallType::None) { if (auto* classInfo = object->classInfo()) { scope.release(); return JSValue::encode(jsMakeNontrivialString(exec, "function ", classInfo->className, "() {\n [native code]\n}")); } } } } return throwVMTypeError(exec, scope); }
static EncodedJSValue JSC_HOST_CALL constructWithArrayConstructor(ExecState* exec) { ArgList args(exec); JSValue prototype = JSValue(); JSObject* newTarget = exec->newTarget().getObject(); if (newTarget->classInfo() != ArrayConstructor::info()) prototype = newTarget->get(exec, exec->propertyNames().prototype); return JSValue::encode(constructArrayWithSizeQuirk(exec, args, prototype)); }
// Variant value must be released with NPReleaseVariantValue() void convertValueToNPVariant(ExecState *exec, JSValue *value, NPVariant *result) { JSLock lock; JSType type = value->type(); VOID_TO_NPVARIANT(*result); if (type == StringType) { UString ustring = value->toString(exec); CString cstring = ustring.UTF8String(); NPString string = { (const NPUTF8 *)cstring.c_str(), static_cast<uint32_t>(cstring.size()) }; NPN_InitializeVariantWithStringCopy(result, &string); } else if (type == NumberType) { DOUBLE_TO_NPVARIANT(value->toNumber(exec), *result); } else if (type == BooleanType) { BOOLEAN_TO_NPVARIANT(value->toBoolean(exec), *result); } else if (type == UnspecifiedType) { VOID_TO_NPVARIANT(*result); } else if (type == NullType) { NULL_TO_NPVARIANT(*result); } else if (type == ObjectType) { JSObject* object = static_cast<JSObject*>(value); if (object->classInfo() == &RuntimeObjectImp::info) { RuntimeObjectImp* imp = static_cast<RuntimeObjectImp *>(value); CInstance* instance = static_cast<CInstance*>(imp->getInternalInstance()); if (instance) { NPObject* obj = instance->getObject(); _NPN_RetainObject(obj); OBJECT_TO_NPVARIANT(obj, *result); } } else { Interpreter* originInterpreter = exec->dynamicInterpreter(); RootObject* originRootObject = findRootObject(originInterpreter); Interpreter* interpreter = 0; if (originInterpreter->isGlobalObject(value)) { interpreter = originInterpreter->interpreterForGlobalObject(value); } if (!interpreter) interpreter = originInterpreter; RootObject* rootObject = findRootObject(interpreter); if (rootObject) { NPObject* npObject = _NPN_CreateScriptObject(0, object, originRootObject, rootObject); OBJECT_TO_NPVARIANT(npObject, *result); } } } }
JSTypedArrayType JSObjectGetTypedArrayType(JSContextRef ctx, JSObjectRef object) { ExecState* exec = toJS(ctx); APIEntryShim entryShim(exec); JSObject* jsObject = toJS(object); JSTypedArrayType type = kJSTypedArrayTypeNone; if( jsObject->inherits(JSArrayBufferView::info()) ) { type = TypedArrayTypes[jsObject->classInfo()->typedArrayStorageType]; } else if( jsObject->inherits(JSArrayBuffer::info()) ) { type = kJSTypedArrayTypeArrayBuffer; } return type; }
JSDOMWindow* toJSDOMWindow(JSValue value) { if (!value.isObject()) return 0; while (!value.isNull()) { JSObject* object = asObject(value); const ClassInfo* classInfo = object->classInfo(); if (classInfo == JSDOMWindow::info()) return jsCast<JSDOMWindow*>(object); if (classInfo == JSDOMWindowShell::info()) return jsCast<JSDOMWindowShell*>(object)->window(); value = object->prototype(); } return 0; }
JSTypedArrayType JSTypedArrayGetType(JSContextRef ctx, JSValueRef value) { ExecState* exec = toJS(ctx); JSLockHolder locker(exec); JSValue jsValue = toJS(exec, value); JSTypedArrayType type = JSTypedArrayType::NotTypedArray; if( jsValue.inherits(JSArrayBufferView::info()) ) { JSObject* object = jsValue.getObject(); type = (JSTypedArrayType) object->classInfo()->typedArrayStorageType; } else if( jsValue.inherits(JSArrayBuffer::info()) ) { type = JSTypedArrayType::TypeDataView; } return type; }
// Variant value must be released with NPReleaseVariantValue() void convertValueToNPVariant(ExecState* exec, JSValue value, NPVariant* result) { JSLock lock(SilenceAssertionsOnly); VOID_TO_NPVARIANT(*result); if (value.isString()) { UString ustring = value.toString(exec); CString cstring = ustring.utf8(); NPString string = { (const NPUTF8*)cstring.data(), static_cast<uint32_t>(cstring.length()) }; NPN_InitializeVariantWithStringCopy(result, &string); } else if (value.isNumber()) { DOUBLE_TO_NPVARIANT(value.toNumber(exec), *result); } else if (value.isBoolean()) { BOOLEAN_TO_NPVARIANT(value.toBoolean(exec), *result); } else if (value.isNull()) { NULL_TO_NPVARIANT(*result); } else if (value.isObject()) { JSObject* object = asObject(value); if (object->classInfo() == &CRuntimeObject::s_info) { CRuntimeObject* runtimeObject = static_cast<CRuntimeObject*>(object); CInstance* instance = runtimeObject->getInternalCInstance(); if (instance) { NPObject* obj = instance->getObject(); _NPN_RetainObject(obj); OBJECT_TO_NPVARIANT(obj, *result); } } else { #ifdef ANDROID RootObject* rootObject = findRootObject(exec->dynamicGlobalObject()); if (!rootObject) rootObject = findRootObject(exec->lexicalGlobalObject()); #else JSGlobalObject* globalObject = exec->dynamicGlobalObject(); RootObject* rootObject = findRootObject(globalObject); #endif if (rootObject) { NPObject* npObject = _NPN_CreateScriptObject(0, object, rootObject); OBJECT_TO_NPVARIANT(npObject, *result); } } } }
// Variant value must be released with NPReleaseVariantValue() void convertValueToNPVariant(ExecState* exec, JSValuePtr value, NPVariant* result) { JSLock lock(false); VOID_TO_NPVARIANT(*result); if (value.isString()) { UString ustring = value.toString(exec); CString cstring = ustring.UTF8String(); NPString string = { (const NPUTF8*)cstring.c_str(), static_cast<uint32_t>(cstring.size()) }; NPN_InitializeVariantWithStringCopy(result, &string); } else if (value.isNumber()) { DOUBLE_TO_NPVARIANT(value.toNumber(exec), *result); } else if (value.isBoolean()) { BOOLEAN_TO_NPVARIANT(value.toBoolean(exec), *result); } else if (value.isNull()) { NULL_TO_NPVARIANT(*result); } else if (value.isObject()) { JSObject* object = asObject(value); if (object->classInfo() == &RuntimeObjectImp::s_info) { RuntimeObjectImp* imp = static_cast<RuntimeObjectImp*>(object); CInstance* instance = static_cast<CInstance*>(imp->getInternalInstance()); if (instance) { NPObject* obj = instance->getObject(); _NPN_RetainObject(obj); OBJECT_TO_NPVARIANT(obj, *result); } } else { JSGlobalObject* globalObject = exec->dynamicGlobalObject(); RootObject* rootObject = findRootObject(globalObject); if (rootObject) { NPObject* npObject = _NPN_CreateScriptObject(0, object, rootObject); OBJECT_TO_NPVARIANT(npObject, *result); } } } }
jvalue convertValueToJValue(ExecState* exec, RootObject* rootObject, JSValue value, JavaType javaType, const char* javaClassName) { JSLock lock(SilenceAssertionsOnly); jvalue result; memset(&result, 0, sizeof(jvalue)); switch (javaType) { case JavaTypeArray: case JavaTypeObject: { // FIXME: JavaJSObject::convertValueToJObject functionality is almost exactly the same, // these functions should use common code. if (value.isObject()) { JSObject* object = asObject(value); if (object->inherits(&JavaRuntimeObject::s_info)) { // Unwrap a Java instance. JavaRuntimeObject* runtimeObject = static_cast<JavaRuntimeObject*>(object); JavaInstance* instance = runtimeObject->getInternalJavaInstance(); if (instance) result.l = instance->javaInstance(); } else if (object->classInfo() == &RuntimeArray::s_info) { // Input is a JavaScript Array that was originally created from a Java Array RuntimeArray* imp = static_cast<RuntimeArray*>(object); JavaArray* array = static_cast<JavaArray*>(imp->getConcreteArray()); result.l = array->javaArray(); } else if (object->classInfo() == &JSArray::s_info) { // Input is a Javascript Array. We need to create it to a Java Array. result.l = convertArrayInstanceToJavaArray(exec, asArray(value), javaClassName); } else if ((!result.l && (!strcmp(javaClassName, "java.lang.Object"))) || (!strcmp(javaClassName, "netscape.javascript.JSObject"))) { // Wrap objects in JSObject instances. JNIEnv* env = getJNIEnv(); jclass jsObjectClass = env->FindClass("sun/plugin/javascript/webkit/JSObject"); jmethodID constructorID = env->GetMethodID(jsObjectClass, "<init>", "(J)V"); if (constructorID) { jlong nativeHandle = ptr_to_jlong(object); rootObject->gcProtect(object); result.l = env->NewObject(jsObjectClass, constructorID, nativeHandle); } } } // Create an appropriate Java object if target type is java.lang.Object. if (!result.l && !strcmp(javaClassName, "java.lang.Object")) { if (value.isString()) { UString stringValue = asString(value)->value(exec); JNIEnv* env = getJNIEnv(); jobject javaString = env->functions->NewString(env, (const jchar*)stringValue.characters(), stringValue.length()); result.l = javaString; } else if (value.isNumber()) { double doubleValue = value.asNumber(); JNIEnv* env = getJNIEnv(); jclass clazz = env->FindClass("java/lang/Double"); jmethodID constructor = env->GetMethodID(clazz, "<init>", "(D)V"); jobject javaDouble = env->functions->NewObject(env, clazz, constructor, doubleValue); result.l = javaDouble; } else if (value.isBoolean()) { bool boolValue = value.asBoolean(); JNIEnv* env = getJNIEnv(); jclass clazz = env->FindClass("java/lang/Boolean"); jmethodID constructor = env->GetMethodID(clazz, "<init>", "(Z)V"); jobject javaBoolean = env->functions->NewObject(env, clazz, constructor, boolValue); result.l = javaBoolean; } else if (value.isUndefined()) { UString stringValue = "undefined"; JNIEnv* env = getJNIEnv(); jobject javaString = env->functions->NewString(env, (const jchar*)stringValue.characters(), stringValue.length()); result.l = javaString; } } // Convert value to a string if the target type is a java.lang.String, and we're not // converting from a null. if (!result.l && !strcmp(javaClassName, "java.lang.String")) { if (!value.isNull()) { UString stringValue = value.toString(exec); JNIEnv* env = getJNIEnv(); jobject javaString = env->functions->NewString(env, (const jchar*)stringValue.characters(), stringValue.length()); result.l = javaString; } } } break; case JavaTypeBoolean: { result.z = (jboolean)value.toNumber(exec); } break; case JavaTypeByte: { result.b = (jbyte)value.toNumber(exec); } break; case JavaTypeChar: { result.c = (jchar)value.toNumber(exec); } break; case JavaTypeShort: { result.s = (jshort)value.toNumber(exec); } break; case JavaTypeInt: { result.i = (jint)value.toNumber(exec); } break; case JavaTypeLong: { result.j = (jlong)value.toNumber(exec); } break; case JavaTypeFloat: { result.f = (jfloat)value.toNumber(exec); } break; case JavaTypeDouble: { result.d = (jdouble)value.toNumber(exec); } break; case JavaTypeInvalid: case JavaTypeVoid: break; } return result; }
jvalue convertValueToJValue(ExecState* exec, JSValue value, JNIType jniType, const char* javaClassName) { JSLock lock(SilenceAssertionsOnly); jvalue result; switch (jniType) { case array_type: case object_type: { result.l = (jobject)0; // First see if we have a Java instance. if (value.isObject()) { JSObject* objectImp = asObject(value); if (objectImp->classInfo() == &RuntimeObjectImp::s_info) { RuntimeObjectImp* imp = static_cast<RuntimeObjectImp*>(objectImp); JavaInstance* instance = static_cast<JavaInstance*>(imp->getInternalInstance()); if (instance) result.l = instance->javaInstance(); } else if (objectImp->classInfo() == &RuntimeArray::s_info) { // Input is a JavaScript Array that was originally created from a Java Array RuntimeArray* imp = static_cast<RuntimeArray*>(objectImp); JavaArray* array = static_cast<JavaArray*>(imp->getConcreteArray()); result.l = array->javaArray(); } else if (objectImp->classInfo() == &JSArray::info) { // Input is a Javascript Array. We need to create it to a Java Array. result.l = convertArrayInstanceToJavaArray(exec, asArray(value), javaClassName); } } // Now convert value to a string if the target type is a java.lang.string, and we're not // converting from a Null. if (!result.l && !strcmp(javaClassName, "java.lang.String")) { #ifdef CONVERT_NULL_TO_EMPTY_STRING if (value->isNull()) { JNIEnv* env = getJNIEnv(); jchar buf[2]; jobject javaString = env->functions->NewString(env, buf, 0); result.l = javaString; } else #else if (!value.isNull()) #endif { UString stringValue = value.toString(exec); JNIEnv* env = getJNIEnv(); jobject javaString = env->functions->NewString(env, (const jchar *)stringValue.data(), stringValue.size()); result.l = javaString; } } else if (!result.l) // ANDROID memset(&result, 0, sizeof(jvalue)); // Handle it the same as a void case } break; case boolean_type: { result.z = (jboolean)value.toNumber(exec); } break; case byte_type: { result.b = (jbyte)value.toNumber(exec); } break; case char_type: { result.c = (jchar)value.toNumber(exec); } break; case short_type: { result.s = (jshort)value.toNumber(exec); } break; case int_type: { result.i = (jint)value.toNumber(exec); } break; case long_type: { result.j = (jlong)value.toNumber(exec); } break; case float_type: { result.f = (jfloat)value.toNumber(exec); } break; case double_type: { result.d = (jdouble)value.toNumber(exec); } break; break; case invalid_type: default: case void_type: { // ANDROID memset(&result, 0, sizeof(jvalue)); } break; } return result; }