Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
W
WASM Utils
Manage
Activity
Members
Labels
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Terraform modules
Analyze
Contributor analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
elixxir
WASM Utils
Commits
22c46f9d
Commit
22c46f9d
authored
Jun 7, 2023
by
Jonah Husson
Browse files
Options
Downloads
Patches
Plain Diff
Put LocalStorage behind interface
parent
e832bc49
No related branches found
No related tags found
2 merge requests
!3
Release
,
!2
Project/base32768
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
storage/localStorage.go
+31
-17
31 additions, 17 deletions
storage/localStorage.go
storage/localStorage_test.go
+20
-20
20 additions, 20 deletions
storage/localStorage_test.go
with
51 additions
and
37 deletions
storage/localStorage.go
+
31
−
17
View file @
22c46f9d
...
@@ -21,7 +21,7 @@ import (
...
@@ -21,7 +21,7 @@ import (
)
)
// localStorageWasmPrefix is prefixed to every keyName saved to local storage by
// localStorageWasmPrefix is prefixed to every keyName saved to local storage by
//
L
ocalStorage. It allows the identification and deletion of keys only created
//
l
ocalStorage. It allows the identification and deletion of keys only created
// by this WASM binary while ignoring keys made by other scripts on the same
// by this WASM binary while ignoring keys made by other scripts on the same
// page.
// page.
//
//
...
@@ -31,8 +31,22 @@ const localStorageWasmPrefix = "xxdkWasmStorage/"
...
@@ -31,8 +31,22 @@ const localStorageWasmPrefix = "xxdkWasmStorage/"
// const localStorageWasmPrefix = "🞮🞮"
// const localStorageWasmPrefix = "🞮🞮"
// LocalStorage contains the js.Value representation of localStorage.
// LocalStorage defines an interface for setting persistent state in a KV format
type
LocalStorage
struct
{
// specifically for web-based implementations.
type
LocalStorage
interface
{
Get
(
key
string
)
([]
byte
,
error
)
Set
(
key
string
,
value
[]
byte
)
error
RemoveItem
(
keyName
string
)
Clear
()
int
ClearPrefix
(
prefix
string
)
int
Key
(
n
int
)
(
string
,
error
)
Keys
()
[]
string
Length
()
int
LocalStorageUNSAFE
()
*
LocalStorageJS
}
// localStorage contains the js.Value representation of localStorage.
type
localStorage
struct
{
// The Javascript value containing the localStorage object
// The Javascript value containing the localStorage object
v
*
LocalStorageJS
v
*
LocalStorageJS
...
@@ -45,24 +59,24 @@ type LocalStorage struct {
...
@@ -45,24 +59,24 @@ type LocalStorage struct {
// jsStorage is the global that stores Javascript as window.localStorage.
// jsStorage is the global that stores Javascript as window.localStorage.
//
//
// Doc: https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage
// Doc: https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage
var
jsStorage
=
newLocalStorage
(
localStorageWasmPrefix
)
var
jsStorage
LocalStorage
=
newLocalStorage
(
localStorageWasmPrefix
)
// newLocalStorage creates a new
L
ocalStorage object with the specified prefix.
// newLocalStorage creates a new
l
ocalStorage object with the specified prefix.
func
newLocalStorage
(
prefix
string
)
*
L
ocalStorage
{
func
newLocalStorage
(
prefix
string
)
*
l
ocalStorage
{
return
&
L
ocalStorage
{
return
&
l
ocalStorage
{
v
:
&
LocalStorageJS
{
js
.
Global
()
.
Get
(
"localStorage"
)},
v
:
&
LocalStorageJS
{
js
.
Global
()
.
Get
(
"localStorage"
)},
prefix
:
prefix
,
prefix
:
prefix
,
}
}
}
}
// GetLocalStorage returns Javascript's local storage.
// GetLocalStorage returns Javascript's local storage.
func
GetLocalStorage
()
*
LocalStorage
{
func
GetLocalStorage
()
LocalStorage
{
return
jsStorage
return
jsStorage
}
}
// Get decodes and returns the value from the local storage given its key
// Get decodes and returns the value from the local storage given its key
// name. Returns os.ErrNotExist if the key does not exist.
// name. Returns os.ErrNotExist if the key does not exist.
func
(
ls
*
L
ocalStorage
)
Get
(
keyName
string
)
([]
byte
,
error
)
{
func
(
ls
*
l
ocalStorage
)
Get
(
keyName
string
)
([]
byte
,
error
)
{
value
,
err
:=
ls
.
v
.
GetItem
(
ls
.
prefix
+
keyName
)
value
,
err
:=
ls
.
v
.
GetItem
(
ls
.
prefix
+
keyName
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
...
@@ -73,19 +87,19 @@ func (ls *LocalStorage) Get(keyName string) ([]byte, error) {
...
@@ -73,19 +87,19 @@ func (ls *LocalStorage) Get(keyName string) ([]byte, error) {
// Set encodes the bytes to a string and adds them to local storage at the
// Set encodes the bytes to a string and adds them to local storage at the
// given key name. Returns an error if local storage quota has been reached.
// given key name. Returns an error if local storage quota has been reached.
func
(
ls
*
L
ocalStorage
)
Set
(
keyName
string
,
keyValue
[]
byte
)
error
{
func
(
ls
*
l
ocalStorage
)
Set
(
keyName
string
,
keyValue
[]
byte
)
error
{
encoded
:=
base32768
.
SafeEncoding
.
EncodeToString
(
keyValue
)
encoded
:=
base32768
.
SafeEncoding
.
EncodeToString
(
keyValue
)
return
ls
.
v
.
SetItem
(
ls
.
prefix
+
keyName
,
encoded
)
return
ls
.
v
.
SetItem
(
ls
.
prefix
+
keyName
,
encoded
)
}
}
// RemoveItem removes a key's value from local storage given its name. If there
// RemoveItem removes a key's value from local storage given its name. If there
// is no item with the given key, this function does nothing.
// is no item with the given key, this function does nothing.
func
(
ls
*
L
ocalStorage
)
RemoveItem
(
keyName
string
)
{
func
(
ls
*
l
ocalStorage
)
RemoveItem
(
keyName
string
)
{
ls
.
v
.
RemoveItem
(
ls
.
prefix
+
keyName
)
ls
.
v
.
RemoveItem
(
ls
.
prefix
+
keyName
)
}
}
// Clear clears all the keys in storage. Returns the number of keys cleared.
// Clear clears all the keys in storage. Returns the number of keys cleared.
func
(
ls
*
L
ocalStorage
)
Clear
()
int
{
func
(
ls
*
l
ocalStorage
)
Clear
()
int
{
// Get a copy of all key names at once
// Get a copy of all key names at once
keys
:=
ls
.
v
.
KeysPrefix
(
ls
.
prefix
)
keys
:=
ls
.
v
.
KeysPrefix
(
ls
.
prefix
)
...
@@ -99,7 +113,7 @@ func (ls *LocalStorage) Clear() int {
...
@@ -99,7 +113,7 @@ func (ls *LocalStorage) Clear() int {
// ClearPrefix clears all keys with the given prefix. Returns the number of
// ClearPrefix clears all keys with the given prefix. Returns the number of
// keys cleared.
// keys cleared.
func
(
ls
*
L
ocalStorage
)
ClearPrefix
(
prefix
string
)
int
{
func
(
ls
*
l
ocalStorage
)
ClearPrefix
(
prefix
string
)
int
{
// Get a copy of all key names at once
// Get a copy of all key names at once
keys
:=
ls
.
v
.
KeysPrefix
(
ls
.
prefix
+
prefix
)
keys
:=
ls
.
v
.
KeysPrefix
(
ls
.
prefix
+
prefix
)
...
@@ -113,7 +127,7 @@ func (ls *LocalStorage) ClearPrefix(prefix string) int {
...
@@ -113,7 +127,7 @@ func (ls *LocalStorage) ClearPrefix(prefix string) int {
// Key returns the name of the nth key in localStorage. Return [os.ErrNotExist]
// Key returns the name of the nth key in localStorage. Return [os.ErrNotExist]
// if the key does not exist. The order of keys is not defined.
// if the key does not exist. The order of keys is not defined.
func
(
ls
*
L
ocalStorage
)
Key
(
n
int
)
(
string
,
error
)
{
func
(
ls
*
l
ocalStorage
)
Key
(
n
int
)
(
string
,
error
)
{
keyName
,
err
:=
ls
.
v
.
Key
(
n
)
keyName
,
err
:=
ls
.
v
.
Key
(
n
)
if
err
!=
nil
{
if
err
!=
nil
{
return
""
,
err
return
""
,
err
...
@@ -122,12 +136,12 @@ func (ls *LocalStorage) Key(n int) (string, error) {
...
@@ -122,12 +136,12 @@ func (ls *LocalStorage) Key(n int) (string, error) {
}
}
// Keys returns a list of all key names in local storage.
// Keys returns a list of all key names in local storage.
func
(
ls
*
L
ocalStorage
)
Keys
()
[]
string
{
func
(
ls
*
l
ocalStorage
)
Keys
()
[]
string
{
return
ls
.
v
.
KeysPrefix
(
ls
.
prefix
)
return
ls
.
v
.
KeysPrefix
(
ls
.
prefix
)
}
}
// Length returns the number of keys in localStorage.
// Length returns the number of keys in localStorage.
func
(
ls
*
L
ocalStorage
)
Length
()
int
{
func
(
ls
*
l
ocalStorage
)
Length
()
int
{
return
ls
.
v
.
Length
()
return
ls
.
v
.
Length
()
}
}
...
@@ -139,7 +153,7 @@ func (ls *LocalStorage) Length() int {
...
@@ -139,7 +153,7 @@ func (ls *LocalStorage) Length() int {
// decode/sanitize the inputs/outputs or track entries using the prefix system.
// decode/sanitize the inputs/outputs or track entries using the prefix system.
// If using it, make sure all key names and values can be converted to valid
// If using it, make sure all key names and values can be converted to valid
// UCS-2 strings.
// UCS-2 strings.
func
(
ls
*
L
ocalStorage
)
LocalStorageUNSAFE
()
*
LocalStorageJS
{
func
(
ls
*
l
ocalStorage
)
LocalStorageUNSAFE
()
*
LocalStorageJS
{
return
ls
.
v
return
ls
.
v
}
}
...
...
This diff is collapsed.
Click to expand it.
storage/localStorage_test.go
+
20
−
20
View file @
22c46f9d
...
@@ -21,7 +21,7 @@ import (
...
@@ -21,7 +21,7 @@ import (
// Unit test of GetLocalStorage.
// Unit test of GetLocalStorage.
func
TestGetLocalStorage
(
t
*
testing
.
T
)
{
func
TestGetLocalStorage
(
t
*
testing
.
T
)
{
expected
:=
&
L
ocalStorage
{
expected
:=
&
l
ocalStorage
{
v
:
&
LocalStorageJS
{
js
.
Global
()
.
Get
(
"localStorage"
)},
v
:
&
LocalStorageJS
{
js
.
Global
()
.
Get
(
"localStorage"
)},
prefix
:
localStorageWasmPrefix
,
prefix
:
localStorageWasmPrefix
,
}
}
...
@@ -29,13 +29,13 @@ func TestGetLocalStorage(t *testing.T) {
...
@@ -29,13 +29,13 @@ func TestGetLocalStorage(t *testing.T) {
ls
:=
GetLocalStorage
()
ls
:=
GetLocalStorage
()
if
!
reflect
.
DeepEqual
(
expected
,
ls
)
{
if
!
reflect
.
DeepEqual
(
expected
,
ls
)
{
t
.
Errorf
(
"Did not receive expected
L
ocalStorage."
+
t
.
Errorf
(
"Did not receive expected
l
ocalStorage."
+
"
\n
expected: %+v
\n
received: %+v"
,
expected
,
ls
)
"
\n
expected: %+v
\n
received: %+v"
,
expected
,
ls
)
}
}
}
}
// Tests that a value set with
L
ocalStorage.Set and retrieved with
// Tests that a value set with
l
ocalStorage.Set and retrieved with
//
L
ocalStorage.Get matches the original.
//
l
ocalStorage.Get matches the original.
func
TestLocalStorage_Get_Set
(
t
*
testing
.
T
)
{
func
TestLocalStorage_Get_Set
(
t
*
testing
.
T
)
{
values
:=
map
[
string
][]
byte
{
values
:=
map
[
string
][]
byte
{
"key1"
:
[]
byte
(
"key value"
),
"key1"
:
[]
byte
(
"key value"
),
...
@@ -64,7 +64,7 @@ func TestLocalStorage_Get_Set(t *testing.T) {
...
@@ -64,7 +64,7 @@ func TestLocalStorage_Get_Set(t *testing.T) {
}
}
}
}
// Tests that
L
ocalStorage.Get returns the error os.ErrNotExist when the key
// Tests that
l
ocalStorage.Get returns the error os.ErrNotExist when the key
// does not exist in storage.
// does not exist in storage.
func
TestLocalStorage_Get_NotExistError
(
t
*
testing
.
T
)
{
func
TestLocalStorage_Get_NotExistError
(
t
*
testing
.
T
)
{
_
,
err
:=
jsStorage
.
Get
(
"someKey"
)
_
,
err
:=
jsStorage
.
Get
(
"someKey"
)
...
@@ -74,7 +74,7 @@ func TestLocalStorage_Get_NotExistError(t *testing.T) {
...
@@ -74,7 +74,7 @@ func TestLocalStorage_Get_NotExistError(t *testing.T) {
}
}
}
}
// Tests that
L
ocalStorage.RemoveItem deletes a key from the store and that it
// Tests that
l
ocalStorage.RemoveItem deletes a key from the store and that it
// cannot be retrieved.
// cannot be retrieved.
func
TestLocalStorage_RemoveItem
(
t
*
testing
.
T
)
{
func
TestLocalStorage_RemoveItem
(
t
*
testing
.
T
)
{
keyName
:=
"key"
keyName
:=
"key"
...
@@ -89,10 +89,10 @@ func TestLocalStorage_RemoveItem(t *testing.T) {
...
@@ -89,10 +89,10 @@ func TestLocalStorage_RemoveItem(t *testing.T) {
}
}
}
}
// Tests that
L
ocalStorage.Clear deletes all the WASM keys from storage and
// Tests that
l
ocalStorage.Clear deletes all the WASM keys from storage and
// does not remove any others
// does not remove any others
func
TestLocalStorage_Clear
(
t
*
testing
.
T
)
{
func
TestLocalStorage_Clear
(
t
*
testing
.
T
)
{
jsStorage
.
v
.
Clear
()
jsStorage
.
LocalStorageUNSAFE
()
.
Clear
()
const
numKeys
=
10
const
numKeys
=
10
var
yesPrefix
,
noPrefix
[]
string
var
yesPrefix
,
noPrefix
[]
string
...
@@ -106,7 +106,7 @@ func TestLocalStorage_Clear(t *testing.T) {
...
@@ -106,7 +106,7 @@ func TestLocalStorage_Clear(t *testing.T) {
}
}
}
else
{
}
else
{
noPrefix
=
append
(
noPrefix
,
keyName
)
noPrefix
=
append
(
noPrefix
,
keyName
)
err
:=
jsStorage
.
v
.
SetItem
(
keyName
,
strconv
.
Itoa
(
i
))
err
:=
jsStorage
.
LocalStorageUNSAFE
()
.
SetItem
(
keyName
,
strconv
.
Itoa
(
i
))
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Errorf
(
"Failed to set with no prefix %q: %+v"
,
keyName
,
err
)
t
.
Errorf
(
"Failed to set with no prefix %q: %+v"
,
keyName
,
err
)
}
}
...
@@ -120,7 +120,7 @@ func TestLocalStorage_Clear(t *testing.T) {
...
@@ -120,7 +120,7 @@ func TestLocalStorage_Clear(t *testing.T) {
}
}
for
_
,
keyName
:=
range
noPrefix
{
for
_
,
keyName
:=
range
noPrefix
{
if
_
,
err
:=
jsStorage
.
v
.
GetItem
(
keyName
);
err
!=
nil
{
if
_
,
err
:=
jsStorage
.
LocalStorageUNSAFE
()
.
GetItem
(
keyName
);
err
!=
nil
{
t
.
Errorf
(
"Could not get keyName %q: %+v"
,
keyName
,
err
)
t
.
Errorf
(
"Could not get keyName %q: %+v"
,
keyName
,
err
)
}
}
}
}
...
@@ -132,10 +132,10 @@ func TestLocalStorage_Clear(t *testing.T) {
...
@@ -132,10 +132,10 @@ func TestLocalStorage_Clear(t *testing.T) {
}
}
}
}
// Tests that
L
ocalStorage.ClearPrefix deletes only the keys with the given
// Tests that
l
ocalStorage.ClearPrefix deletes only the keys with the given
// prefix.
// prefix.
func
TestLocalStorage_ClearPrefix
(
t
*
testing
.
T
)
{
func
TestLocalStorage_ClearPrefix
(
t
*
testing
.
T
)
{
jsStorage
.
v
.
Clear
()
jsStorage
.
LocalStorageUNSAFE
()
.
Clear
()
const
numKeys
=
10
const
numKeys
=
10
var
yesPrefix
,
noPrefix
[]
string
var
yesPrefix
,
noPrefix
[]
string
prefix
:=
"keyNamePrefix/"
prefix
:=
"keyNamePrefix/"
...
@@ -173,10 +173,10 @@ func TestLocalStorage_ClearPrefix(t *testing.T) {
...
@@ -173,10 +173,10 @@ func TestLocalStorage_ClearPrefix(t *testing.T) {
}
}
}
}
// Tests that
L
ocalStorage.Key return all added keys when looping through all
// Tests that
l
ocalStorage.Key return all added keys when looping through all
// indexes.
// indexes.
func
TestLocalStorage_Key
(
t
*
testing
.
T
)
{
func
TestLocalStorage_Key
(
t
*
testing
.
T
)
{
jsStorage
.
v
.
Clear
()
jsStorage
.
LocalStorageUNSAFE
()
.
Clear
()
values
:=
map
[
string
][]
byte
{
values
:=
map
[
string
][]
byte
{
"key1"
:
[]
byte
(
"key value"
),
"key1"
:
[]
byte
(
"key value"
),
"key2"
:
{
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
},
"key2"
:
{
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
},
...
@@ -207,10 +207,10 @@ func TestLocalStorage_Key(t *testing.T) {
...
@@ -207,10 +207,10 @@ func TestLocalStorage_Key(t *testing.T) {
}
}
}
}
// Tests that
L
ocalStorage.Key returns the error os.ErrNotExist when the index
// Tests that
l
ocalStorage.Key returns the error os.ErrNotExist when the index
// is greater than or equal to the number of keys.
// is greater than or equal to the number of keys.
func
TestLocalStorage_Key_NotExistError
(
t
*
testing
.
T
)
{
func
TestLocalStorage_Key_NotExistError
(
t
*
testing
.
T
)
{
jsStorage
.
v
.
Clear
()
jsStorage
.
LocalStorageUNSAFE
()
.
Clear
()
if
err
:=
jsStorage
.
Set
(
"key"
,
[]
byte
(
"value"
));
err
!=
nil
{
if
err
:=
jsStorage
.
Set
(
"key"
,
[]
byte
(
"value"
));
err
!=
nil
{
t
.
Errorf
(
"Failed to set: %+v"
,
err
)
t
.
Errorf
(
"Failed to set: %+v"
,
err
)
}
}
...
@@ -228,10 +228,10 @@ func TestLocalStorage_Key_NotExistError(t *testing.T) {
...
@@ -228,10 +228,10 @@ func TestLocalStorage_Key_NotExistError(t *testing.T) {
}
}
}
}
// Tests that
L
ocalStorage.Length returns the correct Length when adding and
// Tests that
l
ocalStorage.Length returns the correct Length when adding and
// removing various keys.
// removing various keys.
func
TestLocalStorage_Length
(
t
*
testing
.
T
)
{
func
TestLocalStorage_Length
(
t
*
testing
.
T
)
{
jsStorage
.
v
.
Clear
()
jsStorage
.
LocalStorageUNSAFE
()
.
Clear
()
values
:=
map
[
string
][]
byte
{
values
:=
map
[
string
][]
byte
{
"key1"
:
[]
byte
(
"key value"
),
"key1"
:
[]
byte
(
"key value"
),
"key2"
:
{
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
},
"key2"
:
{
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
},
...
@@ -263,9 +263,9 @@ func TestLocalStorage_Length(t *testing.T) {
...
@@ -263,9 +263,9 @@ func TestLocalStorage_Length(t *testing.T) {
}
}
}
}
// Tests that
L
ocalStorage.Keys return a list that contains all the added keys.
// Tests that
l
ocalStorage.Keys return a list that contains all the added keys.
func
TestLocalStorage_Keys
(
t
*
testing
.
T
)
{
func
TestLocalStorage_Keys
(
t
*
testing
.
T
)
{
jsStorage
.
v
.
Clear
()
jsStorage
.
LocalStorageUNSAFE
()
.
Clear
()
values
:=
map
[
string
][]
byte
{
values
:=
map
[
string
][]
byte
{
"key1"
:
[]
byte
(
"key value"
),
"key1"
:
[]
byte
(
"key value"
),
"key2"
:
{
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
},
"key2"
:
{
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
},
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment