bod
04/06/2025, 2:48 PMchrome.offscreen.createDocument
) that exists only in Chrome and not in Firefox. I'm enclosing the piece of code with an if
that knows how to detect that this symbol doesn't exist - but it's still referenced in a "imports" section of the generated JS code:
}(function (_, kotlin_kotlin, kotlin_bbt_shared, kotlin_org_jetbrains_kotlinx_kotlinx_coroutines_core) {
'use strict';
//region block: imports
(... lots of other imports)
var createDocument = chrome.offscreen.createDocument; <- crashes with "Uncaught TypeError: chrome.offscreen is undefined"
(... lots of other imports)
Wondering if there's a proper way to deal with this? Or do I just need to use js("chrome.offscreen.createDocument")
to avoid all this (but feels dirty)?Edoardo Luppi
04/06/2025, 3:18 PMjs
call.bod
04/06/2025, 3:19 PMEdoardo Luppi
04/06/2025, 3:22 PMEdoardo Luppi
04/06/2025, 3:23 PMbod
04/06/2025, 3:24 PMEdoardo Luppi
04/06/2025, 3:24 PMbod
04/06/2025, 3:37 PMEdoardo Luppi
04/06/2025, 3:38 PMbod
04/06/2025, 3:40 PMprivate suspend fun ensureOffscreenDocumentCreated() {
val offscreenRelativePath = "offscreen.html"
val fullyQualifiedPath = chrome.runtime.getURL(offscreenRelativePath)
val existingContexts = chrome.runtime.getContexts(
ContextFilter(
contextTypes = arrayOf("OFFSCREEN_DOCUMENT"),
documentUrls = arrayOf(fullyQualifiedPath),
),
).await()
if (existingContexts.isNotEmpty()) {
return
}
val createParameters = CreateParameters(
justification = "Parse DOM",
reasons = arrayOf("DOM_PARSER"),
url = offscreenRelativePath,
)
val createDocumentPromise = chrome.offscreen.createDocument(createParameters)
// val createDocumentPromise = js("chrome.offscreen.createDocument(createParameters)")
createDocumentPromise.await()
}
js:
//region block: imports
var getURL = chrome.runtime.getURL;
var getContexts = chrome.runtime.getContexts;
var createDocument = chrome.offscreen.createDocument;
var onAlarm = chrome.alarms.onAlarm;
var onMessage = chrome.runtime.onMessage;
var setBadgeText = chrome.action.setBadgeText;
var setBadgeBackgroundColor = chrome.action.setBadgeBackgroundColor;
var get = chrome.alarms.get;
var create = chrome.alarms.create;
var clearAll = chrome.alarms.clearAll;
//endregion
//region block: pre-declaration
class BookmarkExtractor {
(...)Edoardo Luppi
04/06/2025, 3:42 PMbod
04/06/2025, 3:44 PMjs()
version.
Thanks a lot for the help!Edoardo Luppi
04/06/2025, 3:46 PMbod
04/06/2025, 3:47 PMjs
is limited to here so I guess it's manageable for now.
Trying to make something work for both Chrome and Firefox is a horrible experience by the way (not Kotlin's fault at all)Edoardo Luppi
04/06/2025, 3:51 PMbod
04/06/2025, 3:53 PMEdoardo Luppi
04/06/2025, 3:54 PMbod
04/06/2025, 3:54 PMEdoardo Luppi
04/06/2025, 4:07 PMbod
04/06/2025, 4:08 PMbod
04/06/2025, 4:12 PMgit clone <https://github.com/BoD/bbt.git>
cd bbt
git checkout firefox-compat
./gradlew devDist
Result is in build/devDist
.
(in case you don't know or forgot) to load it in Firefox, go to about:debugging#/runtime/this-firefox
and "Load Temporary Add-on", then pick build/devDist/manifest.json
.Edoardo Luppi
04/06/2025, 4:13 PMbod
04/06/2025, 4:13 PMEdoardo Luppi
04/06/2025, 4:13 PMturansky
04/06/2025, 5:00 PMbod
04/06/2025, 5:04 PMEdoardo Luppi
04/06/2025, 5:04 PM@JsQualifier
, and instead use @JsName
, e.g.
@JsName("chrome.runtime.getURL")
external fun getURL(path: String): String
Edoardo Luppi
04/06/2025, 5:05 PMbod
04/06/2025, 5:06 PMbod
04/06/2025, 5:10 PMEdoardo Luppi
04/06/2025, 5:10 PMJsName
is going to be escaped.Edoardo Luppi
04/06/2025, 5:12 PM@JsName("chrome.runtime.getURL", escape = false)
Just an idea @Artem KobzarEdoardo Luppi
04/06/2025, 5:13 PMbod
04/06/2025, 5:14 PMturansky
04/06/2025, 5:17 PMDefinePlugin
and create separate strict builds, without redundant workaroundsbod
04/06/2025, 5:30 PMturansky
04/06/2025, 5:33 PMEdoardo Luppi
04/06/2025, 5:34 PMJsName
, why not.
Had we have the capability of creating new source sets on top of the js
one, I would have gone the route of expect-actual.
_____ js _____
| |
| |
jsChrome jsFirefox
bod
04/06/2025, 5:35 PMbod
04/06/2025, 5:36 PMEdoardo Luppi
04/06/2025, 5:36 PM2 separate bundler configurationsI'm trying to imagine how this would be set up, but I can't really see a straightforward path. Maybe I'm missing how the Kotlin sources would be organized
turansky
04/06/2025, 5:39 PMEdoardo Luppi
04/06/2025, 5:40 PM