@wrongstack/tools 0.7.7 → 0.7.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/builtin.js +173 -124
- package/dist/builtin.js.map +1 -1
- package/dist/codebase-index/index.js +173 -124
- package/dist/codebase-index/index.js.map +1 -1
- package/dist/index.js +173 -124
- package/dist/index.js.map +1 -1
- package/dist/pack.js +173 -124
- package/dist/pack.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@ import * as dns from 'node:dns/promises';
|
|
|
9
9
|
import * as net from 'node:net';
|
|
10
10
|
import * as fs13 from 'node:fs';
|
|
11
11
|
import { statSync, mkdirSync, writeFileSync, unlinkSync } from 'node:fs';
|
|
12
|
-
import {
|
|
12
|
+
import { createRequire } from 'node:module';
|
|
13
13
|
import * as ts from 'typescript';
|
|
14
14
|
|
|
15
15
|
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
@@ -4980,12 +4980,39 @@ function lspKindToInternalKind(k) {
|
|
|
4980
4980
|
// src/codebase-index/writer.ts
|
|
4981
4981
|
var INDEX_DIR = ".codebase-index";
|
|
4982
4982
|
var DB_FILE = "index.db";
|
|
4983
|
+
var warningSilenced = false;
|
|
4984
|
+
function silenceSqliteExperimentalWarning() {
|
|
4985
|
+
if (warningSilenced) return;
|
|
4986
|
+
warningSilenced = true;
|
|
4987
|
+
const original = process.emitWarning.bind(process);
|
|
4988
|
+
process.emitWarning = ((warning, ...rest) => {
|
|
4989
|
+
const msg = typeof warning === "string" ? warning : warning?.message ?? "";
|
|
4990
|
+
const name = typeof warning === "string" ? String(rest[0] ?? "") : warning?.name ?? "";
|
|
4991
|
+
if (/sqlite/i.test(msg) && /experimental/i.test(`${name} ${msg}`)) return;
|
|
4992
|
+
original(warning, ...rest);
|
|
4993
|
+
});
|
|
4994
|
+
}
|
|
4995
|
+
var DatabaseSyncCtor;
|
|
4996
|
+
function loadDatabaseSync() {
|
|
4997
|
+
if (DatabaseSyncCtor) return DatabaseSyncCtor;
|
|
4998
|
+
silenceSqliteExperimentalWarning();
|
|
4999
|
+
try {
|
|
5000
|
+
const req = createRequire(import.meta.url);
|
|
5001
|
+
DatabaseSyncCtor = req("node:sqlite").DatabaseSync;
|
|
5002
|
+
} catch (err) {
|
|
5003
|
+
throw new Error(
|
|
5004
|
+
`The codebase index needs Node's built-in SQLite (node:sqlite), available since Node 22.5. This runtime doesn't provide it: ${err instanceof Error ? err.message : String(err)}`
|
|
5005
|
+
);
|
|
5006
|
+
}
|
|
5007
|
+
return DatabaseSyncCtor;
|
|
5008
|
+
}
|
|
4983
5009
|
var IndexStore = class {
|
|
4984
5010
|
constructor(projectRoot) {
|
|
4985
5011
|
this.projectRoot = projectRoot;
|
|
4986
5012
|
const dir = path.join(projectRoot, INDEX_DIR);
|
|
4987
5013
|
fs13.mkdirSync(dir, { recursive: true });
|
|
4988
|
-
|
|
5014
|
+
const Database = loadDatabaseSync();
|
|
5015
|
+
this.db = new Database(path.join(dir, DB_FILE));
|
|
4989
5016
|
this.initSchema();
|
|
4990
5017
|
}
|
|
4991
5018
|
projectRoot;
|
|
@@ -6000,7 +6027,10 @@ function checkNativeParser() {
|
|
|
6000
6027
|
execSync("rustc --version", { stdio: "pipe" });
|
|
6001
6028
|
const toolsDir = path.join(process.cwd(), "tools");
|
|
6002
6029
|
try {
|
|
6003
|
-
execSync(
|
|
6030
|
+
execSync(
|
|
6031
|
+
"cargo metadata --no-deps --format-version 1 --manifest-path " + path.join(toolsDir, "Cargo.toml"),
|
|
6032
|
+
{ stdio: "pipe" }
|
|
6033
|
+
);
|
|
6004
6034
|
return true;
|
|
6005
6035
|
} catch {
|
|
6006
6036
|
return false;
|
|
@@ -6016,12 +6046,16 @@ function tryNativeParse(file, content) {
|
|
|
6016
6046
|
const tmpFile = path.join(crateDir, "src", "input.rs");
|
|
6017
6047
|
const { writeFileSync: writeFileSync2 } = __require("node:fs");
|
|
6018
6048
|
writeFileSync2(tmpFile, content, "utf8");
|
|
6019
|
-
const result = spawnSync(
|
|
6020
|
-
|
|
6021
|
-
|
|
6022
|
-
|
|
6023
|
-
|
|
6024
|
-
|
|
6049
|
+
const result = spawnSync(
|
|
6050
|
+
"cargo",
|
|
6051
|
+
["run", "--manifest-path", path.join(toolsDir, "Cargo.toml")],
|
|
6052
|
+
{
|
|
6053
|
+
cwd: process.cwd(),
|
|
6054
|
+
encoding: "utf8",
|
|
6055
|
+
timeout: 15e3,
|
|
6056
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
6057
|
+
}
|
|
6058
|
+
);
|
|
6025
6059
|
if (result.status === 0 && result.stdout) {
|
|
6026
6060
|
const symbols = JSON.parse(result.stdout);
|
|
6027
6061
|
return {
|
|
@@ -6055,7 +6089,8 @@ function regexParse(opts) {
|
|
|
6055
6089
|
lineOffsets.push(lineOffsets[i] + lines[i].length + 1);
|
|
6056
6090
|
}
|
|
6057
6091
|
function lineFromOffset(offset) {
|
|
6058
|
-
let lo = 0
|
|
6092
|
+
let lo = 0;
|
|
6093
|
+
let hi = lineOffsets.length - 1;
|
|
6059
6094
|
while (lo < hi) {
|
|
6060
6095
|
const mid = lo + hi + 1 >>> 1;
|
|
6061
6096
|
if (lineOffsets[mid] <= offset) lo = mid;
|
|
@@ -6069,8 +6104,7 @@ function regexParse(opts) {
|
|
|
6069
6104
|
}
|
|
6070
6105
|
for (const pattern of RS_PATTERNS) {
|
|
6071
6106
|
pattern.regex.lastIndex = 0;
|
|
6072
|
-
let match;
|
|
6073
|
-
while ((match = pattern.regex.exec(content)) !== null) {
|
|
6107
|
+
for (let match = pattern.regex.exec(content); match !== null; match = pattern.regex.exec(content)) {
|
|
6074
6108
|
const name = match[1];
|
|
6075
6109
|
const offset = match.index;
|
|
6076
6110
|
const line = lineFromOffset(offset);
|
|
@@ -6123,7 +6157,8 @@ function regexParse2(opts) {
|
|
|
6123
6157
|
lineOffsets.push(lineOffsets[i] + lines[i].length + 1);
|
|
6124
6158
|
}
|
|
6125
6159
|
function lineFromOffset(offset) {
|
|
6126
|
-
let lo = 0
|
|
6160
|
+
let lo = 0;
|
|
6161
|
+
let hi = lineOffsets.length - 1;
|
|
6127
6162
|
while (lo < hi) {
|
|
6128
6163
|
const mid = lo + hi + 1 >>> 1;
|
|
6129
6164
|
if (lineOffsets[mid] <= offset) lo = mid;
|
|
@@ -6135,19 +6170,20 @@ function regexParse2(opts) {
|
|
|
6135
6170
|
if (rootMatch) {
|
|
6136
6171
|
const offset = rootMatch.index;
|
|
6137
6172
|
const line = lineFromOffset(offset);
|
|
6138
|
-
symbols.push(
|
|
6139
|
-
|
|
6140
|
-
|
|
6141
|
-
|
|
6142
|
-
|
|
6143
|
-
|
|
6144
|
-
|
|
6145
|
-
|
|
6146
|
-
|
|
6173
|
+
symbols.push(
|
|
6174
|
+
makeSymbol({
|
|
6175
|
+
name: path.basename(file),
|
|
6176
|
+
kind: "object",
|
|
6177
|
+
line,
|
|
6178
|
+
col: 0,
|
|
6179
|
+
signature: `"${path.basename(file)}" = { ... }`,
|
|
6180
|
+
file,
|
|
6181
|
+
lang
|
|
6182
|
+
})
|
|
6183
|
+
);
|
|
6147
6184
|
}
|
|
6148
6185
|
const topLevelKeyRegex = /^\s*"([^"]+)"\s*:/gm;
|
|
6149
|
-
let match;
|
|
6150
|
-
while ((match = topLevelKeyRegex.exec(content)) !== null) {
|
|
6186
|
+
for (let match = topLevelKeyRegex.exec(content); match !== null; match = topLevelKeyRegex.exec(content)) {
|
|
6151
6187
|
const key = match[1];
|
|
6152
6188
|
const offset = match.index;
|
|
6153
6189
|
const line = lineFromOffset(offset);
|
|
@@ -6174,15 +6210,17 @@ function regexParse2(opts) {
|
|
|
6174
6210
|
signature = `"$ref": "..."`;
|
|
6175
6211
|
}
|
|
6176
6212
|
}
|
|
6177
|
-
symbols.push(
|
|
6178
|
-
|
|
6179
|
-
|
|
6180
|
-
|
|
6181
|
-
|
|
6182
|
-
|
|
6183
|
-
|
|
6184
|
-
|
|
6185
|
-
|
|
6213
|
+
symbols.push(
|
|
6214
|
+
makeSymbol({
|
|
6215
|
+
name: key,
|
|
6216
|
+
kind,
|
|
6217
|
+
line,
|
|
6218
|
+
col,
|
|
6219
|
+
signature,
|
|
6220
|
+
file,
|
|
6221
|
+
lang
|
|
6222
|
+
})
|
|
6223
|
+
);
|
|
6186
6224
|
if (isPackageJson && key === "scripts") {
|
|
6187
6225
|
extractPackageScripts(content, symbols, file, lang, lineOffsets, lineFromOffset);
|
|
6188
6226
|
}
|
|
@@ -6191,20 +6229,21 @@ function regexParse2(opts) {
|
|
|
6191
6229
|
}
|
|
6192
6230
|
}
|
|
6193
6231
|
const defsRegex = /"\$defs"\s*:|"\$defs"\s*:/g;
|
|
6194
|
-
|
|
6195
|
-
|
|
6232
|
+
const defsMatch = defsRegex.exec(content);
|
|
6233
|
+
if (defsMatch !== null) {
|
|
6196
6234
|
const offset = defsMatch.index;
|
|
6197
6235
|
const line = lineFromOffset(offset);
|
|
6198
|
-
symbols.push(
|
|
6199
|
-
|
|
6200
|
-
|
|
6201
|
-
|
|
6202
|
-
|
|
6203
|
-
|
|
6204
|
-
|
|
6205
|
-
|
|
6206
|
-
|
|
6207
|
-
|
|
6236
|
+
symbols.push(
|
|
6237
|
+
makeSymbol({
|
|
6238
|
+
name: "$defs",
|
|
6239
|
+
kind: "property",
|
|
6240
|
+
line,
|
|
6241
|
+
col: offset - (lineOffsets[line - 1] ?? 0),
|
|
6242
|
+
signature: '"$defs": { ... }',
|
|
6243
|
+
file,
|
|
6244
|
+
lang
|
|
6245
|
+
})
|
|
6246
|
+
);
|
|
6208
6247
|
}
|
|
6209
6248
|
const defsPatterns = [
|
|
6210
6249
|
/"\$defs"\s*:/g,
|
|
@@ -6214,69 +6253,71 @@ function regexParse2(opts) {
|
|
|
6214
6253
|
];
|
|
6215
6254
|
for (const pat of defsPatterns) {
|
|
6216
6255
|
pat.lastIndex = 0;
|
|
6217
|
-
|
|
6256
|
+
for (let match = pat.exec(content); match !== null; match = pat.exec(content)) {
|
|
6218
6257
|
const offset = match.index;
|
|
6219
6258
|
const line = lineFromOffset(offset);
|
|
6220
6259
|
const key = match[0].match(/"([^"]+)"/)?.[1] ?? match[0];
|
|
6221
|
-
symbols.push(
|
|
6222
|
-
|
|
6223
|
-
|
|
6224
|
-
|
|
6225
|
-
|
|
6226
|
-
|
|
6227
|
-
|
|
6228
|
-
|
|
6229
|
-
|
|
6260
|
+
symbols.push(
|
|
6261
|
+
makeSymbol({
|
|
6262
|
+
name: key,
|
|
6263
|
+
kind: "property",
|
|
6264
|
+
line,
|
|
6265
|
+
col: offset - (lineOffsets[line - 1] ?? 0),
|
|
6266
|
+
signature: `"${key}": { ... }`,
|
|
6267
|
+
file,
|
|
6268
|
+
lang
|
|
6269
|
+
})
|
|
6270
|
+
);
|
|
6230
6271
|
}
|
|
6231
6272
|
}
|
|
6232
6273
|
return { file, lang, symbols, mtimeMs: Date.now() };
|
|
6233
6274
|
}
|
|
6234
6275
|
function extractPackageScripts(content, symbols, file, lang, lineOffsets, lineFromOffset) {
|
|
6235
6276
|
const scriptsBlockRegex = /"scripts"\s*:\s*\{([^}]+)\}/g;
|
|
6236
|
-
let match;
|
|
6237
|
-
while ((match = scriptsBlockRegex.exec(content)) !== null) {
|
|
6277
|
+
for (let match = scriptsBlockRegex.exec(content); match !== null; match = scriptsBlockRegex.exec(content)) {
|
|
6238
6278
|
const blockContent = match[0];
|
|
6239
6279
|
const blockOffset = match.index;
|
|
6240
6280
|
const scriptKeyRegex = /"(\w[\w-]*)"\s*:/g;
|
|
6241
|
-
let scriptMatch;
|
|
6242
|
-
while ((scriptMatch = scriptKeyRegex.exec(blockContent)) !== null) {
|
|
6281
|
+
for (let scriptMatch = scriptKeyRegex.exec(blockContent); scriptMatch !== null; scriptMatch = scriptKeyRegex.exec(blockContent)) {
|
|
6243
6282
|
const key = scriptMatch[1];
|
|
6244
6283
|
const keyOffset = blockOffset + scriptMatch.index;
|
|
6245
6284
|
const line = lineFromOffset(keyOffset);
|
|
6246
|
-
symbols.push(
|
|
6247
|
-
|
|
6248
|
-
|
|
6249
|
-
|
|
6250
|
-
|
|
6251
|
-
|
|
6252
|
-
|
|
6253
|
-
|
|
6254
|
-
|
|
6285
|
+
symbols.push(
|
|
6286
|
+
makeSymbol({
|
|
6287
|
+
name: key,
|
|
6288
|
+
kind: "function",
|
|
6289
|
+
line,
|
|
6290
|
+
col: keyOffset - (lineOffsets[line - 1] ?? 0),
|
|
6291
|
+
signature: `"${key}": "..."`,
|
|
6292
|
+
file,
|
|
6293
|
+
lang
|
|
6294
|
+
})
|
|
6295
|
+
);
|
|
6255
6296
|
}
|
|
6256
6297
|
}
|
|
6257
6298
|
}
|
|
6258
6299
|
function extractCompilerOptions(content, symbols, file, lang, lineOffsets, parentLine, lineFromOffset) {
|
|
6259
6300
|
const optsBlockRegex = /"compilerOptions"\s*:\s*\{([^}]+)\}/g;
|
|
6260
|
-
let match;
|
|
6261
|
-
while ((match = optsBlockRegex.exec(content)) !== null) {
|
|
6301
|
+
for (let match = optsBlockRegex.exec(content); match !== null; match = optsBlockRegex.exec(content)) {
|
|
6262
6302
|
const blockContent = match[0];
|
|
6263
6303
|
const blockOffset = match.index;
|
|
6264
6304
|
const optKeyRegex = /"(\w[\w]*)"\s*:/g;
|
|
6265
|
-
let optMatch;
|
|
6266
|
-
while ((optMatch = optKeyRegex.exec(blockContent)) !== null) {
|
|
6305
|
+
for (let optMatch = optKeyRegex.exec(blockContent); optMatch !== null; optMatch = optKeyRegex.exec(blockContent)) {
|
|
6267
6306
|
const key = optMatch[1];
|
|
6268
6307
|
const keyOffset = blockOffset + optMatch.index;
|
|
6269
6308
|
const line = lineFromOffset(keyOffset);
|
|
6270
6309
|
if (line <= parentLine) continue;
|
|
6271
|
-
symbols.push(
|
|
6272
|
-
|
|
6273
|
-
|
|
6274
|
-
|
|
6275
|
-
|
|
6276
|
-
|
|
6277
|
-
|
|
6278
|
-
|
|
6279
|
-
|
|
6310
|
+
symbols.push(
|
|
6311
|
+
makeSymbol({
|
|
6312
|
+
name: key,
|
|
6313
|
+
kind: "property",
|
|
6314
|
+
line,
|
|
6315
|
+
col: keyOffset - (lineOffsets[line - 1] ?? 0),
|
|
6316
|
+
signature: `"${key}": ...`,
|
|
6317
|
+
file,
|
|
6318
|
+
lang
|
|
6319
|
+
})
|
|
6320
|
+
);
|
|
6280
6321
|
}
|
|
6281
6322
|
}
|
|
6282
6323
|
}
|
|
@@ -6314,7 +6355,8 @@ function regexParse3(opts) {
|
|
|
6314
6355
|
lineOffsets.push(lineOffsets[i] + lines[i].length + 1);
|
|
6315
6356
|
}
|
|
6316
6357
|
function lineFromOffset(offset) {
|
|
6317
|
-
let lo = 0
|
|
6358
|
+
let lo = 0;
|
|
6359
|
+
let hi = lineOffsets.length - 1;
|
|
6318
6360
|
while (lo < hi) {
|
|
6319
6361
|
const mid = lo + hi + 1 >>> 1;
|
|
6320
6362
|
if (lineOffsets[mid] <= offset) lo = mid;
|
|
@@ -6323,40 +6365,43 @@ function regexParse3(opts) {
|
|
|
6323
6365
|
return lo + 1;
|
|
6324
6366
|
}
|
|
6325
6367
|
const anchorRegex = /&(\w[\w-]*)/g;
|
|
6326
|
-
let match;
|
|
6327
|
-
while ((match = anchorRegex.exec(content)) !== null) {
|
|
6368
|
+
for (let match = anchorRegex.exec(content); match !== null; match = anchorRegex.exec(content)) {
|
|
6328
6369
|
const name = match[1];
|
|
6329
6370
|
const offset = match.index;
|
|
6330
6371
|
const line = lineFromOffset(offset);
|
|
6331
6372
|
const col = offset - (lineOffsets[line - 1] ?? 0);
|
|
6332
|
-
symbols.push(
|
|
6333
|
-
|
|
6334
|
-
|
|
6335
|
-
|
|
6336
|
-
|
|
6337
|
-
|
|
6338
|
-
|
|
6339
|
-
|
|
6340
|
-
|
|
6373
|
+
symbols.push(
|
|
6374
|
+
makeSymbol2({
|
|
6375
|
+
name,
|
|
6376
|
+
kind: "const",
|
|
6377
|
+
line,
|
|
6378
|
+
col,
|
|
6379
|
+
signature: `&${name}`,
|
|
6380
|
+
file,
|
|
6381
|
+
lang
|
|
6382
|
+
})
|
|
6383
|
+
);
|
|
6341
6384
|
}
|
|
6342
6385
|
const aliasRegex = /\*(\w[\w-]*)/g;
|
|
6343
|
-
|
|
6386
|
+
for (let match = aliasRegex.exec(content); match !== null; match = aliasRegex.exec(content)) {
|
|
6344
6387
|
const name = match[1];
|
|
6345
6388
|
const offset = match.index;
|
|
6346
6389
|
const line = lineFromOffset(offset);
|
|
6347
6390
|
const col = offset - (lineOffsets[line - 1] ?? 0);
|
|
6348
|
-
symbols.push(
|
|
6349
|
-
|
|
6350
|
-
|
|
6351
|
-
|
|
6352
|
-
|
|
6353
|
-
|
|
6354
|
-
|
|
6355
|
-
|
|
6356
|
-
|
|
6391
|
+
symbols.push(
|
|
6392
|
+
makeSymbol2({
|
|
6393
|
+
name,
|
|
6394
|
+
kind: "const",
|
|
6395
|
+
line,
|
|
6396
|
+
col,
|
|
6397
|
+
signature: `*${name}`,
|
|
6398
|
+
file,
|
|
6399
|
+
lang
|
|
6400
|
+
})
|
|
6401
|
+
);
|
|
6357
6402
|
}
|
|
6358
6403
|
const kvRegex = /^(\s*)([^:#\s][^:#\s]*)\s*:/gm;
|
|
6359
|
-
|
|
6404
|
+
for (let match = kvRegex.exec(content); match !== null; match = kvRegex.exec(content)) {
|
|
6360
6405
|
const indent = match[1].length;
|
|
6361
6406
|
const key = match[2];
|
|
6362
6407
|
const offset = match.index;
|
|
@@ -6372,38 +6417,42 @@ function regexParse3(opts) {
|
|
|
6372
6417
|
symbols.push(makeSymbol2({ name: key, kind, line, col, signature, file, lang }));
|
|
6373
6418
|
}
|
|
6374
6419
|
const listItemRegex = /^-(\s+)([^:#\s][^:#\s]*)\s*:/gm;
|
|
6375
|
-
|
|
6420
|
+
for (let match = listItemRegex.exec(content); match !== null; match = listItemRegex.exec(content)) {
|
|
6376
6421
|
const key = match[2];
|
|
6377
6422
|
const offset = match.index;
|
|
6378
6423
|
const line = lineFromOffset(offset);
|
|
6379
6424
|
const col = offset - (lineOffsets[line - 1] ?? 0);
|
|
6380
6425
|
const value = extractValue(content, offset + match[0].length);
|
|
6381
6426
|
const kind = isScalar(value) ? "literal" : "property";
|
|
6382
|
-
symbols.push(
|
|
6383
|
-
|
|
6384
|
-
|
|
6385
|
-
|
|
6386
|
-
|
|
6387
|
-
|
|
6388
|
-
|
|
6389
|
-
|
|
6390
|
-
|
|
6427
|
+
symbols.push(
|
|
6428
|
+
makeSymbol2({
|
|
6429
|
+
name: key,
|
|
6430
|
+
kind,
|
|
6431
|
+
line,
|
|
6432
|
+
col,
|
|
6433
|
+
signature: `- ${key}: ${truncate(value, 60)}`,
|
|
6434
|
+
file,
|
|
6435
|
+
lang
|
|
6436
|
+
})
|
|
6437
|
+
);
|
|
6391
6438
|
}
|
|
6392
6439
|
const blockScalarRegex = /^(\s*)([^:#\s][^:#\s]*)\s*:\s*[|>](\s|$)/gm;
|
|
6393
|
-
|
|
6440
|
+
for (let match = blockScalarRegex.exec(content); match !== null; match = blockScalarRegex.exec(content)) {
|
|
6394
6441
|
const key = match[2];
|
|
6395
6442
|
const offset = match.index;
|
|
6396
6443
|
const line = lineFromOffset(offset);
|
|
6397
6444
|
const col = offset - (lineOffsets[line - 1] ?? 0);
|
|
6398
|
-
symbols.push(
|
|
6399
|
-
|
|
6400
|
-
|
|
6401
|
-
|
|
6402
|
-
|
|
6403
|
-
|
|
6404
|
-
|
|
6405
|
-
|
|
6406
|
-
|
|
6445
|
+
symbols.push(
|
|
6446
|
+
makeSymbol2({
|
|
6447
|
+
name: key,
|
|
6448
|
+
kind: "property",
|
|
6449
|
+
line,
|
|
6450
|
+
col,
|
|
6451
|
+
signature: `${key}: | ...`,
|
|
6452
|
+
file,
|
|
6453
|
+
lang
|
|
6454
|
+
})
|
|
6455
|
+
);
|
|
6407
6456
|
}
|
|
6408
6457
|
return { file, lang, symbols, mtimeMs: Date.now() };
|
|
6409
6458
|
}
|