@angular/platform-browser 4.4.3 → 4.4.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license Angular v4.4.3
2
+ * @license Angular v4.4.7
3
3
  * (c) 2010-2017 Google, Inc. https://angular.io/
4
4
  * License: MIT
5
5
  */
@@ -105,13 +105,11 @@ class DomAdapter {
105
105
  * @return {?}
106
106
  */
107
107
  get attrToPropMap() { return this._attrToPropMap; }
108
- ;
109
108
  /**
110
109
  * @param {?} value
111
110
  * @return {?}
112
111
  */
113
112
  set attrToPropMap(value) { this._attrToPropMap = value; }
114
- ;
115
113
  /**
116
114
  * @abstract
117
115
  * @param {?} nodeA
@@ -2435,7 +2433,6 @@ class EventManagerPlugin {
2435
2433
  }
2436
2434
  return this.addEventListener(target, eventName, handler);
2437
2435
  }
2438
- ;
2439
2436
  }
2440
2437
 
2441
2438
  /**
@@ -2617,7 +2614,6 @@ class DomRendererFactory2 {
2617
2614
  this.rendererByCompId = new Map();
2618
2615
  this.defaultRenderer = new DefaultDomRenderer2(eventManager);
2619
2616
  }
2620
- ;
2621
2617
  /**
2622
2618
  * @param {?} element
2623
2619
  * @param {?} type
@@ -3280,6 +3276,172 @@ KeyEventsPlugin.ctorParameters = () => [
3280
3276
  { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT$1,] },] },
3281
3277
  ];
3282
3278
 
3279
+ /**
3280
+ * @license
3281
+ * Copyright Google Inc. All Rights Reserved.
3282
+ *
3283
+ * Use of this source code is governed by an MIT-style license that can be
3284
+ * found in the LICENSE file at https://angular.io/license
3285
+ */
3286
+ /**
3287
+ * This helper class is used to get hold of an inert tree of DOM elements containing dirty HTML
3288
+ * that needs sanitizing.
3289
+ * Depending upon browser support we must use one of three strategies for doing this.
3290
+ * Support: Safari 10.x -> XHR strategy
3291
+ * Support: Firefox -> DomParser strategy
3292
+ * Default: InertDocument strategy
3293
+ */
3294
+ class InertBodyHelper {
3295
+ /**
3296
+ * @param {?} defaultDoc
3297
+ * @param {?} DOM
3298
+ */
3299
+ constructor(defaultDoc, DOM) {
3300
+ this.defaultDoc = defaultDoc;
3301
+ this.DOM = DOM;
3302
+ const inertDocument = this.DOM.createHtmlDocument();
3303
+ this.inertBodyElement = inertDocument.body;
3304
+ if (this.inertBodyElement == null) {
3305
+ // usually there should be only one body element in the document, but IE doesn't have any, so
3306
+ // we need to create one.
3307
+ const inertHtml = this.DOM.createElement('html', inertDocument);
3308
+ this.inertBodyElement = this.DOM.createElement('body', inertDocument);
3309
+ this.DOM.appendChild(inertHtml, this.inertBodyElement);
3310
+ this.DOM.appendChild(inertDocument, inertHtml);
3311
+ }
3312
+ this.DOM.setInnerHTML(this.inertBodyElement, '<svg><g onload="this.parentNode.remove()"></g></svg>');
3313
+ if (this.inertBodyElement.querySelector && !this.inertBodyElement.querySelector('svg')) {
3314
+ // We just hit the Safari 10.1 bug - which allows JS to run inside the SVG G element
3315
+ // so use the XHR strategy.
3316
+ this.getInertBodyElement = this.getInertBodyElement_XHR;
3317
+ return;
3318
+ }
3319
+ this.DOM.setInnerHTML(this.inertBodyElement, '<svg><p><style><img src="</style><img src=x onerror=alert(1)//">');
3320
+ if (this.inertBodyElement.querySelector && this.inertBodyElement.querySelector('svg img')) {
3321
+ // We just hit the Firefox bug - which prevents the inner img JS from being sanitized
3322
+ // so use the DOMParser strategy, if it is available.
3323
+ // If the DOMParser is not available then we are not in Firefox (Server/WebWorker?) so we
3324
+ // fall through to the default strategy below.
3325
+ if (isDOMParserAvailable()) {
3326
+ this.getInertBodyElement = this.getInertBodyElement_DOMParser;
3327
+ return;
3328
+ }
3329
+ }
3330
+ // None of the bugs were hit so it is safe for us to use the default InertDocument strategy
3331
+ this.getInertBodyElement = this.getInertBodyElement_InertDocument;
3332
+ }
3333
+ /**
3334
+ * Use XHR to create and fill an inert body element (on Safari 10.1)
3335
+ * See
3336
+ * https://github.com/cure53/DOMPurify/blob/a992d3a75031cb8bb032e5ea8399ba972bdf9a65/src/purify.js#L439-L449
3337
+ * @param {?} html
3338
+ * @return {?}
3339
+ */
3340
+ getInertBodyElement_XHR(html) {
3341
+ // We add these extra elements to ensure that the rest of the content is parsed as expected
3342
+ // e.g. leading whitespace is maintained and tags like `<meta>` do not get hoisted to the
3343
+ // `<head>` tag.
3344
+ html = '<body><remove></remove>' + html + '</body>';
3345
+ try {
3346
+ html = encodeURI(html);
3347
+ }
3348
+ catch (e) {
3349
+ return null;
3350
+ }
3351
+ const /** @type {?} */ xhr = new XMLHttpRequest();
3352
+ xhr.responseType = 'document';
3353
+ xhr.open('GET', 'data:text/html;charset=utf-8,' + html, false);
3354
+ xhr.send(null);
3355
+ const /** @type {?} */ body = xhr.response.body;
3356
+ body.removeChild(/** @type {?} */ ((body.firstChild)));
3357
+ return body;
3358
+ }
3359
+ /**
3360
+ * Use DOMParser to create and fill an inert body element (on Firefox)
3361
+ * See https://github.com/cure53/DOMPurify/releases/tag/0.6.7
3362
+ *
3363
+ * @param {?} html
3364
+ * @return {?}
3365
+ */
3366
+ getInertBodyElement_DOMParser(html) {
3367
+ // We add these extra elements to ensure that the rest of the content is parsed as expected
3368
+ // e.g. leading whitespace is maintained and tags like `<meta>` do not get hoisted to the
3369
+ // `<head>` tag.
3370
+ html = '<body><remove></remove>' + html + '</body>';
3371
+ try {
3372
+ const /** @type {?} */ body = (new ((window))
3373
+ .DOMParser()
3374
+ .parseFromString(html, 'text/html')
3375
+ .body);
3376
+ body.removeChild(/** @type {?} */ ((body.firstChild)));
3377
+ return body;
3378
+ }
3379
+ catch (e) {
3380
+ return null;
3381
+ }
3382
+ }
3383
+ /**
3384
+ * Use an HTML5 `template` element, if supported, or an inert body element created via
3385
+ * `createHtmlDocument` to create and fill an inert DOM element.
3386
+ * This is the default sane strategy to use if the browser does not require one of the specialised
3387
+ * strategies above.
3388
+ * @param {?} html
3389
+ * @return {?}
3390
+ */
3391
+ getInertBodyElement_InertDocument(html) {
3392
+ // Prefer using <template> element if supported.
3393
+ const /** @type {?} */ templateEl = this.DOM.createElement('template');
3394
+ if ('content' in templateEl) {
3395
+ this.DOM.setInnerHTML(templateEl, html);
3396
+ return templateEl;
3397
+ }
3398
+ this.DOM.setInnerHTML(this.inertBodyElement, html);
3399
+ // Support: IE 9-11 only
3400
+ // strip custom-namespaced attributes on IE<=11
3401
+ if (this.defaultDoc.documentMode) {
3402
+ this.stripCustomNsAttrs(this.inertBodyElement);
3403
+ }
3404
+ return this.inertBodyElement;
3405
+ }
3406
+ /**
3407
+ * When IE9-11 comes across an unknown namespaced attribute e.g. 'xlink:foo' it adds 'xmlns:ns1'
3408
+ * attribute to declare ns1 namespace and prefixes the attribute with 'ns1' (e.g.
3409
+ * 'ns1:xlink:foo').
3410
+ *
3411
+ * This is undesirable since we don't want to allow any of these custom attributes. This method
3412
+ * strips them all.
3413
+ * @param {?} el
3414
+ * @return {?}
3415
+ */
3416
+ stripCustomNsAttrs(el) {
3417
+ this.DOM.attributeMap(el).forEach((_, attrName) => {
3418
+ if (attrName === 'xmlns:ns1' || attrName.indexOf('ns1:') === 0) {
3419
+ this.DOM.removeAttribute(el, attrName);
3420
+ }
3421
+ });
3422
+ for (const /** @type {?} */ n of this.DOM.childNodesAsList(el)) {
3423
+ if (this.DOM.isElementNode(n))
3424
+ this.stripCustomNsAttrs(/** @type {?} */ (n));
3425
+ }
3426
+ }
3427
+ }
3428
+ /**
3429
+ * We need to determine whether the DOMParser exists in the global context.
3430
+ * The try-catch is because, on some browsers, trying to access this property
3431
+ * on window can actually throw an error.
3432
+ *
3433
+ * @suppress {uselessCode}
3434
+ * @return {?}
3435
+ */
3436
+ function isDOMParserAvailable() {
3437
+ try {
3438
+ return !!((window)).DOMParser;
3439
+ }
3440
+ catch (e) {
3441
+ return false;
3442
+ }
3443
+ }
3444
+
3283
3445
  /**
3284
3446
  * @license
3285
3447
  * Copyright Google Inc. All Rights Reserved.
@@ -3347,38 +3509,6 @@ function sanitizeSrcset(srcset) {
3347
3509
  * Use of this source code is governed by an MIT-style license that can be
3348
3510
  * found in the LICENSE file at https://angular.io/license
3349
3511
  */
3350
- /**
3351
- * A <body> element that can be safely used to parse untrusted HTML. Lazily initialized below.
3352
- */
3353
- let inertElement = null;
3354
- /**
3355
- * Lazily initialized to make sure the DOM adapter gets set before use.
3356
- */
3357
- let DOM = null;
3358
- /**
3359
- * Returns an HTML element that is guaranteed to not execute code when creating elements in it.
3360
- * @return {?}
3361
- */
3362
- function getInertElement() {
3363
- if (inertElement)
3364
- return inertElement;
3365
- DOM = getDOM();
3366
- // Prefer using <template> element if supported.
3367
- const /** @type {?} */ templateEl = DOM.createElement('template');
3368
- if ('content' in templateEl)
3369
- return templateEl;
3370
- const /** @type {?} */ doc = DOM.createHtmlDocument();
3371
- inertElement = DOM.querySelector(doc, 'body');
3372
- if (inertElement == null) {
3373
- // usually there should be only one body element in the document, but IE doesn't have any, so we
3374
- // need to create one.
3375
- const /** @type {?} */ html = DOM.createElement('html', doc);
3376
- inertElement = DOM.createElement('body', doc);
3377
- DOM.appendChild(html, inertElement);
3378
- DOM.appendChild(doc, html);
3379
- }
3380
- return inertElement;
3381
- }
3382
3512
  /**
3383
3513
  * @param {?} tags
3384
3514
  * @return {?}
@@ -3447,6 +3577,7 @@ class SanitizingHtmlSerializer {
3447
3577
  constructor() {
3448
3578
  this.sanitizedSomething = false;
3449
3579
  this.buf = [];
3580
+ this.DOM = getDOM();
3450
3581
  }
3451
3582
  /**
3452
3583
  * @param {?} el
@@ -3456,33 +3587,33 @@ class SanitizingHtmlSerializer {
3456
3587
  // This cannot use a TreeWalker, as it has to run on Angular's various DOM adapters.
3457
3588
  // However this code never accesses properties off of `document` before deleting its contents
3458
3589
  // again, so it shouldn't be vulnerable to DOM clobbering.
3459
- let /** @type {?} */ current = ((el.firstChild));
3590
+ let /** @type {?} */ current = ((this.DOM.firstChild(el)));
3460
3591
  while (current) {
3461
- if (DOM.isElementNode(current)) {
3592
+ if (this.DOM.isElementNode(current)) {
3462
3593
  this.startElement(/** @type {?} */ (current));
3463
3594
  }
3464
- else if (DOM.isTextNode(current)) {
3465
- this.chars(/** @type {?} */ ((DOM.nodeValue(current))));
3595
+ else if (this.DOM.isTextNode(current)) {
3596
+ this.chars(/** @type {?} */ ((this.DOM.nodeValue(current))));
3466
3597
  }
3467
3598
  else {
3468
3599
  // Strip non-element, non-text nodes.
3469
3600
  this.sanitizedSomething = true;
3470
3601
  }
3471
- if (DOM.firstChild(current)) {
3472
- current = ((DOM.firstChild(current)));
3602
+ if (this.DOM.firstChild(current)) {
3603
+ current = ((this.DOM.firstChild(current)));
3473
3604
  continue;
3474
3605
  }
3475
3606
  while (current) {
3476
3607
  // Leaving the element. Walk up and to the right, closing tags as we go.
3477
- if (DOM.isElementNode(current)) {
3608
+ if (this.DOM.isElementNode(current)) {
3478
3609
  this.endElement(/** @type {?} */ (current));
3479
3610
  }
3480
- let /** @type {?} */ next = checkClobberedElement(current, /** @type {?} */ ((DOM.nextSibling(current))));
3611
+ let /** @type {?} */ next = this.checkClobberedElement(current, /** @type {?} */ ((this.DOM.nextSibling(current))));
3481
3612
  if (next) {
3482
3613
  current = next;
3483
3614
  break;
3484
3615
  }
3485
- current = checkClobberedElement(current, /** @type {?} */ ((DOM.parentElement(current))));
3616
+ current = this.checkClobberedElement(current, /** @type {?} */ ((this.DOM.parentElement(current))));
3486
3617
  }
3487
3618
  }
3488
3619
  return this.buf.join('');
@@ -3492,14 +3623,14 @@ class SanitizingHtmlSerializer {
3492
3623
  * @return {?}
3493
3624
  */
3494
3625
  startElement(element) {
3495
- const /** @type {?} */ tagName = DOM.nodeName(element).toLowerCase();
3626
+ const /** @type {?} */ tagName = this.DOM.nodeName(element).toLowerCase();
3496
3627
  if (!VALID_ELEMENTS.hasOwnProperty(tagName)) {
3497
3628
  this.sanitizedSomething = true;
3498
3629
  return;
3499
3630
  }
3500
3631
  this.buf.push('<');
3501
3632
  this.buf.push(tagName);
3502
- DOM.attributeMap(element).forEach((value, attrName) => {
3633
+ this.DOM.attributeMap(element).forEach((value, attrName) => {
3503
3634
  const /** @type {?} */ lower = attrName.toLowerCase();
3504
3635
  if (!VALID_ATTRS.hasOwnProperty(lower)) {
3505
3636
  this.sanitizedSomething = true;
@@ -3523,7 +3654,7 @@ class SanitizingHtmlSerializer {
3523
3654
  * @return {?}
3524
3655
  */
3525
3656
  endElement(current) {
3526
- const /** @type {?} */ tagName = DOM.nodeName(current).toLowerCase();
3657
+ const /** @type {?} */ tagName = this.DOM.nodeName(current).toLowerCase();
3527
3658
  if (VALID_ELEMENTS.hasOwnProperty(tagName) && !VOID_ELEMENTS.hasOwnProperty(tagName)) {
3528
3659
  this.buf.push('</');
3529
3660
  this.buf.push(tagName);
@@ -3535,17 +3666,17 @@ class SanitizingHtmlSerializer {
3535
3666
  * @return {?}
3536
3667
  */
3537
3668
  chars(chars) { this.buf.push(encodeEntities(chars)); }
3538
- }
3539
- /**
3540
- * @param {?} node
3541
- * @param {?} nextNode
3542
- * @return {?}
3543
- */
3544
- function checkClobberedElement(node, nextNode) {
3545
- if (nextNode && DOM.contains(node, nextNode)) {
3546
- throw new Error(`Failed to sanitize html because the element is clobbered: ${DOM.getOuterHTML(node)}`);
3669
+ /**
3670
+ * @param {?} node
3671
+ * @param {?} nextNode
3672
+ * @return {?}
3673
+ */
3674
+ checkClobberedElement(node, nextNode) {
3675
+ if (nextNode && this.DOM.contains(node, nextNode)) {
3676
+ throw new Error(`Failed to sanitize html because the element is clobbered: ${this.DOM.getOuterHTML(node)}`);
3677
+ }
3678
+ return nextNode;
3547
3679
  }
3548
- return nextNode;
3549
3680
  }
3550
3681
  // Regular Expressions for parsing tags and attributes
3551
3682
  const SURROGATE_PAIR_REGEXP = /[\uD800-\uDBFF][\uDC00-\uDFFF]/g;
@@ -3569,26 +3700,7 @@ function encodeEntities(value) {
3569
3700
  .replace(/</g, '&lt;')
3570
3701
  .replace(/>/g, '&gt;');
3571
3702
  }
3572
- /**
3573
- * When IE9-11 comes across an unknown namespaced attribute e.g. 'xlink:foo' it adds 'xmlns:ns1'
3574
- * attribute to declare ns1 namespace and prefixes the attribute with 'ns1' (e.g. 'ns1:xlink:foo').
3575
- *
3576
- * This is undesirable since we don't want to allow any of these custom attributes. This method
3577
- * strips them all.
3578
- * @param {?} el
3579
- * @return {?}
3580
- */
3581
- function stripCustomNsAttrs(el) {
3582
- DOM.attributeMap(el).forEach((_, attrName) => {
3583
- if (attrName === 'xmlns:ns1' || attrName.indexOf('ns1:') === 0) {
3584
- DOM.removeAttribute(el, attrName);
3585
- }
3586
- });
3587
- for (const /** @type {?} */ n of DOM.childNodesAsList(el)) {
3588
- if (DOM.isElementNode(n))
3589
- stripCustomNsAttrs(/** @type {?} */ (n));
3590
- }
3591
- }
3703
+ let inertBodyHelper;
3592
3704
  /**
3593
3705
  * Sanitizes the given unsafe, untrusted HTML fragment, and returns HTML text that is safe to add to
3594
3706
  * the DOM in a browser environment.
@@ -3597,10 +3709,13 @@ function stripCustomNsAttrs(el) {
3597
3709
  * @return {?}
3598
3710
  */
3599
3711
  function sanitizeHtml(defaultDoc, unsafeHtmlInput) {
3712
+ const /** @type {?} */ DOM = getDOM();
3713
+ let /** @type {?} */ inertBodyElement = null;
3600
3714
  try {
3601
- const /** @type {?} */ containerEl = getInertElement();
3715
+ inertBodyHelper = inertBodyHelper || new InertBodyHelper(defaultDoc, DOM);
3602
3716
  // Make sure unsafeHtml is actually a string (TypeScript types are not enforced at runtime).
3603
3717
  let /** @type {?} */ unsafeHtml = unsafeHtmlInput ? String(unsafeHtmlInput) : '';
3718
+ inertBodyElement = inertBodyHelper.getInertBodyElement(unsafeHtml);
3604
3719
  // mXSS protection. Repeatedly parse the document to make sure it stabilizes, so that a browser
3605
3720
  // trying to auto-correct incorrect HTML cannot cause formerly inert HTML to become dangerous.
3606
3721
  let /** @type {?} */ mXSSAttempts = 5;
@@ -3611,29 +3726,24 @@ function sanitizeHtml(defaultDoc, unsafeHtmlInput) {
3611
3726
  }
3612
3727
  mXSSAttempts--;
3613
3728
  unsafeHtml = parsedHtml;
3614
- DOM.setInnerHTML(containerEl, unsafeHtml);
3615
- if (defaultDoc.documentMode) {
3616
- // strip custom-namespaced attributes on IE<=11
3617
- stripCustomNsAttrs(containerEl);
3618
- }
3619
- parsedHtml = DOM.getInnerHTML(containerEl);
3729
+ parsedHtml = DOM.getInnerHTML(inertBodyElement);
3730
+ inertBodyElement = inertBodyHelper.getInertBodyElement(unsafeHtml);
3620
3731
  } while (unsafeHtml !== parsedHtml);
3621
3732
  const /** @type {?} */ sanitizer = new SanitizingHtmlSerializer();
3622
- const /** @type {?} */ safeHtml = sanitizer.sanitizeChildren(DOM.getTemplateContent(containerEl) || containerEl);
3623
- // Clear out the body element.
3624
- const /** @type {?} */ parent = DOM.getTemplateContent(containerEl) || containerEl;
3625
- for (const /** @type {?} */ child of DOM.childNodesAsList(parent)) {
3626
- DOM.removeChild(parent, child);
3627
- }
3733
+ const /** @type {?} */ safeHtml = sanitizer.sanitizeChildren(DOM.getTemplateContent(inertBodyElement) || inertBodyElement);
3628
3734
  if (isDevMode() && sanitizer.sanitizedSomething) {
3629
3735
  DOM.log('WARNING: sanitizing HTML stripped some content (see http://g.co/ng/security#xss).');
3630
3736
  }
3631
3737
  return safeHtml;
3632
3738
  }
3633
- catch (e) {
3739
+ finally {
3634
3740
  // In case anything goes wrong, clear out inertElement to reset the entire DOM structure.
3635
- inertElement = null;
3636
- throw e;
3741
+ if (inertBodyElement) {
3742
+ const /** @type {?} */ parent = DOM.getTemplateContent(inertBodyElement) || inertBodyElement;
3743
+ for (const /** @type {?} */ child of DOM.childNodesAsList(parent)) {
3744
+ DOM.removeChild(parent, child);
3745
+ }
3746
+ }
3637
3747
  }
3638
3748
  }
3639
3749
 
@@ -4299,7 +4409,7 @@ class By {
4299
4409
  /**
4300
4410
  * \@stable
4301
4411
  */
4302
- const VERSION = new Version('4.4.3');
4412
+ const VERSION = new Version('4.4.7');
4303
4413
 
4304
4414
  /**
4305
4415
  * @license