2020-07-03 22:43:08 -07:00
describe ( "[[DefineProperty]] trap normal behavior" , ( ) => {
test ( "forwarding when not defined in handler" , ( ) => {
let p = new Proxy ( { } , { defineProperty : null } ) ;
expect ( Object . defineProperty ( p , "foo" , { } ) ) . toBe ( p ) ;
p = new Proxy ( { } , { defineProperty : undefined } ) ;
expect ( Object . defineProperty ( p , "foo" , { } ) ) . toBe ( p ) ;
p = new Proxy ( { } , { } ) ;
expect ( Object . defineProperty ( p , "foo" , { } ) ) . toBe ( p ) ;
2020-06-03 14:34:52 -07:00
} ) ;
2020-07-03 22:43:08 -07:00
test ( "correct arguments passed to trap" , ( ) => {
let o = { } ;
p = new Proxy ( o , {
defineProperty ( target , name , descriptor ) {
expect ( target ) . toBe ( o ) ;
expect ( name ) . toBe ( "foo" ) ;
2020-07-03 23:13:06 -07:00
expect ( descriptor . configurable ) . toBeTrue ( ) ;
2020-07-03 22:43:08 -07:00
expect ( descriptor . enumerable ) . toBeUndefined ( ) ;
2020-07-03 23:13:06 -07:00
expect ( descriptor . writable ) . toBeTrue ( ) ;
2020-07-03 22:43:08 -07:00
expect ( descriptor . value ) . toBe ( 10 ) ;
expect ( descriptor . get ) . toBeUndefined ( ) ;
expect ( descriptor . set ) . toBeUndefined ( ) ;
return true ;
} ,
} ) ;
2020-06-03 14:34:52 -07:00
2020-07-03 22:43:08 -07:00
Object . defineProperty ( p , "foo" , { configurable : true , writable : true , value : 10 } ) ;
2020-06-03 14:34:52 -07:00
} ) ;
2020-07-03 22:43:08 -07:00
test ( "optionally ignoring the define call" , ( ) => {
let o = { } ;
let p = new Proxy ( o , {
defineProperty ( target , name , descriptor ) {
if ( target [ name ] === undefined )
Object . defineProperty ( target , name , descriptor ) ;
return true ;
} ,
} ) ;
2020-06-03 14:34:52 -07:00
2020-07-03 22:43:08 -07:00
Object . defineProperty ( p , "foo" , { value : 10 , enumerable : true , configurable : false , writable : true } ) ;
2020-07-03 23:13:06 -07:00
expect ( p ) . toHaveEnumerableProperty ( "foo" ) ;
expect ( p ) . not . toHaveConfigurableProperty ( "foo" ) ;
expect ( p ) . toHaveWritableProperty ( "foo" ) ;
expect ( p ) . toHaveValueProperty ( "foo" , 10 ) ;
expect ( p ) . not . toHaveGetterProperty ( "foo" ) ;
expect ( p ) . not . toHaveSetterProperty ( "foo" ) ;
2020-06-03 14:34:52 -07:00
2020-07-03 22:43:08 -07:00
Object . defineProperty ( p , "foo" , { value : 20 , enumerable : true , configurable : false , writable : true } ) ;
2020-07-03 23:13:06 -07:00
expect ( p ) . toHaveEnumerableProperty ( "foo" ) ;
expect ( p ) . not . toHaveConfigurableProperty ( "foo" ) ;
expect ( p ) . toHaveWritableProperty ( "foo" ) ;
expect ( p ) . toHaveValueProperty ( "foo" , 10 ) ;
expect ( p ) . not . toHaveGetterProperty ( "foo" ) ;
expect ( p ) . not . toHaveSetterProperty ( "foo" ) ;
2020-07-03 22:43:08 -07:00
} ) ;
} ) ;
2020-06-03 14:34:52 -07:00
2020-07-03 22:43:08 -07:00
describe ( "[[DefineProperty]] invariants" , ( ) => {
test ( "trap can't return false" , ( ) => {
let p = new Proxy ( { } , {
defineProperty ( ) { return false ; }
} ) ;
2020-06-03 14:34:52 -07:00
2020-07-03 22:43:08 -07:00
expect ( ( ) => {
Object . defineProperty ( p , "foo" , { } ) ;
} ) . toThrowWithMessage ( TypeError , "Object's [[DefineProperty]] method returned false" ) ;
2020-06-03 14:34:52 -07:00
} ) ;
2020-07-03 22:43:08 -07:00
test ( "trap cannot return true for a non-extensible target if the property does not exist" , ( ) => {
let o = { } ;
Object . preventExtensions ( o ) ;
let p = new Proxy ( o , {
defineProperty ( ) {
return true ;
}
} ) ;
2020-06-03 14:34:52 -07:00
2020-07-03 22:43:08 -07:00
expect ( ( ) => {
Object . defineProperty ( p , "foo" , { } ) ;
} ) . toThrowWithMessage ( TypeError , "Proxy handler's defineProperty trap violates invariant: a property cannot be reported as being defined if the property does not exist on the target and the target is non-extensible" ) ;
2020-06-03 14:34:52 -07:00
} ) ;
2020-07-03 22:43:08 -07:00
test ( "trap cannot return true for a non-configurable property if it doesn't already exist on the target" , ( ) => {
let o = { } ;
Object . defineProperty ( o , "foo" , { value : 10 , configurable : true } ) ;
let p = new Proxy ( o , {
defineProperty ( ) {
return true ;
} ,
} ) ;
2020-06-03 14:34:52 -07:00
2020-07-03 22:43:08 -07:00
expect ( ( ) => {
Object . defineProperty ( p , "bar" , { value : 6 , configurable : false } ) ;
} ) . toThrowWithMessage ( TypeError , "Proxy handler's defineProperty trap violates invariant: a property cannot be defined as non-configurable if it does not already exist on the target object" ) ;
2020-06-03 14:34:52 -07:00
} ) ;
2020-07-03 22:43:08 -07:00
test ( "trap cannot return true for a non-configurable property if it already exists as a configurable property" , ( ) => {
let o = { } ;
Object . defineProperty ( o , "foo" , { value : 10 , configurable : true } ) ;
let p = new Proxy ( o , {
defineProperty ( ) {
return true ;
} ,
} ) ;
2020-06-03 14:34:52 -07:00
2020-07-03 22:43:08 -07:00
expect ( ( ) => {
Object . defineProperty ( p , "foo" , { value : 6 , configurable : false } ) ;
} ) . toThrowWithMessage ( TypeError , "Proxy handler's defineProperty trap violates invariant: a property cannot be defined as non-configurable if it already exists on the target object as a configurable property" ) ;
} )
} ) ;