From 44596aa8f2cc908c73bc149fccbcc0f8458a330a Mon Sep 17 00:00:00 2001 From: Timmy Willison Date: Sun, 8 Sep 2013 21:05:07 -0400 Subject: [PATCH] Move parsing methods to their own files (separates manipulation dependency from core) Conflicts: src/core.js --- src/ajax.js | 2 + src/ajax/load.js | 1 + src/ajax/parseJSON.js | 41 +++++++++++ src/ajax/parseXML.js | 29 ++++++++ src/core.js | 155 +++++++++--------------------------------- src/core/parseHTML.js | 38 +++++++++++ src/var/rsingleTag.js | 4 ++ 7 files changed, 146 insertions(+), 124 deletions(-) create mode 100644 src/ajax/parseJSON.js create mode 100644 src/ajax/parseXML.js create mode 100644 src/core/parseHTML.js create mode 100644 src/var/rsingleTag.js diff --git a/src/ajax.js b/src/ajax.js index 8a540cc02..41faad8af 100644 --- a/src/ajax.js +++ b/src/ajax.js @@ -3,6 +3,8 @@ define([ "./var/rnotwhite", "./ajax/var/nonce", "./ajax/var/rquery", + "./ajax/parseJSON", + "./ajax/parseXML", "./deferred" ], function( jQuery, rnotwhite, nonce, rquery ) { diff --git a/src/ajax/load.js b/src/ajax/load.js index d8e7e57c4..cc2a71958 100644 --- a/src/ajax/load.js +++ b/src/ajax/load.js @@ -1,5 +1,6 @@ define([ "../core", + "../core/parseHTML", "../ajax", "../traversing", "../manipulation", diff --git a/src/ajax/parseJSON.js b/src/ajax/parseJSON.js new file mode 100644 index 000000000..ff678623e --- /dev/null +++ b/src/ajax/parseJSON.js @@ -0,0 +1,41 @@ +define([ + "../core" +], function( jQuery ) { + + var rvalidchars = /^[\],:{}\s]*$/, + rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, + rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g, + rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g; + + jQuery.parseJSON = function( data ) { + // Attempt to parse using the native JSON parser first + if ( window.JSON && window.JSON.parse ) { + return window.JSON.parse( data ); + } + + if ( data === null ) { + return data; + } + + if ( typeof data === "string" ) { + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + if ( data ) { + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test( data.replace( rvalidescape, "@" ) + .replace( rvalidtokens, "]" ) + .replace( rvalidbraces, "")) ) { + + return ( new Function( "return " + data ) )(); + } + } + } + + jQuery.error( "Invalid JSON: " + data ); + }; + + return jQuery.parseJSON; +}); diff --git a/src/ajax/parseXML.js b/src/ajax/parseXML.js new file mode 100644 index 000000000..ab2969992 --- /dev/null +++ b/src/ajax/parseXML.js @@ -0,0 +1,29 @@ +define([ + "../core" +], function( jQuery ) { + // Cross-browser xml parsing + jQuery.parseXML = function( data ) { + var xml, tmp; + if ( !data || typeof data !== "string" ) { + return null; + } + try { + if ( window.DOMParser ) { // Standard + tmp = new DOMParser(); + xml = tmp.parseFromString( data , "text/xml" ); + } else { // IE + xml = new ActiveXObject( "Microsoft.XMLDOM" ); + xml.async = "false"; + xml.loadXML( data ); + } + } catch( e ) { + xml = undefined; + } + if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; + }; + + return jQuery.parseXML; +}); diff --git a/src/core.js b/src/core.js index 5fdec9175..62fac0045 100644 --- a/src/core.js +++ b/src/core.js @@ -10,9 +10,10 @@ define([ "./var/toString", "./var/hasOwn", "./var/trim", + "./var/rsingleTag", "./var/support" ], function( strundefined, deletedIds, slice, concat, push, indexOf, - class2type, toString, hasOwn, trim, support ) { + class2type, toString, hasOwn, trim, rsingleTag, support ) { var i, @@ -45,15 +46,6 @@ var // Strict HTML recognition (#11290: must start with <) rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, - // Match a standalone tag - rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/, - - // JSON RegExp - rvalidchars = /^[\],:{}\s]*$/, - rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, - rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g, - rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g, - // Matches dashed string for camelizing rmsPrefix = /^-ms-/, rdashAlpha = /-([\da-z])/gi, @@ -95,6 +87,7 @@ jQuery.fn = jQuery.prototype = { context = context instanceof jQuery ? context[0] : context; // scripts is true for back-compat + // Intentionally let the error be thrown if parseHTML is not present jQuery.merge( this, jQuery.parseHTML( match[1], context && context.nodeType ? context.ownerDocument || context : document, @@ -379,90 +372,6 @@ jQuery.extend({ throw new Error( msg ); }, - // data: string of html - // context (optional): If specified, the fragment will be created in this context, defaults to document - // keepScripts (optional): If true, will include scripts passed in the html string - // TODO: Circular reference core -> manipulation -> core - parseHTML: function( data, context, keepScripts ) { - if ( !data || typeof data !== "string" ) { - return null; - } - if ( typeof context === "boolean" ) { - keepScripts = context; - context = false; - } - context = context || document; - - var parsed = rsingleTag.exec( data ), - scripts = !keepScripts && []; - - // Single tag - if ( parsed ) { - return [ context.createElement( parsed[1] ) ]; - } - - parsed = jQuery.buildFragment( [ data ], context, scripts ); - - if ( scripts && scripts.length ) { - jQuery( scripts ).remove(); - } - return jQuery.merge( [], parsed.childNodes ); - }, - - parseJSON: function( data ) { - // Attempt to parse using the native JSON parser first - if ( window.JSON && window.JSON.parse ) { - return window.JSON.parse( data ); - } - - if ( data === null ) { - return data; - } - - if ( typeof data === "string" ) { - - // Make sure leading/trailing whitespace is removed (IE can't handle it) - data = jQuery.trim( data ); - - if ( data ) { - // Make sure the incoming data is actual JSON - // Logic borrowed from http://json.org/json2.js - if ( rvalidchars.test( data.replace( rvalidescape, "@" ) - .replace( rvalidtokens, "]" ) - .replace( rvalidbraces, "")) ) { - - return ( new Function( "return " + data ) )(); - } - } - } - - jQuery.error( "Invalid JSON: " + data ); - }, - - // Cross-browser xml parsing - parseXML: function( data ) { - var xml, tmp; - if ( !data || typeof data !== "string" ) { - return null; - } - try { - if ( window.DOMParser ) { // Standard - tmp = new DOMParser(); - xml = tmp.parseFromString( data , "text/xml" ); - } else { // IE - xml = new ActiveXObject( "Microsoft.XMLDOM" ); - xml.async = "false"; - xml.loadXML( data ); - } - } catch( e ) { - xml = undefined; - } - if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { - jQuery.error( "Invalid XML: " + data ); - } - return xml; - }, - noop: function() {}, // Evaluates a script in a global context @@ -773,44 +682,42 @@ for ( i in jQuery( support ) ) { } support.ownLast = i !== "0"; -jQuery.extend({ - isPlainObject: function( obj ) { - var key; +jQuery.isPlainObject = function( obj ) { + var key; - // Must be an Object. - // Because of IE, we also have to check the presence of the constructor property. - // Make sure that DOM nodes and window objects don't pass through, as well - if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { - return false; - } + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } - try { - // Not own constructor property must be Object - if ( obj.constructor && - !hasOwn.call(obj, "constructor") && - !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { - return false; - } - } catch ( e ) { - // IE8,9 Will throw exceptions on certain host objects #9897 + try { + // Not own constructor property must be Object + if ( obj.constructor && + !hasOwn.call(obj, "constructor") && + !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { return false; } + } catch ( e ) { + // IE8,9 Will throw exceptions on certain host objects #9897 + return false; + } - // Support: IE<9 - // Handle iteration over inherited properties before own properties. - if ( support.ownLast ) { - for ( key in obj ) { - return hasOwn.call( obj, key ); - } + // Support: IE<9 + // Handle iteration over inherited properties before own properties. + if ( support.ownLast ) { + for ( key in obj ) { + return hasOwn.call( obj, key ); } + } - // Own properties are enumerated firstly, so to speed up, - // if last one is own, then all properties are own. - for ( key in obj ) {} + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + for ( key in obj ) {} - return key === undefined || hasOwn.call( obj, key ); - } -}); + return key === undefined || hasOwn.call( obj, key ); +}; // Populate the class2type map jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) { diff --git a/src/core/parseHTML.js b/src/core/parseHTML.js new file mode 100644 index 000000000..b097bfcc5 --- /dev/null +++ b/src/core/parseHTML.js @@ -0,0 +1,38 @@ +define([ + "../core", + "../var/rsingleTag", + "../manipulation" // buildFragment +], function( jQuery, rsingleTag ) { + + // data: string of html + // context (optional): If specified, the fragment will be created in this context, defaults to document + // keepScripts (optional): If true, will include scripts passed in the html string + jQuery.parseHTML = function( data, context, keepScripts ) { + if ( !data || typeof data !== "string" ) { + return null; + } + if ( typeof context === "boolean" ) { + keepScripts = context; + context = false; + } + context = context || document; + + var parsed = rsingleTag.exec( data ), + scripts = !keepScripts && []; + + // Single tag + if ( parsed ) { + return [ context.createElement( parsed[1] ) ]; + } + + parsed = jQuery.buildFragment( [ data ], context, scripts ); + + if ( scripts && scripts.length ) { + jQuery( scripts ).remove(); + } + + return jQuery.merge( [], parsed.childNodes ); + }; + + return jQuery.parseHTML; +}); diff --git a/src/var/rsingleTag.js b/src/var/rsingleTag.js new file mode 100644 index 000000000..7e7090b77 --- /dev/null +++ b/src/var/rsingleTag.js @@ -0,0 +1,4 @@ +define(function() { + // Match a standalone tag + return (/^<(\w+)\s*\/?>(?:<\/\1>|)$/); +}); -- 2.39.5