tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

StackNode.java (10794B)


      1 /*
      2 * Copyright (c) 2007 Henri Sivonen
      3 * Copyright (c) 2007-2011 Mozilla Foundation
      4 *
      5 * Permission is hereby granted, free of charge, to any person obtaining a
      6 * copy of this software and associated documentation files (the "Software"),
      7 * to deal in the Software without restriction, including without limitation
      8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      9 * and/or sell copies of the Software, and to permit persons to whom the
     10 * Software is furnished to do so, subject to the following conditions:
     11 *
     12 * The above copyright notice and this permission notice shall be included in
     13 * all copies or substantial portions of the Software.
     14 *
     15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     21 * DEALINGS IN THE SOFTWARE.
     22 */
     23 
     24 package nu.validator.htmlparser.impl;
     25 
     26 import nu.validator.htmlparser.annotation.Inline;
     27 import nu.validator.htmlparser.annotation.Local;
     28 import nu.validator.htmlparser.annotation.NsUri;
     29 
     30 final class StackNode<T> {
     31    // Index where this stack node is stored in the tree builder's list of stack nodes.
     32    // A value of -1 indicates that the stack node is not owned by a tree builder and
     33    // must delete itself when its refcount reaches 0.
     34    final int idxInTreeBuilder;
     35 
     36    int flags;
     37 
     38    @Local String name;
     39 
     40    @Local String popName;
     41 
     42    @NsUri String ns;
     43 
     44    T node;
     45 
     46    // Only used on the list of formatting elements
     47    HtmlAttributes attributes;
     48 
     49    private int refcount = 0;
     50 
     51    /*
     52     *  Only valid for formatting elements
     53     */
     54    // CPPONLY: private @HtmlCreator Object htmlCreator;
     55 
     56    // [NOCPP[
     57 
     58    private TaintableLocatorImpl locator;
     59 
     60    public TaintableLocatorImpl getLocator() {
     61        return locator;
     62    }
     63 
     64    // ]NOCPP]
     65 
     66    @Inline public int getFlags() {
     67        return flags;
     68    }
     69 
     70    public int getGroup() {
     71        return flags & ElementName.GROUP_MASK;
     72    }
     73 
     74    public boolean isScoping() {
     75        return (flags & ElementName.SCOPING) != 0;
     76    }
     77 
     78    public boolean isSpecial() {
     79        return (flags & ElementName.SPECIAL) != 0;
     80    }
     81 
     82    public boolean isFosterParenting() {
     83        return (flags & ElementName.FOSTER_PARENTING) != 0;
     84    }
     85 
     86    public boolean isHtmlIntegrationPoint() {
     87        return (flags & ElementName.HTML_INTEGRATION_POINT) != 0;
     88    }
     89 
     90    // [NOCPP[
     91 
     92    public boolean isOptionalEndTag() {
     93        return (flags & ElementName.OPTIONAL_END_TAG) != 0;
     94    }
     95 
     96    // ]NOCPP]
     97 
     98    StackNode(int idxInTreeBuilder) {
     99        this.idxInTreeBuilder = idxInTreeBuilder;
    100        this.flags = 0;
    101        this.name = null;
    102        this.popName = null;
    103        // CPPONLY: this.ns = 0;
    104        this.node = null;
    105        this.attributes = null;
    106        this.refcount = 0;
    107        // CPPONLY: this.htmlCreator = null;
    108    }
    109 
    110    // CPPONLY: public @HtmlCreator Object getHtmlCreator() {
    111    // CPPONLY:     return htmlCreator;
    112    // CPPONLY: }
    113 
    114    /**
    115     * Setter for copying. This doesn't take another <code>StackNode</code>
    116     * because in C++ the caller is responsible for reobtaining the local names
    117     * from another interner.
    118     *
    119     * @param flags
    120     * @param ns
    121     * @param name
    122     * @param node
    123     * @param popName
    124     * @param attributes
    125     */
    126    void setValues(int flags, @NsUri String ns, @Local String name, T node,
    127            @Local String popName, HtmlAttributes attributes,
    128            // CPPONLY: @HtmlCreator Object htmlCreator
    129            // [NOCPP[
    130            TaintableLocatorImpl locator
    131            // ]NOCPP]
    132    ) {
    133        assert isUnused();
    134        this.flags = flags;
    135        this.name = name;
    136        this.popName = popName;
    137        this.ns = ns;
    138        this.node = node;
    139        this.attributes = attributes;
    140        this.refcount = 1;
    141        /*
    142         * Need to track creator for formatting elements when copying.
    143         */
    144        // CPPONLY: this.htmlCreator = htmlCreator;
    145        // [NOCPP[
    146        this.locator = locator;
    147        // ]NOCPP]
    148    }
    149 
    150    /**
    151     * Short hand for well-known HTML elements.
    152     *
    153     * @param elementName
    154     * @param node
    155     */
    156    void setValues(ElementName elementName, T node
    157            // [NOCPP[
    158            , TaintableLocatorImpl locator
    159            // ]NOCPP]
    160    ) {
    161        assert isUnused();
    162        this.flags = elementName.getFlags();
    163        this.name = elementName.getName();
    164        this.popName = elementName.getName();
    165        this.ns = "http://www.w3.org/1999/xhtml";
    166        this.node = node;
    167        this.attributes = null;
    168        this.refcount = 1;
    169        assert elementName.isInterned() : "Don't use this constructor for custom elements.";
    170        /*
    171         * Not used for formatting elements, so no need to track creator.
    172         */
    173        // CPPONLY: this.htmlCreator = null;
    174        // [NOCPP[
    175        this.locator = locator;
    176        // ]NOCPP]
    177    }
    178 
    179    /**
    180     * Setter for HTML formatting elements.
    181     *
    182     * @param elementName
    183     * @param node
    184     * @param attributes
    185     */
    186    void setValues(ElementName elementName, T node, HtmlAttributes attributes
    187            // [NOCPP[
    188            , TaintableLocatorImpl locator
    189            // ]NOCPP]
    190    ) {
    191        assert isUnused();
    192        this.flags = elementName.getFlags();
    193        this.name = elementName.getName();
    194        this.popName = elementName.getName();
    195        this.ns = "http://www.w3.org/1999/xhtml";
    196        this.node = node;
    197        this.attributes = attributes;
    198        this.refcount = 1;
    199        assert elementName.isInterned() : "Don't use this constructor for custom elements.";
    200        /*
    201         * Need to track creator for formatting elements in order to be able
    202         * to clone them.
    203         */
    204        // CPPONLY: this.htmlCreator = elementName.getHtmlCreator();
    205        // [NOCPP[
    206        this.locator = locator;
    207        // ]NOCPP]
    208    }
    209 
    210    /**
    211     * The common-case HTML setter.
    212     *
    213     * @param elementName
    214     * @param node
    215     * @param popName
    216     */
    217    void setValues(ElementName elementName, T node, @Local String popName
    218            // [NOCPP[
    219            , TaintableLocatorImpl locator
    220            // ]NOCPP]
    221    ) {
    222        assert isUnused();
    223        this.flags = elementName.getFlags();
    224        this.name = elementName.getName();
    225        this.popName = popName;
    226        this.ns = "http://www.w3.org/1999/xhtml";
    227        this.node = node;
    228        this.attributes = null;
    229        this.refcount = 1;
    230        /*
    231         * Not used for formatting elements, so no need to track creator.
    232         */
    233        // CPPONLY: this.htmlCreator = null;
    234        // [NOCPP[
    235        this.locator = locator;
    236        // ]NOCPP]
    237    }
    238 
    239    /**
    240     * Setter for SVG elements. Note that the order of the arguments is
    241     * what distinguishes this from the HTML setter. This is ugly, but
    242     * AFAICT the least disruptive way to make this work with Java's generics
    243     * and without unnecessary branches. :-(
    244     *
    245     * @param elementName
    246     * @param popName
    247     * @param node
    248     */
    249    void setValues(ElementName elementName, @Local String popName, T node
    250            // [NOCPP[
    251            , TaintableLocatorImpl locator
    252            // ]NOCPP]
    253    ) {
    254        assert isUnused();
    255        this.flags = prepareSvgFlags(elementName.getFlags());
    256        this.name = elementName.getName();
    257        this.popName = popName;
    258        this.ns = "http://www.w3.org/2000/svg";
    259        this.node = node;
    260        this.attributes = null;
    261        this.refcount = 1;
    262        /*
    263         * Not used for formatting elements, so no need to track creator.
    264         */
    265        // CPPONLY: this.htmlCreator = null;
    266        // [NOCPP[
    267        this.locator = locator;
    268        // ]NOCPP]
    269    }
    270 
    271    /**
    272     * Setter for MathML.
    273     *
    274     * @param elementName
    275     * @param node
    276     * @param popName
    277     * @param markAsIntegrationPoint
    278     */
    279    void setValues(ElementName elementName, T node, @Local String popName,
    280            boolean markAsIntegrationPoint
    281            // [NOCPP[
    282            , TaintableLocatorImpl locator
    283            // ]NOCPP]
    284    ) {
    285        assert isUnused();
    286        this.flags = prepareMathFlags(elementName.getFlags(),
    287                markAsIntegrationPoint);
    288        this.name = elementName.getName();
    289        this.popName = popName;
    290        this.ns = "http://www.w3.org/1998/Math/MathML";
    291        this.node = node;
    292        this.attributes = null;
    293        this.refcount = 1;
    294        /*
    295         * Not used for formatting elements, so no need to track creator.
    296         */
    297        // CPPONLY: this.htmlCreator = null;
    298        // [NOCPP[
    299        this.locator = locator;
    300        // ]NOCPP]
    301    }
    302 
    303    private static int prepareSvgFlags(int flags) {
    304        flags &= ~(ElementName.FOSTER_PARENTING | ElementName.SCOPING
    305                | ElementName.SPECIAL | ElementName.OPTIONAL_END_TAG);
    306        if ((flags & ElementName.SCOPING_AS_SVG) != 0) {
    307            flags |= (ElementName.SCOPING | ElementName.SPECIAL | ElementName.HTML_INTEGRATION_POINT);
    308        }
    309        return flags;
    310    }
    311 
    312    private static int prepareMathFlags(int flags,
    313            boolean markAsIntegrationPoint) {
    314        flags &= ~(ElementName.FOSTER_PARENTING | ElementName.SCOPING
    315                | ElementName.SPECIAL | ElementName.OPTIONAL_END_TAG);
    316        if ((flags & ElementName.SCOPING_AS_MATHML) != 0) {
    317            flags |= (ElementName.SCOPING | ElementName.SPECIAL);
    318        }
    319        if (markAsIntegrationPoint) {
    320            flags |= ElementName.HTML_INTEGRATION_POINT;
    321        }
    322        return flags;
    323    }
    324 
    325    @SuppressWarnings("unused") private void destructor() {
    326        // The translator adds refcount debug code here.
    327    }
    328 
    329    public void dropAttributes() {
    330        attributes = null;
    331    }
    332 
    333    // [NOCPP[
    334    /**
    335     * @see java.lang.Object#toString()
    336     */
    337    @Override public @Local String toString() {
    338        return name;
    339    }
    340 
    341    // ]NOCPP]
    342 
    343    public void retain() {
    344        refcount++;
    345    }
    346 
    347    public void release(TreeBuilder<T> owningTreeBuilder) {
    348        refcount--;
    349        assert refcount >= 0;
    350        if (refcount == 0) {
    351            Portability.delete(attributes);
    352            if (idxInTreeBuilder >= 0) {
    353                owningTreeBuilder.notifyUnusedStackNode(idxInTreeBuilder);
    354            } else {
    355                assert owningTreeBuilder == null;
    356                Portability.delete(this);
    357            }
    358        }
    359    }
    360 
    361    boolean isUnused() {
    362        return refcount == 0;
    363    }
    364 }