feat: budgeted console formatter (inspect builtin) - #416
Open
edusperoni wants to merge 2 commits into
Open
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…ed logging console.log without DevTools serialized entire object graphs through JSON.stringify with an O(n^2) seen-array, no depth or size limits, a hand-rolled array printer that only caught direct self-cycles, and a third bespoke dump in console.dir. A large object could hang the app for seconds and shared acyclic references printed as [Circular]. internal/inspect.js is a util.inspect-lite built on primordials: depth, per-collection and total-output budgets make unbounded work impossible; an ancestor set reports only true cycles; getters are never invoked (except the guarded error.stack read every error path already does); brands come from Object.prototype.toString so tampered prototypes cannot break or hijack logging. Native wrappers render as a short class-name hint via the binding bag instead of being walked. Console log/dir/assert all route through it, smart-stringify is retired, and the formatter doubles as the internal __inspect global.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Replaces the console's no-DevTools formatting pipeline — which could hang the app on a single
console.log— withinternal/inspect.js, a budgeted util.inspect-lite built on primordials. Stacked on #415 (primordials), which is stacked on #411 (builtins).The problem
console.log(obj)without a DevTools frontend serialized the whole object graph:JSON.stringify(obj, replacer, 2)with no depth or size limit — logging a store/component tree serialized everything reachable, then shipped megabytes through a stack-frame regex and NSLog.seenarray made cycle tracking O(n²) — quadratic interpreter work under jitless — and never popped on subtree exit, so shared acyclic references falsely printed[Circular].JSON.stringifyinvokes getters andtoJSON— a log line could execute arbitrary user code.console.dirhad a third bespoke dump with the same issues.The fix
inspect.js(function-body builtin, primordials-clean — it must work precisely when the app is broken):Set(enter/exit) — true cycles say[Circular], diamonds print normally, O(1) membership.[Getter]/[Setter]tags). Two deliberate exceptions: a guardederror.stackread (V8 materializes stacks via a lazy accessor and every error path in the runtime already reads it), and customtoStringoverrides — NativeScript core'sViewBase/Observableconvention (Button(42)-style short forms) is honored, matching the previous console: an own-or-inheritedtoStringother thanObject.prototype's is detected via descriptors (no invocation to detect), then invoked guarded and capped; broken overrides degrade to structural rendering.Object.prototype.toString, Map/Set walked through captured iteratornext(early-exit capable, unlikeforEach), sizes via captured accessor getters. Verified by device tests that breakArray.prototype.*,Object.keys,JSON.stringifyetc. and log anyway.[UILabel],[class UIView],[Pointer]) via abinding.getNativeWrapperHintnative callback instead of walking native-backed graphs.[Function: name]/[class Name], TypedArrays/ArrayBuffers with lengths, null-prototype and constructor-name prefixes, sparse arrays, BigInt, symbols.__inspectglobal (testability + app-level escape hatch).C++ side shrinks:
console.log/dir/assertall route through one cached formatter; the array printer, the dir dump, andsmart-stringify.js(+ itsHelpers/Cachesplumbing) are deleted. Top-level strings still print raw. If the formatter ever fails to initialize, logging degrades toToDetailStringinstead of breaking.Also extends
primordials.js(Set methods, iteratornextcaptures, accessor getters, brand/regexp helpers) and the ESLint captured-statics list.Output changes to be aware of
Logs now look like Node's inspect output —
{ a: 1, b: [Circular] },Map(3) { ... },... 150 more items, truncation markers — instead of pretty-printed JSON.console.dirkeeps its dump markers but uses depth 4.Testing
stackgetters and tampered prototypes.InspectTests.js): cycles vs diamonds, caps, getter non-invocation, native-wrapper hints, tampered-prototype formatting, and a regression test thatconsole.logof a 5000-node cyclic graph completes in bounded time.Also fixes a latent js2c bug this PR flushed out: builtin sources containing non-ASCII bytes (UTF-8 >= 0x80) failed to compile as
const chararray initializers; the generator now emitsunsigned char.