NS_IMETHODIMP InsertNodeTransaction::DoTransaction() { if (NS_WARN_IF(!mEditorBase) || NS_WARN_IF(!mContentToInsert) || NS_WARN_IF(!mPointToInsert.IsSet())) { return NS_ERROR_NOT_INITIALIZED; } if (!mPointToInsert.IsSetAndValid()) { // It seems that DOM tree has been changed after first DoTransaction() // and current RedoTranaction() call. if (mPointToInsert.GetChild()) { EditorDOMPoint newPointToInsert(mPointToInsert.GetChild()); if (!newPointToInsert.IsSet()) { // The insertion point has been removed from the DOM tree. // In this case, we should append the node to the container instead. newPointToInsert.SetToEndOf(mPointToInsert.GetContainer()); if (NS_WARN_IF(!newPointToInsert.IsSet())) { return NS_ERROR_FAILURE; } } mPointToInsert = newPointToInsert; } else { mPointToInsert.SetToEndOf(mPointToInsert.GetContainer()); if (NS_WARN_IF(!mPointToInsert.IsSet())) { return NS_ERROR_FAILURE; } } } mEditorBase->MarkNodeDirty(GetAsDOMNode(mContentToInsert)); ErrorResult error; mPointToInsert.GetContainer()->InsertBefore(*mContentToInsert, mPointToInsert.GetChild(), error); error.WouldReportJSException(); if (NS_WARN_IF(error.Failed())) { return error.StealNSResult(); } // Only set selection to insertion point if editor gives permission if (mEditorBase->GetShouldTxnSetSelection()) { RefPtr<Selection> selection = mEditorBase->GetSelection(); if (NS_WARN_IF(!selection)) { return NS_ERROR_FAILURE; } // Place the selection just after the inserted element EditorRawDOMPoint afterInsertedNode(mContentToInsert); DebugOnly<bool> advanced = afterInsertedNode.AdvanceOffset(); NS_WARNING_ASSERTION(advanced, "Failed to advance offset after the inserted node"); selection->Collapse(afterInsertedNode, error); if (NS_WARN_IF(error.Failed())) { error.SuppressException(); } } return NS_OK; }
/* static */ already_AddRefed<Promise> Promise::Constructor(const GlobalObject& aGlobal, JSContext* aCx, PromiseInit& aInit, ErrorResult& aRv) { MOZ_ASSERT(PrefEnabled()); nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.Get()); if (!window) { aRv.Throw(NS_ERROR_UNEXPECTED); return nullptr; } nsRefPtr<Promise> promise = new Promise(window); aInit.Call(promise, *promise->mResolver, aRv, CallbackObject::eRethrowExceptions); aRv.WouldReportJSException(); if (aRv.IsJSException()) { Optional<JS::Handle<JS::Value> > value(aCx); aRv.StealJSException(aCx, &value.Value()); Maybe<JSAutoCompartment> ac; EnterCompartment(ac, aCx, value); promise->mResolver->Reject(aCx, value); } return promise.forget(); }
void WrapperPromiseCallback::Call(const Optional<JS::Handle<JS::Value> >& aValue) { AutoJSContext cx; Maybe<JSAutoCompartment> ac; EnterCompartment(ac, cx, aValue); ErrorResult rv; // If invoking callback threw an exception, run resolver's reject with the // thrown exception as argument and the synchronous flag set. Optional<JS::Handle<JS::Value> > value(cx, mCallback->Call(mNextResolver->GetParentObject(), aValue, rv, CallbackObject::eRethrowExceptions)); rv.WouldReportJSException(); if (rv.Failed() && rv.IsJSException()) { Optional<JS::Handle<JS::Value> > value(cx); rv.StealJSException(cx, &value.Value()); Maybe<JSAutoCompartment> ac2; EnterCompartment(ac2, cx, value); mNextResolver->RejectInternal(cx, value, PromiseResolver::SyncTask); return; } // Otherwise, run resolver's resolve with value and the synchronous flag // set. Maybe<JSAutoCompartment> ac2; EnterCompartment(ac2, cx, value); mNextResolver->ResolveInternal(cx, value, PromiseResolver::SyncTask); }
void WrapperPromiseCallback::Call(const Optional<JS::Handle<JS::Value> >& aValue) { AutoJSContext cx; // FIXME Bug 878849 Maybe<JSAutoCompartment> ac; if (aValue.WasPassed() && aValue.Value().isObject()) { JS::Rooted<JSObject*> rooted(cx, &aValue.Value().toObject()); ac.construct(cx, rooted); } ErrorResult rv; // If invoking callback threw an exception, run resolver's reject with the // thrown exception as argument and the synchronous flag set. Optional<JS::Handle<JS::Value> > value(cx, mCallback->Call(mNextResolver->GetParentObject(), aValue, rv, CallbackObject::eRethrowExceptions)); rv.WouldReportJSException(); if (rv.Failed() && rv.IsJSException()) { Optional<JS::Handle<JS::Value> > value(cx); rv.StealJSException(cx, &value.Value()); mNextResolver->RejectInternal(cx, value, PromiseResolver::SyncTask); return; } // Otherwise, run resolver's resolve with value and the synchronous flag // set. mNextResolver->ResolveInternal(cx, value, PromiseResolver::SyncTask); }
void WrapperPromiseCallback::Call(JS::Handle<JS::Value> aValue) { // AutoCxPusher and co. interact with xpconnect, which crashes on // workers. On workers we'll get the right context from // GetDefaultJSContextForThread(), and since there is only one context, we // don't need to push or pop it from the stack. JSContext* cx = nsContentUtils::GetDefaultJSContextForThread(); Maybe<AutoCxPusher> pusher; if (NS_IsMainThread()) { pusher.construct(cx); } Maybe<JSAutoCompartment> ac; EnterCompartment(ac, cx, aValue); ErrorResult rv; // If invoking callback threw an exception, run resolver's reject with the // thrown exception as argument and the synchronous flag set. JS::Rooted<JS::Value> value(cx, mCallback->Call(mNextPromise->GetParentObject(), aValue, rv, CallbackObject::eRethrowExceptions)); rv.WouldReportJSException(); if (rv.Failed() && rv.IsJSException()) { JS::Rooted<JS::Value> value(cx); rv.StealJSException(cx, &value); Maybe<JSAutoCompartment> ac2; EnterCompartment(ac2, cx, value); mNextPromise->RejectInternal(cx, value, Promise::SyncTask); return; } // Otherwise, run resolver's resolve with value and the synchronous flag // set. Maybe<JSAutoCompartment> ac2; EnterCompartment(ac2, cx, value); mNextPromise->ResolveInternal(cx, value, Promise::SyncTask); }
void WrapperPromiseCallback::Call(JSContext* aCx, JS::Handle<JS::Value> aValue) { JSAutoCompartment ac(aCx, mGlobal); JS::Rooted<JS::Value> value(aCx, aValue); if (!JS_WrapValue(aCx, &value)) { NS_WARNING("Failed to wrap value into the right compartment."); return; } ErrorResult rv; // If invoking callback threw an exception, run resolver's reject with the // thrown exception as argument and the synchronous flag set. JS::Rooted<JS::Value> retValue(aCx); mCallback->Call(value, &retValue, rv, CallbackObject::eRethrowExceptions); rv.WouldReportJSException(); if (rv.Failed() && rv.IsJSException()) { JS::Rooted<JS::Value> value(aCx); rv.StealJSException(aCx, &value); if (!JS_WrapValue(aCx, &value)) { NS_WARNING("Failed to wrap value into the right compartment."); return; } mNextPromise->RejectInternal(aCx, value, Promise::SyncTask); return; } // If the return value is the same as the promise itself, throw TypeError. if (retValue.isObject()) { JS::Rooted<JSObject*> valueObj(aCx, &retValue.toObject()); Promise* returnedPromise; nsresult r = UNWRAP_OBJECT(Promise, valueObj, returnedPromise); if (NS_SUCCEEDED(r) && returnedPromise == mNextPromise) { const char* fileName = nullptr; uint32_t lineNumber = 0; // Try to get some information about the callback to report a sane error, // but don't try too hard (only deals with scripted functions). JS::Rooted<JSObject*> unwrapped(aCx, js::CheckedUnwrap(mCallback->Callback())); if (unwrapped) { JSAutoCompartment ac(aCx, unwrapped); if (JS_ObjectIsFunction(aCx, unwrapped)) { JS::Rooted<JS::Value> asValue(aCx, JS::ObjectValue(*unwrapped)); JS::Rooted<JSFunction*> func(aCx, JS_ValueToFunction(aCx, asValue)); MOZ_ASSERT(func); JSScript* script = JS_GetFunctionScript(aCx, func); if (script) { fileName = JS_GetScriptFilename(script); lineNumber = JS_GetScriptBaseLineNumber(aCx, script); } } } // We're back in aValue's compartment here. JS::Rooted<JSString*> stack(aCx, JS_GetEmptyString(JS_GetRuntime(aCx))); JS::Rooted<JSString*> fn(aCx, JS_NewStringCopyZ(aCx, fileName)); if (!fn) { // Out of memory. Promise will stay unresolved. JS_ClearPendingException(aCx); return; } JS::Rooted<JSString*> message(aCx, JS_NewStringCopyZ(aCx, "then() cannot return same Promise that it resolves.")); if (!message) { // Out of memory. Promise will stay unresolved. JS_ClearPendingException(aCx); return; } JS::Rooted<JS::Value> typeError(aCx); if (!JS::CreateTypeError(aCx, stack, fn, lineNumber, 0, nullptr, message, &typeError)) { // Out of memory. Promise will stay unresolved. JS_ClearPendingException(aCx); return; } mNextPromise->RejectInternal(aCx, typeError, Promise::SyncTask); return; } } // Otherwise, run resolver's resolve with value and the synchronous flag // set. if (!JS_WrapValue(aCx, &retValue)) { NS_WARNING("Failed to wrap value into the right compartment."); return; } mNextPromise->ResolveInternal(aCx, retValue, Promise::SyncTask); }
void WrapperPromiseCallback::Call(JS::Handle<JS::Value> aValue) { // AutoCxPusher and co. interact with xpconnect, which crashes on // workers. On workers we'll get the right context from // GetDefaultJSContextForThread(), and since there is only one context, we // don't need to push or pop it from the stack. JSContext* cx = nsContentUtils::GetDefaultJSContextForThread(); Maybe<AutoCxPusher> pusher; if (NS_IsMainThread()) { pusher.construct(cx); } Maybe<JSAutoCompartment> ac; EnterCompartment(ac, cx, aValue); ErrorResult rv; // If invoking callback threw an exception, run resolver's reject with the // thrown exception as argument and the synchronous flag set. JS::Rooted<JS::Value> value(cx, mCallback->Call(aValue, rv, CallbackObject::eRethrowExceptions)); rv.WouldReportJSException(); if (rv.Failed() && rv.IsJSException()) { JS::Rooted<JS::Value> value(cx); rv.StealJSException(cx, &value); Maybe<JSAutoCompartment> ac2; EnterCompartment(ac2, cx, value); mNextPromise->RejectInternal(cx, value, Promise::SyncTask); return; } // If the return value is the same as the promise itself, throw TypeError. if (value.isObject()) { JS::Rooted<JSObject*> valueObj(cx, &value.toObject()); Promise* returnedPromise; nsresult r = UNWRAP_OBJECT(Promise, valueObj, returnedPromise); if (NS_SUCCEEDED(r) && returnedPromise == mNextPromise) { const char* fileName = nullptr; uint32_t lineNumber = 0; // Try to get some information about the callback to report a sane error, // but don't try too hard (only deals with scripted functions). JS::Rooted<JSObject*> unwrapped(cx, js::CheckedUnwrap(mCallback->Callback())); if (unwrapped) { JSAutoCompartment ac(cx, unwrapped); if (JS_ObjectIsFunction(cx, unwrapped)) { JS::Rooted<JS::Value> asValue(cx, JS::ObjectValue(*unwrapped)); JS::Rooted<JSFunction*> func(cx, JS_ValueToFunction(cx, asValue)); MOZ_ASSERT(func); JSScript* script = JS_GetFunctionScript(cx, func); if (script) { fileName = JS_GetScriptFilename(cx, script); lineNumber = JS_GetScriptBaseLineNumber(cx, script); } } } // We're back in aValue's compartment here. JS::Rooted<JSString*> stack(cx, JS_GetEmptyString(JS_GetRuntime(cx))); JS::Rooted<JSString*> fn(cx, JS_NewStringCopyZ(cx, fileName)); if (!fn) { // Out of memory. Promise will stay unresolved. JS_ClearPendingException(cx); return; } JS::Rooted<JSString*> message(cx, JS_NewStringCopyZ(cx, "then() cannot return same Promise that it resolves.")); if (!message) { // Out of memory. Promise will stay unresolved. JS_ClearPendingException(cx); return; } JS::Rooted<JS::Value> typeError(cx); if (!JS::CreateTypeError(cx, stack, fn, lineNumber, 0, nullptr, message, &typeError)) { // Out of memory. Promise will stay unresolved. JS_ClearPendingException(cx); return; } mNextPromise->RejectInternal(cx, typeError, Promise::SyncTask); return; } } // Otherwise, run resolver's resolve with value and the synchronous flag // set. Maybe<JSAutoCompartment> ac2; EnterCompartment(ac2, cx, value); mNextPromise->ResolveInternal(cx, value, Promise::SyncTask); }
nsresult WrapperPromiseCallback::Call(JSContext* aCx, JS::Handle<JS::Value> aValue) { JS::ExposeObjectToActiveJS(mGlobal); JS::ExposeValueToActiveJS(aValue); JSAutoCompartment ac(aCx, mGlobal); JS::Rooted<JS::Value> value(aCx, aValue); if (!JS_WrapValue(aCx, &value)) { NS_WARNING("Failed to wrap value into the right compartment."); return NS_ERROR_FAILURE; } ErrorResult rv; // PromiseReactionTask step 6 JS::Rooted<JS::Value> retValue(aCx); JSCompartment* compartment; if (mNextPromise) { compartment = mNextPromise->Compartment(); } else { MOZ_ASSERT(mNextPromiseObj); compartment = js::GetObjectCompartment(mNextPromiseObj); } mCallback->Call(value, &retValue, rv, "promise callback", CallbackObject::eRethrowExceptions, compartment); rv.WouldReportJSException(); // PromiseReactionTask step 7 if (rv.Failed()) { JS::Rooted<JS::Value> value(aCx); { // Scope for JSAutoCompartment // Convert the ErrorResult to a JS exception object that we can reject // ourselves with. This will be exactly the exception that would get // thrown from a binding method whose ErrorResult ended up with whatever // is on "rv" right now. Do this in the promise reflector compartment. Maybe<JSAutoCompartment> ac; if (mNextPromise) { ac.emplace(aCx, mNextPromise->GlobalJSObject()); } else { ac.emplace(aCx, mNextPromiseObj); } DebugOnly<bool> conversionResult = ToJSValue(aCx, rv, &value); MOZ_ASSERT(conversionResult); } if (mNextPromise) { mNextPromise->RejectInternal(aCx, value); } else { JS::Rooted<JS::Value> ignored(aCx); ErrorResult rejectRv; mRejectFunc->Call(value, &ignored, rejectRv); // This reported any JS exceptions; we just have a pointless exception on // there now. rejectRv.SuppressException(); } return NS_OK; } // If the return value is the same as the promise itself, throw TypeError. if (retValue.isObject()) { JS::Rooted<JSObject*> valueObj(aCx, &retValue.toObject()); valueObj = js::CheckedUnwrap(valueObj); JS::Rooted<JSObject*> nextPromiseObj(aCx); if (mNextPromise) { nextPromiseObj = mNextPromise->GetWrapper(); } else { MOZ_ASSERT(mNextPromiseObj); nextPromiseObj = mNextPromiseObj; } // XXXbz shouldn't this check be over in ResolveInternal anyway? if (valueObj == nextPromiseObj) { const char* fileName = nullptr; uint32_t lineNumber = 0; // Try to get some information about the callback to report a sane error, // but don't try too hard (only deals with scripted functions). JS::Rooted<JSObject*> unwrapped(aCx, js::CheckedUnwrap(mCallback->Callback())); if (unwrapped) { JSAutoCompartment ac(aCx, unwrapped); if (JS_ObjectIsFunction(aCx, unwrapped)) { JS::Rooted<JS::Value> asValue(aCx, JS::ObjectValue(*unwrapped)); JS::Rooted<JSFunction*> func(aCx, JS_ValueToFunction(aCx, asValue)); MOZ_ASSERT(func); JSScript* script = JS_GetFunctionScript(aCx, func); if (script) { fileName = JS_GetScriptFilename(script); lineNumber = JS_GetScriptBaseLineNumber(aCx, script); } } } // We're back in aValue's compartment here. JS::Rooted<JSString*> fn(aCx, JS_NewStringCopyZ(aCx, fileName)); if (!fn) { // Out of memory. Promise will stay unresolved. JS_ClearPendingException(aCx); return NS_ERROR_OUT_OF_MEMORY; } JS::Rooted<JSString*> message(aCx, JS_NewStringCopyZ(aCx, "then() cannot return same Promise that it resolves.")); if (!message) { // Out of memory. Promise will stay unresolved. JS_ClearPendingException(aCx); return NS_ERROR_OUT_OF_MEMORY; } JS::Rooted<JS::Value> typeError(aCx); if (!JS::CreateError(aCx, JSEXN_TYPEERR, nullptr, fn, lineNumber, 0, nullptr, message, &typeError)) { // Out of memory. Promise will stay unresolved. JS_ClearPendingException(aCx); return NS_ERROR_OUT_OF_MEMORY; } if (mNextPromise) { mNextPromise->RejectInternal(aCx, typeError); } else { JS::Rooted<JS::Value> ignored(aCx); ErrorResult rejectRv; mRejectFunc->Call(typeError, &ignored, rejectRv); // This reported any JS exceptions; we just have a pointless exception // on there now. rejectRv.SuppressException(); } return NS_OK; } } // Otherwise, run resolver's resolve with value. if (!JS_WrapValue(aCx, &retValue)) { NS_WARNING("Failed to wrap value into the right compartment."); return NS_ERROR_FAILURE; } if (mNextPromise) { mNextPromise->ResolveInternal(aCx, retValue); } else { JS::Rooted<JS::Value> ignored(aCx); ErrorResult resolveRv; mResolveFunc->Call(retValue, &ignored, resolveRv); // This reported any JS exceptions; we just have a pointless exception // on there now. resolveRv.SuppressException(); } return NS_OK; }