Hacker News new | ask | show | jobs
by zackmorris 927 days ago
The same thing happens with https://www.wolframalpha.com for me in Safari on macOS, where I frequenly get 250% CPU usage. Even with Safari->Develop->Disable JavaScript, after showing the Develop menu with Safari->Preferences...->Advanced->Show Develop menu in menu bar. Sounds like it's due to the css using time or animations. I can't find a fix for it, other than disabling Safari->Develop->Disable Styles, but who wants to surf the web without css?

Here is an AppleScript I've hacked together over time to show the Safari tab for a PID from Activity Monitor so it can be closed, note that I'm on macOS 10.13.6 on this old 2011 Mac Mini, using Safari 13.1.2, so YMMV:

  -- launch Activity Monitor to find the PID of a misbehaving tab and show it with this script
  
  -- ensure that Safari->Debug->Miscellaneous Flags->Show Web Process IDs in Page Titles is enabled
  tell application "System Events" to tell process "Safari"
    -- ensure that user has enabled assistive access
    try
      menu 1 of menu bar item "Safari" of menu bar 1 -- throws exception if menu not visible
    on error
      display dialog "Please enable assistive access for this script by dragging it into the list of apps in:
  
  System Preferences->Security & Privacy->Privacy->Accessibility
  
  (It must be disabled and re-enabled each time this script is edited)" buttons {"OK"} default button "OK"
      return
    end try
    
    -- ensure that user has enabled Show Web Process IDs in Page Titles
    try
      set debugMenu to menu 1 of menu bar item "Debug" of menu bar 1 -- throws exception if menu not visible
    on error
      display dialog "Enable Debug menu in Safari? It will be relaunched but preserve any open windows." -- stops script if Cancel is clicked
      do shell script "defaults write com.apple.Safari IncludeInternalDebugMenu 1 && killall Safari && osascript -e 'tell application \"Safari\" to activate'" -- force quit Safari to preserve windows on relaunch
      return
    end try
    
    tell menu item "Show Web Process IDs in Page Titles" of menu 1 of menu item "Miscellaneous Flags" of debugMenu
      if (value of attribute "AXMenuItemMarkChar" as string) is "missing value" then click
    end tell
  end tell
  
  -- show tab matching string, prepopulated with [WP _pid_]
  set searchString to text returned of (display dialog "Please enter a string to find the Safari tab containing it:
  
  ([WP _pid_] from Activity Monitor for convenience)" default answer "[WP _pid_]")
  
  tell application "Safari"
    -- bring frontmost to avoid App Tamer from slowing script
    activate
    
    repeat with w from 1 to count of windows
      repeat 1 times
        try
          set theTab to (first tab of window w whose name contains searchString)
        on error
          exit repeat
        end try
        set current tab of window w to theTab
        
        -- work around a bug/feature of Safari where windows lack a way to bring them to front
        if index of window w is not 1 then
          set index of window w to 2
          tell application "System Events"
            tell application process "Safari"
              keystroke "`" using command down
            end tell
          end tell
        end if
        return
      end repeat
    end repeat
    
    display dialog "Couldn't find tab containing \"" & searchString & "\"." buttons {"OK"} default button "OK"
  end tell
Just open Script Editor, paste it in and save it as an application under ~/Library/Scripts or by choosing Script menu->Open Scripts Folder->Open User Scripts Folder. The Script menu can be shown via Script Editor->Preferences->General->Show Script menu in menu bar. Then run it and follow the prompts to ensure that assistive access has been enabled and that tabs show their PID.

The script is loosely derived from:

https://hea-www.harvard.edu/~fine/OSX/safari-tabs.html

https://apple.stackexchange.com/questions/45768/how-can-i-fi...

I tried to make a version that just shows the Safari tab having a pid, but lost a day to it doing a deep dive into listing windows and their pid:

https://stackoverflow.com/questions/48058409/get-windows-wit...

https://stackoverflow.com/questions/14551419/listing-all-win...

https://stackoverflow.com/questions/42018149/get-pids-of-all...

Unfortunately Apple made AppleScript and Automator so arduous to use that I consider them adversarial programming. Like with MS Visual Basic, there's usually less than 50% odds of getting a script to work, regardless of how experienced the developer is. Certainly 0% without resources like web forum posts.

Web browsers are even worse, in the sense that they're written for users instead of developers. Some low-hanging fruit would be to pause all non-focused tabs after a configurable period of time, so that they only use memory. I've wanted that since I first saw NCSA Mosaic in 1995, along with a great many other improvements which the powers that be seem to work tirelessly to prevent. Blah.

1 comments

Just so we have it, here is a script to disable Javascript in Safari, showing just the business logic for brevity:

  tell application "System Events" to tell process "Safari" to tell menu item "Disable JavaScript" of menu 1 of menu bar item "Develop" of menu bar 1
    if (value of attribute "AXMenuItemMarkChar" as string) is "missing value" then click
  end tell
I save it as an application called Disable Javascript under User Scripts in Script menu and enable assistive access for it.

You can attach a keyboard shortcut to any menu, for example System Preferences->Keyboard->App Shortcuts->Safari->Disable Javascript with command-J. Unfortunately that just toggles Javascript, with no visible indication of whether it's on.

You used to be able to assign a keyboard shortcut to launch applications and scripts, but Apple borked that long ago:

https://apple.stackexchange.com/questions/175215/how-do-i-as...

So instead, I created Automator->Service->Run Shell Script with:

  osascript -e 'tell application "Disable Javascript" to activate'
Then saved it as service "Disable Javascript". Then System Preferences->Keyboard->Services->General->Disable Javascript with shift-command-J.

Now I just periodically press shift-command-J while browsing. If a tab won't render, I press command-J, command-R to reload, then command-J again so the tab doesn't use resources.

I used to have a script to launch Safari with Javascript disabled, but Apple changed how it worked so that the flag is stored in their SQLite preferences somewhere, and I just never found time to re-implement it. If anyone knows a way, I'm all ears!

--

Edit: HN stripped the checkmark character (https://www.compart.com/en/unicode/U+2713) when I pasted, even though I made it a code block by prefixing each line with 2 spaces. So I changed the line to:

  if (value of attribute "AXMenuItemMarkChar" as string) is "missing value" then click
Sorry if that prevented the scripts from working!