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 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 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 27#include "config.h" 28#include "JSObjectRef.h" 29#include "JSObjectRefPrivate.h" 30 31#include "APICast.h" 32#include "ButterflyInlines.h" 33#include "CodeBlock.h" 34#include "CopiedSpaceInlines.h" 35#include "DateConstructor.h" 36#include "ErrorConstructor.h" 37#include "FunctionConstructor.h" 38#include "Identifier.h" 39#include "InitializeThreading.h" 40#include "JSAPIWrapperObject.h" 41#include "JSArray.h" 42#include "JSCallbackConstructor.h" 43#include "JSCallbackFunction.h" 44#include "JSCallbackObject.h" 45#include "JSClassRef.h" 46#include "JSFunction.h" 47#include "JSGlobalObject.h" 48#include "JSObject.h" 49#include "JSRetainPtr.h" 50#include "JSString.h" 51#include "JSValueRef.h" 52#include "ObjectConstructor.h" 53#include "ObjectPrototype.h" 54#include "JSCInlines.h" 55#include "PropertyNameArray.h" 56#include "RegExpConstructor.h" 57 58#if ENABLE(REMOTE_INSPECTOR) 59#include "JSGlobalObjectInspectorController.h" 60#endif 61 62using namespace JSC; 63 64JSClassRef JSClassCreate(const JSClassDefinition* definition) 65{ 66 initializeThreading(); 67 RefPtr<OpaqueJSClass> jsClass = (definition->attributes & kJSClassAttributeNoAutomaticPrototype) 68 ? OpaqueJSClass::createNoAutomaticPrototype(definition) 69 : OpaqueJSClass::create(definition); 70 71 return jsClass.release().leakRef(); 72} 73 74JSClassRef JSClassRetain(JSClassRef jsClass) 75{ 76 jsClass->ref(); 77 return jsClass; 78} 79 80void JSClassRelease(JSClassRef jsClass) 81{ 82 jsClass->deref(); 83} 84 85JSObjectRef JSObjectMake(JSContextRef ctx, JSClassRef jsClass, void* data) 86{ 87 if (!ctx) { 88 ASSERT_NOT_REACHED(); 89 return 0; 90 } 91 ExecState* exec = toJS(ctx); 92 JSLockHolder locker(exec); 93 94 if (!jsClass) 95 return toRef(constructEmptyObject(exec)); 96 97 JSCallbackObject<JSDestructibleObject>* object = JSCallbackObject<JSDestructibleObject>::create(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->callbackObjectStructure(), jsClass, data); 98 if (JSObject* prototype = jsClass->prototype(exec)) 99 object->setPrototype(exec->vm(), prototype); 100 101 return toRef(object); 102} 103 104JSObjectRef JSObjectMakeFunctionWithCallback(JSContextRef ctx, JSStringRef name, JSObjectCallAsFunctionCallback callAsFunction) 105{ 106 if (!ctx) { 107 ASSERT_NOT_REACHED(); 108 return 0; 109 } 110 ExecState* exec = toJS(ctx); 111 JSLockHolder locker(exec); 112 return toRef(JSCallbackFunction::create(exec->vm(), exec->lexicalGlobalObject(), callAsFunction, name ? name->string() : ASCIILiteral("anonymous"))); 113} 114 115JSObjectRef JSObjectMakeConstructor(JSContextRef ctx, JSClassRef jsClass, JSObjectCallAsConstructorCallback callAsConstructor) 116{ 117 if (!ctx) { 118 ASSERT_NOT_REACHED(); 119 return 0; 120 } 121 ExecState* exec = toJS(ctx); 122 JSLockHolder locker(exec); 123 124 JSValue jsPrototype = jsClass ? jsClass->prototype(exec) : 0; 125 if (!jsPrototype) 126 jsPrototype = exec->lexicalGlobalObject()->objectPrototype(); 127 128 JSCallbackConstructor* constructor = JSCallbackConstructor::create(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->callbackConstructorStructure(), jsClass, callAsConstructor); 129 constructor->putDirect(exec->vm(), exec->propertyNames().prototype, jsPrototype, DontEnum | DontDelete | ReadOnly); 130 return toRef(constructor); 131} 132 133JSObjectRef JSObjectMakeFunction(JSContextRef ctx, JSStringRef name, unsigned parameterCount, const JSStringRef parameterNames[], JSStringRef body, JSStringRef sourceURL, int startingLineNumber, JSValueRef* exception) 134{ 135 if (!ctx) { 136 ASSERT_NOT_REACHED(); 137 return 0; 138 } 139 ExecState* exec = toJS(ctx); 140 JSLockHolder locker(exec); 141 142 startingLineNumber = std::max(1, startingLineNumber); 143 Identifier nameID = name ? name->identifier(&exec->vm()) : Identifier(exec, "anonymous"); 144 145 MarkedArgumentBuffer args; 146 for (unsigned i = 0; i < parameterCount; i++) 147 args.append(jsString(exec, parameterNames[i]->string())); 148 args.append(jsString(exec, body->string())); 149 150 JSObject* result = constructFunction(exec, exec->lexicalGlobalObject(), args, nameID, sourceURL->string(), TextPosition(OrdinalNumber::fromOneBasedInt(startingLineNumber), OrdinalNumber::first())); 151 if (exec->hadException()) { 152 JSValue exceptionValue = exec->exception(); 153 if (exception) 154 *exception = toRef(exec, exceptionValue); 155 exec->clearException(); 156#if ENABLE(REMOTE_INSPECTOR) 157 exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue); 158#endif 159 result = 0; 160 } 161 return toRef(result); 162} 163 164JSObjectRef JSObjectMakeArray(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) 165{ 166 if (!ctx) { 167 ASSERT_NOT_REACHED(); 168 return 0; 169 } 170 ExecState* exec = toJS(ctx); 171 JSLockHolder locker(exec); 172 173 JSObject* result; 174 if (argumentCount) { 175 MarkedArgumentBuffer argList; 176 for (size_t i = 0; i < argumentCount; ++i) 177 argList.append(toJS(exec, arguments[i])); 178 179 result = constructArray(exec, static_cast<ArrayAllocationProfile*>(0), argList); 180 } else 181 result = constructEmptyArray(exec, 0); 182 183 if (exec->hadException()) { 184 JSValue exceptionValue = exec->exception(); 185 if (exception) 186 *exception = toRef(exec, exceptionValue); 187 exec->clearException(); 188#if ENABLE(REMOTE_INSPECTOR) 189 exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue); 190#endif 191 result = 0; 192 } 193 194 return toRef(result); 195} 196 197JSObjectRef JSObjectMakeDate(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) 198{ 199 if (!ctx) { 200 ASSERT_NOT_REACHED(); 201 return 0; 202 } 203 ExecState* exec = toJS(ctx); 204 JSLockHolder locker(exec); 205 206 MarkedArgumentBuffer argList; 207 for (size_t i = 0; i < argumentCount; ++i) 208 argList.append(toJS(exec, arguments[i])); 209 210 JSObject* result = constructDate(exec, exec->lexicalGlobalObject(), argList); 211 if (exec->hadException()) { 212 JSValue exceptionValue = exec->exception(); 213 if (exception) 214 *exception = toRef(exec, exceptionValue); 215 exec->clearException(); 216#if ENABLE(REMOTE_INSPECTOR) 217 exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue); 218#endif 219 result = 0; 220 } 221 222 return toRef(result); 223} 224 225JSObjectRef JSObjectMakeError(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) 226{ 227 if (!ctx) { 228 ASSERT_NOT_REACHED(); 229 return 0; 230 } 231 ExecState* exec = toJS(ctx); 232 JSLockHolder locker(exec); 233 234 JSValue message = argumentCount ? toJS(exec, arguments[0]) : jsUndefined(); 235 Structure* errorStructure = exec->lexicalGlobalObject()->errorStructure(); 236 JSObject* result = ErrorInstance::create(exec, errorStructure, message); 237 238 if (exec->hadException()) { 239 JSValue exceptionValue = exec->exception(); 240 if (exception) 241 *exception = toRef(exec, exceptionValue); 242 exec->clearException(); 243#if ENABLE(REMOTE_INSPECTOR) 244 exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue); 245#endif 246 result = 0; 247 } 248 249 return toRef(result); 250} 251 252JSObjectRef JSObjectMakeRegExp(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) 253{ 254 if (!ctx) { 255 ASSERT_NOT_REACHED(); 256 return 0; 257 } 258 ExecState* exec = toJS(ctx); 259 JSLockHolder locker(exec); 260 261 MarkedArgumentBuffer argList; 262 for (size_t i = 0; i < argumentCount; ++i) 263 argList.append(toJS(exec, arguments[i])); 264 265 JSObject* result = constructRegExp(exec, exec->lexicalGlobalObject(), argList); 266 if (exec->hadException()) { 267 JSValue exceptionValue = exec->exception(); 268 if (exception) 269 *exception = toRef(exec, exceptionValue); 270 exec->clearException(); 271#if ENABLE(REMOTE_INSPECTOR) 272 exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue); 273#endif 274 result = 0; 275 } 276 277 return toRef(result); 278} 279 280JSValueRef JSObjectGetPrototype(JSContextRef ctx, JSObjectRef object) 281{ 282 if (!ctx) { 283 ASSERT_NOT_REACHED(); 284 return 0; 285 } 286 ExecState* exec = toJS(ctx); 287 JSLockHolder locker(exec); 288 289 JSObject* jsObject = toJS(object); 290 return toRef(exec, jsObject->prototype()); 291} 292 293void JSObjectSetPrototype(JSContextRef ctx, JSObjectRef object, JSValueRef value) 294{ 295 if (!ctx) { 296 ASSERT_NOT_REACHED(); 297 return; 298 } 299 ExecState* exec = toJS(ctx); 300 JSLockHolder locker(exec); 301 302 JSObject* jsObject = toJS(object); 303 JSValue jsValue = toJS(exec, value); 304 305 jsObject->setPrototypeWithCycleCheck(exec, jsValue.isObject() ? jsValue : jsNull()); 306} 307 308bool JSObjectHasProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName) 309{ 310 if (!ctx) { 311 ASSERT_NOT_REACHED(); 312 return false; 313 } 314 ExecState* exec = toJS(ctx); 315 JSLockHolder locker(exec); 316 317 JSObject* jsObject = toJS(object); 318 319 return jsObject->hasProperty(exec, propertyName->identifier(&exec->vm())); 320} 321 322JSValueRef JSObjectGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception) 323{ 324 if (!ctx) { 325 ASSERT_NOT_REACHED(); 326 return 0; 327 } 328 ExecState* exec = toJS(ctx); 329 JSLockHolder locker(exec); 330 331 JSObject* jsObject = toJS(object); 332 333 JSValue jsValue = jsObject->get(exec, propertyName->identifier(&exec->vm())); 334 if (exec->hadException()) { 335 JSValue exceptionValue = exec->exception(); 336 if (exception) 337 *exception = toRef(exec, exceptionValue); 338 exec->clearException(); 339#if ENABLE(REMOTE_INSPECTOR) 340 exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue); 341#endif 342 } 343 return toRef(exec, jsValue); 344} 345 346void JSObjectSetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSPropertyAttributes attributes, JSValueRef* exception) 347{ 348 if (!ctx) { 349 ASSERT_NOT_REACHED(); 350 return; 351 } 352 ExecState* exec = toJS(ctx); 353 JSLockHolder locker(exec); 354 355 JSObject* jsObject = toJS(object); 356 Identifier name(propertyName->identifier(&exec->vm())); 357 JSValue jsValue = toJS(exec, value); 358 359 if (attributes && !jsObject->hasProperty(exec, name)) { 360 PropertyDescriptor desc(jsValue, attributes); 361 jsObject->methodTable()->defineOwnProperty(jsObject, exec, name, desc, false); 362 } else { 363 PutPropertySlot slot(jsObject); 364 jsObject->methodTable()->put(jsObject, exec, name, jsValue, slot); 365 } 366 367 if (exec->hadException()) { 368 JSValue exceptionValue = exec->exception(); 369 if (exception) 370 *exception = toRef(exec, exceptionValue); 371 exec->clearException(); 372#if ENABLE(REMOTE_INSPECTOR) 373 exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue); 374#endif 375 } 376} 377 378JSValueRef JSObjectGetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned propertyIndex, JSValueRef* exception) 379{ 380 if (!ctx) { 381 ASSERT_NOT_REACHED(); 382 return 0; 383 } 384 ExecState* exec = toJS(ctx); 385 JSLockHolder locker(exec); 386 387 JSObject* jsObject = toJS(object); 388 389 JSValue jsValue = jsObject->get(exec, propertyIndex); 390 if (exec->hadException()) { 391 JSValue exceptionValue = exec->exception(); 392 if (exception) 393 *exception = toRef(exec, exceptionValue); 394 exec->clearException(); 395#if ENABLE(REMOTE_INSPECTOR) 396 exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue); 397#endif 398 } 399 return toRef(exec, jsValue); 400} 401 402 403void JSObjectSetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned propertyIndex, JSValueRef value, JSValueRef* exception) 404{ 405 if (!ctx) { 406 ASSERT_NOT_REACHED(); 407 return; 408 } 409 ExecState* exec = toJS(ctx); 410 JSLockHolder locker(exec); 411 412 JSObject* jsObject = toJS(object); 413 JSValue jsValue = toJS(exec, value); 414 415 jsObject->methodTable()->putByIndex(jsObject, exec, propertyIndex, jsValue, false); 416 if (exec->hadException()) { 417 JSValue exceptionValue = exec->exception(); 418 if (exception) 419 *exception = toRef(exec, exceptionValue); 420 exec->clearException(); 421#if ENABLE(REMOTE_INSPECTOR) 422 exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue); 423#endif 424 } 425} 426 427bool JSObjectDeleteProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception) 428{ 429 if (!ctx) { 430 ASSERT_NOT_REACHED(); 431 return false; 432 } 433 ExecState* exec = toJS(ctx); 434 JSLockHolder locker(exec); 435 436 JSObject* jsObject = toJS(object); 437 438 bool result = jsObject->methodTable()->deleteProperty(jsObject, exec, propertyName->identifier(&exec->vm())); 439 if (exec->hadException()) { 440 JSValue exceptionValue = exec->exception(); 441 if (exception) 442 *exception = toRef(exec, exceptionValue); 443 exec->clearException(); 444#if ENABLE(REMOTE_INSPECTOR) 445 exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue); 446#endif 447 } 448 return result; 449} 450 451void* JSObjectGetPrivate(JSObjectRef object) 452{ 453 JSObject* jsObject = uncheckedToJS(object); 454 455 // Get wrapped object if proxied 456 if (jsObject->inherits(JSProxy::info())) 457 jsObject = jsCast<JSProxy*>(jsObject)->target(); 458 459 if (jsObject->inherits(JSCallbackObject<JSGlobalObject>::info())) 460 return jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->getPrivate(); 461 if (jsObject->inherits(JSCallbackObject<JSDestructibleObject>::info())) 462 return jsCast<JSCallbackObject<JSDestructibleObject>*>(jsObject)->getPrivate(); 463#if JSC_OBJC_API_ENABLED 464 if (jsObject->inherits(JSCallbackObject<JSAPIWrapperObject>::info())) 465 return jsCast<JSCallbackObject<JSAPIWrapperObject>*>(jsObject)->getPrivate(); 466#endif 467 468 return 0; 469} 470 471bool JSObjectSetPrivate(JSObjectRef object, void* data) 472{ 473 JSObject* jsObject = uncheckedToJS(object); 474 475 // Get wrapped object if proxied 476 if (jsObject->inherits(JSProxy::info())) 477 jsObject = jsCast<JSProxy*>(jsObject)->target(); 478 479 if (jsObject->inherits(JSCallbackObject<JSGlobalObject>::info())) { 480 jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->setPrivate(data); 481 return true; 482 } 483 if (jsObject->inherits(JSCallbackObject<JSDestructibleObject>::info())) { 484 jsCast<JSCallbackObject<JSDestructibleObject>*>(jsObject)->setPrivate(data); 485 return true; 486 } 487#if JSC_OBJC_API_ENABLED 488 if (jsObject->inherits(JSCallbackObject<JSAPIWrapperObject>::info())) { 489 jsCast<JSCallbackObject<JSAPIWrapperObject>*>(jsObject)->setPrivate(data); 490 return true; 491 } 492#endif 493 494 return false; 495} 496 497JSValueRef JSObjectGetPrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName) 498{ 499 ExecState* exec = toJS(ctx); 500 JSLockHolder locker(exec); 501 JSObject* jsObject = toJS(object); 502 JSValue result; 503 Identifier name(propertyName->identifier(&exec->vm())); 504 if (jsObject->inherits(JSCallbackObject<JSGlobalObject>::info())) 505 result = jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->getPrivateProperty(name); 506 else if (jsObject->inherits(JSCallbackObject<JSDestructibleObject>::info())) 507 result = jsCast<JSCallbackObject<JSDestructibleObject>*>(jsObject)->getPrivateProperty(name); 508#if JSC_OBJC_API_ENABLED 509 else if (jsObject->inherits(JSCallbackObject<JSAPIWrapperObject>::info())) 510 result = jsCast<JSCallbackObject<JSAPIWrapperObject>*>(jsObject)->getPrivateProperty(name); 511#endif 512 return toRef(exec, result); 513} 514 515bool JSObjectSetPrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value) 516{ 517 ExecState* exec = toJS(ctx); 518 JSLockHolder locker(exec); 519 JSObject* jsObject = toJS(object); 520 JSValue jsValue = value ? toJS(exec, value) : JSValue(); 521 Identifier name(propertyName->identifier(&exec->vm())); 522 if (jsObject->inherits(JSCallbackObject<JSGlobalObject>::info())) { 523 jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->setPrivateProperty(exec->vm(), name, jsValue); 524 return true; 525 } 526 if (jsObject->inherits(JSCallbackObject<JSDestructibleObject>::info())) { 527 jsCast<JSCallbackObject<JSDestructibleObject>*>(jsObject)->setPrivateProperty(exec->vm(), name, jsValue); 528 return true; 529 } 530#if JSC_OBJC_API_ENABLED 531 if (jsObject->inherits(JSCallbackObject<JSAPIWrapperObject>::info())) { 532 jsCast<JSCallbackObject<JSAPIWrapperObject>*>(jsObject)->setPrivateProperty(exec->vm(), name, jsValue); 533 return true; 534 } 535#endif 536 return false; 537} 538 539bool JSObjectDeletePrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName) 540{ 541 ExecState* exec = toJS(ctx); 542 JSLockHolder locker(exec); 543 JSObject* jsObject = toJS(object); 544 Identifier name(propertyName->identifier(&exec->vm())); 545 if (jsObject->inherits(JSCallbackObject<JSGlobalObject>::info())) { 546 jsCast<JSCallbackObject<JSGlobalObject>*>(jsObject)->deletePrivateProperty(name); 547 return true; 548 } 549 if (jsObject->inherits(JSCallbackObject<JSDestructibleObject>::info())) { 550 jsCast<JSCallbackObject<JSDestructibleObject>*>(jsObject)->deletePrivateProperty(name); 551 return true; 552 } 553#if JSC_OBJC_API_ENABLED 554 if (jsObject->inherits(JSCallbackObject<JSAPIWrapperObject>::info())) { 555 jsCast<JSCallbackObject<JSAPIWrapperObject>*>(jsObject)->deletePrivateProperty(name); 556 return true; 557 } 558#endif 559 return false; 560} 561 562bool JSObjectIsFunction(JSContextRef ctx, JSObjectRef object) 563{ 564 if (!object) 565 return false; 566 JSLockHolder locker(toJS(ctx)); 567 CallData callData; 568 JSCell* cell = toJS(object); 569 return cell->methodTable()->getCallData(cell, callData) != CallTypeNone; 570} 571 572JSValueRef JSObjectCallAsFunction(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) 573{ 574 ExecState* exec = toJS(ctx); 575 JSLockHolder locker(exec); 576 577 if (!object) 578 return 0; 579 580 JSObject* jsObject = toJS(object); 581 JSObject* jsThisObject = toJS(thisObject); 582 583 if (!jsThisObject) 584 jsThisObject = exec->globalThisValue(); 585 586 MarkedArgumentBuffer argList; 587 for (size_t i = 0; i < argumentCount; i++) 588 argList.append(toJS(exec, arguments[i])); 589 590 CallData callData; 591 CallType callType = jsObject->methodTable()->getCallData(jsObject, callData); 592 if (callType == CallTypeNone) 593 return 0; 594 595 JSValueRef result = toRef(exec, call(exec, jsObject, callType, callData, jsThisObject, argList)); 596 if (exec->hadException()) { 597 JSValue exceptionValue = exec->exception(); 598 if (exception) 599 *exception = toRef(exec, exceptionValue); 600 exec->clearException(); 601#if ENABLE(REMOTE_INSPECTOR) 602 exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue); 603#endif 604 result = 0; 605 } 606 return result; 607} 608 609bool JSObjectIsConstructor(JSContextRef, JSObjectRef object) 610{ 611 if (!object) 612 return false; 613 JSObject* jsObject = toJS(object); 614 ConstructData constructData; 615 return jsObject->methodTable()->getConstructData(jsObject, constructData) != ConstructTypeNone; 616} 617 618JSObjectRef JSObjectCallAsConstructor(JSContextRef ctx, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) 619{ 620 ExecState* exec = toJS(ctx); 621 JSLockHolder locker(exec); 622 623 if (!object) 624 return 0; 625 626 JSObject* jsObject = toJS(object); 627 628 ConstructData constructData; 629 ConstructType constructType = jsObject->methodTable()->getConstructData(jsObject, constructData); 630 if (constructType == ConstructTypeNone) 631 return 0; 632 633 MarkedArgumentBuffer argList; 634 for (size_t i = 0; i < argumentCount; i++) 635 argList.append(toJS(exec, arguments[i])); 636 JSObjectRef result = toRef(construct(exec, jsObject, constructType, constructData, argList)); 637 if (exec->hadException()) { 638 JSValue exceptionValue = exec->exception(); 639 if (exception) 640 *exception = toRef(exec, exceptionValue); 641 exec->clearException(); 642#if ENABLE(REMOTE_INSPECTOR) 643 exec->vmEntryGlobalObject()->inspectorController().reportAPIException(exec, exceptionValue); 644#endif 645 result = 0; 646 } 647 return result; 648} 649 650struct OpaqueJSPropertyNameArray { 651 WTF_MAKE_FAST_ALLOCATED; 652public: 653 OpaqueJSPropertyNameArray(VM* vm) 654 : refCount(0) 655 , vm(vm) 656 { 657 } 658 659 unsigned refCount; 660 VM* vm; 661 Vector<JSRetainPtr<JSStringRef>> array; 662}; 663 664JSPropertyNameArrayRef JSObjectCopyPropertyNames(JSContextRef ctx, JSObjectRef object) 665{ 666 if (!ctx) { 667 ASSERT_NOT_REACHED(); 668 return 0; 669 } 670 ExecState* exec = toJS(ctx); 671 JSLockHolder locker(exec); 672 673 VM* vm = &exec->vm(); 674 675 JSObject* jsObject = toJS(object); 676 JSPropertyNameArrayRef propertyNames = new OpaqueJSPropertyNameArray(vm); 677 PropertyNameArray array(vm); 678 jsObject->methodTable()->getPropertyNames(jsObject, exec, array, ExcludeDontEnumProperties); 679 680 size_t size = array.size(); 681 propertyNames->array.reserveInitialCapacity(size); 682 for (size_t i = 0; i < size; ++i) 683 propertyNames->array.uncheckedAppend(JSRetainPtr<JSStringRef>(Adopt, OpaqueJSString::create(array[i].string()).leakRef())); 684 685 return JSPropertyNameArrayRetain(propertyNames); 686} 687 688JSPropertyNameArrayRef JSPropertyNameArrayRetain(JSPropertyNameArrayRef array) 689{ 690 ++array->refCount; 691 return array; 692} 693 694void JSPropertyNameArrayRelease(JSPropertyNameArrayRef array) 695{ 696 if (--array->refCount == 0) { 697 JSLockHolder locker(array->vm); 698 delete array; 699 } 700} 701 702size_t JSPropertyNameArrayGetCount(JSPropertyNameArrayRef array) 703{ 704 return array->array.size(); 705} 706 707JSStringRef JSPropertyNameArrayGetNameAtIndex(JSPropertyNameArrayRef array, size_t index) 708{ 709 return array->array[static_cast<unsigned>(index)].get(); 710} 711 712void JSPropertyNameAccumulatorAddName(JSPropertyNameAccumulatorRef array, JSStringRef propertyName) 713{ 714 PropertyNameArray* propertyNames = toJS(array); 715 JSLockHolder locker(propertyNames->vm()); 716 propertyNames->add(propertyName->identifier(propertyNames->vm())); 717} 718