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

source code of qtscript/src/3rdparty/javascriptcore/JavaScriptCore/API/JSObjectRef.cpp