Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(angularjs): integrate all fixes #13

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 32 additions & 2 deletions src/.jshintrc
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"extends": "../.jshintrc-base",
"root": true,
"extends": "../.eslintrc-browser.json",
"browser": true,
"globals": {
/* auto/injector.js */
Expand All @@ -14,6 +15,9 @@
"splice": false,
"push": false,
"toString": false,
"minErrConfig": false,
"errorHandlingConfig": false,
"isValidObjectMaxDepth": false,
"ngMinErr": false,
"_angular": false,
"angularModule": false,
Expand All @@ -36,6 +40,7 @@
"extend": false,
"int": false,
"inherit": false,
"merge": false,
"noop": false,
"identity": false,
"valueFn": false,
Expand All @@ -44,7 +49,9 @@
"isObject": false,
"isString": false,
"isNumber": false,
"isNumberNaN": false,
"isDate": false,
"isError": false,
"isArray": false,
"isFunction": false,
"isRegExp": false,
Expand All @@ -55,6 +62,7 @@
"isBlob": false,
"isBoolean": false,
"isPromiseLike": false,
"hasCustomToString": false,
"trim": false,
"escapeForRegexp": false,
"isElement": false,
Expand All @@ -63,6 +71,7 @@
"arrayRemove": false,
"copy": false,
"shallowCopy": false,
"simpleCompare": false,
"equals": false,
"csp": false,
"concat": false,
Expand All @@ -71,6 +80,9 @@
"toJsonReplacer": false,
"toJson": false,
"fromJson": false,
"addDateMinutes": false,
"convertTimezoneToLocal": false,
"timezoneToOffset": false,
"startingTag": false,
"tryDecodeURIComponent": false,
"parseKeyValue": false,
Expand All @@ -90,8 +102,9 @@
"createMap": false,
"VALIDITY_STATE_PROPERTY": false,
"reloadWithDebugInfo": false,

"stringify": false,
"skipDestroyOnNextJQueryCleanData": true,
"UNSAFE_restoreLegacyJqLiteXHTMLReplacement": false,

"NODE_TYPE_ELEMENT": false,
"NODE_TYPE_ATTRIBUTE": false,
Expand Down Expand Up @@ -121,6 +134,7 @@
"ALIASED_ATTR": false,
"jqNextId": false,
"camelCase": false,
"fnCamelCaseReplace": false,
"jqLitePatchJQueryRemove": false,
"JQLite": false,
"jqLiteClone": false,
Expand All @@ -137,6 +151,7 @@
"jqLiteInheritedData": false,
"jqLiteBuildFragment": false,
"jqLiteParseHTML": false,
"jqLiteWrapNode": false,
"getBooleanAttrName": false,
"getAliasedAttrName": false,
"createEventHandler": false,
Expand All @@ -149,20 +164,35 @@
/* apis.js */
"hashKey": false,
"HashMap": false,
"NgMap": false,

/* urlUtils.js */
"urlResolve": false,
"urlIsSameOrigin": false,
"urlIsSameOriginAsBaseUrl": false,
"urlIsAllowedOriginFactory": false,

/* ng/controller.js */
"identifierForController": false,

/* ng/compile.js */
"directiveNormalize": false,

/* ng/parse.js */
"setter": false,

/* ng/q.js */
"markQExceptionHandled": false,

/* sce.js */
"SCE_CONTEXTS": false,

/* ng/directive/directives.js */
"ngDirective": false,

/* ng/directive/ngEventDirs.js */
"createEventDirective": false,

/* ng/directive/input.js */
"VALID_CLASS": false,
"INVALID_CLASS": false,
Expand Down
92 changes: 78 additions & 14 deletions src/Angular.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
extend: true,
int: true,
inherit: true,
merge: true,
noop: true,
identity: true,
valueFn: true,
Expand Down Expand Up @@ -84,6 +85,7 @@
getBlockNodes: true,
hasOwnProperty: true,
createMap: true,
UNSAFE_restoreLegacyJqLiteXHTMLReplacement,

NODE_TYPE_ELEMENT: true,
NODE_TYPE_ATTRIBUTE: true,
Expand Down Expand Up @@ -327,6 +329,41 @@ function setHashKey(obj, h) {
}
}


function baseExtend(dst, objs, deep) {
var h = dst.$$hashKey;
for (var i = 0, ii = objs.length; i < ii; ++i) {
var obj = objs[i];
if (!isObject(obj) && !isFunction(obj)) continue;
var keys = Object.keys(obj);
for (var j = 0, jj = keys.length; j < jj; j++) {
var key = keys[j];
var src = obj[key];
if (deep && isObject(src)) {
if (isDate(src)) {
dst[key] = new Date(src.valueOf());
} else if (isRegExp(src)) {
dst[key] = new RegExp(src);
} else if (src.nodeName) {
dst[key] = src.cloneNode(true);
} else if (isElement(src)) {
dst[key] = src.clone();
} else {
if (key !== '__proto__') {
if (!isObject(dst[key])) dst[key] = isArray(src) ? [] : {};
baseExtend(dst[key], [src], true);
}
}
} else {
dst[key] = src;
}
}
}

setHashKey(dst, h);
return dst;
}

/**
* @ngdoc function
* @name angular.extend
Expand All @@ -344,21 +381,29 @@ function setHashKey(obj, h) {
* @returns {Object} Reference to `dst`.
*/
function extend(dst) {
var h = dst.$$hashKey;

for (var i = 1, ii = arguments.length; i < ii; i++) {
var obj = arguments[i];
if (obj) {
var keys = Object.keys(obj);
for (var j = 0, jj = keys.length; j < jj; j++) {
var key = keys[j];
dst[key] = obj[key];
}
}
}
return baseExtend(dst, slice.call(arguments, 1), false);
}

setHashKey(dst, h);
return dst;
/**
* @ngdoc function
* @name angular.merge
* @module ng
* @kind function
*
* @description
* Deeply extends the destination object `dst` by copying own enumerable properties from the `src` object(s)
* to `dst`. You can specify multiple `src` objects. If you want to preserve original objects, you can do so
* by passing an empty object as the target: `var object = angular.merge({}, object1, object2)`.
*
* Unlike {@link angular.extend extend()}, `merge()` recursively descends into object properties of source
* objects, performing a deep copy.
*
* @param {Object} dst Destination object.
* @param {...Object} src Source object(s).
* @returns {Object} Reference to `dst`.
*/
function merge(dst) {
return baseExtend(dst, slice.call(arguments, 1), true);
}

function int(str) {
Expand Down Expand Up @@ -1570,6 +1615,25 @@ function bindJQuery() {
bindJQueryFired = true;
}

/**
* @ngdoc function
* @name angular.UNSAFE_restoreLegacyJqLiteXHTMLReplacement
* @module ng
* @kind function
*
* @description
* Restores the pre-1.8 behavior of jqLite that turns XHTML-like strings like
* `<div /><span />` to `<div></div><span></span>` instead of `<div><span></span></div>`.
* The new behavior is a security fix so if you use this method, please try to adjust
* to the change & remove the call as soon as possible.
* Note that this only patches jqLite. If you use jQuery 3.5.0 or newer, please read
* [jQuery 3.5 upgrade guide](https://jquery.com/upgrade-guide/3.5/) for more details
* about the workarounds.
*/
function UNSAFE_restoreLegacyJqLiteXHTMLReplacement() {
JQLite.legacyXHTMLReplacement = true;
}

/**
* throw error if the argument is falsy.
*/
Expand Down
4 changes: 3 additions & 1 deletion src/AngularPublic.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ function publishExternalAPI(angular) {
'bootstrap': bootstrap,
'copy': copy,
'extend': extend,
'merge': merge,
'equals': equals,
'element': jqLite,
'forEach': forEach,
Expand All @@ -141,7 +142,8 @@ function publishExternalAPI(angular) {
'getTestability': getTestability,
'$$minErr': minErr,
'$$csp': csp,
'reloadWithDebugInfo': reloadWithDebugInfo
'reloadWithDebugInfo': reloadWithDebugInfo,
'UNSAFE_restoreLegacyJqLiteXHTMLReplacement': UNSAFE_restoreLegacyJqLiteXHTMLReplacement
});

angularModule = setupModuleLoader(window);
Expand Down
47 changes: 39 additions & 8 deletions src/jqLite.js
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,6 @@ var XHTML_TAG_REGEXP = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w

var wrapMap = {
'option': [1, '<select multiple="multiple">', '</select>'],

'thead': [1, '<table>', '</table>'],
'col': [2, '<table><colgroup>', '</colgroup></table>'],
'tr': [2, '<table><tbody>', '</tbody></table>'],
Expand All @@ -170,6 +169,21 @@ wrapMap.optgroup = wrapMap.option;
wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
wrapMap.th = wrapMap.td;

// Support: IE <10 only
// IE 9 requires an option wrapper & it needs to have the whole table structure
// set up up front; assigning `"<td></td>"` to `tr.innerHTML` doesn't work, etc.
var wrapMapIE9 = {
option: [1, '<select multiple="multiple">', '</select>'],
_default: [0, '', '']
};

for (var key in wrapMap) {
var wrapMapValueClosing = wrapMap[key];
var wrapMapValue = wrapMapValueClosing.slice().reverse();
wrapMapIE9[key] = [wrapMapValue.length, '<' + wrapMapValue.join('><') + '>', '</' + wrapMapValueClosing.join('></') + '>'];
}

wrapMapIE9.optgroup = wrapMapIE9.option;

function jqLiteIsTextNode(html) {
return !HTML_REGEXP.test(html);
Expand All @@ -183,7 +197,7 @@ function jqLiteAcceptsData(node) {
}

function jqLiteBuildFragment(html, context) {
var tmp, tag, wrap,
var tmp, tag, wrap, finalHtml,
fragment = context.createDocumentFragment(),
nodes = [], i;

Expand All @@ -194,13 +208,30 @@ function jqLiteBuildFragment(html, context) {
// Convert html into DOM nodes
tmp = tmp || fragment.appendChild(context.createElement("div"));
tag = (TAG_NAME_REGEXP.exec(html) || ["", ""])[1].toLowerCase();
wrap = wrapMap[tag] || wrapMap._default;
tmp.innerHTML = wrap[1] + html.replace(XHTML_TAG_REGEXP, "<$1></$2>") + wrap[2];
finalHtml = JQLite.legacyXHTMLReplacement ?
html.replace(XHTML_TAG_REGEXP, '<$1></$2>') :
html;

if (msie < 10) {
wrap = wrapMapIE9[tag] || wrapMapIE9._default;
tmp.innerHTML = wrap[1] + finalHtml + wrap[2];

// Descend through wrappers to the right content
i = wrap[0];
while (i--) {
tmp = tmp.firstChild;
}
} else {
wrap = wrapMap[tag] || wrapMap._default;

// Descend through wrappers to the right content
i = wrap[0];
while (i--) {
tmp = tmp.lastChild;

tmp.innerHTML = wrap[1] + finalHtml + wrap[2];

// Descend through wrappers to the right content
i = wrap[0];
while (i--) {
tmp = tmp.lastChild;
}
}

nodes = concat(nodes, tmp.childNodes);
Expand Down
2 changes: 1 addition & 1 deletion src/ng/compile.js
Original file line number Diff line number Diff line change
Expand Up @@ -1044,7 +1044,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {

nodeName = nodeName_(this.$$element);

if ((nodeName === 'a' && key === 'href') ||
if ((nodeName === 'a' && (key === 'href' || key === 'xlinkHref')) ||
(nodeName === 'img' && key === 'src')) {
// sanitize a[href] and img[src] values
this[key] = value = $$sanitizeUri(value, key === 'src');
Expand Down
Loading