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 "CodeBlock.h"
32 #include "DateConstructor.h"
33 #include "ErrorConstructor.h"
34 #include "FunctionConstructor.h"
35 #include "Identifier.h"
36 #include "InitializeThreading.h"
38 #include "JSCallbackConstructor.h"
39 #include "JSCallbackFunction.h"
40 #include "JSCallbackObject.h"
41 #include "JSClassRef.h"
42 #include "JSFunction.h"
43 #include "JSGlobalObject.h"
45 #include "JSRetainPtr.h"
47 #include "JSValueRef.h"
48 #include "ObjectPrototype.h"
49 #include "PropertyNameArray.h"
50 #include "RegExpConstructor.h"
51 #include <wtf/Platform.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().releaseRef();
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(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 APIEntryShim
entryShim(exec
);
96 Identifier nameID
= name
? name
->identifier(&exec
->globalData()) : Identifier(exec
, "anonymous");
98 return toRef(new (exec
) JSCallbackFunction(exec
, 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
= new (exec
) JSCallbackConstructor(exec
->lexicalGlobalObject()->callbackConstructorStructure(), jsClass
, callAsConstructor
);
111 constructor
->putDirect(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
, args
, nameID
, sourceURL
->ustring(), startingLineNumber
);
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
, 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 MarkedArgumentBuffer argList
;
188 for (size_t i
= 0; i
< argumentCount
; ++i
)
189 argList
.append(toJS(exec
, arguments
[i
]));
191 JSObject
* result
= constructError(exec
, argList
);
192 if (exec
->hadException()) {
194 *exception
= toRef(exec
, exec
->exception());
195 exec
->clearException();
199 return toRef(result
);
202 JSObjectRef
JSObjectMakeRegExp(JSContextRef ctx
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
204 ExecState
* exec
= toJS(ctx
);
205 APIEntryShim
entryShim(exec
);
207 MarkedArgumentBuffer argList
;
208 for (size_t i
= 0; i
< argumentCount
; ++i
)
209 argList
.append(toJS(exec
, arguments
[i
]));
211 JSObject
* result
= constructRegExp(exec
, argList
);
212 if (exec
->hadException()) {
214 *exception
= toRef(exec
, exec
->exception());
215 exec
->clearException();
219 return toRef(result
);
222 JSValueRef
JSObjectGetPrototype(JSContextRef ctx
, JSObjectRef object
)
224 ExecState
* exec
= toJS(ctx
);
225 APIEntryShim
entryShim(exec
);
227 JSObject
* jsObject
= toJS(object
);
228 return toRef(exec
, jsObject
->prototype());
231 void JSObjectSetPrototype(JSContextRef ctx
, JSObjectRef object
, JSValueRef value
)
233 ExecState
* exec
= toJS(ctx
);
234 APIEntryShim
entryShim(exec
);
236 JSObject
* jsObject
= toJS(object
);
237 JSValue jsValue
= toJS(exec
, value
);
239 jsObject
->setPrototype(jsValue
.isObject() ? jsValue
: jsNull());
242 bool JSObjectHasProperty(JSContextRef ctx
, JSObjectRef object
, JSStringRef propertyName
)
244 ExecState
* exec
= toJS(ctx
);
245 APIEntryShim
entryShim(exec
);
247 JSObject
* jsObject
= toJS(object
);
249 return jsObject
->hasProperty(exec
, propertyName
->identifier(&exec
->globalData()));
252 JSValueRef
JSObjectGetProperty(JSContextRef ctx
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef
* exception
)
254 ExecState
* exec
= toJS(ctx
);
255 APIEntryShim
entryShim(exec
);
257 JSObject
* jsObject
= toJS(object
);
259 JSValue jsValue
= jsObject
->get(exec
, propertyName
->identifier(&exec
->globalData()));
260 if (exec
->hadException()) {
262 *exception
= toRef(exec
, exec
->exception());
263 exec
->clearException();
265 return toRef(exec
, jsValue
);
268 void JSObjectSetProperty(JSContextRef ctx
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef value
, JSPropertyAttributes attributes
, JSValueRef
* exception
)
270 ExecState
* exec
= toJS(ctx
);
271 APIEntryShim
entryShim(exec
);
273 JSObject
* jsObject
= toJS(object
);
274 Identifier
name(propertyName
->identifier(&exec
->globalData()));
275 JSValue jsValue
= toJS(exec
, value
);
277 if (attributes
&& !jsObject
->hasProperty(exec
, name
))
278 jsObject
->putWithAttributes(exec
, name
, jsValue
, attributes
);
280 PutPropertySlot slot
;
281 jsObject
->put(exec
, name
, jsValue
, slot
);
284 if (exec
->hadException()) {
286 *exception
= toRef(exec
, exec
->exception());
287 exec
->clearException();
291 JSValueRef
JSObjectGetPropertyAtIndex(JSContextRef ctx
, JSObjectRef object
, unsigned propertyIndex
, JSValueRef
* exception
)
293 ExecState
* exec
= toJS(ctx
);
294 APIEntryShim
entryShim(exec
);
296 JSObject
* jsObject
= toJS(object
);
298 JSValue jsValue
= jsObject
->get(exec
, propertyIndex
);
299 if (exec
->hadException()) {
301 *exception
= toRef(exec
, exec
->exception());
302 exec
->clearException();
304 return toRef(exec
, jsValue
);
308 void JSObjectSetPropertyAtIndex(JSContextRef ctx
, JSObjectRef object
, unsigned propertyIndex
, JSValueRef value
, JSValueRef
* exception
)
310 ExecState
* exec
= toJS(ctx
);
311 APIEntryShim
entryShim(exec
);
313 JSObject
* jsObject
= toJS(object
);
314 JSValue jsValue
= toJS(exec
, value
);
316 jsObject
->put(exec
, propertyIndex
, jsValue
);
317 if (exec
->hadException()) {
319 *exception
= toRef(exec
, exec
->exception());
320 exec
->clearException();
324 bool JSObjectDeleteProperty(JSContextRef ctx
, JSObjectRef object
, JSStringRef propertyName
, JSValueRef
* exception
)
326 ExecState
* exec
= toJS(ctx
);
327 APIEntryShim
entryShim(exec
);
329 JSObject
* jsObject
= toJS(object
);
331 bool result
= jsObject
->deleteProperty(exec
, propertyName
->identifier(&exec
->globalData()));
332 if (exec
->hadException()) {
334 *exception
= toRef(exec
, exec
->exception());
335 exec
->clearException();
340 void* JSObjectGetPrivate(JSObjectRef object
)
342 JSObject
* jsObject
= toJS(object
);
344 if (jsObject
->inherits(&JSCallbackObject
<JSGlobalObject
>::info
))
345 return static_cast<JSCallbackObject
<JSGlobalObject
>*>(jsObject
)->getPrivate();
346 else if (jsObject
->inherits(&JSCallbackObject
<JSObject
>::info
))
347 return static_cast<JSCallbackObject
<JSObject
>*>(jsObject
)->getPrivate();
352 bool JSObjectSetPrivate(JSObjectRef object
, void* data
)
354 JSObject
* jsObject
= toJS(object
);
356 if (jsObject
->inherits(&JSCallbackObject
<JSGlobalObject
>::info
)) {
357 static_cast<JSCallbackObject
<JSGlobalObject
>*>(jsObject
)->setPrivate(data
);
359 } else if (jsObject
->inherits(&JSCallbackObject
<JSObject
>::info
)) {
360 static_cast<JSCallbackObject
<JSObject
>*>(jsObject
)->setPrivate(data
);
367 bool JSObjectIsFunction(JSContextRef
, JSObjectRef object
)
370 return toJS(object
)->getCallData(callData
) != CallTypeNone
;
373 JSValueRef
JSObjectCallAsFunction(JSContextRef ctx
, JSObjectRef object
, JSObjectRef thisObject
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
375 ExecState
* exec
= toJS(ctx
);
376 APIEntryShim
entryShim(exec
);
378 JSObject
* jsObject
= toJS(object
);
379 JSObject
* jsThisObject
= toJS(thisObject
);
382 jsThisObject
= exec
->globalThisValue();
384 MarkedArgumentBuffer argList
;
385 for (size_t i
= 0; i
< argumentCount
; i
++)
386 argList
.append(toJS(exec
, arguments
[i
]));
389 CallType callType
= jsObject
->getCallData(callData
);
390 if (callType
== CallTypeNone
)
393 JSValueRef result
= toRef(exec
, call(exec
, jsObject
, callType
, callData
, jsThisObject
, argList
));
394 if (exec
->hadException()) {
396 *exception
= toRef(exec
, exec
->exception());
397 exec
->clearException();
403 bool JSObjectIsConstructor(JSContextRef
, JSObjectRef object
)
405 JSObject
* jsObject
= toJS(object
);
406 ConstructData constructData
;
407 return jsObject
->getConstructData(constructData
) != ConstructTypeNone
;
410 JSObjectRef
JSObjectCallAsConstructor(JSContextRef ctx
, JSObjectRef object
, size_t argumentCount
, const JSValueRef arguments
[], JSValueRef
* exception
)
412 ExecState
* exec
= toJS(ctx
);
413 APIEntryShim
entryShim(exec
);
415 JSObject
* jsObject
= toJS(object
);
417 ConstructData constructData
;
418 ConstructType constructType
= jsObject
->getConstructData(constructData
);
419 if (constructType
== ConstructTypeNone
)
422 MarkedArgumentBuffer argList
;
423 for (size_t i
= 0; i
< argumentCount
; i
++)
424 argList
.append(toJS(exec
, arguments
[i
]));
425 JSObjectRef result
= toRef(construct(exec
, jsObject
, constructType
, constructData
, argList
));
426 if (exec
->hadException()) {
428 *exception
= toRef(exec
, exec
->exception());
429 exec
->clearException();
435 struct OpaqueJSPropertyNameArray
: FastAllocBase
{
436 OpaqueJSPropertyNameArray(JSGlobalData
* globalData
)
438 , globalData(globalData
)
443 JSGlobalData
* globalData
;
444 Vector
<JSRetainPtr
<JSStringRef
> > array
;
447 JSPropertyNameArrayRef
JSObjectCopyPropertyNames(JSContextRef ctx
, JSObjectRef object
)
449 JSObject
* jsObject
= toJS(object
);
450 ExecState
* exec
= toJS(ctx
);
451 APIEntryShim
entryShim(exec
);
453 JSGlobalData
* globalData
= &exec
->globalData();
455 JSPropertyNameArrayRef propertyNames
= new OpaqueJSPropertyNameArray(globalData
);
456 PropertyNameArray
array(globalData
);
457 jsObject
->getPropertyNames(exec
, array
);
459 size_t size
= array
.size();
460 propertyNames
->array
.reserveInitialCapacity(size
);
461 for (size_t i
= 0; i
< size
; ++i
)
462 propertyNames
->array
.append(JSRetainPtr
<JSStringRef
>(Adopt
, OpaqueJSString::create(array
[i
].ustring()).releaseRef()));
464 return JSPropertyNameArrayRetain(propertyNames
);
467 JSPropertyNameArrayRef
JSPropertyNameArrayRetain(JSPropertyNameArrayRef array
)
473 void JSPropertyNameArrayRelease(JSPropertyNameArrayRef array
)
475 if (--array
->refCount
== 0) {
476 APIEntryShim
entryShim(array
->globalData
, false);
481 size_t JSPropertyNameArrayGetCount(JSPropertyNameArrayRef array
)
483 return array
->array
.size();
486 JSStringRef
JSPropertyNameArrayGetNameAtIndex(JSPropertyNameArrayRef array
, size_t index
)
488 return array
->array
[static_cast<unsigned>(index
)].get();
491 void JSPropertyNameAccumulatorAddName(JSPropertyNameAccumulatorRef array
, JSStringRef propertyName
)
493 PropertyNameArray
* propertyNames
= toJS(array
);
494 APIEntryShim
entryShim(propertyNames
->globalData());
495 propertyNames
->add(propertyName
->identifier(propertyNames
->globalData()));