tor-browser

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

commit 5f1d7e6644da1aa346b575a5bbb0a2753af016a6
parent 3e1a58787c7effe54ed6eda19a5b5acb2fb6fc94
Author: Alexandra Borovova <aborovova@mozilla.com>
Date:   Fri, 17 Oct 2025 19:07:00 +0000

Bug 1994661 - Fix wpt-update for None values. r=jgraham

Differential Revision: https://phabricator.services.mozilla.com/D268842

Diffstat:
Mtesting/web-platform/tests/tools/wptrunner/wptrunner/manifestupdate.py | 7+++++--
Mtesting/web-platform/tests/tools/wptrunner/wptrunner/tests/test_manifestupdate.py | 35+++++++++++++++++++++++++++++++++++
Mtesting/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/backends/base.py | 5++++-
Mtesting/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/backends/conditional.py | 7+++++--
Mtesting/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/node.py | 12++++++++----
Mtesting/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/parser.py | 34++++++++++++++++++++++++++--------
Mtesting/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/serializer.py | 3+++
7 files changed, 86 insertions(+), 17 deletions(-)

diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/manifestupdate.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/manifestupdate.py @@ -7,7 +7,7 @@ from math import ceil from typing import Any, Callable, ClassVar, Dict, List, Optional from .wptmanifest import serialize -from .wptmanifest.node import (DataNode, ConditionalNode, BinaryExpressionNode, +from .wptmanifest.node import (AtomExprNode, DataNode, ConditionalNode, BinaryExpressionNode, BinaryOperatorNode, NumberNode, StringNode, VariableNode, ValueNode, UnaryExpressionNode, UnaryOperatorNode, ListNode) @@ -919,6 +919,7 @@ def make_expr(prop_set, rhs): UnaryOperatorNode("not"), VariableNode(prop) )) + if len(expressions) > 1: prev = expressions[-1] for curr in reversed(expressions[:-1]): @@ -938,7 +939,9 @@ def make_expr(prop_set, rhs): def make_node(value): - if isinstance(value, (int, float,)): + if value is None: + node = AtomExprNode(None) + elif isinstance(value, (int, float,)): node = NumberNode(value) elif isinstance(value, str): node = StringNode(str(value)) diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/tests/test_manifestupdate.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/tests/test_manifestupdate.py @@ -56,3 +56,38 @@ def test_unconditional_default_promotion(): TIMEOUT """).encode()) assert manifest.node == wptmanifest.parse(contents_after) + + +def test_none_value(): + contents_before = io.BytesIO( + textwrap.dedent( + """\ + [b.html] + """).encode()) + manifest = manifestupdate.compile( + contents_before, + test_path='a/b.html', + url_base='/', + run_info_properties=(['display'], {}), + update_intermittent=True, + remove_intermittent=False) + test = manifest.get_test('/a/b.html') + test.set_result( + metadata.RunInfo({'display': "x11"}), + metadata.Result('PASS', [], 'PASS')) + test.set_result( + metadata.RunInfo({'display': "wayland"}), + metadata.Result('PASS', [], 'PASS')) + test.set_result( + metadata.RunInfo({'display': None}), + metadata.Result('FAIL', [], 'PASS')) + test.update(full_update=True, disable_intermittent=False) + + contents_after = io.BytesIO( + textwrap.dedent( + """\ + [b.html] + expected: + if display == @Null: FAIL + """).encode()) + assert manifest.node == wptmanifest.parse(contents_after) diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/backends/base.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/backends/base.py @@ -42,7 +42,7 @@ class Compiler(NodeVisitor): return self.data_cls_getter(None, None)(node, **kwargs) def visit_DataNode(self, node): - if node != self.tree: + if node is not self.tree: output_parent = self.output_node self.output_node = self.data_cls_getter(self.output_node, node)(node, **self._kwargs) else: @@ -103,6 +103,9 @@ class Compiler(NodeVisitor): return data return value + def visit_AtomExprNode(self, node): + return node.data + def visit_IndexNode(self, node): assert len(node.children) == 1 return self.visit(node.children[0]) diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/backends/conditional.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/backends/conditional.py @@ -114,7 +114,7 @@ class Compiler(NodeVisitor): return self.data_cls_getter(None, None)(node, **kwargs) def visit_DataNode(self, node): - if node != self.tree: + if node is not self.tree: output_parent = self.output_node self.output_node = self.data_cls_getter(self.output_node, node)(node) else: @@ -178,6 +178,9 @@ class Compiler(NodeVisitor): return data return value + def visit_AtomExprNode(self, node): + return lambda x: node.data + def visit_IndexNode(self, node): assert len(node.children) == 1 return self.visit(node.children[0]) @@ -344,7 +347,7 @@ class ManifestItem: def append(self, child): self.children.append(child) child.parent = self - if child.node.parent != self.node: + if child.node.parent is not self.node: self.node.append(child.node) return child diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/node.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/node.py @@ -33,12 +33,12 @@ class Node: return "\n".join(rv) def __eq__(self, other): - if not (self.__class__ == other.__class__ and - self.data == other.data and - len(self.children) == len(other.children)): + if (self.__class__ != other.__class__ or + self.data != other.data or + len(self.children) != len(other.children)): return False for child, other_child in zip(self.children, other.children): - if not child == other_child: + if child != other_child: return False return True @@ -171,3 +171,7 @@ class StringNode(Node): class NumberNode(ValueNode): pass + + +class AtomExprNode(ValueNode): + pass diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/parser.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/parser.py @@ -15,7 +15,7 @@ from io import BytesIO -from .node import (Node, AtomNode, BinaryExpressionNode, BinaryOperatorNode, +from .node import (Node, AtomNode, AtomExprNode, BinaryExpressionNode, BinaryOperatorNode, ConditionalNode, DataNode, IndexNode, KeyValueNode, ListNode, NumberNode, StringNode, UnaryExpressionNode, UnaryOperatorNode, ValueNode, VariableNode) @@ -45,7 +45,8 @@ operators = ["==", "!=", "not", "and", "or"] atoms = {"True": True, "False": False, - "Reset": object()} + "Reset": object(), + "Null": None} def decode(s): assert isinstance(s, str) @@ -326,9 +327,7 @@ class Tokenizer: yield (token_types.string, self.consume_string(quote_char)) self.state = self.line_end_state elif c == "@": - self.consume() - for _, value in self.value_inner_state(): - yield token_types.atom, value + self.state = self.value_atom_state elif c == "[": self.state = self.list_start_state else: @@ -433,6 +432,8 @@ class Tokenizer: self.state = self.operator_state elif c in digits: self.state = self.digit_state + elif c == "@": + self.state = self.expr_atom_state else: self.state = self.ident_state @@ -499,6 +500,17 @@ class Tokenizer: self.state = self.expr_state yield (token_types.ident, self.line[index_0:self.index]) + def value_atom_state(self): + self.consume() + _, value = next(self.ident_state()) + self.state = self.line_end_state + yield (token_types.atom, value) + + def expr_atom_state(self): + self.consume() + _, value = next(self.ident_state()) + yield (token_types.atom, value) + def consume_escape(self): assert self.char() == "\\" self.consume() @@ -755,7 +767,7 @@ class Parser: elif self.token[0] == token_types.ident and self.token[1] in unary_operators: self.expr_unary_op() self.expr_operand() - elif self.token[0] in [token_types.string, token_types.ident]: + elif self.token[0] in [token_types.string, token_types.ident, token_types.atom]: self.expr_value() elif self.token[0] == token_types.number: self.expr_number() @@ -778,8 +790,14 @@ class Parser: def expr_value(self): node_type = {token_types.string: StringNode, - token_types.ident: VariableNode}[self.token[0]] - self.expr_builder.push_operand(node_type(self.token[1])) + token_types.ident: VariableNode, + token_types.atom: AtomExprNode}[self.token[0]] + if self.token[0] == token_types.atom: + value = atoms[self.token[1]] + else: + value = self.token[1] + + self.expr_builder.push_operand(node_type(value)) self.consume() if self.token == (token_types.paren, "["): self.consume() diff --git a/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/serializer.py b/testing/web-platform/tests/tools/wptrunner/wptrunner/wptmanifest/serializer.py @@ -115,6 +115,9 @@ class ManifestSerializer(NodeVisitor): def visit_NumberNode(self, node): return [node.data] + def visit_AtomExprNode(self, node): + return [atom_names[node.data]] + def visit_VariableNode(self, node): rv = escape(node.data) for child in node.children: