Not sure if I hit a bug in WebKit
or I am doing something horribly wrong, but I can't figure out how to use WKScriptMessageHandler
without causing whatever value contained in WKScriptMessage.body
to leak.
I was able to put together a minimum Mac project to isolate the issue, but to no avail.
In the main view controller:
class ViewController: NSViewController {
var webView: WKWebView?
override func viewDidLoad() {
super.viewDidLoad()
let userContentController = WKUserContentController()
userContentController.addScriptMessageHandler(self, name: "handler")
let configuration = WKWebViewConfiguration()
configuration.userContentController = userContentController
webView = WKWebView(frame: CGRectZero, configuration: configuration)
view.addSubview(webView!)
let path = NSBundle.mainBundle().pathForResource("index", ofType: "html")
let url = NSURL(fileURLWithPath: path!)!
webView?.loadRequest(NSURLRequest(URL: url))
}
}
extension ViewController: WKScriptMessageHandler {
func userContentController(userContentController: WKUserContentController, didReceiveScriptMessage message: WKScriptMessage) {
print(message.body)
}
}
And then in the index.html
file:
<html>
<head></head>
<body>
<script type="text/javascript">
webkit.messageHandlers.handler.postMessage("Here's a random number for you: " + Math.random() * 10)
</script>
</body>
</html>
When I run the project then open the memory debugger in Instruments, I see the following leak:
If I add a button that reloads the request, and do so few dozen times, the memory footprint of the app keeps growing, and crashes after a certain threshold. It might take a while before crashing in this minimal example, but in my app where I receive several messages per second, it takes less than 10s to crash.
The whole project can be downloaded here.
Any idea of what's going on?
What you're seeing is a WebKit bug: https://bugs.webkit.org/show_bug.cgi?id=136140. It was fixed in WebKit trunk a while ago, but does not appear to have been merged into any WebKit updates.
You can work around this by adding a
-dealloc
toWKScriptMessage
that compensates for the over-retain. It could look something like this:Drop this in an Objective-C file in your project, set the compiler flags for this file to contain
-fno-objc-arc
, and it should take care of the leak for you.