JSObjectRef.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657
  1. /*
  2. * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
  3. * Copyright (C) 2008 Kelvin W Sherlock (ksherlock@gmail.com)
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  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. *
  14. * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
  15. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  17. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
  18. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  19. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  20. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  21. * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  22. * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  23. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  24. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  25. */
  26. #include "config.h"
  27. #include "JSObjectRef.h"
  28. #include "JSObjectRefPrivate.h"
  29. #include "APICast.h"
  30. #include "ButterflyInlines.h"
  31. #include "CodeBlock.h"
  32. #include "CopiedSpaceInlines.h"
  33. #include "DateConstructor.h"
  34. #include "ErrorConstructor.h"
  35. #include "FunctionConstructor.h"
  36. #include "Identifier.h"
  37. #include "InitializeThreading.h"
  38. #include "JSAPIWrapperObject.h"
  39. #include "JSArray.h"
  40. #include "JSCallbackConstructor.h"
  41. #include "JSCallbackFunction.h"
  42. #include "JSCallbackObject.h"
  43. #include "JSClassRef.h"
  44. #include "JSFunction.h"
  45. #include "JSGlobalObject.h"
  46. #include "JSObject.h"
  47. #include "JSRetainPtr.h"
  48. #include "JSString.h"
  49. #include "JSValueRef.h"
  50. #include "ObjectConstructor.h"
  51. #include "ObjectPrototype.h"
  52. #include "Operations.h"
  53. #include "PropertyNameArray.h"
  54. #include "RegExpConstructor.h"
  55. using namespace JSC;
  56. JSClassRef JSClassCreate(const JSClassDefinition* definition)
  57. {
  58. initializeThreading();
  59. RefPtr<OpaqueJSClass> jsClass = (definition->attributes & kJSClassAttributeNoAutomaticPrototype)
  60. ? OpaqueJSClass::createNoAutomaticPrototype(definition)
  61. : OpaqueJSClass::create(definition);
  62. return jsClass.release().leakRef();
  63. }
  64. JSClassRef JSClassRetain(JSClassRef jsClass)
  65. {
  66. jsClass->ref();
  67. return jsClass;
  68. }
  69. void JSClassRelease(JSClassRef jsClass)
  70. {
  71. jsClass->deref();
  72. }
  73. JSObjectRef JSObjectMake(JSContextRef ctx, JSClassRef jsClass, void* data)
  74. {
  75. if (!ctx) {
  76. ASSERT_NOT_REACHED();
  77. return 0;
  78. }
  79. ExecState* exec = toJS(ctx);
  80. APIEntryShim entryShim(exec);
  81. if (!jsClass)
  82. return toRef(constructEmptyObject(exec));
  83. JSCallbackObject<JSDestructibleObject>* object = JSCallbackObject<JSDestructibleObject>::create(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->callbackObjectStructure(), jsClass, data);
  84. if (JSObject* prototype = jsClass->prototype(exec))
  85. object->setPrototype(exec->vm(), prototype);
  86. return toRef(object);
  87. }
  88. JSObjectRef JSObjectMakeFunctionWithCallback(JSContextRef ctx, JSStringRef name, JSObjectCallAsFunctionCallback callAsFunction)
  89. {
  90. if (!ctx) {
  91. ASSERT_NOT_REACHED();
  92. return 0;
  93. }
  94. ExecState* exec = toJS(ctx);
  95. APIEntryShim entryShim(exec);
  96. return toRef(JSCallbackFunction::create(exec, exec->lexicalGlobalObject(), callAsFunction, name ? name->string() : ASCIILiteral("anonymous")));
  97. }
  98. JSObjectRef JSObjectMakeConstructor(JSContextRef ctx, JSClassRef jsClass, JSObjectCallAsConstructorCallback callAsConstructor)
  99. {
  100. if (!ctx) {
  101. ASSERT_NOT_REACHED();
  102. return 0;
  103. }
  104. ExecState* exec = toJS(ctx);
  105. APIEntryShim entryShim(exec);
  106. JSValue jsPrototype = jsClass ? jsClass->prototype(exec) : 0;
  107. if (!jsPrototype)
  108. jsPrototype = exec->lexicalGlobalObject()->objectPrototype();
  109. JSCallbackConstructor* constructor = JSCallbackConstructor::create(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->callbackConstructorStructure(), jsClass, callAsConstructor);
  110. constructor->putDirect(exec->vm(), exec->propertyNames().prototype, jsPrototype, DontEnum | DontDelete | ReadOnly);
  111. return toRef(constructor);
  112. }
  113. JSObjectRef JSObjectMakeFunction(JSContextRef ctx, JSStringRef name, unsigned parameterCount, const JSStringRef parameterNames[], JSStringRef body, JSStringRef sourceURL, int startingLineNumber, JSValueRef* exception)
  114. {
  115. if (!ctx) {
  116. ASSERT_NOT_REACHED();
  117. return 0;
  118. }
  119. ExecState* exec = toJS(ctx);
  120. APIEntryShim entryShim(exec);
  121. Identifier nameID = name ? name->identifier(&exec->vm()) : Identifier(exec, "anonymous");
  122. MarkedArgumentBuffer args;
  123. for (unsigned i = 0; i < parameterCount; i++)
  124. args.append(jsString(exec, parameterNames[i]->string()));
  125. args.append(jsString(exec, body->string()));
  126. JSObject* result = constructFunction(exec, exec->lexicalGlobalObject(), args, nameID, sourceURL->string(), TextPosition(OrdinalNumber::fromOneBasedInt(startingLineNumber), OrdinalNumber::first()));
  127. if (exec->hadException()) {
  128. if (exception)
  129. *exception = toRef(exec, exec->exception());
  130. exec->clearException();
  131. result = 0;
  132. }
  133. return toRef(result);
  134. }
  135. JSObjectRef JSObjectMakeArray(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
  136. {
  137. if (!ctx) {
  138. ASSERT_NOT_REACHED();
  139. return 0;
  140. }
  141. ExecState* exec = toJS(ctx);
  142. APIEntryShim entryShim(exec);
  143. JSObject* result;
  144. if (argumentCount) {
  145. MarkedArgumentBuffer argList;
  146. for (size_t i = 0; i < argumentCount; ++i)
  147. argList.append(toJS(exec, arguments[i]));
  148. result = constructArray(exec, static_cast<ArrayAllocationProfile*>(0), argList);
  149. } else
  150. result = constructEmptyArray(exec, 0);
  151. if (exec->hadException()) {
  152. if (exception)
  153. *exception = toRef(exec, exec->exception());
  154. exec->clearException();
  155. result = 0;
  156. }
  157. return toRef(result);
  158. }
  159. JSObjectRef JSObjectMakeDate(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
  160. {
  161. if (!ctx) {
  162. ASSERT_NOT_REACHED();
  163. return 0;
  164. }
  165. ExecState* exec = toJS(ctx);
  166. APIEntryShim entryShim(exec);
  167. MarkedArgumentBuffer argList;
  168. for (size_t i = 0; i < argumentCount; ++i)
  169. argList.append(toJS(exec, arguments[i]));
  170. JSObject* result = constructDate(exec, exec->lexicalGlobalObject(), argList);
  171. if (exec->hadException()) {
  172. if (exception)
  173. *exception = toRef(exec, exec->exception());
  174. exec->clearException();
  175. result = 0;
  176. }
  177. return toRef(result);
  178. }
  179. JSObjectRef JSObjectMakeError(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
  180. {
  181. if (!ctx) {
  182. ASSERT_NOT_REACHED();
  183. return 0;
  184. }
  185. ExecState* exec = toJS(ctx);
  186. APIEntryShim entryShim(exec);
  187. JSValue message = argumentCount ? toJS(exec, arguments[0]) : jsUndefined();
  188. Structure* errorStructure = exec->lexicalGlobalObject()->errorStructure();
  189. JSObject* result = ErrorInstance::create(exec, errorStructure, message);
  190. if (exec->hadException()) {
  191. if (exception)
  192. *exception = toRef(exec, exec->exception());
  193. exec->clearException();
  194. result = 0;
  195. }
  196. return toRef(result);
  197. }
  198. JSObjectRef JSObjectMakeRegExp(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
  199. {
  200. if (!ctx) {
  201. ASSERT_NOT_REACHED();
  202. return 0;
  203. }
  204. ExecState* exec = toJS(ctx);
  205. APIEntryShim entryShim(exec);
  206. MarkedArgumentBuffer argList;
  207. for (size_t i = 0; i < argumentCount; ++i)
  208. argList.append(toJS(exec, arguments[i]));
  209. JSObject* result = constructRegExp(exec, exec->lexicalGlobalObject(), argList);
  210. if (exec->hadException()) {
  211. if (exception)
  212. *exception = toRef(exec, exec->exception());
  213. exec->clearException();
  214. result = 0;
  215. }
  216. return toRef(result);
  217. }
  218. JSValueRef JSObjectGetPrototype(JSContextRef ctx, JSObjectRef object)
  219. {
  220. if (!ctx) {
  221. ASSERT_NOT_REACHED();
  222. return 0;
  223. }
  224. ExecState* exec = toJS(ctx);
  225. APIEntryShim entryShim(exec);
  226. JSObject* jsObject = toJS(object);
  227. return toRef(exec, jsObject->prototype());
  228. }
  229. void JSObjectSetPrototype(JSContextRef ctx, JSObjectRef object, JSValueRef value)
  230. {
  231. if (!ctx) {
  232. ASSERT_NOT_REACHED();
  233. return;
  234. }
  235. ExecState* exec = toJS(ctx);
  236. APIEntryShim entryShim(exec);
  237. JSObject* jsObject = toJS(object);
  238. JSValue jsValue = toJS(exec, value);
  239. jsObject->setPrototypeWithCycleCheck(exec->vm(), jsValue.isObject() ? jsValue : jsNull());
  240. }
  241. bool JSObjectHasProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName)
  242. {
  243. if (!ctx) {
  244. ASSERT_NOT_REACHED();
  245. return false;
  246. }
  247. ExecState* exec = toJS(ctx);
  248. APIEntryShim entryShim(exec);
  249. JSObject* jsObject = toJS(object);
  250. return jsObject->hasProperty(exec, propertyName->identifier(&exec->vm()));
  251. }
  252. JSValueRef JSObjectGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
  253. {
  254. if (!ctx) {
  255. ASSERT_NOT_REACHED();
  256. return 0;
  257. }
  258. ExecState* exec = toJS(ctx);
  259. APIEntryShim entryShim(exec);
  260. JSObject* jsObject = toJS(object);
  261. JSValue jsValue = jsObject->get(exec, propertyName->identifier(&exec->vm()));
  262. if (exec->hadException()) {
  263. if (exception)
  264. *exception = toRef(exec, exec->exception());
  265. exec->clearException();
  266. }
  267. return toRef(exec, jsValue);
  268. }
  269. void JSObjectSetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSPropertyAttributes attributes, JSValueRef* exception)
  270. {
  271. if (!ctx) {
  272. ASSERT_NOT_REACHED();
  273. return;
  274. }
  275. ExecState* exec = toJS(ctx);
  276. APIEntryShim entryShim(exec);
  277. JSObject* jsObject = toJS(object);
  278. Identifier name(propertyName->identifier(&exec->vm()));
  279. JSValue jsValue = toJS(exec, value);
  280. if (attributes && !jsObject->hasProperty(exec, name))
  281. jsObject->methodTable()->putDirectVirtual(jsObject, exec, name, jsValue, attributes);
  282. else {
  283. PutPropertySlot slot;
  284. jsObject->methodTable()->put(jsObject, exec, name, jsValue, slot);
  285. }
  286. if (exec->hadException()) {
  287. if (exception)
  288. *exception = toRef(exec, exec->exception());
  289. exec->clearException();
  290. }
  291. }
  292. JSValueRef JSObjectGetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned propertyIndex, JSValueRef* exception)
  293. {
  294. if (!ctx) {
  295. ASSERT_NOT_REACHED();
  296. return 0;
  297. }
  298. ExecState* exec = toJS(ctx);
  299. APIEntryShim entryShim(exec);
  300. JSObject* jsObject = toJS(object);
  301. JSValue jsValue = jsObject->get(exec, propertyIndex);
  302. if (exec->hadException()) {
  303. if (exception)
  304. *exception = toRef(exec, exec->exception());
  305. exec->clearException();
  306. }
  307. return toRef(exec, jsValue);
  308. }
  309. void JSObjectSetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned propertyIndex, JSValueRef value, JSValueRef* exception)
  310. {
  311. if (!ctx) {
  312. ASSERT_NOT_REACHED();
  313. return;
  314. }
  315. ExecState* exec = toJS(ctx);
  316. APIEntryShim entryShim(exec);
  317. JSObject* jsObject = toJS(object);
  318. JSValue jsValue = toJS(exec, value);
  319. jsObject->methodTable()->putByIndex(jsObject, exec, propertyIndex, jsValue, false);
  320. if (exec->hadException()) {
  321. if (exception)
  322. *exception = toRef(exec, exec->exception());
  323. exec->clearException();
  324. }
  325. }
  326. bool JSObjectDeleteProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
  327. {
  328. if (!ctx) {
  329. ASSERT_NOT_REACHED();
  330. return false;
  331. }
  332. ExecState* exec = toJS(ctx);
  333. APIEntryShim entryShim(exec);
  334. JSObject* jsObject = toJS(object);
  335. bool result = jsObject->methodTable()->deleteProperty(jsObject, exec, propertyName->identifier(&exec->vm()));
  336. if (exec->hadException()) {
  337. if (exception)
  338. *exception = toRef(exec, exec->exception());
  339. exec->clearException();
  340. }
  341. return result;
  342. }
  343. void* JSObjectGetPrivate(JSObjectRef object)
  344. {
  345. JSObject* jsObject = uncheckedToJS(object);
  346. if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::s_info))
  347. return jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->getPrivate();
  348. if (jsObject->inherits(&JSCallbackObject<JSDestructibleObject>::s_info))
  349. return jsCast<JSCallbackObject<JSDestructibleObject>*>(jsObject)->getPrivate();
  350. #if JSC_OBJC_API_ENABLED
  351. if (jsObject->inherits(&JSCallbackObject<JSAPIWrapperObject>::s_info))
  352. return jsCast<JSCallbackObject<JSAPIWrapperObject>*>(jsObject)->getPrivate();
  353. #endif
  354. return 0;
  355. }
  356. bool JSObjectSetPrivate(JSObjectRef object, void* data)
  357. {
  358. JSObject* jsObject = uncheckedToJS(object);
  359. if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::s_info)) {
  360. jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->setPrivate(data);
  361. return true;
  362. }
  363. if (jsObject->inherits(&JSCallbackObject<JSDestructibleObject>::s_info)) {
  364. jsCast<JSCallbackObject<JSDestructibleObject>*>(jsObject)->setPrivate(data);
  365. return true;
  366. }
  367. #if JSC_OBJC_API_ENABLED
  368. if (jsObject->inherits(&JSCallbackObject<JSAPIWrapperObject>::s_info)) {
  369. jsCast<JSCallbackObject<JSAPIWrapperObject>*>(jsObject)->setPrivate(data);
  370. return true;
  371. }
  372. #endif
  373. return false;
  374. }
  375. JSValueRef JSObjectGetPrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName)
  376. {
  377. ExecState* exec = toJS(ctx);
  378. APIEntryShim entryShim(exec);
  379. JSObject* jsObject = toJS(object);
  380. JSValue result;
  381. Identifier name(propertyName->identifier(&exec->vm()));
  382. if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::s_info))
  383. result = jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->getPrivateProperty(name);
  384. else if (jsObject->inherits(&JSCallbackObject<JSDestructibleObject>::s_info))
  385. result = jsCast<JSCallbackObject<JSDestructibleObject>*>(jsObject)->getPrivateProperty(name);
  386. #if JSC_OBJC_API_ENABLED
  387. else if (jsObject->inherits(&JSCallbackObject<JSAPIWrapperObject>::s_info))
  388. result = jsCast<JSCallbackObject<JSAPIWrapperObject>*>(jsObject)->getPrivateProperty(name);
  389. #endif
  390. return toRef(exec, result);
  391. }
  392. bool JSObjectSetPrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value)
  393. {
  394. ExecState* exec = toJS(ctx);
  395. APIEntryShim entryShim(exec);
  396. JSObject* jsObject = toJS(object);
  397. JSValue jsValue = value ? toJS(exec, value) : JSValue();
  398. Identifier name(propertyName->identifier(&exec->vm()));
  399. if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::s_info)) {
  400. jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->setPrivateProperty(exec->vm(), name, jsValue);
  401. return true;
  402. }
  403. if (jsObject->inherits(&JSCallbackObject<JSDestructibleObject>::s_info)) {
  404. jsCast<JSCallbackObject<JSDestructibleObject>*>(jsObject)->setPrivateProperty(exec->vm(), name, jsValue);
  405. return true;
  406. }
  407. #if JSC_OBJC_API_ENABLED
  408. if (jsObject->inherits(&JSCallbackObject<JSAPIWrapperObject>::s_info)) {
  409. jsCast<JSCallbackObject<JSAPIWrapperObject>*>(jsObject)->setPrivateProperty(exec->vm(), name, jsValue);
  410. return true;
  411. }
  412. #endif
  413. return false;
  414. }
  415. bool JSObjectDeletePrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName)
  416. {
  417. ExecState* exec = toJS(ctx);
  418. APIEntryShim entryShim(exec);
  419. JSObject* jsObject = toJS(object);
  420. Identifier name(propertyName->identifier(&exec->vm()));
  421. if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::s_info)) {
  422. jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->deletePrivateProperty(name);
  423. return true;
  424. }
  425. if (jsObject->inherits(&JSCallbackObject<JSDestructibleObject>::s_info)) {
  426. jsCast<JSCallbackObject<JSDestructibleObject>*>(jsObject)->deletePrivateProperty(name);
  427. return true;
  428. }
  429. #if JSC_OBJC_API_ENABLED
  430. if (jsObject->inherits(&JSCallbackObject<JSAPIWrapperObject>::s_info)) {
  431. jsCast<JSCallbackObject<JSAPIWrapperObject>*>(jsObject)->deletePrivateProperty(name);
  432. return true;
  433. }
  434. #endif
  435. return false;
  436. }
  437. bool JSObjectIsFunction(JSContextRef, JSObjectRef object)
  438. {
  439. if (!object)
  440. return false;
  441. CallData callData;
  442. JSCell* cell = toJS(object);
  443. return cell->methodTable()->getCallData(cell, callData) != CallTypeNone;
  444. }
  445. JSValueRef JSObjectCallAsFunction(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
  446. {
  447. ExecState* exec = toJS(ctx);
  448. APIEntryShim entryShim(exec);
  449. if (!object)
  450. return 0;
  451. JSObject* jsObject = toJS(object);
  452. JSObject* jsThisObject = toJS(thisObject);
  453. if (!jsThisObject)
  454. jsThisObject = exec->globalThisValue();
  455. jsThisObject = jsThisObject->methodTable()->toThisObject(jsThisObject, exec);
  456. MarkedArgumentBuffer argList;
  457. for (size_t i = 0; i < argumentCount; i++)
  458. argList.append(toJS(exec, arguments[i]));
  459. CallData callData;
  460. CallType callType = jsObject->methodTable()->getCallData(jsObject, callData);
  461. if (callType == CallTypeNone)
  462. return 0;
  463. JSValueRef result = toRef(exec, call(exec, jsObject, callType, callData, jsThisObject, argList));
  464. if (exec->hadException()) {
  465. if (exception)
  466. *exception = toRef(exec, exec->exception());
  467. exec->clearException();
  468. result = 0;
  469. }
  470. return result;
  471. }
  472. bool JSObjectIsConstructor(JSContextRef, JSObjectRef object)
  473. {
  474. if (!object)
  475. return false;
  476. JSObject* jsObject = toJS(object);
  477. ConstructData constructData;
  478. return jsObject->methodTable()->getConstructData(jsObject, constructData) != ConstructTypeNone;
  479. }
  480. JSObjectRef JSObjectCallAsConstructor(JSContextRef ctx, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
  481. {
  482. ExecState* exec = toJS(ctx);
  483. APIEntryShim entryShim(exec);
  484. if (!object)
  485. return 0;
  486. JSObject* jsObject = toJS(object);
  487. ConstructData constructData;
  488. ConstructType constructType = jsObject->methodTable()->getConstructData(jsObject, constructData);
  489. if (constructType == ConstructTypeNone)
  490. return 0;
  491. MarkedArgumentBuffer argList;
  492. for (size_t i = 0; i < argumentCount; i++)
  493. argList.append(toJS(exec, arguments[i]));
  494. JSObjectRef result = toRef(construct(exec, jsObject, constructType, constructData, argList));
  495. if (exec->hadException()) {
  496. if (exception)
  497. *exception = toRef(exec, exec->exception());
  498. exec->clearException();
  499. result = 0;
  500. }
  501. return result;
  502. }
  503. struct OpaqueJSPropertyNameArray {
  504. WTF_MAKE_FAST_ALLOCATED;
  505. public:
  506. OpaqueJSPropertyNameArray(VM* vm)
  507. : refCount(0)
  508. , vm(vm)
  509. {
  510. }
  511. unsigned refCount;
  512. VM* vm;
  513. Vector<JSRetainPtr<JSStringRef> > array;
  514. };
  515. JSPropertyNameArrayRef JSObjectCopyPropertyNames(JSContextRef ctx, JSObjectRef object)
  516. {
  517. if (!ctx) {
  518. ASSERT_NOT_REACHED();
  519. return 0;
  520. }
  521. JSObject* jsObject = toJS(object);
  522. ExecState* exec = toJS(ctx);
  523. APIEntryShim entryShim(exec);
  524. VM* vm = &exec->vm();
  525. JSPropertyNameArrayRef propertyNames = new OpaqueJSPropertyNameArray(vm);
  526. PropertyNameArray array(vm);
  527. jsObject->methodTable()->getPropertyNames(jsObject, exec, array, ExcludeDontEnumProperties);
  528. size_t size = array.size();
  529. propertyNames->array.reserveInitialCapacity(size);
  530. for (size_t i = 0; i < size; ++i)
  531. propertyNames->array.uncheckedAppend(JSRetainPtr<JSStringRef>(Adopt, OpaqueJSString::create(array[i].string()).leakRef()));
  532. return JSPropertyNameArrayRetain(propertyNames);
  533. }
  534. JSPropertyNameArrayRef JSPropertyNameArrayRetain(JSPropertyNameArrayRef array)
  535. {
  536. ++array->refCount;
  537. return array;
  538. }
  539. void JSPropertyNameArrayRelease(JSPropertyNameArrayRef array)
  540. {
  541. if (--array->refCount == 0) {
  542. APIEntryShim entryShim(array->vm, false);
  543. delete array;
  544. }
  545. }
  546. size_t JSPropertyNameArrayGetCount(JSPropertyNameArrayRef array)
  547. {
  548. return array->array.size();
  549. }
  550. JSStringRef JSPropertyNameArrayGetNameAtIndex(JSPropertyNameArrayRef array, size_t index)
  551. {
  552. return array->array[static_cast<unsigned>(index)].get();
  553. }
  554. void JSPropertyNameAccumulatorAddName(JSPropertyNameAccumulatorRef array, JSStringRef propertyName)
  555. {
  556. PropertyNameArray* propertyNames = toJS(array);
  557. APIEntryShim entryShim(propertyNames->vm());
  558. propertyNames->add(propertyName->identifier(propertyNames->vm()));
  559. }