diff --git a/core/block_events.js b/core/block_events.js index b40316871..0af3b9e4c 100644 --- a/core/block_events.js +++ b/core/block_events.js @@ -197,9 +197,8 @@ Blockly.Events.Change.prototype.run = function(forward) { oldMutation = oldMutationDom && Blockly.Xml.domToText(oldMutationDom); } if (block.domToMutation) { - value = value || ''; - var dom = Blockly.Xml.textToDom('' + value + ''); - block.domToMutation(dom.firstChild); + var dom = Blockly.Xml.textToDom(value || ''); + block.domToMutation(dom); } Blockly.Events.fire(new Blockly.Events.Change( block, 'mutation', null, oldMutation, value)); @@ -261,7 +260,7 @@ Blockly.Events.Create.prototype.toJson = function() { */ Blockly.Events.Create.prototype.fromJson = function(json) { Blockly.Events.Create.superClass_.fromJson.call(this, json); - this.xml = Blockly.Xml.textToDom('' + json['xml'] + '').firstChild; + this.xml = Blockly.Xml.textToDom(json['xml']); this.ids = json['ids']; }; diff --git a/core/options.js b/core/options.js index 3775f2dcb..d584ae86d 100644 --- a/core/options.js +++ b/core/options.js @@ -26,8 +26,9 @@ goog.provide('Blockly.Options'); -goog.require('Blockly.Xml'); goog.require('Blockly.Themes.Classic'); +goog.require('Blockly.utils.userAgent'); +goog.require('Blockly.Xml'); /** @@ -48,7 +49,8 @@ Blockly.Options = function(options) { var hasDisable = false; var hasSounds = false; } else { - var languageTree = Blockly.Options.parseToolboxTree(options['toolbox']); + var languageTree = + Blockly.Options.parseToolboxTree(options['toolbox'] || null); var hasCategories = Boolean(languageTree && languageTree.getElementsByTagName('category').length); var hasTrashcan = options['trashcan']; @@ -263,11 +265,11 @@ Blockly.Options.parseGridOptions_ = function(options) { Blockly.Options.parseToolboxTree = function(tree) { if (tree) { if (typeof tree != 'string') { - if (typeof XSLTProcessor == 'undefined' && tree.outerHTML) { + if (Blockly.utils.userAgent.IE && tree.outerHTML) { // In this case the tree will not have been properly built by the // browser. The HTML will be contained in the element, but it will // not have the proper DOM structure since the browser doesn't support - // XSLTProcessor (XML -> HTML). This is the case in IE 9+. + // XSLTProcessor (XML -> HTML). tree = tree.outerHTML; } else if (!(tree instanceof Element)) { tree = null; @@ -275,6 +277,9 @@ Blockly.Options.parseToolboxTree = function(tree) { } if (typeof tree == 'string') { tree = Blockly.Xml.textToDom(tree); + if (tree.nodeName.toLowerCase() != 'xml') { + throw TypeError('Toolbox should be an document.'); + } } } else { tree = null; diff --git a/core/trashcan.js b/core/trashcan.js index 956c21e43..8ab4c0e7b 100644 --- a/core/trashcan.js +++ b/core/trashcan.js @@ -431,7 +431,7 @@ Blockly.Trashcan.prototype.click = function() { var xml = []; for (var i = 0, text; text = this.contents_[i]; i++) { - xml[i] = Blockly.Xml.textToDom(text).firstChild; + xml[i] = Blockly.Xml.textToDom(text); } this.flyout_.show(xml); }; @@ -531,5 +531,5 @@ Blockly.Trashcan.prototype.cleanBlockXML_ = function(xml) { } node = nextNode; } - return '' + Blockly.Xml.domToText(xmlBlock) + ''; + return Blockly.Xml.domToText(xmlBlock); }; diff --git a/core/variables.js b/core/variables.js index f002e2ca7..da4773710 100644 --- a/core/variables.js +++ b/core/variables.js @@ -175,39 +175,33 @@ Blockly.Variables.flyoutCategoryBlocks = function(workspace) { variableModelList[variableModelList.length - 1]); if (Blockly.Blocks['variables_set']) { var gap = Blockly.Blocks['math_change'] ? 8 : 24; - var blockText = '' + - '' + + var blockText = '' + mostRecentVariableFieldXmlString + - '' + - ''; - var block = Blockly.Xml.textToDom(blockText).firstChild; + ''; + var block = Blockly.Xml.textToDom(blockText); xmlList.push(block); } if (Blockly.Blocks['math_change']) { var gap = Blockly.Blocks['variables_get'] ? 20 : 8; - var blockText = '' + - '' + + var blockText = '' + mostRecentVariableFieldXmlString + '' + '' + '1' + '' + '' + - '' + - ''; - var block = Blockly.Xml.textToDom(blockText).firstChild; + ''; + var block = Blockly.Xml.textToDom(blockText); xmlList.push(block); } if (Blockly.Blocks['variables_get']) { variableModelList.sort(Blockly.VariableModel.compareByName); for (var i = 0, variable; variable = variableModelList[i]; i++) { - var blockText = '' + - '' + + var blockText = '' + Blockly.Variables.generateVariableFieldXmlString(variable) + - '' + - ''; - var block = Blockly.Xml.textToDom(blockText).firstChild; + ''; + var block = Blockly.Xml.textToDom(blockText); xmlList.push(block); } } @@ -481,10 +475,7 @@ Blockly.Variables.generateVariableFieldXmlString = function(variableModel) { Blockly.Variables.generateVariableFieldDom = function(variableModel) { var xmlFieldString = Blockly.Variables.generateVariableFieldXmlString(variableModel); - var text = '' + xmlFieldString + ''; - var dom = Blockly.Xml.textToDom(text); - var fieldDom = dom.firstChild; - return fieldDom; + return Blockly.Xml.textToDom(xmlFieldString); }; /** diff --git a/core/variables_dynamic.js b/core/variables_dynamic.js index cc95e2b3e..1408faf92 100644 --- a/core/variables_dynamic.js +++ b/core/variables_dynamic.js @@ -93,23 +93,19 @@ Blockly.VariablesDynamic.flyoutCategoryBlocks = function(workspace) { if (Blockly.Blocks['variables_set_dynamic']) { var firstVariable = variableModelList[variableModelList.length - 1]; var gap = 24; - var blockText = '' + - '' + + var blockText = '' + Blockly.Variables.generateVariableFieldXmlString(firstVariable) + - '' + - ''; - var block = Blockly.Xml.textToDom(blockText).firstChild; + ''; + var block = Blockly.Xml.textToDom(blockText); xmlList.push(block); } if (Blockly.Blocks['variables_get_dynamic']) { variableModelList.sort(Blockly.VariableModel.compareByName); for (var i = 0, variable; variable = variableModelList[i]; i++) { - var blockText = '' + - '' + + var blockText = '' + Blockly.Variables.generateVariableFieldXmlString(variable) + - '' + - ''; - var block = Blockly.Xml.textToDom(blockText).firstChild; + ''; + var block = Blockly.Xml.textToDom(blockText); xmlList.push(block); } } diff --git a/core/xml.js b/core/xml.js index c8fb003e5..6bced0fd0 100644 --- a/core/xml.js +++ b/core/xml.js @@ -317,20 +317,17 @@ Blockly.Xml.domToPrettyText = function(dom) { }; /** - * Converts an XML string into a DOM structure. It requires the XML to have a - * root element of . Other XML string will result in throwing an error. + * Converts an XML string into a DOM structure. * @param {string} text An XML string. * @return {!Element} A DOM object representing the singular child of the * document element. - * @throws if XML doesn't parse or is not the expected structure. + * @throws if the text doesn't parse. */ Blockly.Xml.textToDom = function(text) { var doc = Blockly.Xml.utils.textToDomDocument(text); - // This function only accepts documents. if (!doc || !doc.documentElement || - doc.documentElement.nodeName.toLowerCase() != 'xml') { - // Whatever we got back from the parser is not the expected structure. - throw TypeError('Blockly.Xml.textToDom expected an document.'); + doc.getElementsByTagName('parsererror').length) { + throw Error('textToDom was unable to parse: ' + text); } return doc.documentElement; }; diff --git a/tests/mocha/trashcan_test.js b/tests/mocha/trashcan_test.js index d1ce4c36b..b284e43e0 100644 --- a/tests/mocha/trashcan_test.js +++ b/tests/mocha/trashcan_test.js @@ -287,9 +287,7 @@ suite("Trashcan", function() { test("Max 0", function() { workspace.options.maxTrashcanContents = 0; sendDeleteEvent( - '' + - ' ' + - '' + '' ); chai.assert.equal(this.trashcan.contents_.length, 0); workspace.options.maxTrashcanContents = Infinity; @@ -301,7 +299,7 @@ suite("Trashcan", function() { chai.assert.equal(this.trashcan.contents_.length, 1); chai.assert.equal( Blockly.Xml.textToDom(this.trashcan.contents_[0]) - .children[0].getAttribute('type'), + .getAttribute('type'), 'dummy_type2' ); workspace.options.maxTrashcanContents = Infinity;