tizen 2.4 release
[framework/web/wrt-plugins-common.git] / src / xwalk-module / js_utils.cpp
1 // Copyright 2015 Samsung Electronics Co, Ltd. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "js_utils.h"
6 #include <dlog.h>
7 #include <vector>
8 #include <string>
9 #include <memory>
10
11 template <typename T, size_t N>
12 char (&ArraySizeHelper(T (&array)[N]))[N];
13 #define arraysize(array) (sizeof(ArraySizeHelper(array)))
14
15
16
17 namespace wrt {
18 namespace JsUtils {
19
20 namespace {
21
22 // Templatized backend for StringPrintF/StringAppendF. This does not finalize
23 // the va_list, the caller is expected to do that.
24 template <class StringType>
25 static void StringAppendVT(StringType* dst,
26                            const typename StringType::value_type* format,
27                            va_list ap) {
28     // First try with a small fixed size buffer.
29     // This buffer size should be kept in sync with StringUtilTest.GrowBoundary
30     // and StringUtilTest.StringPrintfBounds.
31     typename StringType::value_type stack_buf[1024];
32
33     va_list ap_copy;
34     va_copy(ap_copy, ap);
35
36     int result = vsnprintf(stack_buf, arraysize(stack_buf), format, ap_copy);
37     va_end(ap_copy);
38
39     if (result >= 0 && result < static_cast<int>(arraysize(stack_buf))) {
40         // It fit.
41         dst->append(stack_buf, result);
42         return;
43     }
44
45     // Repeatedly increase buffer size until it fits.
46     int mem_length = arraysize(stack_buf);
47     while (true) {
48         if (result < 0) {
49             if (errno != 0 && errno != EOVERFLOW)
50                 return;
51             // Try doubling the buffer size.
52             mem_length *= 2;
53         } else {
54             // We need exactly "result + 1" characters.
55             mem_length = result + 1;
56         }
57
58         if (mem_length > 32 * 1024 * 1024) {
59             // That should be plenty, don't try anything larger.  This protects
60             // against huge allocations when using vsnprintfT implementations that
61             // return -1 for reasons other than overflow without setting errno.
62             LOGE("Unable to printf the requested string due to size.");
63             return;
64         }
65
66         std::vector<typename StringType::value_type> mem_buf(mem_length);
67
68         // NOTE: You can only use a va_list once.  Since we're in a while loop, we
69         // need to make a new copy each time so we don't use up the original.
70         va_copy(ap_copy, ap);
71         result = vsnprintf(&mem_buf[0], mem_length, format, ap_copy);
72         va_end(ap_copy);
73
74         if ((result >= 0) && (result < mem_length)) {
75             // It fit.
76             dst->append(&mem_buf[0], result);
77             return;
78         }
79     }
80 }
81
82 std::string StringPrintf(const char* format, ...) {
83     va_list ap;
84     va_start(ap, format);
85     std::string result;
86     StringAppendVT(&result, format, ap);
87     va_end(ap);
88     return result;
89 }
90
91 }// unamed namespace
92
93 JSValueRef ToJSValueRef(JSContextRef ctx, const std::string& str){
94     JSValueRef result = NULL;
95     JSStringRef jsString = JSStringCreateWithUTF8CString(str.c_str());
96     result = JSValueMakeString(ctx, jsString);
97     JSStringRelease(jsString);
98     return result;
99 }
100
101 void SetProperty(JSContextRef ctx , JSObjectRef object, const char *name, JSValueRef value, JSPropertyAttributes attributes, JSValueRef *exception){
102     JSStringRef propertyName = JSStringCreateWithUTF8CString(name);
103     JSValueRef localException = NULL;
104     JSObjectSetProperty(ctx, object, propertyName, value,attributes, &localException);
105     JSStringRelease(propertyName);
106     if( localException != NULL ){
107         if( exception != NULL )
108             *exception = localException;
109     }
110 }
111
112 void DeleteProperty(JSContextRef ctx , JSObjectRef object, const char *name, JSValueRef *exception){
113     JSStringRef propertyName = JSStringCreateWithUTF8CString(name);
114     JSValueRef localException = NULL;
115     JSObjectDeleteProperty(ctx, object, propertyName, &localException);
116     JSStringRelease(propertyName);
117     if( localException != NULL ){
118         if( exception != NULL )
119             *exception = localException;
120     }
121 }
122
123 JSValueRef GetProperty(JSContextRef ctx , JSObjectRef object, const char *name, JSValueRef *exception){
124     JSValueRef value;
125     JSStringRef propertyName = JSStringCreateWithUTF8CString(name);
126     JSValueRef localException = NULL;
127     value = JSObjectGetProperty(ctx, object, propertyName, &localException);
128     JSStringRelease(propertyName);
129
130     if( localException != NULL && exception != NULL){
131         *exception = localException;
132     }
133     return value;
134 }
135
136 std::string JSValueToString(JSContextRef ctx, JSValueRef value){
137     JSValueRef exception = NULL;
138     JSStringRef str = JSValueToStringCopy(ctx, value, &exception);
139     if (exception != NULL) {
140         return std::string();
141     }
142     size_t jsSize = JSStringGetMaximumUTF8CStringSize(str);
143     std::unique_ptr<char []> buffer(new char[jsSize + 1]);
144     JSStringGetUTF8CString(str, buffer.get(), jsSize + 1);
145     JSStringRelease(str);
146     return std::string(buffer.get());
147 }
148
149
150 std::string ExceptionToString(JSContextRef ctx, JSValueRef exception) {
151     JSObjectRef obj = JSValueToObject( ctx, exception, NULL);
152     JSStringRef property_name = JSStringCreateWithUTF8CString("message");
153     JSValueRef message = JSObjectGetProperty( ctx, obj, property_name, NULL);
154     JSStringRelease(property_name);
155
156     JSStringRef msg = JSValueToStringCopy( ctx, message, NULL);
157
158     if (msg == NULL) {
159       return std::string();
160     }
161
162     size_t len = JSStringGetLength(msg);
163     std::unique_ptr<char []> buf(new char [len+1]);
164     JSStringGetUTF8CString(msg, buf.get(), len+1);
165     JSStringRelease(msg);
166     return std::string(buf.get());
167 }
168
169 JSValueRef RunString(JSContextRef ctx, const std::string& code,
170                                 std::string* exception) {
171     LOGD("========== << RunString >> ENTER ==========");
172
173     JSStringRef script = JSStringCreateWithUTF8CString(code.c_str());
174     JSValueRef except_value = NULL;
175     JSValueRef ret = JSEvaluateScript(ctx, script, NULL, NULL, 1, &except_value);
176     JSStringRelease(script);
177     if( except_value != NULL ){
178         if( exception )
179             *exception = ExceptionToString(ctx, except_value);
180         return JSValueMakeUndefined(ctx);
181     }
182
183     LOGD("========== << RunString >> END ==========");
184     return ret;
185 }
186
187
188 }
189 }