bool CrossCompartmentWrapper::nativeCall(JSContext *cx, JSObject *wrapper, Class *clasp, Native native, CallArgs srcArgs) { JS_ASSERT_IF(!srcArgs.calleev().isUndefined(), srcArgs.callee().toFunction()->native() == native || srcArgs.callee().toFunction()->native() == js_generic_native_method_dispatcher); JS_ASSERT(&srcArgs.thisv().toObject() == wrapper); JS_ASSERT(!UnwrapObject(wrapper)->isCrossCompartmentWrapper()); JSObject *wrapped = wrappedObject(wrapper); AutoCompartment call(cx, wrapped); if (!call.enter()) return false; InvokeArgsGuard dstArgs; if (!cx->stack.pushInvokeArgs(cx, srcArgs.length(), &dstArgs)) return false; Value *src = srcArgs.base(); Value *srcend = srcArgs.array() + srcArgs.length(); Value *dst = dstArgs.base(); for (; src != srcend; ++src, ++dst) { *dst = *src; if (!call.destination->wrap(cx, dst)) return false; } if (!Wrapper::nativeCall(cx, wrapper, clasp, native, dstArgs)) return false; dstArgs.pop(); call.leave(); srcArgs.rval() = dstArgs.rval(); return call.origin->wrap(cx, &srcArgs.rval()); }
bool CrossCompartmentWrapper::nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl impl, CallArgs srcArgs) { Rooted<JSObject*> wrapper(cx, &srcArgs.thisv().toObject()); JS_ASSERT(srcArgs.thisv().isMagic(JS_IS_CONSTRUCTING) || !UnwrapObject(wrapper)->isCrossCompartmentWrapper()); RootedObject wrapped(cx, wrappedObject(wrapper)); { AutoCompartment call(cx, wrapped); InvokeArgsGuard dstArgs; if (!cx->stack.pushInvokeArgs(cx, srcArgs.length(), &dstArgs)) return false; Value *src = srcArgs.base(); Value *srcend = srcArgs.array() + srcArgs.length(); Value *dst = dstArgs.base(); for (; src < srcend; ++src, ++dst) { *dst = *src; if (!cx->compartment->wrap(cx, dst)) return false; } if (!CallNonGenericMethod(cx, test, impl, dstArgs)) return false; srcArgs.rval().set(dstArgs.rval()); dstArgs.pop(); } return cx->compartment->wrap(cx, srcArgs.rval().address()); }
bool CrossCompartmentWrapper::nativeCall(JSContext *cx, JSObject *wrapper, Class *clasp, Native native, CallArgs srcArgs) { JS_ASSERT(srcArgs.thisv().isMagic(JS_IS_CONSTRUCTING) || &srcArgs.thisv().toObject() == wrapper); JS_ASSERT(!UnwrapObject(wrapper)->isCrossCompartmentWrapper()); JSObject *wrapped = wrappedObject(wrapper); AutoCompartment call(cx, wrapped); if (!call.enter()) return false; InvokeArgsGuard dstArgs; if (!cx->stack.pushInvokeArgs(cx, srcArgs.length(), &dstArgs)) return false; Value *src = srcArgs.base(); Value *srcend = srcArgs.array() + srcArgs.length(); Value *dst = dstArgs.base(); for (; src != srcend; ++src, ++dst) { *dst = *src; if (!call.destination->wrap(cx, dst)) return false; } if (!CallJSNative(cx, native, dstArgs)) return false; srcArgs.rval() = dstArgs.rval(); dstArgs.pop(); call.leave(); return cx->compartment->wrap(cx, &srcArgs.rval()); }
bool CrossCompartmentWrapper::nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl impl, CallArgs srcArgs) { RootedObject wrapper(cx, &srcArgs.thisv().toObject()); JS_ASSERT(srcArgs.thisv().isMagic(JS_IS_CONSTRUCTING) || !UncheckedUnwrap(wrapper)->isCrossCompartmentWrapper()); RootedObject wrapped(cx, wrappedObject(wrapper)); { AutoCompartment call(cx, wrapped); InvokeArgsGuard dstArgs; if (!cx->stack.pushInvokeArgs(cx, srcArgs.length(), &dstArgs)) return false; Value *src = srcArgs.base(); Value *srcend = srcArgs.array() + srcArgs.length(); Value *dst = dstArgs.base(); RootedValue source(cx); for (; src < srcend; ++src, ++dst) { source = *src; if (!cx->compartment->wrap(cx, &source)) return false; *dst = source.get(); // Handle |this| specially. When we rewrap on the other side of the // membrane, we might apply a same-compartment security wrapper that // will stymie this whole process. If that happens, unwrap the wrapper. // This logic can go away when same-compartment security wrappers go away. if ((src == srcArgs.base() + 1) && dst->isObject()) { RootedObject thisObj(cx, &dst->toObject()); if (thisObj->isWrapper() && !Wrapper::wrapperHandler(thisObj)->isSafeToUnwrap()) { JS_ASSERT(!IsCrossCompartmentWrapper(thisObj)); *dst = ObjectValue(*Wrapper::wrappedObject(thisObj)); } } } if (!CallNonGenericMethod(cx, test, impl, dstArgs)) return false; srcArgs.rval().set(dstArgs.rval()); dstArgs.pop(); } return cx->compartment->wrap(cx, srcArgs.rval()); }