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"
31 #include "DateConstructor.h"
32 #include "ErrorConstructor.h"
33 #include "FunctionConstructor.h"
34 #include "Identifier.h"
35 #include "InitializeThreading.h"
37 #include "JSCallbackConstructor.h"
38 #include "JSCallbackFunction.h"
39 #include "JSCallbackObject.h"
40 #include "JSClassRef.h"
41 #include "JSFunction.h"
42 #include "JSGlobalObject.h"
44 #include "JSRetainPtr.h"
46 #include "JSValueRef.h"
47 #include "ObjectPrototype.h"
48 #include "PropertyNameArray.h"
49 #include "RegExpConstructor.h"
50 #include <wtf/Platform.h>
54 JSClassRef
JSClassCreate(const JSClassDefinition
* definition
)
56 initializeThreading();
57 RefPtr
<OpaqueJSClass
> jsClass
= (definition
->attributes
& kJSClassAttributeNoAutomaticPrototype
)
58 ? OpaqueJSClass::createNoAutomaticPrototype(definition
)
59 : OpaqueJSClass::create(definition
);
61 return jsClass
.release().releaseRef();
64 JSClassRef
JSClassRetain(JSClassRef jsClass
)
70 void JSClassRelease(JSClassRef jsClass
)
75 JSObjectRef
JSObjectMake(JSContextRef ctx
, JSClassRef jsClass
, void* data
)
77 ExecState
* exec
= toJS(ctx
);
78 exec
->globalData().heap
.registerThread();
82 return toRef(new (exec
) JSObject(exec
->lexicalGlobalObject()->emptyObjectStructure())); // slightly more efficient
84 JSCallbackObject
<JSObject
>* object
= new (exec
) JSCallbackObject
<JSObject
>(exec
, exec
->lexicalGlobalObject()->callbackObjectStructure(), jsClass
, data
);
85 if (JSObject
* prototype
= jsClass
->prototype(exec
))
86 object
->setPrototype(prototype
);
91 JSObjectRef
JSObjectMakeFunctionWithCallback(JSContextRef ctx
, JSStringRef name
, JSObjectCallAsFunctionCallback callAsFunction
)
93 ExecState
* exec
= toJS(ctx
);
94 exec
->globalData().heap
.registerThread();
97 Identifier nameID
= name
? name
->identifier(&exec
->globalData()) : Identifier(exec
, "anonymous");
99 return toRef(new (exec
) JSCallbackFunction(exec
, callAsFunction
, nameID
));
102 JSObjectRef
JSObjectMakeConstructor(JSContextRef ctx
, JSClassRef jsClass
, JSObjectCallAsConstructorCallback callAsConstructor
)
104 ExecState
* exec
= toJS(ctx
);
105 exec
->globalData().heap
.registerThread();
108 JSValuePtr jsPrototype
= jsClass
109 ? jsClass
->prototype(exec
)
110 : exec
->lexicalGlobalObject()->objectPrototype();
112 JSCallbackConstructor
* constructor
= new (exec
) JSCallbackConstructor(exec
->lexicalGlobalObject()->callbackConstructorStructure(), jsClass
, callAsConstructor
);
113 constructor
->putDirect(exec
->propertyNames().prototype
, jsPrototype
, DontEnum
| DontDelete
| ReadOnly
);
114 return toRef(constructor
);
117 JSObjectRef
JSObjectMakeFunction(JSContextRef ctx
, JSStringRef name
, unsigned parameterCount
, const JSStringRef parameterNames
[], JSStringRef body
, JSStringRef sourceURL
, int startingLineNumber
, JSValueRef
* exception
)
119 ExecState
* exec
= toJS(ctx
);
120 exec
->globalData().heap
.registerThread();
123 Identifier nameID
= name
? name
->identifier(&exec
->globalData()) : Identifier(exec
, "anonymous");
126 for (unsigned i
= 0; i
< parameterCount
; i
++)
127 args
.append(jsString(exec
, parameterNames
[i
]->ustring()));
128 args
.append(jsString(exec
, body
->ustring()));
130 JSObject
* result
= constructFunction(exec
, args
, nameID
, sourceURL
->ustring(), startingLineNumber
);
131 if (exec
->hadException()) {
133 *exception
= toRef(exec
->exception());
134 exec
->clearException();
137 return toRef(result
);
140 JSObjectRef
JSObjectMakeArray(JSContextRef ctx
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
142 ExecState
* exec
= toJS(ctx
);
143 exec
->globalData().heap
.registerThread();
149 for (size_t i
= 0; i
< argumentCount
; ++i
)
150 argList
.append(toJS(arguments
[i
]));
152 result
= constructArray(exec
, argList
);
154 result
= constructEmptyArray(exec
);
156 if (exec
->hadException()) {
158 *exception
= toRef(exec
->exception());
159 exec
->clearException();
163 return toRef(result
);
166 JSObjectRef
JSObjectMakeDate(JSContextRef ctx
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
168 ExecState
* exec
= toJS(ctx
);
169 exec
->globalData().heap
.registerThread();
173 for (size_t i
= 0; i
< argumentCount
; ++i
)
174 argList
.append(toJS(arguments
[i
]));
176 JSObject
* result
= constructDate(exec
, argList
);
177 if (exec
->hadException()) {
179 *exception
= toRef(exec
->exception());
180 exec
->clearException();
184 return toRef(result
);
187 JSObjectRef
JSObjectMakeError(JSContextRef ctx
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
189 ExecState
* exec
= toJS(ctx
);
190 exec
->globalData().heap
.registerThread();
194 for (size_t i
= 0; i
< argumentCount
; ++i
)
195 argList
.append(toJS(arguments
[i
]));
197 JSObject
* result
= constructError(exec
, argList
);
198 if (exec
->hadException()) {
200 *exception
= toRef(exec
->exception());
201 exec
->clearException();
205 return toRef(result
);
208 JSObjectRef
JSObjectMakeRegExp(JSContextRef ctx
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
210 ExecState
* exec
= toJS(ctx
);
211 exec
->globalData().heap
.registerThread();
215 for (size_t i
= 0; i
< argumentCount
; ++i
)
216 argList
.append(toJS(arguments
[i
]));
218 JSObject
* result
= constructRegExp(exec
, argList
);
219 if (exec
->hadException()) {
221 *exception
= toRef(exec
->exception());
222 exec
->clearException();
226 return toRef(result
);
229 JSValueRef
JSObjectGetPrototype(JSContextRef
, JSObjectRef object
)
231 JSObject
* jsObject
= toJS(object
);
232 return toRef(jsObject
->prototype());
235 void JSObjectSetPrototype(JSContextRef
, JSObjectRef object
, JSValueRef value
)
237 JSObject
* jsObject
= toJS(object
);
238 JSValuePtr jsValue
= toJS(value
);
240 jsObject
->setPrototype(jsValue
.isObject() ? jsValue
: jsNull());
243 bool JSObjectHasProperty(JSContextRef ctx
, JSObjectRef object
, JSStringRef propertyName
)
245 ExecState
* exec
= toJS(ctx
);
246 exec
->globalData().heap
.registerThread();
249 JSObject
* jsObject
= toJS(object
);
251 return jsObject
->hasProperty(exec
, propertyName
->identifier(&exec
->globalData()));
254 JSValueRef
JSObjectGetProperty(JSContextRef ctx
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef
* exception
)
256 ExecState
* exec
= toJS(ctx
);
257 exec
->globalData().heap
.registerThread();
260 JSObject
* jsObject
= toJS(object
);
262 JSValuePtr jsValue
= jsObject
->get(exec
, propertyName
->identifier(&exec
->globalData()));
263 if (exec
->hadException()) {
265 *exception
= toRef(exec
->exception());
266 exec
->clearException();
268 return toRef(jsValue
);
271 void JSObjectSetProperty(JSContextRef ctx
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef value
, JSPropertyAttributes attributes
, JSValueRef
* exception
)
273 ExecState
* exec
= toJS(ctx
);
274 exec
->globalData().heap
.registerThread();
277 JSObject
* jsObject
= toJS(object
);
278 Identifier
name(propertyName
->identifier(&exec
->globalData()));
279 JSValuePtr jsValue
= toJS(value
);
281 if (attributes
&& !jsObject
->hasProperty(exec
, name
))
282 jsObject
->putWithAttributes(exec
, name
, jsValue
, attributes
);
284 PutPropertySlot slot
;
285 jsObject
->put(exec
, name
, jsValue
, slot
);
288 if (exec
->hadException()) {
290 *exception
= toRef(exec
->exception());
291 exec
->clearException();
295 JSValueRef
JSObjectGetPropertyAtIndex(JSContextRef ctx
, JSObjectRef object
, unsigned propertyIndex
, JSValueRef
* exception
)
297 ExecState
* exec
= toJS(ctx
);
298 exec
->globalData().heap
.registerThread();
301 JSObject
* jsObject
= toJS(object
);
303 JSValuePtr jsValue
= jsObject
->get(exec
, propertyIndex
);
304 if (exec
->hadException()) {
306 *exception
= toRef(exec
->exception());
307 exec
->clearException();
309 return toRef(jsValue
);
313 void JSObjectSetPropertyAtIndex(JSContextRef ctx
, JSObjectRef object
, unsigned propertyIndex
, JSValueRef value
, JSValueRef
* exception
)
315 ExecState
* exec
= toJS(ctx
);
316 exec
->globalData().heap
.registerThread();
319 JSObject
* jsObject
= toJS(object
);
320 JSValuePtr jsValue
= toJS(value
);
322 jsObject
->put(exec
, propertyIndex
, jsValue
);
323 if (exec
->hadException()) {
325 *exception
= toRef(exec
->exception());
326 exec
->clearException();
330 bool JSObjectDeleteProperty(JSContextRef ctx
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef
* exception
)
332 ExecState
* exec
= toJS(ctx
);
333 exec
->globalData().heap
.registerThread();
336 JSObject
* jsObject
= toJS(object
);
338 bool result
= jsObject
->deleteProperty(exec
, propertyName
->identifier(&exec
->globalData()));
339 if (exec
->hadException()) {
341 *exception
= toRef(exec
->exception());
342 exec
->clearException();
347 void* JSObjectGetPrivate(JSObjectRef object
)
349 JSObject
* jsObject
= toJS(object
);
351 if (jsObject
->inherits(&JSCallbackObject
<JSGlobalObject
>::info
))
352 return static_cast<JSCallbackObject
<JSGlobalObject
>*>(jsObject
)->getPrivate();
353 else if (jsObject
->inherits(&JSCallbackObject
<JSObject
>::info
))
354 return static_cast<JSCallbackObject
<JSObject
>*>(jsObject
)->getPrivate();
359 bool JSObjectSetPrivate(JSObjectRef object
, void* data
)
361 JSObject
* jsObject
= toJS(object
);
363 if (jsObject
->inherits(&JSCallbackObject
<JSGlobalObject
>::info
)) {
364 static_cast<JSCallbackObject
<JSGlobalObject
>*>(jsObject
)->setPrivate(data
);
366 } else if (jsObject
->inherits(&JSCallbackObject
<JSObject
>::info
)) {
367 static_cast<JSCallbackObject
<JSObject
>*>(jsObject
)->setPrivate(data
);
374 bool JSObjectIsFunction(JSContextRef
, JSObjectRef object
)
377 return toJS(object
)->getCallData(callData
) != CallTypeNone
;
380 JSValueRef
JSObjectCallAsFunction(JSContextRef ctx
, JSObjectRef object
, JSObjectRef thisObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
382 ExecState
* exec
= toJS(ctx
);
383 exec
->globalData().heap
.registerThread();
386 JSObject
* jsObject
= toJS(object
);
387 JSObject
* jsThisObject
= toJS(thisObject
);
390 jsThisObject
= exec
->globalThisValue();
393 for (size_t i
= 0; i
< argumentCount
; i
++)
394 argList
.append(toJS(arguments
[i
]));
397 CallType callType
= jsObject
->getCallData(callData
);
398 if (callType
== CallTypeNone
)
401 JSValueRef result
= toRef(call(exec
, jsObject
, callType
, callData
, jsThisObject
, argList
));
402 if (exec
->hadException()) {
404 *exception
= toRef(exec
->exception());
405 exec
->clearException();
411 bool JSObjectIsConstructor(JSContextRef
, JSObjectRef object
)
413 JSObject
* jsObject
= toJS(object
);
414 ConstructData constructData
;
415 return jsObject
->getConstructData(constructData
) != ConstructTypeNone
;
418 JSObjectRef
JSObjectCallAsConstructor(JSContextRef ctx
, JSObjectRef object
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
420 ExecState
* exec
= toJS(ctx
);
421 exec
->globalData().heap
.registerThread();
424 JSObject
* jsObject
= toJS(object
);
426 ConstructData constructData
;
427 ConstructType constructType
= jsObject
->getConstructData(constructData
);
428 if (constructType
== ConstructTypeNone
)
432 for (size_t i
= 0; i
< argumentCount
; i
++)
433 argList
.append(toJS(arguments
[i
]));
434 JSObjectRef result
= toRef(construct(exec
, jsObject
, constructType
, constructData
, argList
));
435 if (exec
->hadException()) {
437 *exception
= toRef(exec
->exception());
438 exec
->clearException();
444 struct OpaqueJSPropertyNameArray
{
445 OpaqueJSPropertyNameArray(JSGlobalData
* globalData
)
447 , globalData(globalData
)
452 JSGlobalData
* globalData
;
453 Vector
<JSRetainPtr
<JSStringRef
> > array
;
456 JSPropertyNameArrayRef
JSObjectCopyPropertyNames(JSContextRef ctx
, JSObjectRef object
)
458 JSObject
* jsObject
= toJS(object
);
459 ExecState
* exec
= toJS(ctx
);
460 exec
->globalData().heap
.registerThread();
463 JSGlobalData
* globalData
= &exec
->globalData();
465 JSPropertyNameArrayRef propertyNames
= new OpaqueJSPropertyNameArray(globalData
);
466 PropertyNameArray
array(globalData
);
467 jsObject
->getPropertyNames(exec
, array
);
469 size_t size
= array
.size();
470 propertyNames
->array
.reserveInitialCapacity(size
);
471 for (size_t i
= 0; i
< size
; ++i
)
472 propertyNames
->array
.append(JSRetainPtr
<JSStringRef
>(Adopt
, OpaqueJSString::create(array
[i
].ustring()).releaseRef()));
474 return JSPropertyNameArrayRetain(propertyNames
);
477 JSPropertyNameArrayRef
JSPropertyNameArrayRetain(JSPropertyNameArrayRef array
)
483 void JSPropertyNameArrayRelease(JSPropertyNameArrayRef array
)
485 if (--array
->refCount
== 0) {
486 JSLock
lock(array
->globalData
->isSharedInstance
);
491 size_t JSPropertyNameArrayGetCount(JSPropertyNameArrayRef array
)
493 return array
->array
.size();
496 JSStringRef
JSPropertyNameArrayGetNameAtIndex(JSPropertyNameArrayRef array
, size_t index
)
498 return array
->array
[static_cast<unsigned>(index
)].get();
501 void JSPropertyNameAccumulatorAddName(JSPropertyNameAccumulatorRef array
, JSStringRef propertyName
)
503 PropertyNameArray
* propertyNames
= toJS(array
);
505 propertyNames
->globalData()->heap
.registerThread();
506 JSLock
lock(propertyNames
->globalData()->isSharedInstance
);
508 propertyNames
->add(propertyName
->identifier(propertyNames
->globalData()));