fix: remove proxy frames from stack traces

Proxy-related implementation frames were showing up in the stack
traces for failed property assertions. This commit removes them by
setting the proxy getter (instead of the property getter) as the
starting point to remove all implementation frames.
This commit is contained in:
Grant Snodgrass 2016-12-11 11:17:15 -05:00
parent 8fa4f78574
commit b88e53639e
4 changed files with 38 additions and 9 deletions

View file

@ -6,6 +6,7 @@
var chai = require('../../chai'); var chai = require('../../chai');
var flag = require('./flag'); var flag = require('./flag');
var isProxyEnabled = require('./isProxyEnabled');
var transferFlags = require('./transferFlags'); var transferFlags = require('./transferFlags');
/** /**
@ -39,10 +40,12 @@ module.exports = function addProperty(ctx, name, getter) {
Object.defineProperty(ctx, name, Object.defineProperty(ctx, name,
{ get: function propertyGetter() { { get: function propertyGetter() {
if (!isProxyEnabled()) {
var keep_ssfi = flag(this, 'keep_ssfi'); var keep_ssfi = flag(this, 'keep_ssfi');
var old_ssfi = flag(this, 'ssfi'); var old_ssfi = flag(this, 'ssfi');
if (!keep_ssfi && old_ssfi) if (!keep_ssfi && old_ssfi)
flag(this, 'ssfi', propertyGetter); flag(this, 'ssfi', propertyGetter);
}
var result = getter.call(this); var result = getter.call(this);
if (result !== undefined) if (result !== undefined)

View file

@ -6,6 +6,7 @@
var chai = require('../../chai'); var chai = require('../../chai');
var flag = require('./flag'); var flag = require('./flag');
var isProxyEnabled = require('./isProxyEnabled');
var transferFlags = require('./transferFlags'); var transferFlags = require('./transferFlags');
/** /**
@ -51,10 +52,12 @@ module.exports = function overwriteProperty(ctx, name, getter) {
Object.defineProperty(ctx, name, Object.defineProperty(ctx, name,
{ get: function overwritingPropertyGetter() { { get: function overwritingPropertyGetter() {
if (!isProxyEnabled()) {
var keep_ssfi = flag(this, 'keep_ssfi'); var keep_ssfi = flag(this, 'keep_ssfi');
var old_ssfi = flag(this, 'ssfi'); var old_ssfi = flag(this, 'ssfi');
if (!keep_ssfi && old_ssfi) if (!keep_ssfi && old_ssfi)
flag(this, 'ssfi', overwritingPropertyGetter); flag(this, 'ssfi', overwritingPropertyGetter);
}
flag(this, 'keep_ssfi', true); flag(this, 'keep_ssfi', true);
var result = getter(_super).call(this); var result = getter(_super).call(this);

View file

@ -1,4 +1,5 @@
var config = require('../config'); var config = require('../config');
var flag = require('./flag');
var getProperties = require('./getProperties'); var getProperties = require('./getProperties');
var isProxyEnabled = require('./isProxyEnabled'); var isProxyEnabled = require('./isProxyEnabled');
@ -27,6 +28,8 @@ var isProxyEnabled = require('./isProxyEnabled');
* @name proxify * @name proxify
*/ */
var builtins = ['__flags', '__methods', '_obj', 'assert'];
module.exports = function proxify(obj, nonChainableMethodName) { module.exports = function proxify(obj, nonChainableMethodName) {
if (!isProxyEnabled()) return obj; if (!isProxyEnabled()) return obj;
@ -48,7 +51,7 @@ module.exports = function proxify(obj, nonChainableMethodName) {
var orderedProperties = getProperties(target).filter(function(property) { var orderedProperties = getProperties(target).filter(function(property) {
return !Object.prototype.hasOwnProperty(property) && return !Object.prototype.hasOwnProperty(property) &&
['__flags', '__methods', '_obj', 'assert'].indexOf(property) === -1; builtins.indexOf(property) === -1;
}).sort(function(a, b) { }).sort(function(a, b) {
return stringDistance(property, a) - stringDistance(property, b); return stringDistance(property, a) - stringDistance(property, b);
}); });
@ -64,6 +67,10 @@ module.exports = function proxify(obj, nonChainableMethodName) {
} }
} }
if (builtins.indexOf(property) === -1) {
flag(target, 'ssfi', proxyGetter);
}
return Reflect.get(target, property); return Reflect.get(target, property);
} }
}); });

View file

@ -99,6 +99,10 @@ describe('configuration', function () {
it('should include Chai frames in stack trace', function () { it('should include Chai frames in stack trace', function () {
expect(caughtErr.stack).to.contain('propertyGetter'); expect(caughtErr.stack).to.contain('propertyGetter');
if (typeof Proxy !== 'undefined' && typeof Reflect !== 'undefined') {
expect(caughtErr.stack).to.contain('proxyGetter');
}
}); });
it('should include user frames in stack trace', function () { it('should include user frames in stack trace', function () {
@ -121,6 +125,10 @@ describe('configuration', function () {
it('should include Chai frames in stack trace', function () { it('should include Chai frames in stack trace', function () {
expect(caughtErr.stack).to.contain('overwritingPropertyGetter'); expect(caughtErr.stack).to.contain('overwritingPropertyGetter');
if (typeof Proxy !== 'undefined' && typeof Reflect !== 'undefined') {
expect(caughtErr.stack).to.contain('proxyGetter');
}
}); });
it('should include user frames in stack trace', function () { it('should include user frames in stack trace', function () {
@ -233,6 +241,10 @@ describe('configuration', function () {
it('should not include Chai frames in stack trace', function () { it('should not include Chai frames in stack trace', function () {
expect(caughtErr.stack).to.not.contain('propertyGetter'); expect(caughtErr.stack).to.not.contain('propertyGetter');
if (typeof Proxy !== 'undefined' && typeof Reflect !== 'undefined') {
expect(caughtErr.stack).to.not.contain('proxyGetter');
}
}); });
it('should include user frames in stack trace', function () { it('should include user frames in stack trace', function () {
@ -255,6 +267,10 @@ describe('configuration', function () {
it('should not include Chai frames in stack trace', function () { it('should not include Chai frames in stack trace', function () {
expect(caughtErr.stack).to.not.contain('overwritingPropertyGetter'); expect(caughtErr.stack).to.not.contain('overwritingPropertyGetter');
if (typeof Proxy !== 'undefined' && typeof Reflect !== 'undefined') {
expect(caughtErr.stack).to.not.contain('proxyGetter');
}
}); });
it('should include user frames in stack trace', function () { it('should include user frames in stack trace', function () {