Reviewed by Geoff.
[WebKit-https.git] / JavaScriptCore / bindings / c / c_utility.cpp
1 /*
2  * Copyright (C) 2004 Apple Computer, Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "c_utility.h"
27
28 #include "c_instance.h" 
29 #include "npruntime_impl.h"
30 #include "npruntime_priv.h"
31 #include "NP_jsobject.h"
32
33 namespace KJS { namespace Bindings {
34
35 // Requires free() of returned UTF16Chars.
36 void convertNPStringToUTF16(const NPString *string, NPUTF16 **UTF16Chars, unsigned int *UTF16Length)
37 {
38     convertUTF8ToUTF16(string->UTF8Characters, string->UTF8Length, UTF16Chars, UTF16Length);
39 }
40
41 // Requires free() of returned UTF16Chars.
42 void convertUTF8ToUTF16(const NPUTF8 *UTF8Chars, int UTF8Length, NPUTF16 **UTF16Chars, unsigned int *UTF16Length)
43 {
44     assert(UTF8Chars);
45     
46     if (UTF8Length == -1)
47         UTF8Length = strlen(UTF8Chars);
48
49     CFStringRef stringRef = CFStringCreateWithBytes(NULL, (const UInt8*)UTF8Chars, (CFIndex)UTF8Length, kCFStringEncodingUTF8, false);
50
51     *UTF16Length = (unsigned int)CFStringGetLength(stringRef);
52     *UTF16Chars = (NPUTF16 *)malloc(sizeof(NPUTF16) * (*UTF16Length));
53
54     // Convert the string to UTF16.
55     CFRange range = { 0, *UTF16Length };
56     CFStringGetCharacters(stringRef, range, (UniChar *)*UTF16Chars);
57     CFRelease(stringRef);
58 }
59
60 // Variant value must be released with NPReleaseVariantValue()
61 void coerceValueToNPVariantStringType(ExecState *exec, ValueImp *value, NPVariant *result)
62 {
63     UString ustring = value->toString(exec);
64     CString cstring = ustring.UTF8String();
65     NPString string = { (const NPUTF8 *)cstring.c_str(), cstring.size() };
66     NPN_InitializeVariantWithStringCopy(result, &string);
67 }
68
69 // Variant value must be released with NPReleaseVariantValue()
70 void convertValueToNPVariant(ExecState *exec, ValueImp *value, NPVariant *result)
71 {
72     Type type = value->type();
73     
74     if (type == StringType) {
75         UString ustring = value->toString(exec);
76         CString cstring = ustring.UTF8String();
77         NPString string = { (const NPUTF8 *)cstring.c_str(), cstring.size() };
78         NPN_InitializeVariantWithStringCopy(result, &string );
79     }
80     else if (type == NumberType) {
81         NPN_InitializeVariantWithDouble(result, value->toNumber(exec));
82     }
83     else if (type == BooleanType) {
84         NPN_InitializeVariantWithBool(result, value->toBoolean(exec));
85     }
86     else if (type == UnspecifiedType) {
87         NPN_InitializeVariantAsUndefined(result);
88     }
89     else if (type == NullType) {
90         NPN_InitializeVariantAsNull(result);
91     }
92     else if (type == ObjectType) {
93         ObjectImp *objectImp = static_cast<ObjectImp*>(value);
94         if (objectImp->classInfo() == &RuntimeObjectImp::info) {
95             RuntimeObjectImp *imp = static_cast<RuntimeObjectImp *>(value);
96             CInstance *instance = static_cast<CInstance*>(imp->getInternalInstance());
97             NPN_InitializeVariantWithObject(result, instance->getObject());
98         }
99         else {
100
101             Interpreter *originInterpreter = exec->interpreter();
102             const Bindings::RootObject *originExecutionContext = rootForInterpreter(originInterpreter);
103
104             Interpreter *interpreter = 0;
105             if (originInterpreter->isGlobalObject(value)) {
106                 interpreter = originInterpreter->interpreterForGlobalObject(value);
107             }
108
109             if (!interpreter)
110                 interpreter = originInterpreter;
111                 
112             const Bindings::RootObject *executionContext = rootForInterpreter(interpreter);
113             if (!executionContext) {
114                 Bindings::RootObject *newExecutionContext = new Bindings::RootObject(0);
115                 newExecutionContext->setInterpreter(interpreter);
116                 executionContext = newExecutionContext;
117             }
118     
119             NPObject *obj = (NPObject *)exec->interpreter()->createLanguageInstanceForValue(exec, Instance::CLanguage, value->toObject(exec), originExecutionContext, executionContext);
120             NPN_InitializeVariantWithObject(result, obj);
121             _NPN_ReleaseObject(obj);
122         }
123     }
124     else
125         NPN_InitializeVariantAsUndefined(result);
126 }
127
128 ValueImp *convertNPVariantToValue(ExecState *exec, const NPVariant *variant)
129 {
130     NPVariantType type = variant->type;
131
132     if (type == NPVariantType_Bool) {
133         NPBool aBool;
134         if (NPN_VariantToBool(variant, &aBool))
135             return jsBoolean(aBool);
136         return jsBoolean(false);
137     }
138     else if (type == NPVariantType_Null) {
139         return Null();
140     }
141     else if (type == NPVariantType_Void) {
142         return Undefined();
143     }
144     else if (type == NPVariantType_Int32) {
145         int32_t anInt;
146         if (NPN_VariantToInt32(variant, &anInt))
147             return Number(anInt);
148         return Number(0);
149     }
150     else if (type == NPVariantType_Double) {
151         double aDouble;
152         if (NPN_VariantToDouble(variant, &aDouble))
153             return Number(aDouble);
154         return Number(0);
155     }
156     else if (type == NPVariantType_String) {
157         NPUTF16 *stringValue;
158         unsigned int UTF16Length;
159         convertNPStringToUTF16(&variant->value.stringValue, &stringValue, &UTF16Length);    // requires free() of returned memory.
160         UString resultString((const UChar *)stringValue,UTF16Length);
161         free(stringValue);
162         return jsString(resultString);
163     }
164     else if (type == NPVariantType_Object) {
165         NPObject *obj = variant->value.objectValue;
166         
167         if (obj->_class == NPScriptObjectClass) {
168             // Get ObjectImp from NP_JavaScriptObject.
169             JavaScriptObject *o = (JavaScriptObject *)obj;
170             return const_cast<ObjectImp*>(o->imp);
171         }
172         else {
173             //  Wrap NPObject in a CInstance.
174             return Instance::createRuntimeObject(Instance::CLanguage, obj);
175         }
176     }
177     
178     return Undefined();
179 }
180
181 } }