Path: blob/trunk/third_party/closure/goog/dom/safe.js
2868 views
// Copyright 2013 The Closure Library Authors. All Rights Reserved.1//2// Licensed under the Apache License, Version 2.0 (the "License");3// you may not use this file except in compliance with the License.4// You may obtain a copy of the License at5//6// http://www.apache.org/licenses/LICENSE-2.07//8// Unless required by applicable law or agreed to in writing, software9// distributed under the License is distributed on an "AS-IS" BASIS,10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.11// See the License for the specific language governing permissions and12// limitations under the License.1314/**15* @fileoverview Type-safe wrappers for unsafe DOM APIs.16*17* This file provides type-safe wrappers for DOM APIs that can result in18* cross-site scripting (XSS) vulnerabilities, if the API is supplied with19* untrusted (attacker-controlled) input. Instead of plain strings, the type20* safe wrappers consume values of types from the goog.html package whose21* contract promises that values are safe to use in the corresponding context.22*23* Hence, a program that exclusively uses the wrappers in this file (i.e., whose24* only reference to security-sensitive raw DOM APIs are in this file) is25* guaranteed to be free of XSS due to incorrect use of such DOM APIs (modulo26* correctness of code that produces values of the respective goog.html types,27* and absent code that violates type safety).28*29* For example, assigning to an element's .innerHTML property a string that is30* derived (even partially) from untrusted input typically results in an XSS31* vulnerability. The type-safe wrapper goog.dom.safe.setInnerHtml consumes a32* value of type goog.html.SafeHtml, whose contract states that using its values33* in a HTML context will not result in XSS. Hence a program that is free of34* direct assignments to any element's innerHTML property (with the exception of35* the assignment to .innerHTML in this file) is guaranteed to be free of XSS36* due to assignment of untrusted strings to the innerHTML property.37*/3839goog.provide('goog.dom.safe');40goog.provide('goog.dom.safe.InsertAdjacentHtmlPosition');4142goog.require('goog.asserts');43goog.require('goog.html.SafeHtml');44goog.require('goog.html.SafeScript');45goog.require('goog.html.SafeStyle');46goog.require('goog.html.SafeUrl');47goog.require('goog.html.TrustedResourceUrl');48goog.require('goog.string');49goog.require('goog.string.Const');505152/** @enum {string} */53goog.dom.safe.InsertAdjacentHtmlPosition = {54AFTERBEGIN: 'afterbegin',55AFTEREND: 'afterend',56BEFOREBEGIN: 'beforebegin',57BEFOREEND: 'beforeend'58};596061/**62* Inserts known-safe HTML into a Node, at the specified position.63* @param {!Node} node The node on which to call insertAdjacentHTML.64* @param {!goog.dom.safe.InsertAdjacentHtmlPosition} position Position where65* to insert the HTML.66* @param {!goog.html.SafeHtml} html The known-safe HTML to insert.67*/68goog.dom.safe.insertAdjacentHtml = function(node, position, html) {69node.insertAdjacentHTML(position, goog.html.SafeHtml.unwrap(html));70};717273/**74* Tags not allowed in goog.dom.safe.setInnerHtml.75* @private @const {!Object<string, boolean>}76*/77goog.dom.safe.SET_INNER_HTML_DISALLOWED_TAGS_ = {78'MATH': true,79'SCRIPT': true,80'STYLE': true,81'SVG': true,82'TEMPLATE': true83};848586/**87* Assigns known-safe HTML to an element's innerHTML property.88* @param {!Element} elem The element whose innerHTML is to be assigned to.89* @param {!goog.html.SafeHtml} html The known-safe HTML to assign.90* @throws {Error} If called with one of these tags: math, script, style, svg,91* template.92*/93goog.dom.safe.setInnerHtml = function(elem, html) {94if (goog.asserts.ENABLE_ASSERTS) {95var tagName = elem.tagName.toUpperCase();96if (goog.dom.safe.SET_INNER_HTML_DISALLOWED_TAGS_[tagName]) {97throw Error(98'goog.dom.safe.setInnerHtml cannot be used to set content of ' +99elem.tagName + '.');100}101}102elem.innerHTML = goog.html.SafeHtml.unwrap(html);103};104105106/**107* Assigns known-safe HTML to an element's outerHTML property.108* @param {!Element} elem The element whose outerHTML is to be assigned to.109* @param {!goog.html.SafeHtml} html The known-safe HTML to assign.110*/111goog.dom.safe.setOuterHtml = function(elem, html) {112elem.outerHTML = goog.html.SafeHtml.unwrap(html);113};114115116/**117* Sets the given element's style property to the contents of the provided118* SafeStyle object.119* @param {!Element} elem120* @param {!goog.html.SafeStyle} style121*/122goog.dom.safe.setStyle = function(elem, style) {123elem.style.cssText = goog.html.SafeStyle.unwrap(style);124};125126127/**128* Writes known-safe HTML to a document.129* @param {!Document} doc The document to be written to.130* @param {!goog.html.SafeHtml} html The known-safe HTML to assign.131*/132goog.dom.safe.documentWrite = function(doc, html) {133doc.write(goog.html.SafeHtml.unwrap(html));134};135136137/**138* Safely assigns a URL to an anchor element's href property.139*140* If url is of type goog.html.SafeUrl, its value is unwrapped and assigned to141* anchor's href property. If url is of type string however, it is first142* sanitized using goog.html.SafeUrl.sanitize.143*144* Example usage:145* goog.dom.safe.setAnchorHref(anchorEl, url);146* which is a safe alternative to147* anchorEl.href = url;148* The latter can result in XSS vulnerabilities if url is a149* user-/attacker-controlled value.150*151* @param {!HTMLAnchorElement} anchor The anchor element whose href property152* is to be assigned to.153* @param {string|!goog.html.SafeUrl} url The URL to assign.154* @see goog.html.SafeUrl#sanitize155*/156goog.dom.safe.setAnchorHref = function(anchor, url) {157goog.dom.safe.assertIsHTMLAnchorElement_(anchor);158/** @type {!goog.html.SafeUrl} */159var safeUrl;160if (url instanceof goog.html.SafeUrl) {161safeUrl = url;162} else {163safeUrl = goog.html.SafeUrl.sanitize(url);164}165anchor.href = goog.html.SafeUrl.unwrap(safeUrl);166};167168169/**170* Safely assigns a URL to an image element's src property.171*172* If url is of type goog.html.SafeUrl, its value is unwrapped and assigned to173* image's src property. If url is of type string however, it is first174* sanitized using goog.html.SafeUrl.sanitize.175*176* @param {!HTMLImageElement} imageElement The image element whose src property177* is to be assigned to.178* @param {string|!goog.html.SafeUrl} url The URL to assign.179* @see goog.html.SafeUrl#sanitize180*/181goog.dom.safe.setImageSrc = function(imageElement, url) {182goog.dom.safe.assertIsHTMLImageElement_(imageElement);183/** @type {!goog.html.SafeUrl} */184var safeUrl;185if (url instanceof goog.html.SafeUrl) {186safeUrl = url;187} else {188safeUrl = goog.html.SafeUrl.sanitize(url);189}190imageElement.src = goog.html.SafeUrl.unwrap(safeUrl);191};192193194/**195* Safely assigns a URL to an embed element's src property.196*197* Example usage:198* goog.dom.safe.setEmbedSrc(embedEl, url);199* which is a safe alternative to200* embedEl.src = url;201* The latter can result in loading untrusted code unless it is ensured that202* the URL refers to a trustworthy resource.203*204* @param {!HTMLEmbedElement} embed The embed element whose src property205* is to be assigned to.206* @param {!goog.html.TrustedResourceUrl} url The URL to assign.207*/208goog.dom.safe.setEmbedSrc = function(embed, url) {209goog.dom.safe.assertIsHTMLEmbedElement_(embed);210embed.src = goog.html.TrustedResourceUrl.unwrap(url);211};212213214/**215* Safely assigns a URL to a frame element's src property.216*217* Example usage:218* goog.dom.safe.setFrameSrc(frameEl, url);219* which is a safe alternative to220* frameEl.src = url;221* The latter can result in loading untrusted code unless it is ensured that222* the URL refers to a trustworthy resource.223*224* @param {!HTMLFrameElement} frame The frame element whose src property225* is to be assigned to.226* @param {!goog.html.TrustedResourceUrl} url The URL to assign.227*/228goog.dom.safe.setFrameSrc = function(frame, url) {229goog.dom.safe.assertIsHTMLFrameElement_(frame);230frame.src = goog.html.TrustedResourceUrl.unwrap(url);231};232233234/**235* Safely assigns a URL to an iframe element's src property.236*237* Example usage:238* goog.dom.safe.setIframeSrc(iframeEl, url);239* which is a safe alternative to240* iframeEl.src = url;241* The latter can result in loading untrusted code unless it is ensured that242* the URL refers to a trustworthy resource.243*244* @param {!HTMLIFrameElement} iframe The iframe element whose src property245* is to be assigned to.246* @param {!goog.html.TrustedResourceUrl} url The URL to assign.247*/248goog.dom.safe.setIframeSrc = function(iframe, url) {249goog.dom.safe.assertIsHTMLIFrameElement_(iframe);250iframe.src = goog.html.TrustedResourceUrl.unwrap(url);251};252253254/**255* Safely assigns HTML to an iframe element's srcdoc property.256*257* Example usage:258* goog.dom.safe.setIframeSrcdoc(iframeEl, safeHtml);259* which is a safe alternative to260* iframeEl.srcdoc = html;261* The latter can result in loading untrusted code.262*263* @param {!HTMLIFrameElement} iframe The iframe element whose srcdoc property264* is to be assigned to.265* @param {!goog.html.SafeHtml} html The HTML to assign.266*/267goog.dom.safe.setIframeSrcdoc = function(iframe, html) {268goog.dom.safe.assertIsHTMLIFrameElement_(iframe);269iframe.srcdoc = goog.html.SafeHtml.unwrap(html);270};271272273/**274* Safely sets a link element's href and rel properties. Whether or not275* the URL assigned to href has to be a goog.html.TrustedResourceUrl276* depends on the value of the rel property. If rel contains "stylesheet"277* then a TrustedResourceUrl is required.278*279* Example usage:280* goog.dom.safe.setLinkHrefAndRel(linkEl, url, 'stylesheet');281* which is a safe alternative to282* linkEl.rel = 'stylesheet';283* linkEl.href = url;284* The latter can result in loading untrusted code unless it is ensured that285* the URL refers to a trustworthy resource.286*287* @param {!HTMLLinkElement} link The link element whose href property288* is to be assigned to.289* @param {string|!goog.html.SafeUrl|!goog.html.TrustedResourceUrl} url The URL290* to assign to the href property. Must be a TrustedResourceUrl if the291* value assigned to rel contains "stylesheet". A string value is292* sanitized with goog.html.SafeUrl.sanitize.293* @param {string} rel The value to assign to the rel property.294* @throws {Error} if rel contains "stylesheet" and url is not a295* TrustedResourceUrl296* @see goog.html.SafeUrl#sanitize297*/298goog.dom.safe.setLinkHrefAndRel = function(link, url, rel) {299goog.dom.safe.assertIsHTMLLinkElement_(link);300link.rel = rel;301if (goog.string.caseInsensitiveContains(rel, 'stylesheet')) {302goog.asserts.assert(303url instanceof goog.html.TrustedResourceUrl,304'URL must be TrustedResourceUrl because "rel" contains "stylesheet"');305link.href = goog.html.TrustedResourceUrl.unwrap(url);306} else if (url instanceof goog.html.TrustedResourceUrl) {307link.href = goog.html.TrustedResourceUrl.unwrap(url);308} else if (url instanceof goog.html.SafeUrl) {309link.href = goog.html.SafeUrl.unwrap(url);310} else { // string311// SafeUrl.sanitize must return legitimate SafeUrl when passed a string.312link.href = goog.html.SafeUrl.sanitize(url).getTypedStringValue();313}314};315316317/**318* Safely assigns a URL to an object element's data property.319*320* Example usage:321* goog.dom.safe.setObjectData(objectEl, url);322* which is a safe alternative to323* objectEl.data = url;324* The latter can result in loading untrusted code unless setit is ensured that325* the URL refers to a trustworthy resource.326*327* @param {!HTMLObjectElement} object The object element whose data property328* is to be assigned to.329* @param {!goog.html.TrustedResourceUrl} url The URL to assign.330*/331goog.dom.safe.setObjectData = function(object, url) {332goog.dom.safe.assertIsHTMLObjectElement_(object);333object.data = goog.html.TrustedResourceUrl.unwrap(url);334};335336337/**338* Safely assigns a URL to a script element's src property.339*340* Example usage:341* goog.dom.safe.setScriptSrc(scriptEl, url);342* which is a safe alternative to343* scriptEl.src = url;344* The latter can result in loading untrusted code unless it is ensured that345* the URL refers to a trustworthy resource.346*347* @param {!HTMLScriptElement} script The script element whose src property348* is to be assigned to.349* @param {!goog.html.TrustedResourceUrl} url The URL to assign.350*/351goog.dom.safe.setScriptSrc = function(script, url) {352goog.dom.safe.assertIsHTMLScriptElement_(script);353script.src = goog.html.TrustedResourceUrl.unwrap(url);354};355356357/**358* Safely assigns a value to a script element's content.359*360* Example usage:361* goog.dom.safe.setScriptContent(scriptEl, content);362* which is a safe alternative to363* scriptEl.text = content;364* The latter can result in executing untrusted code unless it is ensured that365* the code is loaded from a trustworthy resource.366*367* @param {!HTMLScriptElement} script The script element whose content is being368* set.369* @param {!goog.html.SafeScript} content The content to assign.370*/371goog.dom.safe.setScriptContent = function(script, content) {372goog.dom.safe.assertIsHTMLScriptElement_(script);373script.text = goog.html.SafeScript.unwrap(content);374};375376377/**378* Safely assigns a URL to a Location object's href property.379*380* If url is of type goog.html.SafeUrl, its value is unwrapped and assigned to381* loc's href property. If url is of type string however, it is first sanitized382* using goog.html.SafeUrl.sanitize.383*384* Example usage:385* goog.dom.safe.setLocationHref(document.location, redirectUrl);386* which is a safe alternative to387* document.location.href = redirectUrl;388* The latter can result in XSS vulnerabilities if redirectUrl is a389* user-/attacker-controlled value.390*391* @param {!Location} loc The Location object whose href property is to be392* assigned to.393* @param {string|!goog.html.SafeUrl} url The URL to assign.394* @see goog.html.SafeUrl#sanitize395*/396goog.dom.safe.setLocationHref = function(loc, url) {397goog.dom.safe.assertIsLocation_(loc);398/** @type {!goog.html.SafeUrl} */399var safeUrl;400if (url instanceof goog.html.SafeUrl) {401safeUrl = url;402} else {403safeUrl = goog.html.SafeUrl.sanitize(url);404}405loc.href = goog.html.SafeUrl.unwrap(safeUrl);406};407408409/**410* Safely opens a URL in a new window (via window.open).411*412* If url is of type goog.html.SafeUrl, its value is unwrapped and passed in to413* window.open. If url is of type string however, it is first sanitized414* using goog.html.SafeUrl.sanitize.415*416* Note that this function does not prevent leakages via the referer that is417* sent by window.open. It is advised to only use this to open 1st party URLs.418*419* Example usage:420* goog.dom.safe.openInWindow(url);421* which is a safe alternative to422* window.open(url);423* The latter can result in XSS vulnerabilities if redirectUrl is a424* user-/attacker-controlled value.425*426* @param {string|!goog.html.SafeUrl} url The URL to open.427* @param {Window=} opt_openerWin Window of which to call the .open() method.428* Defaults to the global window.429* @param {!goog.string.Const=} opt_name Name of the window to open in. Can be430* _top, etc as allowed by window.open().431* @param {string=} opt_specs Comma-separated list of specifications, same as432* in window.open().433* @param {boolean=} opt_replace Whether to replace the current entry in browser434* history, same as in window.open().435* @return {Window} Window the url was opened in.436*/437goog.dom.safe.openInWindow = function(438url, opt_openerWin, opt_name, opt_specs, opt_replace) {439/** @type {!goog.html.SafeUrl} */440var safeUrl;441if (url instanceof goog.html.SafeUrl) {442safeUrl = url;443} else {444safeUrl = goog.html.SafeUrl.sanitize(url);445}446var win = opt_openerWin || window;447return win.open(448goog.html.SafeUrl.unwrap(safeUrl),449// If opt_name is undefined, simply passing that in to open() causes IE to450// reuse the current window instead of opening a new one. Thus we pass ''451// in instead, which according to spec opens a new window. See452// https://html.spec.whatwg.org/multipage/browsers.html#dom-open .453opt_name ? goog.string.Const.unwrap(opt_name) : '', opt_specs,454opt_replace);455};456457458/*459* Custom assertions for use in the above wrapper methods to ensure that they460* are indeed invoked on an element of the appropriate type.461*462* Using a goog.dom.safe wrapper on an object on the incorrect type (via an463* incorrect static type cast) can result in security bugs: For instance,464* g.d.s.setAnchorHref ensures that the URL assigned to the .href attribute465* satisfies the SafeUrl contract, i.e., is safe to dereference as a hyperlink.466* However, the value assigned to a HTMLLinkElement's .href property requires467* the stronger TrustedResourceUrl contract, since it can refer to a stylesheet.468* Thus, using g.d.s.setAnchorHref on an (incorrectly statically typed) object469* of type HTMLLinkElement can result in a security vulnerability.470* Assertions of the correct run-time type help prevent such incorrect use.471*472* In some cases, code using the DOM API is tested using mock objects (e.g., a473* plain object such as {'href': url} instead of an actual Location object).474* To allow such mocking, the assertions permit objects of types that are not475* relevant DOM API objects at all (for instance, not Element or Location).476*477* Note that instanceof checks don't work straightforwardly in older versions of478* IE, or across frames (see,479* http://stackoverflow.com/questions/384286/javascript-isdom-how-do-you-check-if-a-javascript-object-is-a-dom-object,480* http://stackoverflow.com/questions/26248599/instanceof-htmlelement-in-iframe-is-not-element-or-object).481*482* Hence, these assertions may pass vacuously in such scenarios. The resulting483* risk of security bugs is limited by the following factors:484* - A bug can only arise in scenarios involving incorrect static typing (the485* wrapper methods are statically typed to demand objects of the appropriate,486* precise type).487* - Operations on elements across frames are relatively rare.488* - Typically, code is tested and exercised in multiple browsers.489*/490491/**492* Asserts that a given object is a Location.493*494* To permit this assertion to pass in the context of tests where DOM APIs might495* be mocked, also accepts any other type except for subtypes of {!Element}.496* This is to ensure that, for instance, HTMLLinkElement is not being used in497* place of a Location, since this could result in security bugs due to stronger498* contracts required for assignments to the href property of the latter.499*500* @param {?Object} o The object whose type to assert.501* @return {!Location}502* @private503*/504goog.dom.safe.assertIsLocation_ = function(o) {505if (goog.asserts.ENABLE_ASSERTS && typeof Location != 'undefined' &&506typeof Element != 'undefined') {507goog.asserts.assert(508o && (o instanceof Location || !(o instanceof Element)),509'Argument is not a Location (or a non-Element mock); got: %s',510goog.dom.safe.debugStringForType_(o));511}512return /** @type {!Location} */ (o);513};514515/**516* Asserts that a given object is a HTMLAnchorElement.517*518* To permit this assertion to pass in the context of tests where elements might519* be mocked, also accepts objects that are not of type Location nor a subtype520* of Element.521*522* @param {?Object} o The object whose type to assert.523* @return {!HTMLAnchorElement}524* @private525*/526goog.dom.safe.assertIsHTMLAnchorElement_ = function(o) {527if (goog.asserts.ENABLE_ASSERTS && typeof HTMLAnchorElement != 'undefined' &&528typeof Location != 'undefined' && typeof Element != 'undefined') {529goog.asserts.assert(530o && (o instanceof HTMLAnchorElement ||531!((o instanceof Location) || (o instanceof Element))),532'Argument is not a HTMLAnchorElement (or a non-Element mock); got: %s',533goog.dom.safe.debugStringForType_(o));534}535return /** @type {!HTMLAnchorElement} */ (o);536};537538/**539* Asserts that a given object is a HTMLLinkElement.540*541* To permit this assertion to pass in the context of tests where elements might542* be mocked, also accepts objects that are not a subtype of Element.543*544* @param {?Object} o The object whose type to assert.545* @return {!HTMLLinkElement}546* @private547*/548goog.dom.safe.assertIsHTMLLinkElement_ = function(o) {549if (goog.asserts.ENABLE_ASSERTS && typeof HTMLLinkElement != 'undefined' &&550typeof Location != 'undefined' && typeof Element != 'undefined') {551goog.asserts.assert(552o && (o instanceof HTMLLinkElement ||553!((o instanceof Location) || (o instanceof Element))),554'Argument is not a HTMLLinkElement (or a non-Element mock); got: %s',555goog.dom.safe.debugStringForType_(o));556}557return /** @type {!HTMLLinkElement} */ (o);558};559560/**561* Asserts that a given object is a HTMLImageElement.562*563* To permit this assertion to pass in the context of tests where elements might564* be mocked, also accepts objects that are not a subtype of Element.565*566* @param {?Object} o The object whose type to assert.567* @return {!HTMLImageElement}568* @private569*/570goog.dom.safe.assertIsHTMLImageElement_ = function(o) {571if (goog.asserts.ENABLE_ASSERTS && typeof HTMLImageElement != 'undefined' &&572typeof Element != 'undefined') {573goog.asserts.assert(574o && (o instanceof HTMLImageElement || !(o instanceof Element)),575'Argument is not a HTMLImageElement (or a non-Element mock); got: %s',576goog.dom.safe.debugStringForType_(o));577}578return /** @type {!HTMLImageElement} */ (o);579};580581/**582* Asserts that a given object is a HTMLEmbedElement.583*584* To permit this assertion to pass in the context of tests where elements might585* be mocked, also accepts objects that are not a subtype of Element.586*587* @param {?Object} o The object whose type to assert.588* @return {!HTMLEmbedElement}589* @private590*/591goog.dom.safe.assertIsHTMLEmbedElement_ = function(o) {592if (goog.asserts.ENABLE_ASSERTS && typeof HTMLEmbedElement != 'undefined' &&593typeof Element != 'undefined') {594goog.asserts.assert(595o && (o instanceof HTMLEmbedElement || !(o instanceof Element)),596'Argument is not a HTMLEmbedElement (or a non-Element mock); got: %s',597goog.dom.safe.debugStringForType_(o));598}599return /** @type {!HTMLEmbedElement} */ (o);600};601602/**603* Asserts that a given object is a HTMLFrameElement.604*605* To permit this assertion to pass in the context of tests where elements might606* be mocked, also accepts objects that are not a subtype of Element.607*608* @param {?Object} o The object whose type to assert.609* @return {!HTMLFrameElement}610* @private611*/612goog.dom.safe.assertIsHTMLFrameElement_ = function(o) {613if (goog.asserts.ENABLE_ASSERTS && typeof HTMLFrameElement != 'undefined' &&614typeof Element != 'undefined') {615goog.asserts.assert(616o && (o instanceof HTMLFrameElement || !(o instanceof Element)),617'Argument is not a HTMLFrameElement (or a non-Element mock); got: %s',618goog.dom.safe.debugStringForType_(o));619}620return /** @type {!HTMLFrameElement} */ (o);621};622623/**624* Asserts that a given object is a HTMLIFrameElement.625*626* To permit this assertion to pass in the context of tests where elements might627* be mocked, also accepts objects that are not a subtype of Element.628*629* @param {?Object} o The object whose type to assert.630* @return {!HTMLIFrameElement}631* @private632*/633goog.dom.safe.assertIsHTMLIFrameElement_ = function(o) {634if (goog.asserts.ENABLE_ASSERTS && typeof HTMLIFrameElement != 'undefined' &&635typeof Element != 'undefined') {636goog.asserts.assert(637o && (o instanceof HTMLIFrameElement || !(o instanceof Element)),638'Argument is not a HTMLIFrameElement (or a non-Element mock); got: %s',639goog.dom.safe.debugStringForType_(o));640}641return /** @type {!HTMLIFrameElement} */ (o);642};643644/**645* Asserts that a given object is a HTMLObjectElement.646*647* To permit this assertion to pass in the context of tests where elements might648* be mocked, also accepts objects that are not a subtype of Element.649*650* @param {?Object} o The object whose type to assert.651* @return {!HTMLObjectElement}652* @private653*/654goog.dom.safe.assertIsHTMLObjectElement_ = function(o) {655if (goog.asserts.ENABLE_ASSERTS && typeof HTMLObjectElement != 'undefined' &&656typeof Element != 'undefined') {657goog.asserts.assert(658o && (o instanceof HTMLObjectElement || !(o instanceof Element)),659'Argument is not a HTMLObjectElement (or a non-Element mock); got: %s',660goog.dom.safe.debugStringForType_(o));661}662return /** @type {!HTMLObjectElement} */ (o);663};664665/**666* Asserts that a given object is a HTMLScriptElement.667*668* To permit this assertion to pass in the context of tests where elements might669* be mocked, also accepts objects that are not a subtype of Element.670*671* @param {?Object} o The object whose type to assert.672* @return {!HTMLScriptElement}673* @private674*/675goog.dom.safe.assertIsHTMLScriptElement_ = function(o) {676if (goog.asserts.ENABLE_ASSERTS && typeof HTMLScriptElement != 'undefined' &&677typeof Element != 'undefined') {678goog.asserts.assert(679o && (o instanceof HTMLScriptElement || !(o instanceof Element)),680'Argument is not a HTMLScriptElement (or a non-Element mock); got: %s',681goog.dom.safe.debugStringForType_(o));682}683return /** @type {!HTMLScriptElement} */ (o);684};685686/**687* Returns a string representation of a value's type.688*689* @param {*} value An object, or primitive.690* @return {string} The best display name for the value.691* @private692*/693goog.dom.safe.debugStringForType_ = function(value) {694if (goog.isObject(value)) {695return value.constructor.displayName || value.constructor.name ||696Object.prototype.toString.call(value);697} else {698return value === undefined ? 'undefined' :699value === null ? 'null' : typeof value;700}701};702703704