]> git.saurik.com Git - apple/javascriptcore.git/blame - API/JSObjectRef.cpp
JavaScriptCore-525.tar.gz
[apple/javascriptcore.git] / API / JSObjectRef.cpp
CommitLineData
b37bf2e1 1/*
9dae56ea
A
2 * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
3 * Copyright (C) 2008 Kelvin W Sherlock (ksherlock@gmail.com)
b37bf2e1
A
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
27#include "config.h"
28#include "JSObjectRef.h"
29
b37bf2e1 30#include "APICast.h"
9dae56ea
A
31#include "DateConstructor.h"
32#include "ErrorConstructor.h"
33#include "FunctionConstructor.h"
34#include "Identifier.h"
35#include "InitializeThreading.h"
36#include "JSArray.h"
b37bf2e1
A
37#include "JSCallbackConstructor.h"
38#include "JSCallbackFunction.h"
39#include "JSCallbackObject.h"
40#include "JSClassRef.h"
9dae56ea 41#include "JSFunction.h"
b37bf2e1 42#include "JSGlobalObject.h"
9dae56ea
A
43#include "JSObject.h"
44#include "JSRetainPtr.h"
45#include "JSString.h"
46#include "JSValueRef.h"
47#include "ObjectPrototype.h"
b37bf2e1 48#include "PropertyNameArray.h"
9dae56ea
A
49#include "RegExpConstructor.h"
50#include <wtf/Platform.h>
b37bf2e1 51
9dae56ea 52using namespace JSC;
b37bf2e1
A
53
54JSClassRef JSClassCreate(const JSClassDefinition* definition)
55{
9dae56ea
A
56 initializeThreading();
57 RefPtr<OpaqueJSClass> jsClass = (definition->attributes & kJSClassAttributeNoAutomaticPrototype)
b37bf2e1
A
58 ? OpaqueJSClass::createNoAutomaticPrototype(definition)
59 : OpaqueJSClass::create(definition);
60
9dae56ea 61 return jsClass.release().releaseRef();
b37bf2e1
A
62}
63
64JSClassRef JSClassRetain(JSClassRef jsClass)
65{
b37bf2e1
A
66 jsClass->ref();
67 return jsClass;
68}
69
70void JSClassRelease(JSClassRef jsClass)
71{
b37bf2e1
A
72 jsClass->deref();
73}
74
75JSObjectRef JSObjectMake(JSContextRef ctx, JSClassRef jsClass, void* data)
76{
b37bf2e1 77 ExecState* exec = toJS(ctx);
9dae56ea
A
78 exec->globalData().heap.registerThread();
79 JSLock lock(exec);
b37bf2e1
A
80
81 if (!jsClass)
9dae56ea 82 return toRef(new (exec) JSObject(exec->lexicalGlobalObject()->emptyObjectStructure())); // slightly more efficient
b37bf2e1 83
9dae56ea
A
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);
b37bf2e1 87
9dae56ea 88 return toRef(object);
b37bf2e1
A
89}
90
91JSObjectRef JSObjectMakeFunctionWithCallback(JSContextRef ctx, JSStringRef name, JSObjectCallAsFunctionCallback callAsFunction)
92{
b37bf2e1 93 ExecState* exec = toJS(ctx);
9dae56ea
A
94 exec->globalData().heap.registerThread();
95 JSLock lock(exec);
96
97 Identifier nameID = name ? name->identifier(&exec->globalData()) : Identifier(exec, "anonymous");
b37bf2e1 98
9dae56ea 99 return toRef(new (exec) JSCallbackFunction(exec, callAsFunction, nameID));
b37bf2e1
A
100}
101
102JSObjectRef JSObjectMakeConstructor(JSContextRef ctx, JSClassRef jsClass, JSObjectCallAsConstructorCallback callAsConstructor)
103{
b37bf2e1 104 ExecState* exec = toJS(ctx);
9dae56ea
A
105 exec->globalData().heap.registerThread();
106 JSLock lock(exec);
107
108 JSValuePtr jsPrototype = jsClass
109 ? jsClass->prototype(exec)
110 : exec->lexicalGlobalObject()->objectPrototype();
b37bf2e1 111
9dae56ea 112 JSCallbackConstructor* constructor = new (exec) JSCallbackConstructor(exec->lexicalGlobalObject()->callbackConstructorStructure(), jsClass, callAsConstructor);
b37bf2e1
A
113 constructor->putDirect(exec->propertyNames().prototype, jsPrototype, DontEnum | DontDelete | ReadOnly);
114 return toRef(constructor);
115}
116
117JSObjectRef JSObjectMakeFunction(JSContextRef ctx, JSStringRef name, unsigned parameterCount, const JSStringRef parameterNames[], JSStringRef body, JSStringRef sourceURL, int startingLineNumber, JSValueRef* exception)
118{
b37bf2e1 119 ExecState* exec = toJS(ctx);
9dae56ea
A
120 exec->globalData().heap.registerThread();
121 JSLock lock(exec);
122
123 Identifier nameID = name ? name->identifier(&exec->globalData()) : Identifier(exec, "anonymous");
b37bf2e1 124
9dae56ea 125 ArgList args;
b37bf2e1 126 for (unsigned i = 0; i < parameterCount; i++)
9dae56ea
A
127 args.append(jsString(exec, parameterNames[i]->ustring()));
128 args.append(jsString(exec, body->ustring()));
129
130 JSObject* result = constructFunction(exec, args, nameID, sourceURL->ustring(), startingLineNumber);
131 if (exec->hadException()) {
132 if (exception)
133 *exception = toRef(exec->exception());
134 exec->clearException();
135 result = 0;
136 }
137 return toRef(result);
138}
139
140JSObjectRef JSObjectMakeArray(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
141{
142 ExecState* exec = toJS(ctx);
143 exec->globalData().heap.registerThread();
144 JSLock lock(exec);
145
146 JSObject* result;
147 if (argumentCount) {
148 ArgList argList;
149 for (size_t i = 0; i < argumentCount; ++i)
150 argList.append(toJS(arguments[i]));
151
152 result = constructArray(exec, argList);
153 } else
154 result = constructEmptyArray(exec);
b37bf2e1 155
b37bf2e1
A
156 if (exec->hadException()) {
157 if (exception)
158 *exception = toRef(exec->exception());
159 exec->clearException();
160 result = 0;
161 }
9dae56ea
A
162
163 return toRef(result);
164}
165
166JSObjectRef JSObjectMakeDate(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
167{
168 ExecState* exec = toJS(ctx);
169 exec->globalData().heap.registerThread();
170 JSLock lock(exec);
171
172 ArgList argList;
173 for (size_t i = 0; i < argumentCount; ++i)
174 argList.append(toJS(arguments[i]));
175
176 JSObject* result = constructDate(exec, argList);
177 if (exec->hadException()) {
178 if (exception)
179 *exception = toRef(exec->exception());
180 exec->clearException();
181 result = 0;
182 }
183
184 return toRef(result);
185}
186
187JSObjectRef JSObjectMakeError(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
188{
189 ExecState* exec = toJS(ctx);
190 exec->globalData().heap.registerThread();
191 JSLock lock(exec);
192
193 ArgList argList;
194 for (size_t i = 0; i < argumentCount; ++i)
195 argList.append(toJS(arguments[i]));
196
197 JSObject* result = constructError(exec, argList);
198 if (exec->hadException()) {
199 if (exception)
200 *exception = toRef(exec->exception());
201 exec->clearException();
202 result = 0;
203 }
204
205 return toRef(result);
206}
207
208JSObjectRef JSObjectMakeRegExp(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
209{
210 ExecState* exec = toJS(ctx);
211 exec->globalData().heap.registerThread();
212 JSLock lock(exec);
213
214 ArgList argList;
215 for (size_t i = 0; i < argumentCount; ++i)
216 argList.append(toJS(arguments[i]));
217
218 JSObject* result = constructRegExp(exec, argList);
219 if (exec->hadException()) {
220 if (exception)
221 *exception = toRef(exec->exception());
222 exec->clearException();
223 result = 0;
224 }
225
b37bf2e1
A
226 return toRef(result);
227}
228
229JSValueRef JSObjectGetPrototype(JSContextRef, JSObjectRef object)
230{
231 JSObject* jsObject = toJS(object);
232 return toRef(jsObject->prototype());
233}
234
235void JSObjectSetPrototype(JSContextRef, JSObjectRef object, JSValueRef value)
236{
237 JSObject* jsObject = toJS(object);
9dae56ea 238 JSValuePtr jsValue = toJS(value);
b37bf2e1 239
9dae56ea 240 jsObject->setPrototype(jsValue.isObject() ? jsValue : jsNull());
b37bf2e1
A
241}
242
243bool JSObjectHasProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName)
244{
b37bf2e1 245 ExecState* exec = toJS(ctx);
9dae56ea
A
246 exec->globalData().heap.registerThread();
247 JSLock lock(exec);
248
b37bf2e1 249 JSObject* jsObject = toJS(object);
b37bf2e1 250
9dae56ea 251 return jsObject->hasProperty(exec, propertyName->identifier(&exec->globalData()));
b37bf2e1
A
252}
253
254JSValueRef JSObjectGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
255{
b37bf2e1 256 ExecState* exec = toJS(ctx);
9dae56ea
A
257 exec->globalData().heap.registerThread();
258 JSLock lock(exec);
259
b37bf2e1 260 JSObject* jsObject = toJS(object);
b37bf2e1 261
9dae56ea 262 JSValuePtr jsValue = jsObject->get(exec, propertyName->identifier(&exec->globalData()));
b37bf2e1
A
263 if (exec->hadException()) {
264 if (exception)
265 *exception = toRef(exec->exception());
266 exec->clearException();
267 }
268 return toRef(jsValue);
269}
270
271void JSObjectSetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSPropertyAttributes attributes, JSValueRef* exception)
272{
b37bf2e1 273 ExecState* exec = toJS(ctx);
9dae56ea
A
274 exec->globalData().heap.registerThread();
275 JSLock lock(exec);
276
b37bf2e1 277 JSObject* jsObject = toJS(object);
9dae56ea
A
278 Identifier name(propertyName->identifier(&exec->globalData()));
279 JSValuePtr jsValue = toJS(value);
280
281 if (attributes && !jsObject->hasProperty(exec, name))
282 jsObject->putWithAttributes(exec, name, jsValue, attributes);
283 else {
284 PutPropertySlot slot;
285 jsObject->put(exec, name, jsValue, slot);
286 }
287
b37bf2e1
A
288 if (exec->hadException()) {
289 if (exception)
290 *exception = toRef(exec->exception());
291 exec->clearException();
292 }
293}
294
295JSValueRef JSObjectGetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned propertyIndex, JSValueRef* exception)
296{
b37bf2e1 297 ExecState* exec = toJS(ctx);
9dae56ea
A
298 exec->globalData().heap.registerThread();
299 JSLock lock(exec);
300
b37bf2e1
A
301 JSObject* jsObject = toJS(object);
302
9dae56ea 303 JSValuePtr jsValue = jsObject->get(exec, propertyIndex);
b37bf2e1
A
304 if (exec->hadException()) {
305 if (exception)
306 *exception = toRef(exec->exception());
307 exec->clearException();
308 }
309 return toRef(jsValue);
310}
311
312
313void JSObjectSetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned propertyIndex, JSValueRef value, JSValueRef* exception)
314{
b37bf2e1 315 ExecState* exec = toJS(ctx);
9dae56ea
A
316 exec->globalData().heap.registerThread();
317 JSLock lock(exec);
318
b37bf2e1 319 JSObject* jsObject = toJS(object);
9dae56ea 320 JSValuePtr jsValue = toJS(value);
b37bf2e1
A
321
322 jsObject->put(exec, propertyIndex, jsValue);
323 if (exec->hadException()) {
324 if (exception)
325 *exception = toRef(exec->exception());
326 exec->clearException();
327 }
328}
329
330bool JSObjectDeleteProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
331{
b37bf2e1 332 ExecState* exec = toJS(ctx);
9dae56ea
A
333 exec->globalData().heap.registerThread();
334 JSLock lock(exec);
335
b37bf2e1 336 JSObject* jsObject = toJS(object);
b37bf2e1 337
9dae56ea 338 bool result = jsObject->deleteProperty(exec, propertyName->identifier(&exec->globalData()));
b37bf2e1
A
339 if (exec->hadException()) {
340 if (exception)
341 *exception = toRef(exec->exception());
342 exec->clearException();
343 }
344 return result;
345}
346
347void* JSObjectGetPrivate(JSObjectRef object)
348{
349 JSObject* jsObject = toJS(object);
350
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();
355
356 return 0;
357}
358
359bool JSObjectSetPrivate(JSObjectRef object, void* data)
360{
361 JSObject* jsObject = toJS(object);
362
363 if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::info)) {
364 static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->setPrivate(data);
365 return true;
366 } else if (jsObject->inherits(&JSCallbackObject<JSObject>::info)) {
367 static_cast<JSCallbackObject<JSObject>*>(jsObject)->setPrivate(data);
368 return true;
369 }
370
371 return false;
372}
373
374bool JSObjectIsFunction(JSContextRef, JSObjectRef object)
375{
9dae56ea
A
376 CallData callData;
377 return toJS(object)->getCallData(callData) != CallTypeNone;
b37bf2e1
A
378}
379
380JSValueRef JSObjectCallAsFunction(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
381{
b37bf2e1 382 ExecState* exec = toJS(ctx);
9dae56ea
A
383 exec->globalData().heap.registerThread();
384 JSLock lock(exec);
385
b37bf2e1
A
386 JSObject* jsObject = toJS(object);
387 JSObject* jsThisObject = toJS(thisObject);
388
389 if (!jsThisObject)
9dae56ea
A
390 jsThisObject = exec->globalThisValue();
391
392 ArgList argList;
b37bf2e1
A
393 for (size_t i = 0; i < argumentCount; i++)
394 argList.append(toJS(arguments[i]));
395
9dae56ea
A
396 CallData callData;
397 CallType callType = jsObject->getCallData(callData);
398 if (callType == CallTypeNone)
399 return 0;
400
401 JSValueRef result = toRef(call(exec, jsObject, callType, callData, jsThisObject, argList));
b37bf2e1
A
402 if (exec->hadException()) {
403 if (exception)
404 *exception = toRef(exec->exception());
405 exec->clearException();
406 result = 0;
407 }
408 return result;
409}
410
411bool JSObjectIsConstructor(JSContextRef, JSObjectRef object)
412{
413 JSObject* jsObject = toJS(object);
9dae56ea
A
414 ConstructData constructData;
415 return jsObject->getConstructData(constructData) != ConstructTypeNone;
b37bf2e1
A
416}
417
418JSObjectRef JSObjectCallAsConstructor(JSContextRef ctx, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
419{
b37bf2e1 420 ExecState* exec = toJS(ctx);
9dae56ea
A
421 exec->globalData().heap.registerThread();
422 JSLock lock(exec);
423
b37bf2e1 424 JSObject* jsObject = toJS(object);
9dae56ea
A
425
426 ConstructData constructData;
427 ConstructType constructType = jsObject->getConstructData(constructData);
428 if (constructType == ConstructTypeNone)
429 return 0;
430
431 ArgList argList;
b37bf2e1
A
432 for (size_t i = 0; i < argumentCount; i++)
433 argList.append(toJS(arguments[i]));
9dae56ea 434 JSObjectRef result = toRef(construct(exec, jsObject, constructType, constructData, argList));
b37bf2e1
A
435 if (exec->hadException()) {
436 if (exception)
437 *exception = toRef(exec->exception());
438 exec->clearException();
439 result = 0;
440 }
441 return result;
442}
443
9dae56ea
A
444struct OpaqueJSPropertyNameArray {
445 OpaqueJSPropertyNameArray(JSGlobalData* globalData)
446 : refCount(0)
447 , globalData(globalData)
b37bf2e1
A
448 {
449 }
450
451 unsigned refCount;
9dae56ea
A
452 JSGlobalData* globalData;
453 Vector<JSRetainPtr<JSStringRef> > array;
b37bf2e1
A
454};
455
456JSPropertyNameArrayRef JSObjectCopyPropertyNames(JSContextRef ctx, JSObjectRef object)
457{
b37bf2e1
A
458 JSObject* jsObject = toJS(object);
459 ExecState* exec = toJS(ctx);
9dae56ea
A
460 exec->globalData().heap.registerThread();
461 JSLock lock(exec);
462
463 JSGlobalData* globalData = &exec->globalData();
464
465 JSPropertyNameArrayRef propertyNames = new OpaqueJSPropertyNameArray(globalData);
466 PropertyNameArray array(globalData);
467 jsObject->getPropertyNames(exec, array);
468
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()));
b37bf2e1
A
473
474 return JSPropertyNameArrayRetain(propertyNames);
475}
476
477JSPropertyNameArrayRef JSPropertyNameArrayRetain(JSPropertyNameArrayRef array)
478{
b37bf2e1
A
479 ++array->refCount;
480 return array;
481}
482
483void JSPropertyNameArrayRelease(JSPropertyNameArrayRef array)
484{
9dae56ea
A
485 if (--array->refCount == 0) {
486 JSLock lock(array->globalData->isSharedInstance);
b37bf2e1 487 delete array;
9dae56ea 488 }
b37bf2e1
A
489}
490
491size_t JSPropertyNameArrayGetCount(JSPropertyNameArrayRef array)
492{
493 return array->array.size();
494}
495
496JSStringRef JSPropertyNameArrayGetNameAtIndex(JSPropertyNameArrayRef array, size_t index)
497{
9dae56ea 498 return array->array[static_cast<unsigned>(index)].get();
b37bf2e1
A
499}
500
501void JSPropertyNameAccumulatorAddName(JSPropertyNameAccumulatorRef array, JSStringRef propertyName)
502{
b37bf2e1 503 PropertyNameArray* propertyNames = toJS(array);
9dae56ea
A
504
505 propertyNames->globalData()->heap.registerThread();
506 JSLock lock(propertyNames->globalData()->isSharedInstance);
507
508 propertyNames->add(propertyName->identifier(propertyNames->globalData()));
b37bf2e1 509}