MediaQuery::MediaQuery(Restrictor r, const String& mediaType, PassOwnPtr<Vector<OwnPtr<MediaQueryExp> > > exprs) : m_restrictor(r) , m_mediaType(mediaType.lower()) , m_expressions(exprs) , m_ignored(false) { if (!m_expressions) { m_expressions = adoptPtr(new Vector<OwnPtr<MediaQueryExp> >); return; } nonCopyingSort(m_expressions->begin(), m_expressions->end(), expressionCompare); // remove all duplicated expressions String key; for (int i = m_expressions->size() - 1; i >= 0; --i) { // if not all of the expressions is valid the media query must be ignored. if (!m_ignored) m_ignored = !m_expressions->at(i)->isValid(); if (m_expressions->at(i)->serialize() == key) m_expressions->remove(i); else key = m_expressions->at(i)->serialize(); } }
ActiveInterpolationsMap AnimationStack::activeInterpolations( AnimationStack* animationStack, const HeapVector<Member<const InertEffect>>* newAnimations, const HeapHashSet<Member<const Animation>>* suppressedAnimations, KeyframeEffectReadOnly::Priority priority, PropertyHandleFilter propertyHandleFilter) { ActiveInterpolationsMap result; if (animationStack) { HeapVector<Member<SampledEffect>>& sampledEffects = animationStack->m_sampledEffects; // std::sort doesn't work with OwnPtrs nonCopyingSort(sampledEffects.begin(), sampledEffects.end(), compareSampledEffects); animationStack->removeRedundantSampledEffects(); for (const auto& sampledEffect : sampledEffects) { if (sampledEffect->priority() != priority || (suppressedAnimations && sampledEffect->effect() && suppressedAnimations->contains( sampledEffect->effect()->animation()))) continue; copyToActiveInterpolationsMap(sampledEffect->interpolations(), propertyHandleFilter, result); } } if (newAnimations) copyNewAnimationsToActiveInterpolationsMap(*newAnimations, propertyHandleFilter, result); return result; }
Vector<RefPtr<TextTrack> > CaptionUserPreferences::sortedTrackListForMenu(TextTrackList* trackList) { ASSERT(trackList); Vector<RefPtr<TextTrack> > tracksForMenu; for (unsigned i = 0, length = trackList->length(); i < length; ++i) tracksForMenu.append(trackList->item(i)); nonCopyingSort(tracksForMenu.begin(), tracksForMenu.end(), textTrackCompare); return tracksForMenu; }
void BitmapTexturePool::releaseUnusedTexturesTimerFired(Timer<BitmapTexturePool>*) { if (m_textures.isEmpty()) return; // Delete entries, which have been unused in s_releaseUnusedSecondsTolerance. nonCopyingSort(m_textures.begin(), m_textures.end(), BitmapTexturePoolEntry::compareTimeLastUsed); double minUsedTime = monotonicallyIncreasingTime() - s_releaseUnusedSecondsTolerance; for (size_t i = 0; i < m_textures.size(); ++i) { if (m_textures[i].m_timeLastUsed < minUsedTime) { m_textures.remove(i, m_textures.size() - i); break; } } }
static String dumpHistoryItem(PassRefPtr<WebCore::HistoryItem> item, int indent, bool current) { String result; int start = 0; if (current) { result = result + "curr->"; start = 6; } for (int i = start; i < indent; i++) result = result + " "; String url = item->urlString(); if (url.contains("file://")) { static String layoutTestsString("/LayoutTests/"); static String fileTestString("(file test):"); String res = url.substring(url.find(layoutTestsString) + layoutTestsString.length()); if (res.isEmpty()) return result; result = result + fileTestString; result = result + res; } else result = result + url; String target = item->target(); if (!target.isEmpty()) result = result + " (in frame \"" + target + "\")"; if (item->isTargetItem()) result = result + " **nav target**"; result = result + "\n"; WebCore::HistoryItemVector children = item->children(); // Must sort to eliminate arbitrary result ordering which defeats reproducible testing. nonCopyingSort(children.begin(), children.end(), historyItemCompare); unsigned resultSize = children.size(); for (unsigned i = 0; i < resultSize; ++i) result = result + dumpHistoryItem(children[i], indent + 4, false); return result; }
void RangeInputType::updateTickMarkValues() { if (!m_tickMarkValuesDirty) return; m_tickMarkValues.clear(); m_tickMarkValuesDirty = false; HTMLDataListElement* dataList = element().dataList(); if (!dataList) return; HTMLDataListOptionsCollection* options = dataList->options(); m_tickMarkValues.reserveCapacity(options->length()); for (unsigned i = 0; i < options->length(); ++i) { HTMLOptionElement* optionElement = options->item(i); String optionValue = optionElement->value(); if (!this->element().isValidValue(optionValue)) continue; m_tickMarkValues.append(parseToNumber(optionValue, Decimal::nan())); } m_tickMarkValues.shrinkToFit(); nonCopyingSort(m_tickMarkValues.begin(), m_tickMarkValues.end(), decimalCompare); }
ActiveInterpolationsMap AnimationStack::activeInterpolations(AnimationStack* animationStack, const HeapVector<Member<InertEffect>>* newAnimations, const HeapHashSet<Member<const Animation>>* suppressedAnimations, KeyframeEffect::Priority priority, double timelineCurrentTime) { // We don't exactly know when new animations will start, but timelineCurrentTime is a good estimate. ActiveInterpolationsMap result; if (animationStack) { HeapVector<Member<SampledEffect>>& effects = animationStack->m_effects; // std::sort doesn't work with OwnPtrs nonCopyingSort(effects.begin(), effects.end(), compareEffects); animationStack->removeClearedEffects(); for (const auto& effect : effects) { if (effect->priority() != priority || (suppressedAnimations && effect->effect() && suppressedAnimations->contains(effect->effect()->animation()))) continue; copyToActiveInterpolationsMap(effect->interpolations(), result); } } if (newAnimations) copyNewAnimationsToActiveInterpolationsMap(*newAnimations, result); return result; }
MediaQuery::MediaQuery(Restrictor r, const String& mediaType, PassOwnPtrWillBeRawPtr<ExpressionHeapVector> expressions) : m_restrictor(r) , m_mediaType(attemptStaticStringCreation(mediaType.lower())) , m_expressions(expressions) { if (!m_expressions) { m_expressions = adoptPtrWillBeNoop(new ExpressionHeapVector); return; } nonCopyingSort(m_expressions->begin(), m_expressions->end(), expressionCompare); // Remove all duplicated expressions. MediaQueryExp* key = 0; for (int i = m_expressions->size() - 1; i >= 0; --i) { MediaQueryExp* exp = m_expressions->at(i).get(); if (key && *exp == *key) m_expressions->remove(i); else key = exp; } }
void V8InjectedScriptHost::getEventListenersCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { if (info.Length() < 1) return; InjectedScriptHost* host = V8InjectedScriptHost::unwrap(info.GetIsolate()->GetCurrentContext(), info.Holder()); V8DebuggerClient* client = static_cast<V8DebuggerImpl&>(host->debugger()).client(); EventListenerInfoMap listenerInfo; client->eventListeners(info[0], listenerInfo); v8::Local<v8::Object> result = v8::Object::New(info.GetIsolate()); Vector<String> types; for (auto& it : listenerInfo) types.append(it.key); nonCopyingSort(types.begin(), types.end(), WTF::codePointCompareLessThan); for (const String& type : types) { v8::Local<v8::Array> listeners = wrapListenerFunctions(info.GetIsolate(), *listenerInfo.get(type)); if (!listeners->Length()) continue; result->Set(v8String(info.GetIsolate(), type), listeners); } v8SetReturnValue(info, result); }
void CueTimeline::updateActiveCues(double movieTime) { // 4.8.10.8 Playing the media resource // If the current playback position changes while the steps are running, // then the user agent must wait for the steps to complete, and then must // immediately rerun the steps. if (ignoreUpdateRequests()) return; HTMLMediaElement& mediaElement = this->mediaElement(); // Don't run the "time marches on" algorithm if the document has been // detached. This primarily guards against dispatch of events w/ // HTMLTrackElement targets. if (mediaElement.document().isDetached()) return; // https://html.spec.whatwg.org/#time-marches-on // 1 - Let current cues be a list of cues, initialized to contain all the // cues of all the hidden, showing, or showing by default text tracks of the // media element (not the disabled ones) whose start times are less than or // equal to the current playback position and whose end times are greater // than the current playback position. CueList currentCues; // The user agent must synchronously unset [the text track cue active] flag // whenever ... the media element's readyState is changed back to // kHaveNothing. if (mediaElement.getReadyState() != HTMLMediaElement::kHaveNothing && mediaElement.webMediaPlayer()) currentCues = m_cueTree.allOverlaps(m_cueTree.createInterval(movieTime, movieTime)); CueList previousCues; CueList missedCues; // 2 - Let other cues be a list of cues, initialized to contain all the cues // of hidden, showing, and showing by default text tracks of the media // element that are not present in current cues. previousCues = m_currentlyActiveCues; // 3 - Let last time be the current playback position at the time this // algorithm was last run for this media element, if this is not the first // time it has run. double lastTime = m_lastUpdateTime; double lastSeekTime = mediaElement.lastSeekTime(); // 4 - If the current playback position has, since the last time this // algorithm was run, only changed through its usual monotonic increase // during normal playback, then let missed cues be the list of cues in other // cues whose start times are greater than or equal to last time and whose // end times are less than or equal to the current playback position. // Otherwise, let missed cues be an empty list. if (lastTime >= 0 && lastSeekTime < movieTime) { CueList potentiallySkippedCues = m_cueTree.allOverlaps(m_cueTree.createInterval(lastTime, movieTime)); for (CueInterval cue : potentiallySkippedCues) { // Consider cues that may have been missed since the last seek time. if (cue.low() > std::max(lastSeekTime, lastTime) && cue.high() < movieTime) missedCues.append(cue); } } m_lastUpdateTime = movieTime; // 5 - If the time was reached through the usual monotonic increase of the // current playback position during normal playback, and if the user agent // has not fired a timeupdate event at the element in the past 15 to 250ms // and is not still running event handlers for such an event, then the user // agent must queue a task to fire a simple event named timeupdate at the // element. (In the other cases, such as explicit seeks, relevant events get // fired as part of the overall process of changing the current playback // position.) if (!mediaElement.seeking() && lastSeekTime < lastTime) mediaElement.scheduleTimeupdateEvent(true); // Explicitly cache vector sizes, as their content is constant from here. size_t missedCuesSize = missedCues.size(); size_t previousCuesSize = previousCues.size(); // 6 - If all of the cues in current cues have their text track cue active // flag set, none of the cues in other cues have their text track cue active // flag set, and missed cues is empty, then abort these steps. bool activeSetChanged = missedCuesSize; for (size_t i = 0; !activeSetChanged && i < previousCuesSize; ++i) { if (!currentCues.contains(previousCues[i]) && previousCues[i].data()->isActive()) activeSetChanged = true; } for (CueInterval currentCue : currentCues) { // Notify any cues that are already active of the current time to mark // past and future nodes. Any inactive cues have an empty display state; // they will be notified of the current time when the display state is // updated. if (currentCue.data()->isActive()) currentCue.data()->updatePastAndFutureNodes(movieTime); else activeSetChanged = true; } if (!activeSetChanged) return; // 7 - If the time was reached through the usual monotonic increase of the // current playback position during normal playback, and there are cues in // other cues that have their text track cue pause-on-exi flag set and that // either have their text track cue active flag set or are also in missed // cues, then immediately pause the media element. for (size_t i = 0; !mediaElement.paused() && i < previousCuesSize; ++i) { if (previousCues[i].data()->pauseOnExit() && previousCues[i].data()->isActive() && !currentCues.contains(previousCues[i])) mediaElement.pause(); } for (size_t i = 0; !mediaElement.paused() && i < missedCuesSize; ++i) { if (missedCues[i].data()->pauseOnExit()) mediaElement.pause(); } // 8 - Let events be a list of tasks, initially empty. Each task in this // list will be associated with a text track, a text track cue, and a time, // which are used to sort the list before the tasks are queued. HeapVector<std::pair<double, Member<TextTrackCue>>> eventTasks; // 8 - Let affected tracks be a list of text tracks, initially empty. HeapVector<Member<TextTrack>> affectedTracks; for (const auto& missedCue : missedCues) { // 9 - For each text track cue in missed cues, prepare an event named enter // for the TextTrackCue object with the text track cue start time. eventTasks.append( std::make_pair(missedCue.data()->startTime(), missedCue.data())); // 10 - For each text track [...] in missed cues, prepare an event // named exit for the TextTrackCue object with the with the later of // the text track cue end time and the text track cue start time. // Note: An explicit task is added only if the cue is NOT a zero or // negative length cue. Otherwise, the need for an exit event is // checked when these tasks are actually queued below. This doesn't // affect sorting events before dispatch either, because the exit // event has the same time as the enter event. if (missedCue.data()->startTime() < missedCue.data()->endTime()) { eventTasks.append( std::make_pair(missedCue.data()->endTime(), missedCue.data())); } } for (const auto& previousCue : previousCues) { // 10 - For each text track cue in other cues that has its text // track cue active flag set prepare an event named exit for the // TextTrackCue object with the text track cue end time. if (!currentCues.contains(previousCue)) { eventTasks.append( std::make_pair(previousCue.data()->endTime(), previousCue.data())); } } for (const auto& currentCue : currentCues) { // 11 - For each text track cue in current cues that does not have its // text track cue active flag set, prepare an event named enter for the // TextTrackCue object with the text track cue start time. if (!previousCues.contains(currentCue)) { eventTasks.append( std::make_pair(currentCue.data()->startTime(), currentCue.data())); } } // 12 - Sort the tasks in events in ascending time order (tasks with earlier // times first). nonCopyingSort(eventTasks.begin(), eventTasks.end(), eventTimeCueCompare); for (const auto& task : eventTasks) { if (!affectedTracks.contains(task.second->track())) affectedTracks.append(task.second->track()); // 13 - Queue each task in events, in list order. // Each event in eventTasks may be either an enterEvent or an exitEvent, // depending on the time that is associated with the event. This // correctly identifies the type of the event, if the startTime is // less than the endTime in the cue. if (task.second->startTime() >= task.second->endTime()) { mediaElement.scheduleEvent( createEventWithTarget(EventTypeNames::enter, task.second.get())); mediaElement.scheduleEvent( createEventWithTarget(EventTypeNames::exit, task.second.get())); } else { bool isEnterEvent = task.first == task.second->startTime(); AtomicString eventName = isEnterEvent ? EventTypeNames::enter : EventTypeNames::exit; mediaElement.scheduleEvent( createEventWithTarget(eventName, task.second.get())); } } // 14 - Sort affected tracks in the same order as the text tracks appear in // the media element's list of text tracks, and remove duplicates. nonCopyingSort(affectedTracks.begin(), affectedTracks.end(), trackIndexCompare); // 15 - For each text track in affected tracks, in the list order, queue a // task to fire a simple event named cuechange at the TextTrack object, and, // ... for (const auto& track : affectedTracks) { mediaElement.scheduleEvent( createEventWithTarget(EventTypeNames::cuechange, track.get())); // ... if the text track has a corresponding track element, to then fire a // simple event named cuechange at the track element as well. if (track->trackType() == TextTrack::TrackElement) { HTMLTrackElement* trackElement = static_cast<LoadableTextTrack*>(track.get())->trackElement(); DCHECK(trackElement); mediaElement.scheduleEvent( createEventWithTarget(EventTypeNames::cuechange, trackElement)); } } // 16 - Set the text track cue active flag of all the cues in the current // cues, and unset the text track cue active flag of all the cues in the // other cues. for (const auto& cue : currentCues) cue.data()->setIsActive(true); for (const auto& previousCue : previousCues) { if (!currentCues.contains(previousCue)) { TextTrackCue* cue = previousCue.data(); cue->setIsActive(false); cue->removeDisplayTree(); } } // Update the current active cues. m_currentlyActiveCues = currentCues; mediaElement.updateTextTrackDisplay(); }