source: webkit/trunk/JavaScriptCore/API/JSObjectRef.cpp@ 15468

Last change on this file since 15468 was 15468, checked in by mjs, 19 years ago

JavaScriptCore:

Reviewed by Darin.


  • switch property lists to be vector+set of Identifiers instead of list of References


This has the following benefits:


  • no duplicates in property lists
  • simplifies API calls
  • probably more efficient, since linked list is gone
  • entirely removed Reference, ReferenceList and ProtectedReference types from the API
  • kjs/PropertyNameArray.cpp: Added. (KJS::PropertyNameArray::add): Check set, if not already there, add to vector.
  • kjs/PropertyNameArray.h: Added. (KJS::PropertyNameArray::PropertyNameArray): Newly added type, combines a set and a vector to make a unique but ordered list of identifiers. (KJS::PropertyNameArray::begin): ditto (KJS::PropertyNameArray::end): ditto (KJS::PropertyNameArray::size): ditto (KJS::PropertyNameArray::operator[]): ditto
  • kjs/array_instance.h:
  • kjs/array_object.cpp: (ArrayInstance::getPropertyNames): renamed from getPropertyList, updated for PropertyNameArray (ArrayInstance::setLength): updated for PropertyNameArray (ArrayInstance::pushUndefinedObjectsToEnd): ditto
  • kjs/nodes.cpp: (ForInNode::execute): updated for PropertyNameArray
  • kjs/nodes.h:
  • kjs/object.cpp: (KJS::JSObject::getPropertyNames): renamed from getPropertyList, updated for PropertyNameArray
  • kjs/object.h:
  • kjs/property_map.cpp: (KJS::PropertyMap::getEnumerablePropertyNames): updated for PropertyNameArray (KJS::PropertyMap::getSparseArrayPropertyNames): ditto
  • kjs/property_map.h:
  • kjs/protected_reference.h: Removed.
  • kjs/reference.cpp: Removed.
  • kjs/reference.h: Removed.
  • kjs/reference_list.cpp: Removed.
  • kjs/reference_list.h: Removed.
  • kjs/scope_chain.cpp: (KJS::ScopeChain::print): Use PropertyNamesArray instead of ReferenceList.
  • kjs/string_object.cpp: (StringInstance::getPropertyNames): Updated for new approach.
  • kjs/string_object.h:
  • kjs/ustring.h:
  • API/APICast.h: (toJS): Added overload for PropertyNameAccumulatorRef / PropertyNameArray* (toRef): ditto
  • API/JSBase.h:
  • API/JSCallbackObject.cpp: (KJS::JSCallbackObject::getPropertyNames): Fixed for new API.
  • API/JSCallbackObject.h:
  • API/JSObjectRef.cpp: (JSPropertyNameArray::JSPropertyNameArray): Type used for a publicly vended JSPropertyNameArrayRef. (JSObjectCopyPropertyNames): New API call - renamed / refactored from JSObjectCreatePropertyList (JSPropertyNameArrayRetain): new retain call for JSPropertyNameArray. (JSPropertyNameArrayRelease): new release call for - " -. (JSPropertyNameArrayGetCount): Instead of having to use a stateful enumerator you can now get the count and items in any order. (JSPropertyNameArrayGetNameAtIndex): See above. (JSPropertyNameAccumulatorAddName): What you add properties to is now an opaque accumulator object.
  • API/JSObjectRef.h: Prototyped new functions, removed old ones
  • JavaScriptCore.exp: Updated exported symbols.
  • JavaScriptCore.xcodeproj/project.pbxproj: Added new files, removed old.
  • API/testapi.c: (MyObject_getPropertyNames): Renamed / fixed callback to fit new paradigm. (main): Updated for new API.

JavaScriptGlue:

Reviewed by Darin.

  • switch property lists to be vector+set of Identifiers instead of list of References


  • JSUtils.cpp: (KJSValueToCFTypeInternal): updated for JSC SPI changes
  • JSValueWrapper.cpp: (JSValueWrapper::JSObjectCopyPropertyNames): ditto
  • UserObjectImp.cpp: (UserObjectImp::getPropertyNames): ditto
  • UserObjectImp.h:

LayoutTests:

Reviewed by Darin.


  • new test case and updated results for property list changes
  • fast/js/for-in-avoid-duplicates-expected.txt: Added.
  • fast/js/for-in-avoid-duplicates.html: Added.
  • fast/js/kde/Array-expected.txt:
  • fast/js/resources/for-in-avoid-duplicates.js: Added.
File size: 11.0 KB
Line 
1// -*- mode: c++; c-basic-offset: 4 -*-
2/*
3 * Copyright (C) 2006 Apple Computer, Inc. All rights reserved.
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 "APICast.h"
28#include "JSValueRef.h"
29#include "JSObjectRef.h"
30#include "JSCallbackConstructor.h"
31#include "JSCallbackFunction.h"
32#include "JSCallbackObject.h"
33#include "JSClassRef.h"
34
35#include "identifier.h"
36#include "function.h"
37#include "nodes.h"
38#include "internal.h"
39#include "object.h"
40#include "PropertyNameArray.h"
41
42using namespace KJS;
43
44JSClassRef JSClassCreate(JSClassDefinition* definition)
45{
46 JSClassRef jsClass = new __JSClass(definition);
47 return JSClassRetain(jsClass);
48}
49
50JSClassRef JSClassRetain(JSClassRef jsClass)
51{
52 ++jsClass->refCount;
53 return jsClass;
54}
55
56void JSClassRelease(JSClassRef jsClass)
57{
58 if (--jsClass->refCount == 0)
59 delete jsClass;
60}
61
62JSObjectRef JSObjectMake(JSContextRef context, JSClassRef jsClass, JSValueRef prototype)
63{
64 JSLock lock;
65
66 ExecState* exec = toJS(context);
67 JSValue* jsPrototype = toJS(prototype);
68
69 if (!prototype)
70 jsPrototype = exec->lexicalInterpreter()->builtinObjectPrototype();
71
72 if (!jsClass)
73 return toRef(new JSObject(jsPrototype)); // slightly more efficient
74 else
75 return toRef(new JSCallbackObject(context, jsClass, jsPrototype));
76}
77
78JSObjectRef JSObjectMakeFunction(JSContextRef context, JSObjectCallAsFunctionCallback callAsFunction)
79{
80 JSLock lock;
81 ExecState* exec = toJS(context);
82 return toRef(new JSCallbackFunction(exec, callAsFunction));
83}
84
85JSObjectRef JSObjectMakeConstructor(JSContextRef context, JSObjectCallAsConstructorCallback callAsConstructor)
86{
87 JSLock lock;
88 ExecState* exec = toJS(context);
89 return toRef(new JSCallbackConstructor(exec, callAsConstructor));
90}
91
92JSObjectRef JSObjectMakeFunctionWithBody(JSContextRef context, JSStringRef name, unsigned parameterCount, const JSStringRef parameterNames[], JSStringRef body, JSStringRef sourceURL, int startingLineNumber, JSValueRef* exception)
93{
94 JSLock lock;
95
96 ExecState* exec = toJS(context);
97 UString::Rep* nameRep = name ? toJS(name) : &UString::Rep::null;
98 UString::Rep* bodyRep = toJS(body);
99 UString::Rep* sourceURLRep = sourceURL ? toJS(sourceURL) : &UString::Rep::null;
100
101 Identifier nameIdentifier = nameRep ? Identifier(nameRep) : Identifier("anonymous");
102
103 List args;
104 for (unsigned i = 0; i < parameterCount; i++)
105 args.append(jsString(UString(toJS(parameterNames[i]))));
106 args.append(jsString(UString(bodyRep)));
107
108 JSObject* result = exec->dynamicInterpreter()->builtinFunction()->construct(exec, args, nameIdentifier, UString(sourceURLRep), startingLineNumber);
109 if (exec->hadException()) {
110 if (exception)
111 *exception = toRef(exec->exception());
112 exec->clearException();
113 result = 0;
114 }
115 return toRef(result);
116}
117
118JSValueRef JSObjectGetPrototype(JSObjectRef object)
119{
120 JSObject* jsObject = toJS(object);
121 return toRef(jsObject->prototype());
122}
123
124void JSObjectSetPrototype(JSObjectRef object, JSValueRef value)
125{
126 JSObject* jsObject = toJS(object);
127 JSValue* jsValue = toJS(value);
128
129 jsObject->setPrototype(jsValue);
130}
131
132bool JSObjectHasProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName)
133{
134 JSLock lock;
135 ExecState* exec = toJS(context);
136 JSObject* jsObject = toJS(object);
137 UString::Rep* nameRep = toJS(propertyName);
138
139 return jsObject->hasProperty(exec, Identifier(nameRep));
140}
141
142JSValueRef JSObjectGetProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
143{
144 JSLock lock;
145 ExecState* exec = toJS(context);
146 JSObject* jsObject = toJS(object);
147 UString::Rep* nameRep = toJS(propertyName);
148
149 JSValue* jsValue = jsObject->get(exec, Identifier(nameRep));
150 if (jsValue->isUndefined())
151 jsValue = 0;
152 if (exec->hadException()) {
153 if (exception)
154 *exception = toRef(exec->exception());
155 exec->clearException();
156 }
157 return toRef(jsValue);
158}
159
160void JSObjectSetProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSPropertyAttributes attributes, JSValueRef* exception)
161{
162 JSLock lock;
163 ExecState* exec = toJS(context);
164 JSObject* jsObject = toJS(object);
165 UString::Rep* nameRep = toJS(propertyName);
166 JSValue* jsValue = toJS(value);
167
168 jsObject->put(exec, Identifier(nameRep), jsValue, attributes);
169 if (exec->hadException()) {
170 if (exception)
171 *exception = toRef(exec->exception());
172 exec->clearException();
173 }
174}
175
176JSValueRef JSObjectGetPropertyAtIndex(JSContextRef context, JSObjectRef object, unsigned propertyIndex)
177{
178 JSLock lock;
179 ExecState* exec = toJS(context);
180 JSObject* jsObject = toJS(object);
181
182 JSValue* jsValue = jsObject->get(exec, propertyIndex);
183 if (jsValue->isUndefined())
184 return 0;
185 return toRef(jsValue);
186}
187
188
189void JSObjectSetPropertyAtIndex(JSContextRef context, JSObjectRef object, unsigned propertyIndex, JSValueRef value)
190{
191 JSLock lock;
192 ExecState* exec = toJS(context);
193 JSObject* jsObject = toJS(object);
194 JSValue* jsValue = toJS(value);
195
196 jsObject->put(exec, propertyIndex, jsValue);
197}
198
199bool JSObjectDeleteProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
200{
201 JSLock lock;
202 ExecState* exec = toJS(context);
203 JSObject* jsObject = toJS(object);
204 UString::Rep* nameRep = toJS(propertyName);
205
206 bool result = jsObject->deleteProperty(exec, Identifier(nameRep));
207 if (exec->hadException()) {
208 if (exception)
209 *exception = toRef(exec->exception());
210 exec->clearException();
211 }
212 return result;
213}
214
215void* JSObjectGetPrivate(JSObjectRef object)
216{
217 JSObject* jsObject = toJS(object);
218
219 if (jsObject->inherits(&JSCallbackObject::info))
220 return static_cast<JSCallbackObject*>(jsObject)->getPrivate();
221
222 if (jsObject->inherits(&JSCallbackFunction::info))
223 return static_cast<JSCallbackFunction*>(jsObject)->getPrivate();
224
225 if (jsObject->inherits(&JSCallbackConstructor::info))
226 return static_cast<JSCallbackConstructor*>(jsObject)->getPrivate();
227
228 return 0;
229}
230
231bool JSObjectSetPrivate(JSObjectRef object, void* data)
232{
233 JSObject* jsObject = toJS(object);
234
235 if (jsObject->inherits(&JSCallbackObject::info)) {
236 static_cast<JSCallbackObject*>(jsObject)->setPrivate(data);
237 return true;
238 }
239
240 if (jsObject->inherits(&JSCallbackFunction::info)) {
241 static_cast<JSCallbackFunction*>(jsObject)->setPrivate(data);
242 return true;
243 }
244
245 if (jsObject->inherits(&JSCallbackConstructor::info)) {
246 static_cast<JSCallbackConstructor*>(jsObject)->setPrivate(data);
247 return true;
248 }
249
250 return false;
251}
252
253bool JSObjectIsFunction(JSObjectRef object)
254{
255 JSObject* jsObject = toJS(object);
256 return jsObject->implementsCall();
257}
258
259JSValueRef JSObjectCallAsFunction(JSContextRef context, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
260{
261 JSLock lock;
262 ExecState* exec = toJS(context);
263 JSObject* jsObject = toJS(object);
264 JSObject* jsThisObject = toJS(thisObject);
265
266 if (!jsThisObject)
267 jsThisObject = exec->dynamicInterpreter()->globalObject();
268
269 List argList;
270 for (size_t i = 0; i < argumentCount; i++)
271 argList.append(toJS(arguments[i]));
272
273 JSValueRef result = toRef(jsObject->call(exec, jsThisObject, argList)); // returns NULL if object->implementsCall() is false
274 if (exec->hadException()) {
275 if (exception)
276 *exception = toRef(exec->exception());
277 exec->clearException();
278 result = 0;
279 }
280 return result;
281}
282
283bool JSObjectIsConstructor(JSObjectRef object)
284{
285 JSObject* jsObject = toJS(object);
286 return jsObject->implementsConstruct();
287}
288
289JSObjectRef JSObjectCallAsConstructor(JSContextRef context, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
290{
291 JSLock lock;
292 ExecState* exec = toJS(context);
293 JSObject* jsObject = toJS(object);
294
295 List argList;
296 for (size_t i = 0; i < argumentCount; i++)
297 argList.append(toJS(arguments[i]));
298
299 JSObjectRef result = toRef(jsObject->construct(exec, argList)); // returns NULL if object->implementsCall() is false
300 if (exec->hadException()) {
301 if (exception)
302 *exception = toRef(exec->exception());
303 exec->clearException();
304 result = 0;
305 }
306 return result;
307}
308
309struct __JSPropertyNameArray
310{
311 __JSPropertyNameArray() : refCount(0)
312 {
313 }
314
315 unsigned refCount;
316 PropertyNameArray array;
317};
318
319JSPropertyNameArrayRef JSObjectCopyPropertyNames(JSContextRef context, JSObjectRef object)
320{
321 JSLock lock;
322 JSObject* jsObject = toJS(object);
323 ExecState* exec = toJS(context);
324
325 JSPropertyNameArrayRef propertyNames = new __JSPropertyNameArray();
326 jsObject->getPropertyNames(exec, propertyNames->array);
327
328 return JSPropertyNameArrayRetain(propertyNames);
329}
330
331JSPropertyNameArrayRef JSPropertyNameArrayRetain(JSPropertyNameArrayRef array)
332{
333 ++array->refCount;
334 return array;
335}
336
337void JSPropertyNameArrayRelease(JSPropertyNameArrayRef array)
338{
339 if (--array->refCount == 0)
340 delete array;
341}
342
343size_t JSPropertyNameArrayGetCount(JSPropertyNameArrayRef array)
344{
345 return array->array.size();
346}
347
348JSStringRef JSPropertyNameArrayGetNameAtIndex(JSPropertyNameArrayRef array, size_t index)
349{
350 return toRef(array->array[index].ustring().rep());
351}
352
353void JSPropertyNameAccumulatorAddName(JSPropertyNameAccumulatorRef array, JSStringRef propertyName)
354{
355 JSLock lock;
356 PropertyNameArray* propertyNames = toJS(array);
357 UString::Rep* rep = toJS(propertyName);
358
359 propertyNames->add(Identifier(rep));
360}
Note: See TracBrowser for help on using the repository browser.