2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 * @file JSAccountManager.cpp
20 * @author Jihwa Park (jh7979.park@samsung.com)
25 #include <dpl/log/log.h>
28 #include <API/Account/IAccountService.h>
29 #include <API/Account/IAccountManager.h>
30 #include <API/Account/AccountFactory.h>
31 #include <API/Account/IEventCreateAccount.h>
32 #include <API/Account/IEventDeleteAccount.h>
33 #include <API/Account/IEventFindAccounts.h>
34 #include <API/Account/IEventUpdateAccount.h>
35 #include <API/Account/IEventFindServiceTypes.h>
37 #include <CommonsJavaScript/PrivateObject.h>
38 #include <CommonsJavaScript/JSDOMExceptionFactory.h>
39 #include <CommonsJavaScript/ScopedJSStringRef.h>
40 #include <CommonsJavaScript/Utils.h>
41 #include <CommonsJavaScript/Validator.h>
42 #include <CommonsJavaScript/Converter.h>
44 #include <Tizen/Common/JSTizenException.h>
45 #include <Tizen/Common/JSTizenExceptionFactory.h>
46 #include <Tizen/Common/SecurityExceptions.h>
48 #include "JSAccount.h"
49 #include "JSAccountManager.h"
50 #include "JSAccountService.h"
51 #include "JSAccountServiceType.h"
52 #include "AccountConverter.h"
53 #include "ResponseDispatcher.h"
54 #include "plugin_config.h"
56 using namespace TizenApis::Api::Account;
57 using namespace WrtDeviceApis::Commons;
58 using namespace WrtDeviceApis::CommonsJavaScript;
59 using namespace TizenApis::Commons;
62 #define TIZEN_ACCOUNT_MANAGER_ATTRIBUTENAME "account"
64 #define TIZEN_ACCOUNT_PROP_TYPE_NONE "TYPE_NONE"
65 #define TIZEN_ACCOUNT_PROP_TYPE_INTERNET "TYPE_INTERNET"
71 JSClassDefinition JSAccountManager::m_classInfo = {
73 kJSClassAttributeNone,
74 TIZEN_ACCOUNT_MANAGER_ATTRIBUTENAME,
83 NULL, //DeleteProperty,
84 NULL, //GetPropertyNames,
85 NULL, //CallAsFunction,
86 NULL, //CallAsConstructor,
91 JSStaticValue JSAccountManager::m_property[] = {
92 //event properties - recurence
93 { TIZEN_ACCOUNT_PROP_TYPE_NONE, getTypeProperty,NULL, kJSPropertyAttributeReadOnly },
94 { TIZEN_ACCOUNT_PROP_TYPE_INTERNET, getTypeProperty,NULL, kJSPropertyAttributeReadOnly },
98 JSStaticFunction JSAccountManager::m_function[] = {
99 { ACCOUNT_FUNCTION_API_GET_ACCOUNT_BY_ID, getAccountById, kJSPropertyAttributeNone },
100 { ACCOUNT_FUNCTION_API_GET_SERVICETYPE_BY_ID, getServiceTypeById, kJSPropertyAttributeNone },
101 { ACCOUNT_FUNCTION_API_GET_PROVIDER_BY_ID, getProviderById, kJSPropertyAttributeNone },
102 { ACCOUNT_FUNCTION_API_FIND_ACCOUNTS_BY_SERVICETYPE, findAccountsByServiceType, kJSPropertyAttributeNone },
103 { ACCOUNT_FUNCTION_API_FIND_ACCOUNTS_BY_TAGS, findAccountsByTags, kJSPropertyAttributeNone },
104 { ACCOUNT_FUNCTION_API_FIND_SERVICES_BY_TAGS, findServicesByTags, kJSPropertyAttributeNone },
105 { ACCOUNT_FUNCTION_API_FIND_PROVIDERS, findProviders, kJSPropertyAttributeNone },
106 { ACCOUNT_FUNCTION_API_FIND_SERVICETYPES, findServiceTypes, kJSPropertyAttributeNone },
107 { ACCOUNT_FUNCTION_API_ADD_ACCOUNT, addAccount, kJSPropertyAttributeNone },
108 { ACCOUNT_FUNCTION_API_ADD_LISTENER_ACCOUNTS, addAccountlistener, kJSPropertyAttributeNone },
109 { ACCOUNT_FUNCTION_API_REMOVE_LISTENER_ACCOUNTS, removeAccountlistener, kJSPropertyAttributeNone },
113 JSClassRef JSAccountManager::m_jsClassRef = JSClassCreate(
114 JSAccountManager::getClassInfo());
116 void JSAccountManager::initialize(JSContextRef context,
120 AccountManagerPrivObject *privateObject = static_cast<AccountManagerPrivObject*>(JSObjectGetPrivate(object));
121 if (NULL == privateObject) {
122 IAccountManagerPtr accountManager = AccountFactory::getInstance().createAccountManagerObject();
123 privateObject = new AccountManagerPrivObject(context, accountManager);
124 if (!JSObjectSetPrivate(object, static_cast<void*>(privateObject))) {
125 delete privateObject;
130 void JSAccountManager::finalize(JSObjectRef object)
132 AccountManagerPrivObject *privateObject = static_cast<AccountManagerPrivObject*>(JSObjectGetPrivate(object));
133 delete privateObject;
138 * Account addAccount(AccountServiceProviderId providerId, optional AccountProperties? properties);
140 JSValueRef JSAccountManager::addAccount(JSContextRef context,
142 JSObjectRef thisObject,
143 size_t argumentCount,
144 const JSValueRef arguments[],
145 JSValueRef* exception)
148 AccountManagerPrivObject *privateObject = static_cast<AccountManagerPrivObject*>(JSObjectGetPrivate(thisObject));
149 assert(privateObject);
151 JSContextRef globalContext = privateObject->getContext();
152 AceSecurityStatus status = ACCOUNT_CHECK_ACCESS(globalContext, ACCOUNT_FUNCTION_API_ADD_ACCOUNT);
153 TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
155 if (argumentCount > 3) {
156 LogError("Wrong number of parameters.");
157 return JSTizenExceptionFactory::postException(context, exception,
158 JSTizenException::INVALID_VALUES_ERROR, "Wrong argument count:"+argumentCount);
161 if (JSValueIsUndefined(context, arguments[0]) || JSValueIsNull(context, arguments[0]) || !JSValueIsString(context, arguments[0])){
162 return JSTizenExceptionFactory::postException(context, exception,
163 JSTizenException::INVALID_VALUES_ERROR, "invalid value argument 0");
165 AccountConverterFactory::ConverterType converter = AccountConverterFactory::getConverter(globalContext);
166 converter->setProvider(arguments[0]);
168 //TODO implement for AccountProperties
169 // EventAccountPtr account = converter->toAccount(arguments[1]);
172 std::string accountServiceProviderId = converter->convertTostring(arguments[0]);
173 EventAccountPtr account = converter->toAccount(accountServiceProviderId);
177 LogError("Failed to get an event.");
178 return JSTizenExceptionFactory::postException(context, exception,
179 JSTizenException::UNKNOWN_ERROR, "Failed to get an event");
182 IEventAddAccountPtr dplEvent(new IEventAddAccount());
183 dplEvent->setEvent(account);
184 dplEvent->setForSynchronousCall();
185 privateObject->getObject()->addAccount(dplEvent);
187 if (dplEvent->getResult()){
189 return converter->toJSValueRefAccount(dplEvent->getEvent());
191 return JSTizenExceptionFactory::postException(context, exception,
192 JSTizenException::UNKNOWN_ERROR, "Unknown error");
194 } Catch(InvalidArgumentException){
195 LogError("Invalid argument");
196 return JSTizenExceptionFactory::postException(context, exception,
197 JSTizenException::TYPE_MISMATCH_ERROR, "Invalid argument");
199 LogError("Unexpected error during adding account");
200 return JSTizenExceptionFactory::postException(context, exception,
201 JSTizenException::UNKNOWN_ERROR, "Unexpected error during adding account");
204 return JSValueMakeNull(context);
209 * @throw InvalidArgumentException If not a callback nor JS null nor JS undefined.
211 JSValueRef getFunctionOrNull(JSContextRef ctx,
214 if (Validator(ctx).isCallback(arg))
216 LogDebug("isCallback");
218 }else if(!JSValueIsNull(ctx, arg) && !JSValueIsUndefined(ctx, arg))
220 LogDebug("not Callback");
221 ThrowMsg(InvalidArgumentException, "Not a function nor JS null.");
226 JSValueRef JSAccountManager::addAccountlistener(JSContextRef context,
228 JSObjectRef thisObject,
229 size_t argumentCount,
230 const JSValueRef arguments[],
231 JSValueRef* exception)
234 return JSDOMExceptionFactory::UnknownException.make(context, exception);
237 JSValueRef JSAccountManager::removeAccountlistener(JSContextRef context,
239 JSObjectRef thisObject,
240 size_t argumentCount,
241 const JSValueRef arguments[],
242 JSValueRef* exception)
245 return JSDOMExceptionFactory::UnknownException.make(context, exception);
248 JSValueRef JSAccountManager::getAccountById(JSContextRef context,
250 JSObjectRef thisObject,
251 size_t argumentCount,
252 const JSValueRef arguments[],
253 JSValueRef* exception)
257 AccountManagerPrivObject *privateObject = static_cast<AccountManagerPrivObject*>(JSObjectGetPrivate(thisObject));
258 assert(privateObject);
260 JSContextRef globalContext = privateObject->getContext();
261 AceSecurityStatus status = ACCOUNT_CHECK_ACCESS(globalContext, ACCOUNT_FUNCTION_API_GET_ACCOUNT_BY_ID);
262 TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
264 if (argumentCount != 1) {
265 LogError(">>> Wrong number of parameters.");
266 return JSTizenExceptionFactory::postException(context, exception,
267 JSTizenException::TYPE_MISMATCH_ERROR, "Wrong argument count:"+argumentCount);
270 if (JSValueIsUndefined(context, arguments[0]) || JSValueIsNull(context, arguments[0]) || !JSValueIsString(context, arguments[0])){
271 return JSTizenExceptionFactory::postException(context, exception,
272 JSTizenException::INVALID_VALUES_ERROR, "Invlid value");
275 AccountConverterFactory::ConverterType converter = AccountConverterFactory::getConverter(globalContext);
277 EventAccountPtr account(new EventAccount());
278 std::string accountId = converter->convertTostring(arguments[0]);
279 account->setAccountId(accountId);
281 AccountLogError(">>> Failed to get an event.");
282 return JSTizenExceptionFactory::postException(context, exception,
283 JSTizenException::UNKNOWN_ERROR, "UNKNOWN ERROR");
286 IEventGetAccountByIdPtr dplEvent(new IEventGetAccountById());
287 dplEvent->setEvent(account);
288 dplEvent->setForSynchronousCall();
289 privateObject->getObject()->getAccountById(dplEvent);
291 if (dplEvent->getResult()){
293 return converter->toJSValueRefAccount(dplEvent->getEvent());
295 AccountLogError("Unexpected error");
296 return JSDOMExceptionFactory::UnknownException.make(context, exception);
298 } Catch(InvalidArgumentException){
299 AccountLogError("Invalid argument");
300 return JSTizenExceptionFactory::postException(context, exception,
301 JSTizenException::TYPE_MISMATCH_ERROR, "Invalid argument");
303 AccountLogError("Unexpected error");
304 return JSTizenExceptionFactory::postException(context, exception,
305 JSTizenException::UNKNOWN_ERROR, "Unexpected error");
308 AccountLogWarning(">>> return NULL");
309 return JSValueMakeNull(context);
312 JSValueRef JSAccountManager::getServiceTypeById(JSContextRef context,
314 JSObjectRef thisObject,
315 size_t argumentCount,
316 const JSValueRef arguments[],
317 JSValueRef* exception)
321 AccountManagerPrivObject *privateObject = static_cast<AccountManagerPrivObject*>(JSObjectGetPrivate(thisObject));
322 assert(privateObject);
324 JSContextRef globalContext = privateObject->getContext();
325 AceSecurityStatus status = ACCOUNT_CHECK_ACCESS(globalContext, ACCOUNT_FUNCTION_API_GET_SERVICETYPE_BY_ID);
326 TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
328 if (argumentCount != 1) {
329 AccountLogError(">>> Wrong number of parameters.");
330 return JSTizenExceptionFactory::postException(context, exception,
331 JSTizenException::TYPE_MISMATCH_ERROR, "Wrong number of parameters.");
334 if (JSValueIsUndefined(context, arguments[0]) || JSValueIsNull(context, arguments[0]) || !JSValueIsString(context, arguments[0])){
335 AccountLogError(">>> invalid value argument 0");
336 return JSTizenExceptionFactory::postException(context, exception,
337 JSTizenException::INVALID_VALUES_ERROR, "invalid value argument 0");
340 AccountConverterFactory::ConverterType converter = AccountConverterFactory::getConverter(globalContext);
342 EventAccountPtr account(new EventAccount());
343 std::string serviceTypeId = converter->convertTostring(arguments[0]);
344 LogDebug("serviceTypeId:[" << serviceTypeId << "]");
345 account->setServiceTypeId(serviceTypeId);
347 AccountLogError(">>> Failed to get an event.");
348 return JSTizenExceptionFactory::postException(context, exception,
349 JSTizenException::UNKNOWN_ERROR, "Failed to get an event.");
352 IEventGetServiceTypeByIdPtr dplEvent(new IEventGetServiceTypeById());
353 dplEvent->setEvent(account);
354 dplEvent->setForSynchronousCall();
355 privateObject->getObject()->getServiceTypeById(dplEvent);
357 if (dplEvent->getResult()){
358 JSValueRef retVal = converter->toJSValueRefAccountServiceType(dplEvent->getAccountServiceTypeProperty());
359 LogDebug(">>> RESULT");
362 AccountLogError(">>> Get result fail");
363 return JSTizenExceptionFactory::postException(context, exception,
364 JSTizenException::UNKNOWN_ERROR, "Get result fail");
366 } Catch(InvalidArgumentException) {
367 AccountLogError("Invalid argument");
368 return JSTizenExceptionFactory::postException(context, exception,
369 JSTizenException::TYPE_MISMATCH_ERROR, "Invalid argument");
371 AccountLogError("Unexpected error during adding account");
372 return JSTizenExceptionFactory::postException(context, exception,
373 JSTizenException::TYPE_MISMATCH_ERROR, "Unexpected error during adding account");
376 AccountLogWarning(">>> return NULL");
377 return JSValueMakeNull(context);
380 JSValueRef JSAccountManager::getProviderById(JSContextRef context,
382 JSObjectRef thisObject,
383 size_t argumentCount,
384 const JSValueRef arguments[],
385 JSValueRef* exception)
388 AccountManagerPrivObject *privateObject = static_cast<AccountManagerPrivObject*>(JSObjectGetPrivate(thisObject));
389 assert(privateObject);
391 JSContextRef globalContext = privateObject->getContext();
392 AceSecurityStatus status = ACCOUNT_CHECK_ACCESS(globalContext, ACCOUNT_FUNCTION_API_GET_SERVICETYPE_BY_ID);
393 TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
395 if (argumentCount != 1) {
396 AccountLogError(">>> Wrong number of parameters.");
397 return JSTizenExceptionFactory::postException(context, exception,
398 JSTizenException::TYPE_MISMATCH_ERROR, "Wrong number of parameters.");
401 if (JSValueIsUndefined(context, arguments[0]) || JSValueIsNull(context, arguments[0]) || !JSValueIsString(context, arguments[0])){
402 AccountLogError(">>> invalid value argument 0");
403 return JSTizenExceptionFactory::postException(context, exception,
404 JSTizenException::INVALID_VALUES_ERROR, "invalid value argument 0");
407 AccountConverterFactory::ConverterType converter = AccountConverterFactory::getConverter(globalContext);
409 EventAccountPtr account(new EventAccount());
410 std::string accountServiceProviderId = converter->convertTostring(arguments[0]);
411 LogDebug("accountServiceProviderId:[" << accountServiceProviderId << "]");
413 account->setProviderId(accountServiceProviderId);
415 AccountLogError(">>> Failed to get an event.");
416 return JSTizenExceptionFactory::postException(context, exception,
417 JSTizenException::UNKNOWN_ERROR, "Failed to get an event.");
420 IEventGetProviderByIdPtr dplEvent(new IEventGetProviderById());
421 dplEvent->setEvent(account);
422 dplEvent->setForSynchronousCall();
423 privateObject->getObject()->getProviderById(dplEvent);
425 if (dplEvent->getResult()){
427 JSValueRef retVal = converter->toJSValueRefAccountServiceProvider(dplEvent->getAccountServiceProviderProperty());
431 AccountLogError(">>> Get result fail");
432 return JSTizenExceptionFactory::postException(context, exception,
433 JSTizenException::UNKNOWN_ERROR, "Get result fail");
435 }Catch(InvalidArgumentException){
436 AccountLogError("Invalid argument");
437 return JSTizenExceptionFactory::postException(context, exception,
438 JSTizenException::TYPE_MISMATCH_ERROR, "Invalid argument");
440 AccountLogError("Unexpected error during adding account");
441 return JSTizenExceptionFactory::postException(context, exception,
442 JSTizenException::TYPE_MISMATCH_ERROR, "Unexpected error during adding account");
445 return JSValueMakeNull(context);
448 JSValueRef JSAccountManager::findAccountsByServiceType(JSContextRef context,
450 JSObjectRef thisObject,
451 size_t argumentCount,
452 const JSValueRef arguments[],
453 JSValueRef* exception)
456 return JSDOMExceptionFactory::UnknownException.make(context, exception);
459 JSValueRef JSAccountManager::findAccountsByTags(JSContextRef context,
461 JSObjectRef thisObject,
462 size_t argumentCount,
463 const JSValueRef arguments[],
464 JSValueRef* exception)
467 return JSDOMExceptionFactory::UnknownException.make(context, exception);
470 JSValueRef JSAccountManager::findServicesByTags(JSContextRef context,
472 JSObjectRef thisObject,
473 size_t argumentCount,
474 const JSValueRef arguments[],
475 JSValueRef* exception)
478 return JSDOMExceptionFactory::UnknownException.make(context, exception);
481 JSValueRef JSAccountManager::findProviders(JSContextRef context,
483 JSObjectRef thisObject,
484 size_t argumentCount,
485 const JSValueRef arguments[],
486 JSValueRef* exception)
488 LogDebug("entered!!!!");
489 AccountManagerPrivObject *privateObject = static_cast<AccountManagerPrivObject*>(JSObjectGetPrivate(thisObject));
490 assert(privateObject);
492 JSContextRef globalContext = privateObject->getContext();
493 AceSecurityStatus status = ACCOUNT_CHECK_ACCESS(globalContext, ACCOUNT_FUNCTION_API_FIND_PROVIDERS);
494 TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
497 if (argumentCount != 1) {
498 LogError("Wrong number of parameters.");
499 return JSDOMExceptionFactory::TypeMismatchException.make(context, exception);
502 if (JSValueIsUndefined(context, arguments[0]) || JSValueIsNull(context, arguments[0]))
504 return JSDOMExceptionFactory::InvalidValuesException.make(privateObject->getContext());
505 return JSValueMakeNull(context);
508 AccountConverterFactory::ConverterType converter = AccountConverterFactory::getConverter(globalContext);
510 EventAccountPtr account(new EventAccount());
511 std::string value = converter->convertTostring(arguments[0]);
512 account->setServiceTypeId(value);
514 LogError("Failed to get an event.");
515 return JSDOMExceptionFactory::UnknownException.make(privateObject->getContext());
518 IEventFindProvidersPtr dplEvent(new IEventFindProviders());
519 dplEvent->setEvent(account);
520 dplEvent->setForSynchronousCall();
521 privateObject->getObject()->FindProviders(dplEvent);
523 if (dplEvent->getResult())
524 return converter->toJSValueRefAccount(dplEvent->getEvent());
526 return JSDOMExceptionFactory::UnknownException.make(context, exception);
528 Catch(InvalidArgumentException)
530 LogError("Invalid argument");
531 return JSDOMExceptionFactory::TypeMismatchException.make(context, exception);
535 LogError("Unexpected error during adding account");
536 return JSDOMExceptionFactory::UnknownException.make(privateObject->getContext());
538 return JSValueMakeNull(context);
542 * AccountServiceType[]? findServiceTypes(DOMString? prefix)
544 JSValueRef JSAccountManager::findServiceTypes(JSContextRef context,
546 JSObjectRef thisObject,
547 size_t argumentCount,
548 const JSValueRef arguments[],
549 JSValueRef* exception)
553 AccountManagerPrivObject *privateObject = static_cast<AccountManagerPrivObject*>(JSObjectGetPrivate(thisObject));
554 assert(privateObject);
556 JSContextRef globalContext = privateObject->getContext();
557 AceSecurityStatus status = ACCOUNT_CHECK_ACCESS(globalContext, ACCOUNT_FUNCTION_API_GET_SERVICETYPE_BY_ID);
558 TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
560 IEventFindServiceTypesPtr eventPtr(new IEventFindServiceTypes());
562 if (argumentCount == 1) {
563 if (JSValueIsUndefined(context, arguments[0]) || JSValueIsNull(context, arguments[0]) || !JSValueIsString(context, arguments[0])){
564 AccountLogError(">>> invalid value argument 0");
565 return JSTizenExceptionFactory::postException(context, exception,
566 JSTizenException::INVALID_VALUES_ERROR, "invalid value argument 0");
569 //TODO input argument
570 AccountConverterFactory::ConverterType converter = AccountConverterFactory::getConverter(globalContext);
571 std::string prefix = converter->convertTostring(arguments[0]);
572 LogDebug("prefix:[" << prefix << "]");
573 eventPtr->setPrefix(prefix);
576 eventPtr->setForSynchronousCall();
577 privateObject->getObject()->findServiceTypes(eventPtr);
579 if (eventPtr->getResult()){
580 AccountServiceTypePropertyArrayPtr properties = eventPtr->getAccountServiceTypeProperties();
582 JSObjectRef jsResult = JSCreateArrayObject(context, 0, NULL);
583 if (NULL == jsResult) {
584 ThrowMsg(NullPointerException, "Could not create js array object");
587 for(unsigned int i = 0; i < properties->size(); i++) {
588 if (!JSSetArrayElement(context, jsResult, i, JSAccountServiceType::createJSObject(context, properties->at(i)))) {
589 ThrowMsg(UnknownException, "Could not insert value into js array");
597 AccountLogError(">>> Get result fail");
598 return JSTizenExceptionFactory::postException(context, exception,
599 JSTizenException::UNKNOWN_ERROR, "Get result fail");
601 } Catch(InvalidArgumentException) {
602 AccountLogError("Invalid argument");
603 return JSTizenExceptionFactory::postException(context, exception,
604 JSTizenException::TYPE_MISMATCH_ERROR, "Invalid argument");
606 AccountLogError("Unexpected error during adding account");
607 return JSTizenExceptionFactory::postException(context, exception,
608 JSTizenException::TYPE_MISMATCH_ERROR, "Unexpected error during adding account");
611 AccountLogWarning(">>> return undefined");
612 return JSValueMakeUndefined(context);
615 const JSClassRef JSAccountManager::getClassRef()
618 m_jsClassRef = JSClassCreate(&m_classInfo);
623 const JSClassDefinition* JSAccountManager::getClassInfo()
628 JSValueRef JSAccountManager::getTypeProperty(JSContextRef context,
630 JSStringRef propertyName,
631 JSValueRef* exception)
636 Converter conveter(context);
637 std::string property = conveter.toString(propertyName);
638 if (property == TIZEN_ACCOUNT_PROP_TYPE_NONE) {
639 return conveter.toJSValueRef(JSAccountManager::TYPE_NONE);
640 }else if(property == TIZEN_ACCOUNT_PROP_TYPE_INTERNET) {
641 return conveter.toJSValueRef(JSAccountManager::TYPE_INTERNET);
646 LogWarning("conversion error");
648 return JSValueMakeUndefined(context);