| 2219 | } else { |
| 2220 | auto result = getContextForId(contextId); |
| 2221 | if (!result) { |
| 2222 | return callContext.throwError(result.moveError()); |
| 2223 | } |
| 2224 | newCurrentContext = result.moveValue(); |
| 2225 | } |
| 2226 | |
| 2227 | auto previous = Context::currentRef(); |
| 2228 | Context::setCurrent(newCurrentContext); |
| 2229 | |
| 2230 | _contextsStack.emplace_back(std::move(previous)); |
| 2231 | |
| 2232 | return callContext.getContext().newUndefined(); |
| 2233 | } |
| 2234 | |
| 2235 | JSValueRef JavaScriptRuntime::runtimePopCurrentContext(JSFunctionNativeCallContext& callContext) { |
| 2236 | if (_contextsStack.empty()) { |
| 2237 | return callContext.throwError(Error("Context stack is empty")); |
| 2238 | } |
| 2239 | |
| 2240 | auto context = std::move(_contextsStack[_contextsStack.size() - 1]); |
| 2241 | _contextsStack.pop_back(); |
| 2242 | |
| 2243 | Context::setCurrent(std::move(context)); |
| 2244 | |
| 2245 | return callContext.getContext().newUndefined(); |
| 2246 | } |
| 2247 | |
| 2248 | JSValueRef JavaScriptRuntime::runtimeGetCurrentContext(JSFunctionNativeCallContext& callContext) { |
| 2249 | auto* context = Context::current(); |
| 2250 | return callContext.getContext().newNumber(static_cast<int32_t>(context->getContextId())); |
| 2251 | } |
| 2252 | |
| 2253 | JSValueRef JavaScriptRuntime::runtimeSaveCurrentContext(JSFunctionNativeCallContext& callContext) { |
| 2254 | // store the current context |
| 2255 | auto context = Context::currentRef(); |
| 2256 | _contextsStash.emplace_back(context); |
| 2257 | // and return its id so that it can be used to restore it |
| 2258 | return callContext.getContext().newNumber(static_cast<int32_t>(context->getContextId())); |
| 2259 | } |
| 2260 | |
| 2261 | JSValueRef JavaScriptRuntime::runtimeRestoreCurrentContext(JSFunctionNativeCallContext& callContext) { |
| 2262 | ContextId contextId = getParameterAsContextId(callContext, 0); |
| 2263 | CHECK_CALL_CONTEXT(callContext); |
| 2264 | // scan the vector of saved contexts for a matching id |
| 2265 | for (auto i = _contextsStash.begin(); i != _contextsStash.end(); ++i) { |
| 2266 | if ((*i)->getContextId() == contextId) { |
| 2267 | // apply current context |
| 2268 | Context::setCurrent(*i); |
| 2269 | // swap the target context with the context at the end |
| 2270 | // this is safe because we know the vector is not empty |
| 2271 | std::swap(*i, _contextsStash.back()); |
| 2272 | // delete the last element from the vector |
| 2273 | _contextsStash.pop_back(); |
| 2274 | break; |
| 2275 | } |
| 2276 | }; |
| 2277 | return callContext.getContext().newUndefined(); |
| 2278 | } |
nothing calls this directly
no test coverage detected