Class: CSS::Native::Cascade
Overview
Subclass of CSS::Cascade that uses the native matcher for the inner rule-matching loop. Selectors are pre-compiled at construction —those that can’t be compiled (pseudo-classes etc.) fall through to the pure-Ruby matcher, so behavior is identical to CSS::Cascade.
Requires a Nokogiri document at construction; the snapshot is built once and reused for every resolve(). Mutate the DOM and you must construct a fresh CSS::Native::Cascade.
Constant Summary
Constants inherited from Cascade
Instance Method Summary collapse
-
#initialize(stylesheet, document, context: CSS::MediaQueries::Context.default) ⇒ Cascade
constructor
A new instance of Cascade.
-
#resolve(element, inline_style: nil, state: nil) ⇒ Object
Override: batch every candidate’s compiled selectors into one FFI hop per resolve (GVL released), then merge in any Ruby-fallback matches.
Constructor Details
#initialize(stylesheet, document, context: CSS::MediaQueries::Context.default) ⇒ Cascade
Returns a new instance of Cascade.
83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/css/native.rb', line 83 def initialize(stylesheet, document, context: CSS::MediaQueries::Context.default) super(stylesheet, context: context) @snapshot = Snapshot.from_document(document) @compiled_by_ast = {}.compare_by_identity @entries.each do |entry| entry.selector_pairs.each {|ast, _spec| @compiled_by_ast[ast] = Native.compile_or_nil(ast) } end end |
Instance Method Details
#resolve(element, inline_style: nil, state: nil) ⇒ Object
Override: batch every candidate’s compiled selectors into one FFI hop per resolve (GVL released), then merge in any Ruby-fallback matches. Cuts per-resolve FFI cost from O(candidates) to O(1).
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/css/native.rb', line 99 def resolve(element, inline_style: nil, state: nil) cache = {} candidates = collect_candidate_indexes(element, cache) order = 0 matches = [] native_state = state && @snapshot.compile_state(state) best_by_entry = native_pass(element, candidates, native_state) ruby_fallback_pass(element, candidates, best_by_entry, cache, state) candidates.each do |entry_idx| spec = best_by_entry[entry_idx] or next @entries[entry_idx].declarations.each {|decl| order += 1 matches << CSS::Cascade::Match.new(declaration: decl, specificity: spec, inline: false, order: order) } end if inline_style inline_declarations(inline_style).each {|decl| order += 1 matches << CSS::Cascade::Match.new( declaration: decl, specificity: CSS::Selectors::Specificity::ZERO, inline: true, order: order ) } end pick_winners(matches) end |