• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "DateConstructor.h"
32 #include "ErrorConstructor.h"
33 #include "FunctionConstructor.h"
34 #include "Identifier.h"
35 #include "InitializeThreading.h"
36 #include "JSArray.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"
43 #include "JSObject.h"
44 #include "JSRetainPtr.h"
45 #include "JSString.h"
46 #include "JSValueRef.h"
47 #include "ObjectPrototype.h"
48 #include "PropertyNameArray.h"
49 #include "RegExpConstructor.h"
50 #include <wtf/Platform.h>
51 
52 using namespace JSC;
53 
JSClassCreate(const JSClassDefinition * definition)54 JSClassRef JSClassCreate(const JSClassDefinition* definition)
55 {
56     initializeThreading();
57     RefPtr<OpaqueJSClass> jsClass = (definition->attributes & kJSClassAttributeNoAutomaticPrototype)
58         ? OpaqueJSClass::createNoAutomaticPrototype(definition)
59         : OpaqueJSClass::create(definition);
60 
61     return jsClass.release().releaseRef();
62 }
63 
JSClassRetain(JSClassRef jsClass)64 JSClassRef JSClassRetain(JSClassRef jsClass)
65 {
66     jsClass->ref();
67     return jsClass;
68 }
69 
JSClassRelease(JSClassRef jsClass)70 void JSClassRelease(JSClassRef jsClass)
71 {
72     jsClass->deref();
73 }
74 
JSObjectMake(JSContextRef ctx,JSClassRef jsClass,void * data)75 JSObjectRef JSObjectMake(JSContextRef ctx, JSClassRef jsClass, void* data)
76 {
77     ExecState* exec = toJS(ctx);
78     exec->globalData().heap.registerThread();
79     JSLock lock(exec);
80 
81     if (!jsClass)
82         return toRef(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(object);
89 }
90 
JSObjectMakeFunctionWithCallback(JSContextRef ctx,JSStringRef name,JSObjectCallAsFunctionCallback callAsFunction)91 JSObjectRef JSObjectMakeFunctionWithCallback(JSContextRef ctx, JSStringRef name, JSObjectCallAsFunctionCallback callAsFunction)
92 {
93     ExecState* exec = toJS(ctx);
94     exec->globalData().heap.registerThread();
95     JSLock lock(exec);
96 
97     Identifier nameID = name ? name->identifier(&exec->globalData()) : Identifier(exec, "anonymous");
98 
99     return toRef(new (exec) JSCallbackFunction(exec, callAsFunction, nameID));
100 }
101 
JSObjectMakeConstructor(JSContextRef ctx,JSClassRef jsClass,JSObjectCallAsConstructorCallback callAsConstructor)102 JSObjectRef JSObjectMakeConstructor(JSContextRef ctx, JSClassRef jsClass, JSObjectCallAsConstructorCallback callAsConstructor)
103 {
104     ExecState* exec = toJS(ctx);
105     exec->globalData().heap.registerThread();
106     JSLock lock(exec);
107 
108     JSValuePtr jsPrototype = jsClass
109         ? jsClass->prototype(exec)
110         : exec->lexicalGlobalObject()->objectPrototype();
111 
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);
115 }
116 
JSObjectMakeFunction(JSContextRef ctx,JSStringRef name,unsigned parameterCount,const JSStringRef parameterNames[],JSStringRef body,JSStringRef sourceURL,int startingLineNumber,JSValueRef * exception)117 JSObjectRef JSObjectMakeFunction(JSContextRef ctx, JSStringRef name, unsigned parameterCount, const JSStringRef parameterNames[], JSStringRef body, JSStringRef sourceURL, int startingLineNumber, JSValueRef* exception)
118 {
119     ExecState* exec = toJS(ctx);
120     exec->globalData().heap.registerThread();
121     JSLock lock(exec);
122 
123     Identifier nameID = name ? name->identifier(&exec->globalData()) : Identifier(exec, "anonymous");
124 
125     ArgList args;
126     for (unsigned i = 0; i < parameterCount; i++)
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 
JSObjectMakeArray(JSContextRef ctx,size_t argumentCount,const JSValueRef arguments[],JSValueRef * exception)140 JSObjectRef 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);
155 
156     if (exec->hadException()) {
157         if (exception)
158             *exception = toRef(exec->exception());
159         exec->clearException();
160         result = 0;
161     }
162 
163     return toRef(result);
164 }
165 
JSObjectMakeDate(JSContextRef ctx,size_t argumentCount,const JSValueRef arguments[],JSValueRef * exception)166 JSObjectRef 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 
JSObjectMakeError(JSContextRef ctx,size_t argumentCount,const JSValueRef arguments[],JSValueRef * exception)187 JSObjectRef 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 
JSObjectMakeRegExp(JSContextRef ctx,size_t argumentCount,const JSValueRef arguments[],JSValueRef * exception)208 JSObjectRef 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 
226     return toRef(result);
227 }
228 
JSObjectGetPrototype(JSContextRef,JSObjectRef object)229 JSValueRef JSObjectGetPrototype(JSContextRef, JSObjectRef object)
230 {
231     JSObject* jsObject = toJS(object);
232     return toRef(jsObject->prototype());
233 }
234 
JSObjectSetPrototype(JSContextRef,JSObjectRef object,JSValueRef value)235 void JSObjectSetPrototype(JSContextRef, JSObjectRef object, JSValueRef value)
236 {
237     JSObject* jsObject = toJS(object);
238     JSValuePtr jsValue = toJS(value);
239 
240     jsObject->setPrototype(jsValue.isObject() ? jsValue : jsNull());
241 }
242 
JSObjectHasProperty(JSContextRef ctx,JSObjectRef object,JSStringRef propertyName)243 bool JSObjectHasProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName)
244 {
245     ExecState* exec = toJS(ctx);
246     exec->globalData().heap.registerThread();
247     JSLock lock(exec);
248 
249     JSObject* jsObject = toJS(object);
250 
251     return jsObject->hasProperty(exec, propertyName->identifier(&exec->globalData()));
252 }
253 
JSObjectGetProperty(JSContextRef ctx,JSObjectRef object,JSStringRef propertyName,JSValueRef * exception)254 JSValueRef JSObjectGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
255 {
256     ExecState* exec = toJS(ctx);
257     exec->globalData().heap.registerThread();
258     JSLock lock(exec);
259 
260     JSObject* jsObject = toJS(object);
261 
262     JSValuePtr jsValue = jsObject->get(exec, propertyName->identifier(&exec->globalData()));
263     if (exec->hadException()) {
264         if (exception)
265             *exception = toRef(exec->exception());
266         exec->clearException();
267     }
268     return toRef(jsValue);
269 }
270 
JSObjectSetProperty(JSContextRef ctx,JSObjectRef object,JSStringRef propertyName,JSValueRef value,JSPropertyAttributes attributes,JSValueRef * exception)271 void JSObjectSetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSPropertyAttributes attributes, JSValueRef* exception)
272 {
273     ExecState* exec = toJS(ctx);
274     exec->globalData().heap.registerThread();
275     JSLock lock(exec);
276 
277     JSObject* jsObject = toJS(object);
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 
288     if (exec->hadException()) {
289         if (exception)
290             *exception = toRef(exec->exception());
291         exec->clearException();
292     }
293 }
294 
JSObjectGetPropertyAtIndex(JSContextRef ctx,JSObjectRef object,unsigned propertyIndex,JSValueRef * exception)295 JSValueRef JSObjectGetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned propertyIndex, JSValueRef* exception)
296 {
297     ExecState* exec = toJS(ctx);
298     exec->globalData().heap.registerThread();
299     JSLock lock(exec);
300 
301     JSObject* jsObject = toJS(object);
302 
303     JSValuePtr jsValue = jsObject->get(exec, propertyIndex);
304     if (exec->hadException()) {
305         if (exception)
306             *exception = toRef(exec->exception());
307         exec->clearException();
308     }
309     return toRef(jsValue);
310 }
311 
312 
JSObjectSetPropertyAtIndex(JSContextRef ctx,JSObjectRef object,unsigned propertyIndex,JSValueRef value,JSValueRef * exception)313 void JSObjectSetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned propertyIndex, JSValueRef value, JSValueRef* exception)
314 {
315     ExecState* exec = toJS(ctx);
316     exec->globalData().heap.registerThread();
317     JSLock lock(exec);
318 
319     JSObject* jsObject = toJS(object);
320     JSValuePtr jsValue = toJS(value);
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 
JSObjectDeleteProperty(JSContextRef ctx,JSObjectRef object,JSStringRef propertyName,JSValueRef * exception)330 bool JSObjectDeleteProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
331 {
332     ExecState* exec = toJS(ctx);
333     exec->globalData().heap.registerThread();
334     JSLock lock(exec);
335 
336     JSObject* jsObject = toJS(object);
337 
338     bool result = jsObject->deleteProperty(exec, propertyName->identifier(&exec->globalData()));
339     if (exec->hadException()) {
340         if (exception)
341             *exception = toRef(exec->exception());
342         exec->clearException();
343     }
344     return result;
345 }
346 
JSObjectGetPrivate(JSObjectRef object)347 void* 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 
JSObjectSetPrivate(JSObjectRef object,void * data)359 bool 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 
JSObjectIsFunction(JSContextRef,JSObjectRef object)374 bool JSObjectIsFunction(JSContextRef, JSObjectRef object)
375 {
376     CallData callData;
377     return toJS(object)->getCallData(callData) != CallTypeNone;
378 }
379 
JSObjectCallAsFunction(JSContextRef ctx,JSObjectRef object,JSObjectRef thisObject,size_t argumentCount,const JSValueRef arguments[],JSValueRef * exception)380 JSValueRef JSObjectCallAsFunction(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
381 {
382     ExecState* exec = toJS(ctx);
383     exec->globalData().heap.registerThread();
384     JSLock lock(exec);
385 
386     JSObject* jsObject = toJS(object);
387     JSObject* jsThisObject = toJS(thisObject);
388 
389     if (!jsThisObject)
390         jsThisObject = exec->globalThisValue();
391 
392     ArgList argList;
393     for (size_t i = 0; i < argumentCount; i++)
394         argList.append(toJS(arguments[i]));
395 
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));
402     if (exec->hadException()) {
403         if (exception)
404             *exception = toRef(exec->exception());
405         exec->clearException();
406         result = 0;
407     }
408     return result;
409 }
410 
JSObjectIsConstructor(JSContextRef,JSObjectRef object)411 bool JSObjectIsConstructor(JSContextRef, JSObjectRef object)
412 {
413     JSObject* jsObject = toJS(object);
414     ConstructData constructData;
415     return jsObject->getConstructData(constructData) != ConstructTypeNone;
416 }
417 
JSObjectCallAsConstructor(JSContextRef ctx,JSObjectRef object,size_t argumentCount,const JSValueRef arguments[],JSValueRef * exception)418 JSObjectRef JSObjectCallAsConstructor(JSContextRef ctx, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
419 {
420     ExecState* exec = toJS(ctx);
421     exec->globalData().heap.registerThread();
422     JSLock lock(exec);
423 
424     JSObject* jsObject = toJS(object);
425 
426     ConstructData constructData;
427     ConstructType constructType = jsObject->getConstructData(constructData);
428     if (constructType == ConstructTypeNone)
429         return 0;
430 
431     ArgList argList;
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()) {
436         if (exception)
437             *exception = toRef(exec->exception());
438         exec->clearException();
439         result = 0;
440     }
441     return result;
442 }
443 
444 struct OpaqueJSPropertyNameArray {
OpaqueJSPropertyNameArrayOpaqueJSPropertyNameArray445     OpaqueJSPropertyNameArray(JSGlobalData* globalData)
446         : refCount(0)
447         , globalData(globalData)
448     {
449     }
450 
451     unsigned refCount;
452     JSGlobalData* globalData;
453     Vector<JSRetainPtr<JSStringRef> > array;
454 };
455 
JSObjectCopyPropertyNames(JSContextRef ctx,JSObjectRef object)456 JSPropertyNameArrayRef JSObjectCopyPropertyNames(JSContextRef ctx, JSObjectRef object)
457 {
458     JSObject* jsObject = toJS(object);
459     ExecState* exec = toJS(ctx);
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.reserveCapacity(size);
471     for (size_t i = 0; i < size; ++i)
472         propertyNames->array.append(JSRetainPtr<JSStringRef>(Adopt, OpaqueJSString::create(array[i].ustring()).releaseRef()));
473 
474     return JSPropertyNameArrayRetain(propertyNames);
475 }
476 
JSPropertyNameArrayRetain(JSPropertyNameArrayRef array)477 JSPropertyNameArrayRef JSPropertyNameArrayRetain(JSPropertyNameArrayRef array)
478 {
479     ++array->refCount;
480     return array;
481 }
482 
JSPropertyNameArrayRelease(JSPropertyNameArrayRef array)483 void JSPropertyNameArrayRelease(JSPropertyNameArrayRef array)
484 {
485     if (--array->refCount == 0) {
486         JSLock lock(array->globalData->isSharedInstance);
487         delete array;
488     }
489 }
490 
JSPropertyNameArrayGetCount(JSPropertyNameArrayRef array)491 size_t JSPropertyNameArrayGetCount(JSPropertyNameArrayRef array)
492 {
493     return array->array.size();
494 }
495 
JSPropertyNameArrayGetNameAtIndex(JSPropertyNameArrayRef array,size_t index)496 JSStringRef JSPropertyNameArrayGetNameAtIndex(JSPropertyNameArrayRef array, size_t index)
497 {
498     return array->array[static_cast<unsigned>(index)].get();
499 }
500 
JSPropertyNameAccumulatorAddName(JSPropertyNameAccumulatorRef array,JSStringRef propertyName)501 void JSPropertyNameAccumulatorAddName(JSPropertyNameAccumulatorRef array, JSStringRef propertyName)
502 {
503     PropertyNameArray* propertyNames = toJS(array);
504 
505     propertyNames->globalData()->heap.registerThread();
506     JSLock lock(propertyNames->globalData()->isSharedInstance);
507 
508     propertyNames->add(propertyName->identifier(propertyNames->globalData()));
509 }
510