initial import
[vuplus_webkit] / Source / JavaScriptCore / API / JSObjectRef.cpp
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 #include "JSObjectRefPrivate.h"
30
31 #include "APICast.h"
32 #include "CodeBlock.h"
33 #include "DateConstructor.h"
34 #include "ErrorConstructor.h"
35 #include "FunctionConstructor.h"
36 #include "Identifier.h"
37 #include "InitializeThreading.h"
38 #include "JSArray.h"
39 #include "JSCallbackConstructor.h"
40 #include "JSCallbackFunction.h"
41 #include "JSCallbackObject.h"
42 #include "JSClassRef.h"
43 #include "JSFunction.h"
44 #include "JSGlobalObject.h"
45 #include "JSObject.h"
46 #include "JSRetainPtr.h"
47 #include "JSString.h"
48 #include "JSValueRef.h"
49 #include "ObjectPrototype.h"
50 #include "PropertyNameArray.h"
51 #include "RegExpConstructor.h"
52
53 using namespace JSC;
54
55 JSClassRef 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().leakRef();
63 }
64
65 JSClassRef JSClassRetain(JSClassRef jsClass)
66 {
67     jsClass->ref();
68     return jsClass;
69 }
70
71 void JSClassRelease(JSClassRef jsClass)
72 {
73     jsClass->deref();
74 }
75
76 JSObjectRef JSObjectMake(JSContextRef ctx, JSClassRef jsClass, void* data)
77 {
78     ExecState* exec = toJS(ctx);
79     APIEntryShim entryShim(exec);
80
81     if (!jsClass)
82         return toRef(constructEmptyObject(exec));
83
84     JSCallbackObject<JSNonFinalObject>* object = JSCallbackObject<JSNonFinalObject>::create(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->callbackObjectStructure(), jsClass, data);
85     if (JSObject* prototype = jsClass->prototype(exec))
86         object->setPrototype(exec->globalData(), prototype);
87
88     return toRef(object);
89 }
90
91 JSObjectRef JSObjectMakeFunctionWithCallback(JSContextRef ctx, JSStringRef name, JSObjectCallAsFunctionCallback callAsFunction)
92 {
93     ExecState* exec = toJS(ctx);
94     APIEntryShim entryShim(exec);
95
96     Identifier nameID = name ? name->identifier(&exec->globalData()) : Identifier(exec, "anonymous");
97     
98     return toRef(JSCallbackFunction::create(exec, exec->lexicalGlobalObject(), callAsFunction, nameID));
99 }
100
101 JSObjectRef JSObjectMakeConstructor(JSContextRef ctx, JSClassRef jsClass, JSObjectCallAsConstructorCallback callAsConstructor)
102 {
103     ExecState* exec = toJS(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 = JSCallbackConstructor::create(exec, exec->lexicalGlobalObject(), exec->lexicalGlobalObject()->callbackConstructorStructure(), jsClass, callAsConstructor);
111     constructor->putDirect(exec->globalData(), exec->propertyNames().prototype, jsPrototype, DontEnum | DontDelete | ReadOnly);
112     return toRef(constructor);
113 }
114
115 JSObjectRef JSObjectMakeFunction(JSContextRef ctx, JSStringRef name, unsigned parameterCount, const JSStringRef parameterNames[], JSStringRef body, JSStringRef sourceURL, int startingLineNumber, JSValueRef* exception)
116 {
117     ExecState* exec = toJS(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(jsString(exec, parameterNames[i]->ustring()));
125     args.append(jsString(exec, body->ustring()));
126
127     JSObject* result = constructFunction(exec, exec->lexicalGlobalObject(), args, nameID, sourceURL->ustring(), startingLineNumber);
128     if (exec->hadException()) {
129         if (exception)
130             *exception = toRef(exec, exec->exception());
131         exec->clearException();
132         result = 0;
133     }
134     return toRef(result);
135 }
136
137 JSObjectRef JSObjectMakeArray(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[],  JSValueRef* exception)
138 {
139     ExecState* exec = toJS(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(toJS(exec, arguments[i]));
147
148         result = constructArray(exec, argList);
149     } else
150         result = constructEmptyArray(exec);
151
152     if (exec->hadException()) {
153         if (exception)
154             *exception = toRef(exec, exec->exception());
155         exec->clearException();
156         result = 0;
157     }
158
159     return toRef(result);
160 }
161
162 JSObjectRef JSObjectMakeDate(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[],  JSValueRef* exception)
163 {
164     ExecState* exec = toJS(ctx);
165     APIEntryShim entryShim(exec);
166
167     MarkedArgumentBuffer argList;
168     for (size_t i = 0; i < argumentCount; ++i)
169         argList.append(toJS(exec, arguments[i]));
170
171     JSObject* result = constructDate(exec, exec->lexicalGlobalObject(), argList);
172     if (exec->hadException()) {
173         if (exception)
174             *exception = toRef(exec, exec->exception());
175         exec->clearException();
176         result = 0;
177     }
178
179     return toRef(result);
180 }
181
182 JSObjectRef JSObjectMakeError(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[],  JSValueRef* exception)
183 {
184     ExecState* exec = toJS(ctx);
185     APIEntryShim entryShim(exec);
186
187     JSValue message = argumentCount ? toJS(exec, arguments[0]) : jsUndefined();
188     Structure* errorStructure = exec->lexicalGlobalObject()->errorStructure();
189     JSObject* result = ErrorInstance::create(exec, errorStructure, message);
190
191     if (exec->hadException()) {
192         if (exception)
193             *exception = toRef(exec, exec->exception());
194         exec->clearException();
195         result = 0;
196     }
197
198     return toRef(result);
199 }
200
201 JSObjectRef JSObjectMakeRegExp(JSContextRef ctx, size_t argumentCount, const JSValueRef arguments[],  JSValueRef* exception)
202 {
203     ExecState* exec = toJS(ctx);
204     APIEntryShim entryShim(exec);
205
206     MarkedArgumentBuffer argList;
207     for (size_t i = 0; i < argumentCount; ++i)
208         argList.append(toJS(exec, arguments[i]));
209
210     JSObject* result = constructRegExp(exec, exec->lexicalGlobalObject(),  argList);
211     if (exec->hadException()) {
212         if (exception)
213             *exception = toRef(exec, exec->exception());
214         exec->clearException();
215         result = 0;
216     }
217     
218     return toRef(result);
219 }
220
221 JSValueRef JSObjectGetPrototype(JSContextRef ctx, JSObjectRef object)
222 {
223     ExecState* exec = toJS(ctx);
224     APIEntryShim entryShim(exec);
225
226     JSObject* jsObject = toJS(object);
227     return toRef(exec, jsObject->prototype());
228 }
229
230 void JSObjectSetPrototype(JSContextRef ctx, JSObjectRef object, JSValueRef value)
231 {
232     ExecState* exec = toJS(ctx);
233     APIEntryShim entryShim(exec);
234
235     JSObject* jsObject = toJS(object);
236     JSValue jsValue = toJS(exec, value);
237
238     jsObject->setPrototypeWithCycleCheck(exec->globalData(), jsValue.isObject() ? jsValue : jsNull());
239 }
240
241 bool JSObjectHasProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName)
242 {
243     ExecState* exec = toJS(ctx);
244     APIEntryShim entryShim(exec);
245
246     JSObject* jsObject = toJS(object);
247     
248     return jsObject->hasProperty(exec, propertyName->identifier(&exec->globalData()));
249 }
250
251 JSValueRef JSObjectGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
252 {
253     ExecState* exec = toJS(ctx);
254     APIEntryShim entryShim(exec);
255
256     JSObject* jsObject = toJS(object);
257
258     JSValue jsValue = jsObject->get(exec, propertyName->identifier(&exec->globalData()));
259     if (exec->hadException()) {
260         if (exception)
261             *exception = toRef(exec, exec->exception());
262         exec->clearException();
263     }
264     return toRef(exec, jsValue);
265 }
266
267 void JSObjectSetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSPropertyAttributes attributes, JSValueRef* exception)
268 {
269     ExecState* exec = toJS(ctx);
270     APIEntryShim entryShim(exec);
271
272     JSObject* jsObject = toJS(object);
273     Identifier name(propertyName->identifier(&exec->globalData()));
274     JSValue jsValue = toJS(exec, value);
275
276     if (attributes && !jsObject->hasProperty(exec, name))
277         jsObject->putWithAttributes(exec, name, jsValue, attributes);
278     else {
279         PutPropertySlot slot;
280         jsObject->put(exec, name, jsValue, slot);
281     }
282
283     if (exec->hadException()) {
284         if (exception)
285             *exception = toRef(exec, exec->exception());
286         exec->clearException();
287     }
288 }
289
290 JSValueRef JSObjectGetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned propertyIndex, JSValueRef* exception)
291 {
292     ExecState* exec = toJS(ctx);
293     APIEntryShim entryShim(exec);
294
295     JSObject* jsObject = toJS(object);
296
297     JSValue jsValue = jsObject->get(exec, propertyIndex);
298     if (exec->hadException()) {
299         if (exception)
300             *exception = toRef(exec, exec->exception());
301         exec->clearException();
302     }
303     return toRef(exec, jsValue);
304 }
305
306
307 void JSObjectSetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned propertyIndex, JSValueRef value, JSValueRef* exception)
308 {
309     ExecState* exec = toJS(ctx);
310     APIEntryShim entryShim(exec);
311
312     JSObject* jsObject = toJS(object);
313     JSValue jsValue = toJS(exec, value);
314     
315     jsObject->put(exec, propertyIndex, jsValue);
316     if (exec->hadException()) {
317         if (exception)
318             *exception = toRef(exec, exec->exception());
319         exec->clearException();
320     }
321 }
322
323 bool JSObjectDeleteProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
324 {
325     ExecState* exec = toJS(ctx);
326     APIEntryShim entryShim(exec);
327
328     JSObject* jsObject = toJS(object);
329
330     bool result = jsObject->deleteProperty(exec, propertyName->identifier(&exec->globalData()));
331     if (exec->hadException()) {
332         if (exception)
333             *exception = toRef(exec, exec->exception());
334         exec->clearException();
335     }
336     return result;
337 }
338
339 void* JSObjectGetPrivate(JSObjectRef object)
340 {
341     JSObject* jsObject = toJS(object);
342     
343     if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::s_info))
344         return static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->getPrivate();
345     if (jsObject->inherits(&JSCallbackObject<JSNonFinalObject>::s_info))
346         return static_cast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->getPrivate();
347     
348     return 0;
349 }
350
351 bool JSObjectSetPrivate(JSObjectRef object, void* data)
352 {
353     JSObject* jsObject = toJS(object);
354     
355     if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::s_info)) {
356         static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->setPrivate(data);
357         return true;
358     }
359     if (jsObject->inherits(&JSCallbackObject<JSNonFinalObject>::s_info)) {
360         static_cast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->setPrivate(data);
361         return true;
362     }
363         
364     return false;
365 }
366
367 JSValueRef JSObjectGetPrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName)
368 {
369     ExecState* exec = toJS(ctx);
370     APIEntryShim entryShim(exec);
371     JSObject* jsObject = toJS(object);
372     JSValue result;
373     Identifier name(propertyName->identifier(&exec->globalData()));
374     if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::s_info))
375         result = static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->getPrivateProperty(name);
376     else if (jsObject->inherits(&JSCallbackObject<JSNonFinalObject>::s_info))
377         result = static_cast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->getPrivateProperty(name);
378     return toRef(exec, result);
379 }
380
381 bool JSObjectSetPrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value)
382 {
383     ExecState* exec = toJS(ctx);
384     APIEntryShim entryShim(exec);
385     JSObject* jsObject = toJS(object);
386     JSValue jsValue = value ? toJS(exec, value) : JSValue();
387     Identifier name(propertyName->identifier(&exec->globalData()));
388     if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::s_info)) {
389         static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->setPrivateProperty(exec->globalData(), name, jsValue);
390         return true;
391     }
392     if (jsObject->inherits(&JSCallbackObject<JSNonFinalObject>::s_info)) {
393         static_cast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->setPrivateProperty(exec->globalData(), name, jsValue);
394         return true;
395     }
396     return false;
397 }
398
399 bool JSObjectDeletePrivateProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName)
400 {
401     ExecState* exec = toJS(ctx);
402     APIEntryShim entryShim(exec);
403     JSObject* jsObject = toJS(object);
404     Identifier name(propertyName->identifier(&exec->globalData()));
405     if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::s_info)) {
406         static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->deletePrivateProperty(name);
407         return true;
408     }
409     if (jsObject->inherits(&JSCallbackObject<JSNonFinalObject>::s_info)) {
410         static_cast<JSCallbackObject<JSNonFinalObject>*>(jsObject)->deletePrivateProperty(name);
411         return true;
412     }
413     return false;
414 }
415
416 bool JSObjectIsFunction(JSContextRef, JSObjectRef object)
417 {
418     CallData callData;
419     return toJS(object)->getCallData(callData) != CallTypeNone;
420 }
421
422 JSValueRef JSObjectCallAsFunction(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
423 {
424     ExecState* exec = toJS(ctx);
425     APIEntryShim entryShim(exec);
426
427     JSObject* jsObject = toJS(object);
428     JSObject* jsThisObject = toJS(thisObject);
429
430     if (!jsThisObject)
431         jsThisObject = exec->globalThisValue();
432
433     MarkedArgumentBuffer argList;
434     for (size_t i = 0; i < argumentCount; i++)
435         argList.append(toJS(exec, arguments[i]));
436
437     CallData callData;
438     CallType callType = jsObject->getCallData(callData);
439     if (callType == CallTypeNone)
440         return 0;
441
442     JSValueRef result = toRef(exec, call(exec, jsObject, callType, callData, jsThisObject, argList));
443     if (exec->hadException()) {
444         if (exception)
445             *exception = toRef(exec, exec->exception());
446         exec->clearException();
447         result = 0;
448     }
449     return result;
450 }
451
452 bool JSObjectIsConstructor(JSContextRef, JSObjectRef object)
453 {
454     JSObject* jsObject = toJS(object);
455     ConstructData constructData;
456     return jsObject->getConstructData(constructData) != ConstructTypeNone;
457 }
458
459 JSObjectRef JSObjectCallAsConstructor(JSContextRef ctx, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
460 {
461     ExecState* exec = toJS(ctx);
462     APIEntryShim entryShim(exec);
463
464     JSObject* jsObject = toJS(object);
465
466     ConstructData constructData;
467     ConstructType constructType = jsObject->getConstructData(constructData);
468     if (constructType == ConstructTypeNone)
469         return 0;
470
471     MarkedArgumentBuffer argList;
472     for (size_t i = 0; i < argumentCount; i++)
473         argList.append(toJS(exec, arguments[i]));
474     JSObjectRef result = toRef(construct(exec, jsObject, constructType, constructData, argList));
475     if (exec->hadException()) {
476         if (exception)
477             *exception = toRef(exec, exec->exception());
478         exec->clearException();
479         result = 0;
480     }
481     return result;
482 }
483
484 struct OpaqueJSPropertyNameArray {
485     WTF_MAKE_FAST_ALLOCATED;
486 public:
487     OpaqueJSPropertyNameArray(JSGlobalData* globalData)
488         : refCount(0)
489         , globalData(globalData)
490     {
491     }
492     
493     unsigned refCount;
494     JSGlobalData* globalData;
495     Vector<JSRetainPtr<JSStringRef> > array;
496 };
497
498 JSPropertyNameArrayRef JSObjectCopyPropertyNames(JSContextRef ctx, JSObjectRef object)
499 {
500     JSObject* jsObject = toJS(object);
501     ExecState* exec = toJS(ctx);
502     APIEntryShim entryShim(exec);
503
504     JSGlobalData* globalData = &exec->globalData();
505
506     JSPropertyNameArrayRef propertyNames = new OpaqueJSPropertyNameArray(globalData);
507     PropertyNameArray array(globalData);
508     jsObject->getPropertyNames(exec, array);
509
510     size_t size = array.size();
511     propertyNames->array.reserveInitialCapacity(size);
512     for (size_t i = 0; i < size; ++i)
513         propertyNames->array.append(JSRetainPtr<JSStringRef>(Adopt, OpaqueJSString::create(array[i].ustring()).leakRef()));
514     
515     return JSPropertyNameArrayRetain(propertyNames);
516 }
517
518 JSPropertyNameArrayRef JSPropertyNameArrayRetain(JSPropertyNameArrayRef array)
519 {
520     ++array->refCount;
521     return array;
522 }
523
524 void JSPropertyNameArrayRelease(JSPropertyNameArrayRef array)
525 {
526     if (--array->refCount == 0) {
527         APIEntryShim entryShim(array->globalData, false);
528         delete array;
529     }
530 }
531
532 size_t JSPropertyNameArrayGetCount(JSPropertyNameArrayRef array)
533 {
534     return array->array.size();
535 }
536
537 JSStringRef JSPropertyNameArrayGetNameAtIndex(JSPropertyNameArrayRef array, size_t index)
538 {
539     return array->array[static_cast<unsigned>(index)].get();
540 }
541
542 void JSPropertyNameAccumulatorAddName(JSPropertyNameAccumulatorRef array, JSStringRef propertyName)
543 {
544     PropertyNameArray* propertyNames = toJS(array);
545     APIEntryShim entryShim(propertyNames->globalData());
546     propertyNames->add(propertyName->identifier(propertyNames->globalData()));
547 }