PageRenderTime 58ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/webkit/JavaScriptGlue/UserObjectImp.cpp

https://github.com/blackberry/WebKit-Smartphone
C++ | 417 lines | 351 code | 31 blank | 35 comment | 128 complexity | 85991ea2208d75b05155b0c9c1c454fc MD5 | raw file
  1. /*
  2. * Copyright (C) 2005, 2008, 2009 Apple 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. *
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
  14. * its contributors may be used to endorse or promote products derived
  15. * from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
  18. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  19. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  20. * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
  21. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  22. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  23. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  24. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  26. * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. */
  28. #include "config.h"
  29. #include "UserObjectImp.h"
  30. #include <JavaScriptCore/JSString.h>
  31. #include <JavaScriptCore/PropertyNameArray.h>
  32. const ClassInfo UserObjectImp::info = { "UserObject", 0, 0, 0 };
  33. UserObjectImp::UserObjectImp(PassRefPtr<Structure> structure, JSUserObject* userObject)
  34. : JSObject(structure)
  35. , fJSUserObject((JSUserObject*)userObject->Retain())
  36. {
  37. }
  38. UserObjectImp::~UserObjectImp()
  39. {
  40. if (fJSUserObject)
  41. fJSUserObject->Release();
  42. }
  43. const ClassInfo * UserObjectImp::classInfo() const
  44. {
  45. return &info;
  46. }
  47. CallType UserObjectImp::getCallData(CallData& callData)
  48. {
  49. return fJSUserObject ? fJSUserObject->getCallData(callData) : CallTypeNone;
  50. }
  51. JSValue UserObjectImp::callAsFunction(ExecState *exec)
  52. {
  53. JSValue result = jsUndefined();
  54. JSUserObject* jsThisObj = KJSValueToJSObject(exec->hostThisValue().toThisObject(exec), exec);
  55. if (jsThisObj) {
  56. CFIndex argCount = exec->argumentCount();
  57. CFArrayCallBacks arrayCallBacks;
  58. JSTypeGetCFArrayCallBacks(&arrayCallBacks);
  59. CFMutableArrayRef jsArgs = CFArrayCreateMutable(0, 0, &arrayCallBacks);
  60. if (jsArgs) {
  61. for (CFIndex i = 0; i < argCount; i++) {
  62. JSUserObject* jsArg = KJSValueToJSObject(exec->argument(i), exec);
  63. CFArrayAppendValue(jsArgs, (void*)jsArg);
  64. jsArg->Release();
  65. }
  66. }
  67. JSUserObject* jsResult;
  68. { // scope
  69. JSGlueAPICallback apiCallback(exec);
  70. // getCallData should have guarded against a NULL fJSUserObject.
  71. assert(fJSUserObject);
  72. jsResult = fJSUserObject->CallFunction(jsThisObj, jsArgs);
  73. }
  74. if (jsResult) {
  75. result = JSObjectKJSValue(jsResult);
  76. jsResult->Release();
  77. }
  78. ReleaseCFType(jsArgs);
  79. jsThisObj->Release();
  80. }
  81. return result;
  82. }
  83. void UserObjectImp::getOwnPropertyNames(ExecState *exec, PropertyNameArray& propertyNames, EnumerationMode mode)
  84. {
  85. JSUserObject* ptr = GetJSUserObject();
  86. if (ptr) {
  87. CFArrayRef cfPropertyNames = ptr->CopyPropertyNames();
  88. if (cfPropertyNames) {
  89. CFIndex count = CFArrayGetCount(cfPropertyNames);
  90. CFIndex i;
  91. for (i = 0; i < count; i++) {
  92. CFStringRef propertyName = (CFStringRef)CFArrayGetValueAtIndex(cfPropertyNames, i);
  93. propertyNames.add(CFStringToIdentifier(propertyName, exec));
  94. }
  95. CFRelease(cfPropertyNames);
  96. }
  97. }
  98. JSObject::getOwnPropertyNames(exec, propertyNames, mode);
  99. }
  100. JSValue UserObjectImp::userObjectGetter(ExecState*, JSValue slotBase, const Identifier& propertyName)
  101. {
  102. UserObjectImp *thisObj = static_cast<UserObjectImp *>(asObject(slotBase));
  103. // getOwnPropertySlot should have guarded against a null fJSUserObject.
  104. assert(thisObj->fJSUserObject);
  105. CFStringRef cfPropName = IdentifierToCFString(propertyName);
  106. JSUserObject *jsResult = thisObj->fJSUserObject->CopyProperty(cfPropName);
  107. ReleaseCFType(cfPropName);
  108. JSValue result = JSObjectKJSValue(jsResult);
  109. jsResult->Release();
  110. return result;
  111. }
  112. bool UserObjectImp::getOwnPropertySlot(ExecState *exec, const Identifier& propertyName, PropertySlot& slot)
  113. {
  114. if (!fJSUserObject)
  115. return false;
  116. CFStringRef cfPropName = IdentifierToCFString(propertyName);
  117. JSUserObject *jsResult = fJSUserObject->CopyProperty(cfPropName);
  118. ReleaseCFType(cfPropName);
  119. if (jsResult) {
  120. slot.setCustom(this, userObjectGetter);
  121. jsResult->Release();
  122. return true;
  123. } else {
  124. JSValue kjsValue = toPrimitive(exec);
  125. if (!kjsValue.isUndefinedOrNull()) {
  126. JSObject* kjsObject = kjsValue.toObject(exec);
  127. if (kjsObject->getPropertySlot(exec, propertyName, slot))
  128. return true;
  129. }
  130. }
  131. return JSObject::getOwnPropertySlot(exec, propertyName, slot);
  132. }
  133. void UserObjectImp::put(ExecState *exec, const Identifier &propertyName, JSValue value, PutPropertySlot&)
  134. {
  135. if (!fJSUserObject)
  136. return;
  137. CFStringRef cfPropName = IdentifierToCFString(propertyName);
  138. JSUserObject *jsValueObj = KJSValueToJSObject(value, exec);
  139. fJSUserObject->SetProperty(cfPropName, jsValueObj);
  140. if (jsValueObj) jsValueObj->Release();
  141. ReleaseCFType(cfPropName);
  142. }
  143. JSUserObject* UserObjectImp::GetJSUserObject() const
  144. {
  145. return fJSUserObject;
  146. }
  147. JSValue UserObjectImp::toPrimitive(ExecState *exec, JSType) const
  148. {
  149. JSValue result = jsUndefined();
  150. JSUserObject* jsObjPtr = KJSValueToJSObject(toObject(exec), exec);
  151. CFTypeRef cfValue = jsObjPtr ? jsObjPtr->CopyCFValue() : 0;
  152. if (cfValue) {
  153. CFTypeID cfType = CFGetTypeID(cfValue); // toPrimitive
  154. if (cfValue == GetCFNull()) {
  155. result = jsNull();
  156. }
  157. else if (cfType == CFBooleanGetTypeID()) {
  158. if (cfValue == kCFBooleanTrue) {
  159. result = jsBoolean(true);
  160. } else {
  161. result = jsBoolean(false);
  162. }
  163. } else if (cfType == CFStringGetTypeID()) {
  164. result = jsString(exec, CFStringToUString((CFStringRef)cfValue));
  165. } else if (cfType == CFNumberGetTypeID()) {
  166. double d = 0.0;
  167. CFNumberGetValue((CFNumberRef)cfValue, kCFNumberDoubleType, &d);
  168. result = jsNumber(exec, d);
  169. } else if (cfType == CFURLGetTypeID()) {
  170. CFURLRef absURL = CFURLCopyAbsoluteURL((CFURLRef)cfValue);
  171. if (absURL) {
  172. result = jsString(exec, CFStringToUString(CFURLGetString(absURL)));
  173. ReleaseCFType(absURL);
  174. }
  175. }
  176. ReleaseCFType(cfValue);
  177. }
  178. if (jsObjPtr)
  179. jsObjPtr->Release();
  180. return result;
  181. }
  182. bool UserObjectImp::toBoolean(ExecState *exec) const
  183. {
  184. bool result = false;
  185. JSUserObject* jsObjPtr = KJSValueToJSObject(toObject(exec), exec);
  186. CFTypeRef cfValue = jsObjPtr ? jsObjPtr->CopyCFValue() : 0;
  187. if (cfValue)
  188. {
  189. CFTypeID cfType = CFGetTypeID(cfValue); // toPrimitive
  190. if (cfValue == GetCFNull())
  191. {
  192. //
  193. }
  194. else if (cfType == CFBooleanGetTypeID())
  195. {
  196. if (cfValue == kCFBooleanTrue)
  197. {
  198. result = true;
  199. }
  200. }
  201. else if (cfType == CFStringGetTypeID())
  202. {
  203. if (CFStringGetLength((CFStringRef)cfValue))
  204. {
  205. result = true;
  206. }
  207. }
  208. else if (cfType == CFNumberGetTypeID())
  209. {
  210. if (cfValue != kCFNumberNaN)
  211. {
  212. double d;
  213. if (CFNumberGetValue((CFNumberRef)cfValue, kCFNumberDoubleType, &d))
  214. {
  215. if (d != 0)
  216. {
  217. result = true;
  218. }
  219. }
  220. }
  221. }
  222. else if (cfType == CFArrayGetTypeID())
  223. {
  224. if (CFArrayGetCount((CFArrayRef)cfValue))
  225. {
  226. result = true;
  227. }
  228. }
  229. else if (cfType == CFDictionaryGetTypeID())
  230. {
  231. if (CFDictionaryGetCount((CFDictionaryRef)cfValue))
  232. {
  233. result = true;
  234. }
  235. }
  236. else if (cfType == CFSetGetTypeID())
  237. {
  238. if (CFSetGetCount((CFSetRef)cfValue))
  239. {
  240. result = true;
  241. }
  242. }
  243. else if (cfType == CFURLGetTypeID())
  244. {
  245. CFURLRef absURL = CFURLCopyAbsoluteURL((CFURLRef)cfValue);
  246. if (absURL)
  247. {
  248. CFStringRef cfStr = CFURLGetString(absURL);
  249. if (cfStr && CFStringGetLength(cfStr))
  250. {
  251. result = true;
  252. }
  253. ReleaseCFType(absURL);
  254. }
  255. }
  256. }
  257. if (jsObjPtr) jsObjPtr->Release();
  258. ReleaseCFType(cfValue);
  259. return result;
  260. }
  261. double UserObjectImp::toNumber(ExecState *exec) const
  262. {
  263. double result = 0;
  264. JSUserObject* jsObjPtr = KJSValueToJSObject(toObject(exec), exec);
  265. CFTypeRef cfValue = jsObjPtr ? jsObjPtr->CopyCFValue() : 0;
  266. if (cfValue)
  267. {
  268. CFTypeID cfType = CFGetTypeID(cfValue);
  269. if (cfValue == GetCFNull())
  270. {
  271. //
  272. }
  273. else if (cfType == CFBooleanGetTypeID())
  274. {
  275. if (cfValue == kCFBooleanTrue)
  276. {
  277. result = 1;
  278. }
  279. }
  280. else if (cfType == CFStringGetTypeID())
  281. {
  282. result = CFStringGetDoubleValue((CFStringRef)cfValue);
  283. }
  284. else if (cfType == CFNumberGetTypeID())
  285. {
  286. CFNumberGetValue((CFNumberRef)cfValue, kCFNumberDoubleType, &result);
  287. }
  288. }
  289. ReleaseCFType(cfValue);
  290. if (jsObjPtr) jsObjPtr->Release();
  291. return result;
  292. }
  293. UString UserObjectImp::toString(ExecState *exec) const
  294. {
  295. UString result;
  296. JSUserObject* jsObjPtr = KJSValueToJSObject(toObject(exec), exec);
  297. CFTypeRef cfValue = jsObjPtr ? jsObjPtr->CopyCFValue() : 0;
  298. if (cfValue)
  299. {
  300. CFTypeID cfType = CFGetTypeID(cfValue);
  301. if (cfValue == GetCFNull())
  302. {
  303. //
  304. }
  305. else if (cfType == CFBooleanGetTypeID())
  306. {
  307. if (cfValue == kCFBooleanTrue)
  308. {
  309. result = "true";
  310. }
  311. else
  312. {
  313. result = "false";
  314. }
  315. }
  316. else if (cfType == CFStringGetTypeID())
  317. {
  318. result = CFStringToUString((CFStringRef)cfValue);
  319. }
  320. else if (cfType == CFNumberGetTypeID())
  321. {
  322. if (cfValue == kCFNumberNaN)
  323. {
  324. result = "Nan";
  325. }
  326. else if (CFNumberCompare(kCFNumberPositiveInfinity, (CFNumberRef)cfValue, 0) == 0)
  327. {
  328. result = "Infinity";
  329. }
  330. else if (CFNumberCompare(kCFNumberNegativeInfinity, (CFNumberRef)cfValue, 0) == 0)
  331. {
  332. result = "-Infinity";
  333. }
  334. else
  335. {
  336. CFStringRef cfNumStr;
  337. double d = 0;
  338. CFNumberGetValue((CFNumberRef)cfValue, kCFNumberDoubleType, &d);
  339. if (CFNumberIsFloatType((CFNumberRef)cfValue))
  340. {
  341. cfNumStr = CFStringCreateWithFormat(0, 0, CFSTR("%f"), d);
  342. }
  343. else
  344. {
  345. cfNumStr = CFStringCreateWithFormat(0, 0, CFSTR("%.0f"), d);
  346. }
  347. result = CFStringToUString(cfNumStr);
  348. ReleaseCFType(cfNumStr);
  349. }
  350. }
  351. else if (cfType == CFArrayGetTypeID())
  352. {
  353. //
  354. }
  355. else if (cfType == CFDictionaryGetTypeID())
  356. {
  357. //
  358. }
  359. else if (cfType == CFSetGetTypeID())
  360. {
  361. //
  362. }
  363. else if (cfType == CFURLGetTypeID())
  364. {
  365. CFURLRef absURL = CFURLCopyAbsoluteURL((CFURLRef)cfValue);
  366. if (absURL)
  367. {
  368. CFStringRef cfStr = CFURLGetString(absURL);
  369. if (cfStr)
  370. {
  371. result = CFStringToUString(cfStr);
  372. }
  373. ReleaseCFType(absURL);
  374. }
  375. }
  376. }
  377. ReleaseCFType(cfValue);
  378. if (jsObjPtr) jsObjPtr->Release();
  379. return result;
  380. }
  381. void UserObjectImp::markChildren(MarkStack& markStack)
  382. {
  383. JSObject::markChildren(markStack);
  384. if (fJSUserObject)
  385. fJSUserObject->Mark();
  386. }