1// Flags: --expose-internals 2'use strict'; 3 4require('../common'); 5const assert = require('assert'); 6const util = require('util'); 7const { internalBinding } = require('internal/test/binding'); 8const processUtil = internalBinding('util'); 9const opts = { showProxy: true }; 10 11let proxyObj; 12let called = false; 13const target = { 14 [util.inspect.custom](depth, { showProxy }) { 15 if (showProxy === false) { 16 called = true; 17 if (proxyObj !== this) { 18 throw new Error('Failed'); 19 } 20 } 21 return [1, 2, 3]; 22 } 23}; 24const handler = { 25 getPrototypeOf() { throw new Error('getPrototypeOf'); }, 26 setPrototypeOf() { throw new Error('setPrototypeOf'); }, 27 isExtensible() { throw new Error('isExtensible'); }, 28 preventExtensions() { throw new Error('preventExtensions'); }, 29 getOwnPropertyDescriptor() { throw new Error('getOwnPropertyDescriptor'); }, 30 defineProperty() { throw new Error('defineProperty'); }, 31 has() { throw new Error('has'); }, 32 get() { throw new Error('get'); }, 33 set() { throw new Error('set'); }, 34 deleteProperty() { throw new Error('deleteProperty'); }, 35 ownKeys() { throw new Error('ownKeys'); }, 36 apply() { throw new Error('apply'); }, 37 construct() { throw new Error('construct'); } 38}; 39proxyObj = new Proxy(target, handler); 40 41// Inspecting the proxy should not actually walk it's properties 42util.inspect(proxyObj, opts); 43 44// Make sure inspecting object does not trigger any proxy traps. 45util.format('%s', proxyObj); 46 47// getProxyDetails is an internal method, not intended for public use. 48// This is here to test that the internals are working correctly. 49let details = processUtil.getProxyDetails(proxyObj, true); 50assert.strictEqual(target, details[0]); 51assert.strictEqual(handler, details[1]); 52 53details = processUtil.getProxyDetails(proxyObj); 54assert.strictEqual(target, details[0]); 55assert.strictEqual(handler, details[1]); 56 57details = processUtil.getProxyDetails(proxyObj, false); 58assert.strictEqual(target, details); 59 60assert.strictEqual( 61 util.inspect(proxyObj, opts), 62 'Proxy [\n' + 63 ' [ 1, 2, 3 ],\n' + 64 ' {\n' + 65 ' getPrototypeOf: [Function: getPrototypeOf],\n' + 66 ' setPrototypeOf: [Function: setPrototypeOf],\n' + 67 ' isExtensible: [Function: isExtensible],\n' + 68 ' preventExtensions: [Function: preventExtensions],\n' + 69 ' getOwnPropertyDescriptor: [Function: getOwnPropertyDescriptor],\n' + 70 ' defineProperty: [Function: defineProperty],\n' + 71 ' has: [Function: has],\n' + 72 ' get: [Function: get],\n' + 73 ' set: [Function: set],\n' + 74 ' deleteProperty: [Function: deleteProperty],\n' + 75 ' ownKeys: [Function: ownKeys],\n' + 76 ' apply: [Function: apply],\n' + 77 ' construct: [Function: construct]\n' + 78 ' }\n' + 79 ']' 80); 81 82// Using getProxyDetails with non-proxy returns undefined 83assert.strictEqual(processUtil.getProxyDetails({}), undefined); 84 85// Inspecting a proxy without the showProxy option set to true should not 86// trigger any proxy handlers. 87assert.strictEqual(util.inspect(proxyObj), '[ 1, 2, 3 ]'); 88assert(called); 89 90// Yo dawg, I heard you liked Proxy so I put a Proxy 91// inside your Proxy that proxies your Proxy's Proxy. 92const proxy1 = new Proxy({}, {}); 93const proxy2 = new Proxy(proxy1, {}); 94const proxy3 = new Proxy(proxy2, proxy1); 95const proxy4 = new Proxy(proxy1, proxy2); 96const proxy5 = new Proxy(proxy3, proxy4); 97const proxy6 = new Proxy(proxy5, proxy5); 98const expected0 = '{}'; 99const expected1 = 'Proxy [ {}, {} ]'; 100const expected2 = 'Proxy [ Proxy [ {}, {} ], {} ]'; 101const expected3 = 'Proxy [ Proxy [ Proxy [ {}, {} ], {} ], Proxy [ {}, {} ] ]'; 102const expected4 = 'Proxy [ Proxy [ {}, {} ], Proxy [ Proxy [ {}, {} ], {} ] ]'; 103const expected5 = 'Proxy [\n ' + 104 'Proxy [ Proxy [ Proxy [Array], {} ], Proxy [ {}, {} ] ],\n' + 105 ' Proxy [ Proxy [ {}, {} ], Proxy [ Proxy [Array], {} ] ]' + 106 '\n]'; 107const expected6 = 'Proxy [\n' + 108 ' Proxy [\n' + 109 ' Proxy [ Proxy [Array], Proxy [Array] ],\n' + 110 ' Proxy [ Proxy [Array], Proxy [Array] ]\n' + 111 ' ],\n' + 112 ' Proxy [\n' + 113 ' Proxy [ Proxy [Array], Proxy [Array] ],\n' + 114 ' Proxy [ Proxy [Array], Proxy [Array] ]\n' + 115 ' ]\n' + 116 ']'; 117assert.strictEqual( 118 util.inspect(proxy1, { showProxy: 1, depth: null }), 119 expected1); 120assert.strictEqual(util.inspect(proxy2, opts), expected2); 121assert.strictEqual(util.inspect(proxy3, opts), expected3); 122assert.strictEqual(util.inspect(proxy4, opts), expected4); 123assert.strictEqual(util.inspect(proxy5, opts), expected5); 124assert.strictEqual(util.inspect(proxy6, opts), expected6); 125assert.strictEqual(util.inspect(proxy1), expected0); 126assert.strictEqual(util.inspect(proxy2), expected0); 127assert.strictEqual(util.inspect(proxy3), expected0); 128assert.strictEqual(util.inspect(proxy4), expected0); 129assert.strictEqual(util.inspect(proxy5), expected0); 130assert.strictEqual(util.inspect(proxy6), expected0); 131 132// Just for fun, let's create a Proxy using Arrays. 133const proxy7 = new Proxy([], []); 134const expected7 = 'Proxy [ [], [] ]'; 135assert.strictEqual(util.inspect(proxy7, opts), expected7); 136assert.strictEqual(util.inspect(proxy7), '[]'); 137 138// Now we're just getting silly, right? 139const proxy8 = new Proxy(Date, []); 140const proxy9 = new Proxy(Date, String); 141const expected8 = 'Proxy [ [Function: Date], [] ]'; 142const expected9 = 'Proxy [ [Function: Date], [Function: String] ]'; 143assert.strictEqual(util.inspect(proxy8, opts), expected8); 144assert.strictEqual(util.inspect(proxy9, opts), expected9); 145assert.strictEqual(util.inspect(proxy8), '[Function: Date]'); 146assert.strictEqual(util.inspect(proxy9), '[Function: Date]'); 147 148const proxy10 = new Proxy(() => {}, {}); 149const proxy11 = new Proxy(() => {}, { 150 get() { 151 return proxy11; 152 }, 153 apply() { 154 return proxy11; 155 } 156}); 157const expected10 = '[Function (anonymous)]'; 158const expected11 = '[Function (anonymous)]'; 159assert.strictEqual(util.inspect(proxy10), expected10); 160assert.strictEqual(util.inspect(proxy11), expected11); 161