value问题处理
Some checks failed
test / Run tests (push) Failing after 3s
build / Build (push) Failing after 6s
Some checks failed
test / Run tests (push) Failing after 3s
build / Build (push) Failing after 6s
This commit is contained in:
parent
9f70b7eb7a
commit
0d86dae710
@ -9,7 +9,7 @@
|
||||
// @connect example.com
|
||||
// ==/UserScript==
|
||||
|
||||
// GM_cookie("store") 方法请看gm_value.js的例子, 可用于隐身窗口的操作
|
||||
// GM_cookie("store") 方法请看storage_name/gm_value.js的例子, 可用于隐身窗口的操作
|
||||
|
||||
GM_cookie("set", {
|
||||
url: "http://example.com/cookie",
|
||||
|
@ -11,13 +11,10 @@
|
||||
// @grant GM_addValueChangeListener
|
||||
// @grant GM_listValues
|
||||
// @grant GM_deleteValue
|
||||
// @grant GM_cookie
|
||||
// ==/UserScript==
|
||||
|
||||
GM_addValueChangeListener("test_set", function (name, oldval, newval, remote, tabid) {
|
||||
GM_cookie("store", tabid, (storeId) => {
|
||||
console.log("store", storeId);
|
||||
});
|
||||
console.log("test_set change", name, oldval, newval, remote, tabid);
|
||||
});
|
||||
|
||||
setInterval(() => {
|
||||
|
18
example/sotrage_name/gm_value_1.js
Normal file
18
example/sotrage_name/gm_value_1.js
Normal file
@ -0,0 +1,18 @@
|
||||
// ==UserScript==
|
||||
// @name gm value storage 设置方
|
||||
// @namespace https://bbs.tampermonkey.net.cn/
|
||||
// @version 0.1.0
|
||||
// @description 多个脚本之间共享数据 设置方
|
||||
// @author You
|
||||
// @match https://bbs.tampermonkey.net.cn/
|
||||
// @run-at document-start
|
||||
// @grant GM_setValue
|
||||
// @grant GM_deleteValue
|
||||
// @storageName example
|
||||
// ==/UserScript==
|
||||
|
||||
setTimeout(() => {
|
||||
GM_deleteValue("test_set");
|
||||
}, 3000);
|
||||
|
||||
GM_setValue("test_set", new Date().getTime());
|
28
example/sotrage_name/gm_value_2.js
Normal file
28
example/sotrage_name/gm_value_2.js
Normal file
@ -0,0 +1,28 @@
|
||||
// ==UserScript==
|
||||
// @name gm value storage 读取与监听方
|
||||
// @namespace https://bbs.tampermonkey.net.cn/
|
||||
// @version 0.1.0
|
||||
// @description 多个脚本之间共享数据 读取与监听方
|
||||
// @author You
|
||||
// @match https://bbs.tampermonkey.net.cn/
|
||||
// @run-at document-start
|
||||
// @grant GM_getValue
|
||||
// @grant GM_addValueChangeListener
|
||||
// @grant GM_listValues
|
||||
// @grant GM_cookie
|
||||
// @storageName example
|
||||
// ==/UserScript==
|
||||
|
||||
GM_addValueChangeListener("test_set", function (name, oldval, newval, remote, tabid) {
|
||||
console.log("test_set change", name, oldval, newval, remote, tabid);
|
||||
// 可以通过tabid获取到触发变化的tab
|
||||
// GM_cookie.store可以获取到对应的cookie storeId
|
||||
GM_cookie("store", tabid, (storeId) => {
|
||||
console.log("store", storeId);
|
||||
});
|
||||
});
|
||||
|
||||
setInterval(() => {
|
||||
console.log(GM_getValue("test_set"));
|
||||
console.log(GM_listValues());
|
||||
}, 2000);
|
@ -1,4 +1,5 @@
|
||||
import LoggerCore from "@App/app/logger/core";
|
||||
import { connect } from "./client";
|
||||
|
||||
export interface Message extends MessageSend {
|
||||
onConnect(callback: (data: any, con: MessageConnect) => void): void;
|
||||
@ -124,7 +125,7 @@ export function forwardMessage(prefix: string, path: string, from: Server, to: M
|
||||
}
|
||||
const fromConnect = fromCon.getConnect();
|
||||
if (fromConnect) {
|
||||
to.connect({ action: prefix + "/" + path, data: params }).then((toCon) => {
|
||||
connect(to, prefix + "/" + path, params).then((toCon) => {
|
||||
fromConnect.onMessage((data) => {
|
||||
toCon.sendMessage(data);
|
||||
});
|
||||
|
@ -90,11 +90,11 @@ export class MapCache {
|
||||
}
|
||||
|
||||
export async function incr(cache: Cache, key: string, increase: number): Promise<number> {
|
||||
const value = await cache.get(key);
|
||||
return cache.tx<number>(key, async (value) => {
|
||||
let num = value || 0;
|
||||
num += increase;
|
||||
await cache.set(key, num);
|
||||
return num;
|
||||
});
|
||||
}
|
||||
|
||||
export default class Cache {
|
||||
@ -138,15 +138,17 @@ export default class Cache {
|
||||
private txPromise: Map<string, Promise<any>> = new Map();
|
||||
|
||||
// 事务处理,如果有事务正在进行,则等待
|
||||
public async tx(key: string, set: (result: any) => Promise<any>): Promise<void> {
|
||||
public async tx<T>(key: string, set: (result: T) => Promise<T>): Promise<T> {
|
||||
let promise = this.txPromise.get(key);
|
||||
if (promise) {
|
||||
await promise;
|
||||
}
|
||||
let newValue: T;
|
||||
promise = this.get(key)
|
||||
.then((result) => set(result))
|
||||
.then((value) => {
|
||||
if (value) {
|
||||
newValue = value;
|
||||
return this.set(key, value);
|
||||
}
|
||||
return Promise.resolve();
|
||||
@ -154,5 +156,6 @@ export default class Cache {
|
||||
this.txPromise.set(key, promise);
|
||||
await promise;
|
||||
this.txPromise.delete(key);
|
||||
return newValue!;
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ import Logger from "./logger";
|
||||
export type LogLevel = "trace" | "debug" | "info" | "warn" | "error";
|
||||
|
||||
export interface LogLabel {
|
||||
[key: string]: string | string[] | boolean | number | undefined;
|
||||
[key: string]: string | string[] | boolean | number | object | undefined;
|
||||
component?: string;
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,8 @@ import Logger from "@App/app/logger/logger";
|
||||
import { GetSender, Group, MessageConnect } from "@Packages/message/server";
|
||||
|
||||
export default class GMApi {
|
||||
logger: Logger = LoggerCore.logger().with({ service: "gmApi" });
|
||||
|
||||
constructor(private group: Group) {}
|
||||
|
||||
async dealXhrResponse(
|
||||
|
@ -282,7 +282,6 @@ export class Runtime {
|
||||
}
|
||||
|
||||
async runScript(script: ScriptRunResouce) {
|
||||
console.log("runScript", script);
|
||||
const exec = this.execScripts.get(script.uuid);
|
||||
// 如果正在运行,先释放
|
||||
if (exec) {
|
||||
|
@ -71,13 +71,15 @@ export default class GMApi {
|
||||
}
|
||||
|
||||
@PermissionVerify.API()
|
||||
async GM_setValue(request: Request) {
|
||||
console.log("setValue", request);
|
||||
async GM_setValue(request: Request, sender: GetSender) {
|
||||
if (!request.params || request.params.length !== 2) {
|
||||
return Promise.reject(new Error("param is failed"));
|
||||
}
|
||||
const [key, value] = request.params;
|
||||
await this.value.setValue(request.script.uuid, key, value);
|
||||
await this.value.setValue(request.script.uuid, key, value, {
|
||||
runFlag: request.runFlag,
|
||||
tabId: sender.getSender().tab?.id,
|
||||
});
|
||||
}
|
||||
|
||||
// 根据header生成dnr规则
|
||||
@ -183,7 +185,6 @@ export default class GMApi {
|
||||
|
||||
@PermissionVerify.API()
|
||||
GM_registerMenuCommand(request: Request, sender: GetSender) {
|
||||
console.log("registerMenuCommand", request.params, sender.getSender(), sender.getSender().tab!.id!);
|
||||
const [id, name, accessKey] = request.params;
|
||||
// 触发菜单注册, 在popup中处理
|
||||
this.mq.emit("registerMenuCommand", {
|
||||
|
@ -20,7 +20,7 @@ import {
|
||||
subscribeScriptMenuRegister,
|
||||
subscribeScriptRunStatus,
|
||||
} from "../queue";
|
||||
import { storageKey } from "@App/runtime/utils";
|
||||
import { getStorageName } from "@App/runtime/utils";
|
||||
|
||||
export type ScriptMenuItem = {
|
||||
id: number;
|
||||
@ -87,7 +87,6 @@ export class PopupService {
|
||||
// 移除之前所有的菜单
|
||||
chrome.contextMenus.removeAll();
|
||||
const [menu, backgroundMenu] = await Promise.all([this.getScriptMenu(tabId), this.getScriptMenu(-1)]);
|
||||
console.log(menu, backgroundMenu, tabId);
|
||||
if (!menu.length && !backgroundMenu.length) {
|
||||
return;
|
||||
}
|
||||
@ -140,7 +139,6 @@ export class PopupService {
|
||||
if (script) {
|
||||
script.menus = script.menus.filter((item) => item.id !== id);
|
||||
}
|
||||
console.log("unregister menu", data);
|
||||
this.updateScriptMenu();
|
||||
return data;
|
||||
});
|
||||
@ -149,7 +147,6 @@ export class PopupService {
|
||||
updateScriptMenu() {
|
||||
// 获取当前页面并更新菜单
|
||||
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
|
||||
console.log("query", tabs);
|
||||
if (!tabs.length) {
|
||||
return;
|
||||
}
|
||||
@ -163,7 +160,7 @@ export class PopupService {
|
||||
return {
|
||||
uuid: script.uuid,
|
||||
name: script.name,
|
||||
storageName: storageKey(script),
|
||||
storageName: getStorageName(script),
|
||||
enable: script.status === SCRIPT_STATUS_ENABLE,
|
||||
updatetime: script.updatetime || 0,
|
||||
hasUserConfig: !!script.config,
|
||||
|
@ -194,6 +194,8 @@ export class RuntimeService {
|
||||
})
|
||||
);
|
||||
|
||||
console.log("pageLoad", enableScript);
|
||||
|
||||
this.mq.emit("pageLoad", {
|
||||
tabId: chromeSender.tab?.id,
|
||||
frameId: chromeSender.frameId,
|
||||
|
@ -2,12 +2,13 @@ import LoggerCore from "@App/app/logger/core";
|
||||
import Logger from "@App/app/logger/logger";
|
||||
import { Script, SCRIPT_TYPE_NORMAL, ScriptDAO } from "@App/app/repo/scripts";
|
||||
import { ValueDAO } from "@App/app/repo/value";
|
||||
import { storageKey } from "@App/runtime/utils";
|
||||
import { getStorageName } from "@App/runtime/utils";
|
||||
import { Group, MessageSend } from "@Packages/message/server";
|
||||
import { RuntimeService } from "./runtime";
|
||||
import { PopupService } from "./popup";
|
||||
import { ValueUpdateData } from "@App/runtime/content/exec_script";
|
||||
import { ValueUpdateData, ValueUpdateSender } from "@App/runtime/content/exec_script";
|
||||
import { sendMessage } from "@Packages/message/client";
|
||||
import Cache from "@App/app/cache";
|
||||
|
||||
export class ValueService {
|
||||
logger: Logger;
|
||||
@ -24,25 +25,27 @@ export class ValueService {
|
||||
}
|
||||
|
||||
async getScriptValue(script: Script) {
|
||||
const ret = await this.valueDAO.get(storageKey(script));
|
||||
const ret = await this.valueDAO.get(getStorageName(script));
|
||||
if (!ret) {
|
||||
return {};
|
||||
}
|
||||
return ret.data;
|
||||
}
|
||||
|
||||
async setValue(uuid: string, key: string, value: any, sender?: any): Promise<boolean> {
|
||||
async setValue(uuid: string, key: string, value: any, sender: ValueUpdateSender): Promise<boolean> {
|
||||
// 查询出脚本
|
||||
const script = await this.scriptDAO.get(uuid);
|
||||
if (!script) {
|
||||
return Promise.reject(new Error("script not found"));
|
||||
}
|
||||
// 查询老的值
|
||||
const storageName = storageKey(script);
|
||||
const valueModel = await this.valueDAO.get(storageName);
|
||||
const storageName = getStorageName(script);
|
||||
let oldValue;
|
||||
// 使用事务来保证数据一致性
|
||||
await Cache.getInstance().tx("setValue:" + storageName, async () => {
|
||||
const valueModel = await this.valueDAO.get(storageName);
|
||||
if (!valueModel) {
|
||||
this.valueDAO.save(storageName, {
|
||||
await this.valueDAO.save(storageName, {
|
||||
uuid: script.uuid,
|
||||
storageName: storageName,
|
||||
data: { [key]: value },
|
||||
@ -52,18 +55,20 @@ export class ValueService {
|
||||
} else {
|
||||
oldValue = valueModel.data[key];
|
||||
valueModel.data[key] = value;
|
||||
this.valueDAO.save(storageName, valueModel);
|
||||
await this.valueDAO.save(storageName, valueModel);
|
||||
}
|
||||
console.log(valueModel);
|
||||
return true;
|
||||
});
|
||||
const sendData: ValueUpdateData = {
|
||||
oldValue,
|
||||
sender,
|
||||
value,
|
||||
key,
|
||||
uuid,
|
||||
storageKey: storageName,
|
||||
storageName: storageName,
|
||||
};
|
||||
// 判断是后台脚本还是前台脚本
|
||||
console.log("value update", script, sendData);
|
||||
if (script.type === SCRIPT_TYPE_NORMAL) {
|
||||
chrome.tabs.query({}, (tabs) => {
|
||||
// 推送到所有加载了本脚本的tab中
|
||||
|
@ -5,7 +5,6 @@ import { deleteScript, scriptSlice, upsertScript } from "./features/script";
|
||||
|
||||
export default function storeSubscribe() {
|
||||
subscribeScriptRunStatus(messageQueue, (data) => {
|
||||
console.log("subscribeScriptRunStatus", data);
|
||||
store.dispatch(scriptSlice.actions.updateRunStatus(data));
|
||||
});
|
||||
subscribeScriptInstall(messageQueue, (message) => {
|
||||
|
@ -5,16 +5,18 @@ import GMApi from "./gm_api";
|
||||
import { compileScript, createContext, proxyContext, ScriptFunc } from "./utils";
|
||||
import { Message } from "@Packages/message/server";
|
||||
|
||||
export type ValueUpdateSender = {
|
||||
runFlag: string;
|
||||
tabId?: number;
|
||||
};
|
||||
|
||||
export type ValueUpdateData = {
|
||||
oldValue: any;
|
||||
value: any;
|
||||
key: string; // 值key
|
||||
uuid: string;
|
||||
storageKey: string; // 储存key
|
||||
sender: {
|
||||
runFlag: string;
|
||||
tabId?: number;
|
||||
};
|
||||
storageName: string; // 储存name
|
||||
sender: ValueUpdateSender;
|
||||
};
|
||||
|
||||
export class RuntimeMessage {}
|
||||
|
@ -2,7 +2,7 @@ import { ScriptRunResouce } from "@App/app/repo/scripts";
|
||||
import { getMetadataStr, getUserConfigStr, parseUserConfig } from "@App/pkg/utils/script";
|
||||
import { ValueUpdateData } from "./exec_script";
|
||||
import { ExtVersion } from "@App/app/const";
|
||||
import { storageKey } from "../utils";
|
||||
import { getStorageName } from "../utils";
|
||||
import { Message, MessageConnect } from "@Packages/message/server";
|
||||
import { CustomEventMessage } from "@Packages/message/custom_event_message";
|
||||
import LoggerCore from "@App/app/logger/core";
|
||||
@ -86,22 +86,18 @@ export default class GMApi {
|
||||
}
|
||||
|
||||
public valueUpdate(data: ValueUpdateData) {
|
||||
if (data.uuid === this.scriptRes.uuid || data.storageKey === storageKey(this.scriptRes)) {
|
||||
if (data.uuid === this.scriptRes.uuid || data.storageName === getStorageName(this.scriptRes)) {
|
||||
// 触发,并更新值
|
||||
if (data.value === undefined) {
|
||||
delete this.scriptRes.value[data.value];
|
||||
if (this.scriptRes.value[data.key] !== undefined) {
|
||||
delete this.scriptRes.value[data.key];
|
||||
}
|
||||
} else {
|
||||
this.scriptRes.value[data.key] = data.value;
|
||||
}
|
||||
this.valueChangeListener.forEach((item) => {
|
||||
if (item.name === data.value.key) {
|
||||
item.listener(
|
||||
data.value.key,
|
||||
data.oldValue,
|
||||
data.value,
|
||||
data.sender.runFlag !== this.runFlag,
|
||||
data.sender.tabId
|
||||
);
|
||||
if (item.name === data.key) {
|
||||
item.listener(data.key, data.oldValue, data.value, data.sender.runFlag !== this.runFlag, data.sender.tabId);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -345,6 +341,8 @@ export default class GMApi {
|
||||
// 处理blob
|
||||
param.dataType = "Blob";
|
||||
param.data = await this.CAT_createBlobUrl(details.data);
|
||||
} else {
|
||||
param.data = details.data;
|
||||
}
|
||||
|
||||
// 处理返回数据
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { ScriptRunResouce } from "@App/app/repo/scripts";
|
||||
import { Message, Server } from "@Packages/message/server";
|
||||
import ExecScript from "./exec_script";
|
||||
import ExecScript, { ValueUpdateData } from "./exec_script";
|
||||
import { addStyle, ScriptFunc } from "./utils";
|
||||
import { getStorageName } from "../utils";
|
||||
|
||||
export class InjectRuntime {
|
||||
execList: ExecScript[] = [];
|
||||
@ -35,11 +36,12 @@ export class InjectRuntime {
|
||||
exec.menuClick(data.id);
|
||||
}
|
||||
});
|
||||
this.server.on("runtime/valueUpdate", (data: { uuid: string; key: string; value: any }) => {
|
||||
const exec = this.execList.find((val) => val.scriptRes.uuid === data.uuid);
|
||||
if (exec) {
|
||||
// exec.valueUpdate(data.key,);
|
||||
}
|
||||
this.server.on("runtime/valueUpdate", (data: ValueUpdateData) => {
|
||||
this.execList
|
||||
.filter((val) => val.scriptRes.uuid === data.uuid || getStorageName(val.scriptRes) === data.storageName)
|
||||
.forEach((val) => {
|
||||
val.valueUpdate(data);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,7 @@ export const unsafeHeaders: { [key: string]: boolean } = {
|
||||
via: true,
|
||||
};
|
||||
|
||||
export function storageKey(script: Script): string {
|
||||
export function getStorageName(script: Script): string {
|
||||
if (script.metadata && script.metadata.storagename) {
|
||||
return script.metadata.storagename[0];
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user