browser_dbg_closure-inspection.js 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
  2. /* Any copyright is dedicated to the Public Domain.
  3. * http://creativecommons.org/publicdomain/zero/1.0/ */
  4. const TAB_URL = EXAMPLE_URL + "doc_closures.html";
  5. // Test that inspecting a closure works as expected.
  6. function test() {
  7. let gPanel, gTab, gDebugger;
  8. let options = {
  9. source: TAB_URL,
  10. line: 1
  11. };
  12. initDebugger(TAB_URL, options).then(([aTab,, aPanel]) => {
  13. gTab = aTab;
  14. gPanel = aPanel;
  15. gDebugger = gPanel.panelWin;
  16. testClosure()
  17. .then(() => resumeDebuggerThenCloseAndFinish(gPanel))
  18. .then(null, aError => {
  19. ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
  20. });
  21. });
  22. function testClosure() {
  23. generateMouseClickInTab(gTab, "content.document.querySelector('button')");
  24. return waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_SCOPES).then(() => {
  25. let gVars = gDebugger.DebuggerView.Variables;
  26. let localScope = gVars.getScopeAtIndex(0);
  27. let localNodes = localScope.target.querySelector(".variables-view-element-details").childNodes;
  28. is(localNodes[4].querySelector(".name").getAttribute("value"), "person",
  29. "Should have the right property name for |person|.");
  30. is(localNodes[4].querySelector(".value").getAttribute("value"), "Object",
  31. "Should have the right property value for |person|.");
  32. // Expand the 'person' tree node. This causes its properties to be
  33. // retrieved and displayed.
  34. let personNode = gVars.getItemForNode(localNodes[4]);
  35. let personFetched = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_PROPERTIES);
  36. personNode.expand();
  37. return personFetched.then(() => {
  38. is(personNode.expanded, true,
  39. "|person| should be expanded at this point.");
  40. is(personNode.get("getName").target.querySelector(".name")
  41. .getAttribute("value"), "getName",
  42. "Should have the right property name for 'getName' in person.");
  43. is(personNode.get("getName").target.querySelector(".value")
  44. .getAttribute("value"), "getName()",
  45. "'getName' in person should have the right value.");
  46. is(personNode.get("getFoo").target.querySelector(".name")
  47. .getAttribute("value"), "getFoo",
  48. "Should have the right property name for 'getFoo' in person.");
  49. is(personNode.get("getFoo").target.querySelector(".value")
  50. .getAttribute("value"), "getFoo()",
  51. "'getFoo' in person should have the right value.");
  52. // Expand the function nodes. This causes their properties to be
  53. // retrieved and displayed.
  54. let getFooNode = personNode.get("getFoo");
  55. let getNameNode = personNode.get("getName");
  56. let funcsFetched = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_PROPERTIES, 2);
  57. let funcClosuresFetched = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_SCOPES, 2);
  58. getFooNode.expand();
  59. getNameNode.expand();
  60. return funcsFetched.then(() => {
  61. is(getFooNode.expanded, true,
  62. "|person.getFoo| should be expanded at this point.");
  63. is(getNameNode.expanded, true,
  64. "|person.getName| should be expanded at this point.");
  65. is(getFooNode.get("<Closure>").target.querySelector(".name")
  66. .getAttribute("value"), "<Closure>",
  67. "Found the closure node for getFoo.");
  68. is(getFooNode.get("<Closure>").target.querySelector(".value")
  69. .getAttribute("value"), "",
  70. "The closure node has no value for getFoo.");
  71. is(getNameNode.get("<Closure>").target.querySelector(".name")
  72. .getAttribute("value"), "<Closure>",
  73. "Found the closure node for getName.");
  74. is(getNameNode.get("<Closure>").target.querySelector(".value")
  75. .getAttribute("value"), "",
  76. "The closure node has no value for getName.");
  77. // Expand the closure nodes. This causes their environments to be
  78. // retrieved and displayed.
  79. let getFooClosure = getFooNode.get("<Closure>");
  80. let getNameClosure = getNameNode.get("<Closure>");
  81. getFooClosure.expand();
  82. getNameClosure.expand();
  83. return funcClosuresFetched.then(() => {
  84. is(getFooClosure.expanded, true,
  85. "|person.getFoo| closure should be expanded at this point.");
  86. is(getNameClosure.expanded, true,
  87. "|person.getName| closure should be expanded at this point.");
  88. is(getFooClosure.get("Function scope [_pfactory]").target.querySelector(".name")
  89. .getAttribute("value"), "Function scope [_pfactory]",
  90. "Found the function scope node for the getFoo closure.");
  91. is(getFooClosure.get("Function scope [_pfactory]").target.querySelector(".value")
  92. .getAttribute("value"), "",
  93. "The function scope node has no value for the getFoo closure.");
  94. is(getNameClosure.get("Function scope [_pfactory]").target.querySelector(".name")
  95. .getAttribute("value"), "Function scope [_pfactory]",
  96. "Found the function scope node for the getName closure.");
  97. is(getNameClosure.get("Function scope [_pfactory]").target.querySelector(".value")
  98. .getAttribute("value"), "",
  99. "The function scope node has no value for the getName closure.");
  100. // Expand the scope nodes.
  101. let getFooInnerScope = getFooClosure.get("Function scope [_pfactory]");
  102. let getNameInnerScope = getNameClosure.get("Function scope [_pfactory]");
  103. let innerFuncsFetched = waitForDebuggerEvents(gPanel, gDebugger.EVENTS.FETCHED_PROPERTIES, 2);
  104. getFooInnerScope.expand();
  105. getNameInnerScope.expand();
  106. return funcsFetched.then(() => {
  107. is(getFooInnerScope.expanded, true,
  108. "|person.getFoo| inner scope should be expanded at this point.");
  109. is(getNameInnerScope.expanded, true,
  110. "|person.getName| inner scope should be expanded at this point.");
  111. // Only test that each function closes over the necessary variable.
  112. // We wouldn't want future SpiderMonkey closure space
  113. // optimizations to break this test.
  114. is(getFooInnerScope.get("foo").target.querySelector(".name")
  115. .getAttribute("value"), "foo",
  116. "Found the foo node for the getFoo inner scope.");
  117. is(getFooInnerScope.get("foo").target.querySelector(".value")
  118. .getAttribute("value"), "10",
  119. "The foo node has the expected value.");
  120. is(getNameInnerScope.get("name").target.querySelector(".name")
  121. .getAttribute("value"), "name",
  122. "Found the name node for the getName inner scope.");
  123. is(getNameInnerScope.get("name").target.querySelector(".value")
  124. .getAttribute("value"), '"Bob"',
  125. "The name node has the expected value.");
  126. });
  127. });
  128. });
  129. });
  130. });
  131. }
  132. }