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 60details = processUtil.getProxyDetails({}, true); 61assert.strictEqual(details, undefined); 62 63const r = Proxy.revocable({}, {}); 64r.revoke(); 65 66details = processUtil.getProxyDetails(r.proxy, true); 67assert.strictEqual(details[0], null); 68assert.strictEqual(details[1], null); 69 70details = processUtil.getProxyDetails(r.proxy, false); 71assert.strictEqual(details, null); 72 73assert.strictEqual(util.inspect(r.proxy), '<Revoked Proxy>'); 74assert.strictEqual( 75 util.inspect(r, { showProxy: true }), 76 '{ proxy: <Revoked Proxy>, revoke: [Function (anonymous)] }', 77); 78 79assert.strictEqual(util.format('%s', r.proxy), '<Revoked Proxy>'); 80 81assert.strictEqual( 82 util.inspect(proxyObj, opts), 83 'Proxy [\n' + 84 ' [ 1, 2, 3 ],\n' + 85 ' {\n' + 86 ' getPrototypeOf: [Function: getPrototypeOf],\n' + 87 ' setPrototypeOf: [Function: setPrototypeOf],\n' + 88 ' isExtensible: [Function: isExtensible],\n' + 89 ' preventExtensions: [Function: preventExtensions],\n' + 90 ' getOwnPropertyDescriptor: [Function: getOwnPropertyDescriptor],\n' + 91 ' defineProperty: [Function: defineProperty],\n' + 92 ' has: [Function: has],\n' + 93 ' get: [Function: get],\n' + 94 ' set: [Function: set],\n' + 95 ' deleteProperty: [Function: deleteProperty],\n' + 96 ' ownKeys: [Function: ownKeys],\n' + 97 ' apply: [Function: apply],\n' + 98 ' construct: [Function: construct]\n' + 99 ' }\n' + 100 ']' 101); 102 103// Using getProxyDetails with non-proxy returns undefined 104assert.strictEqual(processUtil.getProxyDetails({}), undefined); 105 106// Inspecting a proxy without the showProxy option set to true should not 107// trigger any proxy handlers. 108assert.strictEqual(util.inspect(proxyObj), '[ 1, 2, 3 ]'); 109assert(called); 110 111// Yo dawg, I heard you liked Proxy so I put a Proxy 112// inside your Proxy that proxies your Proxy's Proxy. 113const proxy1 = new Proxy({}, {}); 114const proxy2 = new Proxy(proxy1, {}); 115const proxy3 = new Proxy(proxy2, proxy1); 116const proxy4 = new Proxy(proxy1, proxy2); 117const proxy5 = new Proxy(proxy3, proxy4); 118const proxy6 = new Proxy(proxy5, proxy5); 119const expected0 = '{}'; 120const expected1 = 'Proxy [ {}, {} ]'; 121const expected2 = 'Proxy [ Proxy [ {}, {} ], {} ]'; 122const expected3 = 'Proxy [ Proxy [ Proxy [ {}, {} ], {} ], Proxy [ {}, {} ] ]'; 123const expected4 = 'Proxy [ Proxy [ {}, {} ], Proxy [ Proxy [ {}, {} ], {} ] ]'; 124const expected5 = 'Proxy [\n ' + 125 'Proxy [ Proxy [ Proxy [Array], {} ], Proxy [ {}, {} ] ],\n' + 126 ' Proxy [ Proxy [ {}, {} ], Proxy [ Proxy [Array], {} ] ]' + 127 '\n]'; 128const expected6 = 'Proxy [\n' + 129 ' Proxy [\n' + 130 ' Proxy [ Proxy [Array], Proxy [Array] ],\n' + 131 ' Proxy [ Proxy [Array], Proxy [Array] ]\n' + 132 ' ],\n' + 133 ' Proxy [\n' + 134 ' Proxy [ Proxy [Array], Proxy [Array] ],\n' + 135 ' Proxy [ Proxy [Array], Proxy [Array] ]\n' + 136 ' ]\n' + 137 ']'; 138assert.strictEqual( 139 util.inspect(proxy1, { showProxy: 1, depth: null }), 140 expected1); 141assert.strictEqual(util.inspect(proxy2, opts), expected2); 142assert.strictEqual(util.inspect(proxy3, opts), expected3); 143assert.strictEqual(util.inspect(proxy4, opts), expected4); 144assert.strictEqual(util.inspect(proxy5, opts), expected5); 145assert.strictEqual(util.inspect(proxy6, opts), expected6); 146assert.strictEqual(util.inspect(proxy1), expected0); 147assert.strictEqual(util.inspect(proxy2), expected0); 148assert.strictEqual(util.inspect(proxy3), expected0); 149assert.strictEqual(util.inspect(proxy4), expected0); 150assert.strictEqual(util.inspect(proxy5), expected0); 151assert.strictEqual(util.inspect(proxy6), expected0); 152 153// Just for fun, let's create a Proxy using Arrays. 154const proxy7 = new Proxy([], []); 155const expected7 = 'Proxy [ [], [] ]'; 156assert.strictEqual(util.inspect(proxy7, opts), expected7); 157assert.strictEqual(util.inspect(proxy7), '[]'); 158 159// Now we're just getting silly, right? 160const proxy8 = new Proxy(Date, []); 161const proxy9 = new Proxy(Date, String); 162const expected8 = 'Proxy [ [Function: Date], [] ]'; 163const expected9 = 'Proxy [ [Function: Date], [Function: String] ]'; 164assert.strictEqual(util.inspect(proxy8, opts), expected8); 165assert.strictEqual(util.inspect(proxy9, opts), expected9); 166assert.strictEqual(util.inspect(proxy8), '[Function: Date]'); 167assert.strictEqual(util.inspect(proxy9), '[Function: Date]'); 168 169const proxy10 = new Proxy(() => {}, {}); 170const proxy11 = new Proxy(() => {}, { 171 get() { 172 return proxy11; 173 }, 174 apply() { 175 return proxy11; 176 } 177}); 178const expected10 = '[Function (anonymous)]'; 179const expected11 = '[Function (anonymous)]'; 180assert.strictEqual(util.inspect(proxy10), expected10); 181assert.strictEqual(util.inspect(proxy11), expected11); 182