@@ -728,6 +728,49 @@ describe('Test lib.js:', function () {
728728 expect(computed).toEqual(expected);
729729 });
730730 */
731+
732+ it ( 'does not modify inherited objects or the prototype chain' , ( ) => {
733+ const payloads = [
734+ '{"toString.call": 1}' ,
735+ '{"hasOwnProperty.call": 1}' ,
736+ '{"toString.marker": 1}' ,
737+ '{"constructor[0].x": 1}' ,
738+ '{"constructor.prototype.polluted": 1}' ,
739+ '{"__proto__.polluted": 1}' ,
740+ '{"x.__proto__.polluted": 1}' ,
741+ '{"__proto__": {"polluted": 1}}'
742+ ] ;
743+ const targets = [ Object . prototype , Object , Object . prototype . toString , Object . prototype . hasOwnProperty ] ;
744+ const ownNames = ( ) => targets . map ( ( target ) => Object . getOwnPropertyNames ( target ) ) ;
745+ const before = ownNames ( ) ;
746+ const originalProcess = window . process ;
747+ let after ;
748+ let prototypesKept = true ;
749+
750+ try {
751+ [ undefined , { versions : { } } ] . forEach ( ( process ) => {
752+ window . process = process ;
753+ [ Lib . expandObjectPaths , ( obj ) => Lib . extendDeepNoArrays ( { } , obj ) ] . forEach ( ( fn ) => {
754+ payloads . forEach ( ( payload ) => {
755+ const input = JSON . parse ( payload ) ;
756+ fn ( input ) ;
757+ prototypesKept = prototypesKept && Object . getPrototypeOf ( input ) === Object . prototype ;
758+ } ) ;
759+ } ) ;
760+ } ) ;
761+ after = ownNames ( ) ;
762+ } finally {
763+ window . process = originalProcess ;
764+ targets . forEach ( ( target , i ) => {
765+ Object . getOwnPropertyNames ( target )
766+ . filter ( ( name ) => ! before [ i ] . includes ( name ) )
767+ . forEach ( ( name ) => delete target [ name ] ) ;
768+ } ) ;
769+ }
770+
771+ expect ( after ) . toEqual ( before ) ;
772+ expect ( prototypesKept ) . toBe ( true ) ;
773+ } ) ;
731774 } ) ;
732775
733776 describe ( 'coerce' , function ( ) {
0 commit comments