Skip to content

Conversation

@alexfmpe
Copy link
Member

@alexfmpe alexfmpe commented Jan 5, 2020

When ran on the obelisk skeleton:
node-callstack

It would be convenient being able to know what place in the codebase a widget is coming from. The idea here being that one can directly right-click it, choose 'Inspect element' and read the comment immediately before the node. That said, this brings several annoying concerns to the table.

Security

It sounds like a very bad idea to allow easily deploying closed source code which leaks this much info about itself. I was planning to gate this behavior based on whether --interactive was being passed to ghc, but there seems to be no way to detect that with CPP? Maybe we could add a cabal flag for this purpose that would both force --interactive and add a CPP flag to gate on instead? I don't know how this sort of configuration is usually handled.

Scope

place in the codebase a widget is coming from

is very fuzzy given all the factoring, (re)composing and delegating that happens - I see things divided in

  1. the point where element and the el family of functions are called
  2. framework/middleware/lib in between your call in 1 and reflex-dom (e.g. the DomBuilder chain coming from obelisk in the screenshot)
  3. the call stack of your own app/lib that leads down to 1

I think it should mean at least 1 since this is the usual way of telling reflex-dom to create nodes (hence where the execution "leaves" your code), but depending on use case one might want to include 2 and/or 3.

From a quick look, it seems 3 can be "turned on globally" in an application by adding CallStack to the typical all-the-app-wide-constraints synonym (AppWidget or something similar).

@tomsmalley suggested adding a transformer for controlling this behavior, which would make it easy to control scope, e.g.

  • adding "runTransformer" at some desired scope
  • supplying some configuration to the transformer - examples: keeping only 1, filtering out obelisk, filtering out lifted element entries coming from reflex-dom (see removeSelf)

Performance

I'm assuming this will never ever ever ever run outside ghci, where we can quickly toggle it off if in the unlikely case it turns out to have a remotely noticeable effect at some point.

prependCallStackComment cs w = do
let
removeSelf :: [([Char], SrcLoc)] -> [([Char], SrcLoc)]
removeSelf = filter $ not . ("reflex-dom-core" `isPrefixOf`) . srcLocPackage . snd
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reflex-dom-core shouldn't be hardcoded - but how?
Using packageName?
Adding a getPackageName :: CallStack function that wraps a let/where binding with HasCallStack => to grab it from there?
Template Haskell?

return $ CommentNode ()
{-# INLINABLE element #-}
element elementTag cfg child = do
element elementTag cfg child = prependCallStackComment callStack $ do
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably want to do this for inputElement / selectElement / textAreaElement as well

@3noch
Copy link
Member

3noch commented Jan 5, 2020

A transformer might have some performance impact so we'd still want to benchmark if we took anything other than a CPP-like route.

@hamishmack
Copy link
Contributor

Please take a look at #217 and perhaps fix up the merge conflicts and check it still works (I have not had time). It uses the debug feature in ghcjs-dom to do something very similar to this PR, but has a some advantages:

  • It works for anything created with the ghcjs-dom createElement functions.
  • It stores the stacks in a cache so DOM overhead should be lower.
  • The shift-right-click menu provided by addDebugMenu includes not just the call stack of the selected element, but also the stacks of parent elements.
  • Selecting a call stack item in the menu and outputs the source location to stdout in a format IDEs (so far only Leksah that I know of) can use to jump to the source location.

I think the CSS the menu uses might need to be made more robust (the menu sometimes does not display nicely if it conflicts with the applications own CSS).

@alexfmpe
Copy link
Member Author

alexfmpe commented Jan 6, 2020

Oh damn I hadn't seen that one, it does look much better

@alexfmpe alexfmpe closed this Jan 6, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants