mirror of
https://github.com/zebrajr/node.git
synced 2025-12-06 00:20:08 +01:00
lib: throw from localStorage getter on missing storage path
PR-URL: https://github.com/nodejs/node/pull/60351 Reviewed-By: Jacob Smith <jacob@frende.me> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com> Reviewed-By: Matthew Aitken <maitken033380023@gmail.com>
This commit is contained in:
parent
1bb853c9d9
commit
2fb3c7eef5
|
|
@ -1,9 +1,9 @@
|
|||
'use strict';
|
||||
const {
|
||||
ObjectDefineProperties,
|
||||
Proxy,
|
||||
} = primordials;
|
||||
const { getOptionValue } = require('internal/options');
|
||||
const { lazyDOMException } = require('internal/util');
|
||||
const { kConstructorKey, Storage } = internalBinding('webstorage');
|
||||
const { getValidatedPath } = require('internal/fs/utils');
|
||||
const kInMemoryPath = ':memory:';
|
||||
|
|
@ -21,34 +21,17 @@ ObjectDefineProperties(module.exports, {
|
|||
enumerable: true,
|
||||
get() {
|
||||
if (lazyLocalStorage === undefined) {
|
||||
// For consistency with the web specification, throw from the accessor
|
||||
// if the local storage path is not provided.
|
||||
const location = getOptionValue('--localstorage-file');
|
||||
|
||||
if (location === '') {
|
||||
let warningEmitted = false;
|
||||
const handler = {
|
||||
__proto__: null,
|
||||
get(target, prop) {
|
||||
if (!warningEmitted) {
|
||||
process.emitWarning('`--localstorage-file` was provided without a valid path');
|
||||
warningEmitted = true;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
},
|
||||
set(target, prop, value) {
|
||||
if (!warningEmitted) {
|
||||
process.emitWarning('`--localstorage-file` was provided without a valid path');
|
||||
warningEmitted = true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
};
|
||||
|
||||
lazyLocalStorage = new Proxy({}, handler);
|
||||
} else {
|
||||
lazyLocalStorage = new Storage(kConstructorKey, getValidatedPath(location));
|
||||
throw lazyDOMException(
|
||||
'Cannot initialize local storage without a `--localstorage-file` path',
|
||||
'SecurityError',
|
||||
);
|
||||
}
|
||||
|
||||
lazyLocalStorage = new Storage(kConstructorKey, getValidatedPath(location));
|
||||
}
|
||||
|
||||
return lazyLocalStorage;
|
||||
|
|
|
|||
|
|
@ -59,6 +59,14 @@ const hasSQLite = Boolean(process.versions.sqlite);
|
|||
|
||||
const hasQuic = hasCrypto && !!process.features.quic;
|
||||
|
||||
const hasLocalStorage = (() => {
|
||||
try {
|
||||
return hasSQLite && globalThis.localStorage !== undefined;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
})();
|
||||
|
||||
/**
|
||||
* Parse test metadata from the specified file.
|
||||
* @param {string} filename - The name of the file to parse.
|
||||
|
|
@ -350,7 +358,6 @@ const knownGlobals = new Set([
|
|||
'CompressionStream',
|
||||
'DecompressionStream',
|
||||
'Storage',
|
||||
'localStorage',
|
||||
'sessionStorage',
|
||||
].forEach((i) => {
|
||||
if (globalThis[i] !== undefined) {
|
||||
|
|
@ -365,6 +372,10 @@ if (hasCrypto) {
|
|||
knownGlobals.add(globalThis.SubtleCrypto);
|
||||
}
|
||||
|
||||
if (hasLocalStorage) {
|
||||
knownGlobals.add(globalThis.localStorage);
|
||||
}
|
||||
|
||||
const { Worker } = require('node:worker_threads');
|
||||
knownGlobals.add(Worker);
|
||||
|
||||
|
|
@ -389,6 +400,11 @@ if (process.env.NODE_TEST_KNOWN_GLOBALS !== '0') {
|
|||
if (val === 'crypto' && !hasCrypto) {
|
||||
continue;
|
||||
}
|
||||
// globalThis.localStorage is a getter that throws if Node.js was
|
||||
// executed without a --localstorage-file path.
|
||||
if (val === 'localStorage' && !hasLocalStorage) {
|
||||
continue;
|
||||
}
|
||||
if (!knownGlobals.has(globalThis[val])) {
|
||||
leaked.push(val);
|
||||
}
|
||||
|
|
@ -933,6 +949,7 @@ const common = {
|
|||
hasQuic,
|
||||
hasInspector,
|
||||
hasSQLite,
|
||||
hasLocalStorage,
|
||||
invalidArgTypeHelper,
|
||||
isAlive,
|
||||
isASan,
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ const {
|
|||
hasQuic,
|
||||
hasInspector,
|
||||
hasSQLite,
|
||||
hasLocalStorage,
|
||||
hasIntl,
|
||||
hasIPv6,
|
||||
isAIX,
|
||||
|
|
@ -71,6 +72,7 @@ export {
|
|||
hasQuic,
|
||||
hasInspector,
|
||||
hasSQLite,
|
||||
hasLocalStorage,
|
||||
hasIntl,
|
||||
hasIPv6,
|
||||
isAIX,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
'use strict';
|
||||
const { hasCrypto } = require('../common');
|
||||
const { hasCrypto, hasLocalStorage } = require('../common');
|
||||
const { test } = require('node:test');
|
||||
const assert = require('assert');
|
||||
|
||||
|
|
@ -12,7 +12,7 @@ const assert = require('assert');
|
|||
if (process.stdout.isTTY)
|
||||
process.env.NODE_DISABLE_COLORS = '1';
|
||||
|
||||
test('', { skip: !hasCrypto }, () => {
|
||||
test({ skip: !hasCrypto || !hasLocalStorage }, () => {
|
||||
// See https://github.com/nodejs/node/issues/10258
|
||||
{
|
||||
const date = new Date('2016');
|
||||
|
|
|
|||
|
|
@ -41,13 +41,13 @@ test('sessionStorage is not persisted', async () => {
|
|||
assert.strictEqual((await readdir(tmpdir.path)).length, 0);
|
||||
});
|
||||
|
||||
test('localStorage emits a warning when used without --localstorage-file ', async () => {
|
||||
test('localStorage throws without --localstorage-file', async () => {
|
||||
const cp = await spawnPromisified(process.execPath, [
|
||||
'-pe', 'localStorage.length',
|
||||
'-e', 'localStorage',
|
||||
]);
|
||||
assert.strictEqual(cp.code, 0);
|
||||
assert.strictEqual(cp.code, 1);
|
||||
assert.strictEqual(cp.signal, null);
|
||||
assert.match(cp.stderr, /Warning: `--localstorage-file` was provided without a valid path/);
|
||||
assert.match(cp.stderr, /SecurityError:/);
|
||||
});
|
||||
|
||||
test('localStorage is not persisted if it is unused', async () => {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user