在background.js Chrome扩展中使用OPFS(原始私有文件系统)和SQLite WASM(Worker未定义错误)

问题描述 投票:0回答:1

我正在尝试让持久存储与 WASM SQLite 一起使用。

我在background.js文件中的代码是这样的

const worker = new Worker('./worker.js');
worker.postMessage({ loadSQLite: true });

但它永远不会越过 Worker 部分。我收到以下错误。

Uncaught ReferenceError: Worker is not defined

因此,在做了一些研究之后,我尝试了一些可能的解决方案。有些人说你不能在工人中产生工人,并且有一个子工人解决方案,但这对我不起作用(如果它对你有用,请告诉我,但我无法让它发挥作用)。

我认为worker.js中的代码并不重要,但我会在那里发布我想要做的事情。

worker.js

import sqlite3InitModule from './lib/@sqlite.org/sqlite-wasm/index.mjs';
const log = (...args) => console.log(...args);
const error = (...args) => console.error(...args);
console.log("worker loaded...");

//@JA - SQLite Database Setup
const start = function (sqlite3) {
    console.log(sqlite3);
    const capi = sqlite3.capi; // C-style API
    const oo = sqlite3.oo1; // High-level OO API
    console.log(`SQLite3 Version ${capi.sqlite3_libversion()} - ${capi.sqlite3_sourceid()}`);
    let db;
    if ('OpfsDb' in oo) {
        db = new oo.OpfsDb('/mydb.sqlite3');
        console.log('The OPFS is available.');
        console.log(`Persisted db = ${db.filename}`);
    } else {
        db = new oo.DB('/mydb.sqlite3', 'ct');
        console.log('The OPFS is not available.');
        console.log(`transient db = ${db.filename}`);
    }

    try{
        db.exec(`CREATE TABLE IF NOT EXISTS results (id INTEGER PRIMARY KEY AUTOINCREMENT, search_name TEXT, strategy_name TEXT, json_data TEXT)`);
    } finally {
        db.close();
    }
}

self.addEventListener('message', (event) => {
    if (event.data.loadSQLite) {
        // Load the SQLite library within the web worker
        sqlite3InitModule({
            print: log,
            printErr: error,
        }).then(function (sqlite3) {
            log('SQLite Done initializing.');
            try {
                start(sqlite3);
            } catch (e) {
                error('Exception:', e.message);
            }
        });
    }
});

如果我把它放在worker.js之外,这段代码就可以工作,但是它是暂时的,这意味着数据库不会保存!

我的目标是让它使用 OPFS 进行持久存储,但事实证明这非常困难,我遇到了障碍。如有任何帮助,我们将不胜感激!

我的目标是让它说

The OPFS is available.

来自此资源:https://sqlite.org/wasm/doc/trunk/persistence.md

它说必须是服务人员才能工作。我假设background.js是一个服务工作者,但显然它不是,否则这会在那里工作。这就是为什么我试图在那里创建一个服务工作者。

我的清单文件在这里:

{
    "name" : "__MSG_appName__",
    "short_name": "__MSG_appShortName__",
    "description": "__MSG_appDescription__",
    "version" : "2.0.2",
    "version_name": "2.0.2",
    "manifest_version": 3,
    "default_locale": "en",
    "minimum_chrome_version": "88",
    "permissions": [
        "activeTab",
        "tabs",
        "storage",
        "scripting",
        "unlimitedStorage",
        "declarativeNetRequest",
        "declarativeNetRequestFeedback"
    ],
    "icons": {
        "16": "./assets/img/icon-16.png",
        "32": "./assets/img/icon-32.png",
        "48": "./assets/img/icon-48.png",
        "128": "./assets/img/icon-128.png"
    },
    "background":{
        "service_worker": "background.js",
        "type": "module"
    },
    "action":{
        "default_popup": "./popup.html",
        "default_icons": {
            "16": "./assets/img/icon-16.png",
            "32": "./assets/img/icon-32.png",
            "48": "./assets/img/icon-48.png",
            "128": "./assets/img/icon-128.png" 
        },
        "default_title": "__MSG_appName__"
    },
    "host_permissions": [
        "https://*.tradingview.com/*"
    ],
    "content_scripts": [
        {
            "all_frames": true,
            "matches": [
                "https://*.tradingview.com/*",
                "http://*.tradingtools.software/*"
            ],
            "css": [
                "./css/trading-view.css",
                "./lib/datetimepicker/jquery.datetimepicker.min.css"
            ],
            "js": [
                "./lib/jquery/jquery-3.6.0.min.js",
                "./lib/lodash/lodash.js",
                "./lib/luxon/non-es6-luxon.js",
                "./lib/datetimepicker/jquery.datetimepicker.full.min.js",
                "./js/classes/scanner.js",
                "./js/classes/dialogs.js",
                "./js/classes/queues.js",
                "./js/helpers/helpers.js",
                "./js/helpers/inputs.js",
                "./js/helpers/security.js",
                "./js/helpers/manipulators.js",
                "./js/helpers/strategy.js",
                "./js/helpers/license.js",
                "./js/globals/globals.js",
                "./js/content/tradingview-content-script.js"  
            ],
            "run_at": "document_idle"
        },
        {
            "all_frames": true,
            "matches":["https://*.tradingview.com/*","http://*.tradingtools.software/*"],
            "js":[ "./js/injectors/before.js" ],
            "run_at": "document_start"
        },
        {
            "all_frames": true,
            "matches":["https://*.tradingview.com/*","http://*.tradingtools.software/*"],
            "js":[ "./js/injectors/after.js" ],
            "run_at": "document_end"
        }
    ],
    "web_accessible_resources": [{
        "resources": ["/js/injectors/before_inject.js","/js/injectors/after_inject.js","/js/injectors/page-script.js","/assets/*","workers.js"],
        "matches": ["<all_urls>"]
    }],
    "content_security_policy": {
        "extension_pages": "script-src 'self' 'wasm-unsafe-eval'; object-src 'self'; worker-src 'self'",
        "sandbox": "sandbox allow-scripts; default-src 'self' 'wasm-unsafe-eval'; frame-src 'self'; worker-src 'self'"
      }
}
javascript sqlite google-chrome-extension web-worker origin-private-file-system
1个回答
0
投票

您无法从扩展服务工作人员启动工作人员,但您可以在屏幕外文档

中创建一个工作人员

至于在 Chrome 扩展中使用 OPFS 运行 SQLite,您可以使用屏幕外文档来执行此操作。这是一个例子。

您还可以克隆此存储库并运行示例 - https://github.com/clmnin/sqlite-opfs-mv3

manifest.json

{
  "manifest_version": 3,
  "name": "MV3 Sqlite OPFS Example",
  "version": "1",
  "description": "MV3 Sqlite OPFS Example",
  "background": {
    "service_worker": "index.js",
    "type": "module"
  },
  "content_security_policy": {
    "extension_pages": "script-src 'self' 'wasm-unsafe-eval'"
  },
  "permissions": [
    "offscreen"
  ]
}

后台服务人员

索引.ts

console.log('bg ready');

let creating: Promise<void> | null;
async function setupOffscreenDocument(path: string) {
  // Check all windows controlled by the service worker to see if one
  // of them is the offscreen document with the given path
  if (await chrome.offscreen.hasDocument?.()) return;

  // create offscreen document
  if (creating) {
    await creating;
  } else {
    creating = chrome.offscreen.createDocument({
      url: chrome.runtime.getURL(path),
      reasons: [
        chrome.offscreen.Reason.WORKERS || chrome.offscreen.Reason.BLOBS,
      ],
      justification: "To run web worker to run sqlite",
    });
    await creating;
    creating = null;
  }
}

setupOffscreenDocument("index.html");

屏外文档

index.html

<!DOCTYPE html>
<script type="module" src="./index.ts"></script>

索引.ts

const worker = new Worker(
  new URL("./worker.js", import.meta.url),
  { type: "module" },
);
worker.onmessage = function ({ data }) {
  switch (data.type) {
    case 'log':
      console.log(`Message: ${data.payload.args}`);
      break;
    default:
      console.log(`ERROR: Unhandled message: ${data.type}`);
  }
};

worker.js

import sqlite3InitModule from '@sqlite.org/sqlite-wasm';

const logHtml = function (cssClass, ...args) {
  postMessage({
    type: 'log',
    payload: { cssClass, args },
  });
};

const log = (...args) => logHtml('', ...args);
const error = (...args) => logHtml('error', ...args);

const start = function (sqlite3) {
  const capi = sqlite3.capi; // C-style API
  const oo = sqlite3.oo1; // High-level OO API
  log('SQLite3 version', capi.sqlite3_libversion(), capi.sqlite3_sourceid());
  let db;
  if ('OpfsDb' in oo) {
    db = new oo.OpfsDb('/mydb.sqlite3');
    log('The OPFS is available.');
    log('Persisted db =', db.filename);
  } else {
    db = new oo.DB('/mydb.sqlite3', 'ct');
    log('The OPFS is not available.');
    log('transient db =', db.filename);
  }

  try {
    log('Create a table...');
    db.exec('CREATE TABLE IF NOT EXISTS t(a,b)');
    log('Insert some data using exec()...');
    let i;
    for (i = 20; i <= 25; ++i) {
      db.exec({
        sql: 'INSERT INTO t(a,b) VALUES (?,?)',
        bind: [i, i * 2],
      });
    }
    log("Query data with exec() using rowMode 'array'...");
    db.exec({
      sql: 'SELECT a FROM t ORDER BY a LIMIT 3',
      rowMode: 'array', // 'array' (default), 'object', or 'stmt'
      callback: function (row) {
        log('row ', ++this.counter, '=', row);
      }.bind({ counter: 0 }),
    });
  } finally {
    db.close();
  }
};

log('Loading and initializing sqlite3 module...');
sqlite3InitModule({
  print: log,
  printErr: error,
}).then(function (sqlite3) {
  log('Done initializing. Running demo...');
  try {
    start(sqlite3);
  } catch (e) {
    error('Exception:', e.message);
  }
});
© www.soinside.com 2019 - 2024. All rights reserved.