2 * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Kelvin W Sherlock (ksherlock@gmail.com)
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
28 #include "JSObjectRef.h"
29 #include "JSObjectRefPrivate.h"
32 #include "CodeBlock.h"
33 #include "DateConstructor.h"
34 #include "ErrorConstructor.h"
35 #include "FunctionConstructor.h"
36 #include "Identifier.h"
37 #include "InitializeThreading.h"
39 #include "JSCallbackConstructor.h"
40 #include "JSCallbackFunction.h"
41 #include "JSCallbackObject.h"
42 #include "JSClassRef.h"
43 #include "JSFunction.h"
44 #include "JSGlobalObject.h"
46 #include "JSRetainPtr.h"
48 #include "JSValueRef.h"
49 #include "ObjectPrototype.h"
50 #include "PropertyNameArray.h"
51 #include "RegExpConstructor.h"
55 JSClassRef JSClassCreate(const JSClassDefinition* definition)
57 initializeThreading();
58 RefPtr<OpaqueJSClass> jsClass = (definition->attributes & kJSClassAttributeNoAutomaticPrototype)
59 ? OpaqueJSClass::createNoAutomaticPrototype(definition)
60 : OpaqueJSClass::create(definition);
62 return jsClass.release().leakRef();
65 JSClassRef JSClassRetain(JSClassRef jsClass)
71 void JSClassRelease(JSClassRef jsClass)
76 JSObjectRef JSObjectMake(JSContextRef ctx, JSClassRef jsClass, void* data)
78 ExecState* exec = toJS(ctx);
79 APIEntryShim entryShim(exec);
82 return toRef(constructEmptyObject(exec));
84 JSCallbackObject<JSNonFinalObject>* object = JSCallbackObject<JSNonFinalObject>::create(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->callbackObjectStructure(), jsClass, data);
85 if (JSObject* prototype = jsClass->prototype(exec))
86 object->setPrototype(exec->globalData(), prototype);
91 JSObjectRef JSObjectMakeFunctionWithCallback(JSContextRef ctx, JSStringRef name, JSObjectCallAsFunctionCallback callAsFunction)
93 ExecState* exec = toJS(ctx);
94 APIEntryShim entryShim(exec);
96 Identifier nameID = name ? name->identifier(&exec->globalData()) : Identifier(exec, "anonymous");
98 return toRef(JSCallbackFunction::create(exec, exec->lexicalGlobalObject(), callAsFunction, nameID));
101 JSObjectRef JSObjectMakeConstructor(JSContextRef ctx, JSClassRef jsClass, JSObjectCallAsConstructorCallback callAsConstructor)
103 ExecState* exec = toJS(ctx);
104 APIEntryShim entryShim(exec);
106 JSValue jsPrototype = jsClass ? jsClass->prototype(exec) : 0;
108 jsPrototype = exec->lexicalGlobalObject()->objectPrototype();
110 JSCallbackConstructor* constructor = JSCallbackConstructor::create(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->callbackConstructorStructure(), jsClass, callAsConstructor);
111 constructor->putDirect(exec->globalData(), exec->propertyNames().prototype, jsPrototype, DontEnum | DontDelete | ReadOnly);
112 return toRef(constructor);
115 JSObjectRef JSObjectMakeFunction(JSContextRef ctx, JSStringRef name, unsigned parameterCount, const JSStringRef parameterNames[], JSStringRef body, JSStringRef sourceURL, int startingLineNumber, JSValueRef* exception)
117 ExecState* exec = toJS(ctx);
118 APIEntryShim entryShim(exec);
120 Identifier nameID = name ? name->identifier(&exec->globalData()) : Identifier(exec, "anonymous");
122 MarkedArgumentBuffer args;
123 for (unsigned i = 0; i < parameterCount; i++)
124 args.append(jsString(exec, parameterNames[i]->ustring()));
125 args.append(jsString(exec, body->ustring()));
127 JSObject* result = constructFunction(exec, exec->lexicalGlobalObject(), args, nameID, sourceURL->ustring(), TextPosition(OrdinalNumber::fromOneBasedInt(startingLineNumber), OrdinalNumber::first()));
128 if (exec->hadException()) {
130 *exception = toRef(exec, exec->exception());
131 exec->clearException();
134 return toRef(result);
137 JSObjectRef JSObjectMakeArray(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
139 ExecState* exec = toJS(ctx);
140 APIEntryShim entryShim(exec);
144 MarkedArgumentBuffer argList;
145 for (size_t i = 0; i < argumentCount; ++i)
146 argList.append(toJS(exec, arguments[i]));
148 result = constructArray(exec, argList);
150 result = constructEmptyArray(exec);
152 if (exec->hadException()) {
154 *exception = toRef(exec, exec->exception());
155 exec->clearException();
159 return toRef(result);
162 JSObjectRef JSObjectMakeDate(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
164 ExecState* exec = toJS(ctx);
165 APIEntryShim entryShim(exec);
167 MarkedArgumentBuffer argList;
168 for (size_t i = 0; i < argumentCount; ++i)
169 argList.append(toJS(exec, arguments[i]));
171 JSObject* result = constructDate(exec, exec->lexicalGlobalObject(), argList);
172 if (exec->hadException()) {
174 *exception = toRef(exec, exec->exception());
175 exec->clearException();
179 return toRef(result);
182 JSObjectRef JSObjectMakeError(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
184 ExecState* exec = toJS(ctx);
185 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);
191 if (exec->hadException()) {
193 *exception = toRef(exec, exec->exception());
194 exec->clearException();
198 return toRef(result);
201 JSObjectRef JSObjectMakeRegExp(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
203 ExecState* exec = toJS(ctx);
204 APIEntryShim entryShim(exec);
206 MarkedArgumentBuffer argList;
207 for (size_t i = 0; i < argumentCount; ++i)
208 argList.append(toJS(exec, arguments[i]));
210 JSObject* result = constructRegExp(exec, exec->lexicalGlobalObject(), argList);
211 if (exec->hadException()) {
213 *exception = toRef(exec, exec->exception());
214 exec->clearException();
218 return toRef(result);
221 JSValueRef JSObjectGetPrototype(JSContextRef ctx, JSObjectRef object)
223 ExecState* exec = toJS(ctx);
224 APIEntryShim entryShim(exec);
226 JSObject* jsObject = toJS(object);
227 return toRef(exec, jsObject->prototype());
230 void JSObjectSetPrototype(JSContextRef ctx, JSObjectRef object, JSValueRef value)
232 ExecState* exec = toJS(ctx);
233 APIEntryShim entryShim(exec);
235 JSObject* jsObject = toJS(object);
236 JSValue jsValue = toJS(exec, value);
238 jsObject->setPrototypeWithCycleCheck(exec->globalData(), jsValue.isObject() ? jsValue : jsNull());
241 bool JSObjectHasProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName)
243 ExecState* exec = toJS(ctx);
244 APIEntryShim entryShim(exec);
246 JSObject* jsObject = toJS(object);
248 return jsObject->hasProperty(exec, propertyName->identifier(&exec->globalData()));
251 JSValueRef JSObjectGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
253 ExecState* exec = toJS(ctx);
254 APIEntryShim entryShim(exec);
256 JSObject* jsObject = toJS(object);
258 JSValue jsValue = jsObject->get(exec, propertyName->identifier(&exec->globalData()));
259 if (exec->hadException()) {
261 *exception = toRef(exec, exec->exception());
262 exec->clearException();
264 return toRef(exec, jsValue);
267 void JSObjectSetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSPropertyAttributes attributes, JSValueRef* exception)
269 ExecState* exec = toJS(ctx);
270 APIEntryShim entryShim(exec);
272 JSObject* jsObject = toJS(object);
273 Identifier name(propertyName->identifier(&exec->globalData()));
274 JSValue jsValue = toJS(exec, value);
276 if (attributes && !jsObject->hasProperty(exec, name))
277 jsObject->methodTable()->putWithAttributes(jsObject, exec, name, jsValue, attributes);
279 PutPropertySlot slot;
280 jsObject->methodTable()->put(jsObject, exec, name, jsValue, slot);
283 if (exec->hadException()) {
285 *exception = toRef(exec, exec->exception());
286 exec->clearException();
290 JSValueRef JSObjectGetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned propertyIndex, JSValueRef* exception)
292 ExecState* exec = toJS(ctx);
293 APIEntryShim entryShim(exec);
295 JSObject* jsObject = toJS(object);
297 JSValue jsValue = jsObject->get(exec, propertyIndex);
298 if (exec->hadException()) {
300 *exception = toRef(exec, exec->exception());
301 exec->clearException();
303 return toRef(exec, jsValue);
307 void JSObjectSetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned propertyIndex, JSValueRef value, JSValueRef* exception)
309 ExecState* exec = toJS(ctx);
310 APIEntryShim entryShim(exec);
312 JSObject* jsObject = toJS(object);
313 JSValue jsValue = toJS(exec, value);
315 jsObject->methodTable()->putByIndex(jsObject, exec, propertyIndex, jsValue);
316 if (exec->hadException()) {
318 *exception = toRef(exec, exec->exception());
319 exec->clearException();
323 bool JSObjectDeleteProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
325 ExecState* exec = toJS(ctx);
326 APIEntryShim entryShim(exec);
328 JSObject* jsObject = toJS(object);
330 bool result = jsObject->methodTable()->deleteProperty(jsObject, exec, propertyName->identifier(&exec->globalData()));
331 if (exec->hadException()) {
333 *exception = toRef(exec, exec->exception());
334 exec->clearException();
339 void* JSObjectGetPrivate(JSObjectRef object)
341 JSObject* jsObject = toJS(object);
343 if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::s_info))
344 return static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->getPrivate();
345 if (jsObject->inherits(&JSCallbackObject<JSNonFinalObject>::s_info))
346 return static_cast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->getPrivate();
351 bool JSObjectSetPrivate(JSObjectRef object, void* data)
353 JSObject* jsObject = toJS(object);
355 if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::s_info)) {
356 static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->setPrivate(data);
359 if (jsObject->inherits(&JSCallbackObject<JSNonFinalObject>::s_info)) {
360 static_cast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->setPrivate(data);
367 JSValueRef JSObjectGetPrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName)
369 ExecState* exec = toJS(ctx);
370 APIEntryShim entryShim(exec);
371 JSObject* jsObject = toJS(object);
373 Identifier name(propertyName->identifier(&exec->globalData()));
374 if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::s_info))
375 result = static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->getPrivateProperty(name);
376 else if (jsObject->inherits(&JSCallbackObject<JSNonFinalObject>::s_info))
377 result = static_cast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->getPrivateProperty(name);
378 return toRef(exec, result);
381 bool JSObjectSetPrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value)
383 ExecState* exec = toJS(ctx);
384 APIEntryShim entryShim(exec);
385 JSObject* jsObject = toJS(object);
386 JSValue jsValue = value ? toJS(exec, value) : JSValue();
387 Identifier name(propertyName->identifier(&exec->globalData()));
388 if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::s_info)) {
389 static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->setPrivateProperty(exec->globalData(), name, jsValue);
392 if (jsObject->inherits(&JSCallbackObject<JSNonFinalObject>::s_info)) {
393 static_cast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->setPrivateProperty(exec->globalData(), name, jsValue);
399 bool JSObjectDeletePrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName)
401 ExecState* exec = toJS(ctx);
402 APIEntryShim entryShim(exec);
403 JSObject* jsObject = toJS(object);
404 Identifier name(propertyName->identifier(&exec->globalData()));
405 if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::s_info)) {
406 static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->deletePrivateProperty(name);
409 if (jsObject->inherits(&JSCallbackObject<JSNonFinalObject>::s_info)) {
410 static_cast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->deletePrivateProperty(name);
416 bool JSObjectIsFunction(JSContextRef, JSObjectRef object)
419 JSCell* cell = toJS(object);
420 return cell->methodTable()->getCallData(cell, callData) != CallTypeNone;
423 JSValueRef JSObjectCallAsFunction(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
425 ExecState* exec = toJS(ctx);
426 APIEntryShim entryShim(exec);
428 JSObject* jsObject = toJS(object);
429 JSObject* jsThisObject = toJS(thisObject);
432 jsThisObject = exec->globalThisValue();
434 MarkedArgumentBuffer argList;
435 for (size_t i = 0; i < argumentCount; i++)
436 argList.append(toJS(exec, arguments[i]));
439 CallType callType = jsObject->methodTable()->getCallData(jsObject, callData);
440 if (callType == CallTypeNone)
443 JSValueRef result = toRef(exec, call(exec, jsObject, callType, callData, jsThisObject, argList));
444 if (exec->hadException()) {
446 *exception = toRef(exec, exec->exception());
447 exec->clearException();
453 bool JSObjectIsConstructor(JSContextRef, JSObjectRef object)
455 JSObject* jsObject = toJS(object);
456 ConstructData constructData;
457 return jsObject->methodTable()->getConstructData(jsObject, constructData) != ConstructTypeNone;
460 JSObjectRef JSObjectCallAsConstructor(JSContextRef ctx, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
462 ExecState* exec = toJS(ctx);
463 APIEntryShim entryShim(exec);
465 JSObject* jsObject = toJS(object);
467 ConstructData constructData;
468 ConstructType constructType = jsObject->methodTable()->getConstructData(jsObject, constructData);
469 if (constructType == ConstructTypeNone)
472 MarkedArgumentBuffer argList;
473 for (size_t i = 0; i < argumentCount; i++)
474 argList.append(toJS(exec, arguments[i]));
475 JSObjectRef result = toRef(construct(exec, jsObject, constructType, constructData, argList));
476 if (exec->hadException()) {
478 *exception = toRef(exec, exec->exception());
479 exec->clearException();
485 struct OpaqueJSPropertyNameArray {
486 WTF_MAKE_FAST_ALLOCATED;
488 OpaqueJSPropertyNameArray(JSGlobalData* globalData)
490 , globalData(globalData)
495 JSGlobalData* globalData;
496 Vector<JSRetainPtr<JSStringRef> > array;
499 JSPropertyNameArrayRef JSObjectCopyPropertyNames(JSContextRef ctx, JSObjectRef object)
501 JSObject* jsObject = toJS(object);
502 ExecState* exec = toJS(ctx);
503 APIEntryShim entryShim(exec);
505 JSGlobalData* globalData = &exec->globalData();
507 JSPropertyNameArrayRef propertyNames = new OpaqueJSPropertyNameArray(globalData);
508 PropertyNameArray array(globalData);
509 jsObject->methodTable()->getPropertyNames(jsObject, exec, array, ExcludeDontEnumProperties);
511 size_t size = array.size();
512 propertyNames->array.reserveInitialCapacity(size);
513 for (size_t i = 0; i < size; ++i)
514 propertyNames->array.append(JSRetainPtr<JSStringRef>(Adopt, OpaqueJSString::create(array[i].ustring()).leakRef()));
516 return JSPropertyNameArrayRetain(propertyNames);
519 JSPropertyNameArrayRef JSPropertyNameArrayRetain(JSPropertyNameArrayRef array)
525 void JSPropertyNameArrayRelease(JSPropertyNameArrayRef array)
527 if (--array->refCount == 0) {
528 APIEntryShim entryShim(array->globalData, false);
533 size_t JSPropertyNameArrayGetCount(JSPropertyNameArrayRef array)
535 return array->array.size();
538 JSStringRef JSPropertyNameArrayGetNameAtIndex(JSPropertyNameArrayRef array, size_t index)
540 return array->array[static_cast<unsigned>(index)].get();
543 void JSPropertyNameAccumulatorAddName(JSPropertyNameAccumulatorRef array, JSStringRef propertyName)
545 PropertyNameArray* propertyNames = toJS(array);
546 APIEntryShim entryShim(propertyNames->globalData());
547 propertyNames->add(propertyName->identifier(propertyNames->globalData()));
551 * TIZEN - JavaScript extension APIs for WRT
555 //This API will create and return an array object, with vector elements as its initial elements
556 JSObjectRef JSCreateArrayObject(JSContextRef context, int length, const JSValueRef vector[])
558 #if ENABLE(TIZEN_JS_EXT_API)
559 MarkedArgumentBuffer argBuffer;
560 ExecState* ex = toJS(context);
562 for (int i = 0; i < length; i++)
564 argBuffer.append(toJS(ex, vector[i]));
567 /* The way to create a new array object. And add some value to it */
568 JSArray* arrayObj = constructArray(ex, argBuffer);
569 return toRef(arrayObj);
575 /* TIZEN Comment - This API will be used to add an array element at a particular index */
576 bool JSSetArrayElement(JSContextRef context, JSObjectRef object, int index, JSValueRef vp)
578 #if ENABLE(TIZEN_JS_EXT_API)
579 ExecState* ex = toJS(context);
580 JSObject* obj = toJS(object);
581 PutPropertySlot slot;
582 Identifier propertyName;
584 obj->methodTable()->putByIndex(obj, ex, index, toJS(ex, vp));
592 /* TIZEN Comment - This api will be used to get array element at a particular index */
593 JSValueRef JSGetArrayElement(JSContextRef context, JSObjectRef object, int index)
595 #if ENABLE(TIZEN_JS_EXT_API)
596 ExecState* ex = toJS(context);
597 JSArray* arrayObj = (JSArray*)toJS(object);
599 JSValue val = arrayObj->getIndex(index);
602 return toRef(ex, val);
604 return JSValueMakeUndefined(context);
610 /* TIZEN Comment - This api is used to determine whether a particular object is an array object or not */
611 bool JSIsArrayValue(JSContextRef context, JSValueRef valueRef)
613 #if ENABLE(TIZEN_JS_EXT_API)
614 ExecState* ex = toJS(context);
615 JSValue value = toJS(ex, valueRef);
616 return value.inherits(&(JSArray::s_info));
622 /* TIZEN Comment - This apis is used to get the size of the array */
623 unsigned int JSGetArrayLength(JSContextRef context, JSObjectRef object)
625 #if ENABLE(TIZEN_JS_EXT_API)
626 JSArray* arrayObj = (JSArray*)toJS(object);
627 return arrayObj->length();
633 /* TIZEN Comment - Following api is provided for throwing exception in WRT */
634 void JSThrowException(JSContextRef context, int type, char *msg)
636 #if ENABLE(TIZEN_JS_EXT_API)
637 ExecState* ex = toJS(context);
638 throwError(ex, createError(ex, msg));
644 /* TIZEN Comment - This api will be used to add an array element at a particular index referred to by string*/
645 bool JSSetArrayElementInArrayList(JSContextRef context, JSObjectRef object, const char* strIndex, JSValueRef vp)
647 #if ENABLE(TIZEN_JS_EXT_API)
648 if (NULL != strIndex && strcmp(strIndex, "length") == 0)
651 ExecState* ex = toJS(context);
652 JSObject* obj = toJS(object);
653 Identifier ident(ex, strIndex);
654 PutPropertySlot slot;
656 //typedef void (*PutFunctionPtr)(JSCell*, ExecState*, const Identifier& propertyName, JSValue, PutPropertySlot&);
657 obj->methodTable()->put(obj, ex, ident, toJS(ex, vp), slot);
665 /* TIZEN Comment - This api will be used to get array element at a particular index referred to by string*/
666 JSValueRef JSGetArrayElementInArrayList(JSContextRef context, JSObjectRef object, const char* strIndex)
668 #if ENABLE(TIZEN_JS_EXT_API)
669 ExecState* ex = toJS(context);
670 JSObject* obj = toJS(object);
671 Identifier ident(ex, strIndex);
673 return toRef(ex, obj->get(ex, ident));