blob: ede4e0f5e665ab0ea4e4fbbf4f07e4252aee5bdc [file] [log] [blame]
/*
* Copyright (C) 2004 Apple Computer, Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include <NP_jsobject.h>
#include <JavaScriptCore/npruntime.h>
#include <JavaScriptCore/c_utility.h>
#include <JavaScriptCore/npruntime_impl.h>
#include <JavaScriptCore/npruntime_priv.h>
using namespace KJS;
using namespace KJS::Bindings;
static KJS::List listFromVariantArgs(KJS::ExecState *exec, const NPVariant *args, unsigned argCount)
{
KJS::List aList;
unsigned i;
const NPVariant *v = args;
for (i = 0; i < argCount; i++) {
aList.append (convertNPVariantToValue (exec, v));
v++;
}
return aList;
}
static NPObject *jsAllocate(NPP npp, NPClass *aClass)
{
return (NPObject *)malloc(sizeof(JavaScriptObject));
}
static void jsDeallocate (JavaScriptObject *obj)
{
free (obj);
}
static NPClass _javascriptClass = {
1,
jsAllocate,
(NPDeallocateFunctionPtr)jsDeallocate,
0,
0,
0,
0,
0,
0,
0,
0
};
NPClass *NPScriptObjectClass = &_javascriptClass;
static Identifier identifierFromNPIdentifier(const NPUTF8 *name)
{
NPUTF16 *methodName;
unsigned int UTF16Length;
convertUTF8ToUTF16 (name, -1, &methodName, &UTF16Length); // requires free() of returned memory.
Identifier identifier ((const KJS::UChar*)methodName, UTF16Length);
free ((void *)methodName);
return identifier;
}
static bool _isSafeScript(JavaScriptObject *obj)
{
if (obj->originExecutionContext) {
Interpreter *originInterpreter = obj->originExecutionContext->interpreter();
if (originInterpreter) {
return originInterpreter->isSafeScript (obj->executionContext->interpreter());
}
}
return true;
}
NPObject *_NPN_CreateScriptObject (NPP npp, KJS::JSObject *imp, const KJS::Bindings::RootObject *originExecutionContext, const KJS::Bindings::RootObject *executionContext)
{
JavaScriptObject *obj = (JavaScriptObject *)_NPN_CreateObject(npp, NPScriptObjectClass);
obj->imp = imp;
obj->originExecutionContext = originExecutionContext;
obj->executionContext = executionContext;
addNativeReference (executionContext, imp);
return (NPObject *)obj;
}
bool _NPN_InvokeDefault (NPP npp, NPObject *o, const NPVariant *args, uint32_t argCount, NPVariant *result)
{
if (o->_class == NPScriptObjectClass) {
// No notion of a default function on JS objects. Just return false, can't handle.
return false;
}
else {
if (o->_class->invokeDefault) {
return o->_class->invokeDefault (o, args, argCount, result);
}
}
return true;
}
bool _NPN_Invoke (NPP npp, NPObject *o, NPIdentifier methodName, const NPVariant *args, uint32_t argCount, NPVariant *result)
{
if (o->_class == NPScriptObjectClass) {
JavaScriptObject *obj = (JavaScriptObject *)o;
if (!_isSafeScript(obj))
return false;
PrivateIdentifier *i = (PrivateIdentifier *)methodName;
if (!i->isString)
return false;
// Special case the "eval" method.
if (methodName == _NPN_GetStringIdentifier("eval")) {
if (argCount != 1)
return false;
if (args[0].type != NPVariantType_String)
return false;
return _NPN_Evaluate (npp, o, (NPString *)&args[0].value.stringValue, result);
}
else {
// Lookup the function object.
ExecState *exec = obj->executionContext->interpreter()->globalExec();
JSLock lock;
JSValue *func = obj->imp->get (exec, identifierFromNPIdentifier(i->value.string));
if (func->isNull()) {
NPN_InitializeVariantAsNull(result);
return false;
} else if (func->isUndefined()) {
NPN_InitializeVariantAsUndefined(result);
return false;
} else {
// Call the function object.
JSObject *funcImp = static_cast<JSObject*>(func);
JSObject *thisObj = const_cast<JSObject*>(obj->imp);
List argList = listFromVariantArgs(exec, args, argCount);
JSValue *resultV = funcImp->call (exec, thisObj, argList);
// Convert and return the result of the function call.
convertValueToNPVariant(exec, resultV, result);
return true;
}
}
} else if (o->_class->invoke)
return o->_class->invoke (o, methodName, args, argCount, result);
return true;
}
bool _NPN_Evaluate (NPP npp, NPObject *o, NPString *s, NPVariant *variant)
{
if (o->_class == NPScriptObjectClass) {
JavaScriptObject *obj = (JavaScriptObject *)o;
if (!_isSafeScript(obj))
return false;
ExecState *exec = obj->executionContext->interpreter()->globalExec();
JSValue *result;
JSLock lock;
NPUTF16 *scriptString;
unsigned int UTF16Length;
convertNPStringToUTF16 (s, &scriptString, &UTF16Length); // requires free() of returned memory.
Completion completion = obj->executionContext->interpreter()->evaluate(UString(), 0, UString((const UChar *)scriptString,UTF16Length));
ComplType type = completion.complType();
if (type == Normal) {
result = completion.value();
if (!result) {
result = jsUndefined();
}
}
else
result = jsUndefined();
free ((void *)scriptString);
convertValueToNPVariant(exec, result, variant);
return true;
}
return false;
}
bool _NPN_GetProperty (NPP npp, NPObject *o, NPIdentifier propertyName, NPVariant *variant)
{
if (o->_class == NPScriptObjectClass) {
JavaScriptObject *obj = (JavaScriptObject *)o;
if (!_isSafeScript(obj))
return false;
ExecState *exec = obj->executionContext->interpreter()->globalExec();
PrivateIdentifier *i = (PrivateIdentifier *)propertyName;
JSLock lock;
JSValue *result;
if (i->isString) {
result = obj->imp->get (exec, identifierFromNPIdentifier(i->value.string));
} else {
result = obj->imp->get (exec, i->value.number);
}
if (result->isNull()) {
NPN_InitializeVariantAsNull(variant);
return false;
}
else if (result->isUndefined()) {
NPN_InitializeVariantAsUndefined(variant);
return false;
}
else {
convertValueToNPVariant(exec, result, variant);
}
return true;
}
else if (o->_class->hasProperty && o->_class->getProperty) {
if (o->_class->hasProperty (o, propertyName)) {
return o->_class->getProperty (o, propertyName, variant);
}
else {
return false;
}
}
return false;
}
bool _NPN_SetProperty (NPP npp, NPObject *o, NPIdentifier propertyName, const NPVariant *variant)
{
if (o->_class == NPScriptObjectClass) {
JavaScriptObject *obj = (JavaScriptObject *)o;
if (!_isSafeScript(obj))
return false;
ExecState *exec = obj->executionContext->interpreter()->globalExec();
JSLock lock;
PrivateIdentifier *i = (PrivateIdentifier *)propertyName;
if (i->isString)
obj->imp->put(exec, identifierFromNPIdentifier(i->value.string), convertNPVariantToValue(exec, variant));
else
obj->imp->put(exec, i->value.number, convertNPVariantToValue(exec, variant));
return true;
} else if (o->_class->setProperty)
return o->_class->setProperty (o, propertyName, variant);
return false;
}
bool _NPN_RemoveProperty (NPP npp, NPObject *o, NPIdentifier propertyName)
{
if (o->_class == NPScriptObjectClass) {
JavaScriptObject *obj = (JavaScriptObject *)o;
if (!_isSafeScript(obj))
return false;
ExecState *exec = obj->executionContext->interpreter()->globalExec();
PrivateIdentifier *i = (PrivateIdentifier *)propertyName;
if (i->isString) {
if (!obj->imp->hasProperty (exec, identifierFromNPIdentifier(i->value.string))) {
return false;
}
}
else {
if (!obj->imp->hasProperty (exec, i->value.number)) {
return false;
}
}
JSLock lock;
if (i->isString)
obj->imp->deleteProperty (exec, identifierFromNPIdentifier(i->value.string));
else
obj->imp->deleteProperty (exec, i->value.number);
return true;
}
return false;
}
bool _NPN_HasProperty(NPP npp, NPObject *o, NPIdentifier propertyName)
{
if (o->_class == NPScriptObjectClass) {
JavaScriptObject *obj = (JavaScriptObject *)o;
if (!_isSafeScript(obj))
return false;
ExecState *exec = obj->executionContext->interpreter()->globalExec();
PrivateIdentifier *i = (PrivateIdentifier *)propertyName;
JSLock lock;
if (i->isString)
return obj->imp->hasProperty(exec, identifierFromNPIdentifier(i->value.string));
return obj->imp->hasProperty(exec, i->value.number);
} else if (o->_class->hasProperty)
return o->_class->hasProperty (o, propertyName);
return false;
}
bool _NPN_HasMethod(NPP npp, NPObject *o, NPIdentifier methodName)
{
if (o->_class == NPScriptObjectClass) {
JavaScriptObject *obj = (JavaScriptObject *)o;
if (!_isSafeScript(obj))
return false;
PrivateIdentifier *i = (PrivateIdentifier *)methodName;
if (!i->isString)
return false;
// Lookup the function object.
ExecState *exec = obj->executionContext->interpreter()->globalExec();
JSLock lock;
JSValue *func = obj->imp->get (exec, identifierFromNPIdentifier(i->value.string));
if (func->isUndefined()) {
return false;
}
return true;
}
else if (o->_class->hasMethod) {
return o->_class->hasMethod (o, methodName);
}
return false;
}
void _NPN_SetException(NPObject *o, const NPUTF8 *message)
{
if (o->_class == NPScriptObjectClass) {
JavaScriptObject *obj = (JavaScriptObject *)o;
ExecState *exec = obj->executionContext->interpreter()->globalExec();
JSLock lock;
throwError(exec, GeneralError, message);
}
}