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

Last change on this file since 31872 was 31746, checked in by [email protected], 17 years ago

JavaScriptCore:

2008-04-04 Sam Weinig <[email protected]>

Reviewed by Geoffrey Garen.

First step in implementing the "split window"

  • Add a GlobalThisValue to ExecState which should be used in places that used to implement the "use the global object as this if null" rule.
  • Factor out lookupGetter/lookupSetter into virtual methods on JSObject so that they can be forwarded.
  • Make defineGetter/defineSetter virtual methods for the same reason.
  • Have PrototypeReflexiveFunction store the globalObject used to create it so that it can be used to get the correct thisObject for eval.
  • API/JSObjectRef.cpp: (JSObjectCallAsFunction):
  • JavaScriptCore.exp:
  • kjs/Activation.h:
  • kjs/ExecState.cpp: (KJS::ExecState::ExecState): (KJS::GlobalExecState::GlobalExecState):
  • kjs/ExecState.h: (KJS::ExecState::globalThisValue):
  • kjs/ExecStateInlines.h: (KJS::ExecState::ExecState): (KJS::FunctionExecState::FunctionExecState):
  • kjs/JSGlobalObject.cpp: (KJS::JSGlobalObject::reset): (KJS::JSGlobalObject::toGlobalObject):
  • kjs/JSGlobalObject.h: (KJS::JSGlobalObject::JSGlobalObjectData::JSGlobalObjectData): (KJS::JSGlobalObject::JSGlobalObject):
  • kjs/array_instance.cpp: (KJS::CompareWithCompareFunctionArguments::CompareWithCompareFunctionArguments): (KJS::compareWithCompareFunctionForQSort):
  • kjs/array_object.cpp: (KJS::arrayProtoFuncSort): (KJS::arrayProtoFuncFilter): (KJS::arrayProtoFuncMap): (KJS::arrayProtoFuncEvery): (KJS::arrayProtoFuncForEach): (KJS::arrayProtoFuncSome):
  • kjs/function.cpp: (KJS::FunctionImp::callAsFunction): (KJS::ActivationImp::toThisObject): (KJS::globalFuncEval): (KJS::PrototypeReflexiveFunction::PrototypeReflexiveFunction): (KJS::PrototypeReflexiveFunction::mark):
  • kjs/function.h: (KJS::PrototypeReflexiveFunction::cachedGlobalObject):
  • kjs/function_object.cpp: (KJS::functionProtoFuncApply): (KJS::functionProtoFuncCall):
  • kjs/nodes.cpp: (KJS::ExpressionNode::resolveAndCall): (KJS::FunctionCallValueNode::evaluate): (KJS::LocalVarFunctionCallNode::inlineEvaluate): (KJS::ScopedVarFunctionCallNode::inlineEvaluate): (KJS::FunctionCallBracketNode::evaluate): (KJS::FunctionCallDotNode::inlineEvaluate):
  • kjs/object.cpp: (KJS::JSObject::call): (KJS::JSObject::put): (KJS::tryGetAndCallProperty): (KJS::JSObject::lookupGetter): (KJS::JSObject::lookupSetter): (KJS::JSObject::toThisObject): (KJS::JSObject::toGlobalObject): (KJS::JSObject::fillGetterPropertySlot):
  • kjs/object.h:
  • kjs/object_object.cpp: (KJS::objectProtoFuncLookupGetter): (KJS::objectProtoFuncLookupSetter):
  • kjs/string_object.cpp: (KJS::replace):

WebCore:

2008-04-04 Sam Weinig <[email protected]>

Reviewed by Geoffrey Garen.

First step in implementing the "split window"

  • This patch takes the first step in changing the window navigation model from clearing the window properties on navigation, to replacing an inner window. This is necessary to safely perform security checks using the lexical global object.

This first step adds a new class called JSDOMWindowWrapper, which wraps
the real window object. All JS calls that would go to the window object
now go to it, which it forwards to the current inner window. To accomplish
this, the wrapper window is used as the ThisValue wherever the window was used
before.

  • WebCore.base.exp:
  • WebCore.xcodeproj/project.pbxproj:
  • bindings/js/JSDOMWindowBase.cpp: (WebCore::JSDOMWindowBase::JSDOMWindowBase): (WebCore::JSDOMWindowBase::clear): Reset the wrapper windows prototype too. (WebCore::JSDOMWindowBase::toThisObject): (WebCore::JSDOMWindowBase::wrapper): (WebCore::windowProtoFuncAToB): (WebCore::windowProtoFuncBToA): (WebCore::windowProtoFuncOpen): (WebCore::windowProtoFuncSetTimeout): (WebCore::windowProtoFuncClearTimeout): (WebCore::windowProtoFuncSetInterval): (WebCore::windowProtoFuncAddEventListener): (WebCore::windowProtoFuncRemoveEventListener): (WebCore::windowProtoFuncShowModalDialog): (WebCore::windowProtoFuncNotImplemented): (WebCore::toJS):
  • bindings/js/JSDOMWindowBase.h: Fix to expect the wrapper as the thisObj.
  • bindings/js/JSDOMWindowCustom.cpp: (WebCore::JSDOMWindow::postMessage): (WebCore::toDOMWindow):
  • bindings/js/JSDOMWindowWrapper.cpp: Added. (WebCore::): (WebCore::JSDOMWindowWrapper::JSDOMWindowWrapper): (WebCore::JSDOMWindowWrapper::~JSDOMWindowWrapper): (WebCore::JSDOMWindowWrapper::mark): (WebCore::JSDOMWindowWrapper::className): (WebCore::JSDOMWindowWrapper::getOwnPropertySlot): (WebCore::JSDOMWindowWrapper::put): (WebCore::JSDOMWindowWrapper::deleteProperty): (WebCore::JSDOMWindowWrapper::getPropertyNames): (WebCore::JSDOMWindowWrapper::getPropertyAttributes): (WebCore::JSDOMWindowWrapper::defineGetter): (WebCore::JSDOMWindowWrapper::defineSetter): (WebCore::JSDOMWindowWrapper::lookupGetter): (WebCore::JSDOMWindowWrapper::lookupSetter): (WebCore::JSDOMWindowWrapper::toGlobalObject): (WebCore::JSDOMWindowWrapper::impl): (WebCore::JSDOMWindowWrapper::disconnectFrame): (WebCore::JSDOMWindowWrapper::clear): (WebCore::toJS):
  • bindings/js/JSDOMWindowWrapper.h: Added. (WebCore::JSDOMWindowWrapper::innerWindow): (WebCore::JSDOMWindowWrapper::setInnerWindow): (WebCore::JSDOMWindowWrapper::classInfo): Forward methods to the innerWindow.
  • bindings/js/JSHTMLDocumentCustom.cpp: (WebCore::JSHTMLDocument::open):
  • bindings/js/ScheduledAction.cpp: (WebCore::ScheduledAction::execute):
  • bindings/js/kjs_events.cpp: (WebCore::JSAbstractEventListener::handleEvent):
  • bindings/js/kjs_proxy.cpp: (WebCore::KJSProxy::~KJSProxy): (WebCore::KJSProxy::evaluate): (WebCore::KJSProxy::clear): (WebCore::KJSProxy::initScript): (WebCore::KJSProxy::clearDocumentWrapper): (WebCore::KJSProxy::processingUserGesture): (WebCore::KJSProxy::attachDebugger):
  • bindings/js/kjs_proxy.h: (WebCore::KJSProxy::haveWindowWrapper): (WebCore::KJSProxy::windowWrapper): (WebCore::KJSProxy::globalObject): (WebCore::KJSProxy::initScriptIfNeeded): Hold onto the wrapper window instead of global object. As a convenience, keep the globalObject() as a forward to the inner window.
  • bindings/objc/DOMUtility.mm: (KJS::createDOMWrapper):
  • bindings/scripts/CodeGeneratorJS.pm:
  • dom/Document.cpp: (WebCore::Document::domWindow):
  • dom/Document.h: (WebCore::Document::defaultView):
  • loader/FrameLoader.cpp: (WebCore::FrameLoader::dispatchWindowObjectAvailable):
  • page/DOMWindow.idl:
  • page/Frame.cpp: (WebCore::Frame::~Frame): (WebCore::Frame::pageDestroyed):
  • Property svn:eol-style set to native
File size: 12.2 KB
Line 
1// -*- mode: c++; c-basic-offset: 4 -*-
2/*
3 * Copyright (C) 2006, 2007, 2008 Apple 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 "config.h"
28#include "JSObjectRef.h"
29
30#include "APICast.h"
31#include "JSCallbackConstructor.h"
32#include "JSCallbackFunction.h"
33#include "JSCallbackObject.h"
34#include "JSClassRef.h"
35#include "JSGlobalObject.h"
36#include "JSValueRef.h"
37#include "PropertyNameArray.h"
38#include "function.h"
39#include "function_object.h"
40#include "identifier.h"
41#include "internal.h"
42#include "object.h"
43#include "object_object.h"
44#include <wtf/Platform.h>
45
46using namespace KJS;
47
48JSClassRef JSClassCreate(const JSClassDefinition* definition)
49{
50 JSLock lock;
51 RefPtr<OpaqueJSClass> jsClass = (definition->attributes & kJSClassAttributeNoAutomaticPrototype)
52 ? OpaqueJSClass::createNoAutomaticPrototype(definition)
53 : OpaqueJSClass::create(definition);
54
55 return jsClass.release().releaseRef();
56}
57
58JSClassRef JSClassRetain(JSClassRef jsClass)
59{
60 JSLock lock;
61 jsClass->ref();
62 return jsClass;
63}
64
65void JSClassRelease(JSClassRef jsClass)
66{
67 JSLock lock;
68 jsClass->deref();
69}
70
71JSObjectRef JSObjectMake(JSContextRef ctx, JSClassRef jsClass, void* data)
72{
73 JSLock lock;
74 ExecState* exec = toJS(ctx);
75
76 if (!jsClass)
77 return toRef(new JSObject(exec->lexicalGlobalObject()->objectPrototype())); // slightly more efficient
78
79 JSValue* jsPrototype = jsClass->prototype(ctx);
80 if (!jsPrototype)
81 jsPrototype = exec->lexicalGlobalObject()->objectPrototype();
82
83 return toRef(new JSCallbackObject<JSObject>(exec, jsClass, jsPrototype, data));
84}
85
86JSObjectRef JSObjectMakeFunctionWithCallback(JSContextRef ctx, JSStringRef name, JSObjectCallAsFunctionCallback callAsFunction)
87{
88 JSLock lock;
89 ExecState* exec = toJS(ctx);
90 Identifier nameID = name ? Identifier(toJS(name)) : Identifier("anonymous");
91
92 return toRef(new JSCallbackFunction(exec, callAsFunction, nameID));
93}
94
95JSObjectRef JSObjectMakeConstructor(JSContextRef ctx, JSClassRef jsClass, JSObjectCallAsConstructorCallback callAsConstructor)
96{
97 JSLock lock;
98 ExecState* exec = toJS(ctx);
99
100 JSValue* jsPrototype = jsClass
101 ? jsClass->prototype(ctx)
102 : exec->dynamicGlobalObject()->objectPrototype();
103
104 JSCallbackConstructor* constructor = new JSCallbackConstructor(exec, jsClass, callAsConstructor);
105 constructor->putDirect(exec->propertyNames().prototype, jsPrototype, DontEnum | DontDelete | ReadOnly);
106 return toRef(constructor);
107}
108
109JSObjectRef JSObjectMakeFunction(JSContextRef ctx, JSStringRef name, unsigned parameterCount, const JSStringRef parameterNames[], JSStringRef body, JSStringRef sourceURL, int startingLineNumber, JSValueRef* exception)
110{
111 JSLock lock;
112
113 ExecState* exec = toJS(ctx);
114 UString::Rep* bodyRep = toJS(body);
115 UString::Rep* sourceURLRep = sourceURL ? toJS(sourceURL) : &UString::Rep::null;
116
117 Identifier nameID = name ? Identifier(toJS(name)) : Identifier("anonymous");
118
119 List args;
120 for (unsigned i = 0; i < parameterCount; i++)
121 args.append(jsString(UString(toJS(parameterNames[i]))));
122 args.append(jsString(UString(bodyRep)));
123
124 JSObject* result = exec->dynamicGlobalObject()->functionConstructor()->construct(exec, args, nameID, UString(sourceURLRep), startingLineNumber);
125 if (exec->hadException()) {
126 if (exception)
127 *exception = toRef(exec->exception());
128 exec->clearException();
129 result = 0;
130 }
131 return toRef(result);
132}
133
134JSValueRef JSObjectGetPrototype(JSContextRef, JSObjectRef object)
135{
136 JSObject* jsObject = toJS(object);
137 return toRef(jsObject->prototype());
138}
139
140void JSObjectSetPrototype(JSContextRef, JSObjectRef object, JSValueRef value)
141{
142 JSObject* jsObject = toJS(object);
143 JSValue* jsValue = toJS(value);
144
145 jsObject->setPrototype(jsValue);
146}
147
148bool JSObjectHasProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName)
149{
150 JSLock lock;
151 ExecState* exec = toJS(ctx);
152 JSObject* jsObject = toJS(object);
153 UString::Rep* nameRep = toJS(propertyName);
154
155 return jsObject->hasProperty(exec, Identifier(nameRep));
156}
157
158JSValueRef JSObjectGetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
159{
160 JSLock lock;
161 ExecState* exec = toJS(ctx);
162 JSObject* jsObject = toJS(object);
163 UString::Rep* nameRep = toJS(propertyName);
164
165 JSValue* jsValue = jsObject->get(exec, Identifier(nameRep));
166 if (exec->hadException()) {
167 if (exception)
168 *exception = toRef(exec->exception());
169 exec->clearException();
170 }
171 return toRef(jsValue);
172}
173
174void JSObjectSetProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSPropertyAttributes attributes, JSValueRef* exception)
175{
176 JSLock lock;
177 ExecState* exec = toJS(ctx);
178 JSObject* jsObject = toJS(object);
179 Identifier name(toJS(propertyName));
180 JSValue* jsValue = toJS(value);
181
182 // If non-0 attributes were passed, we may need to use a lower-level call than
183 // the normal JSObject::put. If there is no existing property, then use either
184 // initializeVariable or putDirect instead, since those have the power to set attributes.
185 if (attributes && !jsObject->hasProperty(exec, name)) {
186 if (jsObject->isGlobalObject())
187 static_cast<JSGlobalObject*>(jsObject)->initializeVariable(exec, name, jsValue, attributes);
188 else
189 jsObject->putDirect(name, jsValue, attributes);
190 return;
191 }
192
193 jsObject->put(exec, name, jsValue);
194 if (exec->hadException()) {
195 if (exception)
196 *exception = toRef(exec->exception());
197 exec->clearException();
198 }
199}
200
201JSValueRef JSObjectGetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned propertyIndex, JSValueRef* exception)
202{
203 JSLock lock;
204 ExecState* exec = toJS(ctx);
205 JSObject* jsObject = toJS(object);
206
207 JSValue* jsValue = jsObject->get(exec, propertyIndex);
208 if (exec->hadException()) {
209 if (exception)
210 *exception = toRef(exec->exception());
211 exec->clearException();
212 }
213 return toRef(jsValue);
214}
215
216
217void JSObjectSetPropertyAtIndex(JSContextRef ctx, JSObjectRef object, unsigned propertyIndex, JSValueRef value, JSValueRef* exception)
218{
219 JSLock lock;
220 ExecState* exec = toJS(ctx);
221 JSObject* jsObject = toJS(object);
222 JSValue* jsValue = toJS(value);
223
224 jsObject->put(exec, propertyIndex, jsValue);
225 if (exec->hadException()) {
226 if (exception)
227 *exception = toRef(exec->exception());
228 exec->clearException();
229 }
230}
231
232bool JSObjectDeleteProperty(JSContextRef ctx, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
233{
234 JSLock lock;
235 ExecState* exec = toJS(ctx);
236 JSObject* jsObject = toJS(object);
237 UString::Rep* nameRep = toJS(propertyName);
238
239 bool result = jsObject->deleteProperty(exec, Identifier(nameRep));
240 if (exec->hadException()) {
241 if (exception)
242 *exception = toRef(exec->exception());
243 exec->clearException();
244 }
245 return result;
246}
247
248void* JSObjectGetPrivate(JSObjectRef object)
249{
250 JSObject* jsObject = toJS(object);
251
252 if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::info))
253 return static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->getPrivate();
254 else if (jsObject->inherits(&JSCallbackObject<JSObject>::info))
255 return static_cast<JSCallbackObject<JSObject>*>(jsObject)->getPrivate();
256
257 return 0;
258}
259
260bool JSObjectSetPrivate(JSObjectRef object, void* data)
261{
262 JSObject* jsObject = toJS(object);
263
264 if (jsObject->inherits(&JSCallbackObject<JSGlobalObject>::info)) {
265 static_cast<JSCallbackObject<JSGlobalObject>*>(jsObject)->setPrivate(data);
266 return true;
267 } else if (jsObject->inherits(&JSCallbackObject<JSObject>::info)) {
268 static_cast<JSCallbackObject<JSObject>*>(jsObject)->setPrivate(data);
269 return true;
270 }
271
272 return false;
273}
274
275bool JSObjectIsFunction(JSContextRef, JSObjectRef object)
276{
277 JSObject* jsObject = toJS(object);
278 return jsObject->implementsCall();
279}
280
281JSValueRef JSObjectCallAsFunction(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
282{
283 JSLock lock;
284 ExecState* exec = toJS(ctx);
285 JSObject* jsObject = toJS(object);
286 JSObject* jsThisObject = toJS(thisObject);
287
288 if (!jsThisObject)
289 jsThisObject = exec->globalThisValue();
290
291 List argList;
292 for (size_t i = 0; i < argumentCount; i++)
293 argList.append(toJS(arguments[i]));
294
295 JSValueRef result = toRef(jsObject->call(exec, jsThisObject, argList)); // returns NULL if object->implementsCall() is false
296 if (exec->hadException()) {
297 if (exception)
298 *exception = toRef(exec->exception());
299 exec->clearException();
300 result = 0;
301 }
302 return result;
303}
304
305bool JSObjectIsConstructor(JSContextRef, JSObjectRef object)
306{
307 JSObject* jsObject = toJS(object);
308 return jsObject->implementsConstruct();
309}
310
311JSObjectRef JSObjectCallAsConstructor(JSContextRef ctx, JSObjectRef object, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
312{
313 JSLock lock;
314 ExecState* exec = toJS(ctx);
315 JSObject* jsObject = toJS(object);
316
317 List argList;
318 for (size_t i = 0; i < argumentCount; i++)
319 argList.append(toJS(arguments[i]));
320
321 JSObjectRef result = toRef(jsObject->construct(exec, argList)); // returns NULL if object->implementsCall() is false
322 if (exec->hadException()) {
323 if (exception)
324 *exception = toRef(exec->exception());
325 exec->clearException();
326 result = 0;
327 }
328 return result;
329}
330
331struct OpaqueJSPropertyNameArray
332{
333 OpaqueJSPropertyNameArray() : refCount(0)
334 {
335 }
336
337 unsigned refCount;
338 PropertyNameArray array;
339};
340
341JSPropertyNameArrayRef JSObjectCopyPropertyNames(JSContextRef ctx, JSObjectRef object)
342{
343 JSLock lock;
344 JSObject* jsObject = toJS(object);
345 ExecState* exec = toJS(ctx);
346
347 JSPropertyNameArrayRef propertyNames = new OpaqueJSPropertyNameArray();
348 jsObject->getPropertyNames(exec, propertyNames->array);
349
350 return JSPropertyNameArrayRetain(propertyNames);
351}
352
353JSPropertyNameArrayRef JSPropertyNameArrayRetain(JSPropertyNameArrayRef array)
354{
355 JSLock lock;
356 ++array->refCount;
357 return array;
358}
359
360void JSPropertyNameArrayRelease(JSPropertyNameArrayRef array)
361{
362 JSLock lock;
363 if (--array->refCount == 0)
364 delete array;
365}
366
367size_t JSPropertyNameArrayGetCount(JSPropertyNameArrayRef array)
368{
369 return array->array.size();
370}
371
372JSStringRef JSPropertyNameArrayGetNameAtIndex(JSPropertyNameArrayRef array, size_t index)
373{
374 return toRef(array->array[static_cast<unsigned>(index)].ustring().rep());
375}
376
377void JSPropertyNameAccumulatorAddName(JSPropertyNameAccumulatorRef array, JSStringRef propertyName)
378{
379 JSLock lock;
380 PropertyNameArray* propertyNames = toJS(array);
381 UString::Rep* rep = toJS(propertyName);
382
383 propertyNames->add(Identifier(rep));
384}
Note: See TracBrowser for help on using the repository browser.