Skip to content

Commit

Permalink
fix(node): Don't use global variables for jsdom injection
Browse files Browse the repository at this point in the history
Introduce a (hopefully generally applicable) mechanism for
injecting dependencies into modules, specifically in this case
to inject required bits of JSDOM's Window and Document
implementations into core/utils/xml.js when running in
node.js or other environments lacking a DOM.

The injectDependencies function uses an options object to
facilitate optionally injecting multiple named dependencies
at the same time.

Rename the xmlDocument local variable back to document (was
renamed in google#5461) so that the name used in this module
corresponds to the usual global variable it replaces.

Change the injection in scripts/package/node/core.js to use
injectDependencies instead of setXmlDocument + global variables;
also eliminate apparently-unnecessary creation of a special
Document instance, using the default one supplied by jsdom
instead.

Fixes google#6725.
  • Loading branch information
cpcallen committed Jan 12, 2023
1 parent 32c7585 commit 673ea2f
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 19 deletions.
51 changes: 37 additions & 14 deletions core/utils/xml.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,39 +15,62 @@ import * as goog from '../../closure/goog/goog.js';
goog.declareModuleId('Blockly.utils.xml');


/**
* Injected dependencies. By default these are just (and have the
* same types as) the corresponding DOM Window properties, but the
* Node.js wrapper for Blockly (see scripts/package/node/core.js)
* calls injectDependencies to supply implementations from the jsdom
* package instead.
*/
let {document, DOMParser, XMLSerializer} = globalThis;

/**
* Inject dependencies. Used by the Node.js wrapper for Blockly (see
* scripts/package/node/core.js) to supply implementations from the
* jsdom package instead. While they may be set individually, it is
* normally the case that all three should be supplied and sourced
* from the same JSDOM instance.
* @param dependencies Options object contianing dependencies to set.
*/
export function injectDependencies(
dependencies: {
document?: Document,
DOMParser?: typeof DOMParser,
XMLSerializer?: typeof XMLSerializer,
}) {
({
// Default to existing value if option not supplied.
document = document,
DOMParser = DOMParser,
XMLSerializer = XMLSerializer,
} = dependencies);
}

/**
* Namespace for Blockly's XML.
*
* @alias Blockly.utils.xml.NAME_SPACE
*/
export const NAME_SPACE = 'https://developers.google.com/blockly/xml';

/**
* The Document object to use. By default this is just document, but
* the Node.js build of Blockly (see scripts/package/node/core.js)
* calls setDocument to supply a Document implementation from the
* jsdom package instead.
*/
let xmlDocument: Document = globalThis['document'];

/**
* Get the document object to use for XML serialization.
*
* @returns The document object.
* @alias Blockly.utils.xml.getDocument
*/
export function getDocument(): Document {
return xmlDocument;
return document;
}

/**
* Get the document object to use for XML serialization.
*
* @param document The document object to use.
* @param xmlDocument The document object to use.
* @alias Blockly.utils.xml.setDocument
*/
export function setDocument(document: Document) {
xmlDocument = document;
export function setDocument(xmlDocument: Document) {
document = xmlDocument;
}

/**
Expand All @@ -58,7 +81,7 @@ export function setDocument(document: Document) {
* @alias Blockly.utils.xml.createElement
*/
export function createElement(tagName: string): Element {
return xmlDocument.createElementNS(NAME_SPACE, tagName);
return document.createElementNS(NAME_SPACE, tagName);
}

/**
Expand All @@ -69,7 +92,7 @@ export function createElement(tagName: string): Element {
* @alias Blockly.utils.xml.createTextNode
*/
export function createTextNode(text: string): Text {
return xmlDocument.createTextNode(text);
return document.createTextNode(text);
}

/**
Expand Down
7 changes: 2 additions & 5 deletions scripts/package/node/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@
if (typeof globalThis.document !== 'object') {
const {JSDOM} = require('jsdom');
const {window} = new JSDOM(`<!DOCTYPE html>`);
globalThis.DOMParser = window.DOMParser;
globalThis.XMLSerializer = window.XMLSerializer;
const xmlDocument = Blockly.utils.xml.textToDomDocument(
`<xml xmlns="${Blockly.utils.xml.NAME_SPACE}"></xml>`);
Blockly.utils.xml.setDocument(xmlDocument);
Blockly.utils.xml.injectDependencies(window);
Blockly.utils.xml.injectDependencies({document: window.document});
}

0 comments on commit 673ea2f

Please sign in to comment.