mirror of https://github.com/lukechilds/node.git
Browse Source
In certain conditions, inspecting a Proxy object can lead to a max call stack error. Avoid that by detecting the Proxy object and outputting information about the Proxy object itself. Fixes: https://github.com/nodejs/node/issues/6464 PR-URL: https://github.com/nodejs/node/pull/6465 Reviewed-By: Myles Borins <myles.borins@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>process-exit-stdio-flushing
James M Snell
9 years ago
5 changed files with 189 additions and 1 deletions
@ -0,0 +1,44 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
const util = require('util'); |
||||
|
const common = require('../common.js'); |
||||
|
|
||||
|
const bench = common.createBenchmark(main, { |
||||
|
v: [1, 2], |
||||
|
n: [1e6] |
||||
|
}); |
||||
|
|
||||
|
function twoDifferentProxies(n) { |
||||
|
// This one should be slower between we're looking up multiple proxies.
|
||||
|
const proxyA = new Proxy({}, {get: () => {}}); |
||||
|
const proxyB = new Proxy({}, {get: () => {}}); |
||||
|
bench.start(); |
||||
|
for (var i = 0; i < n; i += 1) |
||||
|
util.inspect({a: proxyA, b: proxyB}, {showProxy: true}); |
||||
|
bench.end(n); |
||||
|
} |
||||
|
|
||||
|
function oneProxy(n) { |
||||
|
// This one should be a bit faster because of the internal caching.
|
||||
|
const proxy = new Proxy({}, {get: () => {}}); |
||||
|
bench.start(); |
||||
|
for (var i = 0; i < n; i += 1) |
||||
|
util.inspect({a: proxy, b: proxy}, {showProxy: true}); |
||||
|
bench.end(n); |
||||
|
} |
||||
|
|
||||
|
function main(conf) { |
||||
|
const n = conf.n | 0; |
||||
|
const v = conf.v | 0; |
||||
|
|
||||
|
switch (v) { |
||||
|
case 1: |
||||
|
oneProxy(n); |
||||
|
break; |
||||
|
case 2: |
||||
|
twoDifferentProxies(n); |
||||
|
break; |
||||
|
default: |
||||
|
throw new Error('Should not get to here'); |
||||
|
} |
||||
|
} |
@ -0,0 +1,84 @@ |
|||||
|
'use strict'; |
||||
|
|
||||
|
require('../common'); |
||||
|
const assert = require('assert'); |
||||
|
const util = require('util'); |
||||
|
const processUtil = process.binding('util'); |
||||
|
const opts = {showProxy: true}; |
||||
|
|
||||
|
const target = {}; |
||||
|
const handler = { |
||||
|
get: function() { throw new Error('Getter should not be called'); } |
||||
|
}; |
||||
|
const proxyObj = new Proxy(target, handler); |
||||
|
|
||||
|
// Inspecting the proxy should not actually walk it's properties
|
||||
|
assert.doesNotThrow(() => util.inspect(proxyObj, opts)); |
||||
|
|
||||
|
// getProxyDetails is an internal method, not intended for public use.
|
||||
|
// This is here to test that the internals are working correctly.
|
||||
|
const details = processUtil.getProxyDetails(proxyObj); |
||||
|
assert.strictEqual(target, details[0]); |
||||
|
assert.strictEqual(handler, details[1]); |
||||
|
|
||||
|
assert.strictEqual(util.inspect(proxyObj, opts), |
||||
|
'Proxy [ {}, { get: [Function] } ]'); |
||||
|
|
||||
|
// Using getProxyDetails with non-proxy returns undefined
|
||||
|
assert.strictEqual(processUtil.getProxyDetails({}), undefined); |
||||
|
|
||||
|
// This will throw because the showProxy option is not used
|
||||
|
// and the get function on the handler object defined above
|
||||
|
// is actually invoked.
|
||||
|
assert.throws( |
||||
|
() => util.inspect(proxyObj) |
||||
|
); |
||||
|
|
||||
|
// Yo dawg, I heard you liked Proxy so I put a Proxy
|
||||
|
// inside your Proxy that proxies your Proxy's Proxy.
|
||||
|
const proxy1 = new Proxy({}, {}); |
||||
|
const proxy2 = new Proxy(proxy1, {}); |
||||
|
const proxy3 = new Proxy(proxy2, proxy1); |
||||
|
const proxy4 = new Proxy(proxy1, proxy2); |
||||
|
const proxy5 = new Proxy(proxy3, proxy4); |
||||
|
const proxy6 = new Proxy(proxy5, proxy5); |
||||
|
const expected0 = '{}'; |
||||
|
const expected1 = 'Proxy [ {}, {} ]'; |
||||
|
const expected2 = 'Proxy [ Proxy [ {}, {} ], {} ]'; |
||||
|
const expected3 = 'Proxy [ Proxy [ Proxy [ {}, {} ], {} ], Proxy [ {}, {} ] ]'; |
||||
|
const expected4 = 'Proxy [ Proxy [ {}, {} ], Proxy [ Proxy [ {}, {} ], {} ] ]'; |
||||
|
const expected5 = 'Proxy [ Proxy [ Proxy [ Proxy [Object], {} ],' + |
||||
|
' Proxy [ {}, {} ] ],\n Proxy [ Proxy [ {}, {} ]' + |
||||
|
', Proxy [ Proxy [Object], {} ] ] ]'; |
||||
|
const expected6 = 'Proxy [ Proxy [ Proxy [ Proxy [Object], Proxy [Object]' + |
||||
|
' ],\n Proxy [ Proxy [Object], Proxy [Object] ] ],\n' + |
||||
|
' Proxy [ Proxy [ Proxy [Object], Proxy [Object] ],\n' + |
||||
|
' Proxy [ Proxy [Object], Proxy [Object] ] ] ]'; |
||||
|
assert.strictEqual(util.inspect(proxy1, opts), expected1); |
||||
|
assert.strictEqual(util.inspect(proxy2, opts), expected2); |
||||
|
assert.strictEqual(util.inspect(proxy3, opts), expected3); |
||||
|
assert.strictEqual(util.inspect(proxy4, opts), expected4); |
||||
|
assert.strictEqual(util.inspect(proxy5, opts), expected5); |
||||
|
assert.strictEqual(util.inspect(proxy6, opts), expected6); |
||||
|
assert.strictEqual(util.inspect(proxy1), expected0); |
||||
|
assert.strictEqual(util.inspect(proxy2), expected0); |
||||
|
assert.strictEqual(util.inspect(proxy3), expected0); |
||||
|
assert.strictEqual(util.inspect(proxy4), expected0); |
||||
|
assert.strictEqual(util.inspect(proxy5), expected0); |
||||
|
assert.strictEqual(util.inspect(proxy6), expected0); |
||||
|
|
||||
|
// Just for fun, let's create a Proxy using Arrays.
|
||||
|
const proxy7 = new Proxy([], []); |
||||
|
const expected7 = 'Proxy [ [], [] ]'; |
||||
|
assert.strictEqual(util.inspect(proxy7, opts), expected7); |
||||
|
assert.strictEqual(util.inspect(proxy7), '[]'); |
||||
|
|
||||
|
// Now we're just getting silly, right?
|
||||
|
const proxy8 = new Proxy(Date, []); |
||||
|
const proxy9 = new Proxy(Date, String); |
||||
|
const expected8 = 'Proxy [ [Function: Date], [] ]'; |
||||
|
const expected9 = 'Proxy [ [Function: Date], [Function: String] ]'; |
||||
|
assert.strictEqual(util.inspect(proxy8, opts), expected8); |
||||
|
assert.strictEqual(util.inspect(proxy9, opts), expected9); |
||||
|
assert.strictEqual(util.inspect(proxy8), '[Function: Date]'); |
||||
|
assert.strictEqual(util.inspect(proxy9), '[Function: Date]'); |
Loading…
Reference in new issue