2 * Copyright (C) 2007-2010, 2016 Apple Inc. All rights reserved.
3 * Copyright (C) 2011 Google Inc. All rights reserved.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
22 #include "JSDOMWindowCustom.h"
24 #include "DOMWindowIndexedDatabase.h"
26 #include "HTMLCollection.h"
27 #include "HTMLDocument.h"
29 #include "JSEventListener.h"
30 #include "JSHTMLAudioElement.h"
31 #include "JSHTMLCollection.h"
32 #include "JSHTMLOptionElement.h"
33 #include "JSIDBFactory.h"
34 #include "JSImageConstructor.h"
35 #include "JSMessagePortCustom.h"
38 #include "RuntimeEnabledFeatures.h"
39 #include "ScheduledAction.h"
42 #if ENABLE(IOS_TOUCH_EVENTS)
43 #include "JSTouchConstructorIOS.h"
44 #include "JSTouchListConstructorIOS.h"
48 #include "JSAudioContext.h"
51 #if ENABLE(WEB_SOCKETS)
52 #include "JSWebSocket.h"
55 #if ENABLE(USER_MESSAGE_HANDLERS)
56 #include "JSWebKitNamespace.h"
63 void JSDOMWindow::visitAdditionalChildren(SlotVisitor& visitor)
65 if (Frame* frame = wrapped().frame())
66 visitor.addOpaqueRoot(frame);
69 #if ENABLE(USER_MESSAGE_HANDLERS)
70 static EncodedJSValue jsDOMWindowWebKit(ExecState* exec, EncodedJSValue thisValue, PropertyName)
72 JSDOMWindow* castedThis = toJSDOMWindow(JSValue::decode(thisValue));
73 if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, castedThis->wrapped()))
74 return JSValue::encode(jsUndefined());
75 return JSValue::encode(toJS(exec, castedThis->globalObject(), castedThis->wrapped().webkitNamespace()));
79 static bool jsDOMWindowGetOwnPropertySlotRestrictedAccess(JSDOMWindow* thisObject, Frame* frame, ExecState* exec, PropertyName propertyName, PropertySlot& slot, String& errorMessage)
81 // Allow access to toString() cross-domain, but always Object.prototype.toString.
82 if (propertyName == exec->propertyNames().toString) {
83 slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, nonCachingStaticFunctionGetter<objectProtoFuncToString, 0>);
87 // We don't want any properties other than "close" and "closed" on a frameless window
88 // (i.e. one whose page got closed, or whose iframe got removed).
89 // FIXME: This handling for frameless windows duplicates similar behaviour for cross-origin
90 // access below; we should try to find a way to merge the two.
92 if (propertyName == exec->propertyNames().closed) {
93 slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, jsDOMWindowClosed);
96 if (propertyName == exec->propertyNames().close) {
97 slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, nonCachingStaticFunctionGetter<jsDOMWindowInstanceFunctionClose, 0>);
101 // FIXME: We should have a message here that explains why the property access/function call was
107 // These are the functions we allow access to cross-origin (DoNotCheckSecurity in IDL).
108 // Always provide the original function, on a fresh uncached function object.
109 if (propertyName == exec->propertyNames().blur) {
110 slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, nonCachingStaticFunctionGetter<jsDOMWindowInstanceFunctionBlur, 0>);
113 if (propertyName == exec->propertyNames().close) {
114 slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, nonCachingStaticFunctionGetter<jsDOMWindowInstanceFunctionClose, 0>);
117 if (propertyName == exec->propertyNames().focus) {
118 slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, nonCachingStaticFunctionGetter<jsDOMWindowInstanceFunctionFocus, 0>);
121 if (propertyName == exec->propertyNames().postMessage) {
122 slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, nonCachingStaticFunctionGetter<jsDOMWindowInstanceFunctionPostMessage, 2>);
126 // When accessing cross-origin known Window properties, we always use the original property getter,
127 // even if the property was removed / redefined. As of early 2016, this matches Firefox and Chrome's
129 if (auto* entry = JSDOMWindow::info()->staticPropHashTable->entry(propertyName)) {
130 // Only allow access to these specific properties.
131 if (propertyName == exec->propertyNames().location
132 || propertyName == exec->propertyNames().closed
133 || propertyName == exec->propertyNames().length
134 || propertyName == exec->propertyNames().self
135 || propertyName == exec->propertyNames().window
136 || propertyName == exec->propertyNames().frames
137 || propertyName == exec->propertyNames().opener
138 || propertyName == exec->propertyNames().parent
139 || propertyName == exec->propertyNames().top) {
140 slot.setCacheableCustom(thisObject, ReadOnly | DontDelete | DontEnum, entry->propertyGetter());
144 // For any other entries in the static property table, deny access. (Early return also prevents
145 // named getter from returning frames with matching names - this seems a little questionable, see
146 // FIXME comment on prototype search below.)
147 thisObject->printErrorMessage(errorMessage);
152 // Do prototype lookup early so that functions and attributes in the prototype can have
153 // precedence over the index and name getters.
154 // FIXME: This seems like a silly idea. It only serves to suppress named property access
155 // to frames that happen to have names corresponding to properties on the prototype.
156 // This seems to only serve to leak some information cross-origin.
157 JSValue proto = thisObject->getPrototypeDirect();
158 if (proto.isObject() && asObject(proto)->getPropertySlot(exec, propertyName, slot)) {
159 thisObject->printErrorMessage(errorMessage);
164 // Check for child frames by name before built-in properties to match Mozilla. This does
165 // not match IE, but some sites end up naming frames things that conflict with window
166 // properties that are in Moz but not IE. Since we have some of these, we have to do it
168 if (auto* scopedChild = frame->tree().scopedChild(propertyNameToAtomicString(propertyName))) {
169 slot.setValue(thisObject, ReadOnly | DontDelete | DontEnum, toJS(exec, scopedChild->document()->domWindow()));
173 thisObject->printErrorMessage(errorMessage);
178 static bool jsDOMWindowGetOwnPropertySlotNamedItemGetter(JSDOMWindow* thisObject, Frame& frame, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
180 JSValue proto = thisObject->getPrototypeDirect();
181 if (proto.isObject() && asObject(proto)->hasProperty(exec, propertyName))
184 // Check for child frames by name before built-in properties to match Mozilla. This does
185 // not match IE, but some sites end up naming frames things that conflict with window
186 // properties that are in Moz but not IE. Since we have some of these, we have to do it
188 if (auto* scopedChild = frame.tree().scopedChild(propertyNameToAtomicString(propertyName))) {
189 slot.setValue(thisObject, ReadOnly | DontDelete | DontEnum, toJS(exec, scopedChild->document()->domWindow()));
193 // FIXME: Search the whole frame hierarchy somewhere around here.
194 // We need to test the correct priority order.
196 // Allow shortcuts like 'Image1' instead of document.images.Image1
197 Document* document = frame.document();
198 if (is<HTMLDocument>(*document)) {
199 auto& htmlDocument = downcast<HTMLDocument>(*document);
200 auto* atomicPropertyName = propertyName.publicName();
201 if (atomicPropertyName && htmlDocument.hasWindowNamedItem(*atomicPropertyName)) {
203 if (UNLIKELY(htmlDocument.windowNamedItemContainsMultipleElements(*atomicPropertyName))) {
204 Ref<HTMLCollection> collection = document->windowNamedItems(atomicPropertyName);
205 ASSERT(collection->length() > 1);
206 namedItem = toJS(exec, thisObject->globalObject(), collection.ptr());
208 namedItem = toJS(exec, thisObject->globalObject(), htmlDocument.windowNamedItem(*atomicPropertyName));
209 slot.setValue(thisObject, ReadOnly | DontDelete | DontEnum, namedItem);
217 // Property access sequence is:
218 // (1) indexed properties,
219 // (2) regular own properties,
220 // (3) named properties (in fact, these shouldn't be on the window, should be on the NPO).
221 bool JSDOMWindow::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
223 // (1) First, indexed properties.
224 // Hand off all indexed access to getOwnPropertySlotByIndex, which supports the indexed getter.
225 if (Optional<unsigned> index = parseIndex(propertyName))
226 return getOwnPropertySlotByIndex(object, exec, index.value(), slot);
228 auto* thisObject = jsCast<JSDOMWindow*>(object);
229 auto* frame = thisObject->wrapped().frame();
231 // Hand off all cross-domain/frameless access to jsDOMWindowGetOwnPropertySlotRestrictedAccess.
233 if (!frame || !shouldAllowAccessToDOMWindow(exec, thisObject->wrapped(), errorMessage))
234 return jsDOMWindowGetOwnPropertySlotRestrictedAccess(thisObject, frame, exec, propertyName, slot, errorMessage);
236 // FIXME: this need more explanation.
237 // (Particularly, is it correct that this exists here but not in getOwnPropertySlotByIndex?)
238 slot.setWatchpointSet(thisObject->m_windowCloseWatchpoints);
240 if (propertyName == exec->propertyNames().showModalDialog) {
241 if (Base::getOwnPropertySlot(thisObject, exec, propertyName, slot))
243 if (!DOMWindow::canShowModalDialog(frame))
244 return jsDOMWindowGetOwnPropertySlotNamedItemGetter(thisObject, *frame, exec, propertyName, slot);
247 // (2) Regular own properties.
248 if (getStaticPropertySlot<JSDOMWindow, Base>(exec, *JSDOMWindow::info()->staticPropHashTable, thisObject, propertyName, slot))
251 #if ENABLE(USER_MESSAGE_HANDLERS)
252 if (propertyName == exec->propertyNames().webkit && thisObject->wrapped().shouldHaveWebKitNamespaceForWorld(thisObject->world())) {
253 slot.setCacheableCustom(thisObject, DontDelete | ReadOnly, jsDOMWindowWebKit);
258 // (3) Finally, named properties.
259 // Really, this should just be 'return false;' - these should all be on the NPO.
260 return jsDOMWindowGetOwnPropertySlotNamedItemGetter(thisObject, *frame, exec, propertyName, slot);
263 // Property access sequence is:
264 // (1) indexed properties,
265 // (2) regular own properties,
266 // (3) named properties (in fact, these shouldn't be on the window, should be on the NPO).
267 bool JSDOMWindow::getOwnPropertySlotByIndex(JSObject* object, ExecState* exec, unsigned index, PropertySlot& slot)
269 auto* thisObject = jsCast<JSDOMWindow*>(object);
270 auto* frame = thisObject->wrapped().frame();
272 // Indexed getters take precendence over regular properties, so caching would be invalid.
273 slot.disableCaching();
275 // (1) First, indexed properties.
276 // These are also allowed cross-orgin, so come before the access check.
277 if (frame && index < frame->tree().scopedChildCount()) {
278 slot.setValue(thisObject, ReadOnly | DontDelete | DontEnum, toJS(exec, frame->tree().scopedChild(index)->document()->domWindow()));
282 // Hand off all cross-domain/frameless access to jsDOMWindowGetOwnPropertySlotRestrictedAccess.
284 if (!frame || !shouldAllowAccessToDOMWindow(exec, thisObject->wrapped(), errorMessage))
285 return jsDOMWindowGetOwnPropertySlotRestrictedAccess(thisObject, frame, exec, Identifier::from(exec, index), slot, errorMessage);
287 // (2) Regular own properties.
288 if (Base::getOwnPropertySlotByIndex(thisObject, exec, index, slot))
291 // (3) Finally, named properties.
292 // Really, this should just be 'return false;' - these should all be on the NPO.
293 return jsDOMWindowGetOwnPropertySlotNamedItemGetter(thisObject, *frame, exec, Identifier::from(exec, index), slot);
296 bool JSDOMWindow::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
298 auto* thisObject = jsCast<JSDOMWindow*>(cell);
299 if (!thisObject->wrapped().frame())
303 if (!shouldAllowAccessToDOMWindow(exec, thisObject->wrapped(), errorMessage)) {
304 // We only allow setting "location" attribute cross-origin.
305 if (propertyName == exec->propertyNames().location) {
306 bool putResult = false;
307 if (lookupPut(exec, propertyName, thisObject, value, *s_info.staticPropHashTable, slot, putResult))
311 thisObject->printErrorMessage(errorMessage);
315 return Base::put(thisObject, exec, propertyName, value, slot);
318 bool JSDOMWindow::putByIndex(JSCell* cell, ExecState* exec, unsigned index, JSValue value, bool shouldThrow)
320 auto* thisObject = jsCast<JSDOMWindow*>(cell);
321 if (!thisObject->wrapped().frame() || !BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->wrapped()))
324 return Base::putByIndex(thisObject, exec, index, value, shouldThrow);
327 bool JSDOMWindow::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName)
329 JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(cell);
330 // Only allow deleting properties by frames in the same origin.
331 if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->wrapped()))
333 return Base::deleteProperty(thisObject, exec, propertyName);
336 bool JSDOMWindow::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned propertyName)
338 JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(cell);
339 // Only allow deleting properties by frames in the same origin.
340 if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->wrapped()))
342 return Base::deletePropertyByIndex(thisObject, exec, propertyName);
345 uint32_t JSDOMWindow::getEnumerableLength(ExecState* exec, JSObject* object)
347 JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(object);
348 // Only allow the window to enumerated by frames in the same origin.
349 if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->wrapped()))
351 return Base::getEnumerableLength(exec, thisObject);
354 void JSDOMWindow::getStructurePropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
356 JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(object);
357 // Only allow the window to enumerated by frames in the same origin.
358 if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->wrapped()))
360 Base::getStructurePropertyNames(thisObject, exec, propertyNames, mode);
363 void JSDOMWindow::getGenericPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
365 JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(object);
366 // Only allow the window to enumerated by frames in the same origin.
367 if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->wrapped()))
369 Base::getGenericPropertyNames(thisObject, exec, propertyNames, mode);
372 void JSDOMWindow::getPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
374 JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(object);
375 // Only allow the window to enumerated by frames in the same origin.
376 if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->wrapped()))
378 Base::getPropertyNames(thisObject, exec, propertyNames, mode);
381 void JSDOMWindow::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
383 JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(object);
384 // Only allow the window to enumerated by frames in the same origin.
385 if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->wrapped()))
387 Base::getOwnPropertyNames(thisObject, exec, propertyNames, mode);
390 bool JSDOMWindow::defineOwnProperty(JSC::JSObject* object, JSC::ExecState* exec, JSC::PropertyName propertyName, const JSC::PropertyDescriptor& descriptor, bool shouldThrow)
392 JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(object);
393 // Only allow defining properties in this way by frames in the same origin, as it allows setters to be introduced.
394 if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->wrapped()))
397 // Don't allow shadowing location using accessor properties.
398 if (descriptor.isAccessorDescriptor() && propertyName == Identifier::fromString(exec, "location"))
401 return Base::defineOwnProperty(thisObject, exec, propertyName, descriptor, shouldThrow);
406 void JSDOMWindow::setLocation(ExecState& state, JSValue value)
408 #if ENABLE(DASHBOARD_SUPPORT)
409 // To avoid breaking old widgets, make "var location =" in a top-level frame create
410 // a property named "location" instead of performing a navigation (<rdar://problem/5688039>).
411 if (Frame* activeFrame = activeDOMWindow(&state).frame()) {
412 if (activeFrame->settings().usesDashboardBackwardCompatibilityMode() && !activeFrame->tree().parent()) {
413 if (BindingSecurity::shouldAllowAccessToDOMWindow(&state, wrapped()))
414 putDirect(state.vm(), Identifier::fromString(&state, "location"), value);
420 String locationString = value.toString(&state)->value(&state);
421 if (state.hadException())
424 if (Location* location = wrapped().location())
425 location->setHref(activeDOMWindow(&state), firstDOMWindow(&state), locationString);
428 JSValue JSDOMWindow::event(ExecState& state) const
430 Event* event = currentEvent();
432 return jsUndefined();
433 return toJS(&state, const_cast<JSDOMWindow*>(this), event);
436 JSValue JSDOMWindow::image(ExecState& state) const
438 return createImageConstructor(state.vm(), *this);
443 JSValue JSDOMWindow::open(ExecState& state)
445 String urlString = valueToStringWithUndefinedOrNullCheck(&state, state.argument(0));
446 if (state.hadException())
447 return jsUndefined();
448 AtomicString frameName = state.argument(1).isUndefinedOrNull() ? "_blank" : state.argument(1).toString(&state)->value(&state);
449 if (state.hadException())
450 return jsUndefined();
451 String windowFeaturesString = valueToStringWithUndefinedOrNullCheck(&state, state.argument(2));
452 if (state.hadException())
453 return jsUndefined();
455 RefPtr<DOMWindow> openedWindow = wrapped().open(urlString, frameName, windowFeaturesString, activeDOMWindow(&state), firstDOMWindow(&state));
457 return jsUndefined();
458 return toJS(&state, openedWindow.get());
461 class DialogHandler {
463 explicit DialogHandler(ExecState& exec)
468 void dialogCreated(DOMWindow&);
469 JSValue returnValue() const;
473 RefPtr<Frame> m_frame;
476 inline void DialogHandler::dialogCreated(DOMWindow& dialog)
478 m_frame = dialog.frame();
480 // FIXME: This looks like a leak between the normal world and an isolated
481 // world if dialogArguments comes from an isolated world.
482 JSDOMWindow* globalObject = toJSDOMWindow(m_frame.get(), normalWorld(m_exec.vm()));
483 if (JSValue dialogArguments = m_exec.argument(1))
484 globalObject->putDirect(m_exec.vm(), Identifier::fromString(&m_exec, "dialogArguments"), dialogArguments);
487 inline JSValue DialogHandler::returnValue() const
489 JSDOMWindow* globalObject = toJSDOMWindow(m_frame.get(), normalWorld(m_exec.vm()));
491 return jsUndefined();
492 Identifier identifier = Identifier::fromString(&m_exec, "returnValue");
493 PropertySlot slot(globalObject, PropertySlot::InternalMethodType::Get);
494 if (!JSGlobalObject::getOwnPropertySlot(globalObject, &m_exec, identifier, slot))
495 return jsUndefined();
496 return slot.getValue(&m_exec, identifier);
499 JSValue JSDOMWindow::showModalDialog(ExecState& state)
501 if (UNLIKELY(state.argumentCount() < 1))
502 return state.vm().throwException(&state, createNotEnoughArgumentsError(&state));
504 String urlString = valueToStringWithUndefinedOrNullCheck(&state, state.argument(0));
505 if (state.hadException())
506 return jsUndefined();
507 String dialogFeaturesString = valueToStringWithUndefinedOrNullCheck(&state, state.argument(2));
508 if (state.hadException())
509 return jsUndefined();
511 DialogHandler handler(state);
513 wrapped().showModalDialog(urlString, dialogFeaturesString, activeDOMWindow(&state), firstDOMWindow(&state), [&handler](DOMWindow& dialog) {
514 handler.dialogCreated(dialog);
517 return handler.returnValue();
520 static JSValue handlePostMessage(DOMWindow& impl, ExecState& state)
522 MessagePortArray messagePorts;
523 ArrayBufferArray arrayBuffers;
525 // This function has variable arguments and can be:
527 // postMessage(message, targetOrigin)
528 // postMessage(message, targetOrigin, {sequence of transferrables})
529 // Legacy non-standard implementations in webkit allowed:
530 // postMessage(message, {sequence of transferrables}, targetOrigin);
531 int targetOriginArgIndex = 1;
532 if (state.argumentCount() > 2) {
533 int transferablesArgIndex = 2;
534 if (state.argument(2).isString()) {
535 targetOriginArgIndex = 2;
536 transferablesArgIndex = 1;
538 fillMessagePortArray(state, state.argument(transferablesArgIndex), messagePorts, arrayBuffers);
540 if (state.hadException())
541 return jsUndefined();
543 RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(&state, state.argument(0),
547 if (state.hadException())
548 return jsUndefined();
550 String targetOrigin = valueToStringWithUndefinedOrNullCheck(&state, state.argument(targetOriginArgIndex));
551 if (state.hadException())
552 return jsUndefined();
554 ExceptionCode ec = 0;
555 impl.postMessage(message.release(), &messagePorts, targetOrigin, callerDOMWindow(&state), ec);
556 setDOMException(&state, ec);
558 return jsUndefined();
561 JSValue JSDOMWindow::postMessage(ExecState& state)
563 return handlePostMessage(wrapped(), state);
566 JSValue JSDOMWindow::setTimeout(ExecState& state)
568 ContentSecurityPolicy* contentSecurityPolicy = wrapped().document() ? wrapped().document()->contentSecurityPolicy() : nullptr;
569 std::unique_ptr<ScheduledAction> action = ScheduledAction::create(&state, globalObject()->world(), contentSecurityPolicy);
570 if (state.hadException())
571 return jsUndefined();
576 int delay = state.argument(1).toInt32(&state);
578 ExceptionCode ec = 0;
579 int result = wrapped().setTimeout(WTFMove(action), delay, ec);
580 setDOMException(&state, ec);
582 return jsNumber(result);
585 JSValue JSDOMWindow::setInterval(ExecState& state)
587 ContentSecurityPolicy* contentSecurityPolicy = wrapped().document() ? wrapped().document()->contentSecurityPolicy() : nullptr;
588 std::unique_ptr<ScheduledAction> action = ScheduledAction::create(&state, globalObject()->world(), contentSecurityPolicy);
589 if (state.hadException())
590 return jsUndefined();
591 int delay = state.argument(1).toInt32(&state);
596 ExceptionCode ec = 0;
597 int result = wrapped().setInterval(WTFMove(action), delay, ec);
598 setDOMException(&state, ec);
600 return jsNumber(result);
603 DOMWindow* JSDOMWindow::toWrapped(ExecState&, JSValue value)
605 if (!value.isObject())
607 JSObject* object = asObject(value);
608 if (object->inherits(JSDOMWindow::info()))
609 return &jsCast<JSDOMWindow*>(object)->wrapped();
610 if (object->inherits(JSDOMWindowShell::info()))
611 return &jsCast<JSDOMWindowShell*>(object)->wrapped();
615 } // namespace WebCore