| 1659 | |
| 1660 | |
| 1661 | void CallbackHandlers::PostFrameCallback(const FunctionCallbackInfo<v8::Value> &args) { |
| 1662 | if (android_get_device_api_level() >= 24) { |
| 1663 | InitChoreographer(); |
| 1664 | Isolate *isolate = args.GetIsolate(); |
| 1665 | |
| 1666 | v8::Locker locker(isolate); |
| 1667 | Isolate::Scope isolate_scope(isolate); |
| 1668 | HandleScope handle_scope(isolate); |
| 1669 | auto context = isolate->GetCurrentContext(); |
| 1670 | Context::Scope context_scope(context); |
| 1671 | |
| 1672 | if (args.Length() < 1 || !args[0]->IsFunction()) { |
| 1673 | isolate->ThrowException(v8::Exception::TypeError(v8::String::NewFromUtf8Literal(isolate, "Frame callback argument is not a function"))); |
| 1674 | return; |
| 1675 | } |
| 1676 | |
| 1677 | auto func = args[0].As<Function>(); |
| 1678 | |
| 1679 | auto idKey = ArgConverter::ConvertToV8String(isolate, "_postFrameCallbackId"); |
| 1680 | |
| 1681 | Local<Value> pId; |
| 1682 | bool success = V8GetPrivateValue(isolate, func, idKey, pId); |
| 1683 | |
| 1684 | if (success && pId->IsNumber()){ |
| 1685 | auto id = pId->IntegerValue(context).FromMaybe(0); |
| 1686 | auto cb = frameCallbackCache_.find(id); |
| 1687 | if (cb != frameCallbackCache_.end()) { |
| 1688 | // check if it's already scheduled first, we don't want to schedule it twice |
| 1689 | bool shouldReschedule = !cb->second.isScheduled(); |
| 1690 | // always mark as scheduled, as that will also mark it as not removed anymore |
| 1691 | cb->second.markScheduled(); |
| 1692 | if (shouldReschedule) { |
| 1693 | PostCallback(args, &cb->second, context); |
| 1694 | } |
| 1695 | return; |
| 1696 | } |
| 1697 | } |
| 1698 | |
| 1699 | Local<v8::Function> callback = func; |
| 1700 | uint64_t key = ++frameCallbackCount_; |
| 1701 | |
| 1702 | V8SetPrivateValue(isolate, func, idKey, v8::Number::New(isolate, (double) key)); |
| 1703 | |
| 1704 | robin_hood::unordered_map<uint64_t, FrameCallbackCacheEntry>::iterator val; |
| 1705 | bool inserted; |
| 1706 | std::tie(val, inserted) = frameCallbackCache_.try_emplace(key, isolate, callback, key); |
| 1707 | assert(inserted && "Frame callback ID should not be duplicated"); |
| 1708 | |
| 1709 | val->second.markScheduled(); |
| 1710 | PostCallback(args, &val->second, context); |
| 1711 | } |
| 1712 | } |
| 1713 | |
| 1714 | void CallbackHandlers::RemoveFrameCallback(const FunctionCallbackInfo<v8::Value> &args) { |
| 1715 |
nothing calls this directly
no test coverage detected