TinyMind
.net.cn
首页
资讯
文章
注册
登录
被逮到一个初始状态考虑不周的Bug
birdshome
关注文章
TinyMind专栏频道
这两天是产品beta1以后进行的新一轮bug扫荡,beta1以前产品的bug降低到了大家非常满意的水平。但是beta1以后QA Team发飚,bug总数biu的一下又上升到人均20个上下,真是让人恼火。不过幸好大部分是为了发布beta1而回归出来的UI方面的bug,不过今天却发现被逮到一个非常隐蔽的控件初始状态考虑不足的bug
。
这个bug发生在一个纯脚本的TreeView控件上面,其异常表现为:
当使用键盘Up&Down键移动TreeView上面被选中的Item时,IE报告currentNode为空的脚本错误。
关于这个功能的详细设计,可以参看
本文
,示例效果为:
上图中的node就是程序中的currentNode,Up&Down操作就是根据这个node来进行计算并移动的。在TreeView控件中,为了处理TreeView节点被多选时找到一个确切的currentNode,在每次选择操作时,我在TreeView实例的全局cache中纪录了一个叫m_LastSelected的值,保存最后一次选择动作中的第一个节点。如果是单选就是被选中的节点本身,如果是多选,就是多选时第一个被选中的节点。
Tree.__ContainerOnKeyDown
=
function
()
{
//
...
if
(innerCache.m_Selecteds.m_Count
==
0
)
{
return
;
}
var
currentNode
=
innerCache.m_LastSelected;
//
...
}
Review上面这段代码,取currentNode的地方似乎是已经做了安全检查,可是怎么还是出错了呢?其实除了本身程序有错,上面这个校验代码也是不对的,我检查的是m_Selecteds这个集合里面有没有东西,然后却是用m_LastSelected赋的值,这之间就可能出现m_Selecteds和m_LastSelected不同步的问题。结果确实是m_Selecteds和m_LastSelected之间的关联出了问题!看下面的代码:
TreeNode.__ContentOnMouseDown
=
function
()
{
//
...
if
((
!
evt.shiftKey
&&
!
evt.ctrlKey)
||
!
objNode.Attributes('IsMultipleSelected'))
{
innerCache.UnselectAll();
objNode.SetSelected(
true
);
innerCache.m_LastSelected
=
objNode;
}
//
...
};
由于m_LastSelected和node的选取顺序有关系,它被实现在了鼠标选择TreeView节点的逻辑中,即每次节点被鼠标点选就会更新m_LastSelected的值。
这个逻辑似乎是没有什么问题,反正只要是选择了TreeView上的节点,就会有m_LastSelected的存在,我们也就会得到Up&Down操作的计步节点currentNode。可是就是这里漏掉了一个情况的考虑,如果被选中节点是在initialize我们的TreeView时,由调用代码来设置给节点的(示例如下)。那么由于实现时的疏忽,就出现了m_Selecteds非空,而m_LastSelected为空的情况。
var
tree
=
new
Tree();
var
node
=
TreeNode('
default
node');
tree.Add(node);
tree.Show(/* treeview container element*/);
node.SetSelected(
true
);
SetSelected(isSelected)方法实现如下:
TreeNode.prototype.SetSelected
=
function
(isSelected)
{
var
innerCache
=
this
.m_Tree.m_InnerCache;
if
(isSelected)
{
if
(
!
innerCache.m_Selecteds.Contains(
this
))
{
innerCache.m_Selecteds.Add(
this
);
}
}
else
{
innerCache.m_Selecteds.Remove(
this
);
}
if
(
this
.m_Selected
!=
isSelected)
{
this
.m_Selected
=
isSelected;
if
(
this
.e_SelectedChanged)
{
this
.e_SelectedChanged.Execute(isSelected);
}
}
this
.ApplyUIChange();
};
问题就是这里了,调用SetSelected选中了节点后,m_Selecteds这个集合是更新了,可是却没有设置m_LastSelected(由于Last Selected Node的定义,本身是不该在这里设置),这样就造成了m_Selecteds和m_LastSelected的不同步。从而出现了开始说到的,进行Up&Down操作结果出现currentNode为空的错误。
这个bug如果是Review代码可能细心能找出来,可是直接被QA通过黑合测试给提了出来,确实是相当相当不容易的。因为刚初始化好的TreeView是没有获得焦点的,这时不管怎么按Up&Down键都不会有反映,也就看起来并没有什么错误。如果使用鼠标点击一下TreeView内的任何区域,让其获得焦点,那么至少都会选中一个TreeNode,这样一来m_LastSelected也就有值了。那么这个如此隐蔽的bug是怎么发现的呢?这需要在页面载入并在TreeView生成后,立即使用Tab键把焦点移到TreeView的container元素上,这时候按Up&Down键,如果TreeView上面有初始花时被SetSelected(isSelected)选中的节点,那么就出错了
。
优质内容筛选与推荐
>>
1、居中
2、odoo 附件上传与下载
3、强势的fetch
4、a configuration error occured during startup.please verify the preference field with the prompt:cannot connect to VMtomcat debug错误时
5、Git常用命令解说
赞赏
长按二维码向我转账
受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。
阅读
好看
已推荐到看一看
你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
取消
推荐
我知道了
已取消,“好看”想法已同步删除
知道了
已推荐到看一看
和朋友分享想法
最多200字,当前共
字
发送
已发送
朋友将在看一看看到
确定
分享你的想法...
取消
分享想法到看一看
确定
最多200字,当前共
字
发送中
网络异常,请稍后重试
知道了
微信扫一扫
关注该公众号
0
│
收藏
│
举报