@@ -1330,38 +1330,118 @@ const Zone: ZoneType = (function(global: any) {
1330
1330
let frameParserStrategy = null ;
1331
1331
const stackRewrite = 'stackRewrite' ;
1332
1332
1333
- const assignAll = function ( to , from ) {
1334
- if ( ! to ) {
1335
- return to ;
1333
+ // fix #595, create property descriptor
1334
+ // for error properties
1335
+ const createProperty = function ( props , key ) {
1336
+ // if property is already defined, skip it.
1337
+ if ( props [ key ] ) {
1338
+ return ;
1336
1339
}
1340
+ // define a local property
1341
+ // in case error property is not settable
1342
+ const name = __symbol__ ( key ) ;
1343
+ props [ key ] = {
1344
+ configurable : true ,
1345
+ enumerable : true ,
1346
+ get : function ( ) {
1347
+ // if local property has no value
1348
+ // use internal error's property value
1349
+ if ( ! this [ name ] ) {
1350
+ const error = this [ __symbol__ ( 'error' ) ] ;
1351
+ if ( error ) {
1352
+ this [ name ] = error [ key ] ;
1353
+ }
1354
+ }
1355
+ return this [ name ] ;
1356
+ } ,
1357
+ set : function ( value ) {
1358
+ // setter will set value to local property value
1359
+ this [ name ] = value ;
1360
+ }
1361
+ } ;
1362
+ } ;
1337
1363
1338
- if ( from ) {
1339
- let keys = Object . getOwnPropertyNames ( from ) ;
1340
- for ( let i = 0 ; i < keys . length ; i ++ ) {
1341
- const key = keys [ i ] ;
1342
- // Avoid bugs when hasOwnProperty is shadowed
1343
- if ( Object . prototype . hasOwnProperty . call ( from , key ) ) {
1344
- to [ key ] = from [ key ] ;
1364
+ // fix #595, create property descriptor
1365
+ // for error method properties
1366
+ const createMethodProperty = function ( props , key ) {
1367
+ if ( props [ key ] ) {
1368
+ return ;
1369
+ }
1370
+ props [ key ] = {
1371
+ configurable : true ,
1372
+ enumerable : true ,
1373
+ writable : true ,
1374
+ value : function ( ) {
1375
+ const error = this [ __symbol__ ( 'error' ) ] ;
1376
+ let errorMethod = ( error && error [ key ] ) || this [ key ] ;
1377
+ if ( errorMethod ) {
1378
+ return errorMethod . apply ( error , arguments ) ;
1345
1379
}
1346
1380
}
1381
+ } ;
1382
+ } ;
1347
1383
1348
- // copy all properties from prototype
1349
- // in Error, property such as name/message is in Error's prototype
1350
- // but not enumerable, so we copy those properties through
1351
- // Error's prototype
1352
- const proto = Object . getPrototypeOf ( from ) ;
1353
- if ( proto ) {
1354
- let pKeys = Object . getOwnPropertyNames ( proto ) ;
1355
- for ( let i = 0 ; i < pKeys . length ; i ++ ) {
1356
- const key = pKeys [ i ] ;
1357
- // skip constructor
1358
- if ( key !== 'constructor' ) {
1359
- to [ key ] = from [ key ] ;
1360
- }
1384
+ const createErrorProperties = function ( ) {
1385
+ const props = Object . create ( null ) ;
1386
+
1387
+ const error = new NativeError ( ) ;
1388
+ let keys = Object . getOwnPropertyNames ( error ) ;
1389
+ for ( let i = 0 ; i < keys . length ; i ++ ) {
1390
+ const key = keys [ i ] ;
1391
+ // Avoid bugs when hasOwnProperty is shadowed
1392
+ if ( Object . prototype . hasOwnProperty . call ( error , key ) ) {
1393
+ createProperty ( props , key ) ;
1394
+ }
1395
+ }
1396
+
1397
+ const proto = NativeError . prototype ;
1398
+ if ( proto ) {
1399
+ let pKeys = Object . getOwnPropertyNames ( proto ) ;
1400
+ for ( let i = 0 ; i < pKeys . length ; i ++ ) {
1401
+ const key = pKeys [ i ] ;
1402
+ // skip constructor
1403
+ if ( key !== 'constructor' && key !== 'toString' && key !== 'toSource' ) {
1404
+ createProperty ( props , key ) ;
1361
1405
}
1362
1406
}
1363
1407
}
1364
- return to ;
1408
+
1409
+ // some other properties are not
1410
+ // in NativeError
1411
+ createProperty ( props , 'originalStack' ) ;
1412
+ createProperty ( props , 'zoneAwareStack' ) ;
1413
+
1414
+ // define toString, toSource as method property
1415
+ createMethodProperty ( props , 'toString' ) ;
1416
+ createMethodProperty ( props , 'toSource' ) ;
1417
+ return props ;
1418
+ } ;
1419
+
1420
+ const errorProperties = createErrorProperties ( ) ;
1421
+
1422
+ // for derived Error class which extends ZoneAwareError
1423
+ // we should not override the derived class's property
1424
+ // so we create a new props object only copy the properties
1425
+ // from errorProperties which not exist in derived Error's prototype
1426
+ const getErrorPropertiesForPrototype = function ( prototype ) {
1427
+ // if the prototype is ZoneAwareError.prototype
1428
+ // we just return the prebuilt errorProperties.
1429
+ if ( prototype === ZoneAwareError . prototype ) {
1430
+ return errorProperties ;
1431
+ }
1432
+ const newProps = Object . create ( null ) ;
1433
+ const cKeys = Object . getOwnPropertyNames ( errorProperties ) ;
1434
+ const keys = Object . getOwnPropertyNames ( prototype ) ;
1435
+ cKeys . forEach ( cKey => {
1436
+ if ( keys . filter ( key => {
1437
+ return key === cKey ;
1438
+ } )
1439
+ . length === 0 ) {
1440
+ newProps [ cKey ] = errorProperties [ cKey ] ;
1441
+ }
1442
+ } ) ;
1443
+
1444
+ return newProps ;
1365
1445
} ;
1366
1446
1367
1447
/**
@@ -1378,6 +1458,7 @@ const Zone: ZoneType = (function(global: any) {
1378
1458
}
1379
1459
// Create an Error.
1380
1460
let error : Error = NativeError . apply ( this , arguments ) ;
1461
+ this [ __symbol__ ( 'error' ) ] = error ;
1381
1462
1382
1463
// Save original stack trace
1383
1464
error . originalStack = error . stack ;
@@ -1414,7 +1495,10 @@ const Zone: ZoneType = (function(global: any) {
1414
1495
}
1415
1496
error . stack = error . zoneAwareStack = frames . join ( '\n' ) ;
1416
1497
}
1417
- return assignAll ( this , error ) ;
1498
+ // use defineProperties here instead of copy property value
1499
+ // because of issue #595 which will break angular2.
1500
+ Object . defineProperties ( this , getErrorPropertiesForPrototype ( Object . getPrototypeOf ( this ) ) ) ;
1501
+ return this ;
1418
1502
}
1419
1503
1420
1504
// Copy the prototype so that instanceof operator works as expected
0 commit comments