snapshot of https://github.com/cortezaproject/corteza.git (2024.9.x, 2026-09-18; blobs > 131072B omitted)
Some checks failed
SonarQube / SonarQube (push) Failing after 5m28s
E2e test on main branch push / server and client test (map[name:admin port:8080]) (push) Failing after 3m33s
Server and lib tests / Library test (js) (push) Failing after 1m36s
Server and lib tests / Library test (vue) (push) Successful in 2m24s
Server and lib tests / Web client test (admin) (push) Successful in 2m52s
Server and lib tests / Web client test (compose) (push) Successful in 3m23s
Server and lib tests / Web client test (discovery) (push) Successful in 2m49s
Server and lib tests / Web client test (one) (push) Successful in 2m52s
Server and lib tests / Web client test (privacy) (push) Successful in 2m44s
Server and lib tests / Web client test (reporter) (push) Successful in 2m56s
Server and lib tests / Web client test (workflow) (push) Successful in 3m0s
Server and lib tests / Server tests (push) Failing after 4m55s
E2e test on main branch push / notify-failure (push) Failing after 9s
Server and lib tests / Send matrix testing notification (push) Successful in 2s
Mark stale issues and pull requests / stale (push) Successful in 40s
Some checks failed
SonarQube / SonarQube (push) Failing after 5m28s
E2e test on main branch push / server and client test (map[name:admin port:8080]) (push) Failing after 3m33s
Server and lib tests / Library test (js) (push) Failing after 1m36s
Server and lib tests / Library test (vue) (push) Successful in 2m24s
Server and lib tests / Web client test (admin) (push) Successful in 2m52s
Server and lib tests / Web client test (compose) (push) Successful in 3m23s
Server and lib tests / Web client test (discovery) (push) Successful in 2m49s
Server and lib tests / Web client test (one) (push) Successful in 2m52s
Server and lib tests / Web client test (privacy) (push) Successful in 2m44s
Server and lib tests / Web client test (reporter) (push) Successful in 2m56s
Server and lib tests / Web client test (workflow) (push) Successful in 3m0s
Server and lib tests / Server tests (push) Failing after 4m55s
E2e test on main branch push / notify-failure (push) Failing after 9s
Server and lib tests / Send matrix testing notification (push) Successful in 2s
Mark stale issues and pull requests / stale (push) Successful in 40s
This commit is contained in:
3
server/vendor/github.com/dop251/goja/.gitignore
generated
vendored
Normal file
3
server/vendor/github.com/dop251/goja/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
.idea
|
||||
*.iml
|
||||
testdata/test262
|
||||
11
server/vendor/github.com/dop251/goja/.tc39_test262_checkout.sh
generated
vendored
Normal file
11
server/vendor/github.com/dop251/goja/.tc39_test262_checkout.sh
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
# this is just the commit it was last tested with
|
||||
sha=926b0960d737b9f1dfd0ec0c1dfd95d836016d33
|
||||
|
||||
mkdir -p testdata/test262
|
||||
cd testdata/test262
|
||||
git init
|
||||
git remote add origin https://github.com/tc39/test262.git
|
||||
git fetch origin --depth=1 "${sha}"
|
||||
git reset --hard "${sha}"
|
||||
cd -
|
||||
15
server/vendor/github.com/dop251/goja/LICENSE
generated
vendored
Normal file
15
server/vendor/github.com/dop251/goja/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
Copyright (c) 2016 Dmitry Panov
|
||||
|
||||
Copyright (c) 2012 Robert Krimen
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
||||
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
332
server/vendor/github.com/dop251/goja/README.md
generated
vendored
Normal file
332
server/vendor/github.com/dop251/goja/README.md
generated
vendored
Normal file
@@ -0,0 +1,332 @@
|
||||
goja
|
||||
====
|
||||
|
||||
ECMAScript 5.1(+) implementation in Go.
|
||||
|
||||
[](https://pkg.go.dev/github.com/dop251/goja)
|
||||
|
||||
Goja is an implementation of ECMAScript 5.1 in pure Go with emphasis on standard compliance and
|
||||
performance.
|
||||
|
||||
This project was largely inspired by [otto](https://github.com/robertkrimen/otto).
|
||||
|
||||
Minimum required Go version is 1.16.
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
* Full ECMAScript 5.1 support (including regex and strict mode).
|
||||
* Passes nearly all [tc39 tests](https://github.com/tc39/test262) for the features implemented so far. The goal is to
|
||||
pass all of them. See .tc39_test262_checkout.sh for the latest working commit id.
|
||||
* Capable of running Babel, Typescript compiler and pretty much anything written in ES5.
|
||||
* Sourcemaps.
|
||||
* Most of ES6 functionality, still work in progress, see https://github.com/dop251/goja/milestone/1?closed=1
|
||||
|
||||
Known incompatibilities and caveats
|
||||
-----------------------------------
|
||||
|
||||
### WeakMap
|
||||
WeakMap is implemented by embedding references to the values into the keys. This means that as long
|
||||
as the key is reachable all values associated with it in any weak maps also remain reachable and therefore
|
||||
cannot be garbage collected even if they are not otherwise referenced, even after the WeakMap is gone.
|
||||
The reference to the value is dropped either when the key is explicitly removed from the WeakMap or when the
|
||||
key becomes unreachable.
|
||||
|
||||
To illustrate this:
|
||||
|
||||
```javascript
|
||||
var m = new WeakMap();
|
||||
var key = {};
|
||||
var value = {/* a very large object */};
|
||||
m.set(key, value);
|
||||
value = undefined;
|
||||
m = undefined; // The value does NOT become garbage-collectable at this point
|
||||
key = undefined; // Now it does
|
||||
// m.delete(key); // This would work too
|
||||
```
|
||||
|
||||
The reason for it is the limitation of the Go runtime. At the time of writing (version 1.15) having a finalizer
|
||||
set on an object which is part of a reference cycle makes the whole cycle non-garbage-collectable. The solution
|
||||
above is the only reasonable way I can think of without involving finalizers. This is the third attempt
|
||||
(see https://github.com/dop251/goja/issues/250 and https://github.com/dop251/goja/issues/199 for more details).
|
||||
|
||||
Note, this does not have any effect on the application logic, but may cause a higher-than-expected memory usage.
|
||||
|
||||
### WeakRef and FinalizationRegistry
|
||||
For the reason mentioned above implementing WeakRef and FinalizationRegistry does not seem to be possible at this stage.
|
||||
|
||||
### JSON
|
||||
`JSON.parse()` uses the standard Go library which operates in UTF-8. Therefore, it cannot correctly parse broken UTF-16
|
||||
surrogate pairs, for example:
|
||||
|
||||
```javascript
|
||||
JSON.parse(`"\\uD800"`).charCodeAt(0).toString(16) // returns "fffd" instead of "d800"
|
||||
```
|
||||
|
||||
### Date
|
||||
Conversion from calendar date to epoch timestamp uses the standard Go library which uses `int`, rather than `float` as per
|
||||
ECMAScript specification. This means if you pass arguments that overflow int to the `Date()` constructor or if there is
|
||||
an integer overflow, the result will be incorrect, for example:
|
||||
|
||||
```javascript
|
||||
Date.UTC(1970, 0, 1, 80063993375, 29, 1, -288230376151711740) // returns 29256 instead of 29312
|
||||
```
|
||||
|
||||
FAQ
|
||||
---
|
||||
|
||||
### How fast is it?
|
||||
|
||||
Although it's faster than many scripting language implementations in Go I have seen
|
||||
(for example it's 6-7 times faster than otto on average) it is not a
|
||||
replacement for V8 or SpiderMonkey or any other general-purpose JavaScript engine.
|
||||
You can find some benchmarks [here](https://github.com/dop251/goja/issues/2).
|
||||
|
||||
### Why would I want to use it over a V8 wrapper?
|
||||
|
||||
It greatly depends on your usage scenario. If most of the work is done in javascript
|
||||
(for example crypto or any other heavy calculations) you are definitely better off with V8.
|
||||
|
||||
If you need a scripting language that drives an engine written in Go so that
|
||||
you need to make frequent calls between Go and javascript passing complex data structures
|
||||
then the cgo overhead may outweigh the benefits of having a faster javascript engine.
|
||||
|
||||
Because it's written in pure Go there are no cgo dependencies, it's very easy to build and it
|
||||
should run on any platform supported by Go.
|
||||
|
||||
It gives you a much better control over execution environment so can be useful for research.
|
||||
|
||||
### Is it goroutine-safe?
|
||||
|
||||
No. An instance of goja.Runtime can only be used by a single goroutine
|
||||
at a time. You can create as many instances of Runtime as you like but
|
||||
it's not possible to pass object values between runtimes.
|
||||
|
||||
### Where is setTimeout()?
|
||||
|
||||
setTimeout() assumes concurrent execution of code which requires an execution
|
||||
environment, for example an event loop similar to nodejs or a browser.
|
||||
There is a [separate project](https://github.com/dop251/goja_nodejs) aimed at providing some NodeJS functionality,
|
||||
and it includes an event loop.
|
||||
|
||||
### Can you implement (feature X from ES6 or higher)?
|
||||
|
||||
I will be adding features in their dependency order and as quickly as time permits. Please do not ask
|
||||
for ETAs. Features that are open in the [milestone](https://github.com/dop251/goja/milestone/1) are either in progress
|
||||
or will be worked on next.
|
||||
|
||||
The ongoing work is done in separate feature branches which are merged into master when appropriate.
|
||||
Every commit in these branches represents a relatively stable state (i.e. it compiles and passes all enabled tc39 tests),
|
||||
however because the version of tc39 tests I use is quite old, it may be not as well tested as the ES5.1 functionality. Because there are (usually) no major breaking changes between ECMAScript revisions
|
||||
it should not break your existing code. You are encouraged to give it a try and report any bugs found. Please do not submit fixes though without discussing it first, as the code could be changed in the meantime.
|
||||
|
||||
### How do I contribute?
|
||||
|
||||
Before submitting a pull request please make sure that:
|
||||
|
||||
- You followed ECMA standard as close as possible. If adding a new feature make sure you've read the specification,
|
||||
do not just base it on a couple of examples that work fine.
|
||||
- Your change does not have a significant negative impact on performance (unless it's a bugfix and it's unavoidable)
|
||||
- It passes all relevant tc39 tests.
|
||||
|
||||
Current Status
|
||||
--------------
|
||||
|
||||
* There should be no breaking changes in the API, however it may be extended.
|
||||
* Some of the AnnexB functionality is missing.
|
||||
|
||||
Basic Example
|
||||
-------------
|
||||
|
||||
Run JavaScript and get the result value.
|
||||
|
||||
```go
|
||||
vm := goja.New()
|
||||
v, err := vm.RunString("2 + 2")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if num := v.Export().(int64); num != 4 {
|
||||
panic(num)
|
||||
}
|
||||
```
|
||||
|
||||
Passing Values to JS
|
||||
--------------------
|
||||
Any Go value can be passed to JS using Runtime.ToValue() method. See the method's [documentation](https://pkg.go.dev/github.com/dop251/goja#Runtime.ToValue) for more details.
|
||||
|
||||
Exporting Values from JS
|
||||
------------------------
|
||||
A JS value can be exported into its default Go representation using Value.Export() method.
|
||||
|
||||
Alternatively it can be exported into a specific Go variable using [Runtime.ExportTo()](https://pkg.go.dev/github.com/dop251/goja#Runtime.ExportTo) method.
|
||||
|
||||
Within a single export operation the same Object will be represented by the same Go value (either the same map, slice or
|
||||
a pointer to the same struct). This includes circular objects and makes it possible to export them.
|
||||
|
||||
Calling JS functions from Go
|
||||
----------------------------
|
||||
There are 2 approaches:
|
||||
|
||||
- Using [AssertFunction()](https://pkg.go.dev/github.com/dop251/goja#AssertFunction):
|
||||
```go
|
||||
vm := New()
|
||||
_, err := vm.RunString(`
|
||||
function sum(a, b) {
|
||||
return a+b;
|
||||
}
|
||||
`)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
sum, ok := AssertFunction(vm.Get("sum"))
|
||||
if !ok {
|
||||
panic("Not a function")
|
||||
}
|
||||
|
||||
res, err := sum(Undefined(), vm.ToValue(40), vm.ToValue(2))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println(res)
|
||||
// Output: 42
|
||||
```
|
||||
- Using [Runtime.ExportTo()](https://pkg.go.dev/github.com/dop251/goja#Runtime.ExportTo):
|
||||
```go
|
||||
const SCRIPT = `
|
||||
function f(param) {
|
||||
return +param + 2;
|
||||
}
|
||||
`
|
||||
|
||||
vm := New()
|
||||
_, err := vm.RunString(SCRIPT)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
var fn func(string) string
|
||||
err = vm.ExportTo(vm.Get("f"), &fn)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Println(fn("40")) // note, _this_ value in the function will be undefined.
|
||||
// Output: 42
|
||||
```
|
||||
|
||||
The first one is more low level and allows specifying _this_ value, whereas the second one makes the function look like
|
||||
a normal Go function.
|
||||
|
||||
Mapping struct field and method names
|
||||
-------------------------------------
|
||||
By default, the names are passed through as is which means they are capitalised. This does not match
|
||||
the standard JavaScript naming convention, so if you need to make your JS code look more natural or if you are
|
||||
dealing with a 3rd party library, you can use a [FieldNameMapper](https://pkg.go.dev/github.com/dop251/goja#FieldNameMapper):
|
||||
|
||||
```go
|
||||
vm := New()
|
||||
vm.SetFieldNameMapper(TagFieldNameMapper("json", true))
|
||||
type S struct {
|
||||
Field int `json:"field"`
|
||||
}
|
||||
vm.Set("s", S{Field: 42})
|
||||
res, _ := vm.RunString(`s.field`) // without the mapper it would have been s.Field
|
||||
fmt.Println(res.Export())
|
||||
// Output: 42
|
||||
```
|
||||
|
||||
There are two standard mappers: [TagFieldNameMapper](https://pkg.go.dev/github.com/dop251/goja#TagFieldNameMapper) and
|
||||
[UncapFieldNameMapper](https://pkg.go.dev/github.com/dop251/goja#UncapFieldNameMapper), or you can use your own implementation.
|
||||
|
||||
Native Constructors
|
||||
-------------------
|
||||
|
||||
In order to implement a constructor function in Go use `func (goja.ConstructorCall) *goja.Object`.
|
||||
See [Runtime.ToValue()](https://pkg.go.dev/github.com/dop251/goja#Runtime.ToValue) documentation for more details.
|
||||
|
||||
Regular Expressions
|
||||
-------------------
|
||||
|
||||
Goja uses the embedded Go regexp library where possible, otherwise it falls back to [regexp2](https://github.com/dlclark/regexp2).
|
||||
|
||||
Exceptions
|
||||
----------
|
||||
|
||||
Any exception thrown in JavaScript is returned as an error of type *Exception. It is possible to extract the value thrown
|
||||
by using the Value() method:
|
||||
|
||||
```go
|
||||
vm := New()
|
||||
_, err := vm.RunString(`
|
||||
|
||||
throw("Test");
|
||||
|
||||
`)
|
||||
|
||||
if jserr, ok := err.(*Exception); ok {
|
||||
if jserr.Value().Export() != "Test" {
|
||||
panic("wrong value")
|
||||
}
|
||||
} else {
|
||||
panic("wrong type")
|
||||
}
|
||||
```
|
||||
|
||||
If a native Go function panics with a Value, it is thrown as a Javascript exception (and therefore can be caught):
|
||||
|
||||
```go
|
||||
var vm *Runtime
|
||||
|
||||
func Test() {
|
||||
panic(vm.ToValue("Error"))
|
||||
}
|
||||
|
||||
vm = New()
|
||||
vm.Set("Test", Test)
|
||||
_, err := vm.RunString(`
|
||||
|
||||
try {
|
||||
Test();
|
||||
} catch(e) {
|
||||
if (e !== "Error") {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
`)
|
||||
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
```
|
||||
|
||||
Interrupting
|
||||
------------
|
||||
|
||||
```go
|
||||
func TestInterrupt(t *testing.T) {
|
||||
const SCRIPT = `
|
||||
var i = 0;
|
||||
for (;;) {
|
||||
i++;
|
||||
}
|
||||
`
|
||||
|
||||
vm := New()
|
||||
time.AfterFunc(200 * time.Millisecond, func() {
|
||||
vm.Interrupt("halt")
|
||||
})
|
||||
|
||||
_, err := vm.RunString(SCRIPT)
|
||||
if err == nil {
|
||||
t.Fatal("Err is nil")
|
||||
}
|
||||
// err is of type *InterruptError and its Value() method returns whatever has been passed to vm.Interrupt()
|
||||
}
|
||||
```
|
||||
|
||||
NodeJS Compatibility
|
||||
--------------------
|
||||
|
||||
There is a [separate project](https://github.com/dop251/goja_nodejs) aimed at providing some of the NodeJS functionality.
|
||||
553
server/vendor/github.com/dop251/goja/array.go
generated
vendored
Normal file
553
server/vendor/github.com/dop251/goja/array.go
generated
vendored
Normal file
@@ -0,0 +1,553 @@
|
||||
package goja
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"math/bits"
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
||||
"github.com/dop251/goja/unistring"
|
||||
)
|
||||
|
||||
type arrayIterObject struct {
|
||||
baseObject
|
||||
obj *Object
|
||||
nextIdx int64
|
||||
kind iterationKind
|
||||
}
|
||||
|
||||
func (ai *arrayIterObject) next() Value {
|
||||
if ai.obj == nil {
|
||||
return ai.val.runtime.createIterResultObject(_undefined, true)
|
||||
}
|
||||
if ta, ok := ai.obj.self.(*typedArrayObject); ok {
|
||||
ta.viewedArrayBuf.ensureNotDetached(true)
|
||||
}
|
||||
l := toLength(ai.obj.self.getStr("length", nil))
|
||||
index := ai.nextIdx
|
||||
if index >= l {
|
||||
ai.obj = nil
|
||||
return ai.val.runtime.createIterResultObject(_undefined, true)
|
||||
}
|
||||
ai.nextIdx++
|
||||
idxVal := valueInt(index)
|
||||
if ai.kind == iterationKindKey {
|
||||
return ai.val.runtime.createIterResultObject(idxVal, false)
|
||||
}
|
||||
elementValue := nilSafe(ai.obj.self.getIdx(idxVal, nil))
|
||||
var result Value
|
||||
if ai.kind == iterationKindValue {
|
||||
result = elementValue
|
||||
} else {
|
||||
result = ai.val.runtime.newArrayValues([]Value{idxVal, elementValue})
|
||||
}
|
||||
return ai.val.runtime.createIterResultObject(result, false)
|
||||
}
|
||||
|
||||
func (r *Runtime) createArrayIterator(iterObj *Object, kind iterationKind) Value {
|
||||
o := &Object{runtime: r}
|
||||
|
||||
ai := &arrayIterObject{
|
||||
obj: iterObj,
|
||||
kind: kind,
|
||||
}
|
||||
ai.class = classObject
|
||||
ai.val = o
|
||||
ai.extensible = true
|
||||
o.self = ai
|
||||
ai.prototype = r.getArrayIteratorPrototype()
|
||||
ai.init()
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
type arrayObject struct {
|
||||
baseObject
|
||||
values []Value
|
||||
length uint32
|
||||
objCount int
|
||||
propValueCount int
|
||||
lengthProp valueProperty
|
||||
}
|
||||
|
||||
func (a *arrayObject) init() {
|
||||
a.baseObject.init()
|
||||
a.lengthProp.writable = true
|
||||
|
||||
a._put("length", &a.lengthProp)
|
||||
}
|
||||
|
||||
func (a *arrayObject) _setLengthInt(l uint32, throw bool) bool {
|
||||
ret := true
|
||||
if l <= a.length {
|
||||
if a.propValueCount > 0 {
|
||||
// Slow path
|
||||
for i := len(a.values) - 1; i >= int(l); i-- {
|
||||
if prop, ok := a.values[i].(*valueProperty); ok {
|
||||
if !prop.configurable {
|
||||
l = uint32(i) + 1
|
||||
ret = false
|
||||
break
|
||||
}
|
||||
a.propValueCount--
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if l <= uint32(len(a.values)) {
|
||||
if l >= 16 && l < uint32(cap(a.values))>>2 {
|
||||
ar := make([]Value, l)
|
||||
copy(ar, a.values)
|
||||
a.values = ar
|
||||
} else {
|
||||
ar := a.values[l:len(a.values)]
|
||||
for i := range ar {
|
||||
ar[i] = nil
|
||||
}
|
||||
a.values = a.values[:l]
|
||||
}
|
||||
}
|
||||
a.length = l
|
||||
if !ret {
|
||||
a.val.runtime.typeErrorResult(throw, "Cannot redefine property: length")
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (a *arrayObject) setLengthInt(l uint32, throw bool) bool {
|
||||
if l == a.length {
|
||||
return true
|
||||
}
|
||||
if !a.lengthProp.writable {
|
||||
a.val.runtime.typeErrorResult(throw, "length is not writable")
|
||||
return false
|
||||
}
|
||||
return a._setLengthInt(l, throw)
|
||||
}
|
||||
|
||||
func (a *arrayObject) setLength(v uint32, throw bool) bool {
|
||||
if !a.lengthProp.writable {
|
||||
a.val.runtime.typeErrorResult(throw, "length is not writable")
|
||||
return false
|
||||
}
|
||||
return a._setLengthInt(v, throw)
|
||||
}
|
||||
|
||||
func (a *arrayObject) getIdx(idx valueInt, receiver Value) Value {
|
||||
prop := a.getOwnPropIdx(idx)
|
||||
if prop == nil {
|
||||
if a.prototype != nil {
|
||||
if receiver == nil {
|
||||
return a.prototype.self.getIdx(idx, a.val)
|
||||
}
|
||||
return a.prototype.self.getIdx(idx, receiver)
|
||||
}
|
||||
}
|
||||
if prop, ok := prop.(*valueProperty); ok {
|
||||
if receiver == nil {
|
||||
return prop.get(a.val)
|
||||
}
|
||||
return prop.get(receiver)
|
||||
}
|
||||
return prop
|
||||
}
|
||||
|
||||
func (a *arrayObject) getOwnPropStr(name unistring.String) Value {
|
||||
if len(a.values) > 0 {
|
||||
if i := strToArrayIdx(name); i != math.MaxUint32 {
|
||||
if i < uint32(len(a.values)) {
|
||||
return a.values[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
if name == "length" {
|
||||
return a.getLengthProp()
|
||||
}
|
||||
return a.baseObject.getOwnPropStr(name)
|
||||
}
|
||||
|
||||
func (a *arrayObject) getOwnPropIdx(idx valueInt) Value {
|
||||
if i := toIdx(idx); i != math.MaxUint32 {
|
||||
if i < uint32(len(a.values)) {
|
||||
return a.values[i]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
return a.baseObject.getOwnPropStr(idx.string())
|
||||
}
|
||||
|
||||
func (a *arrayObject) sortLen() int {
|
||||
return len(a.values)
|
||||
}
|
||||
|
||||
func (a *arrayObject) sortGet(i int) Value {
|
||||
v := a.values[i]
|
||||
if p, ok := v.(*valueProperty); ok {
|
||||
v = p.get(a.val)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func (a *arrayObject) swap(i int, j int) {
|
||||
a.values[i], a.values[j] = a.values[j], a.values[i]
|
||||
}
|
||||
|
||||
func (a *arrayObject) getStr(name unistring.String, receiver Value) Value {
|
||||
return a.getStrWithOwnProp(a.getOwnPropStr(name), name, receiver)
|
||||
}
|
||||
|
||||
func (a *arrayObject) getLengthProp() *valueProperty {
|
||||
a.lengthProp.value = intToValue(int64(a.length))
|
||||
return &a.lengthProp
|
||||
}
|
||||
|
||||
func (a *arrayObject) setOwnIdx(idx valueInt, val Value, throw bool) bool {
|
||||
if i := toIdx(idx); i != math.MaxUint32 {
|
||||
return a._setOwnIdx(i, val, throw)
|
||||
} else {
|
||||
return a.baseObject.setOwnStr(idx.string(), val, throw)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *arrayObject) _setOwnIdx(idx uint32, val Value, throw bool) bool {
|
||||
var prop Value
|
||||
if idx < uint32(len(a.values)) {
|
||||
prop = a.values[idx]
|
||||
}
|
||||
|
||||
if prop == nil {
|
||||
if proto := a.prototype; proto != nil {
|
||||
// we know it's foreign because prototype loops are not allowed
|
||||
if res, ok := proto.self.setForeignIdx(valueInt(idx), val, a.val, throw); ok {
|
||||
return res
|
||||
}
|
||||
}
|
||||
// new property
|
||||
if !a.extensible {
|
||||
a.val.runtime.typeErrorResult(throw, "Cannot add property %d, object is not extensible", idx)
|
||||
return false
|
||||
} else {
|
||||
if idx >= a.length {
|
||||
if !a.setLengthInt(idx+1, throw) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
if idx >= uint32(len(a.values)) {
|
||||
if !a.expand(idx) {
|
||||
a.val.self.(*sparseArrayObject).add(idx, val)
|
||||
return true
|
||||
}
|
||||
}
|
||||
a.objCount++
|
||||
}
|
||||
} else {
|
||||
if prop, ok := prop.(*valueProperty); ok {
|
||||
if !prop.isWritable() {
|
||||
a.val.runtime.typeErrorResult(throw)
|
||||
return false
|
||||
}
|
||||
prop.set(a.val, val)
|
||||
return true
|
||||
}
|
||||
}
|
||||
a.values[idx] = val
|
||||
return true
|
||||
}
|
||||
|
||||
func (a *arrayObject) setOwnStr(name unistring.String, val Value, throw bool) bool {
|
||||
if idx := strToArrayIdx(name); idx != math.MaxUint32 {
|
||||
return a._setOwnIdx(idx, val, throw)
|
||||
} else {
|
||||
if name == "length" {
|
||||
return a.setLength(a.val.runtime.toLengthUint32(val), throw)
|
||||
} else {
|
||||
return a.baseObject.setOwnStr(name, val, throw)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (a *arrayObject) setForeignIdx(idx valueInt, val, receiver Value, throw bool) (bool, bool) {
|
||||
return a._setForeignIdx(idx, a.getOwnPropIdx(idx), val, receiver, throw)
|
||||
}
|
||||
|
||||
func (a *arrayObject) setForeignStr(name unistring.String, val, receiver Value, throw bool) (bool, bool) {
|
||||
return a._setForeignStr(name, a.getOwnPropStr(name), val, receiver, throw)
|
||||
}
|
||||
|
||||
type arrayPropIter struct {
|
||||
a *arrayObject
|
||||
limit int
|
||||
idx int
|
||||
}
|
||||
|
||||
func (i *arrayPropIter) next() (propIterItem, iterNextFunc) {
|
||||
for i.idx < len(i.a.values) && i.idx < i.limit {
|
||||
name := asciiString(strconv.Itoa(i.idx))
|
||||
prop := i.a.values[i.idx]
|
||||
i.idx++
|
||||
if prop != nil {
|
||||
return propIterItem{name: name, value: prop}, i.next
|
||||
}
|
||||
}
|
||||
|
||||
return i.a.baseObject.iterateStringKeys()()
|
||||
}
|
||||
|
||||
func (a *arrayObject) iterateStringKeys() iterNextFunc {
|
||||
return (&arrayPropIter{
|
||||
a: a,
|
||||
limit: len(a.values),
|
||||
}).next
|
||||
}
|
||||
|
||||
func (a *arrayObject) stringKeys(all bool, accum []Value) []Value {
|
||||
for i, prop := range a.values {
|
||||
name := strconv.Itoa(i)
|
||||
if prop != nil {
|
||||
if !all {
|
||||
if prop, ok := prop.(*valueProperty); ok && !prop.enumerable {
|
||||
continue
|
||||
}
|
||||
}
|
||||
accum = append(accum, asciiString(name))
|
||||
}
|
||||
}
|
||||
return a.baseObject.stringKeys(all, accum)
|
||||
}
|
||||
|
||||
func (a *arrayObject) hasOwnPropertyStr(name unistring.String) bool {
|
||||
if idx := strToArrayIdx(name); idx != math.MaxUint32 {
|
||||
return idx < uint32(len(a.values)) && a.values[idx] != nil
|
||||
} else {
|
||||
return a.baseObject.hasOwnPropertyStr(name)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *arrayObject) hasOwnPropertyIdx(idx valueInt) bool {
|
||||
if idx := toIdx(idx); idx != math.MaxUint32 {
|
||||
return idx < uint32(len(a.values)) && a.values[idx] != nil
|
||||
}
|
||||
return a.baseObject.hasOwnPropertyStr(idx.string())
|
||||
}
|
||||
|
||||
func (a *arrayObject) expand(idx uint32) bool {
|
||||
targetLen := idx + 1
|
||||
if targetLen > uint32(len(a.values)) {
|
||||
if targetLen < uint32(cap(a.values)) {
|
||||
a.values = a.values[:targetLen]
|
||||
} else {
|
||||
if idx > 4096 && (a.objCount == 0 || idx/uint32(a.objCount) > 10) {
|
||||
//log.Println("Switching standard->sparse")
|
||||
sa := &sparseArrayObject{
|
||||
baseObject: a.baseObject,
|
||||
length: a.length,
|
||||
propValueCount: a.propValueCount,
|
||||
}
|
||||
sa.setValues(a.values, a.objCount+1)
|
||||
sa.val.self = sa
|
||||
sa.lengthProp.writable = a.lengthProp.writable
|
||||
sa._put("length", &sa.lengthProp)
|
||||
return false
|
||||
} else {
|
||||
if bits.UintSize == 32 {
|
||||
if targetLen >= math.MaxInt32 {
|
||||
panic(a.val.runtime.NewTypeError("Array index overflows int"))
|
||||
}
|
||||
}
|
||||
tl := int(targetLen)
|
||||
newValues := make([]Value, tl, growCap(tl, len(a.values), cap(a.values)))
|
||||
copy(newValues, a.values)
|
||||
a.values = newValues
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (r *Runtime) defineArrayLength(prop *valueProperty, descr PropertyDescriptor, setter func(uint32, bool) bool, throw bool) bool {
|
||||
var newLen uint32
|
||||
ret := true
|
||||
if descr.Value != nil {
|
||||
newLen = r.toLengthUint32(descr.Value)
|
||||
}
|
||||
|
||||
if descr.Configurable == FLAG_TRUE || descr.Enumerable == FLAG_TRUE || descr.Getter != nil || descr.Setter != nil {
|
||||
ret = false
|
||||
goto Reject
|
||||
}
|
||||
|
||||
if descr.Value != nil {
|
||||
oldLen := uint32(prop.value.ToInteger())
|
||||
if oldLen != newLen {
|
||||
ret = setter(newLen, false)
|
||||
}
|
||||
} else {
|
||||
ret = true
|
||||
}
|
||||
|
||||
if descr.Writable != FLAG_NOT_SET {
|
||||
w := descr.Writable.Bool()
|
||||
if prop.writable {
|
||||
prop.writable = w
|
||||
} else {
|
||||
if w {
|
||||
ret = false
|
||||
goto Reject
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reject:
|
||||
if !ret {
|
||||
r.typeErrorResult(throw, "Cannot redefine property: length")
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func (a *arrayObject) _defineIdxProperty(idx uint32, desc PropertyDescriptor, throw bool) bool {
|
||||
var existing Value
|
||||
if idx < uint32(len(a.values)) {
|
||||
existing = a.values[idx]
|
||||
}
|
||||
prop, ok := a.baseObject._defineOwnProperty(unistring.String(strconv.FormatUint(uint64(idx), 10)), existing, desc, throw)
|
||||
if ok {
|
||||
if idx >= a.length {
|
||||
if !a.setLengthInt(idx+1, throw) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
if a.expand(idx) {
|
||||
a.values[idx] = prop
|
||||
a.objCount++
|
||||
if _, ok := prop.(*valueProperty); ok {
|
||||
a.propValueCount++
|
||||
}
|
||||
} else {
|
||||
a.val.self.(*sparseArrayObject).add(idx, prop)
|
||||
}
|
||||
}
|
||||
return ok
|
||||
}
|
||||
|
||||
func (a *arrayObject) defineOwnPropertyStr(name unistring.String, descr PropertyDescriptor, throw bool) bool {
|
||||
if idx := strToArrayIdx(name); idx != math.MaxUint32 {
|
||||
return a._defineIdxProperty(idx, descr, throw)
|
||||
}
|
||||
if name == "length" {
|
||||
return a.val.runtime.defineArrayLength(a.getLengthProp(), descr, a.setLength, throw)
|
||||
}
|
||||
return a.baseObject.defineOwnPropertyStr(name, descr, throw)
|
||||
}
|
||||
|
||||
func (a *arrayObject) defineOwnPropertyIdx(idx valueInt, descr PropertyDescriptor, throw bool) bool {
|
||||
if idx := toIdx(idx); idx != math.MaxUint32 {
|
||||
return a._defineIdxProperty(idx, descr, throw)
|
||||
}
|
||||
return a.baseObject.defineOwnPropertyStr(idx.string(), descr, throw)
|
||||
}
|
||||
|
||||
func (a *arrayObject) _deleteIdxProp(idx uint32, throw bool) bool {
|
||||
if idx < uint32(len(a.values)) {
|
||||
if v := a.values[idx]; v != nil {
|
||||
if p, ok := v.(*valueProperty); ok {
|
||||
if !p.configurable {
|
||||
a.val.runtime.typeErrorResult(throw, "Cannot delete property '%d' of %s", idx, a.val.toString())
|
||||
return false
|
||||
}
|
||||
a.propValueCount--
|
||||
}
|
||||
a.values[idx] = nil
|
||||
a.objCount--
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (a *arrayObject) deleteStr(name unistring.String, throw bool) bool {
|
||||
if idx := strToArrayIdx(name); idx != math.MaxUint32 {
|
||||
return a._deleteIdxProp(idx, throw)
|
||||
}
|
||||
return a.baseObject.deleteStr(name, throw)
|
||||
}
|
||||
|
||||
func (a *arrayObject) deleteIdx(idx valueInt, throw bool) bool {
|
||||
if idx := toIdx(idx); idx != math.MaxUint32 {
|
||||
return a._deleteIdxProp(idx, throw)
|
||||
}
|
||||
return a.baseObject.deleteStr(idx.string(), throw)
|
||||
}
|
||||
|
||||
func (a *arrayObject) export(ctx *objectExportCtx) interface{} {
|
||||
if v, exists := ctx.get(a.val); exists {
|
||||
return v
|
||||
}
|
||||
arr := make([]interface{}, a.length)
|
||||
ctx.put(a.val, arr)
|
||||
if a.propValueCount == 0 && a.length == uint32(len(a.values)) && uint32(a.objCount) == a.length {
|
||||
for i, v := range a.values {
|
||||
if v != nil {
|
||||
arr[i] = exportValue(v, ctx)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for i := uint32(0); i < a.length; i++ {
|
||||
v := a.getIdx(valueInt(i), nil)
|
||||
if v != nil {
|
||||
arr[i] = exportValue(v, ctx)
|
||||
}
|
||||
}
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
func (a *arrayObject) exportType() reflect.Type {
|
||||
return reflectTypeArray
|
||||
}
|
||||
|
||||
func (a *arrayObject) exportToArrayOrSlice(dst reflect.Value, typ reflect.Type, ctx *objectExportCtx) error {
|
||||
r := a.val.runtime
|
||||
if iter := a.getSym(SymIterator, nil); iter == r.global.arrayValues || iter == nil {
|
||||
l := toIntStrict(int64(a.length))
|
||||
if typ.Kind() == reflect.Array {
|
||||
if dst.Len() != l {
|
||||
return fmt.Errorf("cannot convert an Array into an array, lengths mismatch (have %d, need %d)", l, dst.Len())
|
||||
}
|
||||
} else {
|
||||
dst.Set(reflect.MakeSlice(typ, l, l))
|
||||
}
|
||||
ctx.putTyped(a.val, typ, dst.Interface())
|
||||
for i := 0; i < l; i++ {
|
||||
if i >= len(a.values) {
|
||||
break
|
||||
}
|
||||
val := a.values[i]
|
||||
if p, ok := val.(*valueProperty); ok {
|
||||
val = p.get(a.val)
|
||||
}
|
||||
err := r.toReflectValue(val, dst.Index(i), ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not convert array element %v to %v at %d: %w", val, typ, i, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return a.baseObject.exportToArrayOrSlice(dst, typ, ctx)
|
||||
}
|
||||
|
||||
func (a *arrayObject) setValuesFromSparse(items []sparseArrayItem, newMaxIdx int) {
|
||||
a.values = make([]Value, newMaxIdx+1)
|
||||
for _, item := range items {
|
||||
a.values[item.idx] = item.value
|
||||
}
|
||||
a.objCount = len(items)
|
||||
}
|
||||
|
||||
func toIdx(v valueInt) uint32 {
|
||||
if v >= 0 && v < math.MaxUint32 {
|
||||
return uint32(v)
|
||||
}
|
||||
return math.MaxUint32
|
||||
}
|
||||
488
server/vendor/github.com/dop251/goja/array_sparse.go
generated
vendored
Normal file
488
server/vendor/github.com/dop251/goja/array_sparse.go
generated
vendored
Normal file
@@ -0,0 +1,488 @@
|
||||
package goja
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"math/bits"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
|
||||
"github.com/dop251/goja/unistring"
|
||||
)
|
||||
|
||||
type sparseArrayItem struct {
|
||||
idx uint32
|
||||
value Value
|
||||
}
|
||||
|
||||
type sparseArrayObject struct {
|
||||
baseObject
|
||||
items []sparseArrayItem
|
||||
length uint32
|
||||
propValueCount int
|
||||
lengthProp valueProperty
|
||||
}
|
||||
|
||||
func (a *sparseArrayObject) findIdx(idx uint32) int {
|
||||
return sort.Search(len(a.items), func(i int) bool {
|
||||
return a.items[i].idx >= idx
|
||||
})
|
||||
}
|
||||
|
||||
func (a *sparseArrayObject) _setLengthInt(l uint32, throw bool) bool {
|
||||
ret := true
|
||||
if l <= a.length {
|
||||
if a.propValueCount > 0 {
|
||||
// Slow path
|
||||
for i := len(a.items) - 1; i >= 0; i-- {
|
||||
item := a.items[i]
|
||||
if item.idx <= l {
|
||||
break
|
||||
}
|
||||
if prop, ok := item.value.(*valueProperty); ok {
|
||||
if !prop.configurable {
|
||||
l = item.idx + 1
|
||||
ret = false
|
||||
break
|
||||
}
|
||||
a.propValueCount--
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
idx := a.findIdx(l)
|
||||
|
||||
aa := a.items[idx:]
|
||||
for i := range aa {
|
||||
aa[i].value = nil
|
||||
}
|
||||
a.items = a.items[:idx]
|
||||
a.length = l
|
||||
if !ret {
|
||||
a.val.runtime.typeErrorResult(throw, "Cannot redefine property: length")
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (a *sparseArrayObject) setLengthInt(l uint32, throw bool) bool {
|
||||
if l == a.length {
|
||||
return true
|
||||
}
|
||||
if !a.lengthProp.writable {
|
||||
a.val.runtime.typeErrorResult(throw, "length is not writable")
|
||||
return false
|
||||
}
|
||||
return a._setLengthInt(l, throw)
|
||||
}
|
||||
|
||||
func (a *sparseArrayObject) setLength(v uint32, throw bool) bool {
|
||||
if !a.lengthProp.writable {
|
||||
a.val.runtime.typeErrorResult(throw, "length is not writable")
|
||||
return false
|
||||
}
|
||||
return a._setLengthInt(v, throw)
|
||||
}
|
||||
|
||||
func (a *sparseArrayObject) _getIdx(idx uint32) Value {
|
||||
i := a.findIdx(idx)
|
||||
if i < len(a.items) && a.items[i].idx == idx {
|
||||
return a.items[i].value
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *sparseArrayObject) getStr(name unistring.String, receiver Value) Value {
|
||||
return a.getStrWithOwnProp(a.getOwnPropStr(name), name, receiver)
|
||||
}
|
||||
|
||||
func (a *sparseArrayObject) getIdx(idx valueInt, receiver Value) Value {
|
||||
prop := a.getOwnPropIdx(idx)
|
||||
if prop == nil {
|
||||
if a.prototype != nil {
|
||||
if receiver == nil {
|
||||
return a.prototype.self.getIdx(idx, a.val)
|
||||
}
|
||||
return a.prototype.self.getIdx(idx, receiver)
|
||||
}
|
||||
}
|
||||
if prop, ok := prop.(*valueProperty); ok {
|
||||
if receiver == nil {
|
||||
return prop.get(a.val)
|
||||
}
|
||||
return prop.get(receiver)
|
||||
}
|
||||
return prop
|
||||
}
|
||||
|
||||
func (a *sparseArrayObject) getLengthProp() *valueProperty {
|
||||
a.lengthProp.value = intToValue(int64(a.length))
|
||||
return &a.lengthProp
|
||||
}
|
||||
|
||||
func (a *sparseArrayObject) getOwnPropStr(name unistring.String) Value {
|
||||
if idx := strToArrayIdx(name); idx != math.MaxUint32 {
|
||||
return a._getIdx(idx)
|
||||
}
|
||||
if name == "length" {
|
||||
return a.getLengthProp()
|
||||
}
|
||||
return a.baseObject.getOwnPropStr(name)
|
||||
}
|
||||
|
||||
func (a *sparseArrayObject) getOwnPropIdx(idx valueInt) Value {
|
||||
if idx := toIdx(idx); idx != math.MaxUint32 {
|
||||
return a._getIdx(idx)
|
||||
}
|
||||
return a.baseObject.getOwnPropStr(idx.string())
|
||||
}
|
||||
|
||||
func (a *sparseArrayObject) add(idx uint32, val Value) {
|
||||
i := a.findIdx(idx)
|
||||
a.items = append(a.items, sparseArrayItem{})
|
||||
copy(a.items[i+1:], a.items[i:])
|
||||
a.items[i] = sparseArrayItem{
|
||||
idx: idx,
|
||||
value: val,
|
||||
}
|
||||
}
|
||||
|
||||
func (a *sparseArrayObject) _setOwnIdx(idx uint32, val Value, throw bool) bool {
|
||||
var prop Value
|
||||
i := a.findIdx(idx)
|
||||
if i < len(a.items) && a.items[i].idx == idx {
|
||||
prop = a.items[i].value
|
||||
}
|
||||
|
||||
if prop == nil {
|
||||
if proto := a.prototype; proto != nil {
|
||||
// we know it's foreign because prototype loops are not allowed
|
||||
if res, ok := proto.self.setForeignIdx(valueInt(idx), val, a.val, throw); ok {
|
||||
return res
|
||||
}
|
||||
}
|
||||
|
||||
// new property
|
||||
if !a.extensible {
|
||||
a.val.runtime.typeErrorResult(throw, "Cannot add property %d, object is not extensible", idx)
|
||||
return false
|
||||
}
|
||||
|
||||
if idx >= a.length {
|
||||
if !a.setLengthInt(idx+1, throw) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if a.expand(idx) {
|
||||
a.items = append(a.items, sparseArrayItem{})
|
||||
copy(a.items[i+1:], a.items[i:])
|
||||
a.items[i] = sparseArrayItem{
|
||||
idx: idx,
|
||||
value: val,
|
||||
}
|
||||
} else {
|
||||
ar := a.val.self.(*arrayObject)
|
||||
ar.values[idx] = val
|
||||
ar.objCount++
|
||||
return true
|
||||
}
|
||||
} else {
|
||||
if prop, ok := prop.(*valueProperty); ok {
|
||||
if !prop.isWritable() {
|
||||
a.val.runtime.typeErrorResult(throw)
|
||||
return false
|
||||
}
|
||||
prop.set(a.val, val)
|
||||
} else {
|
||||
a.items[i].value = val
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (a *sparseArrayObject) setOwnStr(name unistring.String, val Value, throw bool) bool {
|
||||
if idx := strToArrayIdx(name); idx != math.MaxUint32 {
|
||||
return a._setOwnIdx(idx, val, throw)
|
||||
} else {
|
||||
if name == "length" {
|
||||
return a.setLength(a.val.runtime.toLengthUint32(val), throw)
|
||||
} else {
|
||||
return a.baseObject.setOwnStr(name, val, throw)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (a *sparseArrayObject) setOwnIdx(idx valueInt, val Value, throw bool) bool {
|
||||
if idx := toIdx(idx); idx != math.MaxUint32 {
|
||||
return a._setOwnIdx(idx, val, throw)
|
||||
}
|
||||
|
||||
return a.baseObject.setOwnStr(idx.string(), val, throw)
|
||||
}
|
||||
|
||||
func (a *sparseArrayObject) setForeignStr(name unistring.String, val, receiver Value, throw bool) (bool, bool) {
|
||||
return a._setForeignStr(name, a.getOwnPropStr(name), val, receiver, throw)
|
||||
}
|
||||
|
||||
func (a *sparseArrayObject) setForeignIdx(name valueInt, val, receiver Value, throw bool) (bool, bool) {
|
||||
return a._setForeignIdx(name, a.getOwnPropIdx(name), val, receiver, throw)
|
||||
}
|
||||
|
||||
type sparseArrayPropIter struct {
|
||||
a *sparseArrayObject
|
||||
idx int
|
||||
}
|
||||
|
||||
func (i *sparseArrayPropIter) next() (propIterItem, iterNextFunc) {
|
||||
for i.idx < len(i.a.items) {
|
||||
name := asciiString(strconv.Itoa(int(i.a.items[i.idx].idx)))
|
||||
prop := i.a.items[i.idx].value
|
||||
i.idx++
|
||||
if prop != nil {
|
||||
return propIterItem{name: name, value: prop}, i.next
|
||||
}
|
||||
}
|
||||
|
||||
return i.a.baseObject.iterateStringKeys()()
|
||||
}
|
||||
|
||||
func (a *sparseArrayObject) iterateStringKeys() iterNextFunc {
|
||||
return (&sparseArrayPropIter{
|
||||
a: a,
|
||||
}).next
|
||||
}
|
||||
|
||||
func (a *sparseArrayObject) stringKeys(all bool, accum []Value) []Value {
|
||||
if all {
|
||||
for _, item := range a.items {
|
||||
accum = append(accum, asciiString(strconv.FormatUint(uint64(item.idx), 10)))
|
||||
}
|
||||
} else {
|
||||
for _, item := range a.items {
|
||||
if prop, ok := item.value.(*valueProperty); ok && !prop.enumerable {
|
||||
continue
|
||||
}
|
||||
accum = append(accum, asciiString(strconv.FormatUint(uint64(item.idx), 10)))
|
||||
}
|
||||
}
|
||||
|
||||
return a.baseObject.stringKeys(all, accum)
|
||||
}
|
||||
|
||||
func (a *sparseArrayObject) setValues(values []Value, objCount int) {
|
||||
a.items = make([]sparseArrayItem, 0, objCount)
|
||||
for i, val := range values {
|
||||
if val != nil {
|
||||
a.items = append(a.items, sparseArrayItem{
|
||||
idx: uint32(i),
|
||||
value: val,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (a *sparseArrayObject) hasOwnPropertyStr(name unistring.String) bool {
|
||||
if idx := strToArrayIdx(name); idx != math.MaxUint32 {
|
||||
i := a.findIdx(idx)
|
||||
return i < len(a.items) && a.items[i].idx == idx
|
||||
} else {
|
||||
return a.baseObject.hasOwnPropertyStr(name)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *sparseArrayObject) hasOwnPropertyIdx(idx valueInt) bool {
|
||||
if idx := toIdx(idx); idx != math.MaxUint32 {
|
||||
i := a.findIdx(idx)
|
||||
return i < len(a.items) && a.items[i].idx == idx
|
||||
}
|
||||
|
||||
return a.baseObject.hasOwnPropertyStr(idx.string())
|
||||
}
|
||||
|
||||
func (a *sparseArrayObject) expand(idx uint32) bool {
|
||||
if l := len(a.items); l >= 1024 {
|
||||
if ii := a.items[l-1].idx; ii > idx {
|
||||
idx = ii
|
||||
}
|
||||
if (bits.UintSize == 64 || idx < math.MaxInt32) && int(idx)>>3 < l {
|
||||
//log.Println("Switching sparse->standard")
|
||||
ar := &arrayObject{
|
||||
baseObject: a.baseObject,
|
||||
length: a.length,
|
||||
propValueCount: a.propValueCount,
|
||||
}
|
||||
ar.setValuesFromSparse(a.items, int(idx))
|
||||
ar.val.self = ar
|
||||
ar.lengthProp.writable = a.lengthProp.writable
|
||||
a._put("length", &ar.lengthProp)
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (a *sparseArrayObject) _defineIdxProperty(idx uint32, desc PropertyDescriptor, throw bool) bool {
|
||||
var existing Value
|
||||
i := a.findIdx(idx)
|
||||
if i < len(a.items) && a.items[i].idx == idx {
|
||||
existing = a.items[i].value
|
||||
}
|
||||
prop, ok := a.baseObject._defineOwnProperty(unistring.String(strconv.FormatUint(uint64(idx), 10)), existing, desc, throw)
|
||||
if ok {
|
||||
if idx >= a.length {
|
||||
if !a.setLengthInt(idx+1, throw) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
if i >= len(a.items) || a.items[i].idx != idx {
|
||||
if a.expand(idx) {
|
||||
a.items = append(a.items, sparseArrayItem{})
|
||||
copy(a.items[i+1:], a.items[i:])
|
||||
a.items[i] = sparseArrayItem{
|
||||
idx: idx,
|
||||
value: prop,
|
||||
}
|
||||
if idx >= a.length {
|
||||
a.length = idx + 1
|
||||
}
|
||||
} else {
|
||||
a.val.self.(*arrayObject).values[idx] = prop
|
||||
}
|
||||
} else {
|
||||
a.items[i].value = prop
|
||||
}
|
||||
if _, ok := prop.(*valueProperty); ok {
|
||||
a.propValueCount++
|
||||
}
|
||||
}
|
||||
return ok
|
||||
}
|
||||
|
||||
func (a *sparseArrayObject) defineOwnPropertyStr(name unistring.String, descr PropertyDescriptor, throw bool) bool {
|
||||
if idx := strToArrayIdx(name); idx != math.MaxUint32 {
|
||||
return a._defineIdxProperty(idx, descr, throw)
|
||||
}
|
||||
if name == "length" {
|
||||
return a.val.runtime.defineArrayLength(a.getLengthProp(), descr, a.setLength, throw)
|
||||
}
|
||||
return a.baseObject.defineOwnPropertyStr(name, descr, throw)
|
||||
}
|
||||
|
||||
func (a *sparseArrayObject) defineOwnPropertyIdx(idx valueInt, descr PropertyDescriptor, throw bool) bool {
|
||||
if idx := toIdx(idx); idx != math.MaxUint32 {
|
||||
return a._defineIdxProperty(idx, descr, throw)
|
||||
}
|
||||
return a.baseObject.defineOwnPropertyStr(idx.string(), descr, throw)
|
||||
}
|
||||
|
||||
func (a *sparseArrayObject) _deleteIdxProp(idx uint32, throw bool) bool {
|
||||
i := a.findIdx(idx)
|
||||
if i < len(a.items) && a.items[i].idx == idx {
|
||||
if p, ok := a.items[i].value.(*valueProperty); ok {
|
||||
if !p.configurable {
|
||||
a.val.runtime.typeErrorResult(throw, "Cannot delete property '%d' of %s", idx, a.val.toString())
|
||||
return false
|
||||
}
|
||||
a.propValueCount--
|
||||
}
|
||||
copy(a.items[i:], a.items[i+1:])
|
||||
a.items[len(a.items)-1].value = nil
|
||||
a.items = a.items[:len(a.items)-1]
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (a *sparseArrayObject) deleteStr(name unistring.String, throw bool) bool {
|
||||
if idx := strToArrayIdx(name); idx != math.MaxUint32 {
|
||||
return a._deleteIdxProp(idx, throw)
|
||||
}
|
||||
return a.baseObject.deleteStr(name, throw)
|
||||
}
|
||||
|
||||
func (a *sparseArrayObject) deleteIdx(idx valueInt, throw bool) bool {
|
||||
if idx := toIdx(idx); idx != math.MaxUint32 {
|
||||
return a._deleteIdxProp(idx, throw)
|
||||
}
|
||||
return a.baseObject.deleteStr(idx.string(), throw)
|
||||
}
|
||||
|
||||
func (a *sparseArrayObject) sortLen() int {
|
||||
if len(a.items) > 0 {
|
||||
return toIntStrict(int64(a.items[len(a.items)-1].idx) + 1)
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func (a *sparseArrayObject) export(ctx *objectExportCtx) interface{} {
|
||||
if v, exists := ctx.get(a.val); exists {
|
||||
return v
|
||||
}
|
||||
arr := make([]interface{}, a.length)
|
||||
ctx.put(a.val, arr)
|
||||
var prevIdx uint32
|
||||
for _, item := range a.items {
|
||||
idx := item.idx
|
||||
for i := prevIdx; i < idx; i++ {
|
||||
if a.prototype != nil {
|
||||
if v := a.prototype.self.getIdx(valueInt(i), nil); v != nil {
|
||||
arr[i] = exportValue(v, ctx)
|
||||
}
|
||||
}
|
||||
}
|
||||
v := item.value
|
||||
if v != nil {
|
||||
if prop, ok := v.(*valueProperty); ok {
|
||||
v = prop.get(a.val)
|
||||
}
|
||||
arr[idx] = exportValue(v, ctx)
|
||||
}
|
||||
prevIdx = idx + 1
|
||||
}
|
||||
for i := prevIdx; i < a.length; i++ {
|
||||
if a.prototype != nil {
|
||||
if v := a.prototype.self.getIdx(valueInt(i), nil); v != nil {
|
||||
arr[i] = exportValue(v, ctx)
|
||||
}
|
||||
}
|
||||
}
|
||||
return arr
|
||||
}
|
||||
|
||||
func (a *sparseArrayObject) exportType() reflect.Type {
|
||||
return reflectTypeArray
|
||||
}
|
||||
|
||||
func (a *sparseArrayObject) exportToArrayOrSlice(dst reflect.Value, typ reflect.Type, ctx *objectExportCtx) error {
|
||||
r := a.val.runtime
|
||||
if iter := a.getSym(SymIterator, nil); iter == r.global.arrayValues || iter == nil {
|
||||
l := toIntStrict(int64(a.length))
|
||||
if typ.Kind() == reflect.Array {
|
||||
if dst.Len() != l {
|
||||
return fmt.Errorf("cannot convert an Array into an array, lengths mismatch (have %d, need %d)", l, dst.Len())
|
||||
}
|
||||
} else {
|
||||
dst.Set(reflect.MakeSlice(typ, l, l))
|
||||
}
|
||||
ctx.putTyped(a.val, typ, dst.Interface())
|
||||
for _, item := range a.items {
|
||||
val := item.value
|
||||
if p, ok := val.(*valueProperty); ok {
|
||||
val = p.get(a.val)
|
||||
}
|
||||
idx := toIntStrict(int64(item.idx))
|
||||
if idx >= l {
|
||||
break
|
||||
}
|
||||
err := r.toReflectValue(val, dst.Index(idx), ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not convert array element %v to %v at %d: %w", item.value, typ, idx, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return a.baseObject.exportToArrayOrSlice(dst, typ, ctx)
|
||||
}
|
||||
1068
server/vendor/github.com/dop251/goja/ast/README.markdown
generated
vendored
Normal file
1068
server/vendor/github.com/dop251/goja/ast/README.markdown
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
859
server/vendor/github.com/dop251/goja/ast/node.go
generated
vendored
Normal file
859
server/vendor/github.com/dop251/goja/ast/node.go
generated
vendored
Normal file
@@ -0,0 +1,859 @@
|
||||
/*
|
||||
Package ast declares types representing a JavaScript AST.
|
||||
|
||||
# Warning
|
||||
|
||||
The parser and AST interfaces are still works-in-progress (particularly where
|
||||
node types are concerned) and may change in the future.
|
||||
*/
|
||||
package ast
|
||||
|
||||
import (
|
||||
"github.com/dop251/goja/file"
|
||||
"github.com/dop251/goja/token"
|
||||
"github.com/dop251/goja/unistring"
|
||||
)
|
||||
|
||||
type PropertyKind string
|
||||
|
||||
const (
|
||||
PropertyKindValue PropertyKind = "value"
|
||||
PropertyKindGet PropertyKind = "get"
|
||||
PropertyKindSet PropertyKind = "set"
|
||||
PropertyKindMethod PropertyKind = "method"
|
||||
)
|
||||
|
||||
// All nodes implement the Node interface.
|
||||
type Node interface {
|
||||
Idx0() file.Idx // The index of the first character belonging to the node
|
||||
Idx1() file.Idx // The index of the first character immediately after the node
|
||||
}
|
||||
|
||||
// ========== //
|
||||
// Expression //
|
||||
// ========== //
|
||||
|
||||
type (
|
||||
// All expression nodes implement the Expression interface.
|
||||
Expression interface {
|
||||
Node
|
||||
_expressionNode()
|
||||
}
|
||||
|
||||
BindingTarget interface {
|
||||
Expression
|
||||
_bindingTarget()
|
||||
}
|
||||
|
||||
Binding struct {
|
||||
Target BindingTarget
|
||||
Initializer Expression
|
||||
}
|
||||
|
||||
Pattern interface {
|
||||
BindingTarget
|
||||
_pattern()
|
||||
}
|
||||
|
||||
YieldExpression struct {
|
||||
Yield file.Idx
|
||||
Argument Expression
|
||||
Delegate bool
|
||||
}
|
||||
|
||||
AwaitExpression struct {
|
||||
Await file.Idx
|
||||
Argument Expression
|
||||
}
|
||||
|
||||
ArrayLiteral struct {
|
||||
LeftBracket file.Idx
|
||||
RightBracket file.Idx
|
||||
Value []Expression
|
||||
}
|
||||
|
||||
ArrayPattern struct {
|
||||
LeftBracket file.Idx
|
||||
RightBracket file.Idx
|
||||
Elements []Expression
|
||||
Rest Expression
|
||||
}
|
||||
|
||||
AssignExpression struct {
|
||||
Operator token.Token
|
||||
Left Expression
|
||||
Right Expression
|
||||
}
|
||||
|
||||
BadExpression struct {
|
||||
From file.Idx
|
||||
To file.Idx
|
||||
}
|
||||
|
||||
BinaryExpression struct {
|
||||
Operator token.Token
|
||||
Left Expression
|
||||
Right Expression
|
||||
Comparison bool
|
||||
}
|
||||
|
||||
BooleanLiteral struct {
|
||||
Idx file.Idx
|
||||
Literal string
|
||||
Value bool
|
||||
}
|
||||
|
||||
BracketExpression struct {
|
||||
Left Expression
|
||||
Member Expression
|
||||
LeftBracket file.Idx
|
||||
RightBracket file.Idx
|
||||
}
|
||||
|
||||
CallExpression struct {
|
||||
Callee Expression
|
||||
LeftParenthesis file.Idx
|
||||
ArgumentList []Expression
|
||||
RightParenthesis file.Idx
|
||||
}
|
||||
|
||||
ConditionalExpression struct {
|
||||
Test Expression
|
||||
Consequent Expression
|
||||
Alternate Expression
|
||||
}
|
||||
|
||||
DotExpression struct {
|
||||
Left Expression
|
||||
Identifier Identifier
|
||||
}
|
||||
|
||||
PrivateDotExpression struct {
|
||||
Left Expression
|
||||
Identifier PrivateIdentifier
|
||||
}
|
||||
|
||||
OptionalChain struct {
|
||||
Expression
|
||||
}
|
||||
|
||||
Optional struct {
|
||||
Expression
|
||||
}
|
||||
|
||||
FunctionLiteral struct {
|
||||
Function file.Idx
|
||||
Name *Identifier
|
||||
ParameterList *ParameterList
|
||||
Body *BlockStatement
|
||||
Source string
|
||||
|
||||
DeclarationList []*VariableDeclaration
|
||||
|
||||
Async, Generator bool
|
||||
}
|
||||
|
||||
ClassLiteral struct {
|
||||
Class file.Idx
|
||||
RightBrace file.Idx
|
||||
Name *Identifier
|
||||
SuperClass Expression
|
||||
Body []ClassElement
|
||||
Source string
|
||||
}
|
||||
|
||||
ConciseBody interface {
|
||||
Node
|
||||
_conciseBody()
|
||||
}
|
||||
|
||||
ExpressionBody struct {
|
||||
Expression Expression
|
||||
}
|
||||
|
||||
ArrowFunctionLiteral struct {
|
||||
Start file.Idx
|
||||
ParameterList *ParameterList
|
||||
Body ConciseBody
|
||||
Source string
|
||||
DeclarationList []*VariableDeclaration
|
||||
Async bool
|
||||
}
|
||||
|
||||
Identifier struct {
|
||||
Name unistring.String
|
||||
Idx file.Idx
|
||||
}
|
||||
|
||||
PrivateIdentifier struct {
|
||||
Identifier
|
||||
}
|
||||
|
||||
NewExpression struct {
|
||||
New file.Idx
|
||||
Callee Expression
|
||||
LeftParenthesis file.Idx
|
||||
ArgumentList []Expression
|
||||
RightParenthesis file.Idx
|
||||
}
|
||||
|
||||
NullLiteral struct {
|
||||
Idx file.Idx
|
||||
Literal string
|
||||
}
|
||||
|
||||
NumberLiteral struct {
|
||||
Idx file.Idx
|
||||
Literal string
|
||||
Value interface{}
|
||||
}
|
||||
|
||||
ObjectLiteral struct {
|
||||
LeftBrace file.Idx
|
||||
RightBrace file.Idx
|
||||
Value []Property
|
||||
}
|
||||
|
||||
ObjectPattern struct {
|
||||
LeftBrace file.Idx
|
||||
RightBrace file.Idx
|
||||
Properties []Property
|
||||
Rest Expression
|
||||
}
|
||||
|
||||
ParameterList struct {
|
||||
Opening file.Idx
|
||||
List []*Binding
|
||||
Rest Expression
|
||||
Closing file.Idx
|
||||
}
|
||||
|
||||
Property interface {
|
||||
Expression
|
||||
_property()
|
||||
}
|
||||
|
||||
PropertyShort struct {
|
||||
Name Identifier
|
||||
Initializer Expression
|
||||
}
|
||||
|
||||
PropertyKeyed struct {
|
||||
Key Expression
|
||||
Kind PropertyKind
|
||||
Value Expression
|
||||
Computed bool
|
||||
}
|
||||
|
||||
SpreadElement struct {
|
||||
Expression
|
||||
}
|
||||
|
||||
RegExpLiteral struct {
|
||||
Idx file.Idx
|
||||
Literal string
|
||||
Pattern string
|
||||
Flags string
|
||||
}
|
||||
|
||||
SequenceExpression struct {
|
||||
Sequence []Expression
|
||||
}
|
||||
|
||||
StringLiteral struct {
|
||||
Idx file.Idx
|
||||
Literal string
|
||||
Value unistring.String
|
||||
}
|
||||
|
||||
TemplateElement struct {
|
||||
Idx file.Idx
|
||||
Literal string
|
||||
Parsed unistring.String
|
||||
Valid bool
|
||||
}
|
||||
|
||||
TemplateLiteral struct {
|
||||
OpenQuote file.Idx
|
||||
CloseQuote file.Idx
|
||||
Tag Expression
|
||||
Elements []*TemplateElement
|
||||
Expressions []Expression
|
||||
}
|
||||
|
||||
ThisExpression struct {
|
||||
Idx file.Idx
|
||||
}
|
||||
|
||||
SuperExpression struct {
|
||||
Idx file.Idx
|
||||
}
|
||||
|
||||
UnaryExpression struct {
|
||||
Operator token.Token
|
||||
Idx file.Idx // If a prefix operation
|
||||
Operand Expression
|
||||
Postfix bool
|
||||
}
|
||||
|
||||
MetaProperty struct {
|
||||
Meta, Property *Identifier
|
||||
Idx file.Idx
|
||||
}
|
||||
)
|
||||
|
||||
// _expressionNode
|
||||
|
||||
func (*ArrayLiteral) _expressionNode() {}
|
||||
func (*AssignExpression) _expressionNode() {}
|
||||
func (*YieldExpression) _expressionNode() {}
|
||||
func (*AwaitExpression) _expressionNode() {}
|
||||
func (*BadExpression) _expressionNode() {}
|
||||
func (*BinaryExpression) _expressionNode() {}
|
||||
func (*BooleanLiteral) _expressionNode() {}
|
||||
func (*BracketExpression) _expressionNode() {}
|
||||
func (*CallExpression) _expressionNode() {}
|
||||
func (*ConditionalExpression) _expressionNode() {}
|
||||
func (*DotExpression) _expressionNode() {}
|
||||
func (*PrivateDotExpression) _expressionNode() {}
|
||||
func (*FunctionLiteral) _expressionNode() {}
|
||||
func (*ClassLiteral) _expressionNode() {}
|
||||
func (*ArrowFunctionLiteral) _expressionNode() {}
|
||||
func (*Identifier) _expressionNode() {}
|
||||
func (*NewExpression) _expressionNode() {}
|
||||
func (*NullLiteral) _expressionNode() {}
|
||||
func (*NumberLiteral) _expressionNode() {}
|
||||
func (*ObjectLiteral) _expressionNode() {}
|
||||
func (*RegExpLiteral) _expressionNode() {}
|
||||
func (*SequenceExpression) _expressionNode() {}
|
||||
func (*StringLiteral) _expressionNode() {}
|
||||
func (*TemplateLiteral) _expressionNode() {}
|
||||
func (*ThisExpression) _expressionNode() {}
|
||||
func (*SuperExpression) _expressionNode() {}
|
||||
func (*UnaryExpression) _expressionNode() {}
|
||||
func (*MetaProperty) _expressionNode() {}
|
||||
func (*ObjectPattern) _expressionNode() {}
|
||||
func (*ArrayPattern) _expressionNode() {}
|
||||
func (*Binding) _expressionNode() {}
|
||||
|
||||
func (*PropertyShort) _expressionNode() {}
|
||||
func (*PropertyKeyed) _expressionNode() {}
|
||||
|
||||
// ========= //
|
||||
// Statement //
|
||||
// ========= //
|
||||
|
||||
type (
|
||||
// All statement nodes implement the Statement interface.
|
||||
Statement interface {
|
||||
Node
|
||||
_statementNode()
|
||||
}
|
||||
|
||||
BadStatement struct {
|
||||
From file.Idx
|
||||
To file.Idx
|
||||
}
|
||||
|
||||
BlockStatement struct {
|
||||
LeftBrace file.Idx
|
||||
List []Statement
|
||||
RightBrace file.Idx
|
||||
}
|
||||
|
||||
BranchStatement struct {
|
||||
Idx file.Idx
|
||||
Token token.Token
|
||||
Label *Identifier
|
||||
}
|
||||
|
||||
CaseStatement struct {
|
||||
Case file.Idx
|
||||
Test Expression
|
||||
Consequent []Statement
|
||||
}
|
||||
|
||||
CatchStatement struct {
|
||||
Catch file.Idx
|
||||
Parameter BindingTarget
|
||||
Body *BlockStatement
|
||||
}
|
||||
|
||||
DebuggerStatement struct {
|
||||
Debugger file.Idx
|
||||
}
|
||||
|
||||
DoWhileStatement struct {
|
||||
Do file.Idx
|
||||
Test Expression
|
||||
Body Statement
|
||||
}
|
||||
|
||||
EmptyStatement struct {
|
||||
Semicolon file.Idx
|
||||
}
|
||||
|
||||
ExpressionStatement struct {
|
||||
Expression Expression
|
||||
}
|
||||
|
||||
ForInStatement struct {
|
||||
For file.Idx
|
||||
Into ForInto
|
||||
Source Expression
|
||||
Body Statement
|
||||
}
|
||||
|
||||
ForOfStatement struct {
|
||||
For file.Idx
|
||||
Into ForInto
|
||||
Source Expression
|
||||
Body Statement
|
||||
}
|
||||
|
||||
ForStatement struct {
|
||||
For file.Idx
|
||||
Initializer ForLoopInitializer
|
||||
Update Expression
|
||||
Test Expression
|
||||
Body Statement
|
||||
}
|
||||
|
||||
IfStatement struct {
|
||||
If file.Idx
|
||||
Test Expression
|
||||
Consequent Statement
|
||||
Alternate Statement
|
||||
}
|
||||
|
||||
LabelledStatement struct {
|
||||
Label *Identifier
|
||||
Colon file.Idx
|
||||
Statement Statement
|
||||
}
|
||||
|
||||
ReturnStatement struct {
|
||||
Return file.Idx
|
||||
Argument Expression
|
||||
}
|
||||
|
||||
SwitchStatement struct {
|
||||
Switch file.Idx
|
||||
Discriminant Expression
|
||||
Default int
|
||||
Body []*CaseStatement
|
||||
}
|
||||
|
||||
ThrowStatement struct {
|
||||
Throw file.Idx
|
||||
Argument Expression
|
||||
}
|
||||
|
||||
TryStatement struct {
|
||||
Try file.Idx
|
||||
Body *BlockStatement
|
||||
Catch *CatchStatement
|
||||
Finally *BlockStatement
|
||||
}
|
||||
|
||||
VariableStatement struct {
|
||||
Var file.Idx
|
||||
List []*Binding
|
||||
}
|
||||
|
||||
LexicalDeclaration struct {
|
||||
Idx file.Idx
|
||||
Token token.Token
|
||||
List []*Binding
|
||||
}
|
||||
|
||||
WhileStatement struct {
|
||||
While file.Idx
|
||||
Test Expression
|
||||
Body Statement
|
||||
}
|
||||
|
||||
WithStatement struct {
|
||||
With file.Idx
|
||||
Object Expression
|
||||
Body Statement
|
||||
}
|
||||
|
||||
FunctionDeclaration struct {
|
||||
Function *FunctionLiteral
|
||||
}
|
||||
|
||||
ClassDeclaration struct {
|
||||
Class *ClassLiteral
|
||||
}
|
||||
)
|
||||
|
||||
// _statementNode
|
||||
|
||||
func (*BadStatement) _statementNode() {}
|
||||
func (*BlockStatement) _statementNode() {}
|
||||
func (*BranchStatement) _statementNode() {}
|
||||
func (*CaseStatement) _statementNode() {}
|
||||
func (*CatchStatement) _statementNode() {}
|
||||
func (*DebuggerStatement) _statementNode() {}
|
||||
func (*DoWhileStatement) _statementNode() {}
|
||||
func (*EmptyStatement) _statementNode() {}
|
||||
func (*ExpressionStatement) _statementNode() {}
|
||||
func (*ForInStatement) _statementNode() {}
|
||||
func (*ForOfStatement) _statementNode() {}
|
||||
func (*ForStatement) _statementNode() {}
|
||||
func (*IfStatement) _statementNode() {}
|
||||
func (*LabelledStatement) _statementNode() {}
|
||||
func (*ReturnStatement) _statementNode() {}
|
||||
func (*SwitchStatement) _statementNode() {}
|
||||
func (*ThrowStatement) _statementNode() {}
|
||||
func (*TryStatement) _statementNode() {}
|
||||
func (*VariableStatement) _statementNode() {}
|
||||
func (*WhileStatement) _statementNode() {}
|
||||
func (*WithStatement) _statementNode() {}
|
||||
func (*LexicalDeclaration) _statementNode() {}
|
||||
func (*FunctionDeclaration) _statementNode() {}
|
||||
func (*ClassDeclaration) _statementNode() {}
|
||||
|
||||
// =========== //
|
||||
// Declaration //
|
||||
// =========== //
|
||||
|
||||
type (
|
||||
VariableDeclaration struct {
|
||||
Var file.Idx
|
||||
List []*Binding
|
||||
}
|
||||
|
||||
ClassElement interface {
|
||||
Node
|
||||
_classElement()
|
||||
}
|
||||
|
||||
FieldDefinition struct {
|
||||
Idx file.Idx
|
||||
Key Expression
|
||||
Initializer Expression
|
||||
Computed bool
|
||||
Static bool
|
||||
}
|
||||
|
||||
MethodDefinition struct {
|
||||
Idx file.Idx
|
||||
Key Expression
|
||||
Kind PropertyKind // "method", "get" or "set"
|
||||
Body *FunctionLiteral
|
||||
Computed bool
|
||||
Static bool
|
||||
}
|
||||
|
||||
ClassStaticBlock struct {
|
||||
Static file.Idx
|
||||
Block *BlockStatement
|
||||
Source string
|
||||
DeclarationList []*VariableDeclaration
|
||||
}
|
||||
)
|
||||
|
||||
type (
|
||||
ForLoopInitializer interface {
|
||||
Node
|
||||
_forLoopInitializer()
|
||||
}
|
||||
|
||||
ForLoopInitializerExpression struct {
|
||||
Expression Expression
|
||||
}
|
||||
|
||||
ForLoopInitializerVarDeclList struct {
|
||||
Var file.Idx
|
||||
List []*Binding
|
||||
}
|
||||
|
||||
ForLoopInitializerLexicalDecl struct {
|
||||
LexicalDeclaration LexicalDeclaration
|
||||
}
|
||||
|
||||
ForInto interface {
|
||||
Node
|
||||
_forInto()
|
||||
}
|
||||
|
||||
ForIntoVar struct {
|
||||
Binding *Binding
|
||||
}
|
||||
|
||||
ForDeclaration struct {
|
||||
Idx file.Idx
|
||||
IsConst bool
|
||||
Target BindingTarget
|
||||
}
|
||||
|
||||
ForIntoExpression struct {
|
||||
Expression Expression
|
||||
}
|
||||
)
|
||||
|
||||
func (*ForLoopInitializerExpression) _forLoopInitializer() {}
|
||||
func (*ForLoopInitializerVarDeclList) _forLoopInitializer() {}
|
||||
func (*ForLoopInitializerLexicalDecl) _forLoopInitializer() {}
|
||||
|
||||
func (*ForIntoVar) _forInto() {}
|
||||
func (*ForDeclaration) _forInto() {}
|
||||
func (*ForIntoExpression) _forInto() {}
|
||||
|
||||
func (*ArrayPattern) _pattern() {}
|
||||
func (*ArrayPattern) _bindingTarget() {}
|
||||
|
||||
func (*ObjectPattern) _pattern() {}
|
||||
func (*ObjectPattern) _bindingTarget() {}
|
||||
|
||||
func (*BadExpression) _bindingTarget() {}
|
||||
|
||||
func (*PropertyShort) _property() {}
|
||||
func (*PropertyKeyed) _property() {}
|
||||
func (*SpreadElement) _property() {}
|
||||
|
||||
func (*Identifier) _bindingTarget() {}
|
||||
|
||||
func (*BlockStatement) _conciseBody() {}
|
||||
func (*ExpressionBody) _conciseBody() {}
|
||||
|
||||
func (*FieldDefinition) _classElement() {}
|
||||
func (*MethodDefinition) _classElement() {}
|
||||
func (*ClassStaticBlock) _classElement() {}
|
||||
|
||||
// ==== //
|
||||
// Node //
|
||||
// ==== //
|
||||
|
||||
type Program struct {
|
||||
Body []Statement
|
||||
|
||||
DeclarationList []*VariableDeclaration
|
||||
|
||||
File *file.File
|
||||
}
|
||||
|
||||
// ==== //
|
||||
// Idx0 //
|
||||
// ==== //
|
||||
|
||||
func (self *ArrayLiteral) Idx0() file.Idx { return self.LeftBracket }
|
||||
func (self *ArrayPattern) Idx0() file.Idx { return self.LeftBracket }
|
||||
func (self *YieldExpression) Idx0() file.Idx { return self.Yield }
|
||||
func (self *AwaitExpression) Idx0() file.Idx { return self.Await }
|
||||
func (self *ObjectPattern) Idx0() file.Idx { return self.LeftBrace }
|
||||
func (self *ParameterList) Idx0() file.Idx { return self.Opening }
|
||||
func (self *AssignExpression) Idx0() file.Idx { return self.Left.Idx0() }
|
||||
func (self *BadExpression) Idx0() file.Idx { return self.From }
|
||||
func (self *BinaryExpression) Idx0() file.Idx { return self.Left.Idx0() }
|
||||
func (self *BooleanLiteral) Idx0() file.Idx { return self.Idx }
|
||||
func (self *BracketExpression) Idx0() file.Idx { return self.Left.Idx0() }
|
||||
func (self *CallExpression) Idx0() file.Idx { return self.Callee.Idx0() }
|
||||
func (self *ConditionalExpression) Idx0() file.Idx { return self.Test.Idx0() }
|
||||
func (self *DotExpression) Idx0() file.Idx { return self.Left.Idx0() }
|
||||
func (self *PrivateDotExpression) Idx0() file.Idx { return self.Left.Idx0() }
|
||||
func (self *FunctionLiteral) Idx0() file.Idx { return self.Function }
|
||||
func (self *ClassLiteral) Idx0() file.Idx { return self.Class }
|
||||
func (self *ArrowFunctionLiteral) Idx0() file.Idx { return self.Start }
|
||||
func (self *Identifier) Idx0() file.Idx { return self.Idx }
|
||||
func (self *NewExpression) Idx0() file.Idx { return self.New }
|
||||
func (self *NullLiteral) Idx0() file.Idx { return self.Idx }
|
||||
func (self *NumberLiteral) Idx0() file.Idx { return self.Idx }
|
||||
func (self *ObjectLiteral) Idx0() file.Idx { return self.LeftBrace }
|
||||
func (self *RegExpLiteral) Idx0() file.Idx { return self.Idx }
|
||||
func (self *SequenceExpression) Idx0() file.Idx { return self.Sequence[0].Idx0() }
|
||||
func (self *StringLiteral) Idx0() file.Idx { return self.Idx }
|
||||
func (self *TemplateElement) Idx0() file.Idx { return self.Idx }
|
||||
func (self *TemplateLiteral) Idx0() file.Idx { return self.OpenQuote }
|
||||
func (self *ThisExpression) Idx0() file.Idx { return self.Idx }
|
||||
func (self *SuperExpression) Idx0() file.Idx { return self.Idx }
|
||||
func (self *UnaryExpression) Idx0() file.Idx { return self.Idx }
|
||||
func (self *MetaProperty) Idx0() file.Idx { return self.Idx }
|
||||
|
||||
func (self *BadStatement) Idx0() file.Idx { return self.From }
|
||||
func (self *BlockStatement) Idx0() file.Idx { return self.LeftBrace }
|
||||
func (self *BranchStatement) Idx0() file.Idx { return self.Idx }
|
||||
func (self *CaseStatement) Idx0() file.Idx { return self.Case }
|
||||
func (self *CatchStatement) Idx0() file.Idx { return self.Catch }
|
||||
func (self *DebuggerStatement) Idx0() file.Idx { return self.Debugger }
|
||||
func (self *DoWhileStatement) Idx0() file.Idx { return self.Do }
|
||||
func (self *EmptyStatement) Idx0() file.Idx { return self.Semicolon }
|
||||
func (self *ExpressionStatement) Idx0() file.Idx { return self.Expression.Idx0() }
|
||||
func (self *ForInStatement) Idx0() file.Idx { return self.For }
|
||||
func (self *ForOfStatement) Idx0() file.Idx { return self.For }
|
||||
func (self *ForStatement) Idx0() file.Idx { return self.For }
|
||||
func (self *IfStatement) Idx0() file.Idx { return self.If }
|
||||
func (self *LabelledStatement) Idx0() file.Idx { return self.Label.Idx0() }
|
||||
func (self *Program) Idx0() file.Idx { return self.Body[0].Idx0() }
|
||||
func (self *ReturnStatement) Idx0() file.Idx { return self.Return }
|
||||
func (self *SwitchStatement) Idx0() file.Idx { return self.Switch }
|
||||
func (self *ThrowStatement) Idx0() file.Idx { return self.Throw }
|
||||
func (self *TryStatement) Idx0() file.Idx { return self.Try }
|
||||
func (self *VariableStatement) Idx0() file.Idx { return self.Var }
|
||||
func (self *WhileStatement) Idx0() file.Idx { return self.While }
|
||||
func (self *WithStatement) Idx0() file.Idx { return self.With }
|
||||
func (self *LexicalDeclaration) Idx0() file.Idx { return self.Idx }
|
||||
func (self *FunctionDeclaration) Idx0() file.Idx { return self.Function.Idx0() }
|
||||
func (self *ClassDeclaration) Idx0() file.Idx { return self.Class.Idx0() }
|
||||
func (self *Binding) Idx0() file.Idx { return self.Target.Idx0() }
|
||||
|
||||
func (self *ForLoopInitializerExpression) Idx0() file.Idx { return self.Expression.Idx0() }
|
||||
func (self *ForLoopInitializerVarDeclList) Idx0() file.Idx { return self.List[0].Idx0() }
|
||||
func (self *ForLoopInitializerLexicalDecl) Idx0() file.Idx { return self.LexicalDeclaration.Idx0() }
|
||||
func (self *PropertyShort) Idx0() file.Idx { return self.Name.Idx }
|
||||
func (self *PropertyKeyed) Idx0() file.Idx { return self.Key.Idx0() }
|
||||
func (self *ExpressionBody) Idx0() file.Idx { return self.Expression.Idx0() }
|
||||
|
||||
func (self *VariableDeclaration) Idx0() file.Idx { return self.Var }
|
||||
func (self *FieldDefinition) Idx0() file.Idx { return self.Idx }
|
||||
func (self *MethodDefinition) Idx0() file.Idx { return self.Idx }
|
||||
func (self *ClassStaticBlock) Idx0() file.Idx { return self.Static }
|
||||
|
||||
func (self *ForDeclaration) Idx0() file.Idx { return self.Idx }
|
||||
func (self *ForIntoVar) Idx0() file.Idx { return self.Binding.Idx0() }
|
||||
func (self *ForIntoExpression) Idx0() file.Idx { return self.Expression.Idx0() }
|
||||
|
||||
// ==== //
|
||||
// Idx1 //
|
||||
// ==== //
|
||||
|
||||
func (self *ArrayLiteral) Idx1() file.Idx { return self.RightBracket + 1 }
|
||||
func (self *ArrayPattern) Idx1() file.Idx { return self.RightBracket + 1 }
|
||||
func (self *AssignExpression) Idx1() file.Idx { return self.Right.Idx1() }
|
||||
func (self *AwaitExpression) Idx1() file.Idx { return self.Argument.Idx1() }
|
||||
func (self *BadExpression) Idx1() file.Idx { return self.To }
|
||||
func (self *BinaryExpression) Idx1() file.Idx { return self.Right.Idx1() }
|
||||
func (self *BooleanLiteral) Idx1() file.Idx { return file.Idx(int(self.Idx) + len(self.Literal)) }
|
||||
func (self *BracketExpression) Idx1() file.Idx { return self.RightBracket + 1 }
|
||||
func (self *CallExpression) Idx1() file.Idx { return self.RightParenthesis + 1 }
|
||||
func (self *ConditionalExpression) Idx1() file.Idx { return self.Test.Idx1() }
|
||||
func (self *DotExpression) Idx1() file.Idx { return self.Identifier.Idx1() }
|
||||
func (self *PrivateDotExpression) Idx1() file.Idx { return self.Identifier.Idx1() }
|
||||
func (self *FunctionLiteral) Idx1() file.Idx { return self.Body.Idx1() }
|
||||
func (self *ClassLiteral) Idx1() file.Idx { return self.RightBrace + 1 }
|
||||
func (self *ArrowFunctionLiteral) Idx1() file.Idx { return self.Body.Idx1() }
|
||||
func (self *Identifier) Idx1() file.Idx { return file.Idx(int(self.Idx) + len(self.Name)) }
|
||||
func (self *NewExpression) Idx1() file.Idx {
|
||||
if self.ArgumentList != nil {
|
||||
return self.RightParenthesis + 1
|
||||
} else {
|
||||
return self.Callee.Idx1()
|
||||
}
|
||||
}
|
||||
func (self *NullLiteral) Idx1() file.Idx { return file.Idx(int(self.Idx) + 4) } // "null"
|
||||
func (self *NumberLiteral) Idx1() file.Idx { return file.Idx(int(self.Idx) + len(self.Literal)) }
|
||||
func (self *ObjectLiteral) Idx1() file.Idx { return self.RightBrace + 1 }
|
||||
func (self *ObjectPattern) Idx1() file.Idx { return self.RightBrace + 1 }
|
||||
func (self *ParameterList) Idx1() file.Idx { return self.Closing + 1 }
|
||||
func (self *RegExpLiteral) Idx1() file.Idx { return file.Idx(int(self.Idx) + len(self.Literal)) }
|
||||
func (self *SequenceExpression) Idx1() file.Idx { return self.Sequence[len(self.Sequence)-1].Idx1() }
|
||||
func (self *StringLiteral) Idx1() file.Idx { return file.Idx(int(self.Idx) + len(self.Literal)) }
|
||||
func (self *TemplateElement) Idx1() file.Idx { return file.Idx(int(self.Idx) + len(self.Literal)) }
|
||||
func (self *TemplateLiteral) Idx1() file.Idx { return self.CloseQuote + 1 }
|
||||
func (self *ThisExpression) Idx1() file.Idx { return self.Idx + 4 }
|
||||
func (self *SuperExpression) Idx1() file.Idx { return self.Idx + 5 }
|
||||
func (self *UnaryExpression) Idx1() file.Idx {
|
||||
if self.Postfix {
|
||||
return self.Operand.Idx1() + 2 // ++ --
|
||||
}
|
||||
return self.Operand.Idx1()
|
||||
}
|
||||
func (self *MetaProperty) Idx1() file.Idx {
|
||||
return self.Property.Idx1()
|
||||
}
|
||||
|
||||
func (self *BadStatement) Idx1() file.Idx { return self.To }
|
||||
func (self *BlockStatement) Idx1() file.Idx { return self.RightBrace + 1 }
|
||||
func (self *BranchStatement) Idx1() file.Idx { return self.Idx }
|
||||
func (self *CaseStatement) Idx1() file.Idx { return self.Consequent[len(self.Consequent)-1].Idx1() }
|
||||
func (self *CatchStatement) Idx1() file.Idx { return self.Body.Idx1() }
|
||||
func (self *DebuggerStatement) Idx1() file.Idx { return self.Debugger + 8 }
|
||||
func (self *DoWhileStatement) Idx1() file.Idx { return self.Test.Idx1() }
|
||||
func (self *EmptyStatement) Idx1() file.Idx { return self.Semicolon + 1 }
|
||||
func (self *ExpressionStatement) Idx1() file.Idx { return self.Expression.Idx1() }
|
||||
func (self *ForInStatement) Idx1() file.Idx { return self.Body.Idx1() }
|
||||
func (self *ForOfStatement) Idx1() file.Idx { return self.Body.Idx1() }
|
||||
func (self *ForStatement) Idx1() file.Idx { return self.Body.Idx1() }
|
||||
func (self *IfStatement) Idx1() file.Idx {
|
||||
if self.Alternate != nil {
|
||||
return self.Alternate.Idx1()
|
||||
}
|
||||
return self.Consequent.Idx1()
|
||||
}
|
||||
func (self *LabelledStatement) Idx1() file.Idx { return self.Colon + 1 }
|
||||
func (self *Program) Idx1() file.Idx { return self.Body[len(self.Body)-1].Idx1() }
|
||||
func (self *ReturnStatement) Idx1() file.Idx { return self.Return + 6 }
|
||||
func (self *SwitchStatement) Idx1() file.Idx { return self.Body[len(self.Body)-1].Idx1() }
|
||||
func (self *ThrowStatement) Idx1() file.Idx { return self.Argument.Idx1() }
|
||||
func (self *TryStatement) Idx1() file.Idx {
|
||||
if self.Finally != nil {
|
||||
return self.Finally.Idx1()
|
||||
}
|
||||
if self.Catch != nil {
|
||||
return self.Catch.Idx1()
|
||||
}
|
||||
return self.Body.Idx1()
|
||||
}
|
||||
func (self *VariableStatement) Idx1() file.Idx { return self.List[len(self.List)-1].Idx1() }
|
||||
func (self *WhileStatement) Idx1() file.Idx { return self.Body.Idx1() }
|
||||
func (self *WithStatement) Idx1() file.Idx { return self.Body.Idx1() }
|
||||
func (self *LexicalDeclaration) Idx1() file.Idx { return self.List[len(self.List)-1].Idx1() }
|
||||
func (self *FunctionDeclaration) Idx1() file.Idx { return self.Function.Idx1() }
|
||||
func (self *ClassDeclaration) Idx1() file.Idx { return self.Class.Idx1() }
|
||||
func (self *Binding) Idx1() file.Idx {
|
||||
if self.Initializer != nil {
|
||||
return self.Initializer.Idx1()
|
||||
}
|
||||
return self.Target.Idx1()
|
||||
}
|
||||
|
||||
func (self *ForLoopInitializerExpression) Idx1() file.Idx { return self.Expression.Idx1() }
|
||||
func (self *ForLoopInitializerVarDeclList) Idx1() file.Idx { return self.List[len(self.List)-1].Idx1() }
|
||||
func (self *ForLoopInitializerLexicalDecl) Idx1() file.Idx { return self.LexicalDeclaration.Idx1() }
|
||||
|
||||
func (self *PropertyShort) Idx1() file.Idx {
|
||||
if self.Initializer != nil {
|
||||
return self.Initializer.Idx1()
|
||||
}
|
||||
return self.Name.Idx1()
|
||||
}
|
||||
|
||||
func (self *PropertyKeyed) Idx1() file.Idx { return self.Value.Idx1() }
|
||||
|
||||
func (self *ExpressionBody) Idx1() file.Idx { return self.Expression.Idx1() }
|
||||
|
||||
func (self *VariableDeclaration) Idx1() file.Idx {
|
||||
if len(self.List) > 0 {
|
||||
return self.List[len(self.List)-1].Idx1()
|
||||
}
|
||||
|
||||
return self.Var + 3
|
||||
}
|
||||
|
||||
func (self *FieldDefinition) Idx1() file.Idx {
|
||||
if self.Initializer != nil {
|
||||
return self.Initializer.Idx1()
|
||||
}
|
||||
return self.Key.Idx1()
|
||||
}
|
||||
|
||||
func (self *MethodDefinition) Idx1() file.Idx {
|
||||
return self.Body.Idx1()
|
||||
}
|
||||
|
||||
func (self *ClassStaticBlock) Idx1() file.Idx {
|
||||
return self.Block.Idx1()
|
||||
}
|
||||
|
||||
func (self *YieldExpression) Idx1() file.Idx {
|
||||
if self.Argument != nil {
|
||||
return self.Argument.Idx1()
|
||||
}
|
||||
return self.Yield + 5
|
||||
}
|
||||
|
||||
func (self *ForDeclaration) Idx1() file.Idx { return self.Target.Idx1() }
|
||||
func (self *ForIntoVar) Idx1() file.Idx { return self.Binding.Idx1() }
|
||||
func (self *ForIntoExpression) Idx1() file.Idx { return self.Expression.Idx1() }
|
||||
1567
server/vendor/github.com/dop251/goja/builtin_array.go
generated
vendored
Normal file
1567
server/vendor/github.com/dop251/goja/builtin_array.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
50
server/vendor/github.com/dop251/goja/builtin_boolean.go
generated
vendored
Normal file
50
server/vendor/github.com/dop251/goja/builtin_boolean.go
generated
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
package goja
|
||||
|
||||
func (r *Runtime) booleanproto_toString(call FunctionCall) Value {
|
||||
var b bool
|
||||
switch o := call.This.(type) {
|
||||
case valueBool:
|
||||
b = bool(o)
|
||||
goto success
|
||||
case *Object:
|
||||
if p, ok := o.self.(*primitiveValueObject); ok {
|
||||
if b1, ok := p.pValue.(valueBool); ok {
|
||||
b = bool(b1)
|
||||
goto success
|
||||
}
|
||||
}
|
||||
}
|
||||
r.typeErrorResult(true, "Method Boolean.prototype.toString is called on incompatible receiver")
|
||||
|
||||
success:
|
||||
if b {
|
||||
return stringTrue
|
||||
}
|
||||
return stringFalse
|
||||
}
|
||||
|
||||
func (r *Runtime) booleanproto_valueOf(call FunctionCall) Value {
|
||||
switch o := call.This.(type) {
|
||||
case valueBool:
|
||||
return o
|
||||
case *Object:
|
||||
if p, ok := o.self.(*primitiveValueObject); ok {
|
||||
if b, ok := p.pValue.(valueBool); ok {
|
||||
return b
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
r.typeErrorResult(true, "Method Boolean.prototype.valueOf is called on incompatible receiver")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Runtime) initBoolean() {
|
||||
r.global.BooleanPrototype = r.newPrimitiveObject(valueFalse, r.global.ObjectPrototype, classBoolean)
|
||||
o := r.global.BooleanPrototype.self
|
||||
o._putProp("toString", r.newNativeFunc(r.booleanproto_toString, nil, "toString", nil, 0), true, false, true)
|
||||
o._putProp("valueOf", r.newNativeFunc(r.booleanproto_valueOf, nil, "valueOf", nil, 0), true, false, true)
|
||||
|
||||
r.global.Boolean = r.newNativeFunc(r.builtin_Boolean, r.builtin_newBoolean, "Boolean", r.global.BooleanPrototype, 1)
|
||||
r.addToGlobal("Boolean", r.global.Boolean)
|
||||
}
|
||||
1015
server/vendor/github.com/dop251/goja/builtin_date.go
generated
vendored
Normal file
1015
server/vendor/github.com/dop251/goja/builtin_date.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
236
server/vendor/github.com/dop251/goja/builtin_error.go
generated
vendored
Normal file
236
server/vendor/github.com/dop251/goja/builtin_error.go
generated
vendored
Normal file
@@ -0,0 +1,236 @@
|
||||
package goja
|
||||
|
||||
import "github.com/dop251/goja/unistring"
|
||||
|
||||
const propNameStack = "stack"
|
||||
|
||||
type errorObject struct {
|
||||
baseObject
|
||||
stack []StackFrame
|
||||
stackPropAdded bool
|
||||
}
|
||||
|
||||
func (e *errorObject) formatStack() valueString {
|
||||
var b valueStringBuilder
|
||||
val := writeErrorString(&b, e.val)
|
||||
if val != nil {
|
||||
b.WriteString(val)
|
||||
}
|
||||
b.WriteRune('\n')
|
||||
|
||||
for _, frame := range e.stack {
|
||||
b.WriteASCII("\tat ")
|
||||
frame.WriteToValueBuilder(&b)
|
||||
b.WriteRune('\n')
|
||||
}
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func (e *errorObject) addStackProp() Value {
|
||||
if !e.stackPropAdded {
|
||||
res := e._putProp(propNameStack, e.formatStack(), true, false, true)
|
||||
if len(e.propNames) > 1 {
|
||||
// reorder property names to ensure 'stack' is the first one
|
||||
copy(e.propNames[1:], e.propNames)
|
||||
e.propNames[0] = propNameStack
|
||||
}
|
||||
e.stackPropAdded = true
|
||||
return res
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *errorObject) getStr(p unistring.String, receiver Value) Value {
|
||||
return e.getStrWithOwnProp(e.getOwnPropStr(p), p, receiver)
|
||||
}
|
||||
|
||||
func (e *errorObject) getOwnPropStr(name unistring.String) Value {
|
||||
res := e.baseObject.getOwnPropStr(name)
|
||||
if res == nil && name == propNameStack {
|
||||
return e.addStackProp()
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func (e *errorObject) setOwnStr(name unistring.String, val Value, throw bool) bool {
|
||||
if name == propNameStack {
|
||||
e.addStackProp()
|
||||
}
|
||||
return e.baseObject.setOwnStr(name, val, throw)
|
||||
}
|
||||
|
||||
func (e *errorObject) setForeignStr(name unistring.String, val, receiver Value, throw bool) (bool, bool) {
|
||||
return e._setForeignStr(name, e.getOwnPropStr(name), val, receiver, throw)
|
||||
}
|
||||
|
||||
func (e *errorObject) deleteStr(name unistring.String, throw bool) bool {
|
||||
if name == propNameStack {
|
||||
e.addStackProp()
|
||||
}
|
||||
return e.baseObject.deleteStr(name, throw)
|
||||
}
|
||||
|
||||
func (e *errorObject) defineOwnPropertyStr(name unistring.String, desc PropertyDescriptor, throw bool) bool {
|
||||
if name == propNameStack {
|
||||
e.addStackProp()
|
||||
}
|
||||
return e.baseObject.defineOwnPropertyStr(name, desc, throw)
|
||||
}
|
||||
|
||||
func (e *errorObject) hasOwnPropertyStr(name unistring.String) bool {
|
||||
if e.baseObject.hasOwnPropertyStr(name) {
|
||||
return true
|
||||
}
|
||||
|
||||
return name == propNameStack && !e.stackPropAdded
|
||||
}
|
||||
|
||||
func (e *errorObject) stringKeys(all bool, accum []Value) []Value {
|
||||
if all && !e.stackPropAdded {
|
||||
accum = append(accum, asciiString(propNameStack))
|
||||
}
|
||||
return e.baseObject.stringKeys(all, accum)
|
||||
}
|
||||
|
||||
func (e *errorObject) iterateStringKeys() iterNextFunc {
|
||||
e.addStackProp()
|
||||
return e.baseObject.iterateStringKeys()
|
||||
}
|
||||
|
||||
func (e *errorObject) init() {
|
||||
e.baseObject.init()
|
||||
vm := e.val.runtime.vm
|
||||
e.stack = vm.captureStack(make([]StackFrame, 0, len(vm.callStack)+1), 0)
|
||||
}
|
||||
|
||||
func (r *Runtime) newErrorObject(proto *Object, class string) *errorObject {
|
||||
obj := &Object{runtime: r}
|
||||
o := &errorObject{
|
||||
baseObject: baseObject{
|
||||
class: class,
|
||||
val: obj,
|
||||
extensible: true,
|
||||
prototype: proto,
|
||||
},
|
||||
}
|
||||
obj.self = o
|
||||
o.init()
|
||||
return o
|
||||
}
|
||||
|
||||
func (r *Runtime) builtin_Error(args []Value, proto *Object) *Object {
|
||||
obj := r.newErrorObject(proto, classError)
|
||||
if len(args) > 0 && args[0] != _undefined {
|
||||
obj._putProp("message", args[0], true, false, true)
|
||||
}
|
||||
return obj.val
|
||||
}
|
||||
|
||||
func (r *Runtime) builtin_AggregateError(args []Value, proto *Object) *Object {
|
||||
obj := r.newErrorObject(proto, classError)
|
||||
if len(args) > 1 && args[1] != nil && args[1] != _undefined {
|
||||
obj._putProp("message", args[1].toString(), true, false, true)
|
||||
}
|
||||
var errors []Value
|
||||
if len(args) > 0 {
|
||||
errors = r.iterableToList(args[0], nil)
|
||||
}
|
||||
obj._putProp("errors", r.newArrayValues(errors), true, false, true)
|
||||
|
||||
return obj.val
|
||||
}
|
||||
|
||||
func writeErrorString(sb *valueStringBuilder, obj *Object) valueString {
|
||||
var nameStr, msgStr valueString
|
||||
name := obj.self.getStr("name", nil)
|
||||
if name == nil || name == _undefined {
|
||||
nameStr = asciiString("Error")
|
||||
} else {
|
||||
nameStr = name.toString()
|
||||
}
|
||||
msg := obj.self.getStr("message", nil)
|
||||
if msg == nil || msg == _undefined {
|
||||
msgStr = stringEmpty
|
||||
} else {
|
||||
msgStr = msg.toString()
|
||||
}
|
||||
if nameStr.length() == 0 {
|
||||
return msgStr
|
||||
}
|
||||
if msgStr.length() == 0 {
|
||||
return nameStr
|
||||
}
|
||||
sb.WriteString(nameStr)
|
||||
sb.WriteString(asciiString(": "))
|
||||
sb.WriteString(msgStr)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Runtime) error_toString(call FunctionCall) Value {
|
||||
var sb valueStringBuilder
|
||||
val := writeErrorString(&sb, r.toObject(call.This))
|
||||
if val != nil {
|
||||
return val
|
||||
}
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
func (r *Runtime) createErrorPrototype(name valueString) *Object {
|
||||
o := r.newBaseObject(r.global.ErrorPrototype, classObject)
|
||||
o._putProp("message", stringEmpty, true, false, true)
|
||||
o._putProp("name", name, true, false, true)
|
||||
return o.val
|
||||
}
|
||||
|
||||
func (r *Runtime) initErrors() {
|
||||
r.global.ErrorPrototype = r.NewObject()
|
||||
o := r.global.ErrorPrototype.self
|
||||
o._putProp("message", stringEmpty, true, false, true)
|
||||
o._putProp("name", stringError, true, false, true)
|
||||
o._putProp("toString", r.newNativeFunc(r.error_toString, nil, "toString", nil, 0), true, false, true)
|
||||
|
||||
r.global.Error = r.newNativeFuncConstruct(r.builtin_Error, "Error", r.global.ErrorPrototype, 1)
|
||||
r.addToGlobal("Error", r.global.Error)
|
||||
|
||||
r.global.AggregateErrorPrototype = r.createErrorPrototype(stringAggregateError)
|
||||
r.global.AggregateError = r.newNativeFuncConstructProto(r.builtin_AggregateError, "AggregateError", r.global.AggregateErrorPrototype, r.global.Error, 2)
|
||||
r.addToGlobal("AggregateError", r.global.AggregateError)
|
||||
|
||||
r.global.TypeErrorPrototype = r.createErrorPrototype(stringTypeError)
|
||||
|
||||
r.global.TypeError = r.newNativeFuncConstructProto(r.builtin_Error, "TypeError", r.global.TypeErrorPrototype, r.global.Error, 1)
|
||||
r.addToGlobal("TypeError", r.global.TypeError)
|
||||
|
||||
r.global.ReferenceErrorPrototype = r.createErrorPrototype(stringReferenceError)
|
||||
|
||||
r.global.ReferenceError = r.newNativeFuncConstructProto(r.builtin_Error, "ReferenceError", r.global.ReferenceErrorPrototype, r.global.Error, 1)
|
||||
r.addToGlobal("ReferenceError", r.global.ReferenceError)
|
||||
|
||||
r.global.SyntaxErrorPrototype = r.createErrorPrototype(stringSyntaxError)
|
||||
|
||||
r.global.SyntaxError = r.newNativeFuncConstructProto(r.builtin_Error, "SyntaxError", r.global.SyntaxErrorPrototype, r.global.Error, 1)
|
||||
r.addToGlobal("SyntaxError", r.global.SyntaxError)
|
||||
|
||||
r.global.RangeErrorPrototype = r.createErrorPrototype(stringRangeError)
|
||||
|
||||
r.global.RangeError = r.newNativeFuncConstructProto(r.builtin_Error, "RangeError", r.global.RangeErrorPrototype, r.global.Error, 1)
|
||||
r.addToGlobal("RangeError", r.global.RangeError)
|
||||
|
||||
r.global.EvalErrorPrototype = r.createErrorPrototype(stringEvalError)
|
||||
o = r.global.EvalErrorPrototype.self
|
||||
o._putProp("name", stringEvalError, true, false, true)
|
||||
|
||||
r.global.EvalError = r.newNativeFuncConstructProto(r.builtin_Error, "EvalError", r.global.EvalErrorPrototype, r.global.Error, 1)
|
||||
r.addToGlobal("EvalError", r.global.EvalError)
|
||||
|
||||
r.global.URIErrorPrototype = r.createErrorPrototype(stringURIError)
|
||||
|
||||
r.global.URIError = r.newNativeFuncConstructProto(r.builtin_Error, "URIError", r.global.URIErrorPrototype, r.global.Error, 1)
|
||||
r.addToGlobal("URIError", r.global.URIError)
|
||||
|
||||
r.global.GoErrorPrototype = r.createErrorPrototype(stringGoError)
|
||||
|
||||
r.global.GoError = r.newNativeFuncConstructProto(r.builtin_Error, "GoError", r.global.GoErrorPrototype, r.global.Error, 1)
|
||||
r.addToGlobal("GoError", r.global.GoError)
|
||||
}
|
||||
350
server/vendor/github.com/dop251/goja/builtin_function.go
generated
vendored
Normal file
350
server/vendor/github.com/dop251/goja/builtin_function.go
generated
vendored
Normal file
@@ -0,0 +1,350 @@
|
||||
package goja
|
||||
|
||||
import (
|
||||
"math"
|
||||
)
|
||||
|
||||
func (r *Runtime) functionCtor(args []Value, proto *Object, async, generator bool) *Object {
|
||||
var sb valueStringBuilder
|
||||
if async {
|
||||
if generator {
|
||||
sb.WriteString(asciiString("(async function* anonymous("))
|
||||
} else {
|
||||
sb.WriteString(asciiString("(async function anonymous("))
|
||||
}
|
||||
} else {
|
||||
if generator {
|
||||
sb.WriteString(asciiString("(function* anonymous("))
|
||||
} else {
|
||||
sb.WriteString(asciiString("(function anonymous("))
|
||||
}
|
||||
}
|
||||
if len(args) > 1 {
|
||||
ar := args[:len(args)-1]
|
||||
for i, arg := range ar {
|
||||
sb.WriteString(arg.toString())
|
||||
if i < len(ar)-1 {
|
||||
sb.WriteRune(',')
|
||||
}
|
||||
}
|
||||
}
|
||||
sb.WriteString(asciiString("\n) {\n"))
|
||||
if len(args) > 0 {
|
||||
sb.WriteString(args[len(args)-1].toString())
|
||||
}
|
||||
sb.WriteString(asciiString("\n})"))
|
||||
|
||||
ret := r.toObject(r.eval(sb.String(), false, false))
|
||||
ret.self.setProto(proto, true)
|
||||
return ret
|
||||
}
|
||||
|
||||
func (r *Runtime) builtin_Function(args []Value, proto *Object) *Object {
|
||||
return r.functionCtor(args, proto, false, false)
|
||||
}
|
||||
|
||||
func (r *Runtime) builtin_asyncFunction(args []Value, proto *Object) *Object {
|
||||
return r.functionCtor(args, proto, true, false)
|
||||
}
|
||||
|
||||
func (r *Runtime) builtin_generatorFunction(args []Value, proto *Object) *Object {
|
||||
return r.functionCtor(args, proto, false, true)
|
||||
}
|
||||
|
||||
func (r *Runtime) functionproto_toString(call FunctionCall) Value {
|
||||
obj := r.toObject(call.This)
|
||||
if lazy, ok := obj.self.(*lazyObject); ok {
|
||||
obj.self = lazy.create(obj)
|
||||
}
|
||||
switch f := obj.self.(type) {
|
||||
case funcObjectImpl:
|
||||
return f.source()
|
||||
case *proxyObject:
|
||||
if lazy, ok := f.target.self.(*lazyObject); ok {
|
||||
f.target.self = lazy.create(f.target)
|
||||
}
|
||||
if _, ok := f.target.self.(funcObjectImpl); ok {
|
||||
return asciiString("function () { [native code] }")
|
||||
}
|
||||
}
|
||||
panic(r.NewTypeError("Function.prototype.toString requires that 'this' be a Function"))
|
||||
}
|
||||
|
||||
func (r *Runtime) functionproto_hasInstance(call FunctionCall) Value {
|
||||
if o, ok := call.This.(*Object); ok {
|
||||
if _, ok = o.self.assertCallable(); ok {
|
||||
return r.toBoolean(o.self.hasInstance(call.Argument(0)))
|
||||
}
|
||||
}
|
||||
|
||||
return valueFalse
|
||||
}
|
||||
|
||||
func (r *Runtime) createListFromArrayLike(a Value) []Value {
|
||||
o := r.toObject(a)
|
||||
if arr := r.checkStdArrayObj(o); arr != nil {
|
||||
return arr.values
|
||||
}
|
||||
l := toLength(o.self.getStr("length", nil))
|
||||
res := make([]Value, 0, l)
|
||||
for k := int64(0); k < l; k++ {
|
||||
res = append(res, nilSafe(o.self.getIdx(valueInt(k), nil)))
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (r *Runtime) functionproto_apply(call FunctionCall) Value {
|
||||
var args []Value
|
||||
if len(call.Arguments) >= 2 {
|
||||
args = r.createListFromArrayLike(call.Arguments[1])
|
||||
}
|
||||
|
||||
f := r.toCallable(call.This)
|
||||
return f(FunctionCall{
|
||||
This: call.Argument(0),
|
||||
Arguments: args,
|
||||
})
|
||||
}
|
||||
|
||||
func (r *Runtime) functionproto_call(call FunctionCall) Value {
|
||||
var args []Value
|
||||
if len(call.Arguments) > 0 {
|
||||
args = call.Arguments[1:]
|
||||
}
|
||||
|
||||
f := r.toCallable(call.This)
|
||||
return f(FunctionCall{
|
||||
This: call.Argument(0),
|
||||
Arguments: args,
|
||||
})
|
||||
}
|
||||
|
||||
func (r *Runtime) boundCallable(target func(FunctionCall) Value, boundArgs []Value) func(FunctionCall) Value {
|
||||
var this Value
|
||||
var args []Value
|
||||
if len(boundArgs) > 0 {
|
||||
this = boundArgs[0]
|
||||
args = make([]Value, len(boundArgs)-1)
|
||||
copy(args, boundArgs[1:])
|
||||
} else {
|
||||
this = _undefined
|
||||
}
|
||||
return func(call FunctionCall) Value {
|
||||
a := append(args, call.Arguments...)
|
||||
return target(FunctionCall{
|
||||
This: this,
|
||||
Arguments: a,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Runtime) boundConstruct(f *Object, target func([]Value, *Object) *Object, boundArgs []Value) func([]Value, *Object) *Object {
|
||||
if target == nil {
|
||||
return nil
|
||||
}
|
||||
var args []Value
|
||||
if len(boundArgs) > 1 {
|
||||
args = make([]Value, len(boundArgs)-1)
|
||||
copy(args, boundArgs[1:])
|
||||
}
|
||||
return func(fargs []Value, newTarget *Object) *Object {
|
||||
a := append(args, fargs...)
|
||||
if newTarget == f {
|
||||
newTarget = nil
|
||||
}
|
||||
return target(a, newTarget)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Runtime) functionproto_bind(call FunctionCall) Value {
|
||||
obj := r.toObject(call.This)
|
||||
|
||||
fcall := r.toCallable(call.This)
|
||||
construct := obj.self.assertConstructor()
|
||||
|
||||
var l = _positiveZero
|
||||
if obj.self.hasOwnPropertyStr("length") {
|
||||
var li int64
|
||||
switch lenProp := nilSafe(obj.self.getStr("length", nil)).(type) {
|
||||
case valueInt:
|
||||
li = lenProp.ToInteger()
|
||||
case valueFloat:
|
||||
switch lenProp {
|
||||
case _positiveInf:
|
||||
l = lenProp
|
||||
goto lenNotInt
|
||||
case _negativeInf:
|
||||
goto lenNotInt
|
||||
case _negativeZero:
|
||||
// no-op, li == 0
|
||||
default:
|
||||
if !math.IsNaN(float64(lenProp)) {
|
||||
li = int64(math.Abs(float64(lenProp)))
|
||||
} // else li = 0
|
||||
}
|
||||
}
|
||||
if len(call.Arguments) > 1 {
|
||||
li -= int64(len(call.Arguments)) - 1
|
||||
}
|
||||
if li < 0 {
|
||||
li = 0
|
||||
}
|
||||
l = intToValue(li)
|
||||
}
|
||||
lenNotInt:
|
||||
name := obj.self.getStr("name", nil)
|
||||
nameStr := stringBound_
|
||||
if s, ok := name.(valueString); ok {
|
||||
nameStr = nameStr.concat(s)
|
||||
}
|
||||
|
||||
v := &Object{runtime: r}
|
||||
ff := r.newNativeFuncAndConstruct(v, r.boundCallable(fcall, call.Arguments), r.boundConstruct(v, construct, call.Arguments), nil, nameStr.string(), l)
|
||||
bf := &boundFuncObject{
|
||||
nativeFuncObject: *ff,
|
||||
wrapped: obj,
|
||||
}
|
||||
bf.prototype = obj.self.proto()
|
||||
v.self = bf
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
func (r *Runtime) initFunction() {
|
||||
o := r.global.FunctionPrototype.self.(*nativeFuncObject)
|
||||
o.prototype = r.global.ObjectPrototype
|
||||
o._putProp("name", stringEmpty, false, false, true)
|
||||
o._putProp("apply", r.newNativeFunc(r.functionproto_apply, nil, "apply", nil, 2), true, false, true)
|
||||
o._putProp("bind", r.newNativeFunc(r.functionproto_bind, nil, "bind", nil, 1), true, false, true)
|
||||
o._putProp("call", r.newNativeFunc(r.functionproto_call, nil, "call", nil, 1), true, false, true)
|
||||
o._putProp("toString", r.newNativeFunc(r.functionproto_toString, nil, "toString", nil, 0), true, false, true)
|
||||
o._putSym(SymHasInstance, valueProp(r.newNativeFunc(r.functionproto_hasInstance, nil, "[Symbol.hasInstance]", nil, 1), false, false, false))
|
||||
|
||||
r.global.Function = r.newNativeFuncConstruct(r.builtin_Function, "Function", r.global.FunctionPrototype, 1)
|
||||
r.addToGlobal("Function", r.global.Function)
|
||||
}
|
||||
|
||||
func (r *Runtime) createAsyncFunctionProto(val *Object) objectImpl {
|
||||
o := &baseObject{
|
||||
class: classObject,
|
||||
val: val,
|
||||
extensible: true,
|
||||
prototype: r.global.FunctionPrototype,
|
||||
}
|
||||
o.init()
|
||||
|
||||
o._putProp("constructor", r.getAsyncFunction(), true, false, true)
|
||||
|
||||
o._putSym(SymToStringTag, valueProp(asciiString(classAsyncFunction), false, false, true))
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
func (r *Runtime) getAsyncFunctionPrototype() *Object {
|
||||
var o *Object
|
||||
if o = r.global.AsyncFunctionPrototype; o == nil {
|
||||
o = r.newLazyObject(r.createAsyncFunctionProto)
|
||||
r.global.AsyncFunctionPrototype = o
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
func (r *Runtime) createAsyncFunction(val *Object) objectImpl {
|
||||
o := r.newNativeFuncConstructObj(val, r.builtin_asyncFunction, "AsyncFunction", r.getAsyncFunctionPrototype(), 1)
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
func (r *Runtime) getAsyncFunction() *Object {
|
||||
var o *Object
|
||||
if o = r.global.AsyncFunction; o == nil {
|
||||
o = &Object{runtime: r}
|
||||
r.global.AsyncFunction = o
|
||||
o.self = r.createAsyncFunction(o)
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
func (r *Runtime) builtin_genproto_next(call FunctionCall) Value {
|
||||
if o, ok := call.This.(*Object); ok {
|
||||
if gen, ok := o.self.(*generatorObject); ok {
|
||||
return gen.next(call.Argument(0))
|
||||
}
|
||||
}
|
||||
panic(r.NewTypeError("Method [Generator].prototype.next called on incompatible receiver"))
|
||||
}
|
||||
|
||||
func (r *Runtime) builtin_genproto_return(call FunctionCall) Value {
|
||||
if o, ok := call.This.(*Object); ok {
|
||||
if gen, ok := o.self.(*generatorObject); ok {
|
||||
return gen._return(call.Argument(0))
|
||||
}
|
||||
}
|
||||
panic(r.NewTypeError("Method [Generator].prototype.return called on incompatible receiver"))
|
||||
}
|
||||
|
||||
func (r *Runtime) builtin_genproto_throw(call FunctionCall) Value {
|
||||
if o, ok := call.This.(*Object); ok {
|
||||
if gen, ok := o.self.(*generatorObject); ok {
|
||||
return gen.throw(call.Argument(0))
|
||||
}
|
||||
}
|
||||
panic(r.NewTypeError("Method [Generator].prototype.throw called on incompatible receiver"))
|
||||
}
|
||||
|
||||
func (r *Runtime) createGeneratorFunctionProto(val *Object) objectImpl {
|
||||
o := newBaseObjectObj(val, r.global.FunctionPrototype, classObject)
|
||||
|
||||
o._putProp("constructor", r.getGeneratorFunction(), false, false, true)
|
||||
o._putProp("prototype", r.getGeneratorPrototype(), false, false, true)
|
||||
o._putSym(SymToStringTag, valueProp(asciiString(classGeneratorFunction), false, false, true))
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
func (r *Runtime) getGeneratorFunctionPrototype() *Object {
|
||||
var o *Object
|
||||
if o = r.global.GeneratorFunctionPrototype; o == nil {
|
||||
o = r.newLazyObject(r.createGeneratorFunctionProto)
|
||||
r.global.GeneratorFunctionPrototype = o
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
func (r *Runtime) createGeneratorFunction(val *Object) objectImpl {
|
||||
o := r.newNativeFuncConstructObj(val, r.builtin_generatorFunction, "GeneratorFunction", r.getGeneratorFunctionPrototype(), 1)
|
||||
return o
|
||||
}
|
||||
|
||||
func (r *Runtime) getGeneratorFunction() *Object {
|
||||
var o *Object
|
||||
if o = r.global.GeneratorFunction; o == nil {
|
||||
o = &Object{runtime: r}
|
||||
r.global.GeneratorFunction = o
|
||||
o.self = r.createGeneratorFunction(o)
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
func (r *Runtime) createGeneratorProto(val *Object) objectImpl {
|
||||
o := newBaseObjectObj(val, r.getIteratorPrototype(), classObject)
|
||||
|
||||
o._putProp("constructor", r.getGeneratorFunctionPrototype(), false, false, true)
|
||||
o._putProp("next", r.newNativeFunc(r.builtin_genproto_next, nil, "next", nil, 1), true, false, true)
|
||||
o._putProp("return", r.newNativeFunc(r.builtin_genproto_return, nil, "return", nil, 1), true, false, true)
|
||||
o._putProp("throw", r.newNativeFunc(r.builtin_genproto_throw, nil, "throw", nil, 1), true, false, true)
|
||||
|
||||
o._putSym(SymToStringTag, valueProp(asciiString(classGenerator), false, false, true))
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
func (r *Runtime) getGeneratorPrototype() *Object {
|
||||
var o *Object
|
||||
if o = r.global.GeneratorPrototype; o == nil {
|
||||
o = &Object{runtime: r}
|
||||
r.global.GeneratorPrototype = o
|
||||
o.self = r.createGeneratorProto(o)
|
||||
}
|
||||
return o
|
||||
}
|
||||
517
server/vendor/github.com/dop251/goja/builtin_global.go
generated
vendored
Normal file
517
server/vendor/github.com/dop251/goja/builtin_global.go
generated
vendored
Normal file
@@ -0,0 +1,517 @@
|
||||
package goja
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/dop251/goja/unistring"
|
||||
"io"
|
||||
"math"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
const hexUpper = "0123456789ABCDEF"
|
||||
|
||||
var (
|
||||
parseFloatRegexp = regexp.MustCompile(`^([+-]?(?:Infinity|[0-9]*\.?[0-9]*(?:[eE][+-]?[0-9]+)?))`)
|
||||
)
|
||||
|
||||
func (r *Runtime) builtin_isNaN(call FunctionCall) Value {
|
||||
if math.IsNaN(call.Argument(0).ToFloat()) {
|
||||
return valueTrue
|
||||
} else {
|
||||
return valueFalse
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Runtime) builtin_parseInt(call FunctionCall) Value {
|
||||
str := call.Argument(0).toString().toTrimmedUTF8()
|
||||
radix := int(toInt32(call.Argument(1)))
|
||||
v, _ := parseInt(str, radix)
|
||||
return v
|
||||
}
|
||||
|
||||
func (r *Runtime) builtin_parseFloat(call FunctionCall) Value {
|
||||
m := parseFloatRegexp.FindStringSubmatch(call.Argument(0).toString().toTrimmedUTF8())
|
||||
if len(m) == 2 {
|
||||
if s := m[1]; s != "" && s != "+" && s != "-" {
|
||||
switch s {
|
||||
case "+", "-":
|
||||
case "Infinity", "+Infinity":
|
||||
return _positiveInf
|
||||
case "-Infinity":
|
||||
return _negativeInf
|
||||
default:
|
||||
f, err := strconv.ParseFloat(s, 64)
|
||||
if err == nil || isRangeErr(err) {
|
||||
return floatToValue(f)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return _NaN
|
||||
}
|
||||
|
||||
func (r *Runtime) builtin_isFinite(call FunctionCall) Value {
|
||||
f := call.Argument(0).ToFloat()
|
||||
if math.IsNaN(f) || math.IsInf(f, 0) {
|
||||
return valueFalse
|
||||
}
|
||||
return valueTrue
|
||||
}
|
||||
|
||||
func (r *Runtime) _encode(uriString valueString, unescaped *[256]bool) valueString {
|
||||
reader := uriString.reader()
|
||||
utf8Buf := make([]byte, utf8.UTFMax)
|
||||
needed := false
|
||||
l := 0
|
||||
for {
|
||||
rn, _, err := reader.ReadRune()
|
||||
if err != nil {
|
||||
if err != io.EOF {
|
||||
panic(r.newError(r.global.URIError, "Malformed URI"))
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
if rn >= utf8.RuneSelf {
|
||||
needed = true
|
||||
l += utf8.EncodeRune(utf8Buf, rn) * 3
|
||||
} else if !unescaped[rn] {
|
||||
needed = true
|
||||
l += 3
|
||||
} else {
|
||||
l++
|
||||
}
|
||||
}
|
||||
|
||||
if !needed {
|
||||
return uriString
|
||||
}
|
||||
|
||||
buf := make([]byte, l)
|
||||
i := 0
|
||||
reader = uriString.reader()
|
||||
for {
|
||||
rn, _, err := reader.ReadRune()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
|
||||
if rn >= utf8.RuneSelf {
|
||||
n := utf8.EncodeRune(utf8Buf, rn)
|
||||
for _, b := range utf8Buf[:n] {
|
||||
buf[i] = '%'
|
||||
buf[i+1] = hexUpper[b>>4]
|
||||
buf[i+2] = hexUpper[b&15]
|
||||
i += 3
|
||||
}
|
||||
} else if !unescaped[rn] {
|
||||
buf[i] = '%'
|
||||
buf[i+1] = hexUpper[rn>>4]
|
||||
buf[i+2] = hexUpper[rn&15]
|
||||
i += 3
|
||||
} else {
|
||||
buf[i] = byte(rn)
|
||||
i++
|
||||
}
|
||||
}
|
||||
return asciiString(buf)
|
||||
}
|
||||
|
||||
func (r *Runtime) _decode(sv valueString, reservedSet *[256]bool) valueString {
|
||||
s := sv.String()
|
||||
hexCount := 0
|
||||
for i := 0; i < len(s); {
|
||||
switch s[i] {
|
||||
case '%':
|
||||
if i+2 >= len(s) || !ishex(s[i+1]) || !ishex(s[i+2]) {
|
||||
panic(r.newError(r.global.URIError, "Malformed URI"))
|
||||
}
|
||||
c := unhex(s[i+1])<<4 | unhex(s[i+2])
|
||||
if !reservedSet[c] {
|
||||
hexCount++
|
||||
}
|
||||
i += 3
|
||||
default:
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
if hexCount == 0 {
|
||||
return sv
|
||||
}
|
||||
|
||||
t := make([]byte, len(s)-hexCount*2)
|
||||
j := 0
|
||||
isUnicode := false
|
||||
for i := 0; i < len(s); {
|
||||
ch := s[i]
|
||||
switch ch {
|
||||
case '%':
|
||||
c := unhex(s[i+1])<<4 | unhex(s[i+2])
|
||||
if reservedSet[c] {
|
||||
t[j] = s[i]
|
||||
t[j+1] = s[i+1]
|
||||
t[j+2] = s[i+2]
|
||||
j += 3
|
||||
} else {
|
||||
t[j] = c
|
||||
if c >= utf8.RuneSelf {
|
||||
isUnicode = true
|
||||
}
|
||||
j++
|
||||
}
|
||||
i += 3
|
||||
default:
|
||||
if ch >= utf8.RuneSelf {
|
||||
isUnicode = true
|
||||
}
|
||||
t[j] = ch
|
||||
j++
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
if !isUnicode {
|
||||
return asciiString(t)
|
||||
}
|
||||
|
||||
us := make([]rune, 0, len(s))
|
||||
for len(t) > 0 {
|
||||
rn, size := utf8.DecodeRune(t)
|
||||
if rn == utf8.RuneError {
|
||||
if size != 3 || t[0] != 0xef || t[1] != 0xbf || t[2] != 0xbd {
|
||||
panic(r.newError(r.global.URIError, "Malformed URI"))
|
||||
}
|
||||
}
|
||||
us = append(us, rn)
|
||||
t = t[size:]
|
||||
}
|
||||
return unicodeStringFromRunes(us)
|
||||
}
|
||||
|
||||
func ishex(c byte) bool {
|
||||
switch {
|
||||
case '0' <= c && c <= '9':
|
||||
return true
|
||||
case 'a' <= c && c <= 'f':
|
||||
return true
|
||||
case 'A' <= c && c <= 'F':
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func unhex(c byte) byte {
|
||||
switch {
|
||||
case '0' <= c && c <= '9':
|
||||
return c - '0'
|
||||
case 'a' <= c && c <= 'f':
|
||||
return c - 'a' + 10
|
||||
case 'A' <= c && c <= 'F':
|
||||
return c - 'A' + 10
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (r *Runtime) builtin_decodeURI(call FunctionCall) Value {
|
||||
uriString := call.Argument(0).toString()
|
||||
return r._decode(uriString, &uriReservedHash)
|
||||
}
|
||||
|
||||
func (r *Runtime) builtin_decodeURIComponent(call FunctionCall) Value {
|
||||
uriString := call.Argument(0).toString()
|
||||
return r._decode(uriString, &emptyEscapeSet)
|
||||
}
|
||||
|
||||
func (r *Runtime) builtin_encodeURI(call FunctionCall) Value {
|
||||
uriString := call.Argument(0).toString()
|
||||
return r._encode(uriString, &uriReservedUnescapedHash)
|
||||
}
|
||||
|
||||
func (r *Runtime) builtin_encodeURIComponent(call FunctionCall) Value {
|
||||
uriString := call.Argument(0).toString()
|
||||
return r._encode(uriString, &uriUnescaped)
|
||||
}
|
||||
|
||||
func (r *Runtime) builtin_escape(call FunctionCall) Value {
|
||||
s := call.Argument(0).toString()
|
||||
var sb strings.Builder
|
||||
l := s.length()
|
||||
for i := 0; i < l; i++ {
|
||||
r := uint16(s.charAt(i))
|
||||
if r >= 'A' && r <= 'Z' || r >= 'a' && r <= 'z' || r >= '0' && r <= '9' ||
|
||||
r == '@' || r == '*' || r == '_' || r == '+' || r == '-' || r == '.' || r == '/' {
|
||||
sb.WriteByte(byte(r))
|
||||
} else if r <= 0xff {
|
||||
sb.WriteByte('%')
|
||||
sb.WriteByte(hexUpper[r>>4])
|
||||
sb.WriteByte(hexUpper[r&0xf])
|
||||
} else {
|
||||
sb.WriteString("%u")
|
||||
sb.WriteByte(hexUpper[r>>12])
|
||||
sb.WriteByte(hexUpper[(r>>8)&0xf])
|
||||
sb.WriteByte(hexUpper[(r>>4)&0xf])
|
||||
sb.WriteByte(hexUpper[r&0xf])
|
||||
}
|
||||
}
|
||||
return asciiString(sb.String())
|
||||
}
|
||||
|
||||
func (r *Runtime) builtin_unescape(call FunctionCall) Value {
|
||||
s := call.Argument(0).toString()
|
||||
l := s.length()
|
||||
var asciiBuf []byte
|
||||
var unicodeBuf []uint16
|
||||
_, u := devirtualizeString(s)
|
||||
unicode := u != nil
|
||||
if unicode {
|
||||
unicodeBuf = make([]uint16, 1, l+1)
|
||||
unicodeBuf[0] = unistring.BOM
|
||||
} else {
|
||||
asciiBuf = make([]byte, 0, l)
|
||||
}
|
||||
for i := 0; i < l; {
|
||||
r := s.charAt(i)
|
||||
if r == '%' {
|
||||
if i <= l-6 && s.charAt(i+1) == 'u' {
|
||||
c0 := s.charAt(i + 2)
|
||||
c1 := s.charAt(i + 3)
|
||||
c2 := s.charAt(i + 4)
|
||||
c3 := s.charAt(i + 5)
|
||||
if c0 <= 0xff && ishex(byte(c0)) &&
|
||||
c1 <= 0xff && ishex(byte(c1)) &&
|
||||
c2 <= 0xff && ishex(byte(c2)) &&
|
||||
c3 <= 0xff && ishex(byte(c3)) {
|
||||
r = rune(unhex(byte(c0)))<<12 |
|
||||
rune(unhex(byte(c1)))<<8 |
|
||||
rune(unhex(byte(c2)))<<4 |
|
||||
rune(unhex(byte(c3)))
|
||||
i += 5
|
||||
goto out
|
||||
}
|
||||
}
|
||||
if i <= l-3 {
|
||||
c0 := s.charAt(i + 1)
|
||||
c1 := s.charAt(i + 2)
|
||||
if c0 <= 0xff && ishex(byte(c0)) &&
|
||||
c1 <= 0xff && ishex(byte(c1)) {
|
||||
r = rune(unhex(byte(c0))<<4 | unhex(byte(c1)))
|
||||
i += 2
|
||||
}
|
||||
}
|
||||
}
|
||||
out:
|
||||
if r >= utf8.RuneSelf && !unicode {
|
||||
unicodeBuf = make([]uint16, 1, l+1)
|
||||
unicodeBuf[0] = unistring.BOM
|
||||
for _, b := range asciiBuf {
|
||||
unicodeBuf = append(unicodeBuf, uint16(b))
|
||||
}
|
||||
asciiBuf = nil
|
||||
unicode = true
|
||||
}
|
||||
if unicode {
|
||||
unicodeBuf = append(unicodeBuf, uint16(r))
|
||||
} else {
|
||||
asciiBuf = append(asciiBuf, byte(r))
|
||||
}
|
||||
i++
|
||||
}
|
||||
if unicode {
|
||||
return unicodeString(unicodeBuf)
|
||||
}
|
||||
|
||||
return asciiString(asciiBuf)
|
||||
}
|
||||
|
||||
func (r *Runtime) initGlobalObject() {
|
||||
o := r.globalObject.self
|
||||
o._putProp("globalThis", r.globalObject, true, false, true)
|
||||
o._putProp("NaN", _NaN, false, false, false)
|
||||
o._putProp("undefined", _undefined, false, false, false)
|
||||
o._putProp("Infinity", _positiveInf, false, false, false)
|
||||
|
||||
o._putProp("isNaN", r.newNativeFunc(r.builtin_isNaN, nil, "isNaN", nil, 1), true, false, true)
|
||||
o._putProp("parseInt", r.newNativeFunc(r.builtin_parseInt, nil, "parseInt", nil, 2), true, false, true)
|
||||
o._putProp("parseFloat", r.newNativeFunc(r.builtin_parseFloat, nil, "parseFloat", nil, 1), true, false, true)
|
||||
o._putProp("isFinite", r.newNativeFunc(r.builtin_isFinite, nil, "isFinite", nil, 1), true, false, true)
|
||||
o._putProp("decodeURI", r.newNativeFunc(r.builtin_decodeURI, nil, "decodeURI", nil, 1), true, false, true)
|
||||
o._putProp("decodeURIComponent", r.newNativeFunc(r.builtin_decodeURIComponent, nil, "decodeURIComponent", nil, 1), true, false, true)
|
||||
o._putProp("encodeURI", r.newNativeFunc(r.builtin_encodeURI, nil, "encodeURI", nil, 1), true, false, true)
|
||||
o._putProp("encodeURIComponent", r.newNativeFunc(r.builtin_encodeURIComponent, nil, "encodeURIComponent", nil, 1), true, false, true)
|
||||
o._putProp("escape", r.newNativeFunc(r.builtin_escape, nil, "escape", nil, 1), true, false, true)
|
||||
o._putProp("unescape", r.newNativeFunc(r.builtin_unescape, nil, "unescape", nil, 1), true, false, true)
|
||||
|
||||
o._putSym(SymToStringTag, valueProp(asciiString(classGlobal), false, false, true))
|
||||
|
||||
// TODO: Annex B
|
||||
|
||||
}
|
||||
|
||||
func digitVal(d byte) int {
|
||||
var v byte
|
||||
switch {
|
||||
case '0' <= d && d <= '9':
|
||||
v = d - '0'
|
||||
case 'a' <= d && d <= 'z':
|
||||
v = d - 'a' + 10
|
||||
case 'A' <= d && d <= 'Z':
|
||||
v = d - 'A' + 10
|
||||
default:
|
||||
return 36
|
||||
}
|
||||
return int(v)
|
||||
}
|
||||
|
||||
// ECMAScript compatible version of strconv.ParseInt
|
||||
func parseInt(s string, base int) (Value, error) {
|
||||
var n int64
|
||||
var err error
|
||||
var cutoff, maxVal int64
|
||||
var sign bool
|
||||
i := 0
|
||||
|
||||
if len(s) < 1 {
|
||||
err = strconv.ErrSyntax
|
||||
goto Error
|
||||
}
|
||||
|
||||
switch s[0] {
|
||||
case '-':
|
||||
sign = true
|
||||
s = s[1:]
|
||||
case '+':
|
||||
s = s[1:]
|
||||
}
|
||||
|
||||
if len(s) < 1 {
|
||||
err = strconv.ErrSyntax
|
||||
goto Error
|
||||
}
|
||||
|
||||
// Look for hex prefix.
|
||||
if s[0] == '0' && len(s) > 1 && (s[1] == 'x' || s[1] == 'X') {
|
||||
if base == 0 || base == 16 {
|
||||
base = 16
|
||||
s = s[2:]
|
||||
}
|
||||
}
|
||||
|
||||
switch {
|
||||
case len(s) < 1:
|
||||
err = strconv.ErrSyntax
|
||||
goto Error
|
||||
|
||||
case 2 <= base && base <= 36:
|
||||
// valid base; nothing to do
|
||||
|
||||
case base == 0:
|
||||
// Look for hex prefix.
|
||||
switch {
|
||||
case s[0] == '0' && len(s) > 1 && (s[1] == 'x' || s[1] == 'X'):
|
||||
if len(s) < 3 {
|
||||
err = strconv.ErrSyntax
|
||||
goto Error
|
||||
}
|
||||
base = 16
|
||||
s = s[2:]
|
||||
default:
|
||||
base = 10
|
||||
}
|
||||
|
||||
default:
|
||||
err = errors.New("invalid base " + strconv.Itoa(base))
|
||||
goto Error
|
||||
}
|
||||
|
||||
// Cutoff is the smallest number such that cutoff*base > maxInt64.
|
||||
// Use compile-time constants for common cases.
|
||||
switch base {
|
||||
case 10:
|
||||
cutoff = math.MaxInt64/10 + 1
|
||||
case 16:
|
||||
cutoff = math.MaxInt64/16 + 1
|
||||
default:
|
||||
cutoff = math.MaxInt64/int64(base) + 1
|
||||
}
|
||||
|
||||
maxVal = math.MaxInt64
|
||||
for ; i < len(s); i++ {
|
||||
if n >= cutoff {
|
||||
// n*base overflows
|
||||
return parseLargeInt(float64(n), s[i:], base, sign)
|
||||
}
|
||||
v := digitVal(s[i])
|
||||
if v >= base {
|
||||
break
|
||||
}
|
||||
n *= int64(base)
|
||||
|
||||
n1 := n + int64(v)
|
||||
if n1 < n || n1 > maxVal {
|
||||
// n+v overflows
|
||||
return parseLargeInt(float64(n)+float64(v), s[i+1:], base, sign)
|
||||
}
|
||||
n = n1
|
||||
}
|
||||
|
||||
if i == 0 {
|
||||
err = strconv.ErrSyntax
|
||||
goto Error
|
||||
}
|
||||
|
||||
if sign {
|
||||
n = -n
|
||||
}
|
||||
return intToValue(n), nil
|
||||
|
||||
Error:
|
||||
return _NaN, err
|
||||
}
|
||||
|
||||
func parseLargeInt(n float64, s string, base int, sign bool) (Value, error) {
|
||||
i := 0
|
||||
b := float64(base)
|
||||
for ; i < len(s); i++ {
|
||||
v := digitVal(s[i])
|
||||
if v >= base {
|
||||
break
|
||||
}
|
||||
n = n*b + float64(v)
|
||||
}
|
||||
if sign {
|
||||
n = -n
|
||||
}
|
||||
// We know it can't be represented as int, so use valueFloat instead of floatToValue
|
||||
return valueFloat(n), nil
|
||||
}
|
||||
|
||||
var (
|
||||
uriUnescaped [256]bool
|
||||
uriReserved [256]bool
|
||||
uriReservedHash [256]bool
|
||||
uriReservedUnescapedHash [256]bool
|
||||
emptyEscapeSet [256]bool
|
||||
)
|
||||
|
||||
func init() {
|
||||
for _, c := range "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.!~*'()" {
|
||||
uriUnescaped[c] = true
|
||||
}
|
||||
|
||||
for _, c := range ";/?:@&=+$," {
|
||||
uriReserved[c] = true
|
||||
}
|
||||
|
||||
for i := 0; i < 256; i++ {
|
||||
if uriUnescaped[i] || uriReserved[i] {
|
||||
uriReservedUnescapedHash[i] = true
|
||||
}
|
||||
uriReservedHash[i] = uriReserved[i]
|
||||
}
|
||||
uriReservedUnescapedHash['#'] = true
|
||||
uriReservedHash['#'] = true
|
||||
}
|
||||
528
server/vendor/github.com/dop251/goja/builtin_json.go
generated
vendored
Normal file
528
server/vendor/github.com/dop251/goja/builtin_json.go
generated
vendored
Normal file
@@ -0,0 +1,528 @@
|
||||
package goja
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode/utf16"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/dop251/goja/unistring"
|
||||
)
|
||||
|
||||
const hex = "0123456789abcdef"
|
||||
|
||||
func (r *Runtime) builtinJSON_parse(call FunctionCall) Value {
|
||||
d := json.NewDecoder(strings.NewReader(call.Argument(0).toString().String()))
|
||||
|
||||
value, err := r.builtinJSON_decodeValue(d)
|
||||
if err != nil {
|
||||
panic(r.newError(r.global.SyntaxError, err.Error()))
|
||||
}
|
||||
|
||||
if tok, err := d.Token(); err != io.EOF {
|
||||
panic(r.newError(r.global.SyntaxError, "Unexpected token at the end: %v", tok))
|
||||
}
|
||||
|
||||
var reviver func(FunctionCall) Value
|
||||
|
||||
if arg1 := call.Argument(1); arg1 != _undefined {
|
||||
reviver, _ = arg1.ToObject(r).self.assertCallable()
|
||||
}
|
||||
|
||||
if reviver != nil {
|
||||
root := r.NewObject()
|
||||
createDataPropertyOrThrow(root, stringEmpty, value)
|
||||
return r.builtinJSON_reviveWalk(reviver, root, stringEmpty)
|
||||
}
|
||||
|
||||
return value
|
||||
}
|
||||
|
||||
func (r *Runtime) builtinJSON_decodeToken(d *json.Decoder, tok json.Token) (Value, error) {
|
||||
switch tok := tok.(type) {
|
||||
case json.Delim:
|
||||
switch tok {
|
||||
case '{':
|
||||
return r.builtinJSON_decodeObject(d)
|
||||
case '[':
|
||||
return r.builtinJSON_decodeArray(d)
|
||||
}
|
||||
case nil:
|
||||
return _null, nil
|
||||
case string:
|
||||
return newStringValue(tok), nil
|
||||
case float64:
|
||||
return floatToValue(tok), nil
|
||||
case bool:
|
||||
if tok {
|
||||
return valueTrue, nil
|
||||
}
|
||||
return valueFalse, nil
|
||||
}
|
||||
return nil, fmt.Errorf("Unexpected token (%T): %v", tok, tok)
|
||||
}
|
||||
|
||||
func (r *Runtime) builtinJSON_decodeValue(d *json.Decoder) (Value, error) {
|
||||
tok, err := d.Token()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return r.builtinJSON_decodeToken(d, tok)
|
||||
}
|
||||
|
||||
func (r *Runtime) builtinJSON_decodeObject(d *json.Decoder) (*Object, error) {
|
||||
object := r.NewObject()
|
||||
for {
|
||||
key, end, err := r.builtinJSON_decodeObjectKey(d)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if end {
|
||||
break
|
||||
}
|
||||
value, err := r.builtinJSON_decodeValue(d)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
object.self._putProp(unistring.NewFromString(key), value, true, true, true)
|
||||
}
|
||||
return object, nil
|
||||
}
|
||||
|
||||
func (r *Runtime) builtinJSON_decodeObjectKey(d *json.Decoder) (string, bool, error) {
|
||||
tok, err := d.Token()
|
||||
if err != nil {
|
||||
return "", false, err
|
||||
}
|
||||
switch tok := tok.(type) {
|
||||
case json.Delim:
|
||||
if tok == '}' {
|
||||
return "", true, nil
|
||||
}
|
||||
case string:
|
||||
return tok, false, nil
|
||||
}
|
||||
|
||||
return "", false, fmt.Errorf("Unexpected token (%T): %v", tok, tok)
|
||||
}
|
||||
|
||||
func (r *Runtime) builtinJSON_decodeArray(d *json.Decoder) (*Object, error) {
|
||||
var arrayValue []Value
|
||||
for {
|
||||
tok, err := d.Token()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if delim, ok := tok.(json.Delim); ok {
|
||||
if delim == ']' {
|
||||
break
|
||||
}
|
||||
}
|
||||
value, err := r.builtinJSON_decodeToken(d, tok)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
arrayValue = append(arrayValue, value)
|
||||
}
|
||||
return r.newArrayValues(arrayValue), nil
|
||||
}
|
||||
|
||||
func (r *Runtime) builtinJSON_reviveWalk(reviver func(FunctionCall) Value, holder *Object, name Value) Value {
|
||||
value := nilSafe(holder.get(name, nil))
|
||||
|
||||
if object, ok := value.(*Object); ok {
|
||||
if isArray(object) {
|
||||
length := toLength(object.self.getStr("length", nil))
|
||||
for index := int64(0); index < length; index++ {
|
||||
name := asciiString(strconv.FormatInt(index, 10))
|
||||
value := r.builtinJSON_reviveWalk(reviver, object, name)
|
||||
if value == _undefined {
|
||||
object.delete(name, false)
|
||||
} else {
|
||||
createDataProperty(object, name, value)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for _, name := range object.self.stringKeys(false, nil) {
|
||||
value := r.builtinJSON_reviveWalk(reviver, object, name)
|
||||
if value == _undefined {
|
||||
object.self.deleteStr(name.string(), false)
|
||||
} else {
|
||||
createDataProperty(object, name, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return reviver(FunctionCall{
|
||||
This: holder,
|
||||
Arguments: []Value{name, value},
|
||||
})
|
||||
}
|
||||
|
||||
type _builtinJSON_stringifyContext struct {
|
||||
r *Runtime
|
||||
stack []*Object
|
||||
propertyList []Value
|
||||
replacerFunction func(FunctionCall) Value
|
||||
gap, indent string
|
||||
buf bytes.Buffer
|
||||
allAscii bool
|
||||
}
|
||||
|
||||
func (r *Runtime) builtinJSON_stringify(call FunctionCall) Value {
|
||||
ctx := _builtinJSON_stringifyContext{
|
||||
r: r,
|
||||
allAscii: true,
|
||||
}
|
||||
|
||||
replacer, _ := call.Argument(1).(*Object)
|
||||
if replacer != nil {
|
||||
if isArray(replacer) {
|
||||
length := toLength(replacer.self.getStr("length", nil))
|
||||
seen := map[string]bool{}
|
||||
propertyList := make([]Value, length)
|
||||
length = 0
|
||||
for index := range propertyList {
|
||||
var name string
|
||||
value := replacer.self.getIdx(valueInt(int64(index)), nil)
|
||||
switch v := value.(type) {
|
||||
case valueFloat, valueInt, valueString:
|
||||
name = value.String()
|
||||
case *Object:
|
||||
switch v.self.className() {
|
||||
case classNumber, classString:
|
||||
name = value.String()
|
||||
default:
|
||||
continue
|
||||
}
|
||||
default:
|
||||
continue
|
||||
}
|
||||
if seen[name] {
|
||||
continue
|
||||
}
|
||||
seen[name] = true
|
||||
propertyList[length] = newStringValue(name)
|
||||
length += 1
|
||||
}
|
||||
ctx.propertyList = propertyList[0:length]
|
||||
} else if c, ok := replacer.self.assertCallable(); ok {
|
||||
ctx.replacerFunction = c
|
||||
}
|
||||
}
|
||||
if spaceValue := call.Argument(2); spaceValue != _undefined {
|
||||
if o, ok := spaceValue.(*Object); ok {
|
||||
switch oImpl := o.self.(type) {
|
||||
case *primitiveValueObject:
|
||||
switch oImpl.pValue.(type) {
|
||||
case valueInt, valueFloat:
|
||||
spaceValue = o.ToNumber()
|
||||
}
|
||||
case *stringObject:
|
||||
spaceValue = o.ToString()
|
||||
}
|
||||
}
|
||||
isNum := false
|
||||
var num int64
|
||||
if i, ok := spaceValue.(valueInt); ok {
|
||||
num = int64(i)
|
||||
isNum = true
|
||||
} else if f, ok := spaceValue.(valueFloat); ok {
|
||||
num = int64(f)
|
||||
isNum = true
|
||||
}
|
||||
if isNum {
|
||||
if num > 0 {
|
||||
if num > 10 {
|
||||
num = 10
|
||||
}
|
||||
ctx.gap = strings.Repeat(" ", int(num))
|
||||
}
|
||||
} else {
|
||||
if s, ok := spaceValue.(valueString); ok {
|
||||
str := s.String()
|
||||
if len(str) > 10 {
|
||||
ctx.gap = str[:10]
|
||||
} else {
|
||||
ctx.gap = str
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ctx.do(call.Argument(0)) {
|
||||
if ctx.allAscii {
|
||||
return asciiString(ctx.buf.String())
|
||||
} else {
|
||||
return &importedString{
|
||||
s: ctx.buf.String(),
|
||||
}
|
||||
}
|
||||
}
|
||||
return _undefined
|
||||
}
|
||||
|
||||
func (ctx *_builtinJSON_stringifyContext) do(v Value) bool {
|
||||
holder := ctx.r.NewObject()
|
||||
createDataPropertyOrThrow(holder, stringEmpty, v)
|
||||
return ctx.str(stringEmpty, holder)
|
||||
}
|
||||
|
||||
func (ctx *_builtinJSON_stringifyContext) str(key Value, holder *Object) bool {
|
||||
value := nilSafe(holder.get(key, nil))
|
||||
|
||||
if object, ok := value.(*Object); ok {
|
||||
if toJSON, ok := object.self.getStr("toJSON", nil).(*Object); ok {
|
||||
if c, ok := toJSON.self.assertCallable(); ok {
|
||||
value = c(FunctionCall{
|
||||
This: value,
|
||||
Arguments: []Value{key},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ctx.replacerFunction != nil {
|
||||
value = ctx.replacerFunction(FunctionCall{
|
||||
This: holder,
|
||||
Arguments: []Value{key, value},
|
||||
})
|
||||
}
|
||||
|
||||
if o, ok := value.(*Object); ok {
|
||||
switch o1 := o.self.(type) {
|
||||
case *primitiveValueObject:
|
||||
switch pValue := o1.pValue.(type) {
|
||||
case valueInt, valueFloat:
|
||||
value = o.ToNumber()
|
||||
default:
|
||||
value = pValue
|
||||
}
|
||||
case *stringObject:
|
||||
value = o.toString()
|
||||
case *objectGoReflect:
|
||||
if o1.toJson != nil {
|
||||
value = ctx.r.ToValue(o1.toJson())
|
||||
} else if v, ok := o1.origValue.Interface().(json.Marshaler); ok {
|
||||
b, err := v.MarshalJSON()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
ctx.buf.Write(b)
|
||||
ctx.allAscii = false
|
||||
return true
|
||||
} else {
|
||||
switch o1.className() {
|
||||
case classNumber:
|
||||
value = o1.toPrimitiveNumber()
|
||||
case classString:
|
||||
value = o1.toPrimitiveString()
|
||||
case classBoolean:
|
||||
if o.ToInteger() != 0 {
|
||||
value = valueTrue
|
||||
} else {
|
||||
value = valueFalse
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch value1 := value.(type) {
|
||||
case valueBool:
|
||||
if value1 {
|
||||
ctx.buf.WriteString("true")
|
||||
} else {
|
||||
ctx.buf.WriteString("false")
|
||||
}
|
||||
case valueString:
|
||||
ctx.quote(value1)
|
||||
case valueInt:
|
||||
ctx.buf.WriteString(value.String())
|
||||
case valueFloat:
|
||||
if !math.IsNaN(float64(value1)) && !math.IsInf(float64(value1), 0) {
|
||||
ctx.buf.WriteString(value.String())
|
||||
} else {
|
||||
ctx.buf.WriteString("null")
|
||||
}
|
||||
case valueNull:
|
||||
ctx.buf.WriteString("null")
|
||||
case *Object:
|
||||
for _, object := range ctx.stack {
|
||||
if value1 == object {
|
||||
ctx.r.typeErrorResult(true, "Converting circular structure to JSON")
|
||||
}
|
||||
}
|
||||
ctx.stack = append(ctx.stack, value1)
|
||||
defer func() { ctx.stack = ctx.stack[:len(ctx.stack)-1] }()
|
||||
if _, ok := value1.self.assertCallable(); !ok {
|
||||
if isArray(value1) {
|
||||
ctx.ja(value1)
|
||||
} else {
|
||||
ctx.jo(value1)
|
||||
}
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (ctx *_builtinJSON_stringifyContext) ja(array *Object) {
|
||||
var stepback string
|
||||
if ctx.gap != "" {
|
||||
stepback = ctx.indent
|
||||
ctx.indent += ctx.gap
|
||||
}
|
||||
length := toLength(array.self.getStr("length", nil))
|
||||
if length == 0 {
|
||||
ctx.buf.WriteString("[]")
|
||||
return
|
||||
}
|
||||
|
||||
ctx.buf.WriteByte('[')
|
||||
var separator string
|
||||
if ctx.gap != "" {
|
||||
ctx.buf.WriteByte('\n')
|
||||
ctx.buf.WriteString(ctx.indent)
|
||||
separator = ",\n" + ctx.indent
|
||||
} else {
|
||||
separator = ","
|
||||
}
|
||||
|
||||
for i := int64(0); i < length; i++ {
|
||||
if !ctx.str(asciiString(strconv.FormatInt(i, 10)), array) {
|
||||
ctx.buf.WriteString("null")
|
||||
}
|
||||
if i < length-1 {
|
||||
ctx.buf.WriteString(separator)
|
||||
}
|
||||
}
|
||||
if ctx.gap != "" {
|
||||
ctx.buf.WriteByte('\n')
|
||||
ctx.buf.WriteString(stepback)
|
||||
ctx.indent = stepback
|
||||
}
|
||||
ctx.buf.WriteByte(']')
|
||||
}
|
||||
|
||||
func (ctx *_builtinJSON_stringifyContext) jo(object *Object) {
|
||||
var stepback string
|
||||
if ctx.gap != "" {
|
||||
stepback = ctx.indent
|
||||
ctx.indent += ctx.gap
|
||||
}
|
||||
|
||||
ctx.buf.WriteByte('{')
|
||||
mark := ctx.buf.Len()
|
||||
var separator string
|
||||
if ctx.gap != "" {
|
||||
ctx.buf.WriteByte('\n')
|
||||
ctx.buf.WriteString(ctx.indent)
|
||||
separator = ",\n" + ctx.indent
|
||||
} else {
|
||||
separator = ","
|
||||
}
|
||||
|
||||
var props []Value
|
||||
if ctx.propertyList == nil {
|
||||
props = object.self.stringKeys(false, nil)
|
||||
} else {
|
||||
props = ctx.propertyList
|
||||
}
|
||||
|
||||
empty := true
|
||||
for _, name := range props {
|
||||
off := ctx.buf.Len()
|
||||
if !empty {
|
||||
ctx.buf.WriteString(separator)
|
||||
}
|
||||
ctx.quote(name.toString())
|
||||
if ctx.gap != "" {
|
||||
ctx.buf.WriteString(": ")
|
||||
} else {
|
||||
ctx.buf.WriteByte(':')
|
||||
}
|
||||
if ctx.str(name, object) {
|
||||
if empty {
|
||||
empty = false
|
||||
}
|
||||
} else {
|
||||
ctx.buf.Truncate(off)
|
||||
}
|
||||
}
|
||||
|
||||
if empty {
|
||||
ctx.buf.Truncate(mark)
|
||||
} else {
|
||||
if ctx.gap != "" {
|
||||
ctx.buf.WriteByte('\n')
|
||||
ctx.buf.WriteString(stepback)
|
||||
ctx.indent = stepback
|
||||
}
|
||||
}
|
||||
ctx.buf.WriteByte('}')
|
||||
}
|
||||
|
||||
func (ctx *_builtinJSON_stringifyContext) quote(str valueString) {
|
||||
ctx.buf.WriteByte('"')
|
||||
reader := &lenientUtf16Decoder{utf16Reader: str.utf16Reader()}
|
||||
for {
|
||||
r, _, err := reader.ReadRune()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
switch r {
|
||||
case '"', '\\':
|
||||
ctx.buf.WriteByte('\\')
|
||||
ctx.buf.WriteByte(byte(r))
|
||||
case 0x08:
|
||||
ctx.buf.WriteString(`\b`)
|
||||
case 0x09:
|
||||
ctx.buf.WriteString(`\t`)
|
||||
case 0x0A:
|
||||
ctx.buf.WriteString(`\n`)
|
||||
case 0x0C:
|
||||
ctx.buf.WriteString(`\f`)
|
||||
case 0x0D:
|
||||
ctx.buf.WriteString(`\r`)
|
||||
default:
|
||||
if r < 0x20 {
|
||||
ctx.buf.WriteString(`\u00`)
|
||||
ctx.buf.WriteByte(hex[r>>4])
|
||||
ctx.buf.WriteByte(hex[r&0xF])
|
||||
} else {
|
||||
if utf16.IsSurrogate(r) {
|
||||
ctx.buf.WriteString(`\u`)
|
||||
ctx.buf.WriteByte(hex[r>>12])
|
||||
ctx.buf.WriteByte(hex[(r>>8)&0xF])
|
||||
ctx.buf.WriteByte(hex[(r>>4)&0xF])
|
||||
ctx.buf.WriteByte(hex[r&0xF])
|
||||
} else {
|
||||
ctx.buf.WriteRune(r)
|
||||
if ctx.allAscii && r >= utf8.RuneSelf {
|
||||
ctx.allAscii = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ctx.buf.WriteByte('"')
|
||||
}
|
||||
|
||||
func (r *Runtime) initJSON() {
|
||||
JSON := r.newBaseObject(r.global.ObjectPrototype, classObject)
|
||||
JSON._putProp("parse", r.newNativeFunc(r.builtinJSON_parse, nil, "parse", nil, 2), true, false, true)
|
||||
JSON._putProp("stringify", r.newNativeFunc(r.builtinJSON_stringify, nil, "stringify", nil, 3), true, false, true)
|
||||
JSON._putSym(SymToStringTag, valueProp(asciiString(classJSON), false, false, true))
|
||||
|
||||
r.addToGlobal("JSON", JSON.val)
|
||||
}
|
||||
331
server/vendor/github.com/dop251/goja/builtin_map.go
generated
vendored
Normal file
331
server/vendor/github.com/dop251/goja/builtin_map.go
generated
vendored
Normal file
@@ -0,0 +1,331 @@
|
||||
package goja
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
var mapExportType = reflect.TypeOf([][2]interface{}{})
|
||||
|
||||
type mapObject struct {
|
||||
baseObject
|
||||
m *orderedMap
|
||||
}
|
||||
|
||||
type mapIterObject struct {
|
||||
baseObject
|
||||
iter *orderedMapIter
|
||||
kind iterationKind
|
||||
}
|
||||
|
||||
func (o *mapIterObject) next() Value {
|
||||
if o.iter == nil {
|
||||
return o.val.runtime.createIterResultObject(_undefined, true)
|
||||
}
|
||||
|
||||
entry := o.iter.next()
|
||||
if entry == nil {
|
||||
o.iter = nil
|
||||
return o.val.runtime.createIterResultObject(_undefined, true)
|
||||
}
|
||||
|
||||
var result Value
|
||||
switch o.kind {
|
||||
case iterationKindKey:
|
||||
result = entry.key
|
||||
case iterationKindValue:
|
||||
result = entry.value
|
||||
default:
|
||||
result = o.val.runtime.newArrayValues([]Value{entry.key, entry.value})
|
||||
}
|
||||
|
||||
return o.val.runtime.createIterResultObject(result, false)
|
||||
}
|
||||
|
||||
func (mo *mapObject) init() {
|
||||
mo.baseObject.init()
|
||||
mo.m = newOrderedMap(mo.val.runtime.getHash())
|
||||
}
|
||||
|
||||
func (mo *mapObject) exportType() reflect.Type {
|
||||
return mapExportType
|
||||
}
|
||||
|
||||
func (mo *mapObject) export(ctx *objectExportCtx) interface{} {
|
||||
m := make([][2]interface{}, mo.m.size)
|
||||
ctx.put(mo.val, m)
|
||||
|
||||
iter := mo.m.newIter()
|
||||
for i := 0; i < len(m); i++ {
|
||||
entry := iter.next()
|
||||
if entry == nil {
|
||||
break
|
||||
}
|
||||
m[i][0] = exportValue(entry.key, ctx)
|
||||
m[i][1] = exportValue(entry.value, ctx)
|
||||
}
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
func (mo *mapObject) exportToMap(dst reflect.Value, typ reflect.Type, ctx *objectExportCtx) error {
|
||||
dst.Set(reflect.MakeMap(typ))
|
||||
ctx.putTyped(mo.val, typ, dst.Interface())
|
||||
keyTyp := typ.Key()
|
||||
elemTyp := typ.Elem()
|
||||
iter := mo.m.newIter()
|
||||
r := mo.val.runtime
|
||||
for {
|
||||
entry := iter.next()
|
||||
if entry == nil {
|
||||
break
|
||||
}
|
||||
keyVal := reflect.New(keyTyp).Elem()
|
||||
err := r.toReflectValue(entry.key, keyVal, ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
elemVal := reflect.New(elemTyp).Elem()
|
||||
err = r.toReflectValue(entry.value, elemVal, ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dst.SetMapIndex(keyVal, elemVal)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Runtime) mapProto_clear(call FunctionCall) Value {
|
||||
thisObj := r.toObject(call.This)
|
||||
mo, ok := thisObj.self.(*mapObject)
|
||||
if !ok {
|
||||
panic(r.NewTypeError("Method Map.prototype.clear called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
|
||||
}
|
||||
|
||||
mo.m.clear()
|
||||
|
||||
return _undefined
|
||||
}
|
||||
|
||||
func (r *Runtime) mapProto_delete(call FunctionCall) Value {
|
||||
thisObj := r.toObject(call.This)
|
||||
mo, ok := thisObj.self.(*mapObject)
|
||||
if !ok {
|
||||
panic(r.NewTypeError("Method Map.prototype.delete called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
|
||||
}
|
||||
|
||||
return r.toBoolean(mo.m.remove(call.Argument(0)))
|
||||
}
|
||||
|
||||
func (r *Runtime) mapProto_get(call FunctionCall) Value {
|
||||
thisObj := r.toObject(call.This)
|
||||
mo, ok := thisObj.self.(*mapObject)
|
||||
if !ok {
|
||||
panic(r.NewTypeError("Method Map.prototype.get called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
|
||||
}
|
||||
|
||||
return nilSafe(mo.m.get(call.Argument(0)))
|
||||
}
|
||||
|
||||
func (r *Runtime) mapProto_has(call FunctionCall) Value {
|
||||
thisObj := r.toObject(call.This)
|
||||
mo, ok := thisObj.self.(*mapObject)
|
||||
if !ok {
|
||||
panic(r.NewTypeError("Method Map.prototype.has called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
|
||||
}
|
||||
if mo.m.has(call.Argument(0)) {
|
||||
return valueTrue
|
||||
}
|
||||
return valueFalse
|
||||
}
|
||||
|
||||
func (r *Runtime) mapProto_set(call FunctionCall) Value {
|
||||
thisObj := r.toObject(call.This)
|
||||
mo, ok := thisObj.self.(*mapObject)
|
||||
if !ok {
|
||||
panic(r.NewTypeError("Method Map.prototype.set called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
|
||||
}
|
||||
mo.m.set(call.Argument(0), call.Argument(1))
|
||||
return call.This
|
||||
}
|
||||
|
||||
func (r *Runtime) mapProto_entries(call FunctionCall) Value {
|
||||
return r.createMapIterator(call.This, iterationKindKeyValue)
|
||||
}
|
||||
|
||||
func (r *Runtime) mapProto_forEach(call FunctionCall) Value {
|
||||
thisObj := r.toObject(call.This)
|
||||
mo, ok := thisObj.self.(*mapObject)
|
||||
if !ok {
|
||||
panic(r.NewTypeError("Method Map.prototype.forEach called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
|
||||
}
|
||||
callbackFn, ok := r.toObject(call.Argument(0)).self.assertCallable()
|
||||
if !ok {
|
||||
panic(r.NewTypeError("object is not a function %s"))
|
||||
}
|
||||
t := call.Argument(1)
|
||||
iter := mo.m.newIter()
|
||||
for {
|
||||
entry := iter.next()
|
||||
if entry == nil {
|
||||
break
|
||||
}
|
||||
callbackFn(FunctionCall{This: t, Arguments: []Value{entry.value, entry.key, thisObj}})
|
||||
}
|
||||
|
||||
return _undefined
|
||||
}
|
||||
|
||||
func (r *Runtime) mapProto_keys(call FunctionCall) Value {
|
||||
return r.createMapIterator(call.This, iterationKindKey)
|
||||
}
|
||||
|
||||
func (r *Runtime) mapProto_values(call FunctionCall) Value {
|
||||
return r.createMapIterator(call.This, iterationKindValue)
|
||||
}
|
||||
|
||||
func (r *Runtime) mapProto_getSize(call FunctionCall) Value {
|
||||
thisObj := r.toObject(call.This)
|
||||
mo, ok := thisObj.self.(*mapObject)
|
||||
if !ok {
|
||||
panic(r.NewTypeError("Method get Map.prototype.size called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
|
||||
}
|
||||
return intToValue(int64(mo.m.size))
|
||||
}
|
||||
|
||||
func (r *Runtime) builtin_newMap(args []Value, newTarget *Object) *Object {
|
||||
if newTarget == nil {
|
||||
panic(r.needNew("Map"))
|
||||
}
|
||||
proto := r.getPrototypeFromCtor(newTarget, r.global.Map, r.global.MapPrototype)
|
||||
o := &Object{runtime: r}
|
||||
|
||||
mo := &mapObject{}
|
||||
mo.class = classObject
|
||||
mo.val = o
|
||||
mo.extensible = true
|
||||
o.self = mo
|
||||
mo.prototype = proto
|
||||
mo.init()
|
||||
if len(args) > 0 {
|
||||
if arg := args[0]; arg != nil && arg != _undefined && arg != _null {
|
||||
adder := mo.getStr("set", nil)
|
||||
adderFn := toMethod(adder)
|
||||
if adderFn == nil {
|
||||
panic(r.NewTypeError("Map.set in missing"))
|
||||
}
|
||||
iter := r.getIterator(arg, nil)
|
||||
i0 := valueInt(0)
|
||||
i1 := valueInt(1)
|
||||
if adder == r.global.mapAdder {
|
||||
iter.iterate(func(item Value) {
|
||||
itemObj := r.toObject(item)
|
||||
k := nilSafe(itemObj.self.getIdx(i0, nil))
|
||||
v := nilSafe(itemObj.self.getIdx(i1, nil))
|
||||
mo.m.set(k, v)
|
||||
})
|
||||
} else {
|
||||
iter.iterate(func(item Value) {
|
||||
itemObj := r.toObject(item)
|
||||
k := itemObj.self.getIdx(i0, nil)
|
||||
v := itemObj.self.getIdx(i1, nil)
|
||||
adderFn(FunctionCall{This: o, Arguments: []Value{k, v}})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
func (r *Runtime) createMapIterator(mapValue Value, kind iterationKind) Value {
|
||||
obj := r.toObject(mapValue)
|
||||
mapObj, ok := obj.self.(*mapObject)
|
||||
if !ok {
|
||||
panic(r.NewTypeError("Object is not a Map"))
|
||||
}
|
||||
|
||||
o := &Object{runtime: r}
|
||||
|
||||
mi := &mapIterObject{
|
||||
iter: mapObj.m.newIter(),
|
||||
kind: kind,
|
||||
}
|
||||
mi.class = classObject
|
||||
mi.val = o
|
||||
mi.extensible = true
|
||||
o.self = mi
|
||||
mi.prototype = r.getMapIteratorPrototype()
|
||||
mi.init()
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
func (r *Runtime) mapIterProto_next(call FunctionCall) Value {
|
||||
thisObj := r.toObject(call.This)
|
||||
if iter, ok := thisObj.self.(*mapIterObject); ok {
|
||||
return iter.next()
|
||||
}
|
||||
panic(r.NewTypeError("Method Map Iterator.prototype.next called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
|
||||
}
|
||||
|
||||
func (r *Runtime) createMapProto(val *Object) objectImpl {
|
||||
o := newBaseObjectObj(val, r.global.ObjectPrototype, classObject)
|
||||
|
||||
o._putProp("constructor", r.global.Map, true, false, true)
|
||||
o._putProp("clear", r.newNativeFunc(r.mapProto_clear, nil, "clear", nil, 0), true, false, true)
|
||||
r.global.mapAdder = r.newNativeFunc(r.mapProto_set, nil, "set", nil, 2)
|
||||
o._putProp("set", r.global.mapAdder, true, false, true)
|
||||
o._putProp("delete", r.newNativeFunc(r.mapProto_delete, nil, "delete", nil, 1), true, false, true)
|
||||
o._putProp("forEach", r.newNativeFunc(r.mapProto_forEach, nil, "forEach", nil, 1), true, false, true)
|
||||
o._putProp("has", r.newNativeFunc(r.mapProto_has, nil, "has", nil, 1), true, false, true)
|
||||
o._putProp("get", r.newNativeFunc(r.mapProto_get, nil, "get", nil, 1), true, false, true)
|
||||
o.setOwnStr("size", &valueProperty{
|
||||
getterFunc: r.newNativeFunc(r.mapProto_getSize, nil, "get size", nil, 0),
|
||||
accessor: true,
|
||||
writable: true,
|
||||
configurable: true,
|
||||
}, true)
|
||||
o._putProp("keys", r.newNativeFunc(r.mapProto_keys, nil, "keys", nil, 0), true, false, true)
|
||||
o._putProp("values", r.newNativeFunc(r.mapProto_values, nil, "values", nil, 0), true, false, true)
|
||||
|
||||
entriesFunc := r.newNativeFunc(r.mapProto_entries, nil, "entries", nil, 0)
|
||||
o._putProp("entries", entriesFunc, true, false, true)
|
||||
o._putSym(SymIterator, valueProp(entriesFunc, true, false, true))
|
||||
o._putSym(SymToStringTag, valueProp(asciiString(classMap), false, false, true))
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
func (r *Runtime) createMap(val *Object) objectImpl {
|
||||
o := r.newNativeConstructOnly(val, r.builtin_newMap, r.global.MapPrototype, "Map", 0)
|
||||
r.putSpeciesReturnThis(o)
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
func (r *Runtime) createMapIterProto(val *Object) objectImpl {
|
||||
o := newBaseObjectObj(val, r.getIteratorPrototype(), classObject)
|
||||
|
||||
o._putProp("next", r.newNativeFunc(r.mapIterProto_next, nil, "next", nil, 0), true, false, true)
|
||||
o._putSym(SymToStringTag, valueProp(asciiString(classMapIterator), false, false, true))
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
func (r *Runtime) getMapIteratorPrototype() *Object {
|
||||
var o *Object
|
||||
if o = r.global.MapIteratorPrototype; o == nil {
|
||||
o = &Object{runtime: r}
|
||||
r.global.MapIteratorPrototype = o
|
||||
o.self = r.createMapIterProto(o)
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
func (r *Runtime) initMap() {
|
||||
r.global.MapIteratorPrototype = r.newLazyObject(r.createMapIterProto)
|
||||
|
||||
r.global.MapPrototype = r.newLazyObject(r.createMapProto)
|
||||
r.global.Map = r.newLazyObject(r.createMap)
|
||||
|
||||
r.addToGlobal("Map", r.global.Map)
|
||||
}
|
||||
343
server/vendor/github.com/dop251/goja/builtin_math.go
generated
vendored
Normal file
343
server/vendor/github.com/dop251/goja/builtin_math.go
generated
vendored
Normal file
@@ -0,0 +1,343 @@
|
||||
package goja
|
||||
|
||||
import (
|
||||
"math"
|
||||
"math/bits"
|
||||
)
|
||||
|
||||
func (r *Runtime) math_abs(call FunctionCall) Value {
|
||||
return floatToValue(math.Abs(call.Argument(0).ToFloat()))
|
||||
}
|
||||
|
||||
func (r *Runtime) math_acos(call FunctionCall) Value {
|
||||
return floatToValue(math.Acos(call.Argument(0).ToFloat()))
|
||||
}
|
||||
|
||||
func (r *Runtime) math_acosh(call FunctionCall) Value {
|
||||
return floatToValue(math.Acosh(call.Argument(0).ToFloat()))
|
||||
}
|
||||
|
||||
func (r *Runtime) math_asin(call FunctionCall) Value {
|
||||
return floatToValue(math.Asin(call.Argument(0).ToFloat()))
|
||||
}
|
||||
|
||||
func (r *Runtime) math_asinh(call FunctionCall) Value {
|
||||
return floatToValue(math.Asinh(call.Argument(0).ToFloat()))
|
||||
}
|
||||
|
||||
func (r *Runtime) math_atan(call FunctionCall) Value {
|
||||
return floatToValue(math.Atan(call.Argument(0).ToFloat()))
|
||||
}
|
||||
|
||||
func (r *Runtime) math_atanh(call FunctionCall) Value {
|
||||
return floatToValue(math.Atanh(call.Argument(0).ToFloat()))
|
||||
}
|
||||
|
||||
func (r *Runtime) math_atan2(call FunctionCall) Value {
|
||||
y := call.Argument(0).ToFloat()
|
||||
x := call.Argument(1).ToFloat()
|
||||
|
||||
return floatToValue(math.Atan2(y, x))
|
||||
}
|
||||
|
||||
func (r *Runtime) math_cbrt(call FunctionCall) Value {
|
||||
return floatToValue(math.Cbrt(call.Argument(0).ToFloat()))
|
||||
}
|
||||
|
||||
func (r *Runtime) math_ceil(call FunctionCall) Value {
|
||||
return floatToValue(math.Ceil(call.Argument(0).ToFloat()))
|
||||
}
|
||||
|
||||
func (r *Runtime) math_clz32(call FunctionCall) Value {
|
||||
return intToValue(int64(bits.LeadingZeros32(toUint32(call.Argument(0)))))
|
||||
}
|
||||
|
||||
func (r *Runtime) math_cos(call FunctionCall) Value {
|
||||
return floatToValue(math.Cos(call.Argument(0).ToFloat()))
|
||||
}
|
||||
|
||||
func (r *Runtime) math_cosh(call FunctionCall) Value {
|
||||
return floatToValue(math.Cosh(call.Argument(0).ToFloat()))
|
||||
}
|
||||
|
||||
func (r *Runtime) math_exp(call FunctionCall) Value {
|
||||
return floatToValue(math.Exp(call.Argument(0).ToFloat()))
|
||||
}
|
||||
|
||||
func (r *Runtime) math_expm1(call FunctionCall) Value {
|
||||
return floatToValue(math.Expm1(call.Argument(0).ToFloat()))
|
||||
}
|
||||
|
||||
func (r *Runtime) math_floor(call FunctionCall) Value {
|
||||
return floatToValue(math.Floor(call.Argument(0).ToFloat()))
|
||||
}
|
||||
|
||||
func (r *Runtime) math_fround(call FunctionCall) Value {
|
||||
return floatToValue(float64(float32(call.Argument(0).ToFloat())))
|
||||
}
|
||||
|
||||
func (r *Runtime) math_hypot(call FunctionCall) Value {
|
||||
var max float64
|
||||
var hasNaN bool
|
||||
absValues := make([]float64, 0, len(call.Arguments))
|
||||
for _, v := range call.Arguments {
|
||||
arg := nilSafe(v).ToFloat()
|
||||
if math.IsNaN(arg) {
|
||||
hasNaN = true
|
||||
} else {
|
||||
abs := math.Abs(arg)
|
||||
if abs > max {
|
||||
max = abs
|
||||
}
|
||||
absValues = append(absValues, abs)
|
||||
}
|
||||
}
|
||||
if math.IsInf(max, 1) {
|
||||
return _positiveInf
|
||||
}
|
||||
if hasNaN {
|
||||
return _NaN
|
||||
}
|
||||
if max == 0 {
|
||||
return _positiveZero
|
||||
}
|
||||
|
||||
// Kahan summation to avoid rounding errors.
|
||||
// Normalize the numbers to the largest one to avoid overflow.
|
||||
var sum, compensation float64
|
||||
for _, n := range absValues {
|
||||
n /= max
|
||||
summand := n*n - compensation
|
||||
preliminary := sum + summand
|
||||
compensation = (preliminary - sum) - summand
|
||||
sum = preliminary
|
||||
}
|
||||
return floatToValue(math.Sqrt(sum) * max)
|
||||
}
|
||||
|
||||
func (r *Runtime) math_imul(call FunctionCall) Value {
|
||||
x := toUint32(call.Argument(0))
|
||||
y := toUint32(call.Argument(1))
|
||||
return intToValue(int64(int32(x * y)))
|
||||
}
|
||||
|
||||
func (r *Runtime) math_log(call FunctionCall) Value {
|
||||
return floatToValue(math.Log(call.Argument(0).ToFloat()))
|
||||
}
|
||||
|
||||
func (r *Runtime) math_log1p(call FunctionCall) Value {
|
||||
return floatToValue(math.Log1p(call.Argument(0).ToFloat()))
|
||||
}
|
||||
|
||||
func (r *Runtime) math_log10(call FunctionCall) Value {
|
||||
return floatToValue(math.Log10(call.Argument(0).ToFloat()))
|
||||
}
|
||||
|
||||
func (r *Runtime) math_log2(call FunctionCall) Value {
|
||||
return floatToValue(math.Log2(call.Argument(0).ToFloat()))
|
||||
}
|
||||
|
||||
func (r *Runtime) math_max(call FunctionCall) Value {
|
||||
result := math.Inf(-1)
|
||||
args := call.Arguments
|
||||
for i, arg := range args {
|
||||
n := nilSafe(arg).ToFloat()
|
||||
if math.IsNaN(n) {
|
||||
args = args[i+1:]
|
||||
goto NaNLoop
|
||||
}
|
||||
result = math.Max(result, n)
|
||||
}
|
||||
|
||||
return floatToValue(result)
|
||||
|
||||
NaNLoop:
|
||||
// All arguments still need to be coerced to number according to the specs.
|
||||
for _, arg := range args {
|
||||
nilSafe(arg).ToFloat()
|
||||
}
|
||||
return _NaN
|
||||
}
|
||||
|
||||
func (r *Runtime) math_min(call FunctionCall) Value {
|
||||
result := math.Inf(1)
|
||||
args := call.Arguments
|
||||
for i, arg := range args {
|
||||
n := nilSafe(arg).ToFloat()
|
||||
if math.IsNaN(n) {
|
||||
args = args[i+1:]
|
||||
goto NaNLoop
|
||||
}
|
||||
result = math.Min(result, n)
|
||||
}
|
||||
|
||||
return floatToValue(result)
|
||||
|
||||
NaNLoop:
|
||||
// All arguments still need to be coerced to number according to the specs.
|
||||
for _, arg := range args {
|
||||
nilSafe(arg).ToFloat()
|
||||
}
|
||||
return _NaN
|
||||
}
|
||||
|
||||
func pow(x, y Value) Value {
|
||||
if x, ok := x.(valueInt); ok {
|
||||
if y, ok := y.(valueInt); ok && y >= 0 && y < 64 {
|
||||
if y == 0 {
|
||||
return intToValue(1)
|
||||
}
|
||||
if x == 0 {
|
||||
return intToValue(0)
|
||||
}
|
||||
ip := ipow(int64(x), int64(y))
|
||||
if ip != 0 {
|
||||
return intToValue(ip)
|
||||
}
|
||||
}
|
||||
}
|
||||
xf := x.ToFloat()
|
||||
yf := y.ToFloat()
|
||||
if math.Abs(xf) == 1 && math.IsInf(yf, 0) {
|
||||
return _NaN
|
||||
}
|
||||
if xf == 1 && math.IsNaN(yf) {
|
||||
return _NaN
|
||||
}
|
||||
return floatToValue(math.Pow(xf, yf))
|
||||
}
|
||||
|
||||
func (r *Runtime) math_pow(call FunctionCall) Value {
|
||||
return pow(call.Argument(0), call.Argument(1))
|
||||
}
|
||||
|
||||
func (r *Runtime) math_random(call FunctionCall) Value {
|
||||
return floatToValue(r.rand())
|
||||
}
|
||||
|
||||
func (r *Runtime) math_round(call FunctionCall) Value {
|
||||
f := call.Argument(0).ToFloat()
|
||||
if math.IsNaN(f) {
|
||||
return _NaN
|
||||
}
|
||||
|
||||
if f == 0 && math.Signbit(f) {
|
||||
return _negativeZero
|
||||
}
|
||||
|
||||
t := math.Trunc(f)
|
||||
|
||||
if f >= 0 {
|
||||
if f-t >= 0.5 {
|
||||
return floatToValue(t + 1)
|
||||
}
|
||||
} else {
|
||||
if t-f > 0.5 {
|
||||
return floatToValue(t - 1)
|
||||
}
|
||||
}
|
||||
|
||||
return floatToValue(t)
|
||||
}
|
||||
|
||||
func (r *Runtime) math_sign(call FunctionCall) Value {
|
||||
arg := call.Argument(0)
|
||||
num := arg.ToFloat()
|
||||
if math.IsNaN(num) || num == 0 { // this will match -0 too
|
||||
return arg
|
||||
}
|
||||
if num > 0 {
|
||||
return intToValue(1)
|
||||
}
|
||||
return intToValue(-1)
|
||||
}
|
||||
|
||||
func (r *Runtime) math_sin(call FunctionCall) Value {
|
||||
return floatToValue(math.Sin(call.Argument(0).ToFloat()))
|
||||
}
|
||||
|
||||
func (r *Runtime) math_sinh(call FunctionCall) Value {
|
||||
return floatToValue(math.Sinh(call.Argument(0).ToFloat()))
|
||||
}
|
||||
|
||||
func (r *Runtime) math_sqrt(call FunctionCall) Value {
|
||||
return floatToValue(math.Sqrt(call.Argument(0).ToFloat()))
|
||||
}
|
||||
|
||||
func (r *Runtime) math_tan(call FunctionCall) Value {
|
||||
return floatToValue(math.Tan(call.Argument(0).ToFloat()))
|
||||
}
|
||||
|
||||
func (r *Runtime) math_tanh(call FunctionCall) Value {
|
||||
return floatToValue(math.Tanh(call.Argument(0).ToFloat()))
|
||||
}
|
||||
|
||||
func (r *Runtime) math_trunc(call FunctionCall) Value {
|
||||
arg := call.Argument(0)
|
||||
if i, ok := arg.(valueInt); ok {
|
||||
return i
|
||||
}
|
||||
return floatToValue(math.Trunc(arg.ToFloat()))
|
||||
}
|
||||
|
||||
func (r *Runtime) createMath(val *Object) objectImpl {
|
||||
m := &baseObject{
|
||||
class: classObject,
|
||||
val: val,
|
||||
extensible: true,
|
||||
prototype: r.global.ObjectPrototype,
|
||||
}
|
||||
m.init()
|
||||
|
||||
m._putProp("E", valueFloat(math.E), false, false, false)
|
||||
m._putProp("LN10", valueFloat(math.Ln10), false, false, false)
|
||||
m._putProp("LN2", valueFloat(math.Ln2), false, false, false)
|
||||
m._putProp("LOG10E", valueFloat(math.Log10E), false, false, false)
|
||||
m._putProp("LOG2E", valueFloat(math.Log2E), false, false, false)
|
||||
m._putProp("PI", valueFloat(math.Pi), false, false, false)
|
||||
m._putProp("SQRT1_2", valueFloat(sqrt1_2), false, false, false)
|
||||
m._putProp("SQRT2", valueFloat(math.Sqrt2), false, false, false)
|
||||
m._putSym(SymToStringTag, valueProp(asciiString(classMath), false, false, true))
|
||||
|
||||
m._putProp("abs", r.newNativeFunc(r.math_abs, nil, "abs", nil, 1), true, false, true)
|
||||
m._putProp("acos", r.newNativeFunc(r.math_acos, nil, "acos", nil, 1), true, false, true)
|
||||
m._putProp("acosh", r.newNativeFunc(r.math_acosh, nil, "acosh", nil, 1), true, false, true)
|
||||
m._putProp("asin", r.newNativeFunc(r.math_asin, nil, "asin", nil, 1), true, false, true)
|
||||
m._putProp("asinh", r.newNativeFunc(r.math_asinh, nil, "asinh", nil, 1), true, false, true)
|
||||
m._putProp("atan", r.newNativeFunc(r.math_atan, nil, "atan", nil, 1), true, false, true)
|
||||
m._putProp("atanh", r.newNativeFunc(r.math_atanh, nil, "atanh", nil, 1), true, false, true)
|
||||
m._putProp("atan2", r.newNativeFunc(r.math_atan2, nil, "atan2", nil, 2), true, false, true)
|
||||
m._putProp("cbrt", r.newNativeFunc(r.math_cbrt, nil, "cbrt", nil, 1), true, false, true)
|
||||
m._putProp("ceil", r.newNativeFunc(r.math_ceil, nil, "ceil", nil, 1), true, false, true)
|
||||
m._putProp("clz32", r.newNativeFunc(r.math_clz32, nil, "clz32", nil, 1), true, false, true)
|
||||
m._putProp("cos", r.newNativeFunc(r.math_cos, nil, "cos", nil, 1), true, false, true)
|
||||
m._putProp("cosh", r.newNativeFunc(r.math_cosh, nil, "cosh", nil, 1), true, false, true)
|
||||
m._putProp("exp", r.newNativeFunc(r.math_exp, nil, "exp", nil, 1), true, false, true)
|
||||
m._putProp("expm1", r.newNativeFunc(r.math_expm1, nil, "expm1", nil, 1), true, false, true)
|
||||
m._putProp("floor", r.newNativeFunc(r.math_floor, nil, "floor", nil, 1), true, false, true)
|
||||
m._putProp("fround", r.newNativeFunc(r.math_fround, nil, "fround", nil, 1), true, false, true)
|
||||
m._putProp("hypot", r.newNativeFunc(r.math_hypot, nil, "hypot", nil, 2), true, false, true)
|
||||
m._putProp("imul", r.newNativeFunc(r.math_imul, nil, "imul", nil, 2), true, false, true)
|
||||
m._putProp("log", r.newNativeFunc(r.math_log, nil, "log", nil, 1), true, false, true)
|
||||
m._putProp("log1p", r.newNativeFunc(r.math_log1p, nil, "log1p", nil, 1), true, false, true)
|
||||
m._putProp("log10", r.newNativeFunc(r.math_log10, nil, "log10", nil, 1), true, false, true)
|
||||
m._putProp("log2", r.newNativeFunc(r.math_log2, nil, "log2", nil, 1), true, false, true)
|
||||
m._putProp("max", r.newNativeFunc(r.math_max, nil, "max", nil, 2), true, false, true)
|
||||
m._putProp("min", r.newNativeFunc(r.math_min, nil, "min", nil, 2), true, false, true)
|
||||
m._putProp("pow", r.newNativeFunc(r.math_pow, nil, "pow", nil, 2), true, false, true)
|
||||
m._putProp("random", r.newNativeFunc(r.math_random, nil, "random", nil, 0), true, false, true)
|
||||
m._putProp("round", r.newNativeFunc(r.math_round, nil, "round", nil, 1), true, false, true)
|
||||
m._putProp("sign", r.newNativeFunc(r.math_sign, nil, "sign", nil, 1), true, false, true)
|
||||
m._putProp("sin", r.newNativeFunc(r.math_sin, nil, "sin", nil, 1), true, false, true)
|
||||
m._putProp("sinh", r.newNativeFunc(r.math_sinh, nil, "sinh", nil, 1), true, false, true)
|
||||
m._putProp("sqrt", r.newNativeFunc(r.math_sqrt, nil, "sqrt", nil, 1), true, false, true)
|
||||
m._putProp("tan", r.newNativeFunc(r.math_tan, nil, "tan", nil, 1), true, false, true)
|
||||
m._putProp("tanh", r.newNativeFunc(r.math_tanh, nil, "tanh", nil, 1), true, false, true)
|
||||
m._putProp("trunc", r.newNativeFunc(r.math_trunc, nil, "trunc", nil, 1), true, false, true)
|
||||
|
||||
return m
|
||||
}
|
||||
|
||||
func (r *Runtime) initMath() {
|
||||
r.addToGlobal("Math", r.newLazyObject(r.createMath))
|
||||
}
|
||||
210
server/vendor/github.com/dop251/goja/builtin_number.go
generated
vendored
Normal file
210
server/vendor/github.com/dop251/goja/builtin_number.go
generated
vendored
Normal file
@@ -0,0 +1,210 @@
|
||||
package goja
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"github.com/dop251/goja/ftoa"
|
||||
)
|
||||
|
||||
func (r *Runtime) numberproto_valueOf(call FunctionCall) Value {
|
||||
this := call.This
|
||||
if !isNumber(this) {
|
||||
r.typeErrorResult(true, "Value is not a number")
|
||||
}
|
||||
switch t := this.(type) {
|
||||
case valueInt, valueFloat:
|
||||
return this
|
||||
case *Object:
|
||||
if v, ok := t.self.(*primitiveValueObject); ok {
|
||||
return v.pValue
|
||||
}
|
||||
}
|
||||
|
||||
panic(r.NewTypeError("Number.prototype.valueOf is not generic"))
|
||||
}
|
||||
|
||||
func isNumber(v Value) bool {
|
||||
switch t := v.(type) {
|
||||
case valueFloat, valueInt:
|
||||
return true
|
||||
case *Object:
|
||||
switch t := t.self.(type) {
|
||||
case *primitiveValueObject:
|
||||
return isNumber(t.pValue)
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (r *Runtime) numberproto_toString(call FunctionCall) Value {
|
||||
if !isNumber(call.This) {
|
||||
r.typeErrorResult(true, "Value is not a number")
|
||||
}
|
||||
var radix int
|
||||
if arg := call.Argument(0); arg != _undefined {
|
||||
radix = int(arg.ToInteger())
|
||||
} else {
|
||||
radix = 10
|
||||
}
|
||||
|
||||
if radix < 2 || radix > 36 {
|
||||
panic(r.newError(r.global.RangeError, "toString() radix argument must be between 2 and 36"))
|
||||
}
|
||||
|
||||
num := call.This.ToFloat()
|
||||
|
||||
if math.IsNaN(num) {
|
||||
return stringNaN
|
||||
}
|
||||
|
||||
if math.IsInf(num, 1) {
|
||||
return stringInfinity
|
||||
}
|
||||
|
||||
if math.IsInf(num, -1) {
|
||||
return stringNegInfinity
|
||||
}
|
||||
|
||||
if radix == 10 {
|
||||
return asciiString(fToStr(num, ftoa.ModeStandard, 0))
|
||||
}
|
||||
|
||||
return asciiString(ftoa.FToBaseStr(num, radix))
|
||||
}
|
||||
|
||||
func (r *Runtime) numberproto_toFixed(call FunctionCall) Value {
|
||||
num := r.toNumber(call.This).ToFloat()
|
||||
prec := call.Argument(0).ToInteger()
|
||||
|
||||
if prec < 0 || prec > 100 {
|
||||
panic(r.newError(r.global.RangeError, "toFixed() precision must be between 0 and 100"))
|
||||
}
|
||||
if math.IsNaN(num) {
|
||||
return stringNaN
|
||||
}
|
||||
return asciiString(fToStr(num, ftoa.ModeFixed, int(prec)))
|
||||
}
|
||||
|
||||
func (r *Runtime) numberproto_toExponential(call FunctionCall) Value {
|
||||
num := r.toNumber(call.This).ToFloat()
|
||||
precVal := call.Argument(0)
|
||||
var prec int64
|
||||
if precVal == _undefined {
|
||||
return asciiString(fToStr(num, ftoa.ModeStandardExponential, 0))
|
||||
} else {
|
||||
prec = precVal.ToInteger()
|
||||
}
|
||||
|
||||
if math.IsNaN(num) {
|
||||
return stringNaN
|
||||
}
|
||||
if math.IsInf(num, 1) {
|
||||
return stringInfinity
|
||||
}
|
||||
if math.IsInf(num, -1) {
|
||||
return stringNegInfinity
|
||||
}
|
||||
|
||||
if prec < 0 || prec > 100 {
|
||||
panic(r.newError(r.global.RangeError, "toExponential() precision must be between 0 and 100"))
|
||||
}
|
||||
|
||||
return asciiString(fToStr(num, ftoa.ModeExponential, int(prec+1)))
|
||||
}
|
||||
|
||||
func (r *Runtime) numberproto_toPrecision(call FunctionCall) Value {
|
||||
numVal := r.toNumber(call.This)
|
||||
precVal := call.Argument(0)
|
||||
if precVal == _undefined {
|
||||
return numVal.toString()
|
||||
}
|
||||
num := numVal.ToFloat()
|
||||
prec := precVal.ToInteger()
|
||||
|
||||
if math.IsNaN(num) {
|
||||
return stringNaN
|
||||
}
|
||||
if math.IsInf(num, 1) {
|
||||
return stringInfinity
|
||||
}
|
||||
if math.IsInf(num, -1) {
|
||||
return stringNegInfinity
|
||||
}
|
||||
if prec < 1 || prec > 100 {
|
||||
panic(r.newError(r.global.RangeError, "toPrecision() precision must be between 1 and 100"))
|
||||
}
|
||||
|
||||
return asciiString(fToStr(num, ftoa.ModePrecision, int(prec)))
|
||||
}
|
||||
|
||||
func (r *Runtime) number_isFinite(call FunctionCall) Value {
|
||||
switch arg := call.Argument(0).(type) {
|
||||
case valueInt:
|
||||
return valueTrue
|
||||
case valueFloat:
|
||||
f := float64(arg)
|
||||
return r.toBoolean(!math.IsInf(f, 0) && !math.IsNaN(f))
|
||||
default:
|
||||
return valueFalse
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Runtime) number_isInteger(call FunctionCall) Value {
|
||||
switch arg := call.Argument(0).(type) {
|
||||
case valueInt:
|
||||
return valueTrue
|
||||
case valueFloat:
|
||||
f := float64(arg)
|
||||
return r.toBoolean(!math.IsNaN(f) && !math.IsInf(f, 0) && math.Floor(f) == f)
|
||||
default:
|
||||
return valueFalse
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Runtime) number_isNaN(call FunctionCall) Value {
|
||||
if f, ok := call.Argument(0).(valueFloat); ok && math.IsNaN(float64(f)) {
|
||||
return valueTrue
|
||||
}
|
||||
return valueFalse
|
||||
}
|
||||
|
||||
func (r *Runtime) number_isSafeInteger(call FunctionCall) Value {
|
||||
arg := call.Argument(0)
|
||||
if i, ok := arg.(valueInt); ok && i >= -(maxInt-1) && i <= maxInt-1 {
|
||||
return valueTrue
|
||||
}
|
||||
if arg == _negativeZero {
|
||||
return valueTrue
|
||||
}
|
||||
return valueFalse
|
||||
}
|
||||
|
||||
func (r *Runtime) initNumber() {
|
||||
r.global.NumberPrototype = r.newPrimitiveObject(valueInt(0), r.global.ObjectPrototype, classNumber)
|
||||
o := r.global.NumberPrototype.self
|
||||
o._putProp("toExponential", r.newNativeFunc(r.numberproto_toExponential, nil, "toExponential", nil, 1), true, false, true)
|
||||
o._putProp("toFixed", r.newNativeFunc(r.numberproto_toFixed, nil, "toFixed", nil, 1), true, false, true)
|
||||
o._putProp("toLocaleString", r.newNativeFunc(r.numberproto_toString, nil, "toLocaleString", nil, 0), true, false, true)
|
||||
o._putProp("toPrecision", r.newNativeFunc(r.numberproto_toPrecision, nil, "toPrecision", nil, 1), true, false, true)
|
||||
o._putProp("toString", r.newNativeFunc(r.numberproto_toString, nil, "toString", nil, 1), true, false, true)
|
||||
o._putProp("valueOf", r.newNativeFunc(r.numberproto_valueOf, nil, "valueOf", nil, 0), true, false, true)
|
||||
|
||||
r.global.Number = r.newNativeFunc(r.builtin_Number, r.builtin_newNumber, "Number", r.global.NumberPrototype, 1)
|
||||
o = r.global.Number.self
|
||||
o._putProp("EPSILON", _epsilon, false, false, false)
|
||||
o._putProp("isFinite", r.newNativeFunc(r.number_isFinite, nil, "isFinite", nil, 1), true, false, true)
|
||||
o._putProp("isInteger", r.newNativeFunc(r.number_isInteger, nil, "isInteger", nil, 1), true, false, true)
|
||||
o._putProp("isNaN", r.newNativeFunc(r.number_isNaN, nil, "isNaN", nil, 1), true, false, true)
|
||||
o._putProp("isSafeInteger", r.newNativeFunc(r.number_isSafeInteger, nil, "isSafeInteger", nil, 1), true, false, true)
|
||||
o._putProp("MAX_SAFE_INTEGER", valueInt(maxInt-1), false, false, false)
|
||||
o._putProp("MIN_SAFE_INTEGER", valueInt(-(maxInt - 1)), false, false, false)
|
||||
o._putProp("MIN_VALUE", valueFloat(math.SmallestNonzeroFloat64), false, false, false)
|
||||
o._putProp("MAX_VALUE", valueFloat(math.MaxFloat64), false, false, false)
|
||||
o._putProp("NaN", _NaN, false, false, false)
|
||||
o._putProp("NEGATIVE_INFINITY", _negativeInf, false, false, false)
|
||||
o._putProp("parseFloat", r.Get("parseFloat"), true, false, true)
|
||||
o._putProp("parseInt", r.Get("parseInt"), true, false, true)
|
||||
o._putProp("POSITIVE_INFINITY", _positiveInf, false, false, false)
|
||||
r.addToGlobal("Number", r.global.Number)
|
||||
|
||||
}
|
||||
634
server/vendor/github.com/dop251/goja/builtin_object.go
generated
vendored
Normal file
634
server/vendor/github.com/dop251/goja/builtin_object.go
generated
vendored
Normal file
@@ -0,0 +1,634 @@
|
||||
package goja
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func (r *Runtime) builtin_Object(args []Value, newTarget *Object) *Object {
|
||||
if newTarget != nil && newTarget != r.global.Object {
|
||||
proto := r.getPrototypeFromCtor(newTarget, nil, r.global.ObjectPrototype)
|
||||
return r.newBaseObject(proto, classObject).val
|
||||
}
|
||||
if len(args) > 0 {
|
||||
arg := args[0]
|
||||
if arg != _undefined && arg != _null {
|
||||
return arg.ToObject(r)
|
||||
}
|
||||
}
|
||||
return r.NewObject()
|
||||
}
|
||||
|
||||
func (r *Runtime) object_getPrototypeOf(call FunctionCall) Value {
|
||||
o := call.Argument(0).ToObject(r)
|
||||
p := o.self.proto()
|
||||
if p == nil {
|
||||
return _null
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
func (r *Runtime) valuePropToDescriptorObject(desc Value) Value {
|
||||
if desc == nil {
|
||||
return _undefined
|
||||
}
|
||||
var writable, configurable, enumerable, accessor bool
|
||||
var get, set *Object
|
||||
var value Value
|
||||
if v, ok := desc.(*valueProperty); ok {
|
||||
writable = v.writable
|
||||
configurable = v.configurable
|
||||
enumerable = v.enumerable
|
||||
accessor = v.accessor
|
||||
value = v.value
|
||||
get = v.getterFunc
|
||||
set = v.setterFunc
|
||||
} else {
|
||||
writable = true
|
||||
configurable = true
|
||||
enumerable = true
|
||||
value = desc
|
||||
}
|
||||
|
||||
ret := r.NewObject()
|
||||
obj := ret.self
|
||||
if !accessor {
|
||||
obj.setOwnStr("value", value, false)
|
||||
obj.setOwnStr("writable", r.toBoolean(writable), false)
|
||||
} else {
|
||||
if get != nil {
|
||||
obj.setOwnStr("get", get, false)
|
||||
} else {
|
||||
obj.setOwnStr("get", _undefined, false)
|
||||
}
|
||||
if set != nil {
|
||||
obj.setOwnStr("set", set, false)
|
||||
} else {
|
||||
obj.setOwnStr("set", _undefined, false)
|
||||
}
|
||||
}
|
||||
obj.setOwnStr("enumerable", r.toBoolean(enumerable), false)
|
||||
obj.setOwnStr("configurable", r.toBoolean(configurable), false)
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func (r *Runtime) object_getOwnPropertyDescriptor(call FunctionCall) Value {
|
||||
o := call.Argument(0).ToObject(r)
|
||||
propName := toPropertyKey(call.Argument(1))
|
||||
return r.valuePropToDescriptorObject(o.getOwnProp(propName))
|
||||
}
|
||||
|
||||
func (r *Runtime) object_getOwnPropertyDescriptors(call FunctionCall) Value {
|
||||
o := call.Argument(0).ToObject(r)
|
||||
result := r.newBaseObject(r.global.ObjectPrototype, classObject).val
|
||||
for item, next := o.self.iterateKeys()(); next != nil; item, next = next() {
|
||||
var prop Value
|
||||
if item.value == nil {
|
||||
prop = o.getOwnProp(item.name)
|
||||
if prop == nil {
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
prop = item.value
|
||||
}
|
||||
descriptor := r.valuePropToDescriptorObject(prop)
|
||||
if descriptor != _undefined {
|
||||
createDataPropertyOrThrow(result, item.name, descriptor)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (r *Runtime) object_getOwnPropertyNames(call FunctionCall) Value {
|
||||
obj := call.Argument(0).ToObject(r)
|
||||
|
||||
return r.newArrayValues(obj.self.stringKeys(true, nil))
|
||||
}
|
||||
|
||||
func (r *Runtime) object_getOwnPropertySymbols(call FunctionCall) Value {
|
||||
obj := call.Argument(0).ToObject(r)
|
||||
return r.newArrayValues(obj.self.symbols(true, nil))
|
||||
}
|
||||
|
||||
func (r *Runtime) toValueProp(v Value) *valueProperty {
|
||||
if v == nil || v == _undefined {
|
||||
return nil
|
||||
}
|
||||
obj := r.toObject(v)
|
||||
getter := obj.self.getStr("get", nil)
|
||||
setter := obj.self.getStr("set", nil)
|
||||
writable := obj.self.getStr("writable", nil)
|
||||
value := obj.self.getStr("value", nil)
|
||||
if (getter != nil || setter != nil) && (value != nil || writable != nil) {
|
||||
r.typeErrorResult(true, "Invalid property descriptor. Cannot both specify accessors and a value or writable attribute")
|
||||
}
|
||||
|
||||
ret := &valueProperty{}
|
||||
if writable != nil && writable.ToBoolean() {
|
||||
ret.writable = true
|
||||
}
|
||||
if e := obj.self.getStr("enumerable", nil); e != nil && e.ToBoolean() {
|
||||
ret.enumerable = true
|
||||
}
|
||||
if c := obj.self.getStr("configurable", nil); c != nil && c.ToBoolean() {
|
||||
ret.configurable = true
|
||||
}
|
||||
ret.value = value
|
||||
|
||||
if getter != nil && getter != _undefined {
|
||||
o := r.toObject(getter)
|
||||
if _, ok := o.self.assertCallable(); !ok {
|
||||
r.typeErrorResult(true, "getter must be a function")
|
||||
}
|
||||
ret.getterFunc = o
|
||||
}
|
||||
|
||||
if setter != nil && setter != _undefined {
|
||||
o := r.toObject(setter)
|
||||
if _, ok := o.self.assertCallable(); !ok {
|
||||
r.typeErrorResult(true, "setter must be a function")
|
||||
}
|
||||
ret.setterFunc = o
|
||||
}
|
||||
|
||||
if ret.getterFunc != nil || ret.setterFunc != nil {
|
||||
ret.accessor = true
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func (r *Runtime) toPropertyDescriptor(v Value) (ret PropertyDescriptor) {
|
||||
if o, ok := v.(*Object); ok {
|
||||
descr := o.self
|
||||
|
||||
// Save the original descriptor for reference
|
||||
ret.jsDescriptor = o
|
||||
|
||||
ret.Value = descr.getStr("value", nil)
|
||||
|
||||
if p := descr.getStr("writable", nil); p != nil {
|
||||
ret.Writable = ToFlag(p.ToBoolean())
|
||||
}
|
||||
if p := descr.getStr("enumerable", nil); p != nil {
|
||||
ret.Enumerable = ToFlag(p.ToBoolean())
|
||||
}
|
||||
if p := descr.getStr("configurable", nil); p != nil {
|
||||
ret.Configurable = ToFlag(p.ToBoolean())
|
||||
}
|
||||
|
||||
ret.Getter = descr.getStr("get", nil)
|
||||
ret.Setter = descr.getStr("set", nil)
|
||||
|
||||
if ret.Getter != nil && ret.Getter != _undefined {
|
||||
if _, ok := r.toObject(ret.Getter).self.assertCallable(); !ok {
|
||||
r.typeErrorResult(true, "getter must be a function")
|
||||
}
|
||||
}
|
||||
|
||||
if ret.Setter != nil && ret.Setter != _undefined {
|
||||
if _, ok := r.toObject(ret.Setter).self.assertCallable(); !ok {
|
||||
r.typeErrorResult(true, "setter must be a function")
|
||||
}
|
||||
}
|
||||
|
||||
if (ret.Getter != nil || ret.Setter != nil) && (ret.Value != nil || ret.Writable != FLAG_NOT_SET) {
|
||||
r.typeErrorResult(true, "Invalid property descriptor. Cannot both specify accessors and a value or writable attribute")
|
||||
}
|
||||
} else {
|
||||
r.typeErrorResult(true, "Property description must be an object: %s", v.String())
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (r *Runtime) _defineProperties(o *Object, p Value) {
|
||||
type propItem struct {
|
||||
name Value
|
||||
prop PropertyDescriptor
|
||||
}
|
||||
props := p.ToObject(r)
|
||||
var list []propItem
|
||||
for item, next := iterateEnumerableProperties(props)(); next != nil; item, next = next() {
|
||||
list = append(list, propItem{
|
||||
name: item.name,
|
||||
prop: r.toPropertyDescriptor(item.value),
|
||||
})
|
||||
}
|
||||
for _, prop := range list {
|
||||
o.defineOwnProperty(prop.name, prop.prop, true)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Runtime) object_create(call FunctionCall) Value {
|
||||
var proto *Object
|
||||
if arg := call.Argument(0); arg != _null {
|
||||
if o, ok := arg.(*Object); ok {
|
||||
proto = o
|
||||
} else {
|
||||
r.typeErrorResult(true, "Object prototype may only be an Object or null: %s", arg.String())
|
||||
}
|
||||
}
|
||||
o := r.newBaseObject(proto, classObject).val
|
||||
|
||||
if props := call.Argument(1); props != _undefined {
|
||||
r._defineProperties(o, props)
|
||||
}
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
func (r *Runtime) object_defineProperty(call FunctionCall) (ret Value) {
|
||||
if obj, ok := call.Argument(0).(*Object); ok {
|
||||
descr := r.toPropertyDescriptor(call.Argument(2))
|
||||
obj.defineOwnProperty(toPropertyKey(call.Argument(1)), descr, true)
|
||||
ret = call.Argument(0)
|
||||
} else {
|
||||
r.typeErrorResult(true, "Object.defineProperty called on non-object")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (r *Runtime) object_defineProperties(call FunctionCall) Value {
|
||||
obj := r.toObject(call.Argument(0))
|
||||
r._defineProperties(obj, call.Argument(1))
|
||||
return obj
|
||||
}
|
||||
|
||||
func (r *Runtime) object_seal(call FunctionCall) Value {
|
||||
// ES6
|
||||
arg := call.Argument(0)
|
||||
if obj, ok := arg.(*Object); ok {
|
||||
obj.self.preventExtensions(true)
|
||||
descr := PropertyDescriptor{
|
||||
Configurable: FLAG_FALSE,
|
||||
}
|
||||
|
||||
for item, next := obj.self.iterateKeys()(); next != nil; item, next = next() {
|
||||
if prop, ok := item.value.(*valueProperty); ok {
|
||||
prop.configurable = false
|
||||
} else {
|
||||
obj.defineOwnProperty(item.name, descr, true)
|
||||
}
|
||||
}
|
||||
|
||||
return obj
|
||||
}
|
||||
return arg
|
||||
}
|
||||
|
||||
func (r *Runtime) object_freeze(call FunctionCall) Value {
|
||||
arg := call.Argument(0)
|
||||
if obj, ok := arg.(*Object); ok {
|
||||
obj.self.preventExtensions(true)
|
||||
|
||||
for item, next := obj.self.iterateKeys()(); next != nil; item, next = next() {
|
||||
if prop, ok := item.value.(*valueProperty); ok {
|
||||
prop.configurable = false
|
||||
if !prop.accessor {
|
||||
prop.writable = false
|
||||
}
|
||||
} else {
|
||||
prop := obj.getOwnProp(item.name)
|
||||
descr := PropertyDescriptor{
|
||||
Configurable: FLAG_FALSE,
|
||||
}
|
||||
if prop, ok := prop.(*valueProperty); ok && prop.accessor {
|
||||
// no-op
|
||||
} else {
|
||||
descr.Writable = FLAG_FALSE
|
||||
}
|
||||
obj.defineOwnProperty(item.name, descr, true)
|
||||
}
|
||||
}
|
||||
return obj
|
||||
} else {
|
||||
// ES6 behavior
|
||||
return arg
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Runtime) object_preventExtensions(call FunctionCall) (ret Value) {
|
||||
arg := call.Argument(0)
|
||||
if obj, ok := arg.(*Object); ok {
|
||||
obj.self.preventExtensions(true)
|
||||
}
|
||||
return arg
|
||||
}
|
||||
|
||||
func (r *Runtime) object_isSealed(call FunctionCall) Value {
|
||||
if obj, ok := call.Argument(0).(*Object); ok {
|
||||
if obj.self.isExtensible() {
|
||||
return valueFalse
|
||||
}
|
||||
for item, next := obj.self.iterateKeys()(); next != nil; item, next = next() {
|
||||
var prop Value
|
||||
if item.value == nil {
|
||||
prop = obj.getOwnProp(item.name)
|
||||
if prop == nil {
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
prop = item.value
|
||||
}
|
||||
if prop, ok := prop.(*valueProperty); ok {
|
||||
if prop.configurable {
|
||||
return valueFalse
|
||||
}
|
||||
} else {
|
||||
return valueFalse
|
||||
}
|
||||
}
|
||||
}
|
||||
return valueTrue
|
||||
}
|
||||
|
||||
func (r *Runtime) object_isFrozen(call FunctionCall) Value {
|
||||
if obj, ok := call.Argument(0).(*Object); ok {
|
||||
if obj.self.isExtensible() {
|
||||
return valueFalse
|
||||
}
|
||||
for item, next := obj.self.iterateKeys()(); next != nil; item, next = next() {
|
||||
var prop Value
|
||||
if item.value == nil {
|
||||
prop = obj.getOwnProp(item.name)
|
||||
if prop == nil {
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
prop = item.value
|
||||
}
|
||||
if prop, ok := prop.(*valueProperty); ok {
|
||||
if prop.configurable || prop.value != nil && prop.writable {
|
||||
return valueFalse
|
||||
}
|
||||
} else {
|
||||
return valueFalse
|
||||
}
|
||||
}
|
||||
}
|
||||
return valueTrue
|
||||
}
|
||||
|
||||
func (r *Runtime) object_isExtensible(call FunctionCall) Value {
|
||||
if obj, ok := call.Argument(0).(*Object); ok {
|
||||
if obj.self.isExtensible() {
|
||||
return valueTrue
|
||||
}
|
||||
return valueFalse
|
||||
} else {
|
||||
// ES6
|
||||
//r.typeErrorResult(true, "Object.isExtensible called on non-object")
|
||||
return valueFalse
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Runtime) object_keys(call FunctionCall) Value {
|
||||
obj := call.Argument(0).ToObject(r)
|
||||
|
||||
return r.newArrayValues(obj.self.stringKeys(false, nil))
|
||||
}
|
||||
|
||||
func (r *Runtime) object_entries(call FunctionCall) Value {
|
||||
obj := call.Argument(0).ToObject(r)
|
||||
|
||||
var values []Value
|
||||
|
||||
for item, next := iterateEnumerableStringProperties(obj)(); next != nil; item, next = next() {
|
||||
values = append(values, r.newArrayValues([]Value{item.name, item.value}))
|
||||
}
|
||||
|
||||
return r.newArrayValues(values)
|
||||
}
|
||||
|
||||
func (r *Runtime) object_values(call FunctionCall) Value {
|
||||
obj := call.Argument(0).ToObject(r)
|
||||
|
||||
var values []Value
|
||||
|
||||
for item, next := iterateEnumerableStringProperties(obj)(); next != nil; item, next = next() {
|
||||
values = append(values, item.value)
|
||||
}
|
||||
|
||||
return r.newArrayValues(values)
|
||||
}
|
||||
|
||||
func (r *Runtime) objectproto_hasOwnProperty(call FunctionCall) Value {
|
||||
p := toPropertyKey(call.Argument(0))
|
||||
o := call.This.ToObject(r)
|
||||
if o.hasOwnProperty(p) {
|
||||
return valueTrue
|
||||
} else {
|
||||
return valueFalse
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Runtime) objectproto_isPrototypeOf(call FunctionCall) Value {
|
||||
if v, ok := call.Argument(0).(*Object); ok {
|
||||
o := call.This.ToObject(r)
|
||||
for {
|
||||
v = v.self.proto()
|
||||
if v == nil {
|
||||
break
|
||||
}
|
||||
if v == o {
|
||||
return valueTrue
|
||||
}
|
||||
}
|
||||
}
|
||||
return valueFalse
|
||||
}
|
||||
|
||||
func (r *Runtime) objectproto_propertyIsEnumerable(call FunctionCall) Value {
|
||||
p := toPropertyKey(call.Argument(0))
|
||||
o := call.This.ToObject(r)
|
||||
pv := o.getOwnProp(p)
|
||||
if pv == nil {
|
||||
return valueFalse
|
||||
}
|
||||
if prop, ok := pv.(*valueProperty); ok {
|
||||
if !prop.enumerable {
|
||||
return valueFalse
|
||||
}
|
||||
}
|
||||
return valueTrue
|
||||
}
|
||||
|
||||
func (r *Runtime) objectproto_toString(call FunctionCall) Value {
|
||||
switch o := call.This.(type) {
|
||||
case valueNull:
|
||||
return stringObjectNull
|
||||
case valueUndefined:
|
||||
return stringObjectUndefined
|
||||
default:
|
||||
obj := o.ToObject(r)
|
||||
var clsName string
|
||||
if isArray(obj) {
|
||||
clsName = classArray
|
||||
} else {
|
||||
clsName = obj.self.className()
|
||||
}
|
||||
if tag := obj.self.getSym(SymToStringTag, nil); tag != nil {
|
||||
if str, ok := tag.(valueString); ok {
|
||||
clsName = str.String()
|
||||
}
|
||||
}
|
||||
return newStringValue(fmt.Sprintf("[object %s]", clsName))
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Runtime) objectproto_toLocaleString(call FunctionCall) Value {
|
||||
toString := toMethod(r.getVStr(call.This, "toString"))
|
||||
return toString(FunctionCall{This: call.This})
|
||||
}
|
||||
|
||||
func (r *Runtime) objectproto_getProto(call FunctionCall) Value {
|
||||
proto := call.This.ToObject(r).self.proto()
|
||||
if proto != nil {
|
||||
return proto
|
||||
}
|
||||
return _null
|
||||
}
|
||||
|
||||
func (r *Runtime) setObjectProto(o, arg Value) {
|
||||
r.checkObjectCoercible(o)
|
||||
var proto *Object
|
||||
if arg != _null {
|
||||
if obj, ok := arg.(*Object); ok {
|
||||
proto = obj
|
||||
} else {
|
||||
return
|
||||
}
|
||||
}
|
||||
if o, ok := o.(*Object); ok {
|
||||
o.self.setProto(proto, true)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Runtime) objectproto_setProto(call FunctionCall) Value {
|
||||
r.setObjectProto(call.This, call.Argument(0))
|
||||
return _undefined
|
||||
}
|
||||
|
||||
func (r *Runtime) objectproto_valueOf(call FunctionCall) Value {
|
||||
return call.This.ToObject(r)
|
||||
}
|
||||
|
||||
func (r *Runtime) object_assign(call FunctionCall) Value {
|
||||
to := call.Argument(0).ToObject(r)
|
||||
if len(call.Arguments) > 1 {
|
||||
for _, arg := range call.Arguments[1:] {
|
||||
if arg != _undefined && arg != _null {
|
||||
source := arg.ToObject(r)
|
||||
for item, next := iterateEnumerableProperties(source)(); next != nil; item, next = next() {
|
||||
to.setOwn(item.name, item.value, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return to
|
||||
}
|
||||
|
||||
func (r *Runtime) object_is(call FunctionCall) Value {
|
||||
return r.toBoolean(call.Argument(0).SameAs(call.Argument(1)))
|
||||
}
|
||||
|
||||
func (r *Runtime) toProto(proto Value) *Object {
|
||||
if proto != _null {
|
||||
if obj, ok := proto.(*Object); ok {
|
||||
return obj
|
||||
} else {
|
||||
panic(r.NewTypeError("Object prototype may only be an Object or null: %s", proto))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Runtime) object_setPrototypeOf(call FunctionCall) Value {
|
||||
o := call.Argument(0)
|
||||
r.checkObjectCoercible(o)
|
||||
proto := r.toProto(call.Argument(1))
|
||||
if o, ok := o.(*Object); ok {
|
||||
o.self.setProto(proto, true)
|
||||
}
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
func (r *Runtime) object_fromEntries(call FunctionCall) Value {
|
||||
o := call.Argument(0)
|
||||
r.checkObjectCoercible(o)
|
||||
|
||||
result := r.newBaseObject(r.global.ObjectPrototype, classObject).val
|
||||
|
||||
iter := r.getIterator(o, nil)
|
||||
iter.iterate(func(nextValue Value) {
|
||||
i0 := valueInt(0)
|
||||
i1 := valueInt(1)
|
||||
|
||||
itemObj := r.toObject(nextValue)
|
||||
k := itemObj.self.getIdx(i0, nil)
|
||||
v := itemObj.self.getIdx(i1, nil)
|
||||
key := toPropertyKey(k)
|
||||
|
||||
createDataPropertyOrThrow(result, key, v)
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func (r *Runtime) object_hasOwn(call FunctionCall) Value {
|
||||
o := call.Argument(0)
|
||||
obj := o.ToObject(r)
|
||||
p := toPropertyKey(call.Argument(1))
|
||||
|
||||
if obj.hasOwnProperty(p) {
|
||||
return valueTrue
|
||||
} else {
|
||||
return valueFalse
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Runtime) initObject() {
|
||||
o := r.global.ObjectPrototype.self
|
||||
o._putProp("toString", r.newNativeFunc(r.objectproto_toString, nil, "toString", nil, 0), true, false, true)
|
||||
o._putProp("toLocaleString", r.newNativeFunc(r.objectproto_toLocaleString, nil, "toLocaleString", nil, 0), true, false, true)
|
||||
o._putProp("valueOf", r.newNativeFunc(r.objectproto_valueOf, nil, "valueOf", nil, 0), true, false, true)
|
||||
o._putProp("hasOwnProperty", r.newNativeFunc(r.objectproto_hasOwnProperty, nil, "hasOwnProperty", nil, 1), true, false, true)
|
||||
o._putProp("isPrototypeOf", r.newNativeFunc(r.objectproto_isPrototypeOf, nil, "isPrototypeOf", nil, 1), true, false, true)
|
||||
o._putProp("propertyIsEnumerable", r.newNativeFunc(r.objectproto_propertyIsEnumerable, nil, "propertyIsEnumerable", nil, 1), true, false, true)
|
||||
o.defineOwnPropertyStr(__proto__, PropertyDescriptor{
|
||||
Getter: r.newNativeFunc(r.objectproto_getProto, nil, "get __proto__", nil, 0),
|
||||
Setter: r.newNativeFunc(r.objectproto_setProto, nil, "set __proto__", nil, 1),
|
||||
Configurable: FLAG_TRUE,
|
||||
}, true)
|
||||
|
||||
r.global.Object = r.newNativeConstructOnly(nil, r.builtin_Object, r.global.ObjectPrototype, "Object", 1).val
|
||||
r.global.ObjectPrototype.self._putProp("constructor", r.global.Object, true, false, true)
|
||||
o = r.global.Object.self
|
||||
o._putProp("assign", r.newNativeFunc(r.object_assign, nil, "assign", nil, 2), true, false, true)
|
||||
o._putProp("defineProperty", r.newNativeFunc(r.object_defineProperty, nil, "defineProperty", nil, 3), true, false, true)
|
||||
o._putProp("defineProperties", r.newNativeFunc(r.object_defineProperties, nil, "defineProperties", nil, 2), true, false, true)
|
||||
o._putProp("entries", r.newNativeFunc(r.object_entries, nil, "entries", nil, 1), true, false, true)
|
||||
o._putProp("getOwnPropertyDescriptor", r.newNativeFunc(r.object_getOwnPropertyDescriptor, nil, "getOwnPropertyDescriptor", nil, 2), true, false, true)
|
||||
o._putProp("getOwnPropertyDescriptors", r.newNativeFunc(r.object_getOwnPropertyDescriptors, nil, "getOwnPropertyDescriptors", nil, 1), true, false, true)
|
||||
o._putProp("getPrototypeOf", r.newNativeFunc(r.object_getPrototypeOf, nil, "getPrototypeOf", nil, 1), true, false, true)
|
||||
o._putProp("is", r.newNativeFunc(r.object_is, nil, "is", nil, 2), true, false, true)
|
||||
o._putProp("getOwnPropertyNames", r.newNativeFunc(r.object_getOwnPropertyNames, nil, "getOwnPropertyNames", nil, 1), true, false, true)
|
||||
o._putProp("getOwnPropertySymbols", r.newNativeFunc(r.object_getOwnPropertySymbols, nil, "getOwnPropertySymbols", nil, 1), true, false, true)
|
||||
o._putProp("create", r.newNativeFunc(r.object_create, nil, "create", nil, 2), true, false, true)
|
||||
o._putProp("seal", r.newNativeFunc(r.object_seal, nil, "seal", nil, 1), true, false, true)
|
||||
o._putProp("freeze", r.newNativeFunc(r.object_freeze, nil, "freeze", nil, 1), true, false, true)
|
||||
o._putProp("preventExtensions", r.newNativeFunc(r.object_preventExtensions, nil, "preventExtensions", nil, 1), true, false, true)
|
||||
o._putProp("isSealed", r.newNativeFunc(r.object_isSealed, nil, "isSealed", nil, 1), true, false, true)
|
||||
o._putProp("isFrozen", r.newNativeFunc(r.object_isFrozen, nil, "isFrozen", nil, 1), true, false, true)
|
||||
o._putProp("isExtensible", r.newNativeFunc(r.object_isExtensible, nil, "isExtensible", nil, 1), true, false, true)
|
||||
o._putProp("keys", r.newNativeFunc(r.object_keys, nil, "keys", nil, 1), true, false, true)
|
||||
o._putProp("setPrototypeOf", r.newNativeFunc(r.object_setPrototypeOf, nil, "setPrototypeOf", nil, 2), true, false, true)
|
||||
o._putProp("values", r.newNativeFunc(r.object_values, nil, "values", nil, 1), true, false, true)
|
||||
o._putProp("fromEntries", r.newNativeFunc(r.object_fromEntries, nil, "fromEntries", nil, 1), true, false, true)
|
||||
o._putProp("hasOwn", r.newNativeFunc(r.object_hasOwn, nil, "hasOwn", nil, 2), true, false, true)
|
||||
|
||||
r.addToGlobal("Object", r.global.Object)
|
||||
}
|
||||
633
server/vendor/github.com/dop251/goja/builtin_promise.go
generated
vendored
Normal file
633
server/vendor/github.com/dop251/goja/builtin_promise.go
generated
vendored
Normal file
@@ -0,0 +1,633 @@
|
||||
package goja
|
||||
|
||||
import (
|
||||
"github.com/dop251/goja/unistring"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type PromiseState int
|
||||
type PromiseRejectionOperation int
|
||||
|
||||
type promiseReactionType int
|
||||
|
||||
const (
|
||||
PromiseStatePending PromiseState = iota
|
||||
PromiseStateFulfilled
|
||||
PromiseStateRejected
|
||||
)
|
||||
|
||||
const (
|
||||
PromiseRejectionReject PromiseRejectionOperation = iota
|
||||
PromiseRejectionHandle
|
||||
)
|
||||
|
||||
const (
|
||||
promiseReactionFulfill promiseReactionType = iota
|
||||
promiseReactionReject
|
||||
)
|
||||
|
||||
type PromiseRejectionTracker func(p *Promise, operation PromiseRejectionOperation)
|
||||
|
||||
type jobCallback struct {
|
||||
callback func(FunctionCall) Value
|
||||
}
|
||||
|
||||
type promiseCapability struct {
|
||||
promise *Object
|
||||
resolveObj, rejectObj *Object
|
||||
}
|
||||
|
||||
type promiseReaction struct {
|
||||
capability *promiseCapability
|
||||
typ promiseReactionType
|
||||
handler *jobCallback
|
||||
asyncRunner *asyncRunner
|
||||
asyncCtx interface{}
|
||||
}
|
||||
|
||||
var typePromise = reflect.TypeOf((*Promise)(nil))
|
||||
|
||||
// Promise is a Go wrapper around ECMAScript Promise. Calling Runtime.ToValue() on it
|
||||
// returns the underlying Object. Calling Export() on a Promise Object returns a Promise.
|
||||
//
|
||||
// Use Runtime.NewPromise() to create one. Calling Runtime.ToValue() on a zero object or nil returns null Value.
|
||||
//
|
||||
// WARNING: Instances of Promise are not goroutine-safe. See Runtime.NewPromise() for more details.
|
||||
type Promise struct {
|
||||
baseObject
|
||||
state PromiseState
|
||||
result Value
|
||||
fulfillReactions []*promiseReaction
|
||||
rejectReactions []*promiseReaction
|
||||
handled bool
|
||||
}
|
||||
|
||||
func (p *Promise) State() PromiseState {
|
||||
return p.state
|
||||
}
|
||||
|
||||
func (p *Promise) Result() Value {
|
||||
return p.result
|
||||
}
|
||||
|
||||
func (p *Promise) toValue(r *Runtime) Value {
|
||||
if p == nil || p.val == nil {
|
||||
return _null
|
||||
}
|
||||
promise := p.val
|
||||
if promise.runtime != r {
|
||||
panic(r.NewTypeError("Illegal runtime transition of a Promise"))
|
||||
}
|
||||
return promise
|
||||
}
|
||||
|
||||
func (p *Promise) createResolvingFunctions() (resolve, reject *Object) {
|
||||
r := p.val.runtime
|
||||
alreadyResolved := false
|
||||
return p.val.runtime.newNativeFunc(func(call FunctionCall) Value {
|
||||
if alreadyResolved {
|
||||
return _undefined
|
||||
}
|
||||
alreadyResolved = true
|
||||
resolution := call.Argument(0)
|
||||
if resolution.SameAs(p.val) {
|
||||
return p.reject(r.NewTypeError("Promise self-resolution"))
|
||||
}
|
||||
if obj, ok := resolution.(*Object); ok {
|
||||
var thenAction Value
|
||||
ex := r.vm.try(func() {
|
||||
thenAction = obj.self.getStr("then", nil)
|
||||
})
|
||||
if ex != nil {
|
||||
return p.reject(ex.val)
|
||||
}
|
||||
if call, ok := assertCallable(thenAction); ok {
|
||||
job := r.newPromiseResolveThenableJob(p, resolution, &jobCallback{callback: call})
|
||||
r.enqueuePromiseJob(job)
|
||||
return _undefined
|
||||
}
|
||||
}
|
||||
return p.fulfill(resolution)
|
||||
}, nil, "", nil, 1),
|
||||
p.val.runtime.newNativeFunc(func(call FunctionCall) Value {
|
||||
if alreadyResolved {
|
||||
return _undefined
|
||||
}
|
||||
alreadyResolved = true
|
||||
reason := call.Argument(0)
|
||||
return p.reject(reason)
|
||||
}, nil, "", nil, 1)
|
||||
}
|
||||
|
||||
func (p *Promise) reject(reason Value) Value {
|
||||
reactions := p.rejectReactions
|
||||
p.result = reason
|
||||
p.fulfillReactions, p.rejectReactions = nil, nil
|
||||
p.state = PromiseStateRejected
|
||||
r := p.val.runtime
|
||||
if !p.handled {
|
||||
r.trackPromiseRejection(p, PromiseRejectionReject)
|
||||
}
|
||||
r.triggerPromiseReactions(reactions, reason)
|
||||
return _undefined
|
||||
}
|
||||
|
||||
func (p *Promise) fulfill(value Value) Value {
|
||||
reactions := p.fulfillReactions
|
||||
p.result = value
|
||||
p.fulfillReactions, p.rejectReactions = nil, nil
|
||||
p.state = PromiseStateFulfilled
|
||||
p.val.runtime.triggerPromiseReactions(reactions, value)
|
||||
return _undefined
|
||||
}
|
||||
|
||||
func (p *Promise) exportType() reflect.Type {
|
||||
return typePromise
|
||||
}
|
||||
|
||||
func (p *Promise) export(*objectExportCtx) interface{} {
|
||||
return p
|
||||
}
|
||||
|
||||
func (p *Promise) addReactions(fulfillReaction *promiseReaction, rejectReaction *promiseReaction) {
|
||||
r := p.val.runtime
|
||||
if tracker := r.asyncContextTracker; tracker != nil {
|
||||
ctx := tracker.Grab()
|
||||
fulfillReaction.asyncCtx = ctx
|
||||
rejectReaction.asyncCtx = ctx
|
||||
}
|
||||
switch p.state {
|
||||
case PromiseStatePending:
|
||||
p.fulfillReactions = append(p.fulfillReactions, fulfillReaction)
|
||||
p.rejectReactions = append(p.rejectReactions, rejectReaction)
|
||||
case PromiseStateFulfilled:
|
||||
r.enqueuePromiseJob(r.newPromiseReactionJob(fulfillReaction, p.result))
|
||||
default:
|
||||
reason := p.result
|
||||
if !p.handled {
|
||||
r.trackPromiseRejection(p, PromiseRejectionHandle)
|
||||
}
|
||||
r.enqueuePromiseJob(r.newPromiseReactionJob(rejectReaction, reason))
|
||||
}
|
||||
p.handled = true
|
||||
}
|
||||
|
||||
func (r *Runtime) newPromiseResolveThenableJob(p *Promise, thenable Value, then *jobCallback) func() {
|
||||
return func() {
|
||||
resolve, reject := p.createResolvingFunctions()
|
||||
ex := r.vm.try(func() {
|
||||
r.callJobCallback(then, thenable, resolve, reject)
|
||||
})
|
||||
if ex != nil {
|
||||
if fn, ok := reject.self.assertCallable(); ok {
|
||||
fn(FunctionCall{Arguments: []Value{ex.val}})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Runtime) enqueuePromiseJob(job func()) {
|
||||
r.jobQueue = append(r.jobQueue, job)
|
||||
}
|
||||
|
||||
func (r *Runtime) triggerPromiseReactions(reactions []*promiseReaction, argument Value) {
|
||||
for _, reaction := range reactions {
|
||||
r.enqueuePromiseJob(r.newPromiseReactionJob(reaction, argument))
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Runtime) newPromiseReactionJob(reaction *promiseReaction, argument Value) func() {
|
||||
return func() {
|
||||
var handlerResult Value
|
||||
fulfill := false
|
||||
if reaction.handler == nil {
|
||||
handlerResult = argument
|
||||
if reaction.typ == promiseReactionFulfill {
|
||||
fulfill = true
|
||||
}
|
||||
} else {
|
||||
if tracker := r.asyncContextTracker; tracker != nil {
|
||||
tracker.Resumed(reaction.asyncCtx)
|
||||
}
|
||||
ex := r.vm.try(func() {
|
||||
handlerResult = r.callJobCallback(reaction.handler, _undefined, argument)
|
||||
fulfill = true
|
||||
})
|
||||
if ex != nil {
|
||||
handlerResult = ex.val
|
||||
}
|
||||
if tracker := r.asyncContextTracker; tracker != nil {
|
||||
tracker.Exited()
|
||||
}
|
||||
}
|
||||
if reaction.capability != nil {
|
||||
if fulfill {
|
||||
reaction.capability.resolve(handlerResult)
|
||||
} else {
|
||||
reaction.capability.reject(handlerResult)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Runtime) newPromise(proto *Object) *Promise {
|
||||
o := &Object{runtime: r}
|
||||
|
||||
po := &Promise{}
|
||||
po.class = classObject
|
||||
po.val = o
|
||||
po.extensible = true
|
||||
o.self = po
|
||||
po.prototype = proto
|
||||
po.init()
|
||||
return po
|
||||
}
|
||||
|
||||
func (r *Runtime) builtin_newPromise(args []Value, newTarget *Object) *Object {
|
||||
if newTarget == nil {
|
||||
panic(r.needNew("Promise"))
|
||||
}
|
||||
var arg0 Value
|
||||
if len(args) > 0 {
|
||||
arg0 = args[0]
|
||||
}
|
||||
executor := r.toCallable(arg0)
|
||||
|
||||
proto := r.getPrototypeFromCtor(newTarget, r.global.Promise, r.global.PromisePrototype)
|
||||
po := r.newPromise(proto)
|
||||
|
||||
resolve, reject := po.createResolvingFunctions()
|
||||
ex := r.vm.try(func() {
|
||||
executor(FunctionCall{Arguments: []Value{resolve, reject}})
|
||||
})
|
||||
if ex != nil {
|
||||
if fn, ok := reject.self.assertCallable(); ok {
|
||||
fn(FunctionCall{Arguments: []Value{ex.val}})
|
||||
}
|
||||
}
|
||||
return po.val
|
||||
}
|
||||
|
||||
func (r *Runtime) promiseProto_then(call FunctionCall) Value {
|
||||
thisObj := r.toObject(call.This)
|
||||
if p, ok := thisObj.self.(*Promise); ok {
|
||||
c := r.speciesConstructorObj(thisObj, r.global.Promise)
|
||||
resultCapability := r.newPromiseCapability(c)
|
||||
return r.performPromiseThen(p, call.Argument(0), call.Argument(1), resultCapability)
|
||||
}
|
||||
panic(r.NewTypeError("Method Promise.prototype.then called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
|
||||
}
|
||||
|
||||
func (r *Runtime) newPromiseCapability(c *Object) *promiseCapability {
|
||||
pcap := new(promiseCapability)
|
||||
if c == r.global.Promise {
|
||||
p := r.newPromise(r.global.PromisePrototype)
|
||||
pcap.resolveObj, pcap.rejectObj = p.createResolvingFunctions()
|
||||
pcap.promise = p.val
|
||||
} else {
|
||||
var resolve, reject Value
|
||||
executor := r.newNativeFunc(func(call FunctionCall) Value {
|
||||
if resolve != nil {
|
||||
panic(r.NewTypeError("resolve is already set"))
|
||||
}
|
||||
if reject != nil {
|
||||
panic(r.NewTypeError("reject is already set"))
|
||||
}
|
||||
if arg := call.Argument(0); arg != _undefined {
|
||||
resolve = arg
|
||||
}
|
||||
if arg := call.Argument(1); arg != _undefined {
|
||||
reject = arg
|
||||
}
|
||||
return nil
|
||||
}, nil, "", nil, 2)
|
||||
pcap.promise = r.toConstructor(c)([]Value{executor}, c)
|
||||
pcap.resolveObj = r.toObject(resolve)
|
||||
r.toCallable(pcap.resolveObj) // make sure it's callable
|
||||
pcap.rejectObj = r.toObject(reject)
|
||||
r.toCallable(pcap.rejectObj)
|
||||
}
|
||||
return pcap
|
||||
}
|
||||
|
||||
func (r *Runtime) performPromiseThen(p *Promise, onFulfilled, onRejected Value, resultCapability *promiseCapability) Value {
|
||||
var onFulfilledJobCallback, onRejectedJobCallback *jobCallback
|
||||
if f, ok := assertCallable(onFulfilled); ok {
|
||||
onFulfilledJobCallback = &jobCallback{callback: f}
|
||||
}
|
||||
if f, ok := assertCallable(onRejected); ok {
|
||||
onRejectedJobCallback = &jobCallback{callback: f}
|
||||
}
|
||||
fulfillReaction := &promiseReaction{
|
||||
capability: resultCapability,
|
||||
typ: promiseReactionFulfill,
|
||||
handler: onFulfilledJobCallback,
|
||||
}
|
||||
rejectReaction := &promiseReaction{
|
||||
capability: resultCapability,
|
||||
typ: promiseReactionReject,
|
||||
handler: onRejectedJobCallback,
|
||||
}
|
||||
p.addReactions(fulfillReaction, rejectReaction)
|
||||
if resultCapability == nil {
|
||||
return _undefined
|
||||
}
|
||||
return resultCapability.promise
|
||||
}
|
||||
|
||||
func (r *Runtime) promiseProto_catch(call FunctionCall) Value {
|
||||
return r.invoke(call.This, "then", _undefined, call.Argument(0))
|
||||
}
|
||||
|
||||
func (r *Runtime) promiseResolve(c *Object, x Value) *Object {
|
||||
if obj, ok := x.(*Object); ok {
|
||||
xConstructor := nilSafe(obj.self.getStr("constructor", nil))
|
||||
if xConstructor.SameAs(c) {
|
||||
return obj
|
||||
}
|
||||
}
|
||||
pcap := r.newPromiseCapability(c)
|
||||
pcap.resolve(x)
|
||||
return pcap.promise
|
||||
}
|
||||
|
||||
func (r *Runtime) promiseProto_finally(call FunctionCall) Value {
|
||||
promise := r.toObject(call.This)
|
||||
c := r.speciesConstructorObj(promise, r.global.Promise)
|
||||
onFinally := call.Argument(0)
|
||||
var thenFinally, catchFinally Value
|
||||
if onFinallyFn, ok := assertCallable(onFinally); !ok {
|
||||
thenFinally, catchFinally = onFinally, onFinally
|
||||
} else {
|
||||
thenFinally = r.newNativeFunc(func(call FunctionCall) Value {
|
||||
value := call.Argument(0)
|
||||
result := onFinallyFn(FunctionCall{})
|
||||
promise := r.promiseResolve(c, result)
|
||||
valueThunk := r.newNativeFunc(func(call FunctionCall) Value {
|
||||
return value
|
||||
}, nil, "", nil, 0)
|
||||
return r.invoke(promise, "then", valueThunk)
|
||||
}, nil, "", nil, 1)
|
||||
|
||||
catchFinally = r.newNativeFunc(func(call FunctionCall) Value {
|
||||
reason := call.Argument(0)
|
||||
result := onFinallyFn(FunctionCall{})
|
||||
promise := r.promiseResolve(c, result)
|
||||
thrower := r.newNativeFunc(func(call FunctionCall) Value {
|
||||
panic(reason)
|
||||
}, nil, "", nil, 0)
|
||||
return r.invoke(promise, "then", thrower)
|
||||
}, nil, "", nil, 1)
|
||||
}
|
||||
return r.invoke(promise, "then", thenFinally, catchFinally)
|
||||
}
|
||||
|
||||
func (pcap *promiseCapability) resolve(result Value) {
|
||||
pcap.promise.runtime.toCallable(pcap.resolveObj)(FunctionCall{Arguments: []Value{result}})
|
||||
}
|
||||
|
||||
func (pcap *promiseCapability) reject(reason Value) {
|
||||
pcap.promise.runtime.toCallable(pcap.rejectObj)(FunctionCall{Arguments: []Value{reason}})
|
||||
}
|
||||
|
||||
func (pcap *promiseCapability) try(f func()) bool {
|
||||
ex := pcap.promise.runtime.vm.try(f)
|
||||
if ex != nil {
|
||||
pcap.reject(ex.val)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (r *Runtime) promise_all(call FunctionCall) Value {
|
||||
c := r.toObject(call.This)
|
||||
pcap := r.newPromiseCapability(c)
|
||||
|
||||
pcap.try(func() {
|
||||
promiseResolve := r.toCallable(c.self.getStr("resolve", nil))
|
||||
iter := r.getIterator(call.Argument(0), nil)
|
||||
var values []Value
|
||||
remainingElementsCount := 1
|
||||
iter.iterate(func(nextValue Value) {
|
||||
index := len(values)
|
||||
values = append(values, _undefined)
|
||||
nextPromise := promiseResolve(FunctionCall{This: c, Arguments: []Value{nextValue}})
|
||||
alreadyCalled := false
|
||||
onFulfilled := r.newNativeFunc(func(call FunctionCall) Value {
|
||||
if alreadyCalled {
|
||||
return _undefined
|
||||
}
|
||||
alreadyCalled = true
|
||||
values[index] = call.Argument(0)
|
||||
remainingElementsCount--
|
||||
if remainingElementsCount == 0 {
|
||||
pcap.resolve(r.newArrayValues(values))
|
||||
}
|
||||
return _undefined
|
||||
}, nil, "", nil, 1)
|
||||
remainingElementsCount++
|
||||
r.invoke(nextPromise, "then", onFulfilled, pcap.rejectObj)
|
||||
})
|
||||
remainingElementsCount--
|
||||
if remainingElementsCount == 0 {
|
||||
pcap.resolve(r.newArrayValues(values))
|
||||
}
|
||||
})
|
||||
return pcap.promise
|
||||
}
|
||||
|
||||
func (r *Runtime) promise_allSettled(call FunctionCall) Value {
|
||||
c := r.toObject(call.This)
|
||||
pcap := r.newPromiseCapability(c)
|
||||
|
||||
pcap.try(func() {
|
||||
promiseResolve := r.toCallable(c.self.getStr("resolve", nil))
|
||||
iter := r.getIterator(call.Argument(0), nil)
|
||||
var values []Value
|
||||
remainingElementsCount := 1
|
||||
iter.iterate(func(nextValue Value) {
|
||||
index := len(values)
|
||||
values = append(values, _undefined)
|
||||
nextPromise := promiseResolve(FunctionCall{This: c, Arguments: []Value{nextValue}})
|
||||
alreadyCalled := false
|
||||
reaction := func(status Value, valueKey unistring.String) *Object {
|
||||
return r.newNativeFunc(func(call FunctionCall) Value {
|
||||
if alreadyCalled {
|
||||
return _undefined
|
||||
}
|
||||
alreadyCalled = true
|
||||
obj := r.NewObject()
|
||||
obj.self._putProp("status", status, true, true, true)
|
||||
obj.self._putProp(valueKey, call.Argument(0), true, true, true)
|
||||
values[index] = obj
|
||||
remainingElementsCount--
|
||||
if remainingElementsCount == 0 {
|
||||
pcap.resolve(r.newArrayValues(values))
|
||||
}
|
||||
return _undefined
|
||||
}, nil, "", nil, 1)
|
||||
}
|
||||
onFulfilled := reaction(asciiString("fulfilled"), "value")
|
||||
onRejected := reaction(asciiString("rejected"), "reason")
|
||||
remainingElementsCount++
|
||||
r.invoke(nextPromise, "then", onFulfilled, onRejected)
|
||||
})
|
||||
remainingElementsCount--
|
||||
if remainingElementsCount == 0 {
|
||||
pcap.resolve(r.newArrayValues(values))
|
||||
}
|
||||
})
|
||||
return pcap.promise
|
||||
}
|
||||
|
||||
func (r *Runtime) promise_any(call FunctionCall) Value {
|
||||
c := r.toObject(call.This)
|
||||
pcap := r.newPromiseCapability(c)
|
||||
|
||||
pcap.try(func() {
|
||||
promiseResolve := r.toCallable(c.self.getStr("resolve", nil))
|
||||
iter := r.getIterator(call.Argument(0), nil)
|
||||
var errors []Value
|
||||
remainingElementsCount := 1
|
||||
iter.iterate(func(nextValue Value) {
|
||||
index := len(errors)
|
||||
errors = append(errors, _undefined)
|
||||
nextPromise := promiseResolve(FunctionCall{This: c, Arguments: []Value{nextValue}})
|
||||
alreadyCalled := false
|
||||
onRejected := r.newNativeFunc(func(call FunctionCall) Value {
|
||||
if alreadyCalled {
|
||||
return _undefined
|
||||
}
|
||||
alreadyCalled = true
|
||||
errors[index] = call.Argument(0)
|
||||
remainingElementsCount--
|
||||
if remainingElementsCount == 0 {
|
||||
_error := r.builtin_new(r.global.AggregateError, nil)
|
||||
_error.self._putProp("errors", r.newArrayValues(errors), true, false, true)
|
||||
pcap.reject(_error)
|
||||
}
|
||||
return _undefined
|
||||
}, nil, "", nil, 1)
|
||||
|
||||
remainingElementsCount++
|
||||
r.invoke(nextPromise, "then", pcap.resolveObj, onRejected)
|
||||
})
|
||||
remainingElementsCount--
|
||||
if remainingElementsCount == 0 {
|
||||
_error := r.builtin_new(r.global.AggregateError, nil)
|
||||
_error.self._putProp("errors", r.newArrayValues(errors), true, false, true)
|
||||
pcap.reject(_error)
|
||||
}
|
||||
})
|
||||
return pcap.promise
|
||||
}
|
||||
|
||||
func (r *Runtime) promise_race(call FunctionCall) Value {
|
||||
c := r.toObject(call.This)
|
||||
pcap := r.newPromiseCapability(c)
|
||||
|
||||
pcap.try(func() {
|
||||
promiseResolve := r.toCallable(c.self.getStr("resolve", nil))
|
||||
iter := r.getIterator(call.Argument(0), nil)
|
||||
iter.iterate(func(nextValue Value) {
|
||||
nextPromise := promiseResolve(FunctionCall{This: c, Arguments: []Value{nextValue}})
|
||||
r.invoke(nextPromise, "then", pcap.resolveObj, pcap.rejectObj)
|
||||
})
|
||||
})
|
||||
return pcap.promise
|
||||
}
|
||||
|
||||
func (r *Runtime) promise_reject(call FunctionCall) Value {
|
||||
pcap := r.newPromiseCapability(r.toObject(call.This))
|
||||
pcap.reject(call.Argument(0))
|
||||
return pcap.promise
|
||||
}
|
||||
|
||||
func (r *Runtime) promise_resolve(call FunctionCall) Value {
|
||||
return r.promiseResolve(r.toObject(call.This), call.Argument(0))
|
||||
}
|
||||
|
||||
func (r *Runtime) createPromiseProto(val *Object) objectImpl {
|
||||
o := newBaseObjectObj(val, r.global.ObjectPrototype, classObject)
|
||||
o._putProp("constructor", r.global.Promise, true, false, true)
|
||||
|
||||
o._putProp("catch", r.newNativeFunc(r.promiseProto_catch, nil, "catch", nil, 1), true, false, true)
|
||||
o._putProp("finally", r.newNativeFunc(r.promiseProto_finally, nil, "finally", nil, 1), true, false, true)
|
||||
o._putProp("then", r.newNativeFunc(r.promiseProto_then, nil, "then", nil, 2), true, false, true)
|
||||
|
||||
o._putSym(SymToStringTag, valueProp(asciiString(classPromise), false, false, true))
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
func (r *Runtime) createPromise(val *Object) objectImpl {
|
||||
o := r.newNativeConstructOnly(val, r.builtin_newPromise, r.global.PromisePrototype, "Promise", 1)
|
||||
|
||||
o._putProp("all", r.newNativeFunc(r.promise_all, nil, "all", nil, 1), true, false, true)
|
||||
o._putProp("allSettled", r.newNativeFunc(r.promise_allSettled, nil, "allSettled", nil, 1), true, false, true)
|
||||
o._putProp("any", r.newNativeFunc(r.promise_any, nil, "any", nil, 1), true, false, true)
|
||||
o._putProp("race", r.newNativeFunc(r.promise_race, nil, "race", nil, 1), true, false, true)
|
||||
o._putProp("reject", r.newNativeFunc(r.promise_reject, nil, "reject", nil, 1), true, false, true)
|
||||
o._putProp("resolve", r.newNativeFunc(r.promise_resolve, nil, "resolve", nil, 1), true, false, true)
|
||||
|
||||
r.putSpeciesReturnThis(o)
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
func (r *Runtime) initPromise() {
|
||||
r.global.PromisePrototype = r.newLazyObject(r.createPromiseProto)
|
||||
r.global.Promise = r.newLazyObject(r.createPromise)
|
||||
|
||||
r.addToGlobal("Promise", r.global.Promise)
|
||||
}
|
||||
|
||||
func (r *Runtime) wrapPromiseReaction(fObj *Object) func(interface{}) {
|
||||
f, _ := AssertFunction(fObj)
|
||||
return func(x interface{}) {
|
||||
_, _ = f(nil, r.ToValue(x))
|
||||
}
|
||||
}
|
||||
|
||||
// NewPromise creates and returns a Promise and resolving functions for it.
|
||||
//
|
||||
// WARNING: The returned values are not goroutine-safe and must not be called in parallel with VM running.
|
||||
// In order to make use of this method you need an event loop such as the one in goja_nodejs (https://github.com/dop251/goja_nodejs)
|
||||
// where it can be used like this:
|
||||
//
|
||||
// loop := NewEventLoop()
|
||||
// loop.Start()
|
||||
// defer loop.Stop()
|
||||
// loop.RunOnLoop(func(vm *goja.Runtime) {
|
||||
// p, resolve, _ := vm.NewPromise()
|
||||
// vm.Set("p", p)
|
||||
// go func() {
|
||||
// time.Sleep(500 * time.Millisecond) // or perform any other blocking operation
|
||||
// loop.RunOnLoop(func(*goja.Runtime) { // resolve() must be called on the loop, cannot call it here
|
||||
// resolve(result)
|
||||
// })
|
||||
// }()
|
||||
// }
|
||||
func (r *Runtime) NewPromise() (promise *Promise, resolve func(result interface{}), reject func(reason interface{})) {
|
||||
p := r.newPromise(r.global.PromisePrototype)
|
||||
resolveF, rejectF := p.createResolvingFunctions()
|
||||
return p, r.wrapPromiseReaction(resolveF), r.wrapPromiseReaction(rejectF)
|
||||
}
|
||||
|
||||
// SetPromiseRejectionTracker registers a function that will be called in two scenarios: when a promise is rejected
|
||||
// without any handlers (with operation argument set to PromiseRejectionReject), and when a handler is added to a
|
||||
// rejected promise for the first time (with operation argument set to PromiseRejectionHandle).
|
||||
//
|
||||
// Setting a tracker replaces any existing one. Setting it to nil disables the functionality.
|
||||
//
|
||||
// See https://tc39.es/ecma262/#sec-host-promise-rejection-tracker for more details.
|
||||
func (r *Runtime) SetPromiseRejectionTracker(tracker PromiseRejectionTracker) {
|
||||
r.promiseRejectionTracker = tracker
|
||||
}
|
||||
|
||||
// SetAsyncContextTracker registers a handler that allows to track async execution contexts. See AsyncContextTracker
|
||||
// documentation for more details. Setting it to nil disables the functionality.
|
||||
// This method (as Runtime in general) is not goroutine-safe.
|
||||
func (r *Runtime) SetAsyncContextTracker(tracker AsyncContextTracker) {
|
||||
r.asyncContextTracker = tracker
|
||||
}
|
||||
391
server/vendor/github.com/dop251/goja/builtin_proxy.go
generated
vendored
Normal file
391
server/vendor/github.com/dop251/goja/builtin_proxy.go
generated
vendored
Normal file
@@ -0,0 +1,391 @@
|
||||
package goja
|
||||
|
||||
import (
|
||||
"github.com/dop251/goja/unistring"
|
||||
)
|
||||
|
||||
type nativeProxyHandler struct {
|
||||
handler *ProxyTrapConfig
|
||||
}
|
||||
|
||||
func (h *nativeProxyHandler) getPrototypeOf(target *Object) (Value, bool) {
|
||||
if trap := h.handler.GetPrototypeOf; trap != nil {
|
||||
return trap(target), true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (h *nativeProxyHandler) setPrototypeOf(target *Object, proto *Object) (bool, bool) {
|
||||
if trap := h.handler.SetPrototypeOf; trap != nil {
|
||||
return trap(target, proto), true
|
||||
}
|
||||
return false, false
|
||||
}
|
||||
|
||||
func (h *nativeProxyHandler) isExtensible(target *Object) (bool, bool) {
|
||||
if trap := h.handler.IsExtensible; trap != nil {
|
||||
return trap(target), true
|
||||
}
|
||||
return false, false
|
||||
}
|
||||
|
||||
func (h *nativeProxyHandler) preventExtensions(target *Object) (bool, bool) {
|
||||
if trap := h.handler.PreventExtensions; trap != nil {
|
||||
return trap(target), true
|
||||
}
|
||||
return false, false
|
||||
}
|
||||
|
||||
func (h *nativeProxyHandler) getOwnPropertyDescriptorStr(target *Object, prop unistring.String) (Value, bool) {
|
||||
if trap := h.handler.GetOwnPropertyDescriptorIdx; trap != nil {
|
||||
if idx, ok := strToInt(prop); ok {
|
||||
desc := trap(target, idx)
|
||||
return desc.toValue(target.runtime), true
|
||||
}
|
||||
}
|
||||
if trap := h.handler.GetOwnPropertyDescriptor; trap != nil {
|
||||
desc := trap(target, prop.String())
|
||||
return desc.toValue(target.runtime), true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (h *nativeProxyHandler) getOwnPropertyDescriptorIdx(target *Object, prop valueInt) (Value, bool) {
|
||||
if trap := h.handler.GetOwnPropertyDescriptorIdx; trap != nil {
|
||||
desc := trap(target, toIntStrict(int64(prop)))
|
||||
return desc.toValue(target.runtime), true
|
||||
}
|
||||
if trap := h.handler.GetOwnPropertyDescriptor; trap != nil {
|
||||
desc := trap(target, prop.String())
|
||||
return desc.toValue(target.runtime), true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (h *nativeProxyHandler) getOwnPropertyDescriptorSym(target *Object, prop *Symbol) (Value, bool) {
|
||||
if trap := h.handler.GetOwnPropertyDescriptorSym; trap != nil {
|
||||
desc := trap(target, prop)
|
||||
return desc.toValue(target.runtime), true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (h *nativeProxyHandler) definePropertyStr(target *Object, prop unistring.String, desc PropertyDescriptor) (bool, bool) {
|
||||
if trap := h.handler.DefinePropertyIdx; trap != nil {
|
||||
if idx, ok := strToInt(prop); ok {
|
||||
return trap(target, idx, desc), true
|
||||
}
|
||||
}
|
||||
if trap := h.handler.DefineProperty; trap != nil {
|
||||
return trap(target, prop.String(), desc), true
|
||||
}
|
||||
return false, false
|
||||
}
|
||||
|
||||
func (h *nativeProxyHandler) definePropertyIdx(target *Object, prop valueInt, desc PropertyDescriptor) (bool, bool) {
|
||||
if trap := h.handler.DefinePropertyIdx; trap != nil {
|
||||
return trap(target, toIntStrict(int64(prop)), desc), true
|
||||
}
|
||||
if trap := h.handler.DefineProperty; trap != nil {
|
||||
return trap(target, prop.String(), desc), true
|
||||
}
|
||||
return false, false
|
||||
}
|
||||
|
||||
func (h *nativeProxyHandler) definePropertySym(target *Object, prop *Symbol, desc PropertyDescriptor) (bool, bool) {
|
||||
if trap := h.handler.DefinePropertySym; trap != nil {
|
||||
return trap(target, prop, desc), true
|
||||
}
|
||||
return false, false
|
||||
}
|
||||
|
||||
func (h *nativeProxyHandler) hasStr(target *Object, prop unistring.String) (bool, bool) {
|
||||
if trap := h.handler.HasIdx; trap != nil {
|
||||
if idx, ok := strToInt(prop); ok {
|
||||
return trap(target, idx), true
|
||||
}
|
||||
}
|
||||
if trap := h.handler.Has; trap != nil {
|
||||
return trap(target, prop.String()), true
|
||||
}
|
||||
return false, false
|
||||
}
|
||||
|
||||
func (h *nativeProxyHandler) hasIdx(target *Object, prop valueInt) (bool, bool) {
|
||||
if trap := h.handler.HasIdx; trap != nil {
|
||||
return trap(target, toIntStrict(int64(prop))), true
|
||||
}
|
||||
if trap := h.handler.Has; trap != nil {
|
||||
return trap(target, prop.String()), true
|
||||
}
|
||||
return false, false
|
||||
}
|
||||
|
||||
func (h *nativeProxyHandler) hasSym(target *Object, prop *Symbol) (bool, bool) {
|
||||
if trap := h.handler.HasSym; trap != nil {
|
||||
return trap(target, prop), true
|
||||
}
|
||||
return false, false
|
||||
}
|
||||
|
||||
func (h *nativeProxyHandler) getStr(target *Object, prop unistring.String, receiver Value) (Value, bool) {
|
||||
if trap := h.handler.GetIdx; trap != nil {
|
||||
if idx, ok := strToInt(prop); ok {
|
||||
return trap(target, idx, receiver), true
|
||||
}
|
||||
}
|
||||
if trap := h.handler.Get; trap != nil {
|
||||
return trap(target, prop.String(), receiver), true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (h *nativeProxyHandler) getIdx(target *Object, prop valueInt, receiver Value) (Value, bool) {
|
||||
if trap := h.handler.GetIdx; trap != nil {
|
||||
return trap(target, toIntStrict(int64(prop)), receiver), true
|
||||
}
|
||||
if trap := h.handler.Get; trap != nil {
|
||||
return trap(target, prop.String(), receiver), true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (h *nativeProxyHandler) getSym(target *Object, prop *Symbol, receiver Value) (Value, bool) {
|
||||
if trap := h.handler.GetSym; trap != nil {
|
||||
return trap(target, prop, receiver), true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (h *nativeProxyHandler) setStr(target *Object, prop unistring.String, value Value, receiver Value) (bool, bool) {
|
||||
if trap := h.handler.SetIdx; trap != nil {
|
||||
if idx, ok := strToInt(prop); ok {
|
||||
return trap(target, idx, value, receiver), true
|
||||
}
|
||||
}
|
||||
if trap := h.handler.Set; trap != nil {
|
||||
return trap(target, prop.String(), value, receiver), true
|
||||
}
|
||||
return false, false
|
||||
}
|
||||
|
||||
func (h *nativeProxyHandler) setIdx(target *Object, prop valueInt, value Value, receiver Value) (bool, bool) {
|
||||
if trap := h.handler.SetIdx; trap != nil {
|
||||
return trap(target, toIntStrict(int64(prop)), value, receiver), true
|
||||
}
|
||||
if trap := h.handler.Set; trap != nil {
|
||||
return trap(target, prop.String(), value, receiver), true
|
||||
}
|
||||
return false, false
|
||||
}
|
||||
|
||||
func (h *nativeProxyHandler) setSym(target *Object, prop *Symbol, value Value, receiver Value) (bool, bool) {
|
||||
if trap := h.handler.SetSym; trap != nil {
|
||||
return trap(target, prop, value, receiver), true
|
||||
}
|
||||
return false, false
|
||||
}
|
||||
|
||||
func (h *nativeProxyHandler) deleteStr(target *Object, prop unistring.String) (bool, bool) {
|
||||
if trap := h.handler.DeletePropertyIdx; trap != nil {
|
||||
if idx, ok := strToInt(prop); ok {
|
||||
return trap(target, idx), true
|
||||
}
|
||||
}
|
||||
if trap := h.handler.DeleteProperty; trap != nil {
|
||||
return trap(target, prop.String()), true
|
||||
}
|
||||
return false, false
|
||||
}
|
||||
|
||||
func (h *nativeProxyHandler) deleteIdx(target *Object, prop valueInt) (bool, bool) {
|
||||
if trap := h.handler.DeletePropertyIdx; trap != nil {
|
||||
return trap(target, toIntStrict(int64(prop))), true
|
||||
}
|
||||
if trap := h.handler.DeleteProperty; trap != nil {
|
||||
return trap(target, prop.String()), true
|
||||
}
|
||||
return false, false
|
||||
}
|
||||
|
||||
func (h *nativeProxyHandler) deleteSym(target *Object, prop *Symbol) (bool, bool) {
|
||||
if trap := h.handler.DeletePropertySym; trap != nil {
|
||||
return trap(target, prop), true
|
||||
}
|
||||
return false, false
|
||||
}
|
||||
|
||||
func (h *nativeProxyHandler) ownKeys(target *Object) (*Object, bool) {
|
||||
if trap := h.handler.OwnKeys; trap != nil {
|
||||
return trap(target), true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (h *nativeProxyHandler) apply(target *Object, this Value, args []Value) (Value, bool) {
|
||||
if trap := h.handler.Apply; trap != nil {
|
||||
return trap(target, this, args), true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (h *nativeProxyHandler) construct(target *Object, args []Value, newTarget *Object) (Value, bool) {
|
||||
if trap := h.handler.Construct; trap != nil {
|
||||
return trap(target, args, newTarget), true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (h *nativeProxyHandler) toObject(runtime *Runtime) *Object {
|
||||
return runtime.ToValue(h.handler).ToObject(runtime)
|
||||
}
|
||||
|
||||
func (r *Runtime) newNativeProxyHandler(nativeHandler *ProxyTrapConfig) proxyHandler {
|
||||
return &nativeProxyHandler{handler: nativeHandler}
|
||||
}
|
||||
|
||||
// ProxyTrapConfig provides a simplified Go-friendly API for implementing Proxy traps.
|
||||
// If an *Idx trap is defined it gets called for integer property keys, including negative ones. Note that
|
||||
// this only includes string property keys that represent a canonical integer
|
||||
// (i.e. "0", "123", but not "00", "01", " 1" or "-0").
|
||||
// For efficiency strings representing integers exceeding 2^53 are not checked to see if they are canonical,
|
||||
// i.e. the *Idx traps will receive "9007199254740993" as well as "9007199254740994", even though the former is not
|
||||
// a canonical representation in ECMAScript (Number("9007199254740993") === 9007199254740992).
|
||||
// See https://262.ecma-international.org/#sec-canonicalnumericindexstring
|
||||
// If an *Idx trap is not set, the corresponding string one is used.
|
||||
type ProxyTrapConfig struct {
|
||||
// A trap for Object.getPrototypeOf, Reflect.getPrototypeOf, __proto__, Object.prototype.isPrototypeOf, instanceof
|
||||
GetPrototypeOf func(target *Object) (prototype *Object)
|
||||
|
||||
// A trap for Object.setPrototypeOf, Reflect.setPrototypeOf
|
||||
SetPrototypeOf func(target *Object, prototype *Object) (success bool)
|
||||
|
||||
// A trap for Object.isExtensible, Reflect.isExtensible
|
||||
IsExtensible func(target *Object) (success bool)
|
||||
|
||||
// A trap for Object.preventExtensions, Reflect.preventExtensions
|
||||
PreventExtensions func(target *Object) (success bool)
|
||||
|
||||
// A trap for Object.getOwnPropertyDescriptor, Reflect.getOwnPropertyDescriptor (string properties)
|
||||
GetOwnPropertyDescriptor func(target *Object, prop string) (propertyDescriptor PropertyDescriptor)
|
||||
|
||||
// A trap for Object.getOwnPropertyDescriptor, Reflect.getOwnPropertyDescriptor (integer properties)
|
||||
GetOwnPropertyDescriptorIdx func(target *Object, prop int) (propertyDescriptor PropertyDescriptor)
|
||||
|
||||
// A trap for Object.getOwnPropertyDescriptor, Reflect.getOwnPropertyDescriptor (Symbol properties)
|
||||
GetOwnPropertyDescriptorSym func(target *Object, prop *Symbol) (propertyDescriptor PropertyDescriptor)
|
||||
|
||||
// A trap for Object.defineProperty, Reflect.defineProperty (string properties)
|
||||
DefineProperty func(target *Object, key string, propertyDescriptor PropertyDescriptor) (success bool)
|
||||
|
||||
// A trap for Object.defineProperty, Reflect.defineProperty (integer properties)
|
||||
DefinePropertyIdx func(target *Object, key int, propertyDescriptor PropertyDescriptor) (success bool)
|
||||
|
||||
// A trap for Object.defineProperty, Reflect.defineProperty (Symbol properties)
|
||||
DefinePropertySym func(target *Object, key *Symbol, propertyDescriptor PropertyDescriptor) (success bool)
|
||||
|
||||
// A trap for the in operator, with operator, Reflect.has (string properties)
|
||||
Has func(target *Object, property string) (available bool)
|
||||
|
||||
// A trap for the in operator, with operator, Reflect.has (integer properties)
|
||||
HasIdx func(target *Object, property int) (available bool)
|
||||
|
||||
// A trap for the in operator, with operator, Reflect.has (Symbol properties)
|
||||
HasSym func(target *Object, property *Symbol) (available bool)
|
||||
|
||||
// A trap for getting property values, Reflect.get (string properties)
|
||||
Get func(target *Object, property string, receiver Value) (value Value)
|
||||
|
||||
// A trap for getting property values, Reflect.get (integer properties)
|
||||
GetIdx func(target *Object, property int, receiver Value) (value Value)
|
||||
|
||||
// A trap for getting property values, Reflect.get (Symbol properties)
|
||||
GetSym func(target *Object, property *Symbol, receiver Value) (value Value)
|
||||
|
||||
// A trap for setting property values, Reflect.set (string properties)
|
||||
Set func(target *Object, property string, value Value, receiver Value) (success bool)
|
||||
|
||||
// A trap for setting property values, Reflect.set (integer properties)
|
||||
SetIdx func(target *Object, property int, value Value, receiver Value) (success bool)
|
||||
|
||||
// A trap for setting property values, Reflect.set (Symbol properties)
|
||||
SetSym func(target *Object, property *Symbol, value Value, receiver Value) (success bool)
|
||||
|
||||
// A trap for the delete operator, Reflect.deleteProperty (string properties)
|
||||
DeleteProperty func(target *Object, property string) (success bool)
|
||||
|
||||
// A trap for the delete operator, Reflect.deleteProperty (integer properties)
|
||||
DeletePropertyIdx func(target *Object, property int) (success bool)
|
||||
|
||||
// A trap for the delete operator, Reflect.deleteProperty (Symbol properties)
|
||||
DeletePropertySym func(target *Object, property *Symbol) (success bool)
|
||||
|
||||
// A trap for Object.getOwnPropertyNames, Object.getOwnPropertySymbols, Object.keys, Reflect.ownKeys
|
||||
OwnKeys func(target *Object) (object *Object)
|
||||
|
||||
// A trap for a function call, Function.prototype.apply, Function.prototype.call, Reflect.apply
|
||||
Apply func(target *Object, this Value, argumentsList []Value) (value Value)
|
||||
|
||||
// A trap for the new operator, Reflect.construct
|
||||
Construct func(target *Object, argumentsList []Value, newTarget *Object) (value *Object)
|
||||
}
|
||||
|
||||
func (r *Runtime) newProxy(args []Value, proto *Object) *Object {
|
||||
if len(args) >= 2 {
|
||||
if target, ok := args[0].(*Object); ok {
|
||||
if proxyHandler, ok := args[1].(*Object); ok {
|
||||
return r.newProxyObject(target, proxyHandler, proto).val
|
||||
}
|
||||
}
|
||||
}
|
||||
panic(r.NewTypeError("Cannot create proxy with a non-object as target or handler"))
|
||||
}
|
||||
|
||||
func (r *Runtime) builtin_newProxy(args []Value, newTarget *Object) *Object {
|
||||
if newTarget == nil {
|
||||
panic(r.needNew("Proxy"))
|
||||
}
|
||||
return r.newProxy(args, r.getPrototypeFromCtor(newTarget, r.global.Proxy, r.global.ObjectPrototype))
|
||||
}
|
||||
|
||||
func (r *Runtime) NewProxy(target *Object, nativeHandler *ProxyTrapConfig) Proxy {
|
||||
if p, ok := target.self.(*proxyObject); ok {
|
||||
if p.handler == nil {
|
||||
panic(r.NewTypeError("Cannot create proxy with a revoked proxy as target"))
|
||||
}
|
||||
}
|
||||
handler := r.newNativeProxyHandler(nativeHandler)
|
||||
proxy := r._newProxyObject(target, handler, nil)
|
||||
return Proxy{proxy: proxy}
|
||||
}
|
||||
|
||||
func (r *Runtime) builtin_proxy_revocable(call FunctionCall) Value {
|
||||
if len(call.Arguments) >= 2 {
|
||||
if target, ok := call.Argument(0).(*Object); ok {
|
||||
if proxyHandler, ok := call.Argument(1).(*Object); ok {
|
||||
proxy := r.newProxyObject(target, proxyHandler, nil)
|
||||
revoke := r.newNativeFunc(func(FunctionCall) Value {
|
||||
proxy.revoke()
|
||||
return _undefined
|
||||
}, nil, "", nil, 0)
|
||||
ret := r.NewObject()
|
||||
ret.self._putProp("proxy", proxy.val, true, true, true)
|
||||
ret.self._putProp("revoke", revoke, true, true, true)
|
||||
return ret
|
||||
}
|
||||
}
|
||||
}
|
||||
panic(r.NewTypeError("Cannot create proxy with a non-object as target or handler"))
|
||||
}
|
||||
|
||||
func (r *Runtime) createProxy(val *Object) objectImpl {
|
||||
o := r.newNativeConstructOnly(val, r.builtin_newProxy, nil, "Proxy", 2)
|
||||
|
||||
o._putProp("revocable", r.newNativeFunc(r.builtin_proxy_revocable, nil, "revocable", nil, 2), true, false, true)
|
||||
return o
|
||||
}
|
||||
|
||||
func (r *Runtime) initProxy() {
|
||||
r.global.Proxy = r.newLazyObject(r.createProxy)
|
||||
r.addToGlobal("Proxy", r.global.Proxy)
|
||||
}
|
||||
134
server/vendor/github.com/dop251/goja/builtin_reflect.go
generated
vendored
Normal file
134
server/vendor/github.com/dop251/goja/builtin_reflect.go
generated
vendored
Normal file
@@ -0,0 +1,134 @@
|
||||
package goja
|
||||
|
||||
func (r *Runtime) builtin_reflect_apply(call FunctionCall) Value {
|
||||
return r.toCallable(call.Argument(0))(FunctionCall{
|
||||
This: call.Argument(1),
|
||||
Arguments: r.createListFromArrayLike(call.Argument(2))})
|
||||
}
|
||||
|
||||
func (r *Runtime) toConstructor(v Value) func(args []Value, newTarget *Object) *Object {
|
||||
if ctor := r.toObject(v).self.assertConstructor(); ctor != nil {
|
||||
return ctor
|
||||
}
|
||||
panic(r.NewTypeError("Value is not a constructor"))
|
||||
}
|
||||
|
||||
func (r *Runtime) builtin_reflect_construct(call FunctionCall) Value {
|
||||
target := call.Argument(0)
|
||||
ctor := r.toConstructor(target)
|
||||
var newTarget Value
|
||||
if len(call.Arguments) > 2 {
|
||||
newTarget = call.Argument(2)
|
||||
r.toConstructor(newTarget)
|
||||
} else {
|
||||
newTarget = target
|
||||
}
|
||||
return ctor(r.createListFromArrayLike(call.Argument(1)), r.toObject(newTarget))
|
||||
}
|
||||
|
||||
func (r *Runtime) builtin_reflect_defineProperty(call FunctionCall) Value {
|
||||
target := r.toObject(call.Argument(0))
|
||||
key := toPropertyKey(call.Argument(1))
|
||||
desc := r.toPropertyDescriptor(call.Argument(2))
|
||||
|
||||
return r.toBoolean(target.defineOwnProperty(key, desc, false))
|
||||
}
|
||||
|
||||
func (r *Runtime) builtin_reflect_deleteProperty(call FunctionCall) Value {
|
||||
target := r.toObject(call.Argument(0))
|
||||
key := toPropertyKey(call.Argument(1))
|
||||
|
||||
return r.toBoolean(target.delete(key, false))
|
||||
}
|
||||
|
||||
func (r *Runtime) builtin_reflect_get(call FunctionCall) Value {
|
||||
target := r.toObject(call.Argument(0))
|
||||
key := toPropertyKey(call.Argument(1))
|
||||
var receiver Value
|
||||
if len(call.Arguments) > 2 {
|
||||
receiver = call.Arguments[2]
|
||||
}
|
||||
return target.get(key, receiver)
|
||||
}
|
||||
|
||||
func (r *Runtime) builtin_reflect_getOwnPropertyDescriptor(call FunctionCall) Value {
|
||||
target := r.toObject(call.Argument(0))
|
||||
key := toPropertyKey(call.Argument(1))
|
||||
return r.valuePropToDescriptorObject(target.getOwnProp(key))
|
||||
}
|
||||
|
||||
func (r *Runtime) builtin_reflect_getPrototypeOf(call FunctionCall) Value {
|
||||
target := r.toObject(call.Argument(0))
|
||||
if proto := target.self.proto(); proto != nil {
|
||||
return proto
|
||||
}
|
||||
|
||||
return _null
|
||||
}
|
||||
|
||||
func (r *Runtime) builtin_reflect_has(call FunctionCall) Value {
|
||||
target := r.toObject(call.Argument(0))
|
||||
key := toPropertyKey(call.Argument(1))
|
||||
return r.toBoolean(target.hasProperty(key))
|
||||
}
|
||||
|
||||
func (r *Runtime) builtin_reflect_isExtensible(call FunctionCall) Value {
|
||||
target := r.toObject(call.Argument(0))
|
||||
return r.toBoolean(target.self.isExtensible())
|
||||
}
|
||||
|
||||
func (r *Runtime) builtin_reflect_ownKeys(call FunctionCall) Value {
|
||||
target := r.toObject(call.Argument(0))
|
||||
return r.newArrayValues(target.self.keys(true, nil))
|
||||
}
|
||||
|
||||
func (r *Runtime) builtin_reflect_preventExtensions(call FunctionCall) Value {
|
||||
target := r.toObject(call.Argument(0))
|
||||
return r.toBoolean(target.self.preventExtensions(false))
|
||||
}
|
||||
|
||||
func (r *Runtime) builtin_reflect_set(call FunctionCall) Value {
|
||||
target := r.toObject(call.Argument(0))
|
||||
var receiver Value
|
||||
if len(call.Arguments) >= 4 {
|
||||
receiver = call.Argument(3)
|
||||
} else {
|
||||
receiver = target
|
||||
}
|
||||
return r.toBoolean(target.set(call.Argument(1), call.Argument(2), receiver, false))
|
||||
}
|
||||
|
||||
func (r *Runtime) builtin_reflect_setPrototypeOf(call FunctionCall) Value {
|
||||
target := r.toObject(call.Argument(0))
|
||||
var proto *Object
|
||||
if arg := call.Argument(1); arg != _null {
|
||||
proto = r.toObject(arg)
|
||||
}
|
||||
return r.toBoolean(target.self.setProto(proto, false))
|
||||
}
|
||||
|
||||
func (r *Runtime) createReflect(val *Object) objectImpl {
|
||||
o := newBaseObjectObj(val, r.global.ObjectPrototype, classObject)
|
||||
|
||||
o._putProp("apply", r.newNativeFunc(r.builtin_reflect_apply, nil, "apply", nil, 3), true, false, true)
|
||||
o._putProp("construct", r.newNativeFunc(r.builtin_reflect_construct, nil, "construct", nil, 2), true, false, true)
|
||||
o._putProp("defineProperty", r.newNativeFunc(r.builtin_reflect_defineProperty, nil, "defineProperty", nil, 3), true, false, true)
|
||||
o._putProp("deleteProperty", r.newNativeFunc(r.builtin_reflect_deleteProperty, nil, "deleteProperty", nil, 2), true, false, true)
|
||||
o._putProp("get", r.newNativeFunc(r.builtin_reflect_get, nil, "get", nil, 2), true, false, true)
|
||||
o._putProp("getOwnPropertyDescriptor", r.newNativeFunc(r.builtin_reflect_getOwnPropertyDescriptor, nil, "getOwnPropertyDescriptor", nil, 2), true, false, true)
|
||||
o._putProp("getPrototypeOf", r.newNativeFunc(r.builtin_reflect_getPrototypeOf, nil, "getPrototypeOf", nil, 1), true, false, true)
|
||||
o._putProp("has", r.newNativeFunc(r.builtin_reflect_has, nil, "has", nil, 2), true, false, true)
|
||||
o._putProp("isExtensible", r.newNativeFunc(r.builtin_reflect_isExtensible, nil, "isExtensible", nil, 1), true, false, true)
|
||||
o._putProp("ownKeys", r.newNativeFunc(r.builtin_reflect_ownKeys, nil, "ownKeys", nil, 1), true, false, true)
|
||||
o._putProp("preventExtensions", r.newNativeFunc(r.builtin_reflect_preventExtensions, nil, "preventExtensions", nil, 1), true, false, true)
|
||||
o._putProp("set", r.newNativeFunc(r.builtin_reflect_set, nil, "set", nil, 3), true, false, true)
|
||||
o._putProp("setPrototypeOf", r.newNativeFunc(r.builtin_reflect_setPrototypeOf, nil, "setPrototypeOf", nil, 2), true, false, true)
|
||||
|
||||
o._putSym(SymToStringTag, valueProp(asciiString("Reflect"), false, false, true))
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
func (r *Runtime) initReflect() {
|
||||
r.addToGlobal("Reflect", r.newLazyObject(r.createReflect))
|
||||
}
|
||||
1289
server/vendor/github.com/dop251/goja/builtin_regexp.go
generated
vendored
Normal file
1289
server/vendor/github.com/dop251/goja/builtin_regexp.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
333
server/vendor/github.com/dop251/goja/builtin_set.go
generated
vendored
Normal file
333
server/vendor/github.com/dop251/goja/builtin_set.go
generated
vendored
Normal file
@@ -0,0 +1,333 @@
|
||||
package goja
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
var setExportType = reflectTypeArray
|
||||
|
||||
type setObject struct {
|
||||
baseObject
|
||||
m *orderedMap
|
||||
}
|
||||
|
||||
type setIterObject struct {
|
||||
baseObject
|
||||
iter *orderedMapIter
|
||||
kind iterationKind
|
||||
}
|
||||
|
||||
func (o *setIterObject) next() Value {
|
||||
if o.iter == nil {
|
||||
return o.val.runtime.createIterResultObject(_undefined, true)
|
||||
}
|
||||
|
||||
entry := o.iter.next()
|
||||
if entry == nil {
|
||||
o.iter = nil
|
||||
return o.val.runtime.createIterResultObject(_undefined, true)
|
||||
}
|
||||
|
||||
var result Value
|
||||
switch o.kind {
|
||||
case iterationKindValue:
|
||||
result = entry.key
|
||||
default:
|
||||
result = o.val.runtime.newArrayValues([]Value{entry.key, entry.key})
|
||||
}
|
||||
|
||||
return o.val.runtime.createIterResultObject(result, false)
|
||||
}
|
||||
|
||||
func (so *setObject) init() {
|
||||
so.baseObject.init()
|
||||
so.m = newOrderedMap(so.val.runtime.getHash())
|
||||
}
|
||||
|
||||
func (so *setObject) exportType() reflect.Type {
|
||||
return setExportType
|
||||
}
|
||||
|
||||
func (so *setObject) export(ctx *objectExportCtx) interface{} {
|
||||
a := make([]interface{}, so.m.size)
|
||||
ctx.put(so.val, a)
|
||||
iter := so.m.newIter()
|
||||
for i := 0; i < len(a); i++ {
|
||||
entry := iter.next()
|
||||
if entry == nil {
|
||||
break
|
||||
}
|
||||
a[i] = exportValue(entry.key, ctx)
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
func (so *setObject) exportToArrayOrSlice(dst reflect.Value, typ reflect.Type, ctx *objectExportCtx) error {
|
||||
l := so.m.size
|
||||
if typ.Kind() == reflect.Array {
|
||||
if dst.Len() != l {
|
||||
return fmt.Errorf("cannot convert a Set into an array, lengths mismatch: have %d, need %d)", l, dst.Len())
|
||||
}
|
||||
} else {
|
||||
dst.Set(reflect.MakeSlice(typ, l, l))
|
||||
}
|
||||
ctx.putTyped(so.val, typ, dst.Interface())
|
||||
iter := so.m.newIter()
|
||||
r := so.val.runtime
|
||||
for i := 0; i < l; i++ {
|
||||
entry := iter.next()
|
||||
if entry == nil {
|
||||
break
|
||||
}
|
||||
err := r.toReflectValue(entry.key, dst.Index(i), ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (so *setObject) exportToMap(dst reflect.Value, typ reflect.Type, ctx *objectExportCtx) error {
|
||||
dst.Set(reflect.MakeMap(typ))
|
||||
keyTyp := typ.Key()
|
||||
elemTyp := typ.Elem()
|
||||
iter := so.m.newIter()
|
||||
r := so.val.runtime
|
||||
for {
|
||||
entry := iter.next()
|
||||
if entry == nil {
|
||||
break
|
||||
}
|
||||
keyVal := reflect.New(keyTyp).Elem()
|
||||
err := r.toReflectValue(entry.key, keyVal, ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
dst.SetMapIndex(keyVal, reflect.Zero(elemTyp))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Runtime) setProto_add(call FunctionCall) Value {
|
||||
thisObj := r.toObject(call.This)
|
||||
so, ok := thisObj.self.(*setObject)
|
||||
if !ok {
|
||||
panic(r.NewTypeError("Method Set.prototype.add called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
|
||||
}
|
||||
|
||||
so.m.set(call.Argument(0), nil)
|
||||
return call.This
|
||||
}
|
||||
|
||||
func (r *Runtime) setProto_clear(call FunctionCall) Value {
|
||||
thisObj := r.toObject(call.This)
|
||||
so, ok := thisObj.self.(*setObject)
|
||||
if !ok {
|
||||
panic(r.NewTypeError("Method Set.prototype.clear called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
|
||||
}
|
||||
|
||||
so.m.clear()
|
||||
return _undefined
|
||||
}
|
||||
|
||||
func (r *Runtime) setProto_delete(call FunctionCall) Value {
|
||||
thisObj := r.toObject(call.This)
|
||||
so, ok := thisObj.self.(*setObject)
|
||||
if !ok {
|
||||
panic(r.NewTypeError("Method Set.prototype.delete called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
|
||||
}
|
||||
|
||||
return r.toBoolean(so.m.remove(call.Argument(0)))
|
||||
}
|
||||
|
||||
func (r *Runtime) setProto_entries(call FunctionCall) Value {
|
||||
return r.createSetIterator(call.This, iterationKindKeyValue)
|
||||
}
|
||||
|
||||
func (r *Runtime) setProto_forEach(call FunctionCall) Value {
|
||||
thisObj := r.toObject(call.This)
|
||||
so, ok := thisObj.self.(*setObject)
|
||||
if !ok {
|
||||
panic(r.NewTypeError("Method Set.prototype.forEach called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
|
||||
}
|
||||
callbackFn, ok := r.toObject(call.Argument(0)).self.assertCallable()
|
||||
if !ok {
|
||||
panic(r.NewTypeError("object is not a function %s"))
|
||||
}
|
||||
t := call.Argument(1)
|
||||
iter := so.m.newIter()
|
||||
for {
|
||||
entry := iter.next()
|
||||
if entry == nil {
|
||||
break
|
||||
}
|
||||
callbackFn(FunctionCall{This: t, Arguments: []Value{entry.key, entry.key, thisObj}})
|
||||
}
|
||||
|
||||
return _undefined
|
||||
}
|
||||
|
||||
func (r *Runtime) setProto_has(call FunctionCall) Value {
|
||||
thisObj := r.toObject(call.This)
|
||||
so, ok := thisObj.self.(*setObject)
|
||||
if !ok {
|
||||
panic(r.NewTypeError("Method Set.prototype.has called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
|
||||
}
|
||||
|
||||
return r.toBoolean(so.m.has(call.Argument(0)))
|
||||
}
|
||||
|
||||
func (r *Runtime) setProto_getSize(call FunctionCall) Value {
|
||||
thisObj := r.toObject(call.This)
|
||||
so, ok := thisObj.self.(*setObject)
|
||||
if !ok {
|
||||
panic(r.NewTypeError("Method get Set.prototype.size called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
|
||||
}
|
||||
|
||||
return intToValue(int64(so.m.size))
|
||||
}
|
||||
|
||||
func (r *Runtime) setProto_values(call FunctionCall) Value {
|
||||
return r.createSetIterator(call.This, iterationKindValue)
|
||||
}
|
||||
|
||||
func (r *Runtime) builtin_newSet(args []Value, newTarget *Object) *Object {
|
||||
if newTarget == nil {
|
||||
panic(r.needNew("Set"))
|
||||
}
|
||||
proto := r.getPrototypeFromCtor(newTarget, r.global.Set, r.global.SetPrototype)
|
||||
o := &Object{runtime: r}
|
||||
|
||||
so := &setObject{}
|
||||
so.class = classObject
|
||||
so.val = o
|
||||
so.extensible = true
|
||||
o.self = so
|
||||
so.prototype = proto
|
||||
so.init()
|
||||
if len(args) > 0 {
|
||||
if arg := args[0]; arg != nil && arg != _undefined && arg != _null {
|
||||
adder := so.getStr("add", nil)
|
||||
stdArr := r.checkStdArrayIter(arg)
|
||||
if adder == r.global.setAdder {
|
||||
if stdArr != nil {
|
||||
for _, v := range stdArr.values {
|
||||
so.m.set(v, nil)
|
||||
}
|
||||
} else {
|
||||
r.getIterator(arg, nil).iterate(func(item Value) {
|
||||
so.m.set(item, nil)
|
||||
})
|
||||
}
|
||||
} else {
|
||||
adderFn := toMethod(adder)
|
||||
if adderFn == nil {
|
||||
panic(r.NewTypeError("Set.add in missing"))
|
||||
}
|
||||
if stdArr != nil {
|
||||
for _, item := range stdArr.values {
|
||||
adderFn(FunctionCall{This: o, Arguments: []Value{item}})
|
||||
}
|
||||
} else {
|
||||
r.getIterator(arg, nil).iterate(func(item Value) {
|
||||
adderFn(FunctionCall{This: o, Arguments: []Value{item}})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
func (r *Runtime) createSetIterator(setValue Value, kind iterationKind) Value {
|
||||
obj := r.toObject(setValue)
|
||||
setObj, ok := obj.self.(*setObject)
|
||||
if !ok {
|
||||
panic(r.NewTypeError("Object is not a Set"))
|
||||
}
|
||||
|
||||
o := &Object{runtime: r}
|
||||
|
||||
si := &setIterObject{
|
||||
iter: setObj.m.newIter(),
|
||||
kind: kind,
|
||||
}
|
||||
si.class = classObject
|
||||
si.val = o
|
||||
si.extensible = true
|
||||
o.self = si
|
||||
si.prototype = r.getSetIteratorPrototype()
|
||||
si.init()
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
func (r *Runtime) setIterProto_next(call FunctionCall) Value {
|
||||
thisObj := r.toObject(call.This)
|
||||
if iter, ok := thisObj.self.(*setIterObject); ok {
|
||||
return iter.next()
|
||||
}
|
||||
panic(r.NewTypeError("Method Set Iterator.prototype.next called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
|
||||
}
|
||||
|
||||
func (r *Runtime) createSetProto(val *Object) objectImpl {
|
||||
o := newBaseObjectObj(val, r.global.ObjectPrototype, classObject)
|
||||
|
||||
o._putProp("constructor", r.global.Set, true, false, true)
|
||||
r.global.setAdder = r.newNativeFunc(r.setProto_add, nil, "add", nil, 1)
|
||||
o._putProp("add", r.global.setAdder, true, false, true)
|
||||
|
||||
o._putProp("clear", r.newNativeFunc(r.setProto_clear, nil, "clear", nil, 0), true, false, true)
|
||||
o._putProp("delete", r.newNativeFunc(r.setProto_delete, nil, "delete", nil, 1), true, false, true)
|
||||
o._putProp("forEach", r.newNativeFunc(r.setProto_forEach, nil, "forEach", nil, 1), true, false, true)
|
||||
o._putProp("has", r.newNativeFunc(r.setProto_has, nil, "has", nil, 1), true, false, true)
|
||||
o.setOwnStr("size", &valueProperty{
|
||||
getterFunc: r.newNativeFunc(r.setProto_getSize, nil, "get size", nil, 0),
|
||||
accessor: true,
|
||||
writable: true,
|
||||
configurable: true,
|
||||
}, true)
|
||||
|
||||
valuesFunc := r.newNativeFunc(r.setProto_values, nil, "values", nil, 0)
|
||||
o._putProp("values", valuesFunc, true, false, true)
|
||||
o._putProp("keys", valuesFunc, true, false, true)
|
||||
o._putProp("entries", r.newNativeFunc(r.setProto_entries, nil, "entries", nil, 0), true, false, true)
|
||||
o._putSym(SymIterator, valueProp(valuesFunc, true, false, true))
|
||||
o._putSym(SymToStringTag, valueProp(asciiString(classSet), false, false, true))
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
func (r *Runtime) createSet(val *Object) objectImpl {
|
||||
o := r.newNativeConstructOnly(val, r.builtin_newSet, r.global.SetPrototype, "Set", 0)
|
||||
r.putSpeciesReturnThis(o)
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
func (r *Runtime) createSetIterProto(val *Object) objectImpl {
|
||||
o := newBaseObjectObj(val, r.getIteratorPrototype(), classObject)
|
||||
|
||||
o._putProp("next", r.newNativeFunc(r.setIterProto_next, nil, "next", nil, 0), true, false, true)
|
||||
o._putSym(SymToStringTag, valueProp(asciiString(classSetIterator), false, false, true))
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
func (r *Runtime) getSetIteratorPrototype() *Object {
|
||||
var o *Object
|
||||
if o = r.global.SetIteratorPrototype; o == nil {
|
||||
o = &Object{runtime: r}
|
||||
r.global.SetIteratorPrototype = o
|
||||
o.self = r.createSetIterProto(o)
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
func (r *Runtime) initSet() {
|
||||
r.global.SetPrototype = r.newLazyObject(r.createSetProto)
|
||||
r.global.Set = r.newLazyObject(r.createSet)
|
||||
|
||||
r.addToGlobal("Set", r.global.Set)
|
||||
}
|
||||
1004
server/vendor/github.com/dop251/goja/builtin_string.go
generated
vendored
Normal file
1004
server/vendor/github.com/dop251/goja/builtin_string.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
165
server/vendor/github.com/dop251/goja/builtin_symbol.go
generated
vendored
Normal file
165
server/vendor/github.com/dop251/goja/builtin_symbol.go
generated
vendored
Normal file
@@ -0,0 +1,165 @@
|
||||
package goja
|
||||
|
||||
import "github.com/dop251/goja/unistring"
|
||||
|
||||
var (
|
||||
SymHasInstance = newSymbol(asciiString("Symbol.hasInstance"))
|
||||
SymIsConcatSpreadable = newSymbol(asciiString("Symbol.isConcatSpreadable"))
|
||||
SymIterator = newSymbol(asciiString("Symbol.iterator"))
|
||||
SymMatch = newSymbol(asciiString("Symbol.match"))
|
||||
SymMatchAll = newSymbol(asciiString("Symbol.matchAll"))
|
||||
SymReplace = newSymbol(asciiString("Symbol.replace"))
|
||||
SymSearch = newSymbol(asciiString("Symbol.search"))
|
||||
SymSpecies = newSymbol(asciiString("Symbol.species"))
|
||||
SymSplit = newSymbol(asciiString("Symbol.split"))
|
||||
SymToPrimitive = newSymbol(asciiString("Symbol.toPrimitive"))
|
||||
SymToStringTag = newSymbol(asciiString("Symbol.toStringTag"))
|
||||
SymUnscopables = newSymbol(asciiString("Symbol.unscopables"))
|
||||
)
|
||||
|
||||
func (r *Runtime) builtin_symbol(call FunctionCall) Value {
|
||||
var desc valueString
|
||||
if arg := call.Argument(0); !IsUndefined(arg) {
|
||||
desc = arg.toString()
|
||||
}
|
||||
return newSymbol(desc)
|
||||
}
|
||||
|
||||
func (r *Runtime) symbolproto_tostring(call FunctionCall) Value {
|
||||
sym, ok := call.This.(*Symbol)
|
||||
if !ok {
|
||||
if obj, ok := call.This.(*Object); ok {
|
||||
if v, ok := obj.self.(*primitiveValueObject); ok {
|
||||
if sym1, ok := v.pValue.(*Symbol); ok {
|
||||
sym = sym1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if sym == nil {
|
||||
panic(r.NewTypeError("Method Symbol.prototype.toString is called on incompatible receiver"))
|
||||
}
|
||||
return sym.descriptiveString()
|
||||
}
|
||||
|
||||
func (r *Runtime) symbolproto_valueOf(call FunctionCall) Value {
|
||||
_, ok := call.This.(*Symbol)
|
||||
if ok {
|
||||
return call.This
|
||||
}
|
||||
|
||||
if obj, ok := call.This.(*Object); ok {
|
||||
if v, ok := obj.self.(*primitiveValueObject); ok {
|
||||
if sym, ok := v.pValue.(*Symbol); ok {
|
||||
return sym
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
panic(r.NewTypeError("Symbol.prototype.valueOf requires that 'this' be a Symbol"))
|
||||
}
|
||||
|
||||
func (r *Runtime) symbol_for(call FunctionCall) Value {
|
||||
key := call.Argument(0).toString()
|
||||
keyStr := key.string()
|
||||
if v := r.symbolRegistry[keyStr]; v != nil {
|
||||
return v
|
||||
}
|
||||
if r.symbolRegistry == nil {
|
||||
r.symbolRegistry = make(map[unistring.String]*Symbol)
|
||||
}
|
||||
v := newSymbol(key)
|
||||
r.symbolRegistry[keyStr] = v
|
||||
return v
|
||||
}
|
||||
|
||||
func (r *Runtime) symbol_keyfor(call FunctionCall) Value {
|
||||
arg := call.Argument(0)
|
||||
sym, ok := arg.(*Symbol)
|
||||
if !ok {
|
||||
panic(r.NewTypeError("%s is not a symbol", arg.String()))
|
||||
}
|
||||
for key, s := range r.symbolRegistry {
|
||||
if s == sym {
|
||||
return stringValueFromRaw(key)
|
||||
}
|
||||
}
|
||||
return _undefined
|
||||
}
|
||||
|
||||
func (r *Runtime) thisSymbolValue(v Value) *Symbol {
|
||||
if sym, ok := v.(*Symbol); ok {
|
||||
return sym
|
||||
}
|
||||
if obj, ok := v.(*Object); ok {
|
||||
if pVal, ok := obj.self.(*primitiveValueObject); ok {
|
||||
if sym, ok := pVal.pValue.(*Symbol); ok {
|
||||
return sym
|
||||
}
|
||||
}
|
||||
}
|
||||
panic(r.NewTypeError("Value is not a Symbol"))
|
||||
}
|
||||
|
||||
func (r *Runtime) createSymbolProto(val *Object) objectImpl {
|
||||
o := &baseObject{
|
||||
class: classObject,
|
||||
val: val,
|
||||
extensible: true,
|
||||
prototype: r.global.ObjectPrototype,
|
||||
}
|
||||
o.init()
|
||||
|
||||
o._putProp("constructor", r.global.Symbol, true, false, true)
|
||||
o.setOwnStr("description", &valueProperty{
|
||||
configurable: true,
|
||||
getterFunc: r.newNativeFunc(func(call FunctionCall) Value {
|
||||
return r.thisSymbolValue(call.This).desc
|
||||
}, nil, "get description", nil, 0),
|
||||
accessor: true,
|
||||
}, false)
|
||||
o._putProp("toString", r.newNativeFunc(r.symbolproto_tostring, nil, "toString", nil, 0), true, false, true)
|
||||
o._putProp("valueOf", r.newNativeFunc(r.symbolproto_valueOf, nil, "valueOf", nil, 0), true, false, true)
|
||||
o._putSym(SymToPrimitive, valueProp(r.newNativeFunc(r.symbolproto_valueOf, nil, "[Symbol.toPrimitive]", nil, 1), false, false, true))
|
||||
o._putSym(SymToStringTag, valueProp(newStringValue("Symbol"), false, false, true))
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
func (r *Runtime) createSymbol(val *Object) objectImpl {
|
||||
o := r.newNativeFuncObj(val, r.builtin_symbol, func(args []Value, proto *Object) *Object {
|
||||
panic(r.NewTypeError("Symbol is not a constructor"))
|
||||
}, "Symbol", r.global.SymbolPrototype, _positiveZero)
|
||||
|
||||
o._putProp("for", r.newNativeFunc(r.symbol_for, nil, "for", nil, 1), true, false, true)
|
||||
o._putProp("keyFor", r.newNativeFunc(r.symbol_keyfor, nil, "keyFor", nil, 1), true, false, true)
|
||||
|
||||
for _, s := range []*Symbol{
|
||||
SymHasInstance,
|
||||
SymIsConcatSpreadable,
|
||||
SymIterator,
|
||||
SymMatch,
|
||||
SymMatchAll,
|
||||
SymReplace,
|
||||
SymSearch,
|
||||
SymSpecies,
|
||||
SymSplit,
|
||||
SymToPrimitive,
|
||||
SymToStringTag,
|
||||
SymUnscopables,
|
||||
} {
|
||||
n := s.desc.(asciiString)
|
||||
n = n[len("Symbol."):]
|
||||
o._putProp(unistring.String(n), s, false, false, false)
|
||||
}
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
func (r *Runtime) initSymbol() {
|
||||
r.global.SymbolPrototype = r.newLazyObject(r.createSymbolProto)
|
||||
|
||||
r.global.Symbol = r.newLazyObject(r.createSymbol)
|
||||
r.addToGlobal("Symbol", r.global.Symbol)
|
||||
|
||||
}
|
||||
1599
server/vendor/github.com/dop251/goja/builtin_typedarrays.go
generated
vendored
Normal file
1599
server/vendor/github.com/dop251/goja/builtin_typedarrays.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
174
server/vendor/github.com/dop251/goja/builtin_weakmap.go
generated
vendored
Normal file
174
server/vendor/github.com/dop251/goja/builtin_weakmap.go
generated
vendored
Normal file
@@ -0,0 +1,174 @@
|
||||
package goja
|
||||
|
||||
type weakMap uint64
|
||||
|
||||
type weakMapObject struct {
|
||||
baseObject
|
||||
m weakMap
|
||||
}
|
||||
|
||||
func (wmo *weakMapObject) init() {
|
||||
wmo.baseObject.init()
|
||||
wmo.m = weakMap(wmo.val.runtime.genId())
|
||||
}
|
||||
|
||||
func (wm weakMap) set(key *Object, value Value) {
|
||||
key.getWeakRefs()[wm] = value
|
||||
}
|
||||
|
||||
func (wm weakMap) get(key *Object) Value {
|
||||
return key.weakRefs[wm]
|
||||
}
|
||||
|
||||
func (wm weakMap) remove(key *Object) bool {
|
||||
if _, exists := key.weakRefs[wm]; exists {
|
||||
delete(key.weakRefs, wm)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (wm weakMap) has(key *Object) bool {
|
||||
_, exists := key.weakRefs[wm]
|
||||
return exists
|
||||
}
|
||||
|
||||
func (r *Runtime) weakMapProto_delete(call FunctionCall) Value {
|
||||
thisObj := r.toObject(call.This)
|
||||
wmo, ok := thisObj.self.(*weakMapObject)
|
||||
if !ok {
|
||||
panic(r.NewTypeError("Method WeakMap.prototype.delete called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
|
||||
}
|
||||
key, ok := call.Argument(0).(*Object)
|
||||
if ok && wmo.m.remove(key) {
|
||||
return valueTrue
|
||||
}
|
||||
return valueFalse
|
||||
}
|
||||
|
||||
func (r *Runtime) weakMapProto_get(call FunctionCall) Value {
|
||||
thisObj := r.toObject(call.This)
|
||||
wmo, ok := thisObj.self.(*weakMapObject)
|
||||
if !ok {
|
||||
panic(r.NewTypeError("Method WeakMap.prototype.get called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
|
||||
}
|
||||
var res Value
|
||||
if key, ok := call.Argument(0).(*Object); ok {
|
||||
res = wmo.m.get(key)
|
||||
}
|
||||
if res == nil {
|
||||
return _undefined
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (r *Runtime) weakMapProto_has(call FunctionCall) Value {
|
||||
thisObj := r.toObject(call.This)
|
||||
wmo, ok := thisObj.self.(*weakMapObject)
|
||||
if !ok {
|
||||
panic(r.NewTypeError("Method WeakMap.prototype.has called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
|
||||
}
|
||||
key, ok := call.Argument(0).(*Object)
|
||||
if ok && wmo.m.has(key) {
|
||||
return valueTrue
|
||||
}
|
||||
return valueFalse
|
||||
}
|
||||
|
||||
func (r *Runtime) weakMapProto_set(call FunctionCall) Value {
|
||||
thisObj := r.toObject(call.This)
|
||||
wmo, ok := thisObj.self.(*weakMapObject)
|
||||
if !ok {
|
||||
panic(r.NewTypeError("Method WeakMap.prototype.set called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
|
||||
}
|
||||
key := r.toObject(call.Argument(0))
|
||||
wmo.m.set(key, call.Argument(1))
|
||||
return call.This
|
||||
}
|
||||
|
||||
func (r *Runtime) needNew(name string) *Object {
|
||||
return r.NewTypeError("Constructor %s requires 'new'", name)
|
||||
}
|
||||
|
||||
func (r *Runtime) getPrototypeFromCtor(newTarget, defCtor, defProto *Object) *Object {
|
||||
if newTarget == defCtor {
|
||||
return defProto
|
||||
}
|
||||
proto := newTarget.self.getStr("prototype", nil)
|
||||
if obj, ok := proto.(*Object); ok {
|
||||
return obj
|
||||
}
|
||||
return defProto
|
||||
}
|
||||
|
||||
func (r *Runtime) builtin_newWeakMap(args []Value, newTarget *Object) *Object {
|
||||
if newTarget == nil {
|
||||
panic(r.needNew("WeakMap"))
|
||||
}
|
||||
proto := r.getPrototypeFromCtor(newTarget, r.global.WeakMap, r.global.WeakMapPrototype)
|
||||
o := &Object{runtime: r}
|
||||
|
||||
wmo := &weakMapObject{}
|
||||
wmo.class = classObject
|
||||
wmo.val = o
|
||||
wmo.extensible = true
|
||||
o.self = wmo
|
||||
wmo.prototype = proto
|
||||
wmo.init()
|
||||
if len(args) > 0 {
|
||||
if arg := args[0]; arg != nil && arg != _undefined && arg != _null {
|
||||
adder := wmo.getStr("set", nil)
|
||||
adderFn := toMethod(adder)
|
||||
if adderFn == nil {
|
||||
panic(r.NewTypeError("WeakMap.set in missing"))
|
||||
}
|
||||
iter := r.getIterator(arg, nil)
|
||||
i0 := valueInt(0)
|
||||
i1 := valueInt(1)
|
||||
if adder == r.global.weakMapAdder {
|
||||
iter.iterate(func(item Value) {
|
||||
itemObj := r.toObject(item)
|
||||
k := itemObj.self.getIdx(i0, nil)
|
||||
v := nilSafe(itemObj.self.getIdx(i1, nil))
|
||||
wmo.m.set(r.toObject(k), v)
|
||||
})
|
||||
} else {
|
||||
iter.iterate(func(item Value) {
|
||||
itemObj := r.toObject(item)
|
||||
k := itemObj.self.getIdx(i0, nil)
|
||||
v := itemObj.self.getIdx(i1, nil)
|
||||
adderFn(FunctionCall{This: o, Arguments: []Value{k, v}})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
func (r *Runtime) createWeakMapProto(val *Object) objectImpl {
|
||||
o := newBaseObjectObj(val, r.global.ObjectPrototype, classObject)
|
||||
|
||||
o._putProp("constructor", r.global.WeakMap, true, false, true)
|
||||
r.global.weakMapAdder = r.newNativeFunc(r.weakMapProto_set, nil, "set", nil, 2)
|
||||
o._putProp("set", r.global.weakMapAdder, true, false, true)
|
||||
o._putProp("delete", r.newNativeFunc(r.weakMapProto_delete, nil, "delete", nil, 1), true, false, true)
|
||||
o._putProp("has", r.newNativeFunc(r.weakMapProto_has, nil, "has", nil, 1), true, false, true)
|
||||
o._putProp("get", r.newNativeFunc(r.weakMapProto_get, nil, "get", nil, 1), true, false, true)
|
||||
|
||||
o._putSym(SymToStringTag, valueProp(asciiString(classWeakMap), false, false, true))
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
func (r *Runtime) createWeakMap(val *Object) objectImpl {
|
||||
o := r.newNativeConstructOnly(val, r.builtin_newWeakMap, r.global.WeakMapPrototype, "WeakMap", 0)
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
func (r *Runtime) initWeakMap() {
|
||||
r.global.WeakMapPrototype = r.newLazyObject(r.createWeakMapProto)
|
||||
r.global.WeakMap = r.newLazyObject(r.createWeakMap)
|
||||
|
||||
r.addToGlobal("WeakMap", r.global.WeakMap)
|
||||
}
|
||||
122
server/vendor/github.com/dop251/goja/builtin_weakset.go
generated
vendored
Normal file
122
server/vendor/github.com/dop251/goja/builtin_weakset.go
generated
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
package goja
|
||||
|
||||
type weakSetObject struct {
|
||||
baseObject
|
||||
s weakMap
|
||||
}
|
||||
|
||||
func (ws *weakSetObject) init() {
|
||||
ws.baseObject.init()
|
||||
ws.s = weakMap(ws.val.runtime.genId())
|
||||
}
|
||||
|
||||
func (r *Runtime) weakSetProto_add(call FunctionCall) Value {
|
||||
thisObj := r.toObject(call.This)
|
||||
wso, ok := thisObj.self.(*weakSetObject)
|
||||
if !ok {
|
||||
panic(r.NewTypeError("Method WeakSet.prototype.add called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
|
||||
}
|
||||
wso.s.set(r.toObject(call.Argument(0)), nil)
|
||||
return call.This
|
||||
}
|
||||
|
||||
func (r *Runtime) weakSetProto_delete(call FunctionCall) Value {
|
||||
thisObj := r.toObject(call.This)
|
||||
wso, ok := thisObj.self.(*weakSetObject)
|
||||
if !ok {
|
||||
panic(r.NewTypeError("Method WeakSet.prototype.delete called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
|
||||
}
|
||||
obj, ok := call.Argument(0).(*Object)
|
||||
if ok && wso.s.remove(obj) {
|
||||
return valueTrue
|
||||
}
|
||||
return valueFalse
|
||||
}
|
||||
|
||||
func (r *Runtime) weakSetProto_has(call FunctionCall) Value {
|
||||
thisObj := r.toObject(call.This)
|
||||
wso, ok := thisObj.self.(*weakSetObject)
|
||||
if !ok {
|
||||
panic(r.NewTypeError("Method WeakSet.prototype.has called on incompatible receiver %s", r.objectproto_toString(FunctionCall{This: thisObj})))
|
||||
}
|
||||
obj, ok := call.Argument(0).(*Object)
|
||||
if ok && wso.s.has(obj) {
|
||||
return valueTrue
|
||||
}
|
||||
return valueFalse
|
||||
}
|
||||
|
||||
func (r *Runtime) builtin_newWeakSet(args []Value, newTarget *Object) *Object {
|
||||
if newTarget == nil {
|
||||
panic(r.needNew("WeakSet"))
|
||||
}
|
||||
proto := r.getPrototypeFromCtor(newTarget, r.global.WeakSet, r.global.WeakSetPrototype)
|
||||
o := &Object{runtime: r}
|
||||
|
||||
wso := &weakSetObject{}
|
||||
wso.class = classObject
|
||||
wso.val = o
|
||||
wso.extensible = true
|
||||
o.self = wso
|
||||
wso.prototype = proto
|
||||
wso.init()
|
||||
if len(args) > 0 {
|
||||
if arg := args[0]; arg != nil && arg != _undefined && arg != _null {
|
||||
adder := wso.getStr("add", nil)
|
||||
stdArr := r.checkStdArrayIter(arg)
|
||||
if adder == r.global.weakSetAdder {
|
||||
if stdArr != nil {
|
||||
for _, v := range stdArr.values {
|
||||
wso.s.set(r.toObject(v), nil)
|
||||
}
|
||||
} else {
|
||||
r.getIterator(arg, nil).iterate(func(item Value) {
|
||||
wso.s.set(r.toObject(item), nil)
|
||||
})
|
||||
}
|
||||
} else {
|
||||
adderFn := toMethod(adder)
|
||||
if adderFn == nil {
|
||||
panic(r.NewTypeError("WeakSet.add in missing"))
|
||||
}
|
||||
if stdArr != nil {
|
||||
for _, item := range stdArr.values {
|
||||
adderFn(FunctionCall{This: o, Arguments: []Value{item}})
|
||||
}
|
||||
} else {
|
||||
r.getIterator(arg, nil).iterate(func(item Value) {
|
||||
adderFn(FunctionCall{This: o, Arguments: []Value{item}})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
func (r *Runtime) createWeakSetProto(val *Object) objectImpl {
|
||||
o := newBaseObjectObj(val, r.global.ObjectPrototype, classObject)
|
||||
|
||||
o._putProp("constructor", r.global.WeakSet, true, false, true)
|
||||
r.global.weakSetAdder = r.newNativeFunc(r.weakSetProto_add, nil, "add", nil, 1)
|
||||
o._putProp("add", r.global.weakSetAdder, true, false, true)
|
||||
o._putProp("delete", r.newNativeFunc(r.weakSetProto_delete, nil, "delete", nil, 1), true, false, true)
|
||||
o._putProp("has", r.newNativeFunc(r.weakSetProto_has, nil, "has", nil, 1), true, false, true)
|
||||
|
||||
o._putSym(SymToStringTag, valueProp(asciiString(classWeakSet), false, false, true))
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
func (r *Runtime) createWeakSet(val *Object) objectImpl {
|
||||
o := r.newNativeConstructOnly(val, r.builtin_newWeakSet, r.global.WeakSetPrototype, "WeakSet", 0)
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
func (r *Runtime) initWeakSet() {
|
||||
r.global.WeakSetPrototype = r.newLazyObject(r.createWeakSetProto)
|
||||
r.global.WeakSet = r.newLazyObject(r.createWeakSet)
|
||||
|
||||
r.addToGlobal("WeakSet", r.global.WeakSet)
|
||||
}
|
||||
1463
server/vendor/github.com/dop251/goja/compiler.go
generated
vendored
Normal file
1463
server/vendor/github.com/dop251/goja/compiler.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
3608
server/vendor/github.com/dop251/goja/compiler_expr.go
generated
vendored
Normal file
3608
server/vendor/github.com/dop251/goja/compiler_expr.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1127
server/vendor/github.com/dop251/goja/compiler_stmt.go
generated
vendored
Normal file
1127
server/vendor/github.com/dop251/goja/compiler_stmt.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
174
server/vendor/github.com/dop251/goja/date.go
generated
vendored
Normal file
174
server/vendor/github.com/dop251/goja/date.go
generated
vendored
Normal file
@@ -0,0 +1,174 @@
|
||||
package goja
|
||||
|
||||
import (
|
||||
"math"
|
||||
"reflect"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
dateTimeLayout = "Mon Jan 02 2006 15:04:05 GMT-0700 (MST)"
|
||||
utcDateTimeLayout = "Mon, 02 Jan 2006 15:04:05 GMT"
|
||||
isoDateTimeLayout = "2006-01-02T15:04:05.000Z"
|
||||
dateLayout = "Mon Jan 02 2006"
|
||||
timeLayout = "15:04:05 GMT-0700 (MST)"
|
||||
datetimeLayout_en_GB = "01/02/2006, 15:04:05"
|
||||
dateLayout_en_GB = "01/02/2006"
|
||||
timeLayout_en_GB = "15:04:05"
|
||||
|
||||
maxTime = 8.64e15
|
||||
timeUnset = math.MinInt64
|
||||
)
|
||||
|
||||
type dateObject struct {
|
||||
baseObject
|
||||
msec int64
|
||||
}
|
||||
|
||||
type dateLayoutDesc struct {
|
||||
layout string
|
||||
dateOnly bool
|
||||
}
|
||||
|
||||
var (
|
||||
dateLayoutsNumeric = []dateLayoutDesc{
|
||||
{layout: "2006-01-02T15:04:05Z0700"},
|
||||
{layout: "2006-01-02T15:04:05"},
|
||||
{layout: "2006-01-02", dateOnly: true},
|
||||
{layout: "2006-01-02 15:04:05"},
|
||||
|
||||
{layout: "2006", dateOnly: true},
|
||||
{layout: "2006-01", dateOnly: true},
|
||||
|
||||
{layout: "2006T15:04"},
|
||||
{layout: "2006-01T15:04"},
|
||||
{layout: "2006-01-02T15:04"},
|
||||
|
||||
{layout: "2006T15:04:05"},
|
||||
{layout: "2006-01T15:04:05"},
|
||||
|
||||
{layout: "2006T15:04Z0700"},
|
||||
{layout: "2006-01T15:04Z0700"},
|
||||
{layout: "2006-01-02T15:04Z0700"},
|
||||
|
||||
{layout: "2006T15:04:05Z0700"},
|
||||
{layout: "2006-01T15:04:05Z0700"},
|
||||
}
|
||||
|
||||
dateLayoutsAlpha = []dateLayoutDesc{
|
||||
{layout: time.RFC1123},
|
||||
{layout: time.RFC1123Z},
|
||||
{layout: dateTimeLayout},
|
||||
{layout: time.UnixDate},
|
||||
{layout: time.ANSIC},
|
||||
{layout: time.RubyDate},
|
||||
{layout: "Mon, _2 Jan 2006 15:04:05 GMT-0700 (MST)"},
|
||||
{layout: "Mon, _2 Jan 2006 15:04:05 -0700 (MST)"},
|
||||
{layout: "Jan _2, 2006", dateOnly: true},
|
||||
}
|
||||
)
|
||||
|
||||
func dateParse(date string) (time.Time, bool) {
|
||||
var t time.Time
|
||||
var err error
|
||||
var layouts []dateLayoutDesc
|
||||
if len(date) > 0 {
|
||||
first := date[0]
|
||||
if first <= '9' && (first >= '0' || first == '-' || first == '+') {
|
||||
layouts = dateLayoutsNumeric
|
||||
} else {
|
||||
layouts = dateLayoutsAlpha
|
||||
}
|
||||
} else {
|
||||
return time.Time{}, false
|
||||
}
|
||||
for _, desc := range layouts {
|
||||
var defLoc *time.Location
|
||||
if desc.dateOnly {
|
||||
defLoc = time.UTC
|
||||
} else {
|
||||
defLoc = time.Local
|
||||
}
|
||||
t, err = parseDate(desc.layout, date, defLoc)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return time.Time{}, false
|
||||
}
|
||||
unix := timeToMsec(t)
|
||||
return t, unix >= -maxTime && unix <= maxTime
|
||||
}
|
||||
|
||||
func (r *Runtime) newDateObject(t time.Time, isSet bool, proto *Object) *Object {
|
||||
v := &Object{runtime: r}
|
||||
d := &dateObject{}
|
||||
v.self = d
|
||||
d.val = v
|
||||
d.class = classDate
|
||||
d.prototype = proto
|
||||
d.extensible = true
|
||||
d.init()
|
||||
if isSet {
|
||||
d.msec = timeToMsec(t)
|
||||
} else {
|
||||
d.msec = timeUnset
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func dateFormat(t time.Time) string {
|
||||
return t.Local().Format(dateTimeLayout)
|
||||
}
|
||||
|
||||
func timeFromMsec(msec int64) time.Time {
|
||||
sec := msec / 1000
|
||||
nsec := (msec % 1000) * 1e6
|
||||
return time.Unix(sec, nsec)
|
||||
}
|
||||
|
||||
func timeToMsec(t time.Time) int64 {
|
||||
return t.Unix()*1000 + int64(t.Nanosecond())/1e6
|
||||
}
|
||||
|
||||
func (d *dateObject) toPrimitive() Value {
|
||||
return d.toPrimitiveString()
|
||||
}
|
||||
|
||||
func (d *dateObject) exportType() reflect.Type {
|
||||
return typeTime
|
||||
}
|
||||
|
||||
func (d *dateObject) export(*objectExportCtx) interface{} {
|
||||
if d.isSet() {
|
||||
return d.time()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *dateObject) setTimeMs(ms int64) Value {
|
||||
if ms >= 0 && ms <= maxTime || ms < 0 && ms >= -maxTime {
|
||||
d.msec = ms
|
||||
return intToValue(ms)
|
||||
}
|
||||
|
||||
d.unset()
|
||||
return _NaN
|
||||
}
|
||||
|
||||
func (d *dateObject) isSet() bool {
|
||||
return d.msec != timeUnset
|
||||
}
|
||||
|
||||
func (d *dateObject) unset() {
|
||||
d.msec = timeUnset
|
||||
}
|
||||
|
||||
func (d *dateObject) time() time.Time {
|
||||
return timeFromMsec(d.msec)
|
||||
}
|
||||
|
||||
func (d *dateObject) timeUTC() time.Time {
|
||||
return timeFromMsec(d.msec).In(time.UTC)
|
||||
}
|
||||
865
server/vendor/github.com/dop251/goja/date_parser.go
generated
vendored
Normal file
865
server/vendor/github.com/dop251/goja/date_parser.go
generated
vendored
Normal file
@@ -0,0 +1,865 @@
|
||||
package goja
|
||||
|
||||
// This is a slightly modified version of the standard Go parser to make it more compatible with ECMAScript 5.1
|
||||
// Changes:
|
||||
// - 6-digit extended years are supported in place of long year (2006) in the form of +123456
|
||||
// - Timezone formats tolerate colons, e.g. -0700 will parse -07:00
|
||||
// - Short week day will also parse long week day
|
||||
// - Short month ("Jan") will also parse long month ("January")
|
||||
// - Long day ("02") will also parse short day ("2").
|
||||
// - Timezone in brackets, "(MST)", will match any string in brackets (e.g. "(GMT Standard Time)")
|
||||
// - If offset is not set and timezone name is unknown, an error is returned
|
||||
// - If offset and timezone name are both set the offset takes precedence and the resulting Location will be FixedZone("", offset)
|
||||
|
||||
// Original copyright message:
|
||||
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
_ = iota
|
||||
stdLongMonth = iota + stdNeedDate // "January"
|
||||
stdMonth // "Jan"
|
||||
stdNumMonth // "1"
|
||||
stdZeroMonth // "01"
|
||||
stdLongWeekDay // "Monday"
|
||||
stdWeekDay // "Mon"
|
||||
stdDay // "2"
|
||||
stdUnderDay // "_2"
|
||||
stdZeroDay // "02"
|
||||
stdHour = iota + stdNeedClock // "15"
|
||||
stdHour12 // "3"
|
||||
stdZeroHour12 // "03"
|
||||
stdMinute // "4"
|
||||
stdZeroMinute // "04"
|
||||
stdSecond // "5"
|
||||
stdZeroSecond // "05"
|
||||
stdLongYear = iota + stdNeedDate // "2006"
|
||||
stdYear // "06"
|
||||
stdPM = iota + stdNeedClock // "PM"
|
||||
stdpm // "pm"
|
||||
stdTZ = iota // "MST"
|
||||
stdBracketTZ // "(MST)"
|
||||
stdISO8601TZ // "Z0700" // prints Z for UTC
|
||||
stdISO8601SecondsTZ // "Z070000"
|
||||
stdISO8601ShortTZ // "Z07"
|
||||
stdISO8601ColonTZ // "Z07:00" // prints Z for UTC
|
||||
stdISO8601ColonSecondsTZ // "Z07:00:00"
|
||||
stdNumTZ // "-0700" // always numeric
|
||||
stdNumSecondsTz // "-070000"
|
||||
stdNumShortTZ // "-07" // always numeric
|
||||
stdNumColonTZ // "-07:00" // always numeric
|
||||
stdNumColonSecondsTZ // "-07:00:00"
|
||||
stdFracSecond0 // ".0", ".00", ... , trailing zeros included
|
||||
stdFracSecond9 // ".9", ".99", ..., trailing zeros omitted
|
||||
|
||||
stdNeedDate = 1 << 8 // need month, day, year
|
||||
stdNeedClock = 2 << 8 // need hour, minute, second
|
||||
stdArgShift = 16 // extra argument in high bits, above low stdArgShift
|
||||
stdMask = 1<<stdArgShift - 1 // mask out argument
|
||||
)
|
||||
|
||||
var errBad = errors.New("bad value for field") // placeholder not passed to user
|
||||
|
||||
func parseDate(layout, value string, defaultLocation *time.Location) (time.Time, error) {
|
||||
alayout, avalue := layout, value
|
||||
rangeErrString := "" // set if a value is out of range
|
||||
amSet := false // do we need to subtract 12 from the hour for midnight?
|
||||
pmSet := false // do we need to add 12 to the hour?
|
||||
|
||||
// Time being constructed.
|
||||
var (
|
||||
year int
|
||||
month int = 1 // January
|
||||
day int = 1
|
||||
hour int
|
||||
min int
|
||||
sec int
|
||||
nsec int
|
||||
z *time.Location
|
||||
zoneOffset int = -1
|
||||
zoneName string
|
||||
)
|
||||
|
||||
// Each iteration processes one std value.
|
||||
for {
|
||||
var err error
|
||||
prefix, std, suffix := nextStdChunk(layout)
|
||||
stdstr := layout[len(prefix) : len(layout)-len(suffix)]
|
||||
value, err = skip(value, prefix)
|
||||
if err != nil {
|
||||
return time.Time{}, &time.ParseError{Layout: alayout, Value: avalue, LayoutElem: prefix, ValueElem: value}
|
||||
}
|
||||
if std == 0 {
|
||||
if len(value) != 0 {
|
||||
return time.Time{}, &time.ParseError{Layout: alayout, Value: avalue, ValueElem: value, Message: ": extra text: " + value}
|
||||
}
|
||||
break
|
||||
}
|
||||
layout = suffix
|
||||
var p string
|
||||
switch std & stdMask {
|
||||
case stdYear:
|
||||
if len(value) < 2 {
|
||||
err = errBad
|
||||
break
|
||||
}
|
||||
p, value = value[0:2], value[2:]
|
||||
year, err = atoi(p)
|
||||
if year >= 69 { // Unix time starts Dec 31 1969 in some time zones
|
||||
year += 1900
|
||||
} else {
|
||||
year += 2000
|
||||
}
|
||||
case stdLongYear:
|
||||
if len(value) >= 7 && (value[0] == '-' || value[0] == '+') { // extended year
|
||||
neg := value[0] == '-'
|
||||
p, value = value[1:7], value[7:]
|
||||
year, err = atoi(p)
|
||||
if neg {
|
||||
year = -year
|
||||
}
|
||||
} else {
|
||||
if len(value) < 4 || !isDigit(value, 0) {
|
||||
err = errBad
|
||||
break
|
||||
}
|
||||
p, value = value[0:4], value[4:]
|
||||
year, err = atoi(p)
|
||||
}
|
||||
|
||||
case stdMonth:
|
||||
month, value, err = lookup(longMonthNames, value)
|
||||
if err != nil {
|
||||
month, value, err = lookup(shortMonthNames, value)
|
||||
}
|
||||
month++
|
||||
case stdLongMonth:
|
||||
month, value, err = lookup(longMonthNames, value)
|
||||
month++
|
||||
case stdNumMonth, stdZeroMonth:
|
||||
month, value, err = getnum(value, std == stdZeroMonth)
|
||||
if month <= 0 || 12 < month {
|
||||
rangeErrString = "month"
|
||||
}
|
||||
case stdWeekDay:
|
||||
// Ignore weekday except for error checking.
|
||||
_, value, err = lookup(longDayNames, value)
|
||||
if err != nil {
|
||||
_, value, err = lookup(shortDayNames, value)
|
||||
}
|
||||
case stdLongWeekDay:
|
||||
_, value, err = lookup(longDayNames, value)
|
||||
case stdDay, stdUnderDay, stdZeroDay:
|
||||
if std == stdUnderDay && len(value) > 0 && value[0] == ' ' {
|
||||
value = value[1:]
|
||||
}
|
||||
day, value, err = getnum(value, false)
|
||||
if day < 0 {
|
||||
// Note that we allow any one- or two-digit day here.
|
||||
rangeErrString = "day"
|
||||
}
|
||||
case stdHour:
|
||||
hour, value, err = getnum(value, false)
|
||||
if hour < 0 || 24 <= hour {
|
||||
rangeErrString = "hour"
|
||||
}
|
||||
case stdHour12, stdZeroHour12:
|
||||
hour, value, err = getnum(value, std == stdZeroHour12)
|
||||
if hour < 0 || 12 < hour {
|
||||
rangeErrString = "hour"
|
||||
}
|
||||
case stdMinute, stdZeroMinute:
|
||||
min, value, err = getnum(value, std == stdZeroMinute)
|
||||
if min < 0 || 60 <= min {
|
||||
rangeErrString = "minute"
|
||||
}
|
||||
case stdSecond, stdZeroSecond:
|
||||
sec, value, err = getnum(value, std == stdZeroSecond)
|
||||
if sec < 0 || 60 <= sec {
|
||||
rangeErrString = "second"
|
||||
break
|
||||
}
|
||||
// Special case: do we have a fractional second but no
|
||||
// fractional second in the format?
|
||||
if len(value) >= 2 && value[0] == '.' && isDigit(value, 1) {
|
||||
_, std, _ = nextStdChunk(layout)
|
||||
std &= stdMask
|
||||
if std == stdFracSecond0 || std == stdFracSecond9 {
|
||||
// Fractional second in the layout; proceed normally
|
||||
break
|
||||
}
|
||||
// No fractional second in the layout but we have one in the input.
|
||||
n := 2
|
||||
for ; n < len(value) && isDigit(value, n); n++ {
|
||||
}
|
||||
nsec, rangeErrString, err = parseNanoseconds(value, n)
|
||||
value = value[n:]
|
||||
}
|
||||
case stdPM:
|
||||
if len(value) < 2 {
|
||||
err = errBad
|
||||
break
|
||||
}
|
||||
p, value = value[0:2], value[2:]
|
||||
switch p {
|
||||
case "PM":
|
||||
pmSet = true
|
||||
case "AM":
|
||||
amSet = true
|
||||
default:
|
||||
err = errBad
|
||||
}
|
||||
case stdpm:
|
||||
if len(value) < 2 {
|
||||
err = errBad
|
||||
break
|
||||
}
|
||||
p, value = value[0:2], value[2:]
|
||||
switch p {
|
||||
case "pm":
|
||||
pmSet = true
|
||||
case "am":
|
||||
amSet = true
|
||||
default:
|
||||
err = errBad
|
||||
}
|
||||
case stdISO8601TZ, stdISO8601ColonTZ, stdISO8601SecondsTZ, stdISO8601ShortTZ, stdISO8601ColonSecondsTZ, stdNumTZ, stdNumShortTZ, stdNumColonTZ, stdNumSecondsTz, stdNumColonSecondsTZ:
|
||||
if (std == stdISO8601TZ || std == stdISO8601ShortTZ || std == stdISO8601ColonTZ ||
|
||||
std == stdISO8601SecondsTZ || std == stdISO8601ColonSecondsTZ) && len(value) >= 1 && value[0] == 'Z' {
|
||||
|
||||
value = value[1:]
|
||||
z = time.UTC
|
||||
break
|
||||
}
|
||||
var sign, hour, min, seconds string
|
||||
if std == stdISO8601ColonTZ || std == stdNumColonTZ || std == stdNumTZ || std == stdISO8601TZ {
|
||||
if len(value) < 4 {
|
||||
err = errBad
|
||||
break
|
||||
}
|
||||
if value[3] != ':' {
|
||||
if std == stdNumColonTZ || std == stdISO8601ColonTZ || len(value) < 5 {
|
||||
err = errBad
|
||||
break
|
||||
}
|
||||
sign, hour, min, seconds, value = value[0:1], value[1:3], value[3:5], "00", value[5:]
|
||||
} else {
|
||||
if len(value) < 6 {
|
||||
err = errBad
|
||||
break
|
||||
}
|
||||
sign, hour, min, seconds, value = value[0:1], value[1:3], value[4:6], "00", value[6:]
|
||||
}
|
||||
} else if std == stdNumShortTZ || std == stdISO8601ShortTZ {
|
||||
if len(value) < 3 {
|
||||
err = errBad
|
||||
break
|
||||
}
|
||||
sign, hour, min, seconds, value = value[0:1], value[1:3], "00", "00", value[3:]
|
||||
} else if std == stdISO8601ColonSecondsTZ || std == stdNumColonSecondsTZ || std == stdISO8601SecondsTZ || std == stdNumSecondsTz {
|
||||
if len(value) < 7 {
|
||||
err = errBad
|
||||
break
|
||||
}
|
||||
if value[3] != ':' || value[6] != ':' {
|
||||
if std == stdISO8601ColonSecondsTZ || std == stdNumColonSecondsTZ || len(value) < 7 {
|
||||
err = errBad
|
||||
break
|
||||
}
|
||||
sign, hour, min, seconds, value = value[0:1], value[1:3], value[3:5], value[5:7], value[7:]
|
||||
} else {
|
||||
if len(value) < 9 {
|
||||
err = errBad
|
||||
break
|
||||
}
|
||||
sign, hour, min, seconds, value = value[0:1], value[1:3], value[4:6], value[7:9], value[9:]
|
||||
}
|
||||
}
|
||||
var hr, mm, ss int
|
||||
hr, err = atoi(hour)
|
||||
if err == nil {
|
||||
mm, err = atoi(min)
|
||||
}
|
||||
if err == nil {
|
||||
ss, err = atoi(seconds)
|
||||
}
|
||||
zoneOffset = (hr*60+mm)*60 + ss // offset is in seconds
|
||||
switch sign[0] {
|
||||
case '+':
|
||||
case '-':
|
||||
zoneOffset = -zoneOffset
|
||||
default:
|
||||
err = errBad
|
||||
}
|
||||
case stdTZ:
|
||||
// Does it look like a time zone?
|
||||
if len(value) >= 3 && value[0:3] == "UTC" {
|
||||
z = time.UTC
|
||||
value = value[3:]
|
||||
break
|
||||
}
|
||||
n, ok := parseTimeZone(value)
|
||||
if !ok {
|
||||
err = errBad
|
||||
break
|
||||
}
|
||||
zoneName, value = value[:n], value[n:]
|
||||
case stdBracketTZ:
|
||||
if len(value) < 3 || value[0] != '(' {
|
||||
err = errBad
|
||||
break
|
||||
}
|
||||
i := 1
|
||||
for ; ; i++ {
|
||||
if i >= len(value) {
|
||||
err = errBad
|
||||
break
|
||||
}
|
||||
if value[i] == ')' {
|
||||
zoneName, value = value[1:i], value[i+1:]
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
case stdFracSecond0:
|
||||
// stdFracSecond0 requires the exact number of digits as specified in
|
||||
// the layout.
|
||||
ndigit := 1 + (std >> stdArgShift)
|
||||
if len(value) < ndigit {
|
||||
err = errBad
|
||||
break
|
||||
}
|
||||
nsec, rangeErrString, err = parseNanoseconds(value, ndigit)
|
||||
value = value[ndigit:]
|
||||
|
||||
case stdFracSecond9:
|
||||
if len(value) < 2 || value[0] != '.' || value[1] < '0' || '9' < value[1] {
|
||||
// Fractional second omitted.
|
||||
break
|
||||
}
|
||||
// Take any number of digits, even more than asked for,
|
||||
// because it is what the stdSecond case would do.
|
||||
i := 0
|
||||
for i < 9 && i+1 < len(value) && '0' <= value[i+1] && value[i+1] <= '9' {
|
||||
i++
|
||||
}
|
||||
nsec, rangeErrString, err = parseNanoseconds(value, 1+i)
|
||||
value = value[1+i:]
|
||||
}
|
||||
if rangeErrString != "" {
|
||||
return time.Time{}, &time.ParseError{Layout: alayout, Value: avalue, LayoutElem: stdstr, ValueElem: value, Message: ": " + rangeErrString + " out of range"}
|
||||
}
|
||||
if err != nil {
|
||||
return time.Time{}, &time.ParseError{Layout: alayout, Value: avalue, LayoutElem: stdstr, ValueElem: value}
|
||||
}
|
||||
}
|
||||
if pmSet && hour < 12 {
|
||||
hour += 12
|
||||
} else if amSet && hour == 12 {
|
||||
hour = 0
|
||||
}
|
||||
|
||||
// Validate the day of the month.
|
||||
if day < 1 || day > daysIn(time.Month(month), year) {
|
||||
return time.Time{}, &time.ParseError{Layout: alayout, Value: avalue, ValueElem: value, Message: ": day out of range"}
|
||||
}
|
||||
|
||||
if z == nil {
|
||||
if zoneOffset == -1 {
|
||||
if zoneName != "" {
|
||||
if z1, err := time.LoadLocation(zoneName); err == nil {
|
||||
z = z1
|
||||
} else {
|
||||
return time.Time{}, &time.ParseError{Layout: alayout, Value: avalue, ValueElem: value, Message: ": unknown timezone"}
|
||||
}
|
||||
} else {
|
||||
z = defaultLocation
|
||||
}
|
||||
} else if zoneOffset == 0 {
|
||||
z = time.UTC
|
||||
} else {
|
||||
z = time.FixedZone("", zoneOffset)
|
||||
}
|
||||
}
|
||||
|
||||
return time.Date(year, time.Month(month), day, hour, min, sec, nsec, z), nil
|
||||
}
|
||||
|
||||
var errLeadingInt = errors.New("time: bad [0-9]*") // never printed
|
||||
|
||||
func signedLeadingInt(s string) (x int64, rem string, err error) {
|
||||
neg := false
|
||||
if s != "" && (s[0] == '-' || s[0] == '+') {
|
||||
neg = s[0] == '-'
|
||||
s = s[1:]
|
||||
}
|
||||
x, rem, err = leadingInt(s)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if neg {
|
||||
x = -x
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// leadingInt consumes the leading [0-9]* from s.
|
||||
func leadingInt(s string) (x int64, rem string, err error) {
|
||||
i := 0
|
||||
for ; i < len(s); i++ {
|
||||
c := s[i]
|
||||
if c < '0' || c > '9' {
|
||||
break
|
||||
}
|
||||
if x > (1<<63-1)/10 {
|
||||
// overflow
|
||||
return 0, "", errLeadingInt
|
||||
}
|
||||
x = x*10 + int64(c) - '0'
|
||||
if x < 0 {
|
||||
// overflow
|
||||
return 0, "", errLeadingInt
|
||||
}
|
||||
}
|
||||
return x, s[i:], nil
|
||||
}
|
||||
|
||||
// nextStdChunk finds the first occurrence of a std string in
|
||||
// layout and returns the text before, the std string, and the text after.
|
||||
func nextStdChunk(layout string) (prefix string, std int, suffix string) {
|
||||
for i := 0; i < len(layout); i++ {
|
||||
switch c := int(layout[i]); c {
|
||||
case 'J': // January, Jan
|
||||
if len(layout) >= i+3 && layout[i:i+3] == "Jan" {
|
||||
if len(layout) >= i+7 && layout[i:i+7] == "January" {
|
||||
return layout[0:i], stdLongMonth, layout[i+7:]
|
||||
}
|
||||
if !startsWithLowerCase(layout[i+3:]) {
|
||||
return layout[0:i], stdMonth, layout[i+3:]
|
||||
}
|
||||
}
|
||||
|
||||
case 'M': // Monday, Mon, MST
|
||||
if len(layout) >= i+3 {
|
||||
if layout[i:i+3] == "Mon" {
|
||||
if len(layout) >= i+6 && layout[i:i+6] == "Monday" {
|
||||
return layout[0:i], stdLongWeekDay, layout[i+6:]
|
||||
}
|
||||
if !startsWithLowerCase(layout[i+3:]) {
|
||||
return layout[0:i], stdWeekDay, layout[i+3:]
|
||||
}
|
||||
}
|
||||
if layout[i:i+3] == "MST" {
|
||||
return layout[0:i], stdTZ, layout[i+3:]
|
||||
}
|
||||
}
|
||||
|
||||
case '0': // 01, 02, 03, 04, 05, 06
|
||||
if len(layout) >= i+2 && '1' <= layout[i+1] && layout[i+1] <= '6' {
|
||||
return layout[0:i], std0x[layout[i+1]-'1'], layout[i+2:]
|
||||
}
|
||||
|
||||
case '1': // 15, 1
|
||||
if len(layout) >= i+2 && layout[i+1] == '5' {
|
||||
return layout[0:i], stdHour, layout[i+2:]
|
||||
}
|
||||
return layout[0:i], stdNumMonth, layout[i+1:]
|
||||
|
||||
case '2': // 2006, 2
|
||||
if len(layout) >= i+4 && layout[i:i+4] == "2006" {
|
||||
return layout[0:i], stdLongYear, layout[i+4:]
|
||||
}
|
||||
return layout[0:i], stdDay, layout[i+1:]
|
||||
|
||||
case '_': // _2, _2006
|
||||
if len(layout) >= i+2 && layout[i+1] == '2' {
|
||||
//_2006 is really a literal _, followed by stdLongYear
|
||||
if len(layout) >= i+5 && layout[i+1:i+5] == "2006" {
|
||||
return layout[0 : i+1], stdLongYear, layout[i+5:]
|
||||
}
|
||||
return layout[0:i], stdUnderDay, layout[i+2:]
|
||||
}
|
||||
|
||||
case '3':
|
||||
return layout[0:i], stdHour12, layout[i+1:]
|
||||
|
||||
case '4':
|
||||
return layout[0:i], stdMinute, layout[i+1:]
|
||||
|
||||
case '5':
|
||||
return layout[0:i], stdSecond, layout[i+1:]
|
||||
|
||||
case 'P': // PM
|
||||
if len(layout) >= i+2 && layout[i+1] == 'M' {
|
||||
return layout[0:i], stdPM, layout[i+2:]
|
||||
}
|
||||
|
||||
case 'p': // pm
|
||||
if len(layout) >= i+2 && layout[i+1] == 'm' {
|
||||
return layout[0:i], stdpm, layout[i+2:]
|
||||
}
|
||||
|
||||
case '-': // -070000, -07:00:00, -0700, -07:00, -07
|
||||
if len(layout) >= i+7 && layout[i:i+7] == "-070000" {
|
||||
return layout[0:i], stdNumSecondsTz, layout[i+7:]
|
||||
}
|
||||
if len(layout) >= i+9 && layout[i:i+9] == "-07:00:00" {
|
||||
return layout[0:i], stdNumColonSecondsTZ, layout[i+9:]
|
||||
}
|
||||
if len(layout) >= i+5 && layout[i:i+5] == "-0700" {
|
||||
return layout[0:i], stdNumTZ, layout[i+5:]
|
||||
}
|
||||
if len(layout) >= i+6 && layout[i:i+6] == "-07:00" {
|
||||
return layout[0:i], stdNumColonTZ, layout[i+6:]
|
||||
}
|
||||
if len(layout) >= i+3 && layout[i:i+3] == "-07" {
|
||||
return layout[0:i], stdNumShortTZ, layout[i+3:]
|
||||
}
|
||||
|
||||
case 'Z': // Z070000, Z07:00:00, Z0700, Z07:00,
|
||||
if len(layout) >= i+7 && layout[i:i+7] == "Z070000" {
|
||||
return layout[0:i], stdISO8601SecondsTZ, layout[i+7:]
|
||||
}
|
||||
if len(layout) >= i+9 && layout[i:i+9] == "Z07:00:00" {
|
||||
return layout[0:i], stdISO8601ColonSecondsTZ, layout[i+9:]
|
||||
}
|
||||
if len(layout) >= i+5 && layout[i:i+5] == "Z0700" {
|
||||
return layout[0:i], stdISO8601TZ, layout[i+5:]
|
||||
}
|
||||
if len(layout) >= i+6 && layout[i:i+6] == "Z07:00" {
|
||||
return layout[0:i], stdISO8601ColonTZ, layout[i+6:]
|
||||
}
|
||||
if len(layout) >= i+3 && layout[i:i+3] == "Z07" {
|
||||
return layout[0:i], stdISO8601ShortTZ, layout[i+3:]
|
||||
}
|
||||
|
||||
case '.': // .000 or .999 - repeated digits for fractional seconds.
|
||||
if i+1 < len(layout) && (layout[i+1] == '0' || layout[i+1] == '9') {
|
||||
ch := layout[i+1]
|
||||
j := i + 1
|
||||
for j < len(layout) && layout[j] == ch {
|
||||
j++
|
||||
}
|
||||
// String of digits must end here - only fractional second is all digits.
|
||||
if !isDigit(layout, j) {
|
||||
std := stdFracSecond0
|
||||
if layout[i+1] == '9' {
|
||||
std = stdFracSecond9
|
||||
}
|
||||
std |= (j - (i + 1)) << stdArgShift
|
||||
return layout[0:i], std, layout[j:]
|
||||
}
|
||||
}
|
||||
case '(':
|
||||
if len(layout) >= i+5 && layout[i:i+5] == "(MST)" {
|
||||
return layout[0:i], stdBracketTZ, layout[i+5:]
|
||||
}
|
||||
}
|
||||
}
|
||||
return layout, 0, ""
|
||||
}
|
||||
|
||||
var longDayNames = []string{
|
||||
"Sunday",
|
||||
"Monday",
|
||||
"Tuesday",
|
||||
"Wednesday",
|
||||
"Thursday",
|
||||
"Friday",
|
||||
"Saturday",
|
||||
}
|
||||
|
||||
var shortDayNames = []string{
|
||||
"Sun",
|
||||
"Mon",
|
||||
"Tue",
|
||||
"Wed",
|
||||
"Thu",
|
||||
"Fri",
|
||||
"Sat",
|
||||
}
|
||||
|
||||
var shortMonthNames = []string{
|
||||
"Jan",
|
||||
"Feb",
|
||||
"Mar",
|
||||
"Apr",
|
||||
"May",
|
||||
"Jun",
|
||||
"Jul",
|
||||
"Aug",
|
||||
"Sep",
|
||||
"Oct",
|
||||
"Nov",
|
||||
"Dec",
|
||||
}
|
||||
|
||||
var longMonthNames = []string{
|
||||
"January",
|
||||
"February",
|
||||
"March",
|
||||
"April",
|
||||
"May",
|
||||
"June",
|
||||
"July",
|
||||
"August",
|
||||
"September",
|
||||
"October",
|
||||
"November",
|
||||
"December",
|
||||
}
|
||||
|
||||
// isDigit reports whether s[i] is in range and is a decimal digit.
|
||||
func isDigit(s string, i int) bool {
|
||||
if len(s) <= i {
|
||||
return false
|
||||
}
|
||||
c := s[i]
|
||||
return '0' <= c && c <= '9'
|
||||
}
|
||||
|
||||
// getnum parses s[0:1] or s[0:2] (fixed forces the latter)
|
||||
// as a decimal integer and returns the integer and the
|
||||
// remainder of the string.
|
||||
func getnum(s string, fixed bool) (int, string, error) {
|
||||
if !isDigit(s, 0) {
|
||||
return 0, s, errBad
|
||||
}
|
||||
if !isDigit(s, 1) {
|
||||
if fixed {
|
||||
return 0, s, errBad
|
||||
}
|
||||
return int(s[0] - '0'), s[1:], nil
|
||||
}
|
||||
return int(s[0]-'0')*10 + int(s[1]-'0'), s[2:], nil
|
||||
}
|
||||
|
||||
func cutspace(s string) string {
|
||||
for len(s) > 0 && s[0] == ' ' {
|
||||
s = s[1:]
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// skip removes the given prefix from value,
|
||||
// treating runs of space characters as equivalent.
|
||||
func skip(value, prefix string) (string, error) {
|
||||
for len(prefix) > 0 {
|
||||
if prefix[0] == ' ' {
|
||||
if len(value) > 0 && value[0] != ' ' {
|
||||
return value, errBad
|
||||
}
|
||||
prefix = cutspace(prefix)
|
||||
value = cutspace(value)
|
||||
continue
|
||||
}
|
||||
if len(value) == 0 || value[0] != prefix[0] {
|
||||
return value, errBad
|
||||
}
|
||||
prefix = prefix[1:]
|
||||
value = value[1:]
|
||||
}
|
||||
return value, nil
|
||||
}
|
||||
|
||||
// Never printed, just needs to be non-nil for return by atoi.
|
||||
var atoiError = errors.New("time: invalid number")
|
||||
|
||||
// Duplicates functionality in strconv, but avoids dependency.
|
||||
func atoi(s string) (x int, err error) {
|
||||
q, rem, err := signedLeadingInt(s)
|
||||
x = int(q)
|
||||
if err != nil || rem != "" {
|
||||
return 0, atoiError
|
||||
}
|
||||
return x, nil
|
||||
}
|
||||
|
||||
// match reports whether s1 and s2 match ignoring case.
|
||||
// It is assumed s1 and s2 are the same length.
|
||||
func match(s1, s2 string) bool {
|
||||
for i := 0; i < len(s1); i++ {
|
||||
c1 := s1[i]
|
||||
c2 := s2[i]
|
||||
if c1 != c2 {
|
||||
// Switch to lower-case; 'a'-'A' is known to be a single bit.
|
||||
c1 |= 'a' - 'A'
|
||||
c2 |= 'a' - 'A'
|
||||
if c1 != c2 || c1 < 'a' || c1 > 'z' {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func lookup(tab []string, val string) (int, string, error) {
|
||||
for i, v := range tab {
|
||||
if len(val) >= len(v) && match(val[0:len(v)], v) {
|
||||
return i, val[len(v):], nil
|
||||
}
|
||||
}
|
||||
return -1, val, errBad
|
||||
}
|
||||
|
||||
// daysBefore[m] counts the number of days in a non-leap year
|
||||
// before month m begins. There is an entry for m=12, counting
|
||||
// the number of days before January of next year (365).
|
||||
var daysBefore = [...]int32{
|
||||
0,
|
||||
31,
|
||||
31 + 28,
|
||||
31 + 28 + 31,
|
||||
31 + 28 + 31 + 30,
|
||||
31 + 28 + 31 + 30 + 31,
|
||||
31 + 28 + 31 + 30 + 31 + 30,
|
||||
31 + 28 + 31 + 30 + 31 + 30 + 31,
|
||||
31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,
|
||||
31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
|
||||
31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
|
||||
31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
|
||||
31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31,
|
||||
}
|
||||
|
||||
func isLeap(year int) bool {
|
||||
return year%4 == 0 && (year%100 != 0 || year%400 == 0)
|
||||
}
|
||||
|
||||
func daysIn(m time.Month, year int) int {
|
||||
if m == time.February && isLeap(year) {
|
||||
return 29
|
||||
}
|
||||
return int(daysBefore[m] - daysBefore[m-1])
|
||||
}
|
||||
|
||||
// parseTimeZone parses a time zone string and returns its length. Time zones
|
||||
// are human-generated and unpredictable. We can't do precise error checking.
|
||||
// On the other hand, for a correct parse there must be a time zone at the
|
||||
// beginning of the string, so it's almost always true that there's one
|
||||
// there. We look at the beginning of the string for a run of upper-case letters.
|
||||
// If there are more than 5, it's an error.
|
||||
// If there are 4 or 5 and the last is a T, it's a time zone.
|
||||
// If there are 3, it's a time zone.
|
||||
// Otherwise, other than special cases, it's not a time zone.
|
||||
// GMT is special because it can have an hour offset.
|
||||
func parseTimeZone(value string) (length int, ok bool) {
|
||||
if len(value) < 3 {
|
||||
return 0, false
|
||||
}
|
||||
// Special case 1: ChST and MeST are the only zones with a lower-case letter.
|
||||
if len(value) >= 4 && (value[:4] == "ChST" || value[:4] == "MeST") {
|
||||
return 4, true
|
||||
}
|
||||
// Special case 2: GMT may have an hour offset; treat it specially.
|
||||
if value[:3] == "GMT" {
|
||||
length = parseGMT(value)
|
||||
return length, true
|
||||
}
|
||||
// Special Case 3: Some time zones are not named, but have +/-00 format
|
||||
if value[0] == '+' || value[0] == '-' {
|
||||
length = parseSignedOffset(value)
|
||||
return length, true
|
||||
}
|
||||
// How many upper-case letters are there? Need at least three, at most five.
|
||||
var nUpper int
|
||||
for nUpper = 0; nUpper < 6; nUpper++ {
|
||||
if nUpper >= len(value) {
|
||||
break
|
||||
}
|
||||
if c := value[nUpper]; c < 'A' || 'Z' < c {
|
||||
break
|
||||
}
|
||||
}
|
||||
switch nUpper {
|
||||
case 0, 1, 2, 6:
|
||||
return 0, false
|
||||
case 5: // Must end in T to match.
|
||||
if value[4] == 'T' {
|
||||
return 5, true
|
||||
}
|
||||
case 4:
|
||||
// Must end in T, except one special case.
|
||||
if value[3] == 'T' || value[:4] == "WITA" {
|
||||
return 4, true
|
||||
}
|
||||
case 3:
|
||||
return 3, true
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
// parseGMT parses a GMT time zone. The input string is known to start "GMT".
|
||||
// The function checks whether that is followed by a sign and a number in the
|
||||
// range -14 through 12 excluding zero.
|
||||
func parseGMT(value string) int {
|
||||
value = value[3:]
|
||||
if len(value) == 0 {
|
||||
return 3
|
||||
}
|
||||
|
||||
return 3 + parseSignedOffset(value)
|
||||
}
|
||||
|
||||
// parseSignedOffset parses a signed timezone offset (e.g. "+03" or "-04").
|
||||
// The function checks for a signed number in the range -14 through +12 excluding zero.
|
||||
// Returns length of the found offset string or 0 otherwise
|
||||
func parseSignedOffset(value string) int {
|
||||
sign := value[0]
|
||||
if sign != '-' && sign != '+' {
|
||||
return 0
|
||||
}
|
||||
x, rem, err := leadingInt(value[1:])
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
if sign == '-' {
|
||||
x = -x
|
||||
}
|
||||
if x == 0 || x < -14 || 12 < x {
|
||||
return 0
|
||||
}
|
||||
return len(value) - len(rem)
|
||||
}
|
||||
|
||||
func parseNanoseconds(value string, nbytes int) (ns int, rangeErrString string, err error) {
|
||||
if value[0] != '.' {
|
||||
err = errBad
|
||||
return
|
||||
}
|
||||
if ns, err = atoi(value[1:nbytes]); err != nil {
|
||||
return
|
||||
}
|
||||
if ns < 0 || 1e9 <= ns {
|
||||
rangeErrString = "fractional second"
|
||||
return
|
||||
}
|
||||
// We need nanoseconds, which means scaling by the number
|
||||
// of missing digits in the format, maximum length 10. If it's
|
||||
// longer than 10, we won't scale.
|
||||
scaleDigits := 10 - nbytes
|
||||
for i := 0; i < scaleDigits; i++ {
|
||||
ns *= 10
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// std0x records the std values for "01", "02", ..., "06".
|
||||
var std0x = [...]int{stdZeroMonth, stdZeroDay, stdZeroHour12, stdZeroMinute, stdZeroSecond, stdYear}
|
||||
|
||||
// startsWithLowerCase reports whether the string has a lower-case letter at the beginning.
|
||||
// Its purpose is to prevent matching strings like "Month" when looking for "Mon".
|
||||
func startsWithLowerCase(str string) bool {
|
||||
if len(str) == 0 {
|
||||
return false
|
||||
}
|
||||
c := str[0]
|
||||
return 'a' <= c && c <= 'z'
|
||||
}
|
||||
312
server/vendor/github.com/dop251/goja/destruct.go
generated
vendored
Normal file
312
server/vendor/github.com/dop251/goja/destruct.go
generated
vendored
Normal file
@@ -0,0 +1,312 @@
|
||||
package goja
|
||||
|
||||
import (
|
||||
"github.com/dop251/goja/unistring"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type destructKeyedSource struct {
|
||||
r *Runtime
|
||||
wrapped Value
|
||||
usedKeys map[Value]struct{}
|
||||
}
|
||||
|
||||
func newDestructKeyedSource(r *Runtime, wrapped Value) *destructKeyedSource {
|
||||
return &destructKeyedSource{
|
||||
r: r,
|
||||
wrapped: wrapped,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Runtime) newDestructKeyedSource(wrapped Value) *Object {
|
||||
return &Object{
|
||||
runtime: r,
|
||||
self: newDestructKeyedSource(r, wrapped),
|
||||
}
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) w() objectImpl {
|
||||
return d.wrapped.ToObject(d.r).self
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) recordKey(key Value) {
|
||||
if d.usedKeys == nil {
|
||||
d.usedKeys = make(map[Value]struct{})
|
||||
}
|
||||
d.usedKeys[key] = struct{}{}
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) sortLen() int {
|
||||
return d.w().sortLen()
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) sortGet(i int) Value {
|
||||
return d.w().sortGet(i)
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) swap(i int, i2 int) {
|
||||
d.w().swap(i, i2)
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) className() string {
|
||||
return d.w().className()
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) typeOf() valueString {
|
||||
return d.w().typeOf()
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) getStr(p unistring.String, receiver Value) Value {
|
||||
d.recordKey(stringValueFromRaw(p))
|
||||
return d.w().getStr(p, receiver)
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) getIdx(p valueInt, receiver Value) Value {
|
||||
d.recordKey(p.toString())
|
||||
return d.w().getIdx(p, receiver)
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) getSym(p *Symbol, receiver Value) Value {
|
||||
d.recordKey(p)
|
||||
return d.w().getSym(p, receiver)
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) getOwnPropStr(u unistring.String) Value {
|
||||
d.recordKey(stringValueFromRaw(u))
|
||||
return d.w().getOwnPropStr(u)
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) getOwnPropIdx(v valueInt) Value {
|
||||
d.recordKey(v.toString())
|
||||
return d.w().getOwnPropIdx(v)
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) getOwnPropSym(symbol *Symbol) Value {
|
||||
d.recordKey(symbol)
|
||||
return d.w().getOwnPropSym(symbol)
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) setOwnStr(p unistring.String, v Value, throw bool) bool {
|
||||
return d.w().setOwnStr(p, v, throw)
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) setOwnIdx(p valueInt, v Value, throw bool) bool {
|
||||
return d.w().setOwnIdx(p, v, throw)
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) setOwnSym(p *Symbol, v Value, throw bool) bool {
|
||||
return d.w().setOwnSym(p, v, throw)
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) setForeignStr(p unistring.String, v, receiver Value, throw bool) (res bool, handled bool) {
|
||||
return d.w().setForeignStr(p, v, receiver, throw)
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) setForeignIdx(p valueInt, v, receiver Value, throw bool) (res bool, handled bool) {
|
||||
return d.w().setForeignIdx(p, v, receiver, throw)
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) setForeignSym(p *Symbol, v, receiver Value, throw bool) (res bool, handled bool) {
|
||||
return d.w().setForeignSym(p, v, receiver, throw)
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) hasPropertyStr(u unistring.String) bool {
|
||||
return d.w().hasPropertyStr(u)
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) hasPropertyIdx(idx valueInt) bool {
|
||||
return d.w().hasPropertyIdx(idx)
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) hasPropertySym(s *Symbol) bool {
|
||||
return d.w().hasPropertySym(s)
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) hasOwnPropertyStr(u unistring.String) bool {
|
||||
return d.w().hasOwnPropertyStr(u)
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) hasOwnPropertyIdx(v valueInt) bool {
|
||||
return d.w().hasOwnPropertyIdx(v)
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) hasOwnPropertySym(s *Symbol) bool {
|
||||
return d.w().hasOwnPropertySym(s)
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) defineOwnPropertyStr(name unistring.String, desc PropertyDescriptor, throw bool) bool {
|
||||
return d.w().defineOwnPropertyStr(name, desc, throw)
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) defineOwnPropertyIdx(name valueInt, desc PropertyDescriptor, throw bool) bool {
|
||||
return d.w().defineOwnPropertyIdx(name, desc, throw)
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) defineOwnPropertySym(name *Symbol, desc PropertyDescriptor, throw bool) bool {
|
||||
return d.w().defineOwnPropertySym(name, desc, throw)
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) deleteStr(name unistring.String, throw bool) bool {
|
||||
return d.w().deleteStr(name, throw)
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) deleteIdx(idx valueInt, throw bool) bool {
|
||||
return d.w().deleteIdx(idx, throw)
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) deleteSym(s *Symbol, throw bool) bool {
|
||||
return d.w().deleteSym(s, throw)
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) toPrimitiveNumber() Value {
|
||||
return d.w().toPrimitiveNumber()
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) toPrimitiveString() Value {
|
||||
return d.w().toPrimitiveString()
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) toPrimitive() Value {
|
||||
return d.w().toPrimitive()
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) assertCallable() (call func(FunctionCall) Value, ok bool) {
|
||||
return d.w().assertCallable()
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) vmCall(vm *vm, n int) {
|
||||
d.w().vmCall(vm, n)
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) assertConstructor() func(args []Value, newTarget *Object) *Object {
|
||||
return d.w().assertConstructor()
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) proto() *Object {
|
||||
return d.w().proto()
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) setProto(proto *Object, throw bool) bool {
|
||||
return d.w().setProto(proto, throw)
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) hasInstance(v Value) bool {
|
||||
return d.w().hasInstance(v)
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) isExtensible() bool {
|
||||
return d.w().isExtensible()
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) preventExtensions(throw bool) bool {
|
||||
return d.w().preventExtensions(throw)
|
||||
}
|
||||
|
||||
type destructKeyedSourceIter struct {
|
||||
d *destructKeyedSource
|
||||
wrapped iterNextFunc
|
||||
}
|
||||
|
||||
func (i *destructKeyedSourceIter) next() (propIterItem, iterNextFunc) {
|
||||
for {
|
||||
item, next := i.wrapped()
|
||||
if next == nil {
|
||||
return item, nil
|
||||
}
|
||||
i.wrapped = next
|
||||
if _, exists := i.d.usedKeys[item.name]; !exists {
|
||||
return item, i.next
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) iterateStringKeys() iterNextFunc {
|
||||
return (&destructKeyedSourceIter{
|
||||
d: d,
|
||||
wrapped: d.w().iterateStringKeys(),
|
||||
}).next
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) iterateSymbols() iterNextFunc {
|
||||
return (&destructKeyedSourceIter{
|
||||
d: d,
|
||||
wrapped: d.w().iterateSymbols(),
|
||||
}).next
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) iterateKeys() iterNextFunc {
|
||||
return (&destructKeyedSourceIter{
|
||||
d: d,
|
||||
wrapped: d.w().iterateKeys(),
|
||||
}).next
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) export(ctx *objectExportCtx) interface{} {
|
||||
return d.w().export(ctx)
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) exportType() reflect.Type {
|
||||
return d.w().exportType()
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) exportToMap(dst reflect.Value, typ reflect.Type, ctx *objectExportCtx) error {
|
||||
return d.w().exportToMap(dst, typ, ctx)
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) exportToArrayOrSlice(dst reflect.Value, typ reflect.Type, ctx *objectExportCtx) error {
|
||||
return d.w().exportToArrayOrSlice(dst, typ, ctx)
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) equal(impl objectImpl) bool {
|
||||
return d.w().equal(impl)
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) stringKeys(all bool, accum []Value) []Value {
|
||||
var next iterNextFunc
|
||||
if all {
|
||||
next = d.iterateStringKeys()
|
||||
} else {
|
||||
next = (&enumerableIter{
|
||||
o: d.wrapped.ToObject(d.r),
|
||||
wrapped: d.iterateStringKeys(),
|
||||
}).next
|
||||
}
|
||||
for item, next := next(); next != nil; item, next = next() {
|
||||
accum = append(accum, item.name)
|
||||
}
|
||||
return accum
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) filterUsedKeys(keys []Value) []Value {
|
||||
k := 0
|
||||
for i, key := range keys {
|
||||
if _, exists := d.usedKeys[key]; exists {
|
||||
continue
|
||||
}
|
||||
if k != i {
|
||||
keys[k] = key
|
||||
}
|
||||
k++
|
||||
}
|
||||
return keys[:k]
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) symbols(all bool, accum []Value) []Value {
|
||||
return d.filterUsedKeys(d.w().symbols(all, accum))
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) keys(all bool, accum []Value) []Value {
|
||||
return d.filterUsedKeys(d.w().keys(all, accum))
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) _putProp(name unistring.String, value Value, writable, enumerable, configurable bool) Value {
|
||||
return d.w()._putProp(name, value, writable, enumerable, configurable)
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) _putSym(s *Symbol, prop Value) {
|
||||
d.w()._putSym(s, prop)
|
||||
}
|
||||
|
||||
func (d *destructKeyedSource) getPrivateEnv(typ *privateEnvType, create bool) *privateElements {
|
||||
return d.w().getPrivateEnv(typ, create)
|
||||
}
|
||||
3
server/vendor/github.com/dop251/goja/extract_failed_tests.sh
generated
vendored
Normal file
3
server/vendor/github.com/dop251/goja/extract_failed_tests.sh
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
sed -En 's/^.*FAIL: TestTC39\/tc39\/(test\/.*.js).*$/"\1": true,/p'
|
||||
110
server/vendor/github.com/dop251/goja/file/README.markdown
generated
vendored
Normal file
110
server/vendor/github.com/dop251/goja/file/README.markdown
generated
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
# file
|
||||
--
|
||||
import "github.com/dop251/goja/file"
|
||||
|
||||
Package file encapsulates the file abstractions used by the ast & parser.
|
||||
|
||||
## Usage
|
||||
|
||||
#### type File
|
||||
|
||||
```go
|
||||
type File struct {
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
#### func NewFile
|
||||
|
||||
```go
|
||||
func NewFile(filename, src string, base int) *File
|
||||
```
|
||||
|
||||
#### func (*File) Base
|
||||
|
||||
```go
|
||||
func (fl *File) Base() int
|
||||
```
|
||||
|
||||
#### func (*File) Name
|
||||
|
||||
```go
|
||||
func (fl *File) Name() string
|
||||
```
|
||||
|
||||
#### func (*File) Source
|
||||
|
||||
```go
|
||||
func (fl *File) Source() string
|
||||
```
|
||||
|
||||
#### type FileSet
|
||||
|
||||
```go
|
||||
type FileSet struct {
|
||||
}
|
||||
```
|
||||
|
||||
A FileSet represents a set of source files.
|
||||
|
||||
#### func (*FileSet) AddFile
|
||||
|
||||
```go
|
||||
func (self *FileSet) AddFile(filename, src string) int
|
||||
```
|
||||
AddFile adds a new file with the given filename and src.
|
||||
|
||||
This an internal method, but exported for cross-package use.
|
||||
|
||||
#### func (*FileSet) File
|
||||
|
||||
```go
|
||||
func (self *FileSet) File(idx Idx) *File
|
||||
```
|
||||
|
||||
#### func (*FileSet) Position
|
||||
|
||||
```go
|
||||
func (self *FileSet) Position(idx Idx) *Position
|
||||
```
|
||||
Position converts an Idx in the FileSet into a Position.
|
||||
|
||||
#### type Idx
|
||||
|
||||
```go
|
||||
type Idx int
|
||||
```
|
||||
|
||||
Idx is a compact encoding of a source position within a file set. It can be
|
||||
converted into a Position for a more convenient, but much larger,
|
||||
representation.
|
||||
|
||||
#### type Position
|
||||
|
||||
```go
|
||||
type Position struct {
|
||||
Filename string // The filename where the error occurred, if any
|
||||
Offset int // The src offset
|
||||
Line int // The line number, starting at 1
|
||||
Column int // The column number, starting at 1 (The character count)
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
Position describes an arbitrary source position including the filename, line,
|
||||
and column location.
|
||||
|
||||
#### func (*Position) String
|
||||
|
||||
```go
|
||||
func (self *Position) String() string
|
||||
```
|
||||
String returns a string in one of several forms:
|
||||
|
||||
file:line:column A valid position with filename
|
||||
line:column A valid position without filename
|
||||
file An invalid position with filename
|
||||
- An invalid position without filename
|
||||
|
||||
--
|
||||
**godocdown** http://github.com/robertkrimen/godocdown
|
||||
234
server/vendor/github.com/dop251/goja/file/file.go
generated
vendored
Normal file
234
server/vendor/github.com/dop251/goja/file/file.go
generated
vendored
Normal file
@@ -0,0 +1,234 @@
|
||||
// Package file encapsulates the file abstractions used by the ast & parser.
|
||||
package file
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"path"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/go-sourcemap/sourcemap"
|
||||
)
|
||||
|
||||
// Idx is a compact encoding of a source position within a file set.
|
||||
// It can be converted into a Position for a more convenient, but much
|
||||
// larger, representation.
|
||||
type Idx int
|
||||
|
||||
// Position describes an arbitrary source position
|
||||
// including the filename, line, and column location.
|
||||
type Position struct {
|
||||
Filename string // The filename where the error occurred, if any
|
||||
Line int // The line number, starting at 1
|
||||
Column int // The column number, starting at 1 (The character count)
|
||||
|
||||
}
|
||||
|
||||
// A Position is valid if the line number is > 0.
|
||||
|
||||
func (self *Position) isValid() bool {
|
||||
return self.Line > 0
|
||||
}
|
||||
|
||||
// String returns a string in one of several forms:
|
||||
//
|
||||
// file:line:column A valid position with filename
|
||||
// line:column A valid position without filename
|
||||
// file An invalid position with filename
|
||||
// - An invalid position without filename
|
||||
func (self Position) String() string {
|
||||
str := self.Filename
|
||||
if self.isValid() {
|
||||
if str != "" {
|
||||
str += ":"
|
||||
}
|
||||
str += fmt.Sprintf("%d:%d", self.Line, self.Column)
|
||||
}
|
||||
if str == "" {
|
||||
str = "-"
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
// FileSet
|
||||
|
||||
// A FileSet represents a set of source files.
|
||||
type FileSet struct {
|
||||
files []*File
|
||||
last *File
|
||||
}
|
||||
|
||||
// AddFile adds a new file with the given filename and src.
|
||||
//
|
||||
// This an internal method, but exported for cross-package use.
|
||||
func (self *FileSet) AddFile(filename, src string) int {
|
||||
base := self.nextBase()
|
||||
file := &File{
|
||||
name: filename,
|
||||
src: src,
|
||||
base: base,
|
||||
}
|
||||
self.files = append(self.files, file)
|
||||
self.last = file
|
||||
return base
|
||||
}
|
||||
|
||||
func (self *FileSet) nextBase() int {
|
||||
if self.last == nil {
|
||||
return 1
|
||||
}
|
||||
return self.last.base + len(self.last.src) + 1
|
||||
}
|
||||
|
||||
func (self *FileSet) File(idx Idx) *File {
|
||||
for _, file := range self.files {
|
||||
if idx <= Idx(file.base+len(file.src)) {
|
||||
return file
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Position converts an Idx in the FileSet into a Position.
|
||||
func (self *FileSet) Position(idx Idx) Position {
|
||||
for _, file := range self.files {
|
||||
if idx <= Idx(file.base+len(file.src)) {
|
||||
return file.Position(int(idx) - file.base)
|
||||
}
|
||||
}
|
||||
return Position{}
|
||||
}
|
||||
|
||||
type File struct {
|
||||
mu sync.Mutex
|
||||
name string
|
||||
src string
|
||||
base int // This will always be 1 or greater
|
||||
sourceMap *sourcemap.Consumer
|
||||
lineOffsets []int
|
||||
lastScannedOffset int
|
||||
}
|
||||
|
||||
func NewFile(filename, src string, base int) *File {
|
||||
return &File{
|
||||
name: filename,
|
||||
src: src,
|
||||
base: base,
|
||||
}
|
||||
}
|
||||
|
||||
func (fl *File) Name() string {
|
||||
return fl.name
|
||||
}
|
||||
|
||||
func (fl *File) Source() string {
|
||||
return fl.src
|
||||
}
|
||||
|
||||
func (fl *File) Base() int {
|
||||
return fl.base
|
||||
}
|
||||
|
||||
func (fl *File) SetSourceMap(m *sourcemap.Consumer) {
|
||||
fl.sourceMap = m
|
||||
}
|
||||
|
||||
func (fl *File) Position(offset int) Position {
|
||||
var line int
|
||||
var lineOffsets []int
|
||||
fl.mu.Lock()
|
||||
if offset > fl.lastScannedOffset {
|
||||
line = fl.scanTo(offset)
|
||||
lineOffsets = fl.lineOffsets
|
||||
fl.mu.Unlock()
|
||||
} else {
|
||||
lineOffsets = fl.lineOffsets
|
||||
fl.mu.Unlock()
|
||||
line = sort.Search(len(lineOffsets), func(x int) bool { return lineOffsets[x] > offset }) - 1
|
||||
}
|
||||
|
||||
var lineStart int
|
||||
if line >= 0 {
|
||||
lineStart = lineOffsets[line]
|
||||
}
|
||||
|
||||
row := line + 2
|
||||
col := offset - lineStart + 1
|
||||
|
||||
if fl.sourceMap != nil {
|
||||
if source, _, row, col, ok := fl.sourceMap.Source(row, col); ok {
|
||||
sourceUrlStr := source
|
||||
sourceURL := ResolveSourcemapURL(fl.Name(), source)
|
||||
if sourceURL != nil {
|
||||
sourceUrlStr = sourceURL.String()
|
||||
}
|
||||
|
||||
return Position{
|
||||
Filename: sourceUrlStr,
|
||||
Line: row,
|
||||
Column: col,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Position{
|
||||
Filename: fl.name,
|
||||
Line: row,
|
||||
Column: col,
|
||||
}
|
||||
}
|
||||
|
||||
func ResolveSourcemapURL(basename, source string) *url.URL {
|
||||
// if the url is absolute(has scheme) there is nothing to do
|
||||
smURL, err := url.Parse(strings.TrimSpace(source))
|
||||
if err == nil && !smURL.IsAbs() {
|
||||
baseURL, err1 := url.Parse(strings.TrimSpace(basename))
|
||||
if err1 == nil && path.IsAbs(baseURL.Path) {
|
||||
smURL = baseURL.ResolveReference(smURL)
|
||||
} else {
|
||||
// pathological case where both are not absolute paths and using Resolve
|
||||
// as above will produce an absolute one
|
||||
smURL, _ = url.Parse(path.Join(path.Dir(basename), smURL.Path))
|
||||
}
|
||||
}
|
||||
return smURL
|
||||
}
|
||||
|
||||
func findNextLineStart(s string) int {
|
||||
for pos, ch := range s {
|
||||
switch ch {
|
||||
case '\r':
|
||||
if pos < len(s)-1 && s[pos+1] == '\n' {
|
||||
return pos + 2
|
||||
}
|
||||
return pos + 1
|
||||
case '\n':
|
||||
return pos + 1
|
||||
case '\u2028', '\u2029':
|
||||
return pos + 3
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
func (fl *File) scanTo(offset int) int {
|
||||
o := fl.lastScannedOffset
|
||||
for o < offset {
|
||||
p := findNextLineStart(fl.src[o:])
|
||||
if p == -1 {
|
||||
fl.lastScannedOffset = len(fl.src)
|
||||
return len(fl.lineOffsets) - 1
|
||||
}
|
||||
o = o + p
|
||||
fl.lineOffsets = append(fl.lineOffsets, o)
|
||||
}
|
||||
fl.lastScannedOffset = o
|
||||
|
||||
if o == offset {
|
||||
return len(fl.lineOffsets) - 1
|
||||
}
|
||||
|
||||
return len(fl.lineOffsets) - 2
|
||||
}
|
||||
21
server/vendor/github.com/dop251/goja/ftoa/LICENSE_LUCENE
generated
vendored
Normal file
21
server/vendor/github.com/dop251/goja/ftoa/LICENSE_LUCENE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
Copyright (C) 1998, 1999 by Lucent Technologies
|
||||
All Rights Reserved
|
||||
|
||||
Permission to use, copy, modify, and distribute this software and
|
||||
its documentation for any purpose and without fee is hereby
|
||||
granted, provided that the above copyright notice appear in all
|
||||
copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of Lucent or any of its entities
|
||||
not be used in advertising or publicity pertaining to
|
||||
distribution of the software without specific, written prior
|
||||
permission.
|
||||
|
||||
LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
|
||||
IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
|
||||
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
||||
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
THIS SOFTWARE.
|
||||
150
server/vendor/github.com/dop251/goja/ftoa/common.go
generated
vendored
Normal file
150
server/vendor/github.com/dop251/goja/ftoa/common.go
generated
vendored
Normal file
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
Package ftoa provides ECMAScript-compliant floating point number conversion to string.
|
||||
|
||||
It contains code ported from Rhino (https://github.com/mozilla/rhino/blob/master/src/org/mozilla/javascript/DToA.java)
|
||||
as well as from the original code by David M. Gay.
|
||||
|
||||
See LICENSE_LUCENE for the original copyright message and disclaimer.
|
||||
*/
|
||||
package ftoa
|
||||
|
||||
import (
|
||||
"math"
|
||||
)
|
||||
|
||||
const (
|
||||
frac_mask = 0xfffff
|
||||
exp_shift = 20
|
||||
exp_msk1 = 0x100000
|
||||
|
||||
exp_shiftL = 52
|
||||
exp_mask_shifted = 0x7ff
|
||||
frac_maskL = 0xfffffffffffff
|
||||
exp_msk1L = 0x10000000000000
|
||||
exp_shift1 = 20
|
||||
exp_mask = 0x7ff00000
|
||||
bias = 1023
|
||||
p = 53
|
||||
bndry_mask = 0xfffff
|
||||
log2P = 1
|
||||
)
|
||||
|
||||
func lo0bits(x uint32) (k int) {
|
||||
|
||||
if (x & 7) != 0 {
|
||||
if (x & 1) != 0 {
|
||||
return 0
|
||||
}
|
||||
if (x & 2) != 0 {
|
||||
return 1
|
||||
}
|
||||
return 2
|
||||
}
|
||||
if (x & 0xffff) == 0 {
|
||||
k = 16
|
||||
x >>= 16
|
||||
}
|
||||
if (x & 0xff) == 0 {
|
||||
k += 8
|
||||
x >>= 8
|
||||
}
|
||||
if (x & 0xf) == 0 {
|
||||
k += 4
|
||||
x >>= 4
|
||||
}
|
||||
if (x & 0x3) == 0 {
|
||||
k += 2
|
||||
x >>= 2
|
||||
}
|
||||
if (x & 1) == 0 {
|
||||
k++
|
||||
x >>= 1
|
||||
if (x & 1) == 0 {
|
||||
return 32
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func hi0bits(x uint32) (k int) {
|
||||
|
||||
if (x & 0xffff0000) == 0 {
|
||||
k = 16
|
||||
x <<= 16
|
||||
}
|
||||
if (x & 0xff000000) == 0 {
|
||||
k += 8
|
||||
x <<= 8
|
||||
}
|
||||
if (x & 0xf0000000) == 0 {
|
||||
k += 4
|
||||
x <<= 4
|
||||
}
|
||||
if (x & 0xc0000000) == 0 {
|
||||
k += 2
|
||||
x <<= 2
|
||||
}
|
||||
if (x & 0x80000000) == 0 {
|
||||
k++
|
||||
if (x & 0x40000000) == 0 {
|
||||
return 32
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func stuffBits(bits []byte, offset int, val uint32) {
|
||||
bits[offset] = byte(val >> 24)
|
||||
bits[offset+1] = byte(val >> 16)
|
||||
bits[offset+2] = byte(val >> 8)
|
||||
bits[offset+3] = byte(val)
|
||||
}
|
||||
|
||||
func d2b(d float64, b []byte) (e, bits int, dblBits []byte) {
|
||||
dBits := math.Float64bits(d)
|
||||
d0 := uint32(dBits >> 32)
|
||||
d1 := uint32(dBits)
|
||||
|
||||
z := d0 & frac_mask
|
||||
d0 &= 0x7fffffff /* clear sign bit, which we ignore */
|
||||
|
||||
var de, k, i int
|
||||
if de = int(d0 >> exp_shift); de != 0 {
|
||||
z |= exp_msk1
|
||||
}
|
||||
|
||||
y := d1
|
||||
if y != 0 {
|
||||
dblBits = b[:8]
|
||||
k = lo0bits(y)
|
||||
y >>= k
|
||||
if k != 0 {
|
||||
stuffBits(dblBits, 4, y|z<<(32-k))
|
||||
z >>= k
|
||||
} else {
|
||||
stuffBits(dblBits, 4, y)
|
||||
}
|
||||
stuffBits(dblBits, 0, z)
|
||||
if z != 0 {
|
||||
i = 2
|
||||
} else {
|
||||
i = 1
|
||||
}
|
||||
} else {
|
||||
dblBits = b[:4]
|
||||
k = lo0bits(z)
|
||||
z >>= k
|
||||
stuffBits(dblBits, 0, z)
|
||||
k += 32
|
||||
i = 1
|
||||
}
|
||||
|
||||
if de != 0 {
|
||||
e = de - bias - (p - 1) + k
|
||||
bits = p - k
|
||||
} else {
|
||||
e = de - bias - (p - 1) + 1 + k
|
||||
bits = 32*i - hi0bits(z)
|
||||
}
|
||||
return
|
||||
}
|
||||
699
server/vendor/github.com/dop251/goja/ftoa/ftoa.go
generated
vendored
Normal file
699
server/vendor/github.com/dop251/goja/ftoa/ftoa.go
generated
vendored
Normal file
@@ -0,0 +1,699 @@
|
||||
package ftoa
|
||||
|
||||
import (
|
||||
"math"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
const (
|
||||
exp_11 = 0x3ff00000
|
||||
frac_mask1 = 0xfffff
|
||||
bletch = 0x10
|
||||
quick_max = 14
|
||||
int_max = 14
|
||||
)
|
||||
|
||||
var (
|
||||
tens = [...]float64{
|
||||
1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
|
||||
1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
|
||||
1e20, 1e21, 1e22,
|
||||
}
|
||||
|
||||
bigtens = [...]float64{1e16, 1e32, 1e64, 1e128, 1e256}
|
||||
|
||||
big5 = big.NewInt(5)
|
||||
big10 = big.NewInt(10)
|
||||
|
||||
p05 = []*big.Int{big5, big.NewInt(25), big.NewInt(125)}
|
||||
pow5Cache [7]*big.Int
|
||||
|
||||
dtoaModes = []int{
|
||||
ModeStandard: 0,
|
||||
ModeStandardExponential: 0,
|
||||
ModeFixed: 3,
|
||||
ModeExponential: 2,
|
||||
ModePrecision: 2,
|
||||
}
|
||||
)
|
||||
|
||||
/*
|
||||
d must be > 0 and must not be Inf
|
||||
|
||||
mode:
|
||||
|
||||
0 ==> shortest string that yields d when read in
|
||||
and rounded to nearest.
|
||||
1 ==> like 0, but with Steele & White stopping rule;
|
||||
e.g. with IEEE P754 arithmetic , mode 0 gives
|
||||
1e23 whereas mode 1 gives 9.999999999999999e22.
|
||||
2 ==> max(1,ndigits) significant digits. This gives a
|
||||
return value similar to that of ecvt, except
|
||||
that trailing zeros are suppressed.
|
||||
3 ==> through ndigits past the decimal point. This
|
||||
gives a return value similar to that from fcvt,
|
||||
except that trailing zeros are suppressed, and
|
||||
ndigits can be negative.
|
||||
4,5 ==> similar to 2 and 3, respectively, but (in
|
||||
round-nearest mode) with the tests of mode 0 to
|
||||
possibly return a shorter string that rounds to d.
|
||||
With IEEE arithmetic and compilation with
|
||||
-DHonor_FLT_ROUNDS, modes 4 and 5 behave the same
|
||||
as modes 2 and 3 when FLT_ROUNDS != 1.
|
||||
6-9 ==> Debugging modes similar to mode - 4: don't try
|
||||
fast floating-point estimate (if applicable).
|
||||
|
||||
Values of mode other than 0-9 are treated as mode 0.
|
||||
*/
|
||||
func ftoa(d float64, mode int, biasUp bool, ndigits int, buf []byte) ([]byte, int) {
|
||||
startPos := len(buf)
|
||||
dblBits := make([]byte, 0, 8)
|
||||
be, bbits, dblBits := d2b(d, dblBits)
|
||||
|
||||
dBits := math.Float64bits(d)
|
||||
word0 := uint32(dBits >> 32)
|
||||
word1 := uint32(dBits)
|
||||
|
||||
i := int((word0 >> exp_shift1) & (exp_mask >> exp_shift1))
|
||||
var d2 float64
|
||||
var denorm bool
|
||||
if i != 0 {
|
||||
d2 = setWord0(d, (word0&frac_mask1)|exp_11)
|
||||
i -= bias
|
||||
denorm = false
|
||||
} else {
|
||||
/* d is denormalized */
|
||||
i = bbits + be + (bias + (p - 1) - 1)
|
||||
var x uint64
|
||||
if i > 32 {
|
||||
x = uint64(word0)<<(64-i) | uint64(word1)>>(i-32)
|
||||
} else {
|
||||
x = uint64(word1) << (32 - i)
|
||||
}
|
||||
d2 = setWord0(float64(x), uint32((x>>32)-31*exp_mask))
|
||||
i -= (bias + (p - 1) - 1) + 1
|
||||
denorm = true
|
||||
}
|
||||
/* At this point d = f*2^i, where 1 <= f < 2. d2 is an approximation of f. */
|
||||
ds := (d2-1.5)*0.289529654602168 + 0.1760912590558 + float64(i)*0.301029995663981
|
||||
k := int(ds)
|
||||
if ds < 0.0 && ds != float64(k) {
|
||||
k-- /* want k = floor(ds) */
|
||||
}
|
||||
k_check := true
|
||||
if k >= 0 && k < len(tens) {
|
||||
if d < tens[k] {
|
||||
k--
|
||||
}
|
||||
k_check = false
|
||||
}
|
||||
/* At this point floor(log10(d)) <= k <= floor(log10(d))+1.
|
||||
If k_check is zero, we're guaranteed that k = floor(log10(d)). */
|
||||
j := bbits - i - 1
|
||||
var b2, s2, b5, s5 int
|
||||
/* At this point d = b/2^j, where b is an odd integer. */
|
||||
if j >= 0 {
|
||||
b2 = 0
|
||||
s2 = j
|
||||
} else {
|
||||
b2 = -j
|
||||
s2 = 0
|
||||
}
|
||||
if k >= 0 {
|
||||
b5 = 0
|
||||
s5 = k
|
||||
s2 += k
|
||||
} else {
|
||||
b2 -= k
|
||||
b5 = -k
|
||||
s5 = 0
|
||||
}
|
||||
/* At this point d/10^k = (b * 2^b2 * 5^b5) / (2^s2 * 5^s5), where b is an odd integer,
|
||||
b2 >= 0, b5 >= 0, s2 >= 0, and s5 >= 0. */
|
||||
if mode < 0 || mode > 9 {
|
||||
mode = 0
|
||||
}
|
||||
try_quick := true
|
||||
if mode > 5 {
|
||||
mode -= 4
|
||||
try_quick = false
|
||||
}
|
||||
leftright := true
|
||||
var ilim, ilim1 int
|
||||
switch mode {
|
||||
case 0, 1:
|
||||
ilim, ilim1 = -1, -1
|
||||
ndigits = 0
|
||||
case 2:
|
||||
leftright = false
|
||||
fallthrough
|
||||
case 4:
|
||||
if ndigits <= 0 {
|
||||
ndigits = 1
|
||||
}
|
||||
ilim, ilim1 = ndigits, ndigits
|
||||
case 3:
|
||||
leftright = false
|
||||
fallthrough
|
||||
case 5:
|
||||
i = ndigits + k + 1
|
||||
ilim = i
|
||||
ilim1 = i - 1
|
||||
}
|
||||
/* ilim is the maximum number of significant digits we want, based on k and ndigits. */
|
||||
/* ilim1 is the maximum number of significant digits we want, based on k and ndigits,
|
||||
when it turns out that k was computed too high by one. */
|
||||
fast_failed := false
|
||||
if ilim >= 0 && ilim <= quick_max && try_quick {
|
||||
|
||||
/* Try to get by with floating-point arithmetic. */
|
||||
|
||||
i = 0
|
||||
d2 = d
|
||||
k0 := k
|
||||
ilim0 := ilim
|
||||
ieps := 2 /* conservative */
|
||||
/* Divide d by 10^k, keeping track of the roundoff error and avoiding overflows. */
|
||||
if k > 0 {
|
||||
ds = tens[k&0xf]
|
||||
j = k >> 4
|
||||
if (j & bletch) != 0 {
|
||||
/* prevent overflows */
|
||||
j &= bletch - 1
|
||||
d /= bigtens[len(bigtens)-1]
|
||||
ieps++
|
||||
}
|
||||
for ; j != 0; i++ {
|
||||
if (j & 1) != 0 {
|
||||
ieps++
|
||||
ds *= bigtens[i]
|
||||
}
|
||||
j >>= 1
|
||||
}
|
||||
d /= ds
|
||||
} else if j1 := -k; j1 != 0 {
|
||||
d *= tens[j1&0xf]
|
||||
for j = j1 >> 4; j != 0; i++ {
|
||||
if (j & 1) != 0 {
|
||||
ieps++
|
||||
d *= bigtens[i]
|
||||
}
|
||||
j >>= 1
|
||||
}
|
||||
}
|
||||
/* Check that k was computed correctly. */
|
||||
if k_check && d < 1.0 && ilim > 0 {
|
||||
if ilim1 <= 0 {
|
||||
fast_failed = true
|
||||
} else {
|
||||
ilim = ilim1
|
||||
k--
|
||||
d *= 10.
|
||||
ieps++
|
||||
}
|
||||
}
|
||||
/* eps bounds the cumulative error. */
|
||||
eps := float64(ieps)*d + 7.0
|
||||
eps = setWord0(eps, _word0(eps)-(p-1)*exp_msk1)
|
||||
if ilim == 0 {
|
||||
d -= 5.0
|
||||
if d > eps {
|
||||
buf = append(buf, '1')
|
||||
k++
|
||||
return buf, k + 1
|
||||
}
|
||||
if d < -eps {
|
||||
buf = append(buf, '0')
|
||||
return buf, 1
|
||||
}
|
||||
fast_failed = true
|
||||
}
|
||||
if !fast_failed {
|
||||
fast_failed = true
|
||||
if leftright {
|
||||
/* Use Steele & White method of only
|
||||
* generating digits needed.
|
||||
*/
|
||||
eps = 0.5/tens[ilim-1] - eps
|
||||
for i = 0; ; {
|
||||
l := int64(d)
|
||||
d -= float64(l)
|
||||
buf = append(buf, byte('0'+l))
|
||||
if d < eps {
|
||||
return buf, k + 1
|
||||
}
|
||||
if 1.0-d < eps {
|
||||
buf, k = bumpUp(buf, k)
|
||||
return buf, k + 1
|
||||
}
|
||||
i++
|
||||
if i >= ilim {
|
||||
break
|
||||
}
|
||||
eps *= 10.0
|
||||
d *= 10.0
|
||||
}
|
||||
} else {
|
||||
/* Generate ilim digits, then fix them up. */
|
||||
eps *= tens[ilim-1]
|
||||
for i = 1; ; i++ {
|
||||
l := int64(d)
|
||||
d -= float64(l)
|
||||
buf = append(buf, byte('0'+l))
|
||||
if i == ilim {
|
||||
if d > 0.5+eps {
|
||||
buf, k = bumpUp(buf, k)
|
||||
return buf, k + 1
|
||||
} else if d < 0.5-eps {
|
||||
buf = stripTrailingZeroes(buf, startPos)
|
||||
return buf, k + 1
|
||||
}
|
||||
break
|
||||
}
|
||||
d *= 10.0
|
||||
}
|
||||
}
|
||||
}
|
||||
if fast_failed {
|
||||
buf = buf[:startPos]
|
||||
d = d2
|
||||
k = k0
|
||||
ilim = ilim0
|
||||
}
|
||||
}
|
||||
|
||||
/* Do we have a "small" integer? */
|
||||
if be >= 0 && k <= int_max {
|
||||
/* Yes. */
|
||||
ds = tens[k]
|
||||
if ndigits < 0 && ilim <= 0 {
|
||||
if ilim < 0 || d < 5*ds || (!biasUp && d == 5*ds) {
|
||||
buf = buf[:startPos]
|
||||
buf = append(buf, '0')
|
||||
return buf, 1
|
||||
}
|
||||
buf = append(buf, '1')
|
||||
k++
|
||||
return buf, k + 1
|
||||
}
|
||||
for i = 1; ; i++ {
|
||||
l := int64(d / ds)
|
||||
d -= float64(l) * ds
|
||||
buf = append(buf, byte('0'+l))
|
||||
if i == ilim {
|
||||
d += d
|
||||
if (d > ds) || (d == ds && (((l & 1) != 0) || biasUp)) {
|
||||
buf, k = bumpUp(buf, k)
|
||||
}
|
||||
break
|
||||
}
|
||||
d *= 10.0
|
||||
if d == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return buf, k + 1
|
||||
}
|
||||
|
||||
m2 := b2
|
||||
m5 := b5
|
||||
var mhi, mlo *big.Int
|
||||
if leftright {
|
||||
if mode < 2 {
|
||||
if denorm {
|
||||
i = be + (bias + (p - 1) - 1 + 1)
|
||||
} else {
|
||||
i = 1 + p - bbits
|
||||
}
|
||||
/* i is 1 plus the number of trailing zero bits in d's significand. Thus,
|
||||
(2^m2 * 5^m5) / (2^(s2+i) * 5^s5) = (1/2 lsb of d)/10^k. */
|
||||
} else {
|
||||
j = ilim - 1
|
||||
if m5 >= j {
|
||||
m5 -= j
|
||||
} else {
|
||||
j -= m5
|
||||
s5 += j
|
||||
b5 += j
|
||||
m5 = 0
|
||||
}
|
||||
i = ilim
|
||||
if i < 0 {
|
||||
m2 -= i
|
||||
i = 0
|
||||
}
|
||||
/* (2^m2 * 5^m5) / (2^(s2+i) * 5^s5) = (1/2 * 10^(1-ilim))/10^k. */
|
||||
}
|
||||
b2 += i
|
||||
s2 += i
|
||||
mhi = big.NewInt(1)
|
||||
/* (mhi * 2^m2 * 5^m5) / (2^s2 * 5^s5) = one-half of last printed (when mode >= 2) or
|
||||
input (when mode < 2) significant digit, divided by 10^k. */
|
||||
}
|
||||
|
||||
/* We still have d/10^k = (b * 2^b2 * 5^b5) / (2^s2 * 5^s5). Reduce common factors in
|
||||
b2, m2, and s2 without changing the equalities. */
|
||||
if m2 > 0 && s2 > 0 {
|
||||
if m2 < s2 {
|
||||
i = m2
|
||||
} else {
|
||||
i = s2
|
||||
}
|
||||
b2 -= i
|
||||
m2 -= i
|
||||
s2 -= i
|
||||
}
|
||||
|
||||
b := new(big.Int).SetBytes(dblBits)
|
||||
/* Fold b5 into b and m5 into mhi. */
|
||||
if b5 > 0 {
|
||||
if leftright {
|
||||
if m5 > 0 {
|
||||
pow5mult(mhi, m5)
|
||||
b.Mul(mhi, b)
|
||||
}
|
||||
j = b5 - m5
|
||||
if j != 0 {
|
||||
pow5mult(b, j)
|
||||
}
|
||||
} else {
|
||||
pow5mult(b, b5)
|
||||
}
|
||||
}
|
||||
/* Now we have d/10^k = (b * 2^b2) / (2^s2 * 5^s5) and
|
||||
(mhi * 2^m2) / (2^s2 * 5^s5) = one-half of last printed or input significant digit, divided by 10^k. */
|
||||
|
||||
S := big.NewInt(1)
|
||||
if s5 > 0 {
|
||||
pow5mult(S, s5)
|
||||
}
|
||||
/* Now we have d/10^k = (b * 2^b2) / (S * 2^s2) and
|
||||
(mhi * 2^m2) / (S * 2^s2) = one-half of last printed or input significant digit, divided by 10^k. */
|
||||
|
||||
/* Check for special case that d is a normalized power of 2. */
|
||||
spec_case := false
|
||||
if mode < 2 {
|
||||
if (_word1(d) == 0) && ((_word0(d) & bndry_mask) == 0) &&
|
||||
((_word0(d) & (exp_mask & (exp_mask << 1))) != 0) {
|
||||
/* The special case. Here we want to be within a quarter of the last input
|
||||
significant digit instead of one half of it when the decimal output string's value is less than d. */
|
||||
b2 += log2P
|
||||
s2 += log2P
|
||||
spec_case = true
|
||||
}
|
||||
}
|
||||
|
||||
/* Arrange for convenient computation of quotients:
|
||||
* shift left if necessary so divisor has 4 leading 0 bits.
|
||||
*
|
||||
* Perhaps we should just compute leading 28 bits of S once
|
||||
* and for all and pass them and a shift to quorem, so it
|
||||
* can do shifts and ors to compute the numerator for q.
|
||||
*/
|
||||
var zz int
|
||||
if s5 != 0 {
|
||||
S_bytes := S.Bytes()
|
||||
var S_hiWord uint32
|
||||
for idx := 0; idx < 4; idx++ {
|
||||
S_hiWord = S_hiWord << 8
|
||||
if idx < len(S_bytes) {
|
||||
S_hiWord |= uint32(S_bytes[idx])
|
||||
}
|
||||
}
|
||||
zz = 32 - hi0bits(S_hiWord)
|
||||
} else {
|
||||
zz = 1
|
||||
}
|
||||
i = (zz + s2) & 0x1f
|
||||
if i != 0 {
|
||||
i = 32 - i
|
||||
}
|
||||
/* i is the number of leading zero bits in the most significant word of S*2^s2. */
|
||||
if i > 4 {
|
||||
i -= 4
|
||||
b2 += i
|
||||
m2 += i
|
||||
s2 += i
|
||||
} else if i < 4 {
|
||||
i += 28
|
||||
b2 += i
|
||||
m2 += i
|
||||
s2 += i
|
||||
}
|
||||
/* Now S*2^s2 has exactly four leading zero bits in its most significant word. */
|
||||
if b2 > 0 {
|
||||
b = b.Lsh(b, uint(b2))
|
||||
}
|
||||
if s2 > 0 {
|
||||
S.Lsh(S, uint(s2))
|
||||
}
|
||||
/* Now we have d/10^k = b/S and
|
||||
(mhi * 2^m2) / S = maximum acceptable error, divided by 10^k. */
|
||||
if k_check {
|
||||
if b.Cmp(S) < 0 {
|
||||
k--
|
||||
b.Mul(b, big10) /* we botched the k estimate */
|
||||
if leftright {
|
||||
mhi.Mul(mhi, big10)
|
||||
}
|
||||
ilim = ilim1
|
||||
}
|
||||
}
|
||||
/* At this point 1 <= d/10^k = b/S < 10. */
|
||||
|
||||
if ilim <= 0 && mode > 2 {
|
||||
/* We're doing fixed-mode output and d is less than the minimum nonzero output in this mode.
|
||||
Output either zero or the minimum nonzero output depending on which is closer to d. */
|
||||
if ilim >= 0 {
|
||||
i = b.Cmp(S.Mul(S, big5))
|
||||
}
|
||||
if ilim < 0 || i < 0 || i == 0 && !biasUp {
|
||||
/* Always emit at least one digit. If the number appears to be zero
|
||||
using the current mode, then emit one '0' digit and set decpt to 1. */
|
||||
buf = buf[:startPos]
|
||||
buf = append(buf, '0')
|
||||
return buf, 1
|
||||
}
|
||||
buf = append(buf, '1')
|
||||
k++
|
||||
return buf, k + 1
|
||||
}
|
||||
|
||||
var dig byte
|
||||
if leftright {
|
||||
if m2 > 0 {
|
||||
mhi.Lsh(mhi, uint(m2))
|
||||
}
|
||||
|
||||
/* Compute mlo -- check for special case
|
||||
* that d is a normalized power of 2.
|
||||
*/
|
||||
|
||||
mlo = mhi
|
||||
if spec_case {
|
||||
mhi = mlo
|
||||
mhi = new(big.Int).Lsh(mhi, log2P)
|
||||
}
|
||||
/* mlo/S = maximum acceptable error, divided by 10^k, if the output is less than d. */
|
||||
/* mhi/S = maximum acceptable error, divided by 10^k, if the output is greater than d. */
|
||||
var z, delta big.Int
|
||||
for i = 1; ; i++ {
|
||||
z.DivMod(b, S, b)
|
||||
dig = byte(z.Int64() + '0')
|
||||
/* Do we yet have the shortest decimal string
|
||||
* that will round to d?
|
||||
*/
|
||||
j = b.Cmp(mlo)
|
||||
/* j is b/S compared with mlo/S. */
|
||||
delta.Sub(S, mhi)
|
||||
var j1 int
|
||||
if delta.Sign() <= 0 {
|
||||
j1 = 1
|
||||
} else {
|
||||
j1 = b.Cmp(&delta)
|
||||
}
|
||||
/* j1 is b/S compared with 1 - mhi/S. */
|
||||
if (j1 == 0) && (mode == 0) && ((_word1(d) & 1) == 0) {
|
||||
if dig == '9' {
|
||||
var flag bool
|
||||
buf = append(buf, '9')
|
||||
if buf, flag = roundOff(buf, startPos); flag {
|
||||
k++
|
||||
buf = append(buf, '1')
|
||||
}
|
||||
return buf, k + 1
|
||||
}
|
||||
if j > 0 {
|
||||
dig++
|
||||
}
|
||||
buf = append(buf, dig)
|
||||
return buf, k + 1
|
||||
}
|
||||
if (j < 0) || ((j == 0) && (mode == 0) && ((_word1(d) & 1) == 0)) {
|
||||
if j1 > 0 {
|
||||
/* Either dig or dig+1 would work here as the least significant decimal digit.
|
||||
Use whichever would produce a decimal value closer to d. */
|
||||
b.Lsh(b, 1)
|
||||
j1 = b.Cmp(S)
|
||||
if (j1 > 0) || (j1 == 0 && (((dig & 1) == 1) || biasUp)) {
|
||||
dig++
|
||||
if dig == '9' {
|
||||
buf = append(buf, '9')
|
||||
buf, flag := roundOff(buf, startPos)
|
||||
if flag {
|
||||
k++
|
||||
buf = append(buf, '1')
|
||||
}
|
||||
return buf, k + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
buf = append(buf, dig)
|
||||
return buf, k + 1
|
||||
}
|
||||
if j1 > 0 {
|
||||
if dig == '9' { /* possible if i == 1 */
|
||||
buf = append(buf, '9')
|
||||
buf, flag := roundOff(buf, startPos)
|
||||
if flag {
|
||||
k++
|
||||
buf = append(buf, '1')
|
||||
}
|
||||
return buf, k + 1
|
||||
}
|
||||
buf = append(buf, dig+1)
|
||||
return buf, k + 1
|
||||
}
|
||||
buf = append(buf, dig)
|
||||
if i == ilim {
|
||||
break
|
||||
}
|
||||
b.Mul(b, big10)
|
||||
if mlo == mhi {
|
||||
mhi.Mul(mhi, big10)
|
||||
} else {
|
||||
mlo.Mul(mlo, big10)
|
||||
mhi.Mul(mhi, big10)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var z big.Int
|
||||
for i = 1; ; i++ {
|
||||
z.DivMod(b, S, b)
|
||||
dig = byte(z.Int64() + '0')
|
||||
buf = append(buf, dig)
|
||||
if i >= ilim {
|
||||
break
|
||||
}
|
||||
|
||||
b.Mul(b, big10)
|
||||
}
|
||||
}
|
||||
/* Round off last digit */
|
||||
|
||||
b.Lsh(b, 1)
|
||||
j = b.Cmp(S)
|
||||
if (j > 0) || (j == 0 && (((dig & 1) == 1) || biasUp)) {
|
||||
var flag bool
|
||||
buf, flag = roundOff(buf, startPos)
|
||||
if flag {
|
||||
k++
|
||||
buf = append(buf, '1')
|
||||
return buf, k + 1
|
||||
}
|
||||
} else {
|
||||
buf = stripTrailingZeroes(buf, startPos)
|
||||
}
|
||||
|
||||
return buf, k + 1
|
||||
}
|
||||
|
||||
func bumpUp(buf []byte, k int) ([]byte, int) {
|
||||
var lastCh byte
|
||||
stop := 0
|
||||
if len(buf) > 0 && buf[0] == '-' {
|
||||
stop = 1
|
||||
}
|
||||
for {
|
||||
lastCh = buf[len(buf)-1]
|
||||
buf = buf[:len(buf)-1]
|
||||
if lastCh != '9' {
|
||||
break
|
||||
}
|
||||
if len(buf) == stop {
|
||||
k++
|
||||
lastCh = '0'
|
||||
break
|
||||
}
|
||||
}
|
||||
buf = append(buf, lastCh+1)
|
||||
return buf, k
|
||||
}
|
||||
|
||||
func setWord0(d float64, w uint32) float64 {
|
||||
dBits := math.Float64bits(d)
|
||||
return math.Float64frombits(uint64(w)<<32 | dBits&0xffffffff)
|
||||
}
|
||||
|
||||
func _word0(d float64) uint32 {
|
||||
dBits := math.Float64bits(d)
|
||||
return uint32(dBits >> 32)
|
||||
}
|
||||
|
||||
func _word1(d float64) uint32 {
|
||||
dBits := math.Float64bits(d)
|
||||
return uint32(dBits)
|
||||
}
|
||||
|
||||
func stripTrailingZeroes(buf []byte, startPos int) []byte {
|
||||
bl := len(buf) - 1
|
||||
for bl >= startPos && buf[bl] == '0' {
|
||||
bl--
|
||||
}
|
||||
return buf[:bl+1]
|
||||
}
|
||||
|
||||
/* Set b = b * 5^k. k must be nonnegative. */
|
||||
func pow5mult(b *big.Int, k int) *big.Int {
|
||||
if k < (1 << (len(pow5Cache) + 2)) {
|
||||
i := k & 3
|
||||
if i != 0 {
|
||||
b.Mul(b, p05[i-1])
|
||||
}
|
||||
k >>= 2
|
||||
i = 0
|
||||
for {
|
||||
if k&1 != 0 {
|
||||
b.Mul(b, pow5Cache[i])
|
||||
}
|
||||
k >>= 1
|
||||
if k == 0 {
|
||||
break
|
||||
}
|
||||
i++
|
||||
}
|
||||
return b
|
||||
}
|
||||
return b.Mul(b, new(big.Int).Exp(big5, big.NewInt(int64(k)), nil))
|
||||
}
|
||||
|
||||
func roundOff(buf []byte, startPos int) ([]byte, bool) {
|
||||
i := len(buf)
|
||||
for i != startPos {
|
||||
i--
|
||||
if buf[i] != '9' {
|
||||
buf[i]++
|
||||
return buf[:i+1], false
|
||||
}
|
||||
}
|
||||
return buf[:startPos], true
|
||||
}
|
||||
|
||||
func init() {
|
||||
p := big.NewInt(625)
|
||||
pow5Cache[0] = p
|
||||
for i := 1; i < len(pow5Cache); i++ {
|
||||
p = new(big.Int).Mul(p, p)
|
||||
pow5Cache[i] = p
|
||||
}
|
||||
}
|
||||
153
server/vendor/github.com/dop251/goja/ftoa/ftobasestr.go
generated
vendored
Normal file
153
server/vendor/github.com/dop251/goja/ftoa/ftobasestr.go
generated
vendored
Normal file
@@ -0,0 +1,153 @@
|
||||
package ftoa
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"math/big"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
digits = "0123456789abcdefghijklmnopqrstuvwxyz"
|
||||
)
|
||||
|
||||
func FToBaseStr(num float64, radix int) string {
|
||||
var negative bool
|
||||
if num < 0 {
|
||||
num = -num
|
||||
negative = true
|
||||
}
|
||||
|
||||
dfloor := math.Floor(num)
|
||||
ldfloor := int64(dfloor)
|
||||
var intDigits string
|
||||
if dfloor == float64(ldfloor) {
|
||||
if negative {
|
||||
ldfloor = -ldfloor
|
||||
}
|
||||
intDigits = strconv.FormatInt(ldfloor, radix)
|
||||
} else {
|
||||
floorBits := math.Float64bits(num)
|
||||
exp := int(floorBits>>exp_shiftL) & exp_mask_shifted
|
||||
var mantissa int64
|
||||
if exp == 0 {
|
||||
mantissa = int64((floorBits & frac_maskL) << 1)
|
||||
} else {
|
||||
mantissa = int64((floorBits & frac_maskL) | exp_msk1L)
|
||||
}
|
||||
|
||||
if negative {
|
||||
mantissa = -mantissa
|
||||
}
|
||||
exp -= 1075
|
||||
x := big.NewInt(mantissa)
|
||||
if exp > 0 {
|
||||
x.Lsh(x, uint(exp))
|
||||
} else if exp < 0 {
|
||||
x.Rsh(x, uint(-exp))
|
||||
}
|
||||
intDigits = x.Text(radix)
|
||||
}
|
||||
|
||||
if num == dfloor {
|
||||
// No fraction part
|
||||
return intDigits
|
||||
} else {
|
||||
/* We have a fraction. */
|
||||
var buffer strings.Builder
|
||||
buffer.WriteString(intDigits)
|
||||
buffer.WriteByte('.')
|
||||
df := num - dfloor
|
||||
|
||||
dBits := math.Float64bits(num)
|
||||
word0 := uint32(dBits >> 32)
|
||||
word1 := uint32(dBits)
|
||||
|
||||
dblBits := make([]byte, 0, 8)
|
||||
e, _, dblBits := d2b(df, dblBits)
|
||||
// JS_ASSERT(e < 0);
|
||||
/* At this point df = b * 2^e. e must be less than zero because 0 < df < 1. */
|
||||
|
||||
s2 := -int((word0 >> exp_shift1) & (exp_mask >> exp_shift1))
|
||||
if s2 == 0 {
|
||||
s2 = -1
|
||||
}
|
||||
s2 += bias + p
|
||||
/* 1/2^s2 = (nextDouble(d) - d)/2 */
|
||||
// JS_ASSERT(-s2 < e);
|
||||
if -s2 >= e {
|
||||
panic(fmt.Errorf("-s2 >= e: %d, %d", -s2, e))
|
||||
}
|
||||
mlo := big.NewInt(1)
|
||||
mhi := mlo
|
||||
if (word1 == 0) && ((word0 & bndry_mask) == 0) && ((word0 & (exp_mask & (exp_mask << 1))) != 0) {
|
||||
/* The special case. Here we want to be within a quarter of the last input
|
||||
significant digit instead of one half of it when the output string's value is less than d. */
|
||||
s2 += log2P
|
||||
mhi = big.NewInt(1 << log2P)
|
||||
}
|
||||
|
||||
b := new(big.Int).SetBytes(dblBits)
|
||||
b.Lsh(b, uint(e+s2))
|
||||
s := big.NewInt(1)
|
||||
s.Lsh(s, uint(s2))
|
||||
/* At this point we have the following:
|
||||
* s = 2^s2;
|
||||
* 1 > df = b/2^s2 > 0;
|
||||
* (d - prevDouble(d))/2 = mlo/2^s2;
|
||||
* (nextDouble(d) - d)/2 = mhi/2^s2. */
|
||||
bigBase := big.NewInt(int64(radix))
|
||||
|
||||
done := false
|
||||
m := &big.Int{}
|
||||
delta := &big.Int{}
|
||||
for !done {
|
||||
b.Mul(b, bigBase)
|
||||
b.DivMod(b, s, m)
|
||||
digit := byte(b.Int64())
|
||||
b, m = m, b
|
||||
mlo.Mul(mlo, bigBase)
|
||||
if mlo != mhi {
|
||||
mhi.Mul(mhi, bigBase)
|
||||
}
|
||||
|
||||
/* Do we yet have the shortest string that will round to d? */
|
||||
j := b.Cmp(mlo)
|
||||
/* j is b/2^s2 compared with mlo/2^s2. */
|
||||
|
||||
delta.Sub(s, mhi)
|
||||
var j1 int
|
||||
if delta.Sign() <= 0 {
|
||||
j1 = 1
|
||||
} else {
|
||||
j1 = b.Cmp(delta)
|
||||
}
|
||||
/* j1 is b/2^s2 compared with 1 - mhi/2^s2. */
|
||||
if j1 == 0 && (word1&1) == 0 {
|
||||
if j > 0 {
|
||||
digit++
|
||||
}
|
||||
done = true
|
||||
} else if j < 0 || (j == 0 && ((word1 & 1) == 0)) {
|
||||
if j1 > 0 {
|
||||
/* Either dig or dig+1 would work here as the least significant digit.
|
||||
Use whichever would produce an output value closer to d. */
|
||||
b.Lsh(b, 1)
|
||||
j1 = b.Cmp(s)
|
||||
if j1 > 0 { /* The even test (|| (j1 == 0 && (digit & 1))) is not here because it messes up odd base output such as 3.5 in base 3. */
|
||||
digit++
|
||||
}
|
||||
}
|
||||
done = true
|
||||
} else if j1 > 0 {
|
||||
digit++
|
||||
done = true
|
||||
}
|
||||
// JS_ASSERT(digit < (uint32)base);
|
||||
buffer.WriteByte(digits[digit])
|
||||
}
|
||||
|
||||
return buffer.String()
|
||||
}
|
||||
}
|
||||
147
server/vendor/github.com/dop251/goja/ftoa/ftostr.go
generated
vendored
Normal file
147
server/vendor/github.com/dop251/goja/ftoa/ftostr.go
generated
vendored
Normal file
@@ -0,0 +1,147 @@
|
||||
package ftoa
|
||||
|
||||
import (
|
||||
"math"
|
||||
"strconv"
|
||||
|
||||
"github.com/dop251/goja/ftoa/internal/fast"
|
||||
)
|
||||
|
||||
type FToStrMode int
|
||||
|
||||
const (
|
||||
// Either fixed or exponential format; round-trip
|
||||
ModeStandard FToStrMode = iota
|
||||
// Always exponential format; round-trip
|
||||
ModeStandardExponential
|
||||
// Round to <precision> digits after the decimal point; exponential if number is large
|
||||
ModeFixed
|
||||
// Always exponential format; <precision> significant digits
|
||||
ModeExponential
|
||||
// Either fixed or exponential format; <precision> significant digits
|
||||
ModePrecision
|
||||
)
|
||||
|
||||
func insert(b []byte, p int, c byte) []byte {
|
||||
b = append(b, 0)
|
||||
copy(b[p+1:], b[p:])
|
||||
b[p] = c
|
||||
return b
|
||||
}
|
||||
|
||||
func expand(b []byte, delta int) []byte {
|
||||
newLen := len(b) + delta
|
||||
if newLen <= cap(b) {
|
||||
return b[:newLen]
|
||||
}
|
||||
b1 := make([]byte, newLen)
|
||||
copy(b1, b)
|
||||
return b1
|
||||
}
|
||||
|
||||
func FToStr(d float64, mode FToStrMode, precision int, buffer []byte) []byte {
|
||||
if math.IsNaN(d) {
|
||||
buffer = append(buffer, "NaN"...)
|
||||
return buffer
|
||||
}
|
||||
if math.IsInf(d, 0) {
|
||||
if math.Signbit(d) {
|
||||
buffer = append(buffer, '-')
|
||||
}
|
||||
buffer = append(buffer, "Infinity"...)
|
||||
return buffer
|
||||
}
|
||||
|
||||
if mode == ModeFixed && (d >= 1e21 || d <= -1e21) {
|
||||
mode = ModeStandard
|
||||
}
|
||||
|
||||
var decPt int
|
||||
var ok bool
|
||||
startPos := len(buffer)
|
||||
|
||||
if d != 0 { // also matches -0
|
||||
if d < 0 {
|
||||
buffer = append(buffer, '-')
|
||||
d = -d
|
||||
startPos++
|
||||
}
|
||||
switch mode {
|
||||
case ModeStandard, ModeStandardExponential:
|
||||
buffer, decPt, ok = fast.Dtoa(d, fast.ModeShortest, 0, buffer)
|
||||
case ModeExponential, ModePrecision:
|
||||
buffer, decPt, ok = fast.Dtoa(d, fast.ModePrecision, precision, buffer)
|
||||
}
|
||||
} else {
|
||||
buffer = append(buffer, '0')
|
||||
decPt, ok = 1, true
|
||||
}
|
||||
if !ok {
|
||||
buffer, decPt = ftoa(d, dtoaModes[mode], mode >= ModeFixed, precision, buffer)
|
||||
}
|
||||
exponentialNotation := false
|
||||
minNDigits := 0 /* Minimum number of significand digits required by mode and precision */
|
||||
nDigits := len(buffer) - startPos
|
||||
|
||||
switch mode {
|
||||
case ModeStandard:
|
||||
if decPt < -5 || decPt > 21 {
|
||||
exponentialNotation = true
|
||||
} else {
|
||||
minNDigits = decPt
|
||||
}
|
||||
case ModeFixed:
|
||||
if precision >= 0 {
|
||||
minNDigits = decPt + precision
|
||||
} else {
|
||||
minNDigits = decPt
|
||||
}
|
||||
case ModeExponential:
|
||||
// JS_ASSERT(precision > 0);
|
||||
minNDigits = precision
|
||||
fallthrough
|
||||
case ModeStandardExponential:
|
||||
exponentialNotation = true
|
||||
case ModePrecision:
|
||||
// JS_ASSERT(precision > 0);
|
||||
minNDigits = precision
|
||||
if decPt < -5 || decPt > precision {
|
||||
exponentialNotation = true
|
||||
}
|
||||
}
|
||||
|
||||
for nDigits < minNDigits {
|
||||
buffer = append(buffer, '0')
|
||||
nDigits++
|
||||
}
|
||||
|
||||
if exponentialNotation {
|
||||
/* Insert a decimal point if more than one significand digit */
|
||||
if nDigits != 1 {
|
||||
buffer = insert(buffer, startPos+1, '.')
|
||||
}
|
||||
buffer = append(buffer, 'e')
|
||||
if decPt-1 >= 0 {
|
||||
buffer = append(buffer, '+')
|
||||
}
|
||||
buffer = strconv.AppendInt(buffer, int64(decPt-1), 10)
|
||||
} else if decPt != nDigits {
|
||||
/* Some kind of a fraction in fixed notation */
|
||||
// JS_ASSERT(decPt <= nDigits);
|
||||
if decPt > 0 {
|
||||
/* dd...dd . dd...dd */
|
||||
buffer = insert(buffer, startPos+decPt, '.')
|
||||
} else {
|
||||
/* 0 . 00...00dd...dd */
|
||||
buffer = expand(buffer, 2-decPt)
|
||||
copy(buffer[startPos+2-decPt:], buffer[startPos:])
|
||||
buffer[startPos] = '0'
|
||||
buffer[startPos+1] = '.'
|
||||
for i := startPos + 2; i < startPos+2-decPt; i++ {
|
||||
buffer[i] = '0'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return buffer
|
||||
}
|
||||
26
server/vendor/github.com/dop251/goja/ftoa/internal/fast/LICENSE_V8
generated
vendored
Normal file
26
server/vendor/github.com/dop251/goja/ftoa/internal/fast/LICENSE_V8
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
Copyright 2014, the V8 project authors. All rights reserved.
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following
|
||||
disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
120
server/vendor/github.com/dop251/goja/ftoa/internal/fast/cachedpower.go
generated
vendored
Normal file
120
server/vendor/github.com/dop251/goja/ftoa/internal/fast/cachedpower.go
generated
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
package fast
|
||||
|
||||
import "math"
|
||||
|
||||
const (
|
||||
kCachedPowersOffset = 348 // -1 * the first decimal_exponent.
|
||||
kD_1_LOG2_10 = 0.30102999566398114 // 1 / lg(10)
|
||||
kDecimalExponentDistance = 8
|
||||
)
|
||||
|
||||
type cachedPower struct {
|
||||
significand uint64
|
||||
binary_exponent int16
|
||||
decimal_exponent int16
|
||||
}
|
||||
|
||||
var (
|
||||
cachedPowers = [...]cachedPower{
|
||||
{0xFA8FD5A0081C0288, -1220, -348},
|
||||
{0xBAAEE17FA23EBF76, -1193, -340},
|
||||
{0x8B16FB203055AC76, -1166, -332},
|
||||
{0xCF42894A5DCE35EA, -1140, -324},
|
||||
{0x9A6BB0AA55653B2D, -1113, -316},
|
||||
{0xE61ACF033D1A45DF, -1087, -308},
|
||||
{0xAB70FE17C79AC6CA, -1060, -300},
|
||||
{0xFF77B1FCBEBCDC4F, -1034, -292},
|
||||
{0xBE5691EF416BD60C, -1007, -284},
|
||||
{0x8DD01FAD907FFC3C, -980, -276},
|
||||
{0xD3515C2831559A83, -954, -268},
|
||||
{0x9D71AC8FADA6C9B5, -927, -260},
|
||||
{0xEA9C227723EE8BCB, -901, -252},
|
||||
{0xAECC49914078536D, -874, -244},
|
||||
{0x823C12795DB6CE57, -847, -236},
|
||||
{0xC21094364DFB5637, -821, -228},
|
||||
{0x9096EA6F3848984F, -794, -220},
|
||||
{0xD77485CB25823AC7, -768, -212},
|
||||
{0xA086CFCD97BF97F4, -741, -204},
|
||||
{0xEF340A98172AACE5, -715, -196},
|
||||
{0xB23867FB2A35B28E, -688, -188},
|
||||
{0x84C8D4DFD2C63F3B, -661, -180},
|
||||
{0xC5DD44271AD3CDBA, -635, -172},
|
||||
{0x936B9FCEBB25C996, -608, -164},
|
||||
{0xDBAC6C247D62A584, -582, -156},
|
||||
{0xA3AB66580D5FDAF6, -555, -148},
|
||||
{0xF3E2F893DEC3F126, -529, -140},
|
||||
{0xB5B5ADA8AAFF80B8, -502, -132},
|
||||
{0x87625F056C7C4A8B, -475, -124},
|
||||
{0xC9BCFF6034C13053, -449, -116},
|
||||
{0x964E858C91BA2655, -422, -108},
|
||||
{0xDFF9772470297EBD, -396, -100},
|
||||
{0xA6DFBD9FB8E5B88F, -369, -92},
|
||||
{0xF8A95FCF88747D94, -343, -84},
|
||||
{0xB94470938FA89BCF, -316, -76},
|
||||
{0x8A08F0F8BF0F156B, -289, -68},
|
||||
{0xCDB02555653131B6, -263, -60},
|
||||
{0x993FE2C6D07B7FAC, -236, -52},
|
||||
{0xE45C10C42A2B3B06, -210, -44},
|
||||
{0xAA242499697392D3, -183, -36},
|
||||
{0xFD87B5F28300CA0E, -157, -28},
|
||||
{0xBCE5086492111AEB, -130, -20},
|
||||
{0x8CBCCC096F5088CC, -103, -12},
|
||||
{0xD1B71758E219652C, -77, -4},
|
||||
{0x9C40000000000000, -50, 4},
|
||||
{0xE8D4A51000000000, -24, 12},
|
||||
{0xAD78EBC5AC620000, 3, 20},
|
||||
{0x813F3978F8940984, 30, 28},
|
||||
{0xC097CE7BC90715B3, 56, 36},
|
||||
{0x8F7E32CE7BEA5C70, 83, 44},
|
||||
{0xD5D238A4ABE98068, 109, 52},
|
||||
{0x9F4F2726179A2245, 136, 60},
|
||||
{0xED63A231D4C4FB27, 162, 68},
|
||||
{0xB0DE65388CC8ADA8, 189, 76},
|
||||
{0x83C7088E1AAB65DB, 216, 84},
|
||||
{0xC45D1DF942711D9A, 242, 92},
|
||||
{0x924D692CA61BE758, 269, 100},
|
||||
{0xDA01EE641A708DEA, 295, 108},
|
||||
{0xA26DA3999AEF774A, 322, 116},
|
||||
{0xF209787BB47D6B85, 348, 124},
|
||||
{0xB454E4A179DD1877, 375, 132},
|
||||
{0x865B86925B9BC5C2, 402, 140},
|
||||
{0xC83553C5C8965D3D, 428, 148},
|
||||
{0x952AB45CFA97A0B3, 455, 156},
|
||||
{0xDE469FBD99A05FE3, 481, 164},
|
||||
{0xA59BC234DB398C25, 508, 172},
|
||||
{0xF6C69A72A3989F5C, 534, 180},
|
||||
{0xB7DCBF5354E9BECE, 561, 188},
|
||||
{0x88FCF317F22241E2, 588, 196},
|
||||
{0xCC20CE9BD35C78A5, 614, 204},
|
||||
{0x98165AF37B2153DF, 641, 212},
|
||||
{0xE2A0B5DC971F303A, 667, 220},
|
||||
{0xA8D9D1535CE3B396, 694, 228},
|
||||
{0xFB9B7CD9A4A7443C, 720, 236},
|
||||
{0xBB764C4CA7A44410, 747, 244},
|
||||
{0x8BAB8EEFB6409C1A, 774, 252},
|
||||
{0xD01FEF10A657842C, 800, 260},
|
||||
{0x9B10A4E5E9913129, 827, 268},
|
||||
{0xE7109BFBA19C0C9D, 853, 276},
|
||||
{0xAC2820D9623BF429, 880, 284},
|
||||
{0x80444B5E7AA7CF85, 907, 292},
|
||||
{0xBF21E44003ACDD2D, 933, 300},
|
||||
{0x8E679C2F5E44FF8F, 960, 308},
|
||||
{0xD433179D9C8CB841, 986, 316},
|
||||
{0x9E19DB92B4E31BA9, 1013, 324},
|
||||
{0xEB96BF6EBADF77D9, 1039, 332},
|
||||
{0xAF87023B9BF0EE6B, 1066, 340},
|
||||
}
|
||||
)
|
||||
|
||||
func getCachedPowerForBinaryExponentRange(min_exponent, max_exponent int) (power diyfp, decimal_exponent int) {
|
||||
kQ := diyFpKSignificandSize
|
||||
k := int(math.Ceil(float64(min_exponent+kQ-1) * kD_1_LOG2_10))
|
||||
index := (kCachedPowersOffset+k-1)/kDecimalExponentDistance + 1
|
||||
cached_power := cachedPowers[index]
|
||||
_DCHECK(min_exponent <= int(cached_power.binary_exponent))
|
||||
_DCHECK(int(cached_power.binary_exponent) <= max_exponent)
|
||||
decimal_exponent = int(cached_power.decimal_exponent)
|
||||
power = diyfp{f: cached_power.significand, e: int(cached_power.binary_exponent)}
|
||||
|
||||
return
|
||||
}
|
||||
18
server/vendor/github.com/dop251/goja/ftoa/internal/fast/common.go
generated
vendored
Normal file
18
server/vendor/github.com/dop251/goja/ftoa/internal/fast/common.go
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
Package fast contains code ported from V8 (https://github.com/v8/v8/blob/master/src/numbers/fast-dtoa.cc)
|
||||
|
||||
See LICENSE_V8 for the original copyright message and disclaimer.
|
||||
*/
|
||||
package fast
|
||||
|
||||
import "errors"
|
||||
|
||||
var (
|
||||
dcheckFailure = errors.New("DCHECK assertion failed")
|
||||
)
|
||||
|
||||
func _DCHECK(f bool) {
|
||||
if !f {
|
||||
panic(dcheckFailure)
|
||||
}
|
||||
}
|
||||
152
server/vendor/github.com/dop251/goja/ftoa/internal/fast/diyfp.go
generated
vendored
Normal file
152
server/vendor/github.com/dop251/goja/ftoa/internal/fast/diyfp.go
generated
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
package fast
|
||||
|
||||
import "math"
|
||||
|
||||
const (
|
||||
diyFpKSignificandSize = 64
|
||||
kSignificandSize = 53
|
||||
kUint64MSB uint64 = 1 << 63
|
||||
|
||||
kSignificandMask = 0x000FFFFFFFFFFFFF
|
||||
kHiddenBit = 0x0010000000000000
|
||||
kExponentMask = 0x7FF0000000000000
|
||||
|
||||
kPhysicalSignificandSize = 52 // Excludes the hidden bit.
|
||||
kExponentBias = 0x3FF + kPhysicalSignificandSize
|
||||
kDenormalExponent = -kExponentBias + 1
|
||||
)
|
||||
|
||||
type double float64
|
||||
|
||||
type diyfp struct {
|
||||
f uint64
|
||||
e int
|
||||
}
|
||||
|
||||
// f =- o.
|
||||
// The exponents of both numbers must be the same and the significand of this
|
||||
// must be bigger than the significand of other.
|
||||
// The result will not be normalized.
|
||||
func (f *diyfp) subtract(o diyfp) {
|
||||
_DCHECK(f.e == o.e)
|
||||
_DCHECK(f.f >= o.f)
|
||||
f.f -= o.f
|
||||
}
|
||||
|
||||
// Returns f - o
|
||||
// The exponents of both numbers must be the same and this must be bigger
|
||||
// than other. The result will not be normalized.
|
||||
func (f diyfp) minus(o diyfp) diyfp {
|
||||
res := f
|
||||
res.subtract(o)
|
||||
return res
|
||||
}
|
||||
|
||||
// f *= o
|
||||
func (f *diyfp) mul(o diyfp) {
|
||||
// Simply "emulates" a 128 bit multiplication.
|
||||
// However: the resulting number only contains 64 bits. The least
|
||||
// significant 64 bits are only used for rounding the most significant 64
|
||||
// bits.
|
||||
const kM32 uint64 = 0xFFFFFFFF
|
||||
a := f.f >> 32
|
||||
b := f.f & kM32
|
||||
c := o.f >> 32
|
||||
d := o.f & kM32
|
||||
ac := a * c
|
||||
bc := b * c
|
||||
ad := a * d
|
||||
bd := b * d
|
||||
tmp := (bd >> 32) + (ad & kM32) + (bc & kM32)
|
||||
// By adding 1U << 31 to tmp we round the final result.
|
||||
// Halfway cases will be round up.
|
||||
tmp += 1 << 31
|
||||
result_f := ac + (ad >> 32) + (bc >> 32) + (tmp >> 32)
|
||||
f.e += o.e + 64
|
||||
f.f = result_f
|
||||
}
|
||||
|
||||
// Returns f * o
|
||||
func (f diyfp) times(o diyfp) diyfp {
|
||||
res := f
|
||||
res.mul(o)
|
||||
return res
|
||||
}
|
||||
|
||||
func (f *diyfp) _normalize() {
|
||||
f_, e := f.f, f.e
|
||||
// This method is mainly called for normalizing boundaries. In general
|
||||
// boundaries need to be shifted by 10 bits. We thus optimize for this case.
|
||||
const k10MSBits uint64 = 0x3FF << 54
|
||||
for f_&k10MSBits == 0 {
|
||||
f_ <<= 10
|
||||
e -= 10
|
||||
}
|
||||
for f_&kUint64MSB == 0 {
|
||||
f_ <<= 1
|
||||
e--
|
||||
}
|
||||
f.f, f.e = f_, e
|
||||
}
|
||||
|
||||
func normalizeDiyfp(f diyfp) diyfp {
|
||||
res := f
|
||||
res._normalize()
|
||||
return res
|
||||
}
|
||||
|
||||
// f must be strictly greater than 0.
|
||||
func (d double) toNormalizedDiyfp() diyfp {
|
||||
f, e := d.sigExp()
|
||||
|
||||
// The current float could be a denormal.
|
||||
for (f & kHiddenBit) == 0 {
|
||||
f <<= 1
|
||||
e--
|
||||
}
|
||||
// Do the final shifts in one go.
|
||||
f <<= diyFpKSignificandSize - kSignificandSize
|
||||
e -= diyFpKSignificandSize - kSignificandSize
|
||||
return diyfp{f, e}
|
||||
}
|
||||
|
||||
// Returns the two boundaries of this.
|
||||
// The bigger boundary (m_plus) is normalized. The lower boundary has the same
|
||||
// exponent as m_plus.
|
||||
// Precondition: the value encoded by this Double must be greater than 0.
|
||||
func (d double) normalizedBoundaries() (m_minus, m_plus diyfp) {
|
||||
v := d.toDiyFp()
|
||||
significand_is_zero := v.f == kHiddenBit
|
||||
m_plus = normalizeDiyfp(diyfp{f: (v.f << 1) + 1, e: v.e - 1})
|
||||
if significand_is_zero && v.e != kDenormalExponent {
|
||||
// The boundary is closer. Think of v = 1000e10 and v- = 9999e9.
|
||||
// Then the boundary (== (v - v-)/2) is not just at a distance of 1e9 but
|
||||
// at a distance of 1e8.
|
||||
// The only exception is for the smallest normal: the largest denormal is
|
||||
// at the same distance as its successor.
|
||||
// Note: denormals have the same exponent as the smallest normals.
|
||||
m_minus = diyfp{f: (v.f << 2) - 1, e: v.e - 2}
|
||||
} else {
|
||||
m_minus = diyfp{f: (v.f << 1) - 1, e: v.e - 1}
|
||||
}
|
||||
m_minus.f <<= m_minus.e - m_plus.e
|
||||
m_minus.e = m_plus.e
|
||||
return
|
||||
}
|
||||
|
||||
func (d double) toDiyFp() diyfp {
|
||||
f, e := d.sigExp()
|
||||
return diyfp{f: f, e: e}
|
||||
}
|
||||
|
||||
func (d double) sigExp() (significand uint64, exponent int) {
|
||||
d64 := math.Float64bits(float64(d))
|
||||
significand = d64 & kSignificandMask
|
||||
if d64&kExponentMask != 0 { // not denormal
|
||||
significand += kHiddenBit
|
||||
exponent = int((d64&kExponentMask)>>kPhysicalSignificandSize) - kExponentBias
|
||||
} else {
|
||||
exponent = kDenormalExponent
|
||||
}
|
||||
return
|
||||
}
|
||||
642
server/vendor/github.com/dop251/goja/ftoa/internal/fast/dtoa.go
generated
vendored
Normal file
642
server/vendor/github.com/dop251/goja/ftoa/internal/fast/dtoa.go
generated
vendored
Normal file
@@ -0,0 +1,642 @@
|
||||
package fast
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const (
|
||||
kMinimalTargetExponent = -60
|
||||
kMaximalTargetExponent = -32
|
||||
|
||||
kTen4 = 10000
|
||||
kTen5 = 100000
|
||||
kTen6 = 1000000
|
||||
kTen7 = 10000000
|
||||
kTen8 = 100000000
|
||||
kTen9 = 1000000000
|
||||
)
|
||||
|
||||
type Mode int
|
||||
|
||||
const (
|
||||
ModeShortest Mode = iota
|
||||
ModePrecision
|
||||
)
|
||||
|
||||
// Adjusts the last digit of the generated number, and screens out generated
|
||||
// solutions that may be inaccurate. A solution may be inaccurate if it is
|
||||
// outside the safe interval, or if we cannot prove that it is closer to the
|
||||
// input than a neighboring representation of the same length.
|
||||
//
|
||||
// Input: * buffer containing the digits of too_high / 10^kappa
|
||||
// - distance_too_high_w == (too_high - w).f() * unit
|
||||
// - unsafe_interval == (too_high - too_low).f() * unit
|
||||
// - rest = (too_high - buffer * 10^kappa).f() * unit
|
||||
// - ten_kappa = 10^kappa * unit
|
||||
// - unit = the common multiplier
|
||||
//
|
||||
// Output: returns true if the buffer is guaranteed to contain the closest
|
||||
//
|
||||
// representable number to the input.
|
||||
// Modifies the generated digits in the buffer to approach (round towards) w.
|
||||
func roundWeed(buffer []byte, distance_too_high_w, unsafe_interval, rest, ten_kappa, unit uint64) bool {
|
||||
small_distance := distance_too_high_w - unit
|
||||
big_distance := distance_too_high_w + unit
|
||||
|
||||
// Let w_low = too_high - big_distance, and
|
||||
// w_high = too_high - small_distance.
|
||||
// Note: w_low < w < w_high
|
||||
//
|
||||
// The real w (* unit) must lie somewhere inside the interval
|
||||
// ]w_low; w_high[ (often written as "(w_low; w_high)")
|
||||
|
||||
// Basically the buffer currently contains a number in the unsafe interval
|
||||
// ]too_low; too_high[ with too_low < w < too_high
|
||||
//
|
||||
// too_high - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
// ^v 1 unit ^ ^ ^ ^
|
||||
// boundary_high --------------------- . . . .
|
||||
// ^v 1 unit . . . .
|
||||
// - - - - - - - - - - - - - - - - - - - + - - + - - - - - - . .
|
||||
// . . ^ . .
|
||||
// . big_distance . . .
|
||||
// . . . . rest
|
||||
// small_distance . . . .
|
||||
// v . . . .
|
||||
// w_high - - - - - - - - - - - - - - - - - - . . . .
|
||||
// ^v 1 unit . . . .
|
||||
// w ---------------------------------------- . . . .
|
||||
// ^v 1 unit v . . .
|
||||
// w_low - - - - - - - - - - - - - - - - - - - - - . . .
|
||||
// . . v
|
||||
// buffer --------------------------------------------------+-------+--------
|
||||
// . .
|
||||
// safe_interval .
|
||||
// v .
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - .
|
||||
// ^v 1 unit .
|
||||
// boundary_low ------------------------- unsafe_interval
|
||||
// ^v 1 unit v
|
||||
// too_low - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
//
|
||||
//
|
||||
// Note that the value of buffer could lie anywhere inside the range too_low
|
||||
// to too_high.
|
||||
//
|
||||
// boundary_low, boundary_high and w are approximations of the real boundaries
|
||||
// and v (the input number). They are guaranteed to be precise up to one unit.
|
||||
// In fact the error is guaranteed to be strictly less than one unit.
|
||||
//
|
||||
// Anything that lies outside the unsafe interval is guaranteed not to round
|
||||
// to v when read again.
|
||||
// Anything that lies inside the safe interval is guaranteed to round to v
|
||||
// when read again.
|
||||
// If the number inside the buffer lies inside the unsafe interval but not
|
||||
// inside the safe interval then we simply do not know and bail out (returning
|
||||
// false).
|
||||
//
|
||||
// Similarly we have to take into account the imprecision of 'w' when finding
|
||||
// the closest representation of 'w'. If we have two potential
|
||||
// representations, and one is closer to both w_low and w_high, then we know
|
||||
// it is closer to the actual value v.
|
||||
//
|
||||
// By generating the digits of too_high we got the largest (closest to
|
||||
// too_high) buffer that is still in the unsafe interval. In the case where
|
||||
// w_high < buffer < too_high we try to decrement the buffer.
|
||||
// This way the buffer approaches (rounds towards) w.
|
||||
// There are 3 conditions that stop the decrementation process:
|
||||
// 1) the buffer is already below w_high
|
||||
// 2) decrementing the buffer would make it leave the unsafe interval
|
||||
// 3) decrementing the buffer would yield a number below w_high and farther
|
||||
// away than the current number. In other words:
|
||||
// (buffer{-1} < w_high) && w_high - buffer{-1} > buffer - w_high
|
||||
// Instead of using the buffer directly we use its distance to too_high.
|
||||
// Conceptually rest ~= too_high - buffer
|
||||
// We need to do the following tests in this order to avoid over- and
|
||||
// underflows.
|
||||
_DCHECK(rest <= unsafe_interval)
|
||||
for rest < small_distance && // Negated condition 1
|
||||
unsafe_interval-rest >= ten_kappa && // Negated condition 2
|
||||
(rest+ten_kappa < small_distance || // buffer{-1} > w_high
|
||||
small_distance-rest >= rest+ten_kappa-small_distance) {
|
||||
buffer[len(buffer)-1]--
|
||||
rest += ten_kappa
|
||||
}
|
||||
|
||||
// We have approached w+ as much as possible. We now test if approaching w-
|
||||
// would require changing the buffer. If yes, then we have two possible
|
||||
// representations close to w, but we cannot decide which one is closer.
|
||||
if rest < big_distance && unsafe_interval-rest >= ten_kappa &&
|
||||
(rest+ten_kappa < big_distance ||
|
||||
big_distance-rest > rest+ten_kappa-big_distance) {
|
||||
return false
|
||||
}
|
||||
|
||||
// Weeding test.
|
||||
// The safe interval is [too_low + 2 ulp; too_high - 2 ulp]
|
||||
// Since too_low = too_high - unsafe_interval this is equivalent to
|
||||
// [too_high - unsafe_interval + 4 ulp; too_high - 2 ulp]
|
||||
// Conceptually we have: rest ~= too_high - buffer
|
||||
return (2*unit <= rest) && (rest <= unsafe_interval-4*unit)
|
||||
}
|
||||
|
||||
// Rounds the buffer upwards if the result is closer to v by possibly adding
|
||||
// 1 to the buffer. If the precision of the calculation is not sufficient to
|
||||
// round correctly, return false.
|
||||
// The rounding might shift the whole buffer in which case the kappa is
|
||||
// adjusted. For example "99", kappa = 3 might become "10", kappa = 4.
|
||||
//
|
||||
// If 2*rest > ten_kappa then the buffer needs to be round up.
|
||||
// rest can have an error of +/- 1 unit. This function accounts for the
|
||||
// imprecision and returns false, if the rounding direction cannot be
|
||||
// unambiguously determined.
|
||||
//
|
||||
// Precondition: rest < ten_kappa.
|
||||
func roundWeedCounted(buffer []byte, rest, ten_kappa, unit uint64, kappa *int) bool {
|
||||
_DCHECK(rest < ten_kappa)
|
||||
// The following tests are done in a specific order to avoid overflows. They
|
||||
// will work correctly with any uint64 values of rest < ten_kappa and unit.
|
||||
//
|
||||
// If the unit is too big, then we don't know which way to round. For example
|
||||
// a unit of 50 means that the real number lies within rest +/- 50. If
|
||||
// 10^kappa == 40 then there is no way to tell which way to round.
|
||||
if unit >= ten_kappa {
|
||||
return false
|
||||
}
|
||||
// Even if unit is just half the size of 10^kappa we are already completely
|
||||
// lost. (And after the previous test we know that the expression will not
|
||||
// over/underflow.)
|
||||
if ten_kappa-unit <= unit {
|
||||
return false
|
||||
}
|
||||
// If 2 * (rest + unit) <= 10^kappa we can safely round down.
|
||||
if (ten_kappa-rest > rest) && (ten_kappa-2*rest >= 2*unit) {
|
||||
return true
|
||||
}
|
||||
|
||||
// If 2 * (rest - unit) >= 10^kappa, then we can safely round up.
|
||||
if (rest > unit) && (ten_kappa-(rest-unit) <= (rest - unit)) {
|
||||
// Increment the last digit recursively until we find a non '9' digit.
|
||||
buffer[len(buffer)-1]++
|
||||
for i := len(buffer) - 1; i > 0; i-- {
|
||||
if buffer[i] != '0'+10 {
|
||||
break
|
||||
}
|
||||
buffer[i] = '0'
|
||||
buffer[i-1]++
|
||||
}
|
||||
// If the first digit is now '0'+ 10 we had a buffer with all '9's. With the
|
||||
// exception of the first digit all digits are now '0'. Simply switch the
|
||||
// first digit to '1' and adjust the kappa. Example: "99" becomes "10" and
|
||||
// the power (the kappa) is increased.
|
||||
if buffer[0] == '0'+10 {
|
||||
buffer[0] = '1'
|
||||
*kappa += 1
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Returns the biggest power of ten that is less than or equal than the given
|
||||
// number. We furthermore receive the maximum number of bits 'number' has.
|
||||
// If number_bits == 0 then 0^-1 is returned
|
||||
// The number of bits must be <= 32.
|
||||
// Precondition: number < (1 << (number_bits + 1)).
|
||||
func biggestPowerTen(number uint32, number_bits int) (power uint32, exponent int) {
|
||||
switch number_bits {
|
||||
case 32, 31, 30:
|
||||
if kTen9 <= number {
|
||||
power = kTen9
|
||||
exponent = 9
|
||||
break
|
||||
}
|
||||
fallthrough
|
||||
case 29, 28, 27:
|
||||
if kTen8 <= number {
|
||||
power = kTen8
|
||||
exponent = 8
|
||||
break
|
||||
}
|
||||
fallthrough
|
||||
case 26, 25, 24:
|
||||
if kTen7 <= number {
|
||||
power = kTen7
|
||||
exponent = 7
|
||||
break
|
||||
}
|
||||
fallthrough
|
||||
case 23, 22, 21, 20:
|
||||
if kTen6 <= number {
|
||||
power = kTen6
|
||||
exponent = 6
|
||||
break
|
||||
}
|
||||
fallthrough
|
||||
case 19, 18, 17:
|
||||
if kTen5 <= number {
|
||||
power = kTen5
|
||||
exponent = 5
|
||||
break
|
||||
}
|
||||
fallthrough
|
||||
case 16, 15, 14:
|
||||
if kTen4 <= number {
|
||||
power = kTen4
|
||||
exponent = 4
|
||||
break
|
||||
}
|
||||
fallthrough
|
||||
case 13, 12, 11, 10:
|
||||
if 1000 <= number {
|
||||
power = 1000
|
||||
exponent = 3
|
||||
break
|
||||
}
|
||||
fallthrough
|
||||
case 9, 8, 7:
|
||||
if 100 <= number {
|
||||
power = 100
|
||||
exponent = 2
|
||||
break
|
||||
}
|
||||
fallthrough
|
||||
case 6, 5, 4:
|
||||
if 10 <= number {
|
||||
power = 10
|
||||
exponent = 1
|
||||
break
|
||||
}
|
||||
fallthrough
|
||||
case 3, 2, 1:
|
||||
if 1 <= number {
|
||||
power = 1
|
||||
exponent = 0
|
||||
break
|
||||
}
|
||||
fallthrough
|
||||
case 0:
|
||||
power = 0
|
||||
exponent = -1
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Generates the digits of input number w.
|
||||
// w is a floating-point number (DiyFp), consisting of a significand and an
|
||||
// exponent. Its exponent is bounded by kMinimalTargetExponent and
|
||||
// kMaximalTargetExponent.
|
||||
//
|
||||
// Hence -60 <= w.e() <= -32.
|
||||
//
|
||||
// Returns false if it fails, in which case the generated digits in the buffer
|
||||
// should not be used.
|
||||
// Preconditions:
|
||||
// - low, w and high are correct up to 1 ulp (unit in the last place). That
|
||||
// is, their error must be less than a unit of their last digits.
|
||||
// - low.e() == w.e() == high.e()
|
||||
// - low < w < high, and taking into account their error: low~ <= high~
|
||||
// - kMinimalTargetExponent <= w.e() <= kMaximalTargetExponent
|
||||
//
|
||||
// Postconditions: returns false if procedure fails.
|
||||
//
|
||||
// otherwise:
|
||||
// * buffer is not null-terminated, but len contains the number of digits.
|
||||
// * buffer contains the shortest possible decimal digit-sequence
|
||||
// such that LOW < buffer * 10^kappa < HIGH, where LOW and HIGH are the
|
||||
// correct values of low and high (without their error).
|
||||
// * if more than one decimal representation gives the minimal number of
|
||||
// decimal digits then the one closest to W (where W is the correct value
|
||||
// of w) is chosen.
|
||||
//
|
||||
// Remark: this procedure takes into account the imprecision of its input
|
||||
//
|
||||
// numbers. If the precision is not enough to guarantee all the postconditions
|
||||
// then false is returned. This usually happens rarely (~0.5%).
|
||||
//
|
||||
// Say, for the sake of example, that
|
||||
//
|
||||
// w.e() == -48, and w.f() == 0x1234567890ABCDEF
|
||||
//
|
||||
// w's value can be computed by w.f() * 2^w.e()
|
||||
// We can obtain w's integral digits by simply shifting w.f() by -w.e().
|
||||
//
|
||||
// -> w's integral part is 0x1234
|
||||
// w's fractional part is therefore 0x567890ABCDEF.
|
||||
//
|
||||
// Printing w's integral part is easy (simply print 0x1234 in decimal).
|
||||
// In order to print its fraction we repeatedly multiply the fraction by 10 and
|
||||
// get each digit. Example the first digit after the point would be computed by
|
||||
//
|
||||
// (0x567890ABCDEF * 10) >> 48. -> 3
|
||||
//
|
||||
// The whole thing becomes slightly more complicated because we want to stop
|
||||
// once we have enough digits. That is, once the digits inside the buffer
|
||||
// represent 'w' we can stop. Everything inside the interval low - high
|
||||
// represents w. However we have to pay attention to low, high and w's
|
||||
// imprecision.
|
||||
func digitGen(low, w, high diyfp, buffer []byte) (kappa int, buf []byte, res bool) {
|
||||
_DCHECK(low.e == w.e && w.e == high.e)
|
||||
_DCHECK(low.f+1 <= high.f-1)
|
||||
_DCHECK(kMinimalTargetExponent <= w.e && w.e <= kMaximalTargetExponent)
|
||||
// low, w and high are imprecise, but by less than one ulp (unit in the last
|
||||
// place).
|
||||
// If we remove (resp. add) 1 ulp from low (resp. high) we are certain that
|
||||
// the new numbers are outside of the interval we want the final
|
||||
// representation to lie in.
|
||||
// Inversely adding (resp. removing) 1 ulp from low (resp. high) would yield
|
||||
// numbers that are certain to lie in the interval. We will use this fact
|
||||
// later on.
|
||||
// We will now start by generating the digits within the uncertain
|
||||
// interval. Later we will weed out representations that lie outside the safe
|
||||
// interval and thus _might_ lie outside the correct interval.
|
||||
unit := uint64(1)
|
||||
too_low := diyfp{f: low.f - unit, e: low.e}
|
||||
too_high := diyfp{f: high.f + unit, e: high.e}
|
||||
// too_low and too_high are guaranteed to lie outside the interval we want the
|
||||
// generated number in.
|
||||
unsafe_interval := too_high.minus(too_low)
|
||||
// We now cut the input number into two parts: the integral digits and the
|
||||
// fractionals. We will not write any decimal separator though, but adapt
|
||||
// kappa instead.
|
||||
// Reminder: we are currently computing the digits (stored inside the buffer)
|
||||
// such that: too_low < buffer * 10^kappa < too_high
|
||||
// We use too_high for the digit_generation and stop as soon as possible.
|
||||
// If we stop early we effectively round down.
|
||||
one := diyfp{f: 1 << -w.e, e: w.e}
|
||||
// Division by one is a shift.
|
||||
integrals := uint32(too_high.f >> -one.e)
|
||||
// Modulo by one is an and.
|
||||
fractionals := too_high.f & (one.f - 1)
|
||||
divisor, divisor_exponent := biggestPowerTen(integrals, diyFpKSignificandSize-(-one.e))
|
||||
kappa = divisor_exponent + 1
|
||||
buf = buffer
|
||||
for kappa > 0 {
|
||||
digit := int(integrals / divisor)
|
||||
buf = append(buf, byte('0'+digit))
|
||||
integrals %= divisor
|
||||
kappa--
|
||||
// Note that kappa now equals the exponent of the divisor and that the
|
||||
// invariant thus holds again.
|
||||
rest := uint64(integrals)<<-one.e + fractionals
|
||||
// Invariant: too_high = buffer * 10^kappa + DiyFp(rest, one.e)
|
||||
// Reminder: unsafe_interval.e == one.e
|
||||
if rest < unsafe_interval.f {
|
||||
// Rounding down (by not emitting the remaining digits) yields a number
|
||||
// that lies within the unsafe interval.
|
||||
res = roundWeed(buf, too_high.minus(w).f,
|
||||
unsafe_interval.f, rest,
|
||||
uint64(divisor)<<-one.e, unit)
|
||||
return
|
||||
}
|
||||
divisor /= 10
|
||||
}
|
||||
// The integrals have been generated. We are at the point of the decimal
|
||||
// separator. In the following loop we simply multiply the remaining digits by
|
||||
// 10 and divide by one. We just need to pay attention to multiply associated
|
||||
// data (like the interval or 'unit'), too.
|
||||
// Note that the multiplication by 10 does not overflow, because w.e >= -60
|
||||
// and thus one.e >= -60.
|
||||
_DCHECK(one.e >= -60)
|
||||
_DCHECK(fractionals < one.f)
|
||||
_DCHECK(0xFFFFFFFFFFFFFFFF/10 >= one.f)
|
||||
for {
|
||||
fractionals *= 10
|
||||
unit *= 10
|
||||
unsafe_interval.f *= 10
|
||||
// Integer division by one.
|
||||
digit := byte(fractionals >> -one.e)
|
||||
buf = append(buf, '0'+digit)
|
||||
fractionals &= one.f - 1 // Modulo by one.
|
||||
kappa--
|
||||
if fractionals < unsafe_interval.f {
|
||||
res = roundWeed(buf, too_high.minus(w).f*unit, unsafe_interval.f, fractionals, one.f, unit)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Generates (at most) requested_digits of input number w.
|
||||
// w is a floating-point number (DiyFp), consisting of a significand and an
|
||||
// exponent. Its exponent is bounded by kMinimalTargetExponent and
|
||||
// kMaximalTargetExponent.
|
||||
//
|
||||
// Hence -60 <= w.e() <= -32.
|
||||
//
|
||||
// Returns false if it fails, in which case the generated digits in the buffer
|
||||
// should not be used.
|
||||
// Preconditions:
|
||||
// - w is correct up to 1 ulp (unit in the last place). That
|
||||
// is, its error must be strictly less than a unit of its last digit.
|
||||
// - kMinimalTargetExponent <= w.e() <= kMaximalTargetExponent
|
||||
//
|
||||
// Postconditions: returns false if procedure fails.
|
||||
//
|
||||
// otherwise:
|
||||
// * buffer is not null-terminated, but length contains the number of
|
||||
// digits.
|
||||
// * the representation in buffer is the most precise representation of
|
||||
// requested_digits digits.
|
||||
// * buffer contains at most requested_digits digits of w. If there are less
|
||||
// than requested_digits digits then some trailing '0's have been removed.
|
||||
// * kappa is such that
|
||||
// w = buffer * 10^kappa + eps with |eps| < 10^kappa / 2.
|
||||
//
|
||||
// Remark: This procedure takes into account the imprecision of its input
|
||||
//
|
||||
// numbers. If the precision is not enough to guarantee all the postconditions
|
||||
// then false is returned. This usually happens rarely, but the failure-rate
|
||||
// increases with higher requested_digits.
|
||||
func digitGenCounted(w diyfp, requested_digits int, buffer []byte) (kappa int, buf []byte, res bool) {
|
||||
_DCHECK(kMinimalTargetExponent <= w.e && w.e <= kMaximalTargetExponent)
|
||||
|
||||
// w is assumed to have an error less than 1 unit. Whenever w is scaled we
|
||||
// also scale its error.
|
||||
w_error := uint64(1)
|
||||
// We cut the input number into two parts: the integral digits and the
|
||||
// fractional digits. We don't emit any decimal separator, but adapt kappa
|
||||
// instead. Example: instead of writing "1.2" we put "12" into the buffer and
|
||||
// increase kappa by 1.
|
||||
one := diyfp{f: 1 << -w.e, e: w.e}
|
||||
// Division by one is a shift.
|
||||
integrals := uint32(w.f >> -one.e)
|
||||
// Modulo by one is an and.
|
||||
fractionals := w.f & (one.f - 1)
|
||||
divisor, divisor_exponent := biggestPowerTen(integrals, diyFpKSignificandSize-(-one.e))
|
||||
kappa = divisor_exponent + 1
|
||||
buf = buffer
|
||||
// Loop invariant: buffer = w / 10^kappa (integer division)
|
||||
// The invariant holds for the first iteration: kappa has been initialized
|
||||
// with the divisor exponent + 1. And the divisor is the biggest power of ten
|
||||
// that is smaller than 'integrals'.
|
||||
for kappa > 0 {
|
||||
digit := byte(integrals / divisor)
|
||||
buf = append(buf, '0'+digit)
|
||||
requested_digits--
|
||||
integrals %= divisor
|
||||
kappa--
|
||||
// Note that kappa now equals the exponent of the divisor and that the
|
||||
// invariant thus holds again.
|
||||
if requested_digits == 0 {
|
||||
break
|
||||
}
|
||||
divisor /= 10
|
||||
}
|
||||
|
||||
if requested_digits == 0 {
|
||||
rest := uint64(integrals)<<-one.e + fractionals
|
||||
res = roundWeedCounted(buf, rest, uint64(divisor)<<-one.e, w_error, &kappa)
|
||||
return
|
||||
}
|
||||
|
||||
// The integrals have been generated. We are at the point of the decimal
|
||||
// separator. In the following loop we simply multiply the remaining digits by
|
||||
// 10 and divide by one. We just need to pay attention to multiply associated
|
||||
// data (the 'unit'), too.
|
||||
// Note that the multiplication by 10 does not overflow, because w.e >= -60
|
||||
// and thus one.e >= -60.
|
||||
_DCHECK(one.e >= -60)
|
||||
_DCHECK(fractionals < one.f)
|
||||
_DCHECK(0xFFFFFFFFFFFFFFFF/10 >= one.f)
|
||||
for requested_digits > 0 && fractionals > w_error {
|
||||
fractionals *= 10
|
||||
w_error *= 10
|
||||
// Integer division by one.
|
||||
digit := byte(fractionals >> -one.e)
|
||||
buf = append(buf, '0'+digit)
|
||||
requested_digits--
|
||||
fractionals &= one.f - 1 // Modulo by one.
|
||||
kappa--
|
||||
}
|
||||
if requested_digits != 0 {
|
||||
res = false
|
||||
} else {
|
||||
res = roundWeedCounted(buf, fractionals, one.f, w_error, &kappa)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Provides a decimal representation of v.
|
||||
// Returns true if it succeeds, otherwise the result cannot be trusted.
|
||||
// There will be *length digits inside the buffer (not null-terminated).
|
||||
// If the function returns true then
|
||||
//
|
||||
// v == (double) (buffer * 10^decimal_exponent).
|
||||
//
|
||||
// The digits in the buffer are the shortest representation possible: no
|
||||
// 0.09999999999999999 instead of 0.1. The shorter representation will even be
|
||||
// chosen even if the longer one would be closer to v.
|
||||
// The last digit will be closest to the actual v. That is, even if several
|
||||
// digits might correctly yield 'v' when read again, the closest will be
|
||||
// computed.
|
||||
func grisu3(f float64, buffer []byte) (digits []byte, decimal_exponent int, result bool) {
|
||||
v := double(f)
|
||||
w := v.toNormalizedDiyfp()
|
||||
|
||||
// boundary_minus and boundary_plus are the boundaries between v and its
|
||||
// closest floating-point neighbors. Any number strictly between
|
||||
// boundary_minus and boundary_plus will round to v when convert to a double.
|
||||
// Grisu3 will never output representations that lie exactly on a boundary.
|
||||
boundary_minus, boundary_plus := v.normalizedBoundaries()
|
||||
ten_mk_minimal_binary_exponent := kMinimalTargetExponent - (w.e + diyFpKSignificandSize)
|
||||
ten_mk_maximal_binary_exponent := kMaximalTargetExponent - (w.e + diyFpKSignificandSize)
|
||||
ten_mk, mk := getCachedPowerForBinaryExponentRange(ten_mk_minimal_binary_exponent, ten_mk_maximal_binary_exponent)
|
||||
|
||||
_DCHECK(
|
||||
(kMinimalTargetExponent <=
|
||||
w.e+ten_mk.e+diyFpKSignificandSize) &&
|
||||
(kMaximalTargetExponent >= w.e+ten_mk.e+diyFpKSignificandSize))
|
||||
// Note that ten_mk is only an approximation of 10^-k. A DiyFp only contains a
|
||||
// 64 bit significand and ten_mk is thus only precise up to 64 bits.
|
||||
|
||||
// The DiyFp::Times procedure rounds its result, and ten_mk is approximated
|
||||
// too. The variable scaled_w (as well as scaled_boundary_minus/plus) are now
|
||||
// off by a small amount.
|
||||
// In fact: scaled_w - w*10^k < 1ulp (unit in the last place) of scaled_w.
|
||||
// In other words: let f = scaled_w.f() and e = scaled_w.e(), then
|
||||
// (f-1) * 2^e < w*10^k < (f+1) * 2^e
|
||||
scaled_w := w.times(ten_mk)
|
||||
_DCHECK(scaled_w.e ==
|
||||
boundary_plus.e+ten_mk.e+diyFpKSignificandSize)
|
||||
// In theory it would be possible to avoid some recomputations by computing
|
||||
// the difference between w and boundary_minus/plus (a power of 2) and to
|
||||
// compute scaled_boundary_minus/plus by subtracting/adding from
|
||||
// scaled_w. However the code becomes much less readable and the speed
|
||||
// enhancements are not terrific.
|
||||
scaled_boundary_minus := boundary_minus.times(ten_mk)
|
||||
scaled_boundary_plus := boundary_plus.times(ten_mk)
|
||||
// DigitGen will generate the digits of scaled_w. Therefore we have
|
||||
// v == (double) (scaled_w * 10^-mk).
|
||||
// Set decimal_exponent == -mk and pass it to DigitGen. If scaled_w is not an
|
||||
// integer than it will be updated. For instance if scaled_w == 1.23 then
|
||||
// the buffer will be filled with "123" und the decimal_exponent will be
|
||||
// decreased by 2.
|
||||
var kappa int
|
||||
kappa, digits, result = digitGen(scaled_boundary_minus, scaled_w, scaled_boundary_plus, buffer)
|
||||
decimal_exponent = -mk + kappa
|
||||
return
|
||||
}
|
||||
|
||||
// The "counted" version of grisu3 (see above) only generates requested_digits
|
||||
// number of digits. This version does not generate the shortest representation,
|
||||
// and with enough requested digits 0.1 will at some point print as 0.9999999...
|
||||
// Grisu3 is too imprecise for real halfway cases (1.5 will not work) and
|
||||
// therefore the rounding strategy for halfway cases is irrelevant.
|
||||
func grisu3Counted(v float64, requested_digits int, buffer []byte) (digits []byte, decimal_exponent int, result bool) {
|
||||
w := double(v).toNormalizedDiyfp()
|
||||
ten_mk_minimal_binary_exponent := kMinimalTargetExponent - (w.e + diyFpKSignificandSize)
|
||||
ten_mk_maximal_binary_exponent := kMaximalTargetExponent - (w.e + diyFpKSignificandSize)
|
||||
ten_mk, mk := getCachedPowerForBinaryExponentRange(ten_mk_minimal_binary_exponent, ten_mk_maximal_binary_exponent)
|
||||
|
||||
_DCHECK(
|
||||
(kMinimalTargetExponent <=
|
||||
w.e+ten_mk.e+diyFpKSignificandSize) &&
|
||||
(kMaximalTargetExponent >= w.e+ten_mk.e+diyFpKSignificandSize))
|
||||
// Note that ten_mk is only an approximation of 10^-k. A DiyFp only contains a
|
||||
// 64 bit significand and ten_mk is thus only precise up to 64 bits.
|
||||
|
||||
// The DiyFp::Times procedure rounds its result, and ten_mk is approximated
|
||||
// too. The variable scaled_w (as well as scaled_boundary_minus/plus) are now
|
||||
// off by a small amount.
|
||||
// In fact: scaled_w - w*10^k < 1ulp (unit in the last place) of scaled_w.
|
||||
// In other words: let f = scaled_w.f() and e = scaled_w.e(), then
|
||||
// (f-1) * 2^e < w*10^k < (f+1) * 2^e
|
||||
scaled_w := w.times(ten_mk)
|
||||
// We now have (double) (scaled_w * 10^-mk).
|
||||
// DigitGen will generate the first requested_digits digits of scaled_w and
|
||||
// return together with a kappa such that scaled_w ~= buffer * 10^kappa. (It
|
||||
// will not always be exactly the same since DigitGenCounted only produces a
|
||||
// limited number of digits.)
|
||||
var kappa int
|
||||
kappa, digits, result = digitGenCounted(scaled_w, requested_digits, buffer)
|
||||
decimal_exponent = -mk + kappa
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// v must be > 0 and must not be Inf or NaN
|
||||
func Dtoa(v float64, mode Mode, requested_digits int, buffer []byte) (digits []byte, decimal_point int, result bool) {
|
||||
defer func() {
|
||||
if x := recover(); x != nil {
|
||||
if x == dcheckFailure {
|
||||
panic(fmt.Errorf("DCHECK assertion failed while formatting %s in mode %d", strconv.FormatFloat(v, 'e', 50, 64), mode))
|
||||
}
|
||||
panic(x)
|
||||
}
|
||||
}()
|
||||
var decimal_exponent int
|
||||
startPos := len(buffer)
|
||||
switch mode {
|
||||
case ModeShortest:
|
||||
digits, decimal_exponent, result = grisu3(v, buffer)
|
||||
case ModePrecision:
|
||||
digits, decimal_exponent, result = grisu3Counted(v, requested_digits, buffer)
|
||||
}
|
||||
if result {
|
||||
decimal_point = len(digits) - startPos + decimal_exponent
|
||||
} else {
|
||||
digits = digits[:startPos]
|
||||
}
|
||||
return
|
||||
}
|
||||
1101
server/vendor/github.com/dop251/goja/func.go
generated
vendored
Normal file
1101
server/vendor/github.com/dop251/goja/func.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
97
server/vendor/github.com/dop251/goja/ipow.go
generated
vendored
Normal file
97
server/vendor/github.com/dop251/goja/ipow.go
generated
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
package goja
|
||||
|
||||
// ported from https://gist.github.com/orlp/3551590
|
||||
|
||||
var highest_bit_set = [256]byte{
|
||||
0, 1, 2, 2, 3, 3, 3, 3,
|
||||
4, 4, 4, 4, 4, 4, 4, 4,
|
||||
5, 5, 5, 5, 5, 5, 5, 5,
|
||||
5, 5, 5, 5, 5, 5, 5, 5,
|
||||
6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 255, // anything past 63 is a guaranteed overflow with base > 1
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
255, 255, 255, 255, 255, 255, 255, 255,
|
||||
}
|
||||
|
||||
func ipow(base, exp int64) (result int64) {
|
||||
result = 1
|
||||
|
||||
switch highest_bit_set[byte(exp)] {
|
||||
case 255: // we use 255 as an overflow marker and return 0 on overflow/underflow
|
||||
if base == 1 {
|
||||
return 1
|
||||
}
|
||||
|
||||
if base == -1 {
|
||||
return 1 - 2*(exp&1)
|
||||
}
|
||||
|
||||
return 0
|
||||
case 6:
|
||||
if exp&1 != 0 {
|
||||
result *= base
|
||||
}
|
||||
exp >>= 1
|
||||
base *= base
|
||||
fallthrough
|
||||
case 5:
|
||||
if exp&1 != 0 {
|
||||
result *= base
|
||||
}
|
||||
exp >>= 1
|
||||
base *= base
|
||||
fallthrough
|
||||
case 4:
|
||||
if exp&1 != 0 {
|
||||
result *= base
|
||||
}
|
||||
exp >>= 1
|
||||
base *= base
|
||||
fallthrough
|
||||
case 3:
|
||||
if exp&1 != 0 {
|
||||
result *= base
|
||||
}
|
||||
exp >>= 1
|
||||
base *= base
|
||||
fallthrough
|
||||
case 2:
|
||||
if exp&1 != 0 {
|
||||
result *= base
|
||||
}
|
||||
exp >>= 1
|
||||
base *= base
|
||||
fallthrough
|
||||
case 1:
|
||||
if exp&1 != 0 {
|
||||
result *= base
|
||||
}
|
||||
fallthrough
|
||||
default:
|
||||
return result
|
||||
}
|
||||
}
|
||||
169
server/vendor/github.com/dop251/goja/map.go
generated
vendored
Normal file
169
server/vendor/github.com/dop251/goja/map.go
generated
vendored
Normal file
@@ -0,0 +1,169 @@
|
||||
package goja
|
||||
|
||||
import (
|
||||
"hash/maphash"
|
||||
)
|
||||
|
||||
type mapEntry struct {
|
||||
key, value Value
|
||||
|
||||
iterPrev, iterNext *mapEntry
|
||||
hNext *mapEntry
|
||||
}
|
||||
|
||||
type orderedMap struct {
|
||||
hash *maphash.Hash
|
||||
hashTable map[uint64]*mapEntry
|
||||
iterFirst, iterLast *mapEntry
|
||||
size int
|
||||
}
|
||||
|
||||
type orderedMapIter struct {
|
||||
m *orderedMap
|
||||
cur *mapEntry
|
||||
}
|
||||
|
||||
func (m *orderedMap) lookup(key Value) (h uint64, entry, hPrev *mapEntry) {
|
||||
if key == _negativeZero {
|
||||
key = intToValue(0)
|
||||
}
|
||||
h = key.hash(m.hash)
|
||||
for entry = m.hashTable[h]; entry != nil && !entry.key.SameAs(key); hPrev, entry = entry, entry.hNext {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (m *orderedMap) set(key, value Value) {
|
||||
h, entry, hPrev := m.lookup(key)
|
||||
if entry != nil {
|
||||
entry.value = value
|
||||
} else {
|
||||
if key == _negativeZero {
|
||||
key = intToValue(0)
|
||||
}
|
||||
entry = &mapEntry{key: key, value: value}
|
||||
if hPrev == nil {
|
||||
m.hashTable[h] = entry
|
||||
} else {
|
||||
hPrev.hNext = entry
|
||||
}
|
||||
if m.iterLast != nil {
|
||||
entry.iterPrev = m.iterLast
|
||||
m.iterLast.iterNext = entry
|
||||
} else {
|
||||
m.iterFirst = entry
|
||||
}
|
||||
m.iterLast = entry
|
||||
m.size++
|
||||
}
|
||||
}
|
||||
|
||||
func (m *orderedMap) get(key Value) Value {
|
||||
_, entry, _ := m.lookup(key)
|
||||
if entry != nil {
|
||||
return entry.value
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *orderedMap) remove(key Value) bool {
|
||||
h, entry, hPrev := m.lookup(key)
|
||||
if entry != nil {
|
||||
entry.key = nil
|
||||
entry.value = nil
|
||||
|
||||
// remove from the doubly-linked list
|
||||
if entry.iterPrev != nil {
|
||||
entry.iterPrev.iterNext = entry.iterNext
|
||||
} else {
|
||||
m.iterFirst = entry.iterNext
|
||||
}
|
||||
if entry.iterNext != nil {
|
||||
entry.iterNext.iterPrev = entry.iterPrev
|
||||
} else {
|
||||
m.iterLast = entry.iterPrev
|
||||
}
|
||||
|
||||
// remove from the hashTable
|
||||
if hPrev == nil {
|
||||
if entry.hNext == nil {
|
||||
delete(m.hashTable, h)
|
||||
} else {
|
||||
m.hashTable[h] = entry.hNext
|
||||
}
|
||||
} else {
|
||||
hPrev.hNext = entry.hNext
|
||||
}
|
||||
|
||||
m.size--
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (m *orderedMap) has(key Value) bool {
|
||||
_, entry, _ := m.lookup(key)
|
||||
return entry != nil
|
||||
}
|
||||
|
||||
func (iter *orderedMapIter) next() *mapEntry {
|
||||
if iter.m == nil {
|
||||
// closed iterator
|
||||
return nil
|
||||
}
|
||||
|
||||
cur := iter.cur
|
||||
// if the current item was deleted, track back to find the latest that wasn't
|
||||
for cur != nil && cur.key == nil {
|
||||
cur = cur.iterPrev
|
||||
}
|
||||
|
||||
if cur != nil {
|
||||
cur = cur.iterNext
|
||||
} else {
|
||||
cur = iter.m.iterFirst
|
||||
}
|
||||
|
||||
if cur == nil {
|
||||
iter.close()
|
||||
} else {
|
||||
iter.cur = cur
|
||||
}
|
||||
|
||||
return cur
|
||||
}
|
||||
|
||||
func (iter *orderedMapIter) close() {
|
||||
iter.m = nil
|
||||
iter.cur = nil
|
||||
}
|
||||
|
||||
func newOrderedMap(h *maphash.Hash) *orderedMap {
|
||||
return &orderedMap{
|
||||
hash: h,
|
||||
hashTable: make(map[uint64]*mapEntry),
|
||||
}
|
||||
}
|
||||
|
||||
func (m *orderedMap) newIter() *orderedMapIter {
|
||||
iter := &orderedMapIter{
|
||||
m: m,
|
||||
}
|
||||
return iter
|
||||
}
|
||||
|
||||
func (m *orderedMap) clear() {
|
||||
for item := m.iterFirst; item != nil; item = item.iterNext {
|
||||
item.key = nil
|
||||
item.value = nil
|
||||
if item.iterPrev != nil {
|
||||
item.iterPrev.iterNext = nil
|
||||
}
|
||||
}
|
||||
m.iterFirst = nil
|
||||
m.iterLast = nil
|
||||
m.hashTable = make(map[uint64]*mapEntry)
|
||||
m.size = 0
|
||||
}
|
||||
1843
server/vendor/github.com/dop251/goja/object.go
generated
vendored
Normal file
1843
server/vendor/github.com/dop251/goja/object.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
139
server/vendor/github.com/dop251/goja/object_args.go
generated
vendored
Normal file
139
server/vendor/github.com/dop251/goja/object_args.go
generated
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
package goja
|
||||
|
||||
import "github.com/dop251/goja/unistring"
|
||||
|
||||
type argumentsObject struct {
|
||||
baseObject
|
||||
length int
|
||||
}
|
||||
|
||||
type mappedProperty struct {
|
||||
valueProperty
|
||||
v *Value
|
||||
}
|
||||
|
||||
func (a *argumentsObject) getStr(name unistring.String, receiver Value) Value {
|
||||
return a.getStrWithOwnProp(a.getOwnPropStr(name), name, receiver)
|
||||
}
|
||||
|
||||
func (a *argumentsObject) getOwnPropStr(name unistring.String) Value {
|
||||
if mapped, ok := a.values[name].(*mappedProperty); ok {
|
||||
if mapped.writable && mapped.enumerable && mapped.configurable {
|
||||
return *mapped.v
|
||||
}
|
||||
return &valueProperty{
|
||||
value: *mapped.v,
|
||||
writable: mapped.writable,
|
||||
configurable: mapped.configurable,
|
||||
enumerable: mapped.enumerable,
|
||||
}
|
||||
}
|
||||
|
||||
return a.baseObject.getOwnPropStr(name)
|
||||
}
|
||||
|
||||
func (a *argumentsObject) init() {
|
||||
a.baseObject.init()
|
||||
a._putProp("length", intToValue(int64(a.length)), true, false, true)
|
||||
}
|
||||
|
||||
func (a *argumentsObject) setOwnStr(name unistring.String, val Value, throw bool) bool {
|
||||
if prop, ok := a.values[name].(*mappedProperty); ok {
|
||||
if !prop.writable {
|
||||
a.val.runtime.typeErrorResult(throw, "Property is not writable: %s", name)
|
||||
return false
|
||||
}
|
||||
*prop.v = val
|
||||
return true
|
||||
}
|
||||
return a.baseObject.setOwnStr(name, val, throw)
|
||||
}
|
||||
|
||||
func (a *argumentsObject) setForeignStr(name unistring.String, val, receiver Value, throw bool) (bool, bool) {
|
||||
return a._setForeignStr(name, a.getOwnPropStr(name), val, receiver, throw)
|
||||
}
|
||||
|
||||
func (a *argumentsObject) deleteStr(name unistring.String, throw bool) bool {
|
||||
if prop, ok := a.values[name].(*mappedProperty); ok {
|
||||
if !a.checkDeleteProp(name, &prop.valueProperty, throw) {
|
||||
return false
|
||||
}
|
||||
a._delete(name)
|
||||
return true
|
||||
}
|
||||
|
||||
return a.baseObject.deleteStr(name, throw)
|
||||
}
|
||||
|
||||
type argumentsPropIter struct {
|
||||
wrapped iterNextFunc
|
||||
}
|
||||
|
||||
func (i *argumentsPropIter) next() (propIterItem, iterNextFunc) {
|
||||
var item propIterItem
|
||||
item, i.wrapped = i.wrapped()
|
||||
if i.wrapped == nil {
|
||||
return propIterItem{}, nil
|
||||
}
|
||||
if prop, ok := item.value.(*mappedProperty); ok {
|
||||
item.value = *prop.v
|
||||
}
|
||||
return item, i.next
|
||||
}
|
||||
|
||||
func (a *argumentsObject) iterateStringKeys() iterNextFunc {
|
||||
return (&argumentsPropIter{
|
||||
wrapped: a.baseObject.iterateStringKeys(),
|
||||
}).next
|
||||
}
|
||||
|
||||
func (a *argumentsObject) defineOwnPropertyStr(name unistring.String, descr PropertyDescriptor, throw bool) bool {
|
||||
if mapped, ok := a.values[name].(*mappedProperty); ok {
|
||||
existing := &valueProperty{
|
||||
configurable: mapped.configurable,
|
||||
writable: true,
|
||||
enumerable: mapped.enumerable,
|
||||
value: *mapped.v,
|
||||
}
|
||||
|
||||
val, ok := a.baseObject._defineOwnProperty(name, existing, descr, throw)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
if prop, ok := val.(*valueProperty); ok {
|
||||
if !prop.accessor {
|
||||
*mapped.v = prop.value
|
||||
}
|
||||
if prop.accessor || !prop.writable {
|
||||
a._put(name, prop)
|
||||
return true
|
||||
}
|
||||
mapped.configurable = prop.configurable
|
||||
mapped.enumerable = prop.enumerable
|
||||
} else {
|
||||
*mapped.v = val
|
||||
mapped.configurable = true
|
||||
mapped.enumerable = true
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
return a.baseObject.defineOwnPropertyStr(name, descr, throw)
|
||||
}
|
||||
|
||||
func (a *argumentsObject) export(ctx *objectExportCtx) interface{} {
|
||||
if v, exists := ctx.get(a.val); exists {
|
||||
return v
|
||||
}
|
||||
arr := make([]interface{}, a.length)
|
||||
ctx.put(a.val, arr)
|
||||
for i := range arr {
|
||||
v := a.getIdx(valueInt(int64(i)), nil)
|
||||
if v != nil {
|
||||
arr[i] = exportValue(v, ctx)
|
||||
}
|
||||
}
|
||||
return arr
|
||||
}
|
||||
806
server/vendor/github.com/dop251/goja/object_dynamic.go
generated
vendored
Normal file
806
server/vendor/github.com/dop251/goja/object_dynamic.go
generated
vendored
Normal file
@@ -0,0 +1,806 @@
|
||||
package goja
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
||||
"github.com/dop251/goja/unistring"
|
||||
)
|
||||
|
||||
/*
|
||||
DynamicObject is an interface representing a handler for a dynamic Object. Such an object can be created
|
||||
using the Runtime.NewDynamicObject() method.
|
||||
|
||||
Note that Runtime.ToValue() does not have any special treatment for DynamicObject. The only way to create
|
||||
a dynamic object is by using the Runtime.NewDynamicObject() method. This is done deliberately to avoid
|
||||
silent code breaks when this interface changes.
|
||||
*/
|
||||
type DynamicObject interface {
|
||||
// Get a property value for the key. May return nil if the property does not exist.
|
||||
Get(key string) Value
|
||||
// Set a property value for the key. Return true if success, false otherwise.
|
||||
Set(key string, val Value) bool
|
||||
// Has should return true if and only if the property exists.
|
||||
Has(key string) bool
|
||||
// Delete the property for the key. Returns true on success (note, that includes missing property).
|
||||
Delete(key string) bool
|
||||
// Keys returns a list of all existing property keys. There are no checks for duplicates or to make sure
|
||||
// that the order conforms to https://262.ecma-international.org/#sec-ordinaryownpropertykeys
|
||||
Keys() []string
|
||||
}
|
||||
|
||||
/*
|
||||
DynamicArray is an interface representing a handler for a dynamic array Object. Such an object can be created
|
||||
using the Runtime.NewDynamicArray() method.
|
||||
|
||||
Any integer property key or a string property key that can be parsed into an int value (including negative
|
||||
ones) is treated as an index and passed to the trap methods of the DynamicArray. Note this is different from
|
||||
the regular ECMAScript arrays which only support positive indexes up to 2^32-1.
|
||||
|
||||
DynamicArray cannot be sparse, i.e. hasOwnProperty(num) will return true for num >= 0 && num < Len(). Deleting
|
||||
such a property is equivalent to setting it to undefined. Note that this creates a slight peculiarity because
|
||||
hasOwnProperty() will still return true, even after deletion.
|
||||
|
||||
Note that Runtime.ToValue() does not have any special treatment for DynamicArray. The only way to create
|
||||
a dynamic array is by using the Runtime.NewDynamicArray() method. This is done deliberately to avoid
|
||||
silent code breaks when this interface changes.
|
||||
*/
|
||||
type DynamicArray interface {
|
||||
// Len returns the current array length.
|
||||
Len() int
|
||||
// Get an item at index idx. Note that idx may be any integer, negative or beyond the current length.
|
||||
Get(idx int) Value
|
||||
// Set an item at index idx. Note that idx may be any integer, negative or beyond the current length.
|
||||
// The expected behaviour when it's beyond length is that the array's length is increased to accommodate
|
||||
// the item. All elements in the 'new' section of the array should be zeroed.
|
||||
Set(idx int, val Value) bool
|
||||
// SetLen is called when the array's 'length' property is changed. If the length is increased all elements in the
|
||||
// 'new' section of the array should be zeroed.
|
||||
SetLen(int) bool
|
||||
}
|
||||
|
||||
type baseDynamicObject struct {
|
||||
val *Object
|
||||
prototype *Object
|
||||
}
|
||||
|
||||
type dynamicObject struct {
|
||||
baseDynamicObject
|
||||
d DynamicObject
|
||||
}
|
||||
|
||||
type dynamicArray struct {
|
||||
baseDynamicObject
|
||||
a DynamicArray
|
||||
}
|
||||
|
||||
/*
|
||||
NewDynamicObject creates an Object backed by the provided DynamicObject handler.
|
||||
|
||||
All properties of this Object are Writable, Enumerable and Configurable data properties. Any attempt to define
|
||||
a property that does not conform to this will fail.
|
||||
|
||||
The Object is always extensible and cannot be made non-extensible. Object.preventExtensions() will fail.
|
||||
|
||||
The Object's prototype is initially set to Object.prototype, but can be changed using regular mechanisms
|
||||
(Object.SetPrototype() in Go or Object.setPrototypeOf() in JS).
|
||||
|
||||
The Object cannot have own Symbol properties, however its prototype can. If you need an iterator support for
|
||||
example, you could create a regular object, set Symbol.iterator on that object and then use it as a
|
||||
prototype. See TestDynamicObjectCustomProto for more details.
|
||||
|
||||
Export() returns the original DynamicObject.
|
||||
|
||||
This mechanism is similar to ECMAScript Proxy, however because all properties are enumerable and the object
|
||||
is always extensible there is no need for invariant checks which removes the need to have a target object and
|
||||
makes it a lot more efficient.
|
||||
*/
|
||||
func (r *Runtime) NewDynamicObject(d DynamicObject) *Object {
|
||||
v := &Object{runtime: r}
|
||||
o := &dynamicObject{
|
||||
d: d,
|
||||
baseDynamicObject: baseDynamicObject{
|
||||
val: v,
|
||||
prototype: r.global.ObjectPrototype,
|
||||
},
|
||||
}
|
||||
v.self = o
|
||||
return v
|
||||
}
|
||||
|
||||
/*
|
||||
NewSharedDynamicObject is similar to Runtime.NewDynamicObject but the resulting Object can be shared across multiple
|
||||
Runtimes. The Object's prototype will be null. The provided DynamicObject must be goroutine-safe.
|
||||
*/
|
||||
func NewSharedDynamicObject(d DynamicObject) *Object {
|
||||
v := &Object{}
|
||||
o := &dynamicObject{
|
||||
d: d,
|
||||
baseDynamicObject: baseDynamicObject{
|
||||
val: v,
|
||||
},
|
||||
}
|
||||
v.self = o
|
||||
return v
|
||||
}
|
||||
|
||||
/*
|
||||
NewDynamicArray creates an array Object backed by the provided DynamicArray handler.
|
||||
It is similar to NewDynamicObject, the differences are:
|
||||
|
||||
- the Object is an array (i.e. Array.isArray() will return true and it will have the length property).
|
||||
|
||||
- the prototype will be initially set to Array.prototype.
|
||||
|
||||
- the Object cannot have any own string properties except for the 'length'.
|
||||
*/
|
||||
func (r *Runtime) NewDynamicArray(a DynamicArray) *Object {
|
||||
v := &Object{runtime: r}
|
||||
o := &dynamicArray{
|
||||
a: a,
|
||||
baseDynamicObject: baseDynamicObject{
|
||||
val: v,
|
||||
prototype: r.global.ArrayPrototype,
|
||||
},
|
||||
}
|
||||
v.self = o
|
||||
return v
|
||||
}
|
||||
|
||||
/*
|
||||
NewSharedDynamicArray is similar to Runtime.NewDynamicArray but the resulting Object can be shared across multiple
|
||||
Runtimes. The Object's prototype will be null. If you need to run Array's methods on it, use Array.prototype.[...].call(a, ...).
|
||||
The provided DynamicArray must be goroutine-safe.
|
||||
*/
|
||||
func NewSharedDynamicArray(a DynamicArray) *Object {
|
||||
v := &Object{}
|
||||
o := &dynamicArray{
|
||||
a: a,
|
||||
baseDynamicObject: baseDynamicObject{
|
||||
val: v,
|
||||
},
|
||||
}
|
||||
v.self = o
|
||||
return v
|
||||
}
|
||||
|
||||
func (*dynamicObject) sortLen() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (*dynamicObject) sortGet(i int) Value {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*dynamicObject) swap(i int, i2 int) {
|
||||
}
|
||||
|
||||
func (*dynamicObject) className() string {
|
||||
return classObject
|
||||
}
|
||||
|
||||
func (o *baseDynamicObject) getParentStr(p unistring.String, receiver Value) Value {
|
||||
if proto := o.prototype; proto != nil {
|
||||
if receiver == nil {
|
||||
return proto.self.getStr(p, o.val)
|
||||
}
|
||||
return proto.self.getStr(p, receiver)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *dynamicObject) getStr(p unistring.String, receiver Value) Value {
|
||||
prop := o.d.Get(p.String())
|
||||
if prop == nil {
|
||||
return o.getParentStr(p, receiver)
|
||||
}
|
||||
return prop
|
||||
}
|
||||
|
||||
func (o *baseDynamicObject) getParentIdx(p valueInt, receiver Value) Value {
|
||||
if proto := o.prototype; proto != nil {
|
||||
if receiver == nil {
|
||||
return proto.self.getIdx(p, o.val)
|
||||
}
|
||||
return proto.self.getIdx(p, receiver)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *dynamicObject) getIdx(p valueInt, receiver Value) Value {
|
||||
prop := o.d.Get(p.String())
|
||||
if prop == nil {
|
||||
return o.getParentIdx(p, receiver)
|
||||
}
|
||||
return prop
|
||||
}
|
||||
|
||||
func (o *baseDynamicObject) getSym(p *Symbol, receiver Value) Value {
|
||||
if proto := o.prototype; proto != nil {
|
||||
if receiver == nil {
|
||||
return proto.self.getSym(p, o.val)
|
||||
}
|
||||
return proto.self.getSym(p, receiver)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *dynamicObject) getOwnPropStr(u unistring.String) Value {
|
||||
return o.d.Get(u.String())
|
||||
}
|
||||
|
||||
func (o *dynamicObject) getOwnPropIdx(v valueInt) Value {
|
||||
return o.d.Get(v.String())
|
||||
}
|
||||
|
||||
func (*baseDynamicObject) getOwnPropSym(*Symbol) Value {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *dynamicObject) _set(prop string, v Value, throw bool) bool {
|
||||
if o.d.Set(prop, v) {
|
||||
return true
|
||||
}
|
||||
typeErrorResult(throw, "'Set' on a dynamic object returned false")
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *baseDynamicObject) _setSym(throw bool) {
|
||||
typeErrorResult(throw, "Dynamic objects do not support Symbol properties")
|
||||
}
|
||||
|
||||
func (o *dynamicObject) setOwnStr(p unistring.String, v Value, throw bool) bool {
|
||||
prop := p.String()
|
||||
if !o.d.Has(prop) {
|
||||
if proto := o.prototype; proto != nil {
|
||||
// we know it's foreign because prototype loops are not allowed
|
||||
if res, handled := proto.self.setForeignStr(p, v, o.val, throw); handled {
|
||||
return res
|
||||
}
|
||||
}
|
||||
}
|
||||
return o._set(prop, v, throw)
|
||||
}
|
||||
|
||||
func (o *dynamicObject) setOwnIdx(p valueInt, v Value, throw bool) bool {
|
||||
prop := p.String()
|
||||
if !o.d.Has(prop) {
|
||||
if proto := o.prototype; proto != nil {
|
||||
// we know it's foreign because prototype loops are not allowed
|
||||
if res, handled := proto.self.setForeignIdx(p, v, o.val, throw); handled {
|
||||
return res
|
||||
}
|
||||
}
|
||||
}
|
||||
return o._set(prop, v, throw)
|
||||
}
|
||||
|
||||
func (o *baseDynamicObject) setOwnSym(s *Symbol, v Value, throw bool) bool {
|
||||
if proto := o.prototype; proto != nil {
|
||||
// we know it's foreign because prototype loops are not allowed
|
||||
if res, handled := proto.self.setForeignSym(s, v, o.val, throw); handled {
|
||||
return res
|
||||
}
|
||||
}
|
||||
o._setSym(throw)
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *baseDynamicObject) setParentForeignStr(p unistring.String, v, receiver Value, throw bool) (res bool, handled bool) {
|
||||
if proto := o.prototype; proto != nil {
|
||||
if receiver != proto {
|
||||
return proto.self.setForeignStr(p, v, receiver, throw)
|
||||
}
|
||||
return proto.self.setOwnStr(p, v, throw), true
|
||||
}
|
||||
return false, false
|
||||
}
|
||||
|
||||
func (o *dynamicObject) setForeignStr(p unistring.String, v, receiver Value, throw bool) (res bool, handled bool) {
|
||||
prop := p.String()
|
||||
if !o.d.Has(prop) {
|
||||
return o.setParentForeignStr(p, v, receiver, throw)
|
||||
}
|
||||
return false, false
|
||||
}
|
||||
|
||||
func (o *baseDynamicObject) setParentForeignIdx(p valueInt, v, receiver Value, throw bool) (res bool, handled bool) {
|
||||
if proto := o.prototype; proto != nil {
|
||||
if receiver != proto {
|
||||
return proto.self.setForeignIdx(p, v, receiver, throw)
|
||||
}
|
||||
return proto.self.setOwnIdx(p, v, throw), true
|
||||
}
|
||||
return false, false
|
||||
}
|
||||
|
||||
func (o *dynamicObject) setForeignIdx(p valueInt, v, receiver Value, throw bool) (res bool, handled bool) {
|
||||
prop := p.String()
|
||||
if !o.d.Has(prop) {
|
||||
return o.setParentForeignIdx(p, v, receiver, throw)
|
||||
}
|
||||
return false, false
|
||||
}
|
||||
|
||||
func (o *baseDynamicObject) setForeignSym(p *Symbol, v, receiver Value, throw bool) (res bool, handled bool) {
|
||||
if proto := o.prototype; proto != nil {
|
||||
if receiver != proto {
|
||||
return proto.self.setForeignSym(p, v, receiver, throw)
|
||||
}
|
||||
return proto.self.setOwnSym(p, v, throw), true
|
||||
}
|
||||
return false, false
|
||||
}
|
||||
|
||||
func (o *dynamicObject) hasPropertyStr(u unistring.String) bool {
|
||||
if o.hasOwnPropertyStr(u) {
|
||||
return true
|
||||
}
|
||||
if proto := o.prototype; proto != nil {
|
||||
return proto.self.hasPropertyStr(u)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *dynamicObject) hasPropertyIdx(idx valueInt) bool {
|
||||
if o.hasOwnPropertyIdx(idx) {
|
||||
return true
|
||||
}
|
||||
if proto := o.prototype; proto != nil {
|
||||
return proto.self.hasPropertyIdx(idx)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *baseDynamicObject) hasPropertySym(s *Symbol) bool {
|
||||
if proto := o.prototype; proto != nil {
|
||||
return proto.self.hasPropertySym(s)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *dynamicObject) hasOwnPropertyStr(u unistring.String) bool {
|
||||
return o.d.Has(u.String())
|
||||
}
|
||||
|
||||
func (o *dynamicObject) hasOwnPropertyIdx(v valueInt) bool {
|
||||
return o.d.Has(v.String())
|
||||
}
|
||||
|
||||
func (*baseDynamicObject) hasOwnPropertySym(_ *Symbol) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *baseDynamicObject) checkDynamicObjectPropertyDescr(name fmt.Stringer, descr PropertyDescriptor, throw bool) bool {
|
||||
if descr.Getter != nil || descr.Setter != nil {
|
||||
typeErrorResult(throw, "Dynamic objects do not support accessor properties")
|
||||
return false
|
||||
}
|
||||
if descr.Writable == FLAG_FALSE {
|
||||
typeErrorResult(throw, "Dynamic object field %q cannot be made read-only", name.String())
|
||||
return false
|
||||
}
|
||||
if descr.Enumerable == FLAG_FALSE {
|
||||
typeErrorResult(throw, "Dynamic object field %q cannot be made non-enumerable", name.String())
|
||||
return false
|
||||
}
|
||||
if descr.Configurable == FLAG_FALSE {
|
||||
typeErrorResult(throw, "Dynamic object field %q cannot be made non-configurable", name.String())
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (o *dynamicObject) defineOwnPropertyStr(name unistring.String, desc PropertyDescriptor, throw bool) bool {
|
||||
if o.checkDynamicObjectPropertyDescr(name, desc, throw) {
|
||||
return o._set(name.String(), desc.Value, throw)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *dynamicObject) defineOwnPropertyIdx(name valueInt, desc PropertyDescriptor, throw bool) bool {
|
||||
if o.checkDynamicObjectPropertyDescr(name, desc, throw) {
|
||||
return o._set(name.String(), desc.Value, throw)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *baseDynamicObject) defineOwnPropertySym(name *Symbol, desc PropertyDescriptor, throw bool) bool {
|
||||
o._setSym(throw)
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *dynamicObject) _delete(prop string, throw bool) bool {
|
||||
if o.d.Delete(prop) {
|
||||
return true
|
||||
}
|
||||
typeErrorResult(throw, "Could not delete property %q of a dynamic object", prop)
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *dynamicObject) deleteStr(name unistring.String, throw bool) bool {
|
||||
return o._delete(name.String(), throw)
|
||||
}
|
||||
|
||||
func (o *dynamicObject) deleteIdx(idx valueInt, throw bool) bool {
|
||||
return o._delete(idx.String(), throw)
|
||||
}
|
||||
|
||||
func (*baseDynamicObject) deleteSym(_ *Symbol, _ bool) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (o *baseDynamicObject) toPrimitiveNumber() Value {
|
||||
return o.val.genericToPrimitiveNumber()
|
||||
}
|
||||
|
||||
func (o *baseDynamicObject) toPrimitiveString() Value {
|
||||
return o.val.genericToPrimitiveString()
|
||||
}
|
||||
|
||||
func (o *baseDynamicObject) toPrimitive() Value {
|
||||
return o.val.genericToPrimitive()
|
||||
}
|
||||
|
||||
func (o *baseDynamicObject) assertCallable() (call func(FunctionCall) Value, ok bool) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (o *baseDynamicObject) vmCall(vm *vm, n int) {
|
||||
panic(vm.r.NewTypeError("Dynamic object is not callable"))
|
||||
}
|
||||
|
||||
func (*baseDynamicObject) assertConstructor() func(args []Value, newTarget *Object) *Object {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *baseDynamicObject) proto() *Object {
|
||||
return o.prototype
|
||||
}
|
||||
|
||||
func (o *baseDynamicObject) setProto(proto *Object, throw bool) bool {
|
||||
o.prototype = proto
|
||||
return true
|
||||
}
|
||||
|
||||
func (o *baseDynamicObject) hasInstance(v Value) bool {
|
||||
panic(newTypeError("Expecting a function in instanceof check, but got a dynamic object"))
|
||||
}
|
||||
|
||||
func (*baseDynamicObject) isExtensible() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (o *baseDynamicObject) preventExtensions(throw bool) bool {
|
||||
typeErrorResult(throw, "Cannot make a dynamic object non-extensible")
|
||||
return false
|
||||
}
|
||||
|
||||
type dynamicObjectPropIter struct {
|
||||
o *dynamicObject
|
||||
propNames []string
|
||||
idx int
|
||||
}
|
||||
|
||||
func (i *dynamicObjectPropIter) next() (propIterItem, iterNextFunc) {
|
||||
for i.idx < len(i.propNames) {
|
||||
name := i.propNames[i.idx]
|
||||
i.idx++
|
||||
if i.o.d.Has(name) {
|
||||
return propIterItem{name: newStringValue(name), enumerable: _ENUM_TRUE}, i.next
|
||||
}
|
||||
}
|
||||
return propIterItem{}, nil
|
||||
}
|
||||
|
||||
func (o *dynamicObject) iterateStringKeys() iterNextFunc {
|
||||
keys := o.d.Keys()
|
||||
return (&dynamicObjectPropIter{
|
||||
o: o,
|
||||
propNames: keys,
|
||||
}).next
|
||||
}
|
||||
|
||||
func (o *baseDynamicObject) iterateSymbols() iterNextFunc {
|
||||
return func() (propIterItem, iterNextFunc) {
|
||||
return propIterItem{}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (o *dynamicObject) iterateKeys() iterNextFunc {
|
||||
return o.iterateStringKeys()
|
||||
}
|
||||
|
||||
func (o *dynamicObject) export(ctx *objectExportCtx) interface{} {
|
||||
return o.d
|
||||
}
|
||||
|
||||
func (o *dynamicObject) exportType() reflect.Type {
|
||||
return reflect.TypeOf(o.d)
|
||||
}
|
||||
|
||||
func (o *baseDynamicObject) exportToMap(dst reflect.Value, typ reflect.Type, ctx *objectExportCtx) error {
|
||||
return genericExportToMap(o.val, dst, typ, ctx)
|
||||
}
|
||||
|
||||
func (o *baseDynamicObject) exportToArrayOrSlice(dst reflect.Value, typ reflect.Type, ctx *objectExportCtx) error {
|
||||
return genericExportToArrayOrSlice(o.val, dst, typ, ctx)
|
||||
}
|
||||
|
||||
func (o *dynamicObject) equal(impl objectImpl) bool {
|
||||
if other, ok := impl.(*dynamicObject); ok {
|
||||
return o.d == other.d
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *dynamicObject) stringKeys(all bool, accum []Value) []Value {
|
||||
keys := o.d.Keys()
|
||||
if l := len(accum) + len(keys); l > cap(accum) {
|
||||
oldAccum := accum
|
||||
accum = make([]Value, len(accum), l)
|
||||
copy(accum, oldAccum)
|
||||
}
|
||||
for _, key := range keys {
|
||||
accum = append(accum, newStringValue(key))
|
||||
}
|
||||
return accum
|
||||
}
|
||||
|
||||
func (*baseDynamicObject) symbols(all bool, accum []Value) []Value {
|
||||
return accum
|
||||
}
|
||||
|
||||
func (o *dynamicObject) keys(all bool, accum []Value) []Value {
|
||||
return o.stringKeys(all, accum)
|
||||
}
|
||||
|
||||
func (*baseDynamicObject) _putProp(name unistring.String, value Value, writable, enumerable, configurable bool) Value {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*baseDynamicObject) _putSym(s *Symbol, prop Value) {
|
||||
}
|
||||
|
||||
func (o *baseDynamicObject) getPrivateEnv(*privateEnvType, bool) *privateElements {
|
||||
panic(newTypeError("Dynamic objects cannot have private elements"))
|
||||
}
|
||||
|
||||
func (o *baseDynamicObject) typeOf() valueString {
|
||||
return stringObjectC
|
||||
}
|
||||
|
||||
func (a *dynamicArray) sortLen() int {
|
||||
return a.a.Len()
|
||||
}
|
||||
|
||||
func (a *dynamicArray) sortGet(i int) Value {
|
||||
return a.a.Get(i)
|
||||
}
|
||||
|
||||
func (a *dynamicArray) swap(i int, j int) {
|
||||
x := a.sortGet(i)
|
||||
y := a.sortGet(j)
|
||||
a.a.Set(int(i), y)
|
||||
a.a.Set(int(j), x)
|
||||
}
|
||||
|
||||
func (a *dynamicArray) className() string {
|
||||
return classArray
|
||||
}
|
||||
|
||||
func (a *dynamicArray) getStr(p unistring.String, receiver Value) Value {
|
||||
if p == "length" {
|
||||
return intToValue(int64(a.a.Len()))
|
||||
}
|
||||
if idx, ok := strToInt(p); ok {
|
||||
return a.a.Get(idx)
|
||||
}
|
||||
return a.getParentStr(p, receiver)
|
||||
}
|
||||
|
||||
func (a *dynamicArray) getIdx(p valueInt, receiver Value) Value {
|
||||
if val := a.getOwnPropIdx(p); val != nil {
|
||||
return val
|
||||
}
|
||||
return a.getParentIdx(p, receiver)
|
||||
}
|
||||
|
||||
func (a *dynamicArray) getOwnPropStr(u unistring.String) Value {
|
||||
if u == "length" {
|
||||
return &valueProperty{
|
||||
value: intToValue(int64(a.a.Len())),
|
||||
writable: true,
|
||||
}
|
||||
}
|
||||
if idx, ok := strToInt(u); ok {
|
||||
return a.a.Get(idx)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *dynamicArray) getOwnPropIdx(v valueInt) Value {
|
||||
return a.a.Get(toIntStrict(int64(v)))
|
||||
}
|
||||
|
||||
func (a *dynamicArray) _setLen(v Value, throw bool) bool {
|
||||
if a.a.SetLen(toIntStrict(v.ToInteger())) {
|
||||
return true
|
||||
}
|
||||
typeErrorResult(throw, "'SetLen' on a dynamic array returned false")
|
||||
return false
|
||||
}
|
||||
|
||||
func (a *dynamicArray) setOwnStr(p unistring.String, v Value, throw bool) bool {
|
||||
if p == "length" {
|
||||
return a._setLen(v, throw)
|
||||
}
|
||||
if idx, ok := strToInt(p); ok {
|
||||
return a._setIdx(idx, v, throw)
|
||||
}
|
||||
typeErrorResult(throw, "Cannot set property %q on a dynamic array", p.String())
|
||||
return false
|
||||
}
|
||||
|
||||
func (a *dynamicArray) _setIdx(idx int, v Value, throw bool) bool {
|
||||
if a.a.Set(idx, v) {
|
||||
return true
|
||||
}
|
||||
typeErrorResult(throw, "'Set' on a dynamic array returned false")
|
||||
return false
|
||||
}
|
||||
|
||||
func (a *dynamicArray) setOwnIdx(p valueInt, v Value, throw bool) bool {
|
||||
return a._setIdx(toIntStrict(int64(p)), v, throw)
|
||||
}
|
||||
|
||||
func (a *dynamicArray) setForeignStr(p unistring.String, v, receiver Value, throw bool) (res bool, handled bool) {
|
||||
return a.setParentForeignStr(p, v, receiver, throw)
|
||||
}
|
||||
|
||||
func (a *dynamicArray) setForeignIdx(p valueInt, v, receiver Value, throw bool) (res bool, handled bool) {
|
||||
return a.setParentForeignIdx(p, v, receiver, throw)
|
||||
}
|
||||
|
||||
func (a *dynamicArray) hasPropertyStr(u unistring.String) bool {
|
||||
if a.hasOwnPropertyStr(u) {
|
||||
return true
|
||||
}
|
||||
if proto := a.prototype; proto != nil {
|
||||
return proto.self.hasPropertyStr(u)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (a *dynamicArray) hasPropertyIdx(idx valueInt) bool {
|
||||
if a.hasOwnPropertyIdx(idx) {
|
||||
return true
|
||||
}
|
||||
if proto := a.prototype; proto != nil {
|
||||
return proto.self.hasPropertyIdx(idx)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (a *dynamicArray) _has(idx int) bool {
|
||||
return idx >= 0 && idx < a.a.Len()
|
||||
}
|
||||
|
||||
func (a *dynamicArray) hasOwnPropertyStr(u unistring.String) bool {
|
||||
if u == "length" {
|
||||
return true
|
||||
}
|
||||
if idx, ok := strToInt(u); ok {
|
||||
return a._has(idx)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (a *dynamicArray) hasOwnPropertyIdx(v valueInt) bool {
|
||||
return a._has(toIntStrict(int64(v)))
|
||||
}
|
||||
|
||||
func (a *dynamicArray) defineOwnPropertyStr(name unistring.String, desc PropertyDescriptor, throw bool) bool {
|
||||
if a.checkDynamicObjectPropertyDescr(name, desc, throw) {
|
||||
if idx, ok := strToInt(name); ok {
|
||||
return a._setIdx(idx, desc.Value, throw)
|
||||
}
|
||||
typeErrorResult(throw, "Cannot define property %q on a dynamic array", name.String())
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (a *dynamicArray) defineOwnPropertyIdx(name valueInt, desc PropertyDescriptor, throw bool) bool {
|
||||
if a.checkDynamicObjectPropertyDescr(name, desc, throw) {
|
||||
return a._setIdx(toIntStrict(int64(name)), desc.Value, throw)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (a *dynamicArray) _delete(idx int, throw bool) bool {
|
||||
if a._has(idx) {
|
||||
a._setIdx(idx, _undefined, throw)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (a *dynamicArray) deleteStr(name unistring.String, throw bool) bool {
|
||||
if idx, ok := strToInt(name); ok {
|
||||
return a._delete(idx, throw)
|
||||
}
|
||||
if a.hasOwnPropertyStr(name) {
|
||||
typeErrorResult(throw, "Cannot delete property %q on a dynamic array", name.String())
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (a *dynamicArray) deleteIdx(idx valueInt, throw bool) bool {
|
||||
return a._delete(toIntStrict(int64(idx)), throw)
|
||||
}
|
||||
|
||||
type dynArrayPropIter struct {
|
||||
a DynamicArray
|
||||
idx, limit int
|
||||
}
|
||||
|
||||
func (i *dynArrayPropIter) next() (propIterItem, iterNextFunc) {
|
||||
if i.idx < i.limit && i.idx < i.a.Len() {
|
||||
name := strconv.Itoa(i.idx)
|
||||
i.idx++
|
||||
return propIterItem{name: asciiString(name), enumerable: _ENUM_TRUE}, i.next
|
||||
}
|
||||
|
||||
return propIterItem{}, nil
|
||||
}
|
||||
|
||||
func (a *dynamicArray) iterateStringKeys() iterNextFunc {
|
||||
return (&dynArrayPropIter{
|
||||
a: a.a,
|
||||
limit: a.a.Len(),
|
||||
}).next
|
||||
}
|
||||
|
||||
func (a *dynamicArray) iterateKeys() iterNextFunc {
|
||||
return a.iterateStringKeys()
|
||||
}
|
||||
|
||||
func (a *dynamicArray) export(ctx *objectExportCtx) interface{} {
|
||||
return a.a
|
||||
}
|
||||
|
||||
func (a *dynamicArray) exportType() reflect.Type {
|
||||
return reflect.TypeOf(a.a)
|
||||
}
|
||||
|
||||
func (a *dynamicArray) equal(impl objectImpl) bool {
|
||||
if other, ok := impl.(*dynamicArray); ok {
|
||||
return a == other
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (a *dynamicArray) stringKeys(all bool, accum []Value) []Value {
|
||||
al := a.a.Len()
|
||||
l := len(accum) + al
|
||||
if all {
|
||||
l++
|
||||
}
|
||||
if l > cap(accum) {
|
||||
oldAccum := accum
|
||||
accum = make([]Value, len(oldAccum), l)
|
||||
copy(accum, oldAccum)
|
||||
}
|
||||
for i := 0; i < al; i++ {
|
||||
accum = append(accum, asciiString(strconv.Itoa(i)))
|
||||
}
|
||||
if all {
|
||||
accum = append(accum, asciiString("length"))
|
||||
}
|
||||
return accum
|
||||
}
|
||||
|
||||
func (a *dynamicArray) keys(all bool, accum []Value) []Value {
|
||||
return a.stringKeys(all, accum)
|
||||
}
|
||||
356
server/vendor/github.com/dop251/goja/object_goarray_reflect.go
generated
vendored
Normal file
356
server/vendor/github.com/dop251/goja/object_goarray_reflect.go
generated
vendored
Normal file
@@ -0,0 +1,356 @@
|
||||
package goja
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
||||
"github.com/dop251/goja/unistring"
|
||||
)
|
||||
|
||||
type objectGoArrayReflect struct {
|
||||
objectGoReflect
|
||||
lengthProp valueProperty
|
||||
|
||||
valueCache valueArrayCache
|
||||
|
||||
putIdx func(idx int, v Value, throw bool) bool
|
||||
}
|
||||
|
||||
type valueArrayCache []reflectValueWrapper
|
||||
|
||||
func (c *valueArrayCache) get(idx int) reflectValueWrapper {
|
||||
if idx < len(*c) {
|
||||
return (*c)[idx]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *valueArrayCache) grow(newlen int) {
|
||||
oldcap := cap(*c)
|
||||
if oldcap < newlen {
|
||||
a := make([]reflectValueWrapper, newlen, growCap(newlen, len(*c), oldcap))
|
||||
copy(a, *c)
|
||||
*c = a
|
||||
} else {
|
||||
*c = (*c)[:newlen]
|
||||
}
|
||||
}
|
||||
|
||||
func (c *valueArrayCache) put(idx int, w reflectValueWrapper) {
|
||||
if len(*c) <= idx {
|
||||
c.grow(idx + 1)
|
||||
}
|
||||
(*c)[idx] = w
|
||||
}
|
||||
|
||||
func (c *valueArrayCache) shrink(newlen int) {
|
||||
if len(*c) > newlen {
|
||||
tail := (*c)[newlen:]
|
||||
for i, item := range tail {
|
||||
if item != nil {
|
||||
copyReflectValueWrapper(item)
|
||||
tail[i] = nil
|
||||
}
|
||||
}
|
||||
*c = (*c)[:newlen]
|
||||
}
|
||||
}
|
||||
|
||||
func (o *objectGoArrayReflect) _init() {
|
||||
o.objectGoReflect.init()
|
||||
o.class = classArray
|
||||
o.prototype = o.val.runtime.global.ArrayPrototype
|
||||
o.updateLen()
|
||||
o.baseObject._put("length", &o.lengthProp)
|
||||
}
|
||||
|
||||
func (o *objectGoArrayReflect) init() {
|
||||
o._init()
|
||||
o.putIdx = o._putIdx
|
||||
}
|
||||
|
||||
func (o *objectGoArrayReflect) updateLen() {
|
||||
o.lengthProp.value = intToValue(int64(o.fieldsValue.Len()))
|
||||
}
|
||||
|
||||
func (o *objectGoArrayReflect) _hasIdx(idx valueInt) bool {
|
||||
if idx := int64(idx); idx >= 0 && idx < int64(o.fieldsValue.Len()) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *objectGoArrayReflect) _hasStr(name unistring.String) bool {
|
||||
if idx := strToIdx64(name); idx >= 0 && idx < int64(o.fieldsValue.Len()) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *objectGoArrayReflect) _getIdx(idx int) Value {
|
||||
if v := o.valueCache.get(idx); v != nil {
|
||||
return v.esValue()
|
||||
}
|
||||
|
||||
v := o.fieldsValue.Index(idx)
|
||||
|
||||
res, w := o.elemToValue(v)
|
||||
if w != nil {
|
||||
o.valueCache.put(idx, w)
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
func (o *objectGoArrayReflect) getIdx(idx valueInt, receiver Value) Value {
|
||||
if idx := toIntStrict(int64(idx)); idx >= 0 && idx < o.fieldsValue.Len() {
|
||||
return o._getIdx(idx)
|
||||
}
|
||||
return o.objectGoReflect.getStr(idx.string(), receiver)
|
||||
}
|
||||
|
||||
func (o *objectGoArrayReflect) getStr(name unistring.String, receiver Value) Value {
|
||||
var ownProp Value
|
||||
if idx := strToGoIdx(name); idx >= 0 && idx < o.fieldsValue.Len() {
|
||||
ownProp = o._getIdx(idx)
|
||||
} else if name == "length" {
|
||||
ownProp = &o.lengthProp
|
||||
} else {
|
||||
ownProp = o.objectGoReflect.getOwnPropStr(name)
|
||||
}
|
||||
return o.getStrWithOwnProp(ownProp, name, receiver)
|
||||
}
|
||||
|
||||
func (o *objectGoArrayReflect) getOwnPropStr(name unistring.String) Value {
|
||||
if idx := strToGoIdx(name); idx >= 0 {
|
||||
if idx < o.fieldsValue.Len() {
|
||||
return &valueProperty{
|
||||
value: o._getIdx(idx),
|
||||
writable: true,
|
||||
enumerable: true,
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if name == "length" {
|
||||
return &o.lengthProp
|
||||
}
|
||||
return o.objectGoReflect.getOwnPropStr(name)
|
||||
}
|
||||
|
||||
func (o *objectGoArrayReflect) getOwnPropIdx(idx valueInt) Value {
|
||||
if idx := toIntStrict(int64(idx)); idx >= 0 && idx < o.fieldsValue.Len() {
|
||||
return &valueProperty{
|
||||
value: o._getIdx(idx),
|
||||
writable: true,
|
||||
enumerable: true,
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *objectGoArrayReflect) _putIdx(idx int, v Value, throw bool) bool {
|
||||
cached := o.valueCache.get(idx)
|
||||
if cached != nil {
|
||||
copyReflectValueWrapper(cached)
|
||||
}
|
||||
|
||||
rv := o.fieldsValue.Index(idx)
|
||||
err := o.val.runtime.toReflectValue(v, rv, &objectExportCtx{})
|
||||
if err != nil {
|
||||
if cached != nil {
|
||||
cached.setReflectValue(rv)
|
||||
}
|
||||
o.val.runtime.typeErrorResult(throw, "Go type conversion error: %v", err)
|
||||
return false
|
||||
}
|
||||
if cached != nil {
|
||||
o.valueCache[idx] = nil
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (o *objectGoArrayReflect) setOwnIdx(idx valueInt, val Value, throw bool) bool {
|
||||
if i := toIntStrict(int64(idx)); i >= 0 {
|
||||
if i >= o.fieldsValue.Len() {
|
||||
if res, ok := o._setForeignIdx(idx, nil, val, o.val, throw); ok {
|
||||
return res
|
||||
}
|
||||
}
|
||||
return o.putIdx(i, val, throw)
|
||||
} else {
|
||||
name := idx.string()
|
||||
if res, ok := o._setForeignStr(name, nil, val, o.val, throw); !ok {
|
||||
o.val.runtime.typeErrorResult(throw, "Can't set property '%s' on Go slice", name)
|
||||
return false
|
||||
} else {
|
||||
return res
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (o *objectGoArrayReflect) setOwnStr(name unistring.String, val Value, throw bool) bool {
|
||||
if idx := strToGoIdx(name); idx >= 0 {
|
||||
if idx >= o.fieldsValue.Len() {
|
||||
if res, ok := o._setForeignStr(name, nil, val, o.val, throw); ok {
|
||||
return res
|
||||
}
|
||||
}
|
||||
return o.putIdx(idx, val, throw)
|
||||
} else {
|
||||
if res, ok := o._setForeignStr(name, nil, val, o.val, throw); !ok {
|
||||
o.val.runtime.typeErrorResult(throw, "Can't set property '%s' on Go slice", name)
|
||||
return false
|
||||
} else {
|
||||
return res
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (o *objectGoArrayReflect) setForeignIdx(idx valueInt, val, receiver Value, throw bool) (bool, bool) {
|
||||
return o._setForeignIdx(idx, trueValIfPresent(o._hasIdx(idx)), val, receiver, throw)
|
||||
}
|
||||
|
||||
func (o *objectGoArrayReflect) setForeignStr(name unistring.String, val, receiver Value, throw bool) (bool, bool) {
|
||||
return o._setForeignStr(name, trueValIfPresent(o.hasOwnPropertyStr(name)), val, receiver, throw)
|
||||
}
|
||||
|
||||
func (o *objectGoArrayReflect) hasOwnPropertyIdx(idx valueInt) bool {
|
||||
return o._hasIdx(idx)
|
||||
}
|
||||
|
||||
func (o *objectGoArrayReflect) hasOwnPropertyStr(name unistring.String) bool {
|
||||
if o._hasStr(name) || name == "length" {
|
||||
return true
|
||||
}
|
||||
return o.objectGoReflect._has(name.String())
|
||||
}
|
||||
|
||||
func (o *objectGoArrayReflect) defineOwnPropertyIdx(idx valueInt, descr PropertyDescriptor, throw bool) bool {
|
||||
if i := toIntStrict(int64(idx)); i >= 0 {
|
||||
if !o.val.runtime.checkHostObjectPropertyDescr(idx.string(), descr, throw) {
|
||||
return false
|
||||
}
|
||||
val := descr.Value
|
||||
if val == nil {
|
||||
val = _undefined
|
||||
}
|
||||
return o.putIdx(i, val, throw)
|
||||
}
|
||||
o.val.runtime.typeErrorResult(throw, "Cannot define property '%d' on a Go slice", idx)
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *objectGoArrayReflect) defineOwnPropertyStr(name unistring.String, descr PropertyDescriptor, throw bool) bool {
|
||||
if idx := strToGoIdx(name); idx >= 0 {
|
||||
if !o.val.runtime.checkHostObjectPropertyDescr(name, descr, throw) {
|
||||
return false
|
||||
}
|
||||
val := descr.Value
|
||||
if val == nil {
|
||||
val = _undefined
|
||||
}
|
||||
return o.putIdx(idx, val, throw)
|
||||
}
|
||||
o.val.runtime.typeErrorResult(throw, "Cannot define property '%s' on a Go slice", name)
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *objectGoArrayReflect) toPrimitive() Value {
|
||||
return o.toPrimitiveString()
|
||||
}
|
||||
|
||||
func (o *objectGoArrayReflect) _deleteIdx(idx int) {
|
||||
if idx < o.fieldsValue.Len() {
|
||||
if cv := o.valueCache.get(idx); cv != nil {
|
||||
copyReflectValueWrapper(cv)
|
||||
o.valueCache[idx] = nil
|
||||
}
|
||||
|
||||
o.fieldsValue.Index(idx).Set(reflect.Zero(o.fieldsValue.Type().Elem()))
|
||||
}
|
||||
}
|
||||
|
||||
func (o *objectGoArrayReflect) deleteStr(name unistring.String, throw bool) bool {
|
||||
if idx := strToGoIdx(name); idx >= 0 {
|
||||
o._deleteIdx(idx)
|
||||
return true
|
||||
}
|
||||
|
||||
return o.objectGoReflect.deleteStr(name, throw)
|
||||
}
|
||||
|
||||
func (o *objectGoArrayReflect) deleteIdx(i valueInt, throw bool) bool {
|
||||
idx := toIntStrict(int64(i))
|
||||
if idx >= 0 {
|
||||
o._deleteIdx(idx)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
type goArrayReflectPropIter struct {
|
||||
o *objectGoArrayReflect
|
||||
idx, limit int
|
||||
}
|
||||
|
||||
func (i *goArrayReflectPropIter) next() (propIterItem, iterNextFunc) {
|
||||
if i.idx < i.limit && i.idx < i.o.fieldsValue.Len() {
|
||||
name := strconv.Itoa(i.idx)
|
||||
i.idx++
|
||||
return propIterItem{name: asciiString(name), enumerable: _ENUM_TRUE}, i.next
|
||||
}
|
||||
|
||||
return i.o.objectGoReflect.iterateStringKeys()()
|
||||
}
|
||||
|
||||
func (o *objectGoArrayReflect) stringKeys(all bool, accum []Value) []Value {
|
||||
for i := 0; i < o.fieldsValue.Len(); i++ {
|
||||
accum = append(accum, asciiString(strconv.Itoa(i)))
|
||||
}
|
||||
|
||||
return o.objectGoReflect.stringKeys(all, accum)
|
||||
}
|
||||
|
||||
func (o *objectGoArrayReflect) iterateStringKeys() iterNextFunc {
|
||||
return (&goArrayReflectPropIter{
|
||||
o: o,
|
||||
limit: o.fieldsValue.Len(),
|
||||
}).next
|
||||
}
|
||||
|
||||
func (o *objectGoArrayReflect) sortLen() int {
|
||||
return o.fieldsValue.Len()
|
||||
}
|
||||
|
||||
func (o *objectGoArrayReflect) sortGet(i int) Value {
|
||||
return o.getIdx(valueInt(i), nil)
|
||||
}
|
||||
|
||||
func (o *objectGoArrayReflect) swap(i int, j int) {
|
||||
vi := o.fieldsValue.Index(i)
|
||||
vj := o.fieldsValue.Index(j)
|
||||
tmp := reflect.New(o.fieldsValue.Type().Elem()).Elem()
|
||||
tmp.Set(vi)
|
||||
vi.Set(vj)
|
||||
vj.Set(tmp)
|
||||
|
||||
cachedI := o.valueCache.get(i)
|
||||
cachedJ := o.valueCache.get(j)
|
||||
if cachedI != nil {
|
||||
cachedI.setReflectValue(vj)
|
||||
o.valueCache.put(j, cachedI)
|
||||
} else {
|
||||
if j < len(o.valueCache) {
|
||||
o.valueCache[j] = nil
|
||||
}
|
||||
}
|
||||
|
||||
if cachedJ != nil {
|
||||
cachedJ.setReflectValue(vi)
|
||||
o.valueCache.put(i, cachedJ)
|
||||
} else {
|
||||
if i < len(o.valueCache) {
|
||||
o.valueCache[i] = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
176
server/vendor/github.com/dop251/goja/object_gomap.go
generated
vendored
Normal file
176
server/vendor/github.com/dop251/goja/object_gomap.go
generated
vendored
Normal file
@@ -0,0 +1,176 @@
|
||||
package goja
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/dop251/goja/unistring"
|
||||
)
|
||||
|
||||
type objectGoMapSimple struct {
|
||||
baseObject
|
||||
data map[string]interface{}
|
||||
}
|
||||
|
||||
func (o *objectGoMapSimple) init() {
|
||||
o.baseObject.init()
|
||||
o.prototype = o.val.runtime.global.ObjectPrototype
|
||||
o.class = classObject
|
||||
o.extensible = true
|
||||
}
|
||||
|
||||
func (o *objectGoMapSimple) _getStr(name string) Value {
|
||||
v, exists := o.data[name]
|
||||
if !exists {
|
||||
return nil
|
||||
}
|
||||
return o.val.runtime.ToValue(v)
|
||||
}
|
||||
|
||||
func (o *objectGoMapSimple) getStr(name unistring.String, receiver Value) Value {
|
||||
if v := o._getStr(name.String()); v != nil {
|
||||
return v
|
||||
}
|
||||
return o.baseObject.getStr(name, receiver)
|
||||
}
|
||||
|
||||
func (o *objectGoMapSimple) getOwnPropStr(name unistring.String) Value {
|
||||
if v := o._getStr(name.String()); v != nil {
|
||||
return v
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *objectGoMapSimple) setOwnStr(name unistring.String, val Value, throw bool) bool {
|
||||
n := name.String()
|
||||
if _, exists := o.data[n]; exists {
|
||||
o.data[n] = val.Export()
|
||||
return true
|
||||
}
|
||||
if proto := o.prototype; proto != nil {
|
||||
// we know it's foreign because prototype loops are not allowed
|
||||
if res, ok := proto.self.setForeignStr(name, val, o.val, throw); ok {
|
||||
return res
|
||||
}
|
||||
}
|
||||
// new property
|
||||
if !o.extensible {
|
||||
o.val.runtime.typeErrorResult(throw, "Cannot add property %s, object is not extensible", name)
|
||||
return false
|
||||
} else {
|
||||
o.data[n] = val.Export()
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func trueValIfPresent(present bool) Value {
|
||||
if present {
|
||||
return valueTrue
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *objectGoMapSimple) setForeignStr(name unistring.String, val, receiver Value, throw bool) (bool, bool) {
|
||||
return o._setForeignStr(name, trueValIfPresent(o._hasStr(name.String())), val, receiver, throw)
|
||||
}
|
||||
|
||||
func (o *objectGoMapSimple) _hasStr(name string) bool {
|
||||
_, exists := o.data[name]
|
||||
return exists
|
||||
}
|
||||
|
||||
func (o *objectGoMapSimple) hasOwnPropertyStr(name unistring.String) bool {
|
||||
return o._hasStr(name.String())
|
||||
}
|
||||
|
||||
func (o *objectGoMapSimple) defineOwnPropertyStr(name unistring.String, descr PropertyDescriptor, throw bool) bool {
|
||||
if !o.val.runtime.checkHostObjectPropertyDescr(name, descr, throw) {
|
||||
return false
|
||||
}
|
||||
|
||||
n := name.String()
|
||||
if o.extensible || o._hasStr(n) {
|
||||
o.data[n] = descr.Value.Export()
|
||||
return true
|
||||
}
|
||||
|
||||
o.val.runtime.typeErrorResult(throw, "Cannot define property %s, object is not extensible", n)
|
||||
return false
|
||||
}
|
||||
|
||||
/*
|
||||
func (o *objectGoMapSimple) toPrimitiveNumber() Value {
|
||||
return o.toPrimitiveString()
|
||||
}
|
||||
|
||||
func (o *objectGoMapSimple) toPrimitiveString() Value {
|
||||
return stringObjectObject
|
||||
}
|
||||
|
||||
func (o *objectGoMapSimple) toPrimitive() Value {
|
||||
return o.toPrimitiveString()
|
||||
}
|
||||
|
||||
func (o *objectGoMapSimple) assertCallable() (call func(FunctionCall) Value, ok bool) {
|
||||
return nil, false
|
||||
}
|
||||
*/
|
||||
|
||||
func (o *objectGoMapSimple) deleteStr(name unistring.String, _ bool) bool {
|
||||
delete(o.data, name.String())
|
||||
return true
|
||||
}
|
||||
|
||||
type gomapPropIter struct {
|
||||
o *objectGoMapSimple
|
||||
propNames []string
|
||||
idx int
|
||||
}
|
||||
|
||||
func (i *gomapPropIter) next() (propIterItem, iterNextFunc) {
|
||||
for i.idx < len(i.propNames) {
|
||||
name := i.propNames[i.idx]
|
||||
i.idx++
|
||||
if _, exists := i.o.data[name]; exists {
|
||||
return propIterItem{name: newStringValue(name), enumerable: _ENUM_TRUE}, i.next
|
||||
}
|
||||
}
|
||||
|
||||
return propIterItem{}, nil
|
||||
}
|
||||
|
||||
func (o *objectGoMapSimple) iterateStringKeys() iterNextFunc {
|
||||
propNames := make([]string, len(o.data))
|
||||
i := 0
|
||||
for key := range o.data {
|
||||
propNames[i] = key
|
||||
i++
|
||||
}
|
||||
|
||||
return (&gomapPropIter{
|
||||
o: o,
|
||||
propNames: propNames,
|
||||
}).next
|
||||
}
|
||||
|
||||
func (o *objectGoMapSimple) stringKeys(_ bool, accum []Value) []Value {
|
||||
// all own keys are enumerable
|
||||
for key := range o.data {
|
||||
accum = append(accum, newStringValue(key))
|
||||
}
|
||||
return accum
|
||||
}
|
||||
|
||||
func (o *objectGoMapSimple) export(*objectExportCtx) interface{} {
|
||||
return o.data
|
||||
}
|
||||
|
||||
func (o *objectGoMapSimple) exportType() reflect.Type {
|
||||
return reflectTypeMap
|
||||
}
|
||||
|
||||
func (o *objectGoMapSimple) equal(other objectImpl) bool {
|
||||
if other, ok := other.(*objectGoMapSimple); ok {
|
||||
return o == other
|
||||
}
|
||||
return false
|
||||
}
|
||||
265
server/vendor/github.com/dop251/goja/object_gomap_reflect.go
generated
vendored
Normal file
265
server/vendor/github.com/dop251/goja/object_gomap_reflect.go
generated
vendored
Normal file
@@ -0,0 +1,265 @@
|
||||
package goja
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/dop251/goja/unistring"
|
||||
)
|
||||
|
||||
type objectGoMapReflect struct {
|
||||
objectGoReflect
|
||||
|
||||
keyType, valueType reflect.Type
|
||||
}
|
||||
|
||||
func (o *objectGoMapReflect) init() {
|
||||
o.objectGoReflect.init()
|
||||
o.keyType = o.fieldsValue.Type().Key()
|
||||
o.valueType = o.fieldsValue.Type().Elem()
|
||||
}
|
||||
|
||||
func (o *objectGoMapReflect) toKey(n Value, throw bool) reflect.Value {
|
||||
key := reflect.New(o.keyType).Elem()
|
||||
err := o.val.runtime.toReflectValue(n, key, &objectExportCtx{})
|
||||
if err != nil {
|
||||
o.val.runtime.typeErrorResult(throw, "map key conversion error: %v", err)
|
||||
return reflect.Value{}
|
||||
}
|
||||
return key
|
||||
}
|
||||
|
||||
func (o *objectGoMapReflect) strToKey(name string, throw bool) reflect.Value {
|
||||
if o.keyType.Kind() == reflect.String {
|
||||
return reflect.ValueOf(name).Convert(o.keyType)
|
||||
}
|
||||
return o.toKey(newStringValue(name), throw)
|
||||
}
|
||||
|
||||
func (o *objectGoMapReflect) _getKey(key reflect.Value) Value {
|
||||
if !key.IsValid() {
|
||||
return nil
|
||||
}
|
||||
if v := o.fieldsValue.MapIndex(key); v.IsValid() {
|
||||
rv := v
|
||||
if rv.Kind() == reflect.Interface {
|
||||
rv = rv.Elem()
|
||||
}
|
||||
return o.val.runtime.toValue(v.Interface(), rv)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *objectGoMapReflect) _get(n Value) Value {
|
||||
return o._getKey(o.toKey(n, false))
|
||||
}
|
||||
|
||||
func (o *objectGoMapReflect) _getStr(name string) Value {
|
||||
return o._getKey(o.strToKey(name, false))
|
||||
}
|
||||
|
||||
func (o *objectGoMapReflect) getStr(name unistring.String, receiver Value) Value {
|
||||
if v := o._getStr(name.String()); v != nil {
|
||||
return v
|
||||
}
|
||||
return o.objectGoReflect.getStr(name, receiver)
|
||||
}
|
||||
|
||||
func (o *objectGoMapReflect) getIdx(idx valueInt, receiver Value) Value {
|
||||
if v := o._get(idx); v != nil {
|
||||
return v
|
||||
}
|
||||
return o.objectGoReflect.getIdx(idx, receiver)
|
||||
}
|
||||
|
||||
func (o *objectGoMapReflect) getOwnPropStr(name unistring.String) Value {
|
||||
if v := o._getStr(name.String()); v != nil {
|
||||
return &valueProperty{
|
||||
value: v,
|
||||
writable: true,
|
||||
enumerable: true,
|
||||
}
|
||||
}
|
||||
return o.objectGoReflect.getOwnPropStr(name)
|
||||
}
|
||||
|
||||
func (o *objectGoMapReflect) getOwnPropIdx(idx valueInt) Value {
|
||||
if v := o._get(idx); v != nil {
|
||||
return &valueProperty{
|
||||
value: v,
|
||||
writable: true,
|
||||
enumerable: true,
|
||||
}
|
||||
}
|
||||
return o.objectGoReflect.getOwnPropStr(idx.string())
|
||||
}
|
||||
|
||||
func (o *objectGoMapReflect) toValue(val Value, throw bool) (reflect.Value, bool) {
|
||||
v := reflect.New(o.valueType).Elem()
|
||||
err := o.val.runtime.toReflectValue(val, v, &objectExportCtx{})
|
||||
if err != nil {
|
||||
o.val.runtime.typeErrorResult(throw, "map value conversion error: %v", err)
|
||||
return reflect.Value{}, false
|
||||
}
|
||||
|
||||
return v, true
|
||||
}
|
||||
|
||||
func (o *objectGoMapReflect) _put(key reflect.Value, val Value, throw bool) bool {
|
||||
if key.IsValid() {
|
||||
if o.extensible || o.fieldsValue.MapIndex(key).IsValid() {
|
||||
v, ok := o.toValue(val, throw)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
o.fieldsValue.SetMapIndex(key, v)
|
||||
} else {
|
||||
o.val.runtime.typeErrorResult(throw, "Cannot set property %s, object is not extensible", key.String())
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *objectGoMapReflect) setOwnStr(name unistring.String, val Value, throw bool) bool {
|
||||
n := name.String()
|
||||
key := o.strToKey(n, false)
|
||||
if !key.IsValid() || !o.fieldsValue.MapIndex(key).IsValid() {
|
||||
if proto := o.prototype; proto != nil {
|
||||
// we know it's foreign because prototype loops are not allowed
|
||||
if res, ok := proto.self.setForeignStr(name, val, o.val, throw); ok {
|
||||
return res
|
||||
}
|
||||
}
|
||||
// new property
|
||||
if !o.extensible {
|
||||
o.val.runtime.typeErrorResult(throw, "Cannot add property %s, object is not extensible", n)
|
||||
return false
|
||||
} else {
|
||||
if throw && !key.IsValid() {
|
||||
o.strToKey(n, true)
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
o._put(key, val, throw)
|
||||
return true
|
||||
}
|
||||
|
||||
func (o *objectGoMapReflect) setOwnIdx(idx valueInt, val Value, throw bool) bool {
|
||||
key := o.toKey(idx, false)
|
||||
if !key.IsValid() || !o.fieldsValue.MapIndex(key).IsValid() {
|
||||
if proto := o.prototype; proto != nil {
|
||||
// we know it's foreign because prototype loops are not allowed
|
||||
if res, ok := proto.self.setForeignIdx(idx, val, o.val, throw); ok {
|
||||
return res
|
||||
}
|
||||
}
|
||||
// new property
|
||||
if !o.extensible {
|
||||
o.val.runtime.typeErrorResult(throw, "Cannot add property %d, object is not extensible", idx)
|
||||
return false
|
||||
} else {
|
||||
if throw && !key.IsValid() {
|
||||
o.toKey(idx, true)
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
o._put(key, val, throw)
|
||||
return true
|
||||
}
|
||||
|
||||
func (o *objectGoMapReflect) setForeignStr(name unistring.String, val, receiver Value, throw bool) (bool, bool) {
|
||||
return o._setForeignStr(name, trueValIfPresent(o.hasOwnPropertyStr(name)), val, receiver, throw)
|
||||
}
|
||||
|
||||
func (o *objectGoMapReflect) setForeignIdx(idx valueInt, val, receiver Value, throw bool) (bool, bool) {
|
||||
return o._setForeignIdx(idx, trueValIfPresent(o.hasOwnPropertyIdx(idx)), val, receiver, throw)
|
||||
}
|
||||
|
||||
func (o *objectGoMapReflect) defineOwnPropertyStr(name unistring.String, descr PropertyDescriptor, throw bool) bool {
|
||||
if !o.val.runtime.checkHostObjectPropertyDescr(name, descr, throw) {
|
||||
return false
|
||||
}
|
||||
|
||||
return o._put(o.strToKey(name.String(), throw), descr.Value, throw)
|
||||
}
|
||||
|
||||
func (o *objectGoMapReflect) defineOwnPropertyIdx(idx valueInt, descr PropertyDescriptor, throw bool) bool {
|
||||
if !o.val.runtime.checkHostObjectPropertyDescr(idx.string(), descr, throw) {
|
||||
return false
|
||||
}
|
||||
|
||||
return o._put(o.toKey(idx, throw), descr.Value, throw)
|
||||
}
|
||||
|
||||
func (o *objectGoMapReflect) hasOwnPropertyStr(name unistring.String) bool {
|
||||
key := o.strToKey(name.String(), false)
|
||||
if key.IsValid() && o.fieldsValue.MapIndex(key).IsValid() {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *objectGoMapReflect) hasOwnPropertyIdx(idx valueInt) bool {
|
||||
key := o.toKey(idx, false)
|
||||
if key.IsValid() && o.fieldsValue.MapIndex(key).IsValid() {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *objectGoMapReflect) deleteStr(name unistring.String, throw bool) bool {
|
||||
key := o.strToKey(name.String(), throw)
|
||||
if !key.IsValid() {
|
||||
return false
|
||||
}
|
||||
o.fieldsValue.SetMapIndex(key, reflect.Value{})
|
||||
return true
|
||||
}
|
||||
|
||||
func (o *objectGoMapReflect) deleteIdx(idx valueInt, throw bool) bool {
|
||||
key := o.toKey(idx, throw)
|
||||
if !key.IsValid() {
|
||||
return false
|
||||
}
|
||||
o.fieldsValue.SetMapIndex(key, reflect.Value{})
|
||||
return true
|
||||
}
|
||||
|
||||
type gomapReflectPropIter struct {
|
||||
o *objectGoMapReflect
|
||||
keys []reflect.Value
|
||||
idx int
|
||||
}
|
||||
|
||||
func (i *gomapReflectPropIter) next() (propIterItem, iterNextFunc) {
|
||||
for i.idx < len(i.keys) {
|
||||
key := i.keys[i.idx]
|
||||
v := i.o.fieldsValue.MapIndex(key)
|
||||
i.idx++
|
||||
if v.IsValid() {
|
||||
return propIterItem{name: newStringValue(key.String()), enumerable: _ENUM_TRUE}, i.next
|
||||
}
|
||||
}
|
||||
|
||||
return propIterItem{}, nil
|
||||
}
|
||||
|
||||
func (o *objectGoMapReflect) iterateStringKeys() iterNextFunc {
|
||||
return (&gomapReflectPropIter{
|
||||
o: o,
|
||||
keys: o.fieldsValue.MapKeys(),
|
||||
}).next
|
||||
}
|
||||
|
||||
func (o *objectGoMapReflect) stringKeys(_ bool, accum []Value) []Value {
|
||||
// all own keys are enumerable
|
||||
for _, key := range o.fieldsValue.MapKeys() {
|
||||
accum = append(accum, newStringValue(key.String()))
|
||||
}
|
||||
|
||||
return accum
|
||||
}
|
||||
715
server/vendor/github.com/dop251/goja/object_goreflect.go
generated
vendored
Normal file
715
server/vendor/github.com/dop251/goja/object_goreflect.go
generated
vendored
Normal file
@@ -0,0 +1,715 @@
|
||||
package goja
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/dop251/goja/parser"
|
||||
"github.com/dop251/goja/unistring"
|
||||
)
|
||||
|
||||
// JsonEncodable allows custom JSON encoding by JSON.stringify()
|
||||
// Note that if the returned value itself also implements JsonEncodable, it won't have any effect.
|
||||
type JsonEncodable interface {
|
||||
JsonEncodable() interface{}
|
||||
}
|
||||
|
||||
// FieldNameMapper provides custom mapping between Go and JavaScript property names.
|
||||
type FieldNameMapper interface {
|
||||
// FieldName returns a JavaScript name for the given struct field in the given type.
|
||||
// If this method returns "" the field becomes hidden.
|
||||
FieldName(t reflect.Type, f reflect.StructField) string
|
||||
|
||||
// MethodName returns a JavaScript name for the given method in the given type.
|
||||
// If this method returns "" the method becomes hidden.
|
||||
MethodName(t reflect.Type, m reflect.Method) string
|
||||
}
|
||||
|
||||
type tagFieldNameMapper struct {
|
||||
tagName string
|
||||
uncapMethods bool
|
||||
}
|
||||
|
||||
func (tfm tagFieldNameMapper) FieldName(_ reflect.Type, f reflect.StructField) string {
|
||||
tag := f.Tag.Get(tfm.tagName)
|
||||
if idx := strings.IndexByte(tag, ','); idx != -1 {
|
||||
tag = tag[:idx]
|
||||
}
|
||||
if parser.IsIdentifier(tag) {
|
||||
return tag
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func uncapitalize(s string) string {
|
||||
return strings.ToLower(s[0:1]) + s[1:]
|
||||
}
|
||||
|
||||
func (tfm tagFieldNameMapper) MethodName(_ reflect.Type, m reflect.Method) string {
|
||||
if tfm.uncapMethods {
|
||||
return uncapitalize(m.Name)
|
||||
}
|
||||
return m.Name
|
||||
}
|
||||
|
||||
type uncapFieldNameMapper struct {
|
||||
}
|
||||
|
||||
func (u uncapFieldNameMapper) FieldName(_ reflect.Type, f reflect.StructField) string {
|
||||
return uncapitalize(f.Name)
|
||||
}
|
||||
|
||||
func (u uncapFieldNameMapper) MethodName(_ reflect.Type, m reflect.Method) string {
|
||||
return uncapitalize(m.Name)
|
||||
}
|
||||
|
||||
type reflectFieldInfo struct {
|
||||
Index []int
|
||||
Anonymous bool
|
||||
}
|
||||
|
||||
type reflectFieldsInfo struct {
|
||||
Fields map[string]reflectFieldInfo
|
||||
Names []string
|
||||
}
|
||||
|
||||
type reflectMethodsInfo struct {
|
||||
Methods map[string]int
|
||||
Names []string
|
||||
}
|
||||
|
||||
type reflectValueWrapper interface {
|
||||
esValue() Value
|
||||
reflectValue() reflect.Value
|
||||
setReflectValue(reflect.Value)
|
||||
}
|
||||
|
||||
func isContainer(k reflect.Kind) bool {
|
||||
switch k {
|
||||
case reflect.Struct, reflect.Slice, reflect.Array:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func copyReflectValueWrapper(w reflectValueWrapper) {
|
||||
v := w.reflectValue()
|
||||
c := reflect.New(v.Type()).Elem()
|
||||
c.Set(v)
|
||||
w.setReflectValue(c)
|
||||
}
|
||||
|
||||
type objectGoReflect struct {
|
||||
baseObject
|
||||
origValue, fieldsValue reflect.Value
|
||||
|
||||
fieldsInfo *reflectFieldsInfo
|
||||
methodsInfo *reflectMethodsInfo
|
||||
|
||||
methodsValue reflect.Value
|
||||
|
||||
valueCache map[string]reflectValueWrapper
|
||||
|
||||
toString, valueOf func() Value
|
||||
|
||||
toJson func() interface{}
|
||||
}
|
||||
|
||||
func (o *objectGoReflect) init() {
|
||||
o.baseObject.init()
|
||||
switch o.fieldsValue.Kind() {
|
||||
case reflect.Bool:
|
||||
o.class = classBoolean
|
||||
o.prototype = o.val.runtime.global.BooleanPrototype
|
||||
o.toString = o._toStringBool
|
||||
o.valueOf = o._valueOfBool
|
||||
case reflect.String:
|
||||
o.class = classString
|
||||
o.prototype = o.val.runtime.global.StringPrototype
|
||||
o.toString = o._toStringString
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
o.class = classNumber
|
||||
o.prototype = o.val.runtime.global.NumberPrototype
|
||||
o.valueOf = o._valueOfInt
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
o.class = classNumber
|
||||
o.prototype = o.val.runtime.global.NumberPrototype
|
||||
o.valueOf = o._valueOfUint
|
||||
case reflect.Float32, reflect.Float64:
|
||||
o.class = classNumber
|
||||
o.prototype = o.val.runtime.global.NumberPrototype
|
||||
o.valueOf = o._valueOfFloat
|
||||
default:
|
||||
o.class = classObject
|
||||
o.prototype = o.val.runtime.global.ObjectPrototype
|
||||
}
|
||||
|
||||
if o.fieldsValue.Kind() == reflect.Struct {
|
||||
o.fieldsInfo = o.val.runtime.fieldsInfo(o.fieldsValue.Type())
|
||||
}
|
||||
|
||||
var methodsType reflect.Type
|
||||
// Always use pointer type for non-interface values to be able to access both methods defined on
|
||||
// the literal type and on the pointer.
|
||||
if o.fieldsValue.Kind() != reflect.Interface {
|
||||
methodsType = reflect.PtrTo(o.fieldsValue.Type())
|
||||
} else {
|
||||
methodsType = o.fieldsValue.Type()
|
||||
}
|
||||
|
||||
o.methodsInfo = o.val.runtime.methodsInfo(methodsType)
|
||||
|
||||
// Container values and values that have at least one method defined on the pointer type
|
||||
// need to be addressable.
|
||||
if !o.origValue.CanAddr() && (isContainer(o.origValue.Kind()) || len(o.methodsInfo.Names) > 0) {
|
||||
value := reflect.New(o.origValue.Type()).Elem()
|
||||
value.Set(o.origValue)
|
||||
o.origValue = value
|
||||
if value.Kind() != reflect.Ptr {
|
||||
o.fieldsValue = value
|
||||
}
|
||||
}
|
||||
|
||||
o.extensible = true
|
||||
|
||||
switch o.origValue.Interface().(type) {
|
||||
case fmt.Stringer:
|
||||
o.toString = o._toStringStringer
|
||||
case error:
|
||||
o.toString = o._toStringError
|
||||
}
|
||||
|
||||
if o.toString != nil || o.valueOf != nil {
|
||||
o.baseObject._putProp("toString", o.val.runtime.newNativeFunc(o.toStringFunc, nil, "toString", nil, 0), true, false, true)
|
||||
o.baseObject._putProp("valueOf", o.val.runtime.newNativeFunc(o.valueOfFunc, nil, "valueOf", nil, 0), true, false, true)
|
||||
}
|
||||
|
||||
if len(o.methodsInfo.Names) > 0 && o.fieldsValue.Kind() != reflect.Interface {
|
||||
o.methodsValue = o.fieldsValue.Addr()
|
||||
} else {
|
||||
o.methodsValue = o.fieldsValue
|
||||
}
|
||||
|
||||
if j, ok := o.origValue.Interface().(JsonEncodable); ok {
|
||||
o.toJson = j.JsonEncodable
|
||||
}
|
||||
}
|
||||
|
||||
func (o *objectGoReflect) toStringFunc(FunctionCall) Value {
|
||||
return o.toPrimitiveString()
|
||||
}
|
||||
|
||||
func (o *objectGoReflect) valueOfFunc(FunctionCall) Value {
|
||||
return o.toPrimitiveNumber()
|
||||
}
|
||||
|
||||
func (o *objectGoReflect) getStr(name unistring.String, receiver Value) Value {
|
||||
if v := o._get(name.String()); v != nil {
|
||||
return v
|
||||
}
|
||||
return o.baseObject.getStr(name, receiver)
|
||||
}
|
||||
|
||||
func (o *objectGoReflect) _getField(jsName string) reflect.Value {
|
||||
if o.fieldsInfo != nil {
|
||||
if info, exists := o.fieldsInfo.Fields[jsName]; exists {
|
||||
return o.fieldsValue.FieldByIndex(info.Index)
|
||||
}
|
||||
}
|
||||
|
||||
return reflect.Value{}
|
||||
}
|
||||
|
||||
func (o *objectGoReflect) _getMethod(jsName string) reflect.Value {
|
||||
if o.methodsInfo != nil {
|
||||
if idx, exists := o.methodsInfo.Methods[jsName]; exists {
|
||||
return o.methodsValue.Method(idx)
|
||||
}
|
||||
}
|
||||
|
||||
return reflect.Value{}
|
||||
}
|
||||
|
||||
func (o *objectGoReflect) elemToValue(ev reflect.Value) (Value, reflectValueWrapper) {
|
||||
if isContainer(ev.Kind()) {
|
||||
ret := o.val.runtime.toValue(ev.Interface(), ev)
|
||||
if obj, ok := ret.(*Object); ok {
|
||||
if w, ok := obj.self.(reflectValueWrapper); ok {
|
||||
return ret, w
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
if ev.Kind() == reflect.Interface {
|
||||
ev = ev.Elem()
|
||||
}
|
||||
|
||||
if ev.Kind() == reflect.Invalid {
|
||||
return _null, nil
|
||||
}
|
||||
|
||||
return o.val.runtime.toValue(ev.Interface(), ev), nil
|
||||
}
|
||||
|
||||
func (o *objectGoReflect) _getFieldValue(name string) Value {
|
||||
if v := o.valueCache[name]; v != nil {
|
||||
return v.esValue()
|
||||
}
|
||||
if v := o._getField(name); v.IsValid() {
|
||||
res, w := o.elemToValue(v)
|
||||
if w != nil {
|
||||
if o.valueCache == nil {
|
||||
o.valueCache = make(map[string]reflectValueWrapper)
|
||||
}
|
||||
o.valueCache[name] = w
|
||||
}
|
||||
return res
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *objectGoReflect) _get(name string) Value {
|
||||
if o.fieldsValue.Kind() == reflect.Struct {
|
||||
if ret := o._getFieldValue(name); ret != nil {
|
||||
return ret
|
||||
}
|
||||
}
|
||||
|
||||
if v := o._getMethod(name); v.IsValid() {
|
||||
return o.val.runtime.toValue(v.Interface(), v)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *objectGoReflect) getOwnPropStr(name unistring.String) Value {
|
||||
n := name.String()
|
||||
if o.fieldsValue.Kind() == reflect.Struct {
|
||||
if v := o._getFieldValue(n); v != nil {
|
||||
return &valueProperty{
|
||||
value: v,
|
||||
writable: true,
|
||||
enumerable: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if v := o._getMethod(n); v.IsValid() {
|
||||
return &valueProperty{
|
||||
value: o.val.runtime.toValue(v.Interface(), v),
|
||||
enumerable: true,
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *objectGoReflect) setOwnStr(name unistring.String, val Value, throw bool) bool {
|
||||
has, ok := o._put(name.String(), val, throw)
|
||||
if !has {
|
||||
if res, ok := o._setForeignStr(name, nil, val, o.val, throw); !ok {
|
||||
o.val.runtime.typeErrorResult(throw, "Cannot assign to property %s of a host object", name)
|
||||
return false
|
||||
} else {
|
||||
return res
|
||||
}
|
||||
}
|
||||
return ok
|
||||
}
|
||||
|
||||
func (o *objectGoReflect) setForeignStr(name unistring.String, val, receiver Value, throw bool) (bool, bool) {
|
||||
return o._setForeignStr(name, trueValIfPresent(o._has(name.String())), val, receiver, throw)
|
||||
}
|
||||
|
||||
func (o *objectGoReflect) setForeignIdx(idx valueInt, val, receiver Value, throw bool) (bool, bool) {
|
||||
return o._setForeignIdx(idx, nil, val, receiver, throw)
|
||||
}
|
||||
|
||||
func (o *objectGoReflect) _put(name string, val Value, throw bool) (has, ok bool) {
|
||||
if o.fieldsValue.Kind() == reflect.Struct {
|
||||
if v := o._getField(name); v.IsValid() {
|
||||
cached := o.valueCache[name]
|
||||
if cached != nil {
|
||||
copyReflectValueWrapper(cached)
|
||||
}
|
||||
|
||||
err := o.val.runtime.toReflectValue(val, v, &objectExportCtx{})
|
||||
if err != nil {
|
||||
if cached != nil {
|
||||
cached.setReflectValue(v)
|
||||
}
|
||||
o.val.runtime.typeErrorResult(throw, "Go struct conversion error: %v", err)
|
||||
return true, false
|
||||
}
|
||||
if cached != nil {
|
||||
delete(o.valueCache, name)
|
||||
}
|
||||
return true, true
|
||||
}
|
||||
}
|
||||
return false, false
|
||||
}
|
||||
|
||||
func (o *objectGoReflect) _putProp(name unistring.String, value Value, writable, enumerable, configurable bool) Value {
|
||||
if _, ok := o._put(name.String(), value, false); ok {
|
||||
return value
|
||||
}
|
||||
return o.baseObject._putProp(name, value, writable, enumerable, configurable)
|
||||
}
|
||||
|
||||
func (r *Runtime) checkHostObjectPropertyDescr(name unistring.String, descr PropertyDescriptor, throw bool) bool {
|
||||
if descr.Getter != nil || descr.Setter != nil {
|
||||
r.typeErrorResult(throw, "Host objects do not support accessor properties")
|
||||
return false
|
||||
}
|
||||
if descr.Writable == FLAG_FALSE {
|
||||
r.typeErrorResult(throw, "Host object field %s cannot be made read-only", name)
|
||||
return false
|
||||
}
|
||||
if descr.Configurable == FLAG_TRUE {
|
||||
r.typeErrorResult(throw, "Host object field %s cannot be made configurable", name)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (o *objectGoReflect) defineOwnPropertyStr(name unistring.String, descr PropertyDescriptor, throw bool) bool {
|
||||
if o.val.runtime.checkHostObjectPropertyDescr(name, descr, throw) {
|
||||
n := name.String()
|
||||
if has, ok := o._put(n, descr.Value, throw); !has {
|
||||
o.val.runtime.typeErrorResult(throw, "Cannot define property '%s' on a host object", n)
|
||||
return false
|
||||
} else {
|
||||
return ok
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *objectGoReflect) _has(name string) bool {
|
||||
if o.fieldsValue.Kind() == reflect.Struct {
|
||||
if v := o._getField(name); v.IsValid() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
if v := o._getMethod(name); v.IsValid() {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *objectGoReflect) hasOwnPropertyStr(name unistring.String) bool {
|
||||
return o._has(name.String())
|
||||
}
|
||||
|
||||
func (o *objectGoReflect) _valueOfInt() Value {
|
||||
return intToValue(o.fieldsValue.Int())
|
||||
}
|
||||
|
||||
func (o *objectGoReflect) _valueOfUint() Value {
|
||||
return intToValue(int64(o.fieldsValue.Uint()))
|
||||
}
|
||||
|
||||
func (o *objectGoReflect) _valueOfBool() Value {
|
||||
if o.fieldsValue.Bool() {
|
||||
return valueTrue
|
||||
} else {
|
||||
return valueFalse
|
||||
}
|
||||
}
|
||||
|
||||
func (o *objectGoReflect) _valueOfFloat() Value {
|
||||
return floatToValue(o.fieldsValue.Float())
|
||||
}
|
||||
|
||||
func (o *objectGoReflect) _toStringStringer() Value {
|
||||
return newStringValue(o.origValue.Interface().(fmt.Stringer).String())
|
||||
}
|
||||
|
||||
func (o *objectGoReflect) _toStringString() Value {
|
||||
return newStringValue(o.fieldsValue.String())
|
||||
}
|
||||
|
||||
func (o *objectGoReflect) _toStringBool() Value {
|
||||
if o.fieldsValue.Bool() {
|
||||
return stringTrue
|
||||
} else {
|
||||
return stringFalse
|
||||
}
|
||||
}
|
||||
|
||||
func (o *objectGoReflect) _toStringError() Value {
|
||||
return newStringValue(o.origValue.Interface().(error).Error())
|
||||
}
|
||||
|
||||
func (o *objectGoReflect) toPrimitiveNumber() Value {
|
||||
if o.valueOf != nil {
|
||||
return o.valueOf()
|
||||
}
|
||||
if o.toString != nil {
|
||||
return o.toString()
|
||||
}
|
||||
return o.baseObject.toPrimitiveNumber()
|
||||
}
|
||||
|
||||
func (o *objectGoReflect) toPrimitiveString() Value {
|
||||
if o.toString != nil {
|
||||
return o.toString()
|
||||
}
|
||||
if o.valueOf != nil {
|
||||
return o.valueOf().toString()
|
||||
}
|
||||
return o.baseObject.toPrimitiveString()
|
||||
}
|
||||
|
||||
func (o *objectGoReflect) toPrimitive() Value {
|
||||
if o.valueOf != nil {
|
||||
return o.valueOf()
|
||||
}
|
||||
if o.toString != nil {
|
||||
return o.toString()
|
||||
}
|
||||
|
||||
return o.baseObject.toPrimitive()
|
||||
}
|
||||
|
||||
func (o *objectGoReflect) deleteStr(name unistring.String, throw bool) bool {
|
||||
n := name.String()
|
||||
if o._has(n) {
|
||||
o.val.runtime.typeErrorResult(throw, "Cannot delete property %s from a Go type", n)
|
||||
return false
|
||||
}
|
||||
return o.baseObject.deleteStr(name, throw)
|
||||
}
|
||||
|
||||
type goreflectPropIter struct {
|
||||
o *objectGoReflect
|
||||
idx int
|
||||
}
|
||||
|
||||
func (i *goreflectPropIter) nextField() (propIterItem, iterNextFunc) {
|
||||
names := i.o.fieldsInfo.Names
|
||||
if i.idx < len(names) {
|
||||
name := names[i.idx]
|
||||
i.idx++
|
||||
return propIterItem{name: newStringValue(name), enumerable: _ENUM_TRUE}, i.nextField
|
||||
}
|
||||
|
||||
i.idx = 0
|
||||
return i.nextMethod()
|
||||
}
|
||||
|
||||
func (i *goreflectPropIter) nextMethod() (propIterItem, iterNextFunc) {
|
||||
names := i.o.methodsInfo.Names
|
||||
if i.idx < len(names) {
|
||||
name := names[i.idx]
|
||||
i.idx++
|
||||
return propIterItem{name: newStringValue(name), enumerable: _ENUM_TRUE}, i.nextMethod
|
||||
}
|
||||
|
||||
return propIterItem{}, nil
|
||||
}
|
||||
|
||||
func (o *objectGoReflect) iterateStringKeys() iterNextFunc {
|
||||
r := &goreflectPropIter{
|
||||
o: o,
|
||||
}
|
||||
if o.fieldsInfo != nil {
|
||||
return r.nextField
|
||||
}
|
||||
|
||||
return r.nextMethod
|
||||
}
|
||||
|
||||
func (o *objectGoReflect) stringKeys(_ bool, accum []Value) []Value {
|
||||
// all own keys are enumerable
|
||||
if o.fieldsInfo != nil {
|
||||
for _, name := range o.fieldsInfo.Names {
|
||||
accum = append(accum, newStringValue(name))
|
||||
}
|
||||
}
|
||||
|
||||
for _, name := range o.methodsInfo.Names {
|
||||
accum = append(accum, newStringValue(name))
|
||||
}
|
||||
|
||||
return accum
|
||||
}
|
||||
|
||||
func (o *objectGoReflect) export(*objectExportCtx) interface{} {
|
||||
return o.origValue.Interface()
|
||||
}
|
||||
|
||||
func (o *objectGoReflect) exportType() reflect.Type {
|
||||
return o.origValue.Type()
|
||||
}
|
||||
|
||||
func (o *objectGoReflect) equal(other objectImpl) bool {
|
||||
if other, ok := other.(*objectGoReflect); ok {
|
||||
k1, k2 := o.fieldsValue.Kind(), other.fieldsValue.Kind()
|
||||
if k1 == k2 {
|
||||
if isContainer(k1) {
|
||||
return o.fieldsValue == other.fieldsValue
|
||||
}
|
||||
return o.fieldsValue.Interface() == other.fieldsValue.Interface()
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *objectGoReflect) reflectValue() reflect.Value {
|
||||
return o.fieldsValue
|
||||
}
|
||||
|
||||
func (o *objectGoReflect) setReflectValue(v reflect.Value) {
|
||||
o.fieldsValue = v
|
||||
o.origValue = v
|
||||
o.methodsValue = v.Addr()
|
||||
}
|
||||
|
||||
func (o *objectGoReflect) esValue() Value {
|
||||
return o.val
|
||||
}
|
||||
|
||||
func (r *Runtime) buildFieldInfo(t reflect.Type, index []int, info *reflectFieldsInfo) {
|
||||
n := t.NumField()
|
||||
for i := 0; i < n; i++ {
|
||||
field := t.Field(i)
|
||||
name := field.Name
|
||||
if !ast.IsExported(name) {
|
||||
continue
|
||||
}
|
||||
if r.fieldNameMapper != nil {
|
||||
name = r.fieldNameMapper.FieldName(t, field)
|
||||
}
|
||||
|
||||
if name != "" {
|
||||
if inf, exists := info.Fields[name]; !exists {
|
||||
info.Names = append(info.Names, name)
|
||||
} else {
|
||||
if len(inf.Index) <= len(index) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if name != "" || field.Anonymous {
|
||||
idx := make([]int, len(index)+1)
|
||||
copy(idx, index)
|
||||
idx[len(idx)-1] = i
|
||||
|
||||
if name != "" {
|
||||
info.Fields[name] = reflectFieldInfo{
|
||||
Index: idx,
|
||||
Anonymous: field.Anonymous,
|
||||
}
|
||||
}
|
||||
if field.Anonymous {
|
||||
typ := field.Type
|
||||
for typ.Kind() == reflect.Ptr {
|
||||
typ = typ.Elem()
|
||||
}
|
||||
if typ.Kind() == reflect.Struct {
|
||||
r.buildFieldInfo(typ, idx, info)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var emptyMethodsInfo = reflectMethodsInfo{}
|
||||
|
||||
func (r *Runtime) buildMethodsInfo(t reflect.Type) (info *reflectMethodsInfo) {
|
||||
n := t.NumMethod()
|
||||
if n == 0 {
|
||||
return &emptyMethodsInfo
|
||||
}
|
||||
info = new(reflectMethodsInfo)
|
||||
info.Methods = make(map[string]int, n)
|
||||
info.Names = make([]string, 0, n)
|
||||
for i := 0; i < n; i++ {
|
||||
method := t.Method(i)
|
||||
name := method.Name
|
||||
if !ast.IsExported(name) {
|
||||
continue
|
||||
}
|
||||
if r.fieldNameMapper != nil {
|
||||
name = r.fieldNameMapper.MethodName(t, method)
|
||||
if name == "" {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if _, exists := info.Methods[name]; !exists {
|
||||
info.Names = append(info.Names, name)
|
||||
}
|
||||
|
||||
info.Methods[name] = i
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (r *Runtime) buildFieldsInfo(t reflect.Type) (info *reflectFieldsInfo) {
|
||||
info = new(reflectFieldsInfo)
|
||||
n := t.NumField()
|
||||
info.Fields = make(map[string]reflectFieldInfo, n)
|
||||
info.Names = make([]string, 0, n)
|
||||
r.buildFieldInfo(t, nil, info)
|
||||
return
|
||||
}
|
||||
|
||||
func (r *Runtime) fieldsInfo(t reflect.Type) (info *reflectFieldsInfo) {
|
||||
var exists bool
|
||||
if info, exists = r.fieldsInfoCache[t]; !exists {
|
||||
info = r.buildFieldsInfo(t)
|
||||
if r.fieldsInfoCache == nil {
|
||||
r.fieldsInfoCache = make(map[reflect.Type]*reflectFieldsInfo)
|
||||
}
|
||||
r.fieldsInfoCache[t] = info
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (r *Runtime) methodsInfo(t reflect.Type) (info *reflectMethodsInfo) {
|
||||
var exists bool
|
||||
if info, exists = r.methodsInfoCache[t]; !exists {
|
||||
info = r.buildMethodsInfo(t)
|
||||
if r.methodsInfoCache == nil {
|
||||
r.methodsInfoCache = make(map[reflect.Type]*reflectMethodsInfo)
|
||||
}
|
||||
r.methodsInfoCache[t] = info
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// SetFieldNameMapper sets a custom field name mapper for Go types. It can be called at any time, however
|
||||
// the mapping for any given value is fixed at the point of creation.
|
||||
// Setting this to nil restores the default behaviour which is all exported fields and methods are mapped to their
|
||||
// original unchanged names.
|
||||
func (r *Runtime) SetFieldNameMapper(mapper FieldNameMapper) {
|
||||
r.fieldNameMapper = mapper
|
||||
r.fieldsInfoCache = nil
|
||||
r.methodsInfoCache = nil
|
||||
}
|
||||
|
||||
// TagFieldNameMapper returns a FieldNameMapper that uses the given tagName for struct fields and optionally
|
||||
// uncapitalises (making the first letter lower case) method names.
|
||||
// The common tag value syntax is supported (name[,options]), however options are ignored.
|
||||
// Setting name to anything other than a valid ECMAScript identifier makes the field hidden.
|
||||
func TagFieldNameMapper(tagName string, uncapMethods bool) FieldNameMapper {
|
||||
return tagFieldNameMapper{
|
||||
tagName: tagName,
|
||||
uncapMethods: uncapMethods,
|
||||
}
|
||||
}
|
||||
|
||||
// UncapFieldNameMapper returns a FieldNameMapper that uncapitalises struct field and method names
|
||||
// making the first letter lower case.
|
||||
func UncapFieldNameMapper() FieldNameMapper {
|
||||
return uncapFieldNameMapper{}
|
||||
}
|
||||
336
server/vendor/github.com/dop251/goja/object_goslice.go
generated
vendored
Normal file
336
server/vendor/github.com/dop251/goja/object_goslice.go
generated
vendored
Normal file
@@ -0,0 +1,336 @@
|
||||
package goja
|
||||
|
||||
import (
|
||||
"math"
|
||||
"math/bits"
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
||||
"github.com/dop251/goja/unistring"
|
||||
)
|
||||
|
||||
type objectGoSlice struct {
|
||||
baseObject
|
||||
data *[]interface{}
|
||||
lengthProp valueProperty
|
||||
}
|
||||
|
||||
func (r *Runtime) newObjectGoSlice(data *[]interface{}) *objectGoSlice {
|
||||
obj := &Object{runtime: r}
|
||||
a := &objectGoSlice{
|
||||
baseObject: baseObject{
|
||||
val: obj,
|
||||
},
|
||||
data: data,
|
||||
}
|
||||
obj.self = a
|
||||
a.init()
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) init() {
|
||||
o.baseObject.init()
|
||||
o.class = classArray
|
||||
o.prototype = o.val.runtime.global.ArrayPrototype
|
||||
o.lengthProp.writable = true
|
||||
o.extensible = true
|
||||
o.updateLen()
|
||||
o.baseObject._put("length", &o.lengthProp)
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) updateLen() {
|
||||
o.lengthProp.value = intToValue(int64(len(*o.data)))
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) _getIdx(idx int) Value {
|
||||
return o.val.runtime.ToValue((*o.data)[idx])
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) getStr(name unistring.String, receiver Value) Value {
|
||||
var ownProp Value
|
||||
if idx := strToGoIdx(name); idx >= 0 && idx < len(*o.data) {
|
||||
ownProp = o._getIdx(idx)
|
||||
} else if name == "length" {
|
||||
ownProp = &o.lengthProp
|
||||
}
|
||||
|
||||
return o.getStrWithOwnProp(ownProp, name, receiver)
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) getIdx(idx valueInt, receiver Value) Value {
|
||||
if idx := int64(idx); idx >= 0 && idx < int64(len(*o.data)) {
|
||||
return o._getIdx(int(idx))
|
||||
}
|
||||
if o.prototype != nil {
|
||||
if receiver == nil {
|
||||
return o.prototype.self.getIdx(idx, o.val)
|
||||
}
|
||||
return o.prototype.self.getIdx(idx, receiver)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) getOwnPropStr(name unistring.String) Value {
|
||||
if idx := strToGoIdx(name); idx >= 0 {
|
||||
if idx < len(*o.data) {
|
||||
return &valueProperty{
|
||||
value: o._getIdx(idx),
|
||||
writable: true,
|
||||
enumerable: true,
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if name == "length" {
|
||||
return &o.lengthProp
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) getOwnPropIdx(idx valueInt) Value {
|
||||
if idx := int64(idx); idx >= 0 && idx < int64(len(*o.data)) {
|
||||
return &valueProperty{
|
||||
value: o._getIdx(int(idx)),
|
||||
writable: true,
|
||||
enumerable: true,
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) grow(size int) {
|
||||
oldcap := cap(*o.data)
|
||||
if oldcap < size {
|
||||
n := make([]interface{}, size, growCap(size, len(*o.data), oldcap))
|
||||
copy(n, *o.data)
|
||||
*o.data = n
|
||||
} else {
|
||||
tail := (*o.data)[len(*o.data):size]
|
||||
for k := range tail {
|
||||
tail[k] = nil
|
||||
}
|
||||
*o.data = (*o.data)[:size]
|
||||
}
|
||||
o.updateLen()
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) shrink(size int) {
|
||||
tail := (*o.data)[size:]
|
||||
for k := range tail {
|
||||
tail[k] = nil
|
||||
}
|
||||
*o.data = (*o.data)[:size]
|
||||
o.updateLen()
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) putIdx(idx int, v Value, throw bool) {
|
||||
if idx >= len(*o.data) {
|
||||
o.grow(idx + 1)
|
||||
}
|
||||
(*o.data)[idx] = v.Export()
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) putLength(v uint32, throw bool) bool {
|
||||
if bits.UintSize == 32 && v > math.MaxInt32 {
|
||||
panic(rangeError("Integer value overflows 32-bit int"))
|
||||
}
|
||||
newLen := int(v)
|
||||
curLen := len(*o.data)
|
||||
if newLen > curLen {
|
||||
o.grow(newLen)
|
||||
} else if newLen < curLen {
|
||||
o.shrink(newLen)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) setOwnIdx(idx valueInt, val Value, throw bool) bool {
|
||||
if i := toIntStrict(int64(idx)); i >= 0 {
|
||||
if i >= len(*o.data) {
|
||||
if res, ok := o._setForeignIdx(idx, nil, val, o.val, throw); ok {
|
||||
return res
|
||||
}
|
||||
}
|
||||
o.putIdx(i, val, throw)
|
||||
} else {
|
||||
name := idx.string()
|
||||
if res, ok := o._setForeignStr(name, nil, val, o.val, throw); !ok {
|
||||
o.val.runtime.typeErrorResult(throw, "Can't set property '%s' on Go slice", name)
|
||||
return false
|
||||
} else {
|
||||
return res
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) setOwnStr(name unistring.String, val Value, throw bool) bool {
|
||||
if idx := strToGoIdx(name); idx >= 0 {
|
||||
if idx >= len(*o.data) {
|
||||
if res, ok := o._setForeignStr(name, nil, val, o.val, throw); ok {
|
||||
return res
|
||||
}
|
||||
}
|
||||
o.putIdx(idx, val, throw)
|
||||
} else {
|
||||
if name == "length" {
|
||||
return o.putLength(o.val.runtime.toLengthUint32(val), throw)
|
||||
}
|
||||
if res, ok := o._setForeignStr(name, nil, val, o.val, throw); !ok {
|
||||
o.val.runtime.typeErrorResult(throw, "Can't set property '%s' on Go slice", name)
|
||||
return false
|
||||
} else {
|
||||
return res
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) setForeignIdx(idx valueInt, val, receiver Value, throw bool) (bool, bool) {
|
||||
return o._setForeignIdx(idx, trueValIfPresent(o.hasOwnPropertyIdx(idx)), val, receiver, throw)
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) setForeignStr(name unistring.String, val, receiver Value, throw bool) (bool, bool) {
|
||||
return o._setForeignStr(name, trueValIfPresent(o.hasOwnPropertyStr(name)), val, receiver, throw)
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) hasOwnPropertyIdx(idx valueInt) bool {
|
||||
if idx := int64(idx); idx >= 0 {
|
||||
return idx < int64(len(*o.data))
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) hasOwnPropertyStr(name unistring.String) bool {
|
||||
if idx := strToIdx64(name); idx >= 0 {
|
||||
return idx < int64(len(*o.data))
|
||||
}
|
||||
return name == "length"
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) defineOwnPropertyIdx(idx valueInt, descr PropertyDescriptor, throw bool) bool {
|
||||
if i := toIntStrict(int64(idx)); i >= 0 {
|
||||
if !o.val.runtime.checkHostObjectPropertyDescr(idx.string(), descr, throw) {
|
||||
return false
|
||||
}
|
||||
val := descr.Value
|
||||
if val == nil {
|
||||
val = _undefined
|
||||
}
|
||||
o.putIdx(i, val, throw)
|
||||
return true
|
||||
}
|
||||
o.val.runtime.typeErrorResult(throw, "Cannot define property '%d' on a Go slice", idx)
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) defineOwnPropertyStr(name unistring.String, descr PropertyDescriptor, throw bool) bool {
|
||||
if idx := strToGoIdx(name); idx >= 0 {
|
||||
if !o.val.runtime.checkHostObjectPropertyDescr(name, descr, throw) {
|
||||
return false
|
||||
}
|
||||
val := descr.Value
|
||||
if val == nil {
|
||||
val = _undefined
|
||||
}
|
||||
o.putIdx(idx, val, throw)
|
||||
return true
|
||||
}
|
||||
if name == "length" {
|
||||
return o.val.runtime.defineArrayLength(&o.lengthProp, descr, o.putLength, throw)
|
||||
}
|
||||
o.val.runtime.typeErrorResult(throw, "Cannot define property '%s' on a Go slice", name)
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) _deleteIdx(idx int64) {
|
||||
if idx < int64(len(*o.data)) {
|
||||
(*o.data)[idx] = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) deleteStr(name unistring.String, throw bool) bool {
|
||||
if idx := strToIdx64(name); idx >= 0 {
|
||||
o._deleteIdx(idx)
|
||||
return true
|
||||
}
|
||||
return o.baseObject.deleteStr(name, throw)
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) deleteIdx(i valueInt, throw bool) bool {
|
||||
idx := int64(i)
|
||||
if idx >= 0 {
|
||||
o._deleteIdx(idx)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
type goslicePropIter struct {
|
||||
o *objectGoSlice
|
||||
idx, limit int
|
||||
}
|
||||
|
||||
func (i *goslicePropIter) next() (propIterItem, iterNextFunc) {
|
||||
if i.idx < i.limit && i.idx < len(*i.o.data) {
|
||||
name := strconv.Itoa(i.idx)
|
||||
i.idx++
|
||||
return propIterItem{name: newStringValue(name), enumerable: _ENUM_TRUE}, i.next
|
||||
}
|
||||
|
||||
return propIterItem{}, nil
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) iterateStringKeys() iterNextFunc {
|
||||
return (&goslicePropIter{
|
||||
o: o,
|
||||
limit: len(*o.data),
|
||||
}).next
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) stringKeys(_ bool, accum []Value) []Value {
|
||||
for i := range *o.data {
|
||||
accum = append(accum, asciiString(strconv.Itoa(i)))
|
||||
}
|
||||
|
||||
return accum
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) export(*objectExportCtx) interface{} {
|
||||
return *o.data
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) exportType() reflect.Type {
|
||||
return reflectTypeArray
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) equal(other objectImpl) bool {
|
||||
if other, ok := other.(*objectGoSlice); ok {
|
||||
return o.data == other.data
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) esValue() Value {
|
||||
return o.val
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) reflectValue() reflect.Value {
|
||||
return reflect.ValueOf(o.data).Elem()
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) setReflectValue(value reflect.Value) {
|
||||
o.data = value.Addr().Interface().(*[]interface{})
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) sortLen() int {
|
||||
return len(*o.data)
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) sortGet(i int) Value {
|
||||
return o.getIdx(valueInt(i), nil)
|
||||
}
|
||||
|
||||
func (o *objectGoSlice) swap(i int, j int) {
|
||||
(*o.data)[i], (*o.data)[j] = (*o.data)[j], (*o.data)[i]
|
||||
}
|
||||
91
server/vendor/github.com/dop251/goja/object_goslice_reflect.go
generated
vendored
Normal file
91
server/vendor/github.com/dop251/goja/object_goslice_reflect.go
generated
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
package goja
|
||||
|
||||
import (
|
||||
"math"
|
||||
"math/bits"
|
||||
"reflect"
|
||||
|
||||
"github.com/dop251/goja/unistring"
|
||||
)
|
||||
|
||||
type objectGoSliceReflect struct {
|
||||
objectGoArrayReflect
|
||||
}
|
||||
|
||||
func (o *objectGoSliceReflect) init() {
|
||||
o.objectGoArrayReflect._init()
|
||||
o.lengthProp.writable = true
|
||||
o.putIdx = o._putIdx
|
||||
}
|
||||
|
||||
func (o *objectGoSliceReflect) _putIdx(idx int, v Value, throw bool) bool {
|
||||
if idx >= o.fieldsValue.Len() {
|
||||
o.grow(idx + 1)
|
||||
}
|
||||
return o.objectGoArrayReflect._putIdx(idx, v, throw)
|
||||
}
|
||||
|
||||
func (o *objectGoSliceReflect) grow(size int) {
|
||||
oldcap := o.fieldsValue.Cap()
|
||||
if oldcap < size {
|
||||
n := reflect.MakeSlice(o.fieldsValue.Type(), size, growCap(size, o.fieldsValue.Len(), oldcap))
|
||||
reflect.Copy(n, o.fieldsValue)
|
||||
o.fieldsValue.Set(n)
|
||||
l := len(o.valueCache)
|
||||
if l > size {
|
||||
l = size
|
||||
}
|
||||
for i, w := range o.valueCache[:l] {
|
||||
if w != nil {
|
||||
w.setReflectValue(o.fieldsValue.Index(i))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
tail := o.fieldsValue.Slice(o.fieldsValue.Len(), size)
|
||||
zero := reflect.Zero(o.fieldsValue.Type().Elem())
|
||||
for i := 0; i < tail.Len(); i++ {
|
||||
tail.Index(i).Set(zero)
|
||||
}
|
||||
o.fieldsValue.SetLen(size)
|
||||
}
|
||||
o.updateLen()
|
||||
}
|
||||
|
||||
func (o *objectGoSliceReflect) shrink(size int) {
|
||||
o.valueCache.shrink(size)
|
||||
tail := o.fieldsValue.Slice(size, o.fieldsValue.Len())
|
||||
zero := reflect.Zero(o.fieldsValue.Type().Elem())
|
||||
for i := 0; i < tail.Len(); i++ {
|
||||
tail.Index(i).Set(zero)
|
||||
}
|
||||
o.fieldsValue.SetLen(size)
|
||||
o.updateLen()
|
||||
}
|
||||
|
||||
func (o *objectGoSliceReflect) putLength(v uint32, throw bool) bool {
|
||||
if bits.UintSize == 32 && v > math.MaxInt32 {
|
||||
panic(rangeError("Integer value overflows 32-bit int"))
|
||||
}
|
||||
newLen := int(v)
|
||||
curLen := o.fieldsValue.Len()
|
||||
if newLen > curLen {
|
||||
o.grow(newLen)
|
||||
} else if newLen < curLen {
|
||||
o.shrink(newLen)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (o *objectGoSliceReflect) setOwnStr(name unistring.String, val Value, throw bool) bool {
|
||||
if name == "length" {
|
||||
return o.putLength(o.val.runtime.toLengthUint32(val), throw)
|
||||
}
|
||||
return o.objectGoArrayReflect.setOwnStr(name, val, throw)
|
||||
}
|
||||
|
||||
func (o *objectGoSliceReflect) defineOwnPropertyStr(name unistring.String, descr PropertyDescriptor, throw bool) bool {
|
||||
if name == "length" {
|
||||
return o.val.runtime.defineArrayLength(&o.lengthProp, descr, o.putLength, throw)
|
||||
}
|
||||
return o.objectGoArrayReflect.defineOwnPropertyStr(name, descr, throw)
|
||||
}
|
||||
332
server/vendor/github.com/dop251/goja/object_lazy.go
generated
vendored
Normal file
332
server/vendor/github.com/dop251/goja/object_lazy.go
generated
vendored
Normal file
@@ -0,0 +1,332 @@
|
||||
package goja
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"github.com/dop251/goja/unistring"
|
||||
)
|
||||
|
||||
type lazyObject struct {
|
||||
val *Object
|
||||
create func(*Object) objectImpl
|
||||
}
|
||||
|
||||
func (o *lazyObject) className() string {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.className()
|
||||
}
|
||||
|
||||
func (o *lazyObject) typeOf() valueString {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.typeOf()
|
||||
}
|
||||
|
||||
func (o *lazyObject) getIdx(p valueInt, receiver Value) Value {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.getIdx(p, receiver)
|
||||
}
|
||||
|
||||
func (o *lazyObject) getSym(p *Symbol, receiver Value) Value {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.getSym(p, receiver)
|
||||
}
|
||||
|
||||
func (o *lazyObject) getOwnPropIdx(idx valueInt) Value {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.getOwnPropIdx(idx)
|
||||
}
|
||||
|
||||
func (o *lazyObject) getOwnPropSym(s *Symbol) Value {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.getOwnPropSym(s)
|
||||
}
|
||||
|
||||
func (o *lazyObject) hasPropertyIdx(idx valueInt) bool {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.hasPropertyIdx(idx)
|
||||
}
|
||||
|
||||
func (o *lazyObject) hasPropertySym(s *Symbol) bool {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.hasPropertySym(s)
|
||||
}
|
||||
|
||||
func (o *lazyObject) hasOwnPropertyIdx(idx valueInt) bool {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.hasOwnPropertyIdx(idx)
|
||||
}
|
||||
|
||||
func (o *lazyObject) hasOwnPropertySym(s *Symbol) bool {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.hasOwnPropertySym(s)
|
||||
}
|
||||
|
||||
func (o *lazyObject) defineOwnPropertyStr(name unistring.String, desc PropertyDescriptor, throw bool) bool {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.defineOwnPropertyStr(name, desc, throw)
|
||||
}
|
||||
|
||||
func (o *lazyObject) defineOwnPropertyIdx(name valueInt, desc PropertyDescriptor, throw bool) bool {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.defineOwnPropertyIdx(name, desc, throw)
|
||||
}
|
||||
|
||||
func (o *lazyObject) defineOwnPropertySym(name *Symbol, desc PropertyDescriptor, throw bool) bool {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.defineOwnPropertySym(name, desc, throw)
|
||||
}
|
||||
|
||||
func (o *lazyObject) deleteIdx(idx valueInt, throw bool) bool {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.deleteIdx(idx, throw)
|
||||
}
|
||||
|
||||
func (o *lazyObject) deleteSym(s *Symbol, throw bool) bool {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.deleteSym(s, throw)
|
||||
}
|
||||
|
||||
func (o *lazyObject) getStr(name unistring.String, receiver Value) Value {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.getStr(name, receiver)
|
||||
}
|
||||
|
||||
func (o *lazyObject) getOwnPropStr(name unistring.String) Value {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.getOwnPropStr(name)
|
||||
}
|
||||
|
||||
func (o *lazyObject) setOwnStr(p unistring.String, v Value, throw bool) bool {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.setOwnStr(p, v, throw)
|
||||
}
|
||||
|
||||
func (o *lazyObject) setOwnIdx(p valueInt, v Value, throw bool) bool {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.setOwnIdx(p, v, throw)
|
||||
}
|
||||
|
||||
func (o *lazyObject) setOwnSym(p *Symbol, v Value, throw bool) bool {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.setOwnSym(p, v, throw)
|
||||
}
|
||||
|
||||
func (o *lazyObject) setForeignStr(p unistring.String, v, receiver Value, throw bool) (bool, bool) {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.setForeignStr(p, v, receiver, throw)
|
||||
}
|
||||
|
||||
func (o *lazyObject) setForeignIdx(p valueInt, v, receiver Value, throw bool) (bool, bool) {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.setForeignIdx(p, v, receiver, throw)
|
||||
}
|
||||
|
||||
func (o *lazyObject) setForeignSym(p *Symbol, v, receiver Value, throw bool) (bool, bool) {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.setForeignSym(p, v, receiver, throw)
|
||||
}
|
||||
|
||||
func (o *lazyObject) hasPropertyStr(name unistring.String) bool {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.hasPropertyStr(name)
|
||||
}
|
||||
|
||||
func (o *lazyObject) hasOwnPropertyStr(name unistring.String) bool {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.hasOwnPropertyStr(name)
|
||||
}
|
||||
|
||||
func (o *lazyObject) _putProp(unistring.String, Value, bool, bool, bool) Value {
|
||||
panic("cannot use _putProp() in lazy object")
|
||||
}
|
||||
|
||||
func (o *lazyObject) _putSym(*Symbol, Value) {
|
||||
panic("cannot use _putSym() in lazy object")
|
||||
}
|
||||
|
||||
func (o *lazyObject) toPrimitiveNumber() Value {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.toPrimitiveNumber()
|
||||
}
|
||||
|
||||
func (o *lazyObject) toPrimitiveString() Value {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.toPrimitiveString()
|
||||
}
|
||||
|
||||
func (o *lazyObject) toPrimitive() Value {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.toPrimitive()
|
||||
}
|
||||
|
||||
func (o *lazyObject) assertCallable() (call func(FunctionCall) Value, ok bool) {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.assertCallable()
|
||||
}
|
||||
|
||||
func (o *lazyObject) vmCall(vm *vm, n int) {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
obj.vmCall(vm, n)
|
||||
}
|
||||
|
||||
func (o *lazyObject) assertConstructor() func(args []Value, newTarget *Object) *Object {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.assertConstructor()
|
||||
}
|
||||
|
||||
func (o *lazyObject) deleteStr(name unistring.String, throw bool) bool {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.deleteStr(name, throw)
|
||||
}
|
||||
|
||||
func (o *lazyObject) proto() *Object {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.proto()
|
||||
}
|
||||
|
||||
func (o *lazyObject) hasInstance(v Value) bool {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.hasInstance(v)
|
||||
}
|
||||
|
||||
func (o *lazyObject) isExtensible() bool {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.isExtensible()
|
||||
}
|
||||
|
||||
func (o *lazyObject) preventExtensions(throw bool) bool {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.preventExtensions(throw)
|
||||
}
|
||||
|
||||
func (o *lazyObject) iterateStringKeys() iterNextFunc {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.iterateStringKeys()
|
||||
}
|
||||
|
||||
func (o *lazyObject) iterateSymbols() iterNextFunc {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.iterateSymbols()
|
||||
}
|
||||
|
||||
func (o *lazyObject) iterateKeys() iterNextFunc {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.iterateKeys()
|
||||
}
|
||||
|
||||
func (o *lazyObject) export(ctx *objectExportCtx) interface{} {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.export(ctx)
|
||||
}
|
||||
|
||||
func (o *lazyObject) exportType() reflect.Type {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.exportType()
|
||||
}
|
||||
|
||||
func (o *lazyObject) exportToMap(m reflect.Value, typ reflect.Type, ctx *objectExportCtx) error {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.exportToMap(m, typ, ctx)
|
||||
}
|
||||
|
||||
func (o *lazyObject) exportToArrayOrSlice(s reflect.Value, typ reflect.Type, ctx *objectExportCtx) error {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.exportToArrayOrSlice(s, typ, ctx)
|
||||
}
|
||||
|
||||
func (o *lazyObject) equal(other objectImpl) bool {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.equal(other)
|
||||
}
|
||||
|
||||
func (o *lazyObject) stringKeys(all bool, accum []Value) []Value {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.stringKeys(all, accum)
|
||||
}
|
||||
|
||||
func (o *lazyObject) symbols(all bool, accum []Value) []Value {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.symbols(all, accum)
|
||||
}
|
||||
|
||||
func (o *lazyObject) keys(all bool, accum []Value) []Value {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.keys(all, accum)
|
||||
}
|
||||
|
||||
func (o *lazyObject) setProto(proto *Object, throw bool) bool {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.setProto(proto, throw)
|
||||
}
|
||||
|
||||
func (o *lazyObject) getPrivateEnv(typ *privateEnvType, create bool) *privateElements {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.getPrivateEnv(typ, create)
|
||||
}
|
||||
|
||||
func (o *lazyObject) sortLen() int {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.sortLen()
|
||||
}
|
||||
|
||||
func (o *lazyObject) sortGet(i int) Value {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
return obj.sortGet(i)
|
||||
}
|
||||
|
||||
func (o *lazyObject) swap(i int, j int) {
|
||||
obj := o.create(o.val)
|
||||
o.val.self = obj
|
||||
obj.swap(i, j)
|
||||
}
|
||||
184
server/vendor/github.com/dop251/goja/parser/README.markdown
generated
vendored
Normal file
184
server/vendor/github.com/dop251/goja/parser/README.markdown
generated
vendored
Normal file
@@ -0,0 +1,184 @@
|
||||
# parser
|
||||
--
|
||||
import "github.com/dop251/goja/parser"
|
||||
|
||||
Package parser implements a parser for JavaScript. Borrowed from https://github.com/robertkrimen/otto/tree/master/parser
|
||||
|
||||
import (
|
||||
"github.com/dop251/goja/parser"
|
||||
)
|
||||
|
||||
Parse and return an AST
|
||||
|
||||
filename := "" // A filename is optional
|
||||
src := `
|
||||
// Sample xyzzy example
|
||||
(function(){
|
||||
if (3.14159 > 0) {
|
||||
console.log("Hello, World.");
|
||||
return;
|
||||
}
|
||||
|
||||
var xyzzy = NaN;
|
||||
console.log("Nothing happens.");
|
||||
return xyzzy;
|
||||
})();
|
||||
`
|
||||
|
||||
// Parse some JavaScript, yielding a *ast.Program and/or an ErrorList
|
||||
program, err := parser.ParseFile(nil, filename, src, 0)
|
||||
|
||||
|
||||
### Warning
|
||||
|
||||
The parser and AST interfaces are still works-in-progress (particularly where
|
||||
node types are concerned) and may change in the future.
|
||||
|
||||
## Usage
|
||||
|
||||
#### func ParseFile
|
||||
|
||||
```go
|
||||
func ParseFile(fileSet *file.FileSet, filename string, src interface{}, mode Mode) (*ast.Program, error)
|
||||
```
|
||||
ParseFile parses the source code of a single JavaScript/ECMAScript source file
|
||||
and returns the corresponding ast.Program node.
|
||||
|
||||
If fileSet == nil, ParseFile parses source without a FileSet. If fileSet != nil,
|
||||
ParseFile first adds filename and src to fileSet.
|
||||
|
||||
The filename argument is optional and is used for labelling errors, etc.
|
||||
|
||||
src may be a string, a byte slice, a bytes.Buffer, or an io.Reader, but it MUST
|
||||
always be in UTF-8.
|
||||
|
||||
// Parse some JavaScript, yielding a *ast.Program and/or an ErrorList
|
||||
program, err := parser.ParseFile(nil, "", `if (abc > 1) {}`, 0)
|
||||
|
||||
#### func ParseFunction
|
||||
|
||||
```go
|
||||
func ParseFunction(parameterList, body string) (*ast.FunctionLiteral, error)
|
||||
```
|
||||
ParseFunction parses a given parameter list and body as a function and returns
|
||||
the corresponding ast.FunctionLiteral node.
|
||||
|
||||
The parameter list, if any, should be a comma-separated list of identifiers.
|
||||
|
||||
#### func ReadSource
|
||||
|
||||
```go
|
||||
func ReadSource(filename string, src interface{}) ([]byte, error)
|
||||
```
|
||||
|
||||
#### func TransformRegExp
|
||||
|
||||
```go
|
||||
func TransformRegExp(pattern string) (string, error)
|
||||
```
|
||||
TransformRegExp transforms a JavaScript pattern into a Go "regexp" pattern.
|
||||
|
||||
re2 (Go) cannot do backtracking, so the presence of a lookahead (?=) (?!) or
|
||||
backreference (\1, \2, ...) will cause an error.
|
||||
|
||||
re2 (Go) has a different definition for \s: [\t\n\f\r ]. The JavaScript
|
||||
definition, on the other hand, also includes \v, Unicode "Separator, Space",
|
||||
etc.
|
||||
|
||||
If the pattern is invalid (not valid even in JavaScript), then this function
|
||||
returns the empty string and an error.
|
||||
|
||||
If the pattern is valid, but incompatible (contains a lookahead or
|
||||
backreference), then this function returns the transformation (a non-empty
|
||||
string) AND an error.
|
||||
|
||||
#### type Error
|
||||
|
||||
```go
|
||||
type Error struct {
|
||||
Position file.Position
|
||||
Message string
|
||||
}
|
||||
```
|
||||
|
||||
An Error represents a parsing error. It includes the position where the error
|
||||
occurred and a message/description.
|
||||
|
||||
#### func (Error) Error
|
||||
|
||||
```go
|
||||
func (self Error) Error() string
|
||||
```
|
||||
|
||||
#### type ErrorList
|
||||
|
||||
```go
|
||||
type ErrorList []*Error
|
||||
```
|
||||
|
||||
ErrorList is a list of *Errors.
|
||||
|
||||
#### func (*ErrorList) Add
|
||||
|
||||
```go
|
||||
func (self *ErrorList) Add(position file.Position, msg string)
|
||||
```
|
||||
Add adds an Error with given position and message to an ErrorList.
|
||||
|
||||
#### func (ErrorList) Err
|
||||
|
||||
```go
|
||||
func (self ErrorList) Err() error
|
||||
```
|
||||
Err returns an error equivalent to this ErrorList. If the list is empty, Err
|
||||
returns nil.
|
||||
|
||||
#### func (ErrorList) Error
|
||||
|
||||
```go
|
||||
func (self ErrorList) Error() string
|
||||
```
|
||||
Error implements the Error interface.
|
||||
|
||||
#### func (ErrorList) Len
|
||||
|
||||
```go
|
||||
func (self ErrorList) Len() int
|
||||
```
|
||||
|
||||
#### func (ErrorList) Less
|
||||
|
||||
```go
|
||||
func (self ErrorList) Less(i, j int) bool
|
||||
```
|
||||
|
||||
#### func (*ErrorList) Reset
|
||||
|
||||
```go
|
||||
func (self *ErrorList) Reset()
|
||||
```
|
||||
Reset resets an ErrorList to no errors.
|
||||
|
||||
#### func (ErrorList) Sort
|
||||
|
||||
```go
|
||||
func (self ErrorList) Sort()
|
||||
```
|
||||
|
||||
#### func (ErrorList) Swap
|
||||
|
||||
```go
|
||||
func (self ErrorList) Swap(i, j int)
|
||||
```
|
||||
|
||||
#### type Mode
|
||||
|
||||
```go
|
||||
type Mode uint
|
||||
```
|
||||
|
||||
A Mode value is a set of flags (or 0). They control optional parser
|
||||
functionality.
|
||||
|
||||
--
|
||||
**godocdown** http://github.com/robertkrimen/godocdown
|
||||
176
server/vendor/github.com/dop251/goja/parser/error.go
generated
vendored
Normal file
176
server/vendor/github.com/dop251/goja/parser/error.go
generated
vendored
Normal file
@@ -0,0 +1,176 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"github.com/dop251/goja/file"
|
||||
"github.com/dop251/goja/token"
|
||||
)
|
||||
|
||||
const (
|
||||
err_UnexpectedToken = "Unexpected token %v"
|
||||
err_UnexpectedEndOfInput = "Unexpected end of input"
|
||||
err_UnexpectedEscape = "Unexpected escape"
|
||||
)
|
||||
|
||||
// UnexpectedNumber: 'Unexpected number',
|
||||
// UnexpectedString: 'Unexpected string',
|
||||
// UnexpectedIdentifier: 'Unexpected identifier',
|
||||
// UnexpectedReserved: 'Unexpected reserved word',
|
||||
// NewlineAfterThrow: 'Illegal newline after throw',
|
||||
// InvalidRegExp: 'Invalid regular expression',
|
||||
// UnterminatedRegExp: 'Invalid regular expression: missing /',
|
||||
// InvalidLHSInAssignment: 'Invalid left-hand side in assignment',
|
||||
// InvalidLHSInForIn: 'Invalid left-hand side in for-in',
|
||||
// MultipleDefaultsInSwitch: 'More than one default clause in switch statement',
|
||||
// NoCatchOrFinally: 'Missing catch or finally after try',
|
||||
// UnknownLabel: 'Undefined label \'%0\'',
|
||||
// Redeclaration: '%0 \'%1\' has already been declared',
|
||||
// IllegalContinue: 'Illegal continue statement',
|
||||
// IllegalBreak: 'Illegal break statement',
|
||||
// IllegalReturn: 'Illegal return statement',
|
||||
// StrictModeWith: 'Strict mode code may not include a with statement',
|
||||
// StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode',
|
||||
// StrictVarName: 'Variable name may not be eval or arguments in strict mode',
|
||||
// StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode',
|
||||
// StrictParamDupe: 'Strict mode function may not have duplicate parameter names',
|
||||
// StrictFunctionName: 'Function name may not be eval or arguments in strict mode',
|
||||
// StrictOctalLiteral: 'Octal literals are not allowed in strict mode.',
|
||||
// StrictDelete: 'Delete of an unqualified identifier in strict mode.',
|
||||
// StrictDuplicateProperty: 'Duplicate data property in object literal not allowed in strict mode',
|
||||
// AccessorDataProperty: 'Object literal may not have data and accessor property with the same name',
|
||||
// AccessorGetSet: 'Object literal may not have multiple get/set accessors with the same name',
|
||||
// StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode',
|
||||
// StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode',
|
||||
// StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode',
|
||||
// StrictReservedWord: 'Use of future reserved word in strict mode'
|
||||
|
||||
// A SyntaxError is a description of an ECMAScript syntax error.
|
||||
|
||||
// An Error represents a parsing error. It includes the position where the error occurred and a message/description.
|
||||
type Error struct {
|
||||
Position file.Position
|
||||
Message string
|
||||
}
|
||||
|
||||
// FIXME Should this be "SyntaxError"?
|
||||
|
||||
func (self Error) Error() string {
|
||||
filename := self.Position.Filename
|
||||
if filename == "" {
|
||||
filename = "(anonymous)"
|
||||
}
|
||||
return fmt.Sprintf("%s: Line %d:%d %s",
|
||||
filename,
|
||||
self.Position.Line,
|
||||
self.Position.Column,
|
||||
self.Message,
|
||||
)
|
||||
}
|
||||
|
||||
func (self *_parser) error(place interface{}, msg string, msgValues ...interface{}) *Error {
|
||||
idx := file.Idx(0)
|
||||
switch place := place.(type) {
|
||||
case int:
|
||||
idx = self.idxOf(place)
|
||||
case file.Idx:
|
||||
if place == 0 {
|
||||
idx = self.idxOf(self.chrOffset)
|
||||
} else {
|
||||
idx = place
|
||||
}
|
||||
default:
|
||||
panic(fmt.Errorf("error(%T, ...)", place))
|
||||
}
|
||||
|
||||
position := self.position(idx)
|
||||
msg = fmt.Sprintf(msg, msgValues...)
|
||||
self.errors.Add(position, msg)
|
||||
return self.errors[len(self.errors)-1]
|
||||
}
|
||||
|
||||
func (self *_parser) errorUnexpected(idx file.Idx, chr rune) error {
|
||||
if chr == -1 {
|
||||
return self.error(idx, err_UnexpectedEndOfInput)
|
||||
}
|
||||
return self.error(idx, err_UnexpectedToken, token.ILLEGAL)
|
||||
}
|
||||
|
||||
func (self *_parser) errorUnexpectedToken(tkn token.Token) error {
|
||||
switch tkn {
|
||||
case token.EOF:
|
||||
return self.error(file.Idx(0), err_UnexpectedEndOfInput)
|
||||
}
|
||||
value := tkn.String()
|
||||
switch tkn {
|
||||
case token.BOOLEAN, token.NULL:
|
||||
value = self.literal
|
||||
case token.IDENTIFIER:
|
||||
return self.error(self.idx, "Unexpected identifier")
|
||||
case token.KEYWORD:
|
||||
// TODO Might be a future reserved word
|
||||
return self.error(self.idx, "Unexpected reserved word")
|
||||
case token.ESCAPED_RESERVED_WORD:
|
||||
return self.error(self.idx, "Keyword must not contain escaped characters")
|
||||
case token.NUMBER:
|
||||
return self.error(self.idx, "Unexpected number")
|
||||
case token.STRING:
|
||||
return self.error(self.idx, "Unexpected string")
|
||||
}
|
||||
return self.error(self.idx, err_UnexpectedToken, value)
|
||||
}
|
||||
|
||||
// ErrorList is a list of *Errors.
|
||||
type ErrorList []*Error
|
||||
|
||||
// Add adds an Error with given position and message to an ErrorList.
|
||||
func (self *ErrorList) Add(position file.Position, msg string) {
|
||||
*self = append(*self, &Error{position, msg})
|
||||
}
|
||||
|
||||
// Reset resets an ErrorList to no errors.
|
||||
func (self *ErrorList) Reset() { *self = (*self)[0:0] }
|
||||
|
||||
func (self ErrorList) Len() int { return len(self) }
|
||||
func (self ErrorList) Swap(i, j int) { self[i], self[j] = self[j], self[i] }
|
||||
func (self ErrorList) Less(i, j int) bool {
|
||||
x := &self[i].Position
|
||||
y := &self[j].Position
|
||||
if x.Filename < y.Filename {
|
||||
return true
|
||||
}
|
||||
if x.Filename == y.Filename {
|
||||
if x.Line < y.Line {
|
||||
return true
|
||||
}
|
||||
if x.Line == y.Line {
|
||||
return x.Column < y.Column
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (self ErrorList) Sort() {
|
||||
sort.Sort(self)
|
||||
}
|
||||
|
||||
// Error implements the Error interface.
|
||||
func (self ErrorList) Error() string {
|
||||
switch len(self) {
|
||||
case 0:
|
||||
return "no errors"
|
||||
case 1:
|
||||
return self[0].Error()
|
||||
}
|
||||
return fmt.Sprintf("%s (and %d more errors)", self[0].Error(), len(self)-1)
|
||||
}
|
||||
|
||||
// Err returns an error equivalent to this ErrorList.
|
||||
// If the list is empty, Err returns nil.
|
||||
func (self ErrorList) Err() error {
|
||||
if len(self) == 0 {
|
||||
return nil
|
||||
}
|
||||
return self
|
||||
}
|
||||
1655
server/vendor/github.com/dop251/goja/parser/expression.go
generated
vendored
Normal file
1655
server/vendor/github.com/dop251/goja/parser/expression.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1179
server/vendor/github.com/dop251/goja/parser/lexer.go
generated
vendored
Normal file
1179
server/vendor/github.com/dop251/goja/parser/lexer.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
268
server/vendor/github.com/dop251/goja/parser/parser.go
generated
vendored
Normal file
268
server/vendor/github.com/dop251/goja/parser/parser.go
generated
vendored
Normal file
@@ -0,0 +1,268 @@
|
||||
/*
|
||||
Package parser implements a parser for JavaScript.
|
||||
|
||||
import (
|
||||
"github.com/dop251/goja/parser"
|
||||
)
|
||||
|
||||
Parse and return an AST
|
||||
|
||||
filename := "" // A filename is optional
|
||||
src := `
|
||||
// Sample xyzzy example
|
||||
(function(){
|
||||
if (3.14159 > 0) {
|
||||
console.log("Hello, World.");
|
||||
return;
|
||||
}
|
||||
|
||||
var xyzzy = NaN;
|
||||
console.log("Nothing happens.");
|
||||
return xyzzy;
|
||||
})();
|
||||
`
|
||||
|
||||
// Parse some JavaScript, yielding a *ast.Program and/or an ErrorList
|
||||
program, err := parser.ParseFile(nil, filename, src, 0)
|
||||
|
||||
# Warning
|
||||
|
||||
The parser and AST interfaces are still works-in-progress (particularly where
|
||||
node types are concerned) and may change in the future.
|
||||
*/
|
||||
package parser
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/dop251/goja/ast"
|
||||
"github.com/dop251/goja/file"
|
||||
"github.com/dop251/goja/token"
|
||||
"github.com/dop251/goja/unistring"
|
||||
)
|
||||
|
||||
// A Mode value is a set of flags (or 0). They control optional parser functionality.
|
||||
type Mode uint
|
||||
|
||||
const (
|
||||
IgnoreRegExpErrors Mode = 1 << iota // Ignore RegExp compatibility errors (allow backtracking)
|
||||
)
|
||||
|
||||
type options struct {
|
||||
disableSourceMaps bool
|
||||
sourceMapLoader func(path string) ([]byte, error)
|
||||
}
|
||||
|
||||
// Option represents one of the options for the parser to use in the Parse methods. Currently supported are:
|
||||
// WithDisableSourceMaps and WithSourceMapLoader.
|
||||
type Option func(*options)
|
||||
|
||||
// WithDisableSourceMaps is an option to disable source maps support. May save a bit of time when source maps
|
||||
// are not in use.
|
||||
func WithDisableSourceMaps(opts *options) {
|
||||
opts.disableSourceMaps = true
|
||||
}
|
||||
|
||||
// WithSourceMapLoader is an option to set a custom source map loader. The loader will be given a path or a
|
||||
// URL from the sourceMappingURL. If sourceMappingURL is not absolute it is resolved relatively to the name
|
||||
// of the file being parsed. Any error returned by the loader will fail the parsing.
|
||||
// Note that setting this to nil does not disable source map support, there is a default loader which reads
|
||||
// from the filesystem. Use WithDisableSourceMaps to disable source map support.
|
||||
func WithSourceMapLoader(loader func(path string) ([]byte, error)) Option {
|
||||
return func(opts *options) {
|
||||
opts.sourceMapLoader = loader
|
||||
}
|
||||
}
|
||||
|
||||
type _parser struct {
|
||||
str string
|
||||
length int
|
||||
base int
|
||||
|
||||
chr rune // The current character
|
||||
chrOffset int // The offset of current character
|
||||
offset int // The offset after current character (may be greater than 1)
|
||||
|
||||
idx file.Idx // The index of token
|
||||
token token.Token // The token
|
||||
literal string // The literal of the token, if any
|
||||
parsedLiteral unistring.String
|
||||
|
||||
scope *_scope
|
||||
insertSemicolon bool // If we see a newline, then insert an implicit semicolon
|
||||
implicitSemicolon bool // An implicit semicolon exists
|
||||
|
||||
errors ErrorList
|
||||
|
||||
recover struct {
|
||||
// Scratch when trying to seek to the next statement, etc.
|
||||
idx file.Idx
|
||||
count int
|
||||
}
|
||||
|
||||
mode Mode
|
||||
opts options
|
||||
|
||||
file *file.File
|
||||
}
|
||||
|
||||
func _newParser(filename, src string, base int, opts ...Option) *_parser {
|
||||
p := &_parser{
|
||||
chr: ' ', // This is set so we can start scanning by skipping whitespace
|
||||
str: src,
|
||||
length: len(src),
|
||||
base: base,
|
||||
file: file.NewFile(filename, src, base),
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(&p.opts)
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
func newParser(filename, src string) *_parser {
|
||||
return _newParser(filename, src, 1)
|
||||
}
|
||||
|
||||
func ReadSource(filename string, src interface{}) ([]byte, error) {
|
||||
if src != nil {
|
||||
switch src := src.(type) {
|
||||
case string:
|
||||
return []byte(src), nil
|
||||
case []byte:
|
||||
return src, nil
|
||||
case *bytes.Buffer:
|
||||
if src != nil {
|
||||
return src.Bytes(), nil
|
||||
}
|
||||
case io.Reader:
|
||||
var bfr bytes.Buffer
|
||||
if _, err := io.Copy(&bfr, src); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return bfr.Bytes(), nil
|
||||
}
|
||||
return nil, errors.New("invalid source")
|
||||
}
|
||||
return os.ReadFile(filename)
|
||||
}
|
||||
|
||||
// ParseFile parses the source code of a single JavaScript/ECMAScript source file and returns
|
||||
// the corresponding ast.Program node.
|
||||
//
|
||||
// If fileSet == nil, ParseFile parses source without a FileSet.
|
||||
// If fileSet != nil, ParseFile first adds filename and src to fileSet.
|
||||
//
|
||||
// The filename argument is optional and is used for labelling errors, etc.
|
||||
//
|
||||
// src may be a string, a byte slice, a bytes.Buffer, or an io.Reader, but it MUST always be in UTF-8.
|
||||
//
|
||||
// // Parse some JavaScript, yielding a *ast.Program and/or an ErrorList
|
||||
// program, err := parser.ParseFile(nil, "", `if (abc > 1) {}`, 0)
|
||||
func ParseFile(fileSet *file.FileSet, filename string, src interface{}, mode Mode, options ...Option) (*ast.Program, error) {
|
||||
str, err := ReadSource(filename, src)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
{
|
||||
str := string(str)
|
||||
|
||||
base := 1
|
||||
if fileSet != nil {
|
||||
base = fileSet.AddFile(filename, str)
|
||||
}
|
||||
|
||||
parser := _newParser(filename, str, base, options...)
|
||||
parser.mode = mode
|
||||
return parser.parse()
|
||||
}
|
||||
}
|
||||
|
||||
// ParseFunction parses a given parameter list and body as a function and returns the
|
||||
// corresponding ast.FunctionLiteral node.
|
||||
//
|
||||
// The parameter list, if any, should be a comma-separated list of identifiers.
|
||||
func ParseFunction(parameterList, body string, options ...Option) (*ast.FunctionLiteral, error) {
|
||||
|
||||
src := "(function(" + parameterList + ") {\n" + body + "\n})"
|
||||
|
||||
parser := _newParser("", src, 1, options...)
|
||||
program, err := parser.parse()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral), nil
|
||||
}
|
||||
|
||||
func (self *_parser) slice(idx0, idx1 file.Idx) string {
|
||||
from := int(idx0) - self.base
|
||||
to := int(idx1) - self.base
|
||||
if from >= 0 && to <= len(self.str) {
|
||||
return self.str[from:to]
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func (self *_parser) parse() (*ast.Program, error) {
|
||||
self.openScope()
|
||||
defer self.closeScope()
|
||||
self.next()
|
||||
program := self.parseProgram()
|
||||
if false {
|
||||
self.errors.Sort()
|
||||
}
|
||||
return program, self.errors.Err()
|
||||
}
|
||||
|
||||
func (self *_parser) next() {
|
||||
self.token, self.literal, self.parsedLiteral, self.idx = self.scan()
|
||||
}
|
||||
|
||||
func (self *_parser) optionalSemicolon() {
|
||||
if self.token == token.SEMICOLON {
|
||||
self.next()
|
||||
return
|
||||
}
|
||||
|
||||
if self.implicitSemicolon {
|
||||
self.implicitSemicolon = false
|
||||
return
|
||||
}
|
||||
|
||||
if self.token != token.EOF && self.token != token.RIGHT_BRACE {
|
||||
self.expect(token.SEMICOLON)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_parser) semicolon() {
|
||||
if self.token != token.RIGHT_PARENTHESIS && self.token != token.RIGHT_BRACE {
|
||||
if self.implicitSemicolon {
|
||||
self.implicitSemicolon = false
|
||||
return
|
||||
}
|
||||
|
||||
self.expect(token.SEMICOLON)
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_parser) idxOf(offset int) file.Idx {
|
||||
return file.Idx(self.base + offset)
|
||||
}
|
||||
|
||||
func (self *_parser) expect(value token.Token) file.Idx {
|
||||
idx := self.idx
|
||||
if self.token != value {
|
||||
self.errorUnexpectedToken(self.token)
|
||||
}
|
||||
self.next()
|
||||
return idx
|
||||
}
|
||||
|
||||
func (self *_parser) position(idx file.Idx) file.Position {
|
||||
return self.file.Position(int(idx) - self.base)
|
||||
}
|
||||
458
server/vendor/github.com/dop251/goja/parser/regexp.go
generated
vendored
Normal file
458
server/vendor/github.com/dop251/goja/parser/regexp.go
generated
vendored
Normal file
@@ -0,0 +1,458 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
const (
|
||||
WhitespaceChars = " \f\n\r\t\v\u00a0\u1680\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000\ufeff"
|
||||
Re2Dot = "[^\r\n\u2028\u2029]"
|
||||
)
|
||||
|
||||
type regexpParseError struct {
|
||||
offset int
|
||||
err string
|
||||
}
|
||||
|
||||
type RegexpErrorIncompatible struct {
|
||||
regexpParseError
|
||||
}
|
||||
type RegexpSyntaxError struct {
|
||||
regexpParseError
|
||||
}
|
||||
|
||||
func (s regexpParseError) Error() string {
|
||||
return s.err
|
||||
}
|
||||
|
||||
type _RegExp_parser struct {
|
||||
str string
|
||||
length int
|
||||
|
||||
chr rune // The current character
|
||||
chrOffset int // The offset of current character
|
||||
offset int // The offset after current character (may be greater than 1)
|
||||
|
||||
err error
|
||||
|
||||
goRegexp strings.Builder
|
||||
passOffset int
|
||||
}
|
||||
|
||||
// TransformRegExp transforms a JavaScript pattern into a Go "regexp" pattern.
|
||||
//
|
||||
// re2 (Go) cannot do backtracking, so the presence of a lookahead (?=) (?!) or
|
||||
// backreference (\1, \2, ...) will cause an error.
|
||||
//
|
||||
// re2 (Go) has a different definition for \s: [\t\n\f\r ].
|
||||
// The JavaScript definition, on the other hand, also includes \v, Unicode "Separator, Space", etc.
|
||||
//
|
||||
// If the pattern is valid, but incompatible (contains a lookahead or backreference),
|
||||
// then this function returns an empty string an error of type RegexpErrorIncompatible.
|
||||
//
|
||||
// If the pattern is invalid (not valid even in JavaScript), then this function
|
||||
// returns an empty string and a generic error.
|
||||
func TransformRegExp(pattern string) (transformed string, err error) {
|
||||
|
||||
if pattern == "" {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
parser := _RegExp_parser{
|
||||
str: pattern,
|
||||
length: len(pattern),
|
||||
}
|
||||
err = parser.parse()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return parser.ResultString(), nil
|
||||
}
|
||||
|
||||
func (self *_RegExp_parser) ResultString() string {
|
||||
if self.passOffset != -1 {
|
||||
return self.str[:self.passOffset]
|
||||
}
|
||||
return self.goRegexp.String()
|
||||
}
|
||||
|
||||
func (self *_RegExp_parser) parse() (err error) {
|
||||
self.read() // Pull in the first character
|
||||
self.scan()
|
||||
return self.err
|
||||
}
|
||||
|
||||
func (self *_RegExp_parser) read() {
|
||||
if self.offset < self.length {
|
||||
self.chrOffset = self.offset
|
||||
chr, width := rune(self.str[self.offset]), 1
|
||||
if chr >= utf8.RuneSelf { // !ASCII
|
||||
chr, width = utf8.DecodeRuneInString(self.str[self.offset:])
|
||||
if chr == utf8.RuneError && width == 1 {
|
||||
self.error(true, "Invalid UTF-8 character")
|
||||
return
|
||||
}
|
||||
}
|
||||
self.offset += width
|
||||
self.chr = chr
|
||||
} else {
|
||||
self.chrOffset = self.length
|
||||
self.chr = -1 // EOF
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_RegExp_parser) stopPassing() {
|
||||
self.goRegexp.Grow(3 * len(self.str) / 2)
|
||||
self.goRegexp.WriteString(self.str[:self.passOffset])
|
||||
self.passOffset = -1
|
||||
}
|
||||
|
||||
func (self *_RegExp_parser) write(p []byte) {
|
||||
if self.passOffset != -1 {
|
||||
self.stopPassing()
|
||||
}
|
||||
self.goRegexp.Write(p)
|
||||
}
|
||||
|
||||
func (self *_RegExp_parser) writeByte(b byte) {
|
||||
if self.passOffset != -1 {
|
||||
self.stopPassing()
|
||||
}
|
||||
self.goRegexp.WriteByte(b)
|
||||
}
|
||||
|
||||
func (self *_RegExp_parser) writeString(s string) {
|
||||
if self.passOffset != -1 {
|
||||
self.stopPassing()
|
||||
}
|
||||
self.goRegexp.WriteString(s)
|
||||
}
|
||||
|
||||
func (self *_RegExp_parser) scan() {
|
||||
for self.chr != -1 {
|
||||
switch self.chr {
|
||||
case '\\':
|
||||
self.read()
|
||||
self.scanEscape(false)
|
||||
case '(':
|
||||
self.pass()
|
||||
self.scanGroup()
|
||||
case '[':
|
||||
self.scanBracket()
|
||||
case ')':
|
||||
self.error(true, "Unmatched ')'")
|
||||
return
|
||||
case '.':
|
||||
self.writeString(Re2Dot)
|
||||
self.read()
|
||||
default:
|
||||
self.pass()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// (...)
|
||||
func (self *_RegExp_parser) scanGroup() {
|
||||
str := self.str[self.chrOffset:]
|
||||
if len(str) > 1 { // A possibility of (?= or (?!
|
||||
if str[0] == '?' {
|
||||
ch := str[1]
|
||||
switch {
|
||||
case ch == '=' || ch == '!':
|
||||
self.error(false, "re2: Invalid (%s) <lookahead>", self.str[self.chrOffset:self.chrOffset+2])
|
||||
return
|
||||
case ch == '<':
|
||||
self.error(false, "re2: Invalid (%s) <lookbehind>", self.str[self.chrOffset:self.chrOffset+2])
|
||||
return
|
||||
case ch != ':':
|
||||
self.error(true, "Invalid group")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
for self.chr != -1 && self.chr != ')' {
|
||||
switch self.chr {
|
||||
case '\\':
|
||||
self.read()
|
||||
self.scanEscape(false)
|
||||
case '(':
|
||||
self.pass()
|
||||
self.scanGroup()
|
||||
case '[':
|
||||
self.scanBracket()
|
||||
case '.':
|
||||
self.writeString(Re2Dot)
|
||||
self.read()
|
||||
default:
|
||||
self.pass()
|
||||
continue
|
||||
}
|
||||
}
|
||||
if self.chr != ')' {
|
||||
self.error(true, "Unterminated group")
|
||||
return
|
||||
}
|
||||
self.pass()
|
||||
}
|
||||
|
||||
// [...]
|
||||
func (self *_RegExp_parser) scanBracket() {
|
||||
str := self.str[self.chrOffset:]
|
||||
if strings.HasPrefix(str, "[]") {
|
||||
// [] -- Empty character class
|
||||
self.writeString("[^\u0000-\U0001FFFF]")
|
||||
self.offset += 1
|
||||
self.read()
|
||||
return
|
||||
}
|
||||
|
||||
if strings.HasPrefix(str, "[^]") {
|
||||
self.writeString("[\u0000-\U0001FFFF]")
|
||||
self.offset += 2
|
||||
self.read()
|
||||
return
|
||||
}
|
||||
|
||||
self.pass()
|
||||
for self.chr != -1 {
|
||||
if self.chr == ']' {
|
||||
break
|
||||
} else if self.chr == '\\' {
|
||||
self.read()
|
||||
self.scanEscape(true)
|
||||
continue
|
||||
}
|
||||
self.pass()
|
||||
}
|
||||
if self.chr != ']' {
|
||||
self.error(true, "Unterminated character class")
|
||||
return
|
||||
}
|
||||
self.pass()
|
||||
}
|
||||
|
||||
// \...
|
||||
func (self *_RegExp_parser) scanEscape(inClass bool) {
|
||||
offset := self.chrOffset
|
||||
|
||||
var length, base uint32
|
||||
switch self.chr {
|
||||
|
||||
case '0', '1', '2', '3', '4', '5', '6', '7':
|
||||
var value int64
|
||||
size := 0
|
||||
for {
|
||||
digit := int64(digitValue(self.chr))
|
||||
if digit >= 8 {
|
||||
// Not a valid digit
|
||||
break
|
||||
}
|
||||
value = value*8 + digit
|
||||
self.read()
|
||||
size += 1
|
||||
}
|
||||
if size == 1 { // The number of characters read
|
||||
if value != 0 {
|
||||
// An invalid backreference
|
||||
self.error(false, "re2: Invalid \\%d <backreference>", value)
|
||||
return
|
||||
}
|
||||
self.passString(offset-1, self.chrOffset)
|
||||
return
|
||||
}
|
||||
tmp := []byte{'\\', 'x', '0', 0}
|
||||
if value >= 16 {
|
||||
tmp = tmp[0:2]
|
||||
} else {
|
||||
tmp = tmp[0:3]
|
||||
}
|
||||
tmp = strconv.AppendInt(tmp, value, 16)
|
||||
self.write(tmp)
|
||||
return
|
||||
|
||||
case '8', '9':
|
||||
self.read()
|
||||
self.error(false, "re2: Invalid \\%s <backreference>", self.str[offset:self.chrOffset])
|
||||
return
|
||||
|
||||
case 'x':
|
||||
self.read()
|
||||
length, base = 2, 16
|
||||
|
||||
case 'u':
|
||||
self.read()
|
||||
if self.chr == '{' {
|
||||
self.read()
|
||||
length, base = 0, 16
|
||||
} else {
|
||||
length, base = 4, 16
|
||||
}
|
||||
|
||||
case 'b':
|
||||
if inClass {
|
||||
self.write([]byte{'\\', 'x', '0', '8'})
|
||||
self.read()
|
||||
return
|
||||
}
|
||||
fallthrough
|
||||
|
||||
case 'B':
|
||||
fallthrough
|
||||
|
||||
case 'd', 'D', 'w', 'W':
|
||||
// This is slightly broken, because ECMAScript
|
||||
// includes \v in \s, \S, while re2 does not
|
||||
fallthrough
|
||||
|
||||
case '\\':
|
||||
fallthrough
|
||||
|
||||
case 'f', 'n', 'r', 't', 'v':
|
||||
self.passString(offset-1, self.offset)
|
||||
self.read()
|
||||
return
|
||||
|
||||
case 'c':
|
||||
self.read()
|
||||
var value int64
|
||||
if 'a' <= self.chr && self.chr <= 'z' {
|
||||
value = int64(self.chr - 'a' + 1)
|
||||
} else if 'A' <= self.chr && self.chr <= 'Z' {
|
||||
value = int64(self.chr - 'A' + 1)
|
||||
} else {
|
||||
self.writeByte('c')
|
||||
return
|
||||
}
|
||||
tmp := []byte{'\\', 'x', '0', 0}
|
||||
if value >= 16 {
|
||||
tmp = tmp[0:2]
|
||||
} else {
|
||||
tmp = tmp[0:3]
|
||||
}
|
||||
tmp = strconv.AppendInt(tmp, value, 16)
|
||||
self.write(tmp)
|
||||
self.read()
|
||||
return
|
||||
case 's':
|
||||
if inClass {
|
||||
self.writeString(WhitespaceChars)
|
||||
} else {
|
||||
self.writeString("[" + WhitespaceChars + "]")
|
||||
}
|
||||
self.read()
|
||||
return
|
||||
case 'S':
|
||||
if inClass {
|
||||
self.error(false, "S in class")
|
||||
return
|
||||
} else {
|
||||
self.writeString("[^" + WhitespaceChars + "]")
|
||||
}
|
||||
self.read()
|
||||
return
|
||||
default:
|
||||
// $ is an identifier character, so we have to have
|
||||
// a special case for it here
|
||||
if self.chr == '$' || self.chr < utf8.RuneSelf && !isIdentifierPart(self.chr) {
|
||||
// A non-identifier character needs escaping
|
||||
self.passString(offset-1, self.offset)
|
||||
self.read()
|
||||
return
|
||||
}
|
||||
// Unescape the character for re2
|
||||
self.pass()
|
||||
return
|
||||
}
|
||||
|
||||
// Otherwise, we're a \u.... or \x...
|
||||
valueOffset := self.chrOffset
|
||||
|
||||
if length > 0 {
|
||||
for length := length; length > 0; length-- {
|
||||
digit := uint32(digitValue(self.chr))
|
||||
if digit >= base {
|
||||
// Not a valid digit
|
||||
goto skip
|
||||
}
|
||||
self.read()
|
||||
}
|
||||
} else {
|
||||
for self.chr != '}' && self.chr != -1 {
|
||||
digit := uint32(digitValue(self.chr))
|
||||
if digit >= base {
|
||||
// Not a valid digit
|
||||
goto skip
|
||||
}
|
||||
self.read()
|
||||
}
|
||||
}
|
||||
|
||||
if length == 4 || length == 0 {
|
||||
self.write([]byte{
|
||||
'\\',
|
||||
'x',
|
||||
'{',
|
||||
})
|
||||
self.passString(valueOffset, self.chrOffset)
|
||||
if length != 0 {
|
||||
self.writeByte('}')
|
||||
}
|
||||
} else if length == 2 {
|
||||
self.passString(offset-1, valueOffset+2)
|
||||
} else {
|
||||
// Should never, ever get here...
|
||||
self.error(true, "re2: Illegal branch in scanEscape")
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
|
||||
skip:
|
||||
self.passString(offset, self.chrOffset)
|
||||
}
|
||||
|
||||
func (self *_RegExp_parser) pass() {
|
||||
if self.passOffset == self.chrOffset {
|
||||
self.passOffset = self.offset
|
||||
} else {
|
||||
if self.passOffset != -1 {
|
||||
self.stopPassing()
|
||||
}
|
||||
if self.chr != -1 {
|
||||
self.goRegexp.WriteRune(self.chr)
|
||||
}
|
||||
}
|
||||
self.read()
|
||||
}
|
||||
|
||||
func (self *_RegExp_parser) passString(start, end int) {
|
||||
if self.passOffset == start {
|
||||
self.passOffset = end
|
||||
return
|
||||
}
|
||||
if self.passOffset != -1 {
|
||||
self.stopPassing()
|
||||
}
|
||||
self.goRegexp.WriteString(self.str[start:end])
|
||||
}
|
||||
|
||||
func (self *_RegExp_parser) error(fatal bool, msg string, msgValues ...interface{}) {
|
||||
if self.err != nil {
|
||||
return
|
||||
}
|
||||
e := regexpParseError{
|
||||
offset: self.offset,
|
||||
err: fmt.Sprintf(msg, msgValues...),
|
||||
}
|
||||
if fatal {
|
||||
self.err = RegexpSyntaxError{e}
|
||||
} else {
|
||||
self.err = RegexpErrorIncompatible{e}
|
||||
}
|
||||
self.offset = self.length
|
||||
self.chr = -1
|
||||
}
|
||||
50
server/vendor/github.com/dop251/goja/parser/scope.go
generated
vendored
Normal file
50
server/vendor/github.com/dop251/goja/parser/scope.go
generated
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"github.com/dop251/goja/ast"
|
||||
"github.com/dop251/goja/unistring"
|
||||
)
|
||||
|
||||
type _scope struct {
|
||||
outer *_scope
|
||||
allowIn bool
|
||||
allowLet bool
|
||||
inIteration bool
|
||||
inSwitch bool
|
||||
inFuncParams bool
|
||||
inFunction bool
|
||||
inAsync bool
|
||||
allowAwait bool
|
||||
allowYield bool
|
||||
declarationList []*ast.VariableDeclaration
|
||||
|
||||
labels []unistring.String
|
||||
}
|
||||
|
||||
func (self *_parser) openScope() {
|
||||
self.scope = &_scope{
|
||||
outer: self.scope,
|
||||
allowIn: true,
|
||||
}
|
||||
}
|
||||
|
||||
func (self *_parser) closeScope() {
|
||||
self.scope = self.scope.outer
|
||||
}
|
||||
|
||||
func (self *_scope) declare(declaration *ast.VariableDeclaration) {
|
||||
self.declarationList = append(self.declarationList, declaration)
|
||||
}
|
||||
|
||||
func (self *_scope) hasLabel(name unistring.String) bool {
|
||||
for _, label := range self.labels {
|
||||
if label == name {
|
||||
return true
|
||||
}
|
||||
}
|
||||
if self.outer != nil && !self.inFunction {
|
||||
// Crossing a function boundary to look for a label is verboten
|
||||
return self.outer.hasLabel(name)
|
||||
}
|
||||
return false
|
||||
}
|
||||
1076
server/vendor/github.com/dop251/goja/parser/statement.go
generated
vendored
Normal file
1076
server/vendor/github.com/dop251/goja/parser/statement.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
308
server/vendor/github.com/dop251/goja/profiler.go
generated
vendored
Normal file
308
server/vendor/github.com/dop251/goja/profiler.go
generated
vendored
Normal file
@@ -0,0 +1,308 @@
|
||||
package goja
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"strconv"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/google/pprof/profile"
|
||||
)
|
||||
|
||||
const profInterval = 10 * time.Millisecond
|
||||
const profMaxStackDepth = 64
|
||||
|
||||
const (
|
||||
profReqNone int32 = iota
|
||||
profReqDoSample
|
||||
profReqSampleReady
|
||||
profReqStop
|
||||
)
|
||||
|
||||
type _globalProfiler struct {
|
||||
p profiler
|
||||
w io.Writer
|
||||
|
||||
enabled int32
|
||||
}
|
||||
|
||||
var globalProfiler _globalProfiler
|
||||
|
||||
type profTracker struct {
|
||||
req, finished int32
|
||||
start, stop time.Time
|
||||
numFrames int
|
||||
frames [profMaxStackDepth]StackFrame
|
||||
}
|
||||
|
||||
type profiler struct {
|
||||
mu sync.Mutex
|
||||
trackers []*profTracker
|
||||
buf *profBuffer
|
||||
running bool
|
||||
}
|
||||
|
||||
type profFunc struct {
|
||||
f profile.Function
|
||||
locs map[int32]*profile.Location
|
||||
}
|
||||
|
||||
type profSampleNode struct {
|
||||
loc *profile.Location
|
||||
sample *profile.Sample
|
||||
parent *profSampleNode
|
||||
children map[*profile.Location]*profSampleNode
|
||||
}
|
||||
|
||||
type profBuffer struct {
|
||||
funcs map[*Program]*profFunc
|
||||
root profSampleNode
|
||||
}
|
||||
|
||||
func (pb *profBuffer) addSample(pt *profTracker) {
|
||||
sampleFrames := pt.frames[:pt.numFrames]
|
||||
n := &pb.root
|
||||
for j := len(sampleFrames) - 1; j >= 0; j-- {
|
||||
frame := sampleFrames[j]
|
||||
if frame.prg == nil {
|
||||
continue
|
||||
}
|
||||
var f *profFunc
|
||||
if f = pb.funcs[frame.prg]; f == nil {
|
||||
f = &profFunc{
|
||||
locs: make(map[int32]*profile.Location),
|
||||
}
|
||||
if pb.funcs == nil {
|
||||
pb.funcs = make(map[*Program]*profFunc)
|
||||
}
|
||||
pb.funcs[frame.prg] = f
|
||||
}
|
||||
var loc *profile.Location
|
||||
if loc = f.locs[int32(frame.pc)]; loc == nil {
|
||||
loc = &profile.Location{}
|
||||
f.locs[int32(frame.pc)] = loc
|
||||
}
|
||||
if nn := n.children[loc]; nn == nil {
|
||||
if n.children == nil {
|
||||
n.children = make(map[*profile.Location]*profSampleNode, 1)
|
||||
}
|
||||
nn = &profSampleNode{
|
||||
parent: n,
|
||||
loc: loc,
|
||||
}
|
||||
n.children[loc] = nn
|
||||
n = nn
|
||||
} else {
|
||||
n = nn
|
||||
}
|
||||
}
|
||||
smpl := n.sample
|
||||
if smpl == nil {
|
||||
locs := make([]*profile.Location, 0, len(sampleFrames))
|
||||
for n1 := n; n1.loc != nil; n1 = n1.parent {
|
||||
locs = append(locs, n1.loc)
|
||||
}
|
||||
smpl = &profile.Sample{
|
||||
Location: locs,
|
||||
Value: make([]int64, 2),
|
||||
}
|
||||
n.sample = smpl
|
||||
}
|
||||
smpl.Value[0]++
|
||||
smpl.Value[1] += int64(pt.stop.Sub(pt.start))
|
||||
}
|
||||
|
||||
func (pb *profBuffer) profile() *profile.Profile {
|
||||
pr := profile.Profile{}
|
||||
pr.SampleType = []*profile.ValueType{
|
||||
{Type: "samples", Unit: "count"},
|
||||
{Type: "cpu", Unit: "nanoseconds"},
|
||||
}
|
||||
pr.PeriodType = pr.SampleType[1]
|
||||
pr.Period = int64(profInterval)
|
||||
mapping := &profile.Mapping{
|
||||
ID: 1,
|
||||
File: "[ECMAScript code]",
|
||||
}
|
||||
pr.Mapping = make([]*profile.Mapping, 1, len(pb.funcs)+1)
|
||||
pr.Mapping[0] = mapping
|
||||
|
||||
pr.Function = make([]*profile.Function, 0, len(pb.funcs))
|
||||
funcNames := make(map[string]struct{})
|
||||
var funcId, locId uint64
|
||||
for prg, f := range pb.funcs {
|
||||
fileName := prg.src.Name()
|
||||
funcId++
|
||||
f.f.ID = funcId
|
||||
f.f.Filename = fileName
|
||||
var funcName string
|
||||
if prg.funcName != "" {
|
||||
funcName = prg.funcName.String()
|
||||
} else {
|
||||
funcName = "<anonymous>"
|
||||
}
|
||||
// Make sure the function name is unique, otherwise the graph display merges them into one node, even
|
||||
// if they are in different mappings.
|
||||
if _, exists := funcNames[funcName]; exists {
|
||||
funcName += "." + strconv.FormatUint(f.f.ID, 10)
|
||||
} else {
|
||||
funcNames[funcName] = struct{}{}
|
||||
}
|
||||
f.f.Name = funcName
|
||||
pr.Function = append(pr.Function, &f.f)
|
||||
for pc, loc := range f.locs {
|
||||
locId++
|
||||
loc.ID = locId
|
||||
pos := prg.src.Position(prg.sourceOffset(int(pc)))
|
||||
loc.Line = []profile.Line{
|
||||
{
|
||||
Function: &f.f,
|
||||
Line: int64(pos.Line),
|
||||
},
|
||||
}
|
||||
|
||||
loc.Mapping = mapping
|
||||
pr.Location = append(pr.Location, loc)
|
||||
}
|
||||
}
|
||||
pb.addSamples(&pr, &pb.root)
|
||||
return &pr
|
||||
}
|
||||
|
||||
func (pb *profBuffer) addSamples(p *profile.Profile, n *profSampleNode) {
|
||||
if n.sample != nil {
|
||||
p.Sample = append(p.Sample, n.sample)
|
||||
}
|
||||
for _, child := range n.children {
|
||||
pb.addSamples(p, child)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *profiler) run() {
|
||||
ticker := time.NewTicker(profInterval)
|
||||
counter := 0
|
||||
L:
|
||||
for ts := range ticker.C {
|
||||
p.mu.Lock()
|
||||
left := len(p.trackers)
|
||||
for {
|
||||
// This loop runs until either one of the VMs is signalled or all of the VMs are scanned and found
|
||||
// busy or deleted.
|
||||
if counter >= len(p.trackers) {
|
||||
counter = 0
|
||||
}
|
||||
tracker := p.trackers[counter]
|
||||
req := atomic.LoadInt32(&tracker.req)
|
||||
if req == profReqSampleReady {
|
||||
if p.buf != nil {
|
||||
p.buf.addSample(tracker)
|
||||
}
|
||||
}
|
||||
if atomic.LoadInt32(&tracker.finished) != 0 {
|
||||
p.trackers[counter] = p.trackers[len(p.trackers)-1]
|
||||
p.trackers[len(p.trackers)-1] = nil
|
||||
p.trackers = p.trackers[:len(p.trackers)-1]
|
||||
if len(p.trackers) == 0 {
|
||||
break L
|
||||
}
|
||||
} else {
|
||||
counter++
|
||||
if p.buf != nil {
|
||||
if req != profReqDoSample {
|
||||
// signal the VM to take a sample
|
||||
tracker.start = ts
|
||||
atomic.StoreInt32(&tracker.req, profReqDoSample)
|
||||
break
|
||||
}
|
||||
} else {
|
||||
atomic.StoreInt32(&tracker.req, profReqStop)
|
||||
}
|
||||
}
|
||||
left--
|
||||
if left <= 0 {
|
||||
// all VMs are busy
|
||||
break
|
||||
}
|
||||
}
|
||||
p.mu.Unlock()
|
||||
}
|
||||
ticker.Stop()
|
||||
p.running = false
|
||||
p.mu.Unlock()
|
||||
}
|
||||
|
||||
func (p *profiler) registerVm() *profTracker {
|
||||
pt := new(profTracker)
|
||||
p.mu.Lock()
|
||||
p.trackers = append(p.trackers, pt)
|
||||
if !p.running {
|
||||
go p.run()
|
||||
p.running = true
|
||||
}
|
||||
p.mu.Unlock()
|
||||
return pt
|
||||
}
|
||||
|
||||
func (p *profiler) start() error {
|
||||
p.mu.Lock()
|
||||
if p.buf != nil {
|
||||
p.mu.Unlock()
|
||||
return errors.New("profiler is already active")
|
||||
}
|
||||
p.buf = new(profBuffer)
|
||||
p.mu.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *profiler) stop() *profile.Profile {
|
||||
p.mu.Lock()
|
||||
buf := p.buf
|
||||
p.buf = nil
|
||||
p.mu.Unlock()
|
||||
if buf != nil {
|
||||
return buf.profile()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
/*
|
||||
StartProfile enables execution time profiling for all Runtimes within the current process.
|
||||
This works similar to pprof.StartCPUProfile and produces the same format which can be consumed by `go tool pprof`.
|
||||
There are, however, a few notable differences. Firstly, it's not a CPU profile, rather "execution time" profile.
|
||||
It measures the time the VM spends executing an instruction. If this instruction happens to be a call to a
|
||||
blocking Go function, the waiting time will be measured. Secondly, the 'cpu' sample isn't simply `count*period`,
|
||||
it's the time interval between when sampling was requested and when the instruction has finished. If a VM is still
|
||||
executing the same instruction when the time comes for the next sample, the sampling is skipped (i.e. `count` doesn't
|
||||
grow).
|
||||
|
||||
If there are multiple functions with the same name, their names get a '.N' suffix, where N is a unique number,
|
||||
because otherwise the graph view merges them together (even if they are in different mappings). This includes
|
||||
"<anonymous>" functions.
|
||||
|
||||
The sampling period is set to 10ms.
|
||||
|
||||
It returns an error if profiling is already active.
|
||||
*/
|
||||
func StartProfile(w io.Writer) error {
|
||||
err := globalProfiler.p.start()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
globalProfiler.w = w
|
||||
atomic.StoreInt32(&globalProfiler.enabled, 1)
|
||||
return nil
|
||||
}
|
||||
|
||||
/*
|
||||
StopProfile stops the current profile initiated by StartProfile, if any.
|
||||
*/
|
||||
func StopProfile() {
|
||||
atomic.StoreInt32(&globalProfiler.enabled, 0)
|
||||
pr := globalProfiler.p.stop()
|
||||
if pr != nil {
|
||||
_ = pr.Write(globalProfiler.w)
|
||||
}
|
||||
globalProfiler.w = nil
|
||||
}
|
||||
1074
server/vendor/github.com/dop251/goja/proxy.go
generated
vendored
Normal file
1074
server/vendor/github.com/dop251/goja/proxy.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
643
server/vendor/github.com/dop251/goja/regexp.go
generated
vendored
Normal file
643
server/vendor/github.com/dop251/goja/regexp.go
generated
vendored
Normal file
@@ -0,0 +1,643 @@
|
||||
package goja
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/dlclark/regexp2"
|
||||
"github.com/dop251/goja/unistring"
|
||||
"io"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
"unicode/utf16"
|
||||
)
|
||||
|
||||
type regexp2MatchCache struct {
|
||||
target valueString
|
||||
runes []rune
|
||||
posMap []int
|
||||
}
|
||||
|
||||
// Not goroutine-safe. Use regexp2Wrapper.clone()
|
||||
type regexp2Wrapper struct {
|
||||
rx *regexp2.Regexp
|
||||
cache *regexp2MatchCache
|
||||
}
|
||||
|
||||
type regexpWrapper regexp.Regexp
|
||||
|
||||
type positionMapItem struct {
|
||||
src, dst int
|
||||
}
|
||||
type positionMap []positionMapItem
|
||||
|
||||
func (m positionMap) get(src int) int {
|
||||
if src <= 0 {
|
||||
return src
|
||||
}
|
||||
res := sort.Search(len(m), func(n int) bool { return m[n].src >= src })
|
||||
if res >= len(m) || m[res].src != src {
|
||||
panic("index not found")
|
||||
}
|
||||
return m[res].dst
|
||||
}
|
||||
|
||||
type arrayRuneReader struct {
|
||||
runes []rune
|
||||
pos int
|
||||
}
|
||||
|
||||
func (rd *arrayRuneReader) ReadRune() (r rune, size int, err error) {
|
||||
if rd.pos < len(rd.runes) {
|
||||
r = rd.runes[rd.pos]
|
||||
size = 1
|
||||
rd.pos++
|
||||
} else {
|
||||
err = io.EOF
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Not goroutine-safe. Use regexpPattern.clone()
|
||||
type regexpPattern struct {
|
||||
src string
|
||||
|
||||
global, ignoreCase, multiline, sticky, unicode bool
|
||||
|
||||
regexpWrapper *regexpWrapper
|
||||
regexp2Wrapper *regexp2Wrapper
|
||||
}
|
||||
|
||||
func compileRegexp2(src string, multiline, ignoreCase bool) (*regexp2Wrapper, error) {
|
||||
var opts regexp2.RegexOptions = regexp2.ECMAScript
|
||||
if multiline {
|
||||
opts |= regexp2.Multiline
|
||||
}
|
||||
if ignoreCase {
|
||||
opts |= regexp2.IgnoreCase
|
||||
}
|
||||
regexp2Pattern, err1 := regexp2.Compile(src, opts)
|
||||
if err1 != nil {
|
||||
return nil, fmt.Errorf("Invalid regular expression (regexp2): %s (%v)", src, err1)
|
||||
}
|
||||
|
||||
return ®exp2Wrapper{rx: regexp2Pattern}, nil
|
||||
}
|
||||
|
||||
func (p *regexpPattern) createRegexp2() {
|
||||
if p.regexp2Wrapper != nil {
|
||||
return
|
||||
}
|
||||
rx, err := compileRegexp2(p.src, p.multiline, p.ignoreCase)
|
||||
if err != nil {
|
||||
// At this point the regexp should have been successfully converted to re2, if it fails now, it's a bug.
|
||||
panic(err)
|
||||
}
|
||||
p.regexp2Wrapper = rx
|
||||
}
|
||||
|
||||
func buildUTF8PosMap(s unicodeString) (positionMap, string) {
|
||||
pm := make(positionMap, 0, s.length())
|
||||
rd := s.reader()
|
||||
sPos, utf8Pos := 0, 0
|
||||
var sb strings.Builder
|
||||
for {
|
||||
r, size, err := rd.ReadRune()
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
// the string contains invalid UTF-16, bailing out
|
||||
return nil, ""
|
||||
}
|
||||
utf8Size, _ := sb.WriteRune(r)
|
||||
sPos += size
|
||||
utf8Pos += utf8Size
|
||||
pm = append(pm, positionMapItem{src: utf8Pos, dst: sPos})
|
||||
}
|
||||
return pm, sb.String()
|
||||
}
|
||||
|
||||
func (p *regexpPattern) findSubmatchIndex(s valueString, start int) []int {
|
||||
if p.regexpWrapper == nil {
|
||||
return p.regexp2Wrapper.findSubmatchIndex(s, start, p.unicode, p.global || p.sticky)
|
||||
}
|
||||
if start != 0 {
|
||||
// Unfortunately Go's regexp library does not allow starting from an arbitrary position.
|
||||
// If we just drop the first _start_ characters of the string the assertions (^, $, \b and \B) will not
|
||||
// work correctly.
|
||||
p.createRegexp2()
|
||||
return p.regexp2Wrapper.findSubmatchIndex(s, start, p.unicode, p.global || p.sticky)
|
||||
}
|
||||
return p.regexpWrapper.findSubmatchIndex(s, p.unicode)
|
||||
}
|
||||
|
||||
func (p *regexpPattern) findAllSubmatchIndex(s valueString, start int, limit int, sticky bool) [][]int {
|
||||
if p.regexpWrapper == nil {
|
||||
return p.regexp2Wrapper.findAllSubmatchIndex(s, start, limit, sticky, p.unicode)
|
||||
}
|
||||
if start == 0 {
|
||||
a, u := devirtualizeString(s)
|
||||
if u == nil {
|
||||
return p.regexpWrapper.findAllSubmatchIndex(string(a), limit, sticky)
|
||||
}
|
||||
if limit == 1 {
|
||||
result := p.regexpWrapper.findSubmatchIndexUnicode(u, p.unicode)
|
||||
if result == nil {
|
||||
return nil
|
||||
}
|
||||
return [][]int{result}
|
||||
}
|
||||
// Unfortunately Go's regexp library lacks FindAllReaderSubmatchIndex(), so we have to use a UTF-8 string as an
|
||||
// input.
|
||||
if p.unicode {
|
||||
// Try to convert s to UTF-8. If it does not contain any invalid UTF-16 we can do the matching in UTF-8.
|
||||
pm, str := buildUTF8PosMap(u)
|
||||
if pm != nil {
|
||||
res := p.regexpWrapper.findAllSubmatchIndex(str, limit, sticky)
|
||||
for _, result := range res {
|
||||
for i, idx := range result {
|
||||
result[i] = pm.get(idx)
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p.createRegexp2()
|
||||
return p.regexp2Wrapper.findAllSubmatchIndex(s, start, limit, sticky, p.unicode)
|
||||
}
|
||||
|
||||
// clone creates a copy of the regexpPattern which can be used concurrently.
|
||||
func (p *regexpPattern) clone() *regexpPattern {
|
||||
ret := ®expPattern{
|
||||
src: p.src,
|
||||
global: p.global,
|
||||
ignoreCase: p.ignoreCase,
|
||||
multiline: p.multiline,
|
||||
sticky: p.sticky,
|
||||
unicode: p.unicode,
|
||||
}
|
||||
if p.regexpWrapper != nil {
|
||||
ret.regexpWrapper = p.regexpWrapper.clone()
|
||||
}
|
||||
if p.regexp2Wrapper != nil {
|
||||
ret.regexp2Wrapper = p.regexp2Wrapper.clone()
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
type regexpObject struct {
|
||||
baseObject
|
||||
pattern *regexpPattern
|
||||
source valueString
|
||||
|
||||
standard bool
|
||||
}
|
||||
|
||||
func (r *regexp2Wrapper) findSubmatchIndex(s valueString, start int, fullUnicode, doCache bool) (result []int) {
|
||||
if fullUnicode {
|
||||
return r.findSubmatchIndexUnicode(s, start, doCache)
|
||||
}
|
||||
return r.findSubmatchIndexUTF16(s, start, doCache)
|
||||
}
|
||||
|
||||
func (r *regexp2Wrapper) findUTF16Cached(s valueString, start int, doCache bool) (match *regexp2.Match, runes []rune, err error) {
|
||||
wrapped := r.rx
|
||||
cache := r.cache
|
||||
if cache != nil && cache.posMap == nil && cache.target.SameAs(s) {
|
||||
runes = cache.runes
|
||||
} else {
|
||||
runes = s.utf16Runes()
|
||||
cache = nil
|
||||
}
|
||||
match, err = wrapped.FindRunesMatchStartingAt(runes, start)
|
||||
if doCache && match != nil && err == nil {
|
||||
if cache == nil {
|
||||
if r.cache == nil {
|
||||
r.cache = new(regexp2MatchCache)
|
||||
}
|
||||
*r.cache = regexp2MatchCache{
|
||||
target: s,
|
||||
runes: runes,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
r.cache = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (r *regexp2Wrapper) findSubmatchIndexUTF16(s valueString, start int, doCache bool) (result []int) {
|
||||
match, _, err := r.findUTF16Cached(s, start, doCache)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if match == nil {
|
||||
return
|
||||
}
|
||||
groups := match.Groups()
|
||||
|
||||
result = make([]int, 0, len(groups)<<1)
|
||||
for _, group := range groups {
|
||||
if len(group.Captures) > 0 {
|
||||
result = append(result, group.Index, group.Index+group.Length)
|
||||
} else {
|
||||
result = append(result, -1, 0)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (r *regexp2Wrapper) findUnicodeCached(s valueString, start int, doCache bool) (match *regexp2.Match, posMap []int, err error) {
|
||||
var (
|
||||
runes []rune
|
||||
mappedStart int
|
||||
splitPair bool
|
||||
savedRune rune
|
||||
)
|
||||
wrapped := r.rx
|
||||
cache := r.cache
|
||||
if cache != nil && cache.posMap != nil && cache.target.SameAs(s) {
|
||||
runes, posMap = cache.runes, cache.posMap
|
||||
mappedStart, splitPair = posMapReverseLookup(posMap, start)
|
||||
} else {
|
||||
posMap, runes, mappedStart, splitPair = buildPosMap(&lenientUtf16Decoder{utf16Reader: s.utf16Reader()}, s.length(), start)
|
||||
cache = nil
|
||||
}
|
||||
if splitPair {
|
||||
// temporarily set the rune at mappedStart to the second code point of the pair
|
||||
_, second := utf16.EncodeRune(runes[mappedStart])
|
||||
savedRune, runes[mappedStart] = runes[mappedStart], second
|
||||
}
|
||||
match, err = wrapped.FindRunesMatchStartingAt(runes, mappedStart)
|
||||
if doCache && match != nil && err == nil {
|
||||
if splitPair {
|
||||
runes[mappedStart] = savedRune
|
||||
}
|
||||
if cache == nil {
|
||||
if r.cache == nil {
|
||||
r.cache = new(regexp2MatchCache)
|
||||
}
|
||||
*r.cache = regexp2MatchCache{
|
||||
target: s,
|
||||
runes: runes,
|
||||
posMap: posMap,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
r.cache = nil
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (r *regexp2Wrapper) findSubmatchIndexUnicode(s valueString, start int, doCache bool) (result []int) {
|
||||
match, posMap, err := r.findUnicodeCached(s, start, doCache)
|
||||
if match == nil || err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
groups := match.Groups()
|
||||
|
||||
result = make([]int, 0, len(groups)<<1)
|
||||
for _, group := range groups {
|
||||
if len(group.Captures) > 0 {
|
||||
result = append(result, posMap[group.Index], posMap[group.Index+group.Length])
|
||||
} else {
|
||||
result = append(result, -1, 0)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (r *regexp2Wrapper) findAllSubmatchIndexUTF16(s valueString, start, limit int, sticky bool) [][]int {
|
||||
wrapped := r.rx
|
||||
match, runes, err := r.findUTF16Cached(s, start, false)
|
||||
if match == nil || err != nil {
|
||||
return nil
|
||||
}
|
||||
if limit < 0 {
|
||||
limit = len(runes) + 1
|
||||
}
|
||||
results := make([][]int, 0, limit)
|
||||
for match != nil {
|
||||
groups := match.Groups()
|
||||
|
||||
result := make([]int, 0, len(groups)<<1)
|
||||
|
||||
for _, group := range groups {
|
||||
if len(group.Captures) > 0 {
|
||||
startPos := group.Index
|
||||
endPos := group.Index + group.Length
|
||||
result = append(result, startPos, endPos)
|
||||
} else {
|
||||
result = append(result, -1, 0)
|
||||
}
|
||||
}
|
||||
|
||||
if sticky && len(result) > 1 {
|
||||
if result[0] != start {
|
||||
break
|
||||
}
|
||||
start = result[1]
|
||||
}
|
||||
|
||||
results = append(results, result)
|
||||
limit--
|
||||
if limit <= 0 {
|
||||
break
|
||||
}
|
||||
match, err = wrapped.FindNextMatch(match)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return results
|
||||
}
|
||||
|
||||
func buildPosMap(rd io.RuneReader, l, start int) (posMap []int, runes []rune, mappedStart int, splitPair bool) {
|
||||
posMap = make([]int, 0, l+1)
|
||||
curPos := 0
|
||||
runes = make([]rune, 0, l)
|
||||
startFound := false
|
||||
for {
|
||||
if !startFound {
|
||||
if curPos == start {
|
||||
mappedStart = len(runes)
|
||||
startFound = true
|
||||
}
|
||||
if curPos > start {
|
||||
// start position splits a surrogate pair
|
||||
mappedStart = len(runes) - 1
|
||||
splitPair = true
|
||||
startFound = true
|
||||
}
|
||||
}
|
||||
rn, size, err := rd.ReadRune()
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
runes = append(runes, rn)
|
||||
posMap = append(posMap, curPos)
|
||||
curPos += size
|
||||
}
|
||||
posMap = append(posMap, curPos)
|
||||
return
|
||||
}
|
||||
|
||||
func posMapReverseLookup(posMap []int, pos int) (int, bool) {
|
||||
mapped := sort.SearchInts(posMap, pos)
|
||||
if mapped < len(posMap) && posMap[mapped] != pos {
|
||||
return mapped - 1, true
|
||||
}
|
||||
return mapped, false
|
||||
}
|
||||
|
||||
func (r *regexp2Wrapper) findAllSubmatchIndexUnicode(s unicodeString, start, limit int, sticky bool) [][]int {
|
||||
wrapped := r.rx
|
||||
if limit < 0 {
|
||||
limit = len(s) + 1
|
||||
}
|
||||
results := make([][]int, 0, limit)
|
||||
match, posMap, err := r.findUnicodeCached(s, start, false)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
for match != nil {
|
||||
groups := match.Groups()
|
||||
|
||||
result := make([]int, 0, len(groups)<<1)
|
||||
|
||||
for _, group := range groups {
|
||||
if len(group.Captures) > 0 {
|
||||
start := posMap[group.Index]
|
||||
end := posMap[group.Index+group.Length]
|
||||
result = append(result, start, end)
|
||||
} else {
|
||||
result = append(result, -1, 0)
|
||||
}
|
||||
}
|
||||
|
||||
if sticky && len(result) > 1 {
|
||||
if result[0] != start {
|
||||
break
|
||||
}
|
||||
start = result[1]
|
||||
}
|
||||
|
||||
results = append(results, result)
|
||||
match, err = wrapped.FindNextMatch(match)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return results
|
||||
}
|
||||
|
||||
func (r *regexp2Wrapper) findAllSubmatchIndex(s valueString, start, limit int, sticky, fullUnicode bool) [][]int {
|
||||
a, u := devirtualizeString(s)
|
||||
if u != nil {
|
||||
if fullUnicode {
|
||||
return r.findAllSubmatchIndexUnicode(u, start, limit, sticky)
|
||||
}
|
||||
return r.findAllSubmatchIndexUTF16(u, start, limit, sticky)
|
||||
}
|
||||
return r.findAllSubmatchIndexUTF16(a, start, limit, sticky)
|
||||
}
|
||||
|
||||
func (r *regexp2Wrapper) clone() *regexp2Wrapper {
|
||||
return ®exp2Wrapper{
|
||||
rx: r.rx,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *regexpWrapper) findAllSubmatchIndex(s string, limit int, sticky bool) (results [][]int) {
|
||||
wrapped := (*regexp.Regexp)(r)
|
||||
results = wrapped.FindAllStringSubmatchIndex(s, limit)
|
||||
pos := 0
|
||||
if sticky {
|
||||
for i, result := range results {
|
||||
if len(result) > 1 {
|
||||
if result[0] != pos {
|
||||
return results[:i]
|
||||
}
|
||||
pos = result[1]
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (r *regexpWrapper) findSubmatchIndex(s valueString, fullUnicode bool) []int {
|
||||
a, u := devirtualizeString(s)
|
||||
if u != nil {
|
||||
return r.findSubmatchIndexUnicode(u, fullUnicode)
|
||||
}
|
||||
return r.findSubmatchIndexASCII(string(a))
|
||||
}
|
||||
|
||||
func (r *regexpWrapper) findSubmatchIndexASCII(s string) []int {
|
||||
wrapped := (*regexp.Regexp)(r)
|
||||
return wrapped.FindStringSubmatchIndex(s)
|
||||
}
|
||||
|
||||
func (r *regexpWrapper) findSubmatchIndexUnicode(s unicodeString, fullUnicode bool) (result []int) {
|
||||
wrapped := (*regexp.Regexp)(r)
|
||||
if fullUnicode {
|
||||
posMap, runes, _, _ := buildPosMap(&lenientUtf16Decoder{utf16Reader: s.utf16Reader()}, s.length(), 0)
|
||||
res := wrapped.FindReaderSubmatchIndex(&arrayRuneReader{runes: runes})
|
||||
for i, item := range res {
|
||||
if item >= 0 {
|
||||
res[i] = posMap[item]
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
return wrapped.FindReaderSubmatchIndex(s.utf16Reader())
|
||||
}
|
||||
|
||||
func (r *regexpWrapper) clone() *regexpWrapper {
|
||||
return r
|
||||
}
|
||||
|
||||
func (r *regexpObject) execResultToArray(target valueString, result []int) Value {
|
||||
captureCount := len(result) >> 1
|
||||
valueArray := make([]Value, captureCount)
|
||||
matchIndex := result[0]
|
||||
valueArray[0] = target.substring(result[0], result[1])
|
||||
lowerBound := 0
|
||||
for index := 1; index < captureCount; index++ {
|
||||
offset := index << 1
|
||||
if result[offset] >= 0 && result[offset+1] >= lowerBound {
|
||||
valueArray[index] = target.substring(result[offset], result[offset+1])
|
||||
lowerBound = result[offset]
|
||||
} else {
|
||||
valueArray[index] = _undefined
|
||||
}
|
||||
}
|
||||
match := r.val.runtime.newArrayValues(valueArray)
|
||||
match.self.setOwnStr("input", target, false)
|
||||
match.self.setOwnStr("index", intToValue(int64(matchIndex)), false)
|
||||
return match
|
||||
}
|
||||
|
||||
func (r *regexpObject) getLastIndex() int64 {
|
||||
lastIndex := toLength(r.getStr("lastIndex", nil))
|
||||
if !r.pattern.global && !r.pattern.sticky {
|
||||
return 0
|
||||
}
|
||||
return lastIndex
|
||||
}
|
||||
|
||||
func (r *regexpObject) updateLastIndex(index int64, firstResult, lastResult []int) bool {
|
||||
if r.pattern.sticky {
|
||||
if firstResult == nil || int64(firstResult[0]) != index {
|
||||
r.setOwnStr("lastIndex", intToValue(0), true)
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
if firstResult == nil {
|
||||
if r.pattern.global {
|
||||
r.setOwnStr("lastIndex", intToValue(0), true)
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if r.pattern.global || r.pattern.sticky {
|
||||
r.setOwnStr("lastIndex", intToValue(int64(lastResult[1])), true)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (r *regexpObject) execRegexp(target valueString) (match bool, result []int) {
|
||||
index := r.getLastIndex()
|
||||
if index >= 0 && index <= int64(target.length()) {
|
||||
result = r.pattern.findSubmatchIndex(target, int(index))
|
||||
}
|
||||
match = r.updateLastIndex(index, result, result)
|
||||
return
|
||||
}
|
||||
|
||||
func (r *regexpObject) exec(target valueString) Value {
|
||||
match, result := r.execRegexp(target)
|
||||
if match {
|
||||
return r.execResultToArray(target, result)
|
||||
}
|
||||
return _null
|
||||
}
|
||||
|
||||
func (r *regexpObject) test(target valueString) bool {
|
||||
match, _ := r.execRegexp(target)
|
||||
return match
|
||||
}
|
||||
|
||||
func (r *regexpObject) clone() *regexpObject {
|
||||
r1 := r.val.runtime.newRegexpObject(r.prototype)
|
||||
r1.source = r.source
|
||||
r1.pattern = r.pattern
|
||||
|
||||
return r1
|
||||
}
|
||||
|
||||
func (r *regexpObject) init() {
|
||||
r.baseObject.init()
|
||||
r.standard = true
|
||||
r._putProp("lastIndex", intToValue(0), true, false, false)
|
||||
}
|
||||
|
||||
func (r *regexpObject) setProto(proto *Object, throw bool) bool {
|
||||
res := r.baseObject.setProto(proto, throw)
|
||||
if res {
|
||||
r.standard = false
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (r *regexpObject) defineOwnPropertyStr(name unistring.String, desc PropertyDescriptor, throw bool) bool {
|
||||
res := r.baseObject.defineOwnPropertyStr(name, desc, throw)
|
||||
if res {
|
||||
r.standard = false
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (r *regexpObject) defineOwnPropertySym(name *Symbol, desc PropertyDescriptor, throw bool) bool {
|
||||
res := r.baseObject.defineOwnPropertySym(name, desc, throw)
|
||||
if res && r.standard {
|
||||
switch name {
|
||||
case SymMatch, SymMatchAll, SymSearch, SymSplit, SymReplace:
|
||||
r.standard = false
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (r *regexpObject) deleteStr(name unistring.String, throw bool) bool {
|
||||
res := r.baseObject.deleteStr(name, throw)
|
||||
if res {
|
||||
r.standard = false
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (r *regexpObject) setOwnStr(name unistring.String, value Value, throw bool) bool {
|
||||
res := r.baseObject.setOwnStr(name, value, throw)
|
||||
if res && r.standard && name == "exec" {
|
||||
r.standard = false
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (r *regexpObject) setOwnSym(name *Symbol, value Value, throw bool) bool {
|
||||
res := r.baseObject.setOwnSym(name, value, throw)
|
||||
if res && r.standard {
|
||||
switch name {
|
||||
case SymMatch, SymMatchAll, SymSearch, SymSplit, SymReplace:
|
||||
r.standard = false
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
3184
server/vendor/github.com/dop251/goja/runtime.go
generated
vendored
Normal file
3184
server/vendor/github.com/dop251/goja/runtime.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
server/vendor/github.com/dop251/goja/staticcheck.conf
generated
vendored
Normal file
1
server/vendor/github.com/dop251/goja/staticcheck.conf
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
checks = ["all", "-ST1000", "-ST1003", "-ST1005", "-ST1006", "-ST1012", "-ST1021", "-ST1020", "-ST1008"]
|
||||
329
server/vendor/github.com/dop251/goja/string.go
generated
vendored
Normal file
329
server/vendor/github.com/dop251/goja/string.go
generated
vendored
Normal file
@@ -0,0 +1,329 @@
|
||||
package goja
|
||||
|
||||
import (
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/dop251/goja/unistring"
|
||||
)
|
||||
|
||||
const (
|
||||
__proto__ = "__proto__"
|
||||
)
|
||||
|
||||
var (
|
||||
stringTrue valueString = asciiString("true")
|
||||
stringFalse valueString = asciiString("false")
|
||||
stringNull valueString = asciiString("null")
|
||||
stringUndefined valueString = asciiString("undefined")
|
||||
stringObjectC valueString = asciiString("object")
|
||||
stringFunction valueString = asciiString("function")
|
||||
stringBoolean valueString = asciiString("boolean")
|
||||
stringString valueString = asciiString("string")
|
||||
stringSymbol valueString = asciiString("symbol")
|
||||
stringNumber valueString = asciiString("number")
|
||||
stringNaN valueString = asciiString("NaN")
|
||||
stringInfinity = asciiString("Infinity")
|
||||
stringNegInfinity = asciiString("-Infinity")
|
||||
stringBound_ valueString = asciiString("bound ")
|
||||
stringEmpty valueString = asciiString("")
|
||||
|
||||
stringError valueString = asciiString("Error")
|
||||
stringAggregateError valueString = asciiString("AggregateError")
|
||||
stringTypeError valueString = asciiString("TypeError")
|
||||
stringReferenceError valueString = asciiString("ReferenceError")
|
||||
stringSyntaxError valueString = asciiString("SyntaxError")
|
||||
stringRangeError valueString = asciiString("RangeError")
|
||||
stringEvalError valueString = asciiString("EvalError")
|
||||
stringURIError valueString = asciiString("URIError")
|
||||
stringGoError valueString = asciiString("GoError")
|
||||
|
||||
stringObjectNull valueString = asciiString("[object Null]")
|
||||
stringObjectUndefined valueString = asciiString("[object Undefined]")
|
||||
stringInvalidDate valueString = asciiString("Invalid Date")
|
||||
)
|
||||
|
||||
type valueString interface {
|
||||
Value
|
||||
charAt(int) rune
|
||||
length() int
|
||||
concat(valueString) valueString
|
||||
substring(start, end int) valueString
|
||||
compareTo(valueString) int
|
||||
reader() io.RuneReader
|
||||
utf16Reader() io.RuneReader
|
||||
utf16Runes() []rune
|
||||
index(valueString, int) int
|
||||
lastIndex(valueString, int) int
|
||||
toLower() valueString
|
||||
toUpper() valueString
|
||||
toTrimmedUTF8() string
|
||||
}
|
||||
|
||||
type stringIterObject struct {
|
||||
baseObject
|
||||
reader io.RuneReader
|
||||
}
|
||||
|
||||
func isUTF16FirstSurrogate(r rune) bool {
|
||||
return r >= 0xD800 && r <= 0xDBFF
|
||||
}
|
||||
|
||||
func isUTF16SecondSurrogate(r rune) bool {
|
||||
return r >= 0xDC00 && r <= 0xDFFF
|
||||
}
|
||||
|
||||
func (si *stringIterObject) next() Value {
|
||||
if si.reader == nil {
|
||||
return si.val.runtime.createIterResultObject(_undefined, true)
|
||||
}
|
||||
r, _, err := si.reader.ReadRune()
|
||||
if err == io.EOF {
|
||||
si.reader = nil
|
||||
return si.val.runtime.createIterResultObject(_undefined, true)
|
||||
}
|
||||
return si.val.runtime.createIterResultObject(stringFromRune(r), false)
|
||||
}
|
||||
|
||||
func stringFromRune(r rune) valueString {
|
||||
if r < utf8.RuneSelf {
|
||||
var sb strings.Builder
|
||||
sb.WriteByte(byte(r))
|
||||
return asciiString(sb.String())
|
||||
}
|
||||
var sb unicodeStringBuilder
|
||||
sb.WriteRune(r)
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
func (r *Runtime) createStringIterator(s valueString) Value {
|
||||
o := &Object{runtime: r}
|
||||
|
||||
si := &stringIterObject{
|
||||
reader: &lenientUtf16Decoder{utf16Reader: s.utf16Reader()},
|
||||
}
|
||||
si.class = classObject
|
||||
si.val = o
|
||||
si.extensible = true
|
||||
o.self = si
|
||||
si.prototype = r.getStringIteratorPrototype()
|
||||
si.init()
|
||||
|
||||
return o
|
||||
}
|
||||
|
||||
type stringObject struct {
|
||||
baseObject
|
||||
value valueString
|
||||
length int
|
||||
lengthProp valueProperty
|
||||
}
|
||||
|
||||
func newStringValue(s string) valueString {
|
||||
if u := unistring.Scan(s); u != nil {
|
||||
return unicodeString(u)
|
||||
}
|
||||
return asciiString(s)
|
||||
}
|
||||
|
||||
func stringValueFromRaw(raw unistring.String) valueString {
|
||||
if b := raw.AsUtf16(); b != nil {
|
||||
return unicodeString(b)
|
||||
}
|
||||
return asciiString(raw)
|
||||
}
|
||||
|
||||
func (s *stringObject) init() {
|
||||
s.baseObject.init()
|
||||
s.setLength()
|
||||
}
|
||||
|
||||
func (s *stringObject) setLength() {
|
||||
if s.value != nil {
|
||||
s.length = s.value.length()
|
||||
}
|
||||
s.lengthProp.value = intToValue(int64(s.length))
|
||||
s._put("length", &s.lengthProp)
|
||||
}
|
||||
|
||||
func (s *stringObject) getStr(name unistring.String, receiver Value) Value {
|
||||
if i := strToGoIdx(name); i >= 0 && i < s.length {
|
||||
return s._getIdx(i)
|
||||
}
|
||||
return s.baseObject.getStr(name, receiver)
|
||||
}
|
||||
|
||||
func (s *stringObject) getIdx(idx valueInt, receiver Value) Value {
|
||||
i := int(idx)
|
||||
if i >= 0 && i < s.length {
|
||||
return s._getIdx(i)
|
||||
}
|
||||
return s.baseObject.getStr(idx.string(), receiver)
|
||||
}
|
||||
|
||||
func (s *stringObject) getOwnPropStr(name unistring.String) Value {
|
||||
if i := strToGoIdx(name); i >= 0 && i < s.length {
|
||||
val := s._getIdx(i)
|
||||
return &valueProperty{
|
||||
value: val,
|
||||
enumerable: true,
|
||||
}
|
||||
}
|
||||
|
||||
return s.baseObject.getOwnPropStr(name)
|
||||
}
|
||||
|
||||
func (s *stringObject) getOwnPropIdx(idx valueInt) Value {
|
||||
i := int64(idx)
|
||||
if i >= 0 {
|
||||
if i < int64(s.length) {
|
||||
val := s._getIdx(int(i))
|
||||
return &valueProperty{
|
||||
value: val,
|
||||
enumerable: true,
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
return s.baseObject.getOwnPropStr(idx.string())
|
||||
}
|
||||
|
||||
func (s *stringObject) _getIdx(idx int) Value {
|
||||
return s.value.substring(idx, idx+1)
|
||||
}
|
||||
|
||||
func (s *stringObject) setOwnStr(name unistring.String, val Value, throw bool) bool {
|
||||
if i := strToGoIdx(name); i >= 0 && i < s.length {
|
||||
s.val.runtime.typeErrorResult(throw, "Cannot assign to read only property '%d' of a String", i)
|
||||
return false
|
||||
}
|
||||
|
||||
return s.baseObject.setOwnStr(name, val, throw)
|
||||
}
|
||||
|
||||
func (s *stringObject) setOwnIdx(idx valueInt, val Value, throw bool) bool {
|
||||
i := int64(idx)
|
||||
if i >= 0 && i < int64(s.length) {
|
||||
s.val.runtime.typeErrorResult(throw, "Cannot assign to read only property '%d' of a String", i)
|
||||
return false
|
||||
}
|
||||
|
||||
return s.baseObject.setOwnStr(idx.string(), val, throw)
|
||||
}
|
||||
|
||||
func (s *stringObject) setForeignStr(name unistring.String, val, receiver Value, throw bool) (bool, bool) {
|
||||
return s._setForeignStr(name, s.getOwnPropStr(name), val, receiver, throw)
|
||||
}
|
||||
|
||||
func (s *stringObject) setForeignIdx(idx valueInt, val, receiver Value, throw bool) (bool, bool) {
|
||||
return s._setForeignIdx(idx, s.getOwnPropIdx(idx), val, receiver, throw)
|
||||
}
|
||||
|
||||
func (s *stringObject) defineOwnPropertyStr(name unistring.String, descr PropertyDescriptor, throw bool) bool {
|
||||
if i := strToGoIdx(name); i >= 0 && i < s.length {
|
||||
_, ok := s._defineOwnProperty(name, &valueProperty{enumerable: true}, descr, throw)
|
||||
return ok
|
||||
}
|
||||
|
||||
return s.baseObject.defineOwnPropertyStr(name, descr, throw)
|
||||
}
|
||||
|
||||
func (s *stringObject) defineOwnPropertyIdx(idx valueInt, descr PropertyDescriptor, throw bool) bool {
|
||||
i := int64(idx)
|
||||
if i >= 0 && i < int64(s.length) {
|
||||
s.val.runtime.typeErrorResult(throw, "Cannot redefine property: %d", i)
|
||||
return false
|
||||
}
|
||||
|
||||
return s.baseObject.defineOwnPropertyStr(idx.string(), descr, throw)
|
||||
}
|
||||
|
||||
type stringPropIter struct {
|
||||
str valueString // separate, because obj can be the singleton
|
||||
obj *stringObject
|
||||
idx, length int
|
||||
}
|
||||
|
||||
func (i *stringPropIter) next() (propIterItem, iterNextFunc) {
|
||||
if i.idx < i.length {
|
||||
name := strconv.Itoa(i.idx)
|
||||
i.idx++
|
||||
return propIterItem{name: asciiString(name), enumerable: _ENUM_TRUE}, i.next
|
||||
}
|
||||
|
||||
return i.obj.baseObject.iterateStringKeys()()
|
||||
}
|
||||
|
||||
func (s *stringObject) iterateStringKeys() iterNextFunc {
|
||||
return (&stringPropIter{
|
||||
str: s.value,
|
||||
obj: s,
|
||||
length: s.length,
|
||||
}).next
|
||||
}
|
||||
|
||||
func (s *stringObject) stringKeys(all bool, accum []Value) []Value {
|
||||
for i := 0; i < s.length; i++ {
|
||||
accum = append(accum, asciiString(strconv.Itoa(i)))
|
||||
}
|
||||
|
||||
return s.baseObject.stringKeys(all, accum)
|
||||
}
|
||||
|
||||
func (s *stringObject) deleteStr(name unistring.String, throw bool) bool {
|
||||
if i := strToGoIdx(name); i >= 0 && i < s.length {
|
||||
s.val.runtime.typeErrorResult(throw, "Cannot delete property '%d' of a String", i)
|
||||
return false
|
||||
}
|
||||
|
||||
return s.baseObject.deleteStr(name, throw)
|
||||
}
|
||||
|
||||
func (s *stringObject) deleteIdx(idx valueInt, throw bool) bool {
|
||||
i := int64(idx)
|
||||
if i >= 0 && i < int64(s.length) {
|
||||
s.val.runtime.typeErrorResult(throw, "Cannot delete property '%d' of a String", i)
|
||||
return false
|
||||
}
|
||||
|
||||
return s.baseObject.deleteStr(idx.string(), throw)
|
||||
}
|
||||
|
||||
func (s *stringObject) hasOwnPropertyStr(name unistring.String) bool {
|
||||
if i := strToGoIdx(name); i >= 0 && i < s.length {
|
||||
return true
|
||||
}
|
||||
return s.baseObject.hasOwnPropertyStr(name)
|
||||
}
|
||||
|
||||
func (s *stringObject) hasOwnPropertyIdx(idx valueInt) bool {
|
||||
i := int64(idx)
|
||||
if i >= 0 && i < int64(s.length) {
|
||||
return true
|
||||
}
|
||||
return s.baseObject.hasOwnPropertyStr(idx.string())
|
||||
}
|
||||
|
||||
func devirtualizeString(s valueString) (asciiString, unicodeString) {
|
||||
switch s := s.(type) {
|
||||
case asciiString:
|
||||
return s, nil
|
||||
case unicodeString:
|
||||
return "", s
|
||||
case *importedString:
|
||||
s.ensureScanned()
|
||||
if s.u != nil {
|
||||
return "", s.u
|
||||
}
|
||||
return asciiString(s.s), nil
|
||||
default:
|
||||
panic(unknownStringTypeErr(s))
|
||||
}
|
||||
}
|
||||
|
||||
func unknownStringTypeErr(v Value) interface{} {
|
||||
return newTypeError("Internal bug: unknown string type: %T", v)
|
||||
}
|
||||
327
server/vendor/github.com/dop251/goja/string_ascii.go
generated
vendored
Normal file
327
server/vendor/github.com/dop251/goja/string_ascii.go
generated
vendored
Normal file
@@ -0,0 +1,327 @@
|
||||
package goja
|
||||
|
||||
import (
|
||||
"hash/maphash"
|
||||
"io"
|
||||
"math"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/dop251/goja/unistring"
|
||||
)
|
||||
|
||||
type asciiString string
|
||||
|
||||
type asciiRuneReader struct {
|
||||
s asciiString
|
||||
pos int
|
||||
}
|
||||
|
||||
func (rr *asciiRuneReader) ReadRune() (r rune, size int, err error) {
|
||||
if rr.pos < len(rr.s) {
|
||||
r = rune(rr.s[rr.pos])
|
||||
size = 1
|
||||
rr.pos++
|
||||
} else {
|
||||
err = io.EOF
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s asciiString) reader() io.RuneReader {
|
||||
return &asciiRuneReader{
|
||||
s: s,
|
||||
}
|
||||
}
|
||||
|
||||
func (s asciiString) utf16Reader() io.RuneReader {
|
||||
return s.reader()
|
||||
}
|
||||
|
||||
func (s asciiString) utf16Runes() []rune {
|
||||
runes := make([]rune, len(s))
|
||||
for i := 0; i < len(s); i++ {
|
||||
runes[i] = rune(s[i])
|
||||
}
|
||||
return runes
|
||||
}
|
||||
|
||||
// ss must be trimmed
|
||||
func stringToInt(ss string) (int64, error) {
|
||||
if ss == "" {
|
||||
return 0, nil
|
||||
}
|
||||
if ss == "-0" {
|
||||
return 0, strconv.ErrSyntax
|
||||
}
|
||||
if len(ss) > 2 {
|
||||
switch ss[:2] {
|
||||
case "0x", "0X":
|
||||
return strconv.ParseInt(ss[2:], 16, 64)
|
||||
case "0b", "0B":
|
||||
return strconv.ParseInt(ss[2:], 2, 64)
|
||||
case "0o", "0O":
|
||||
return strconv.ParseInt(ss[2:], 8, 64)
|
||||
}
|
||||
}
|
||||
return strconv.ParseInt(ss, 10, 64)
|
||||
}
|
||||
|
||||
func (s asciiString) _toInt() (int64, error) {
|
||||
return stringToInt(strings.TrimSpace(string(s)))
|
||||
}
|
||||
|
||||
func isRangeErr(err error) bool {
|
||||
if err, ok := err.(*strconv.NumError); ok {
|
||||
return err.Err == strconv.ErrRange
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (s asciiString) _toFloat() (float64, error) {
|
||||
ss := strings.TrimSpace(string(s))
|
||||
if ss == "" {
|
||||
return 0, nil
|
||||
}
|
||||
if ss == "-0" {
|
||||
var f float64
|
||||
return -f, nil
|
||||
}
|
||||
f, err := strconv.ParseFloat(ss, 64)
|
||||
if isRangeErr(err) {
|
||||
err = nil
|
||||
}
|
||||
return f, err
|
||||
}
|
||||
|
||||
func (s asciiString) ToInteger() int64 {
|
||||
if s == "" {
|
||||
return 0
|
||||
}
|
||||
if s == "Infinity" || s == "+Infinity" {
|
||||
return math.MaxInt64
|
||||
}
|
||||
if s == "-Infinity" {
|
||||
return math.MinInt64
|
||||
}
|
||||
i, err := s._toInt()
|
||||
if err != nil {
|
||||
f, err := s._toFloat()
|
||||
if err == nil {
|
||||
return int64(f)
|
||||
}
|
||||
}
|
||||
return i
|
||||
}
|
||||
|
||||
func (s asciiString) toString() valueString {
|
||||
return s
|
||||
}
|
||||
|
||||
func (s asciiString) ToString() Value {
|
||||
return s
|
||||
}
|
||||
|
||||
func (s asciiString) String() string {
|
||||
return string(s)
|
||||
}
|
||||
|
||||
func (s asciiString) ToFloat() float64 {
|
||||
if s == "" {
|
||||
return 0
|
||||
}
|
||||
if s == "Infinity" || s == "+Infinity" {
|
||||
return math.Inf(1)
|
||||
}
|
||||
if s == "-Infinity" {
|
||||
return math.Inf(-1)
|
||||
}
|
||||
f, err := s._toFloat()
|
||||
if err != nil {
|
||||
i, err := s._toInt()
|
||||
if err == nil {
|
||||
return float64(i)
|
||||
}
|
||||
f = math.NaN()
|
||||
}
|
||||
return f
|
||||
}
|
||||
|
||||
func (s asciiString) ToBoolean() bool {
|
||||
return s != ""
|
||||
}
|
||||
|
||||
func (s asciiString) ToNumber() Value {
|
||||
if s == "" {
|
||||
return intToValue(0)
|
||||
}
|
||||
if s == "Infinity" || s == "+Infinity" {
|
||||
return _positiveInf
|
||||
}
|
||||
if s == "-Infinity" {
|
||||
return _negativeInf
|
||||
}
|
||||
|
||||
if i, err := s._toInt(); err == nil {
|
||||
return intToValue(i)
|
||||
}
|
||||
|
||||
if f, err := s._toFloat(); err == nil {
|
||||
return floatToValue(f)
|
||||
}
|
||||
|
||||
return _NaN
|
||||
}
|
||||
|
||||
func (s asciiString) ToObject(r *Runtime) *Object {
|
||||
return r._newString(s, r.global.StringPrototype)
|
||||
}
|
||||
|
||||
func (s asciiString) SameAs(other Value) bool {
|
||||
return s.StrictEquals(other)
|
||||
}
|
||||
|
||||
func (s asciiString) Equals(other Value) bool {
|
||||
if s.StrictEquals(other) {
|
||||
return true
|
||||
}
|
||||
|
||||
if o, ok := other.(valueInt); ok {
|
||||
if o1, e := s._toInt(); e == nil {
|
||||
return o1 == int64(o)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
if o, ok := other.(valueFloat); ok {
|
||||
return s.ToFloat() == float64(o)
|
||||
}
|
||||
|
||||
if o, ok := other.(valueBool); ok {
|
||||
if o1, e := s._toFloat(); e == nil {
|
||||
return o1 == o.ToFloat()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
if o, ok := other.(*Object); ok {
|
||||
return s.Equals(o.toPrimitive())
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (s asciiString) StrictEquals(other Value) bool {
|
||||
if otherStr, ok := other.(asciiString); ok {
|
||||
return s == otherStr
|
||||
}
|
||||
if otherStr, ok := other.(*importedString); ok {
|
||||
if otherStr.u == nil {
|
||||
return string(s) == otherStr.s
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (s asciiString) baseObject(r *Runtime) *Object {
|
||||
ss := r.stringSingleton
|
||||
ss.value = s
|
||||
ss.setLength()
|
||||
return ss.val
|
||||
}
|
||||
|
||||
func (s asciiString) hash(hash *maphash.Hash) uint64 {
|
||||
_, _ = hash.WriteString(string(s))
|
||||
h := hash.Sum64()
|
||||
hash.Reset()
|
||||
return h
|
||||
}
|
||||
|
||||
func (s asciiString) charAt(idx int) rune {
|
||||
return rune(s[idx])
|
||||
}
|
||||
|
||||
func (s asciiString) length() int {
|
||||
return len(s)
|
||||
}
|
||||
|
||||
func (s asciiString) concat(other valueString) valueString {
|
||||
a, u := devirtualizeString(other)
|
||||
if u != nil {
|
||||
b := make([]uint16, len(s)+len(u))
|
||||
b[0] = unistring.BOM
|
||||
for i := 0; i < len(s); i++ {
|
||||
b[i+1] = uint16(s[i])
|
||||
}
|
||||
copy(b[len(s)+1:], u[1:])
|
||||
return unicodeString(b)
|
||||
}
|
||||
return s + a
|
||||
}
|
||||
|
||||
func (s asciiString) substring(start, end int) valueString {
|
||||
return s[start:end]
|
||||
}
|
||||
|
||||
func (s asciiString) compareTo(other valueString) int {
|
||||
switch other := other.(type) {
|
||||
case asciiString:
|
||||
return strings.Compare(string(s), string(other))
|
||||
case unicodeString:
|
||||
return strings.Compare(string(s), other.String())
|
||||
case *importedString:
|
||||
return strings.Compare(string(s), other.s)
|
||||
default:
|
||||
panic(newTypeError("Internal bug: unknown string type: %T", other))
|
||||
}
|
||||
}
|
||||
|
||||
func (s asciiString) index(substr valueString, start int) int {
|
||||
a, u := devirtualizeString(substr)
|
||||
if u == nil {
|
||||
p := strings.Index(string(s[start:]), string(a))
|
||||
if p >= 0 {
|
||||
return p + start
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
func (s asciiString) lastIndex(substr valueString, pos int) int {
|
||||
a, u := devirtualizeString(substr)
|
||||
if u == nil {
|
||||
end := pos + len(a)
|
||||
var ss string
|
||||
if end > len(s) {
|
||||
ss = string(s)
|
||||
} else {
|
||||
ss = string(s[:end])
|
||||
}
|
||||
return strings.LastIndex(ss, string(a))
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
func (s asciiString) toLower() valueString {
|
||||
return asciiString(strings.ToLower(string(s)))
|
||||
}
|
||||
|
||||
func (s asciiString) toUpper() valueString {
|
||||
return asciiString(strings.ToUpper(string(s)))
|
||||
}
|
||||
|
||||
func (s asciiString) toTrimmedUTF8() string {
|
||||
return strings.TrimSpace(string(s))
|
||||
}
|
||||
|
||||
func (s asciiString) string() unistring.String {
|
||||
return unistring.String(s)
|
||||
}
|
||||
|
||||
func (s asciiString) Export() interface{} {
|
||||
return string(s)
|
||||
}
|
||||
|
||||
func (s asciiString) ExportType() reflect.Type {
|
||||
return reflectTypeString
|
||||
}
|
||||
288
server/vendor/github.com/dop251/goja/string_imported.go
generated
vendored
Normal file
288
server/vendor/github.com/dop251/goja/string_imported.go
generated
vendored
Normal file
@@ -0,0 +1,288 @@
|
||||
package goja
|
||||
|
||||
import (
|
||||
"hash/maphash"
|
||||
"io"
|
||||
"math"
|
||||
"reflect"
|
||||
"strings"
|
||||
"unicode/utf16"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/dop251/goja/parser"
|
||||
"github.com/dop251/goja/unistring"
|
||||
|
||||
"golang.org/x/text/cases"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
// Represents a string imported from Go. The idea is to delay the scanning for unicode characters and converting
|
||||
// to unicodeString until necessary. This way strings that are merely passed through never get scanned which
|
||||
// saves CPU and memory.
|
||||
// Currently, importedString is created in 2 cases: Runtime.ToValue() for strings longer than 16 bytes and as a result
|
||||
// of JSON.stringify() if it may contain unicode characters. More cases could be added in the future.
|
||||
type importedString struct {
|
||||
s string
|
||||
u unicodeString
|
||||
|
||||
scanned bool
|
||||
}
|
||||
|
||||
func (i *importedString) scan() {
|
||||
i.u = unistring.Scan(i.s)
|
||||
i.scanned = true
|
||||
}
|
||||
|
||||
func (i *importedString) ensureScanned() {
|
||||
if !i.scanned {
|
||||
i.scan()
|
||||
}
|
||||
}
|
||||
|
||||
func (i *importedString) ToInteger() int64 {
|
||||
i.ensureScanned()
|
||||
if i.u != nil {
|
||||
return 0
|
||||
}
|
||||
return asciiString(i.s).ToInteger()
|
||||
}
|
||||
|
||||
func (i *importedString) toString() valueString {
|
||||
return i
|
||||
}
|
||||
|
||||
func (i *importedString) string() unistring.String {
|
||||
i.ensureScanned()
|
||||
if i.u != nil {
|
||||
return unistring.FromUtf16(i.u)
|
||||
}
|
||||
return unistring.String(i.s)
|
||||
}
|
||||
|
||||
func (i *importedString) ToString() Value {
|
||||
return i
|
||||
}
|
||||
|
||||
func (i *importedString) String() string {
|
||||
return i.s
|
||||
}
|
||||
|
||||
func (i *importedString) ToFloat() float64 {
|
||||
i.ensureScanned()
|
||||
if i.u != nil {
|
||||
return math.NaN()
|
||||
}
|
||||
return asciiString(i.s).ToFloat()
|
||||
}
|
||||
|
||||
func (i *importedString) ToNumber() Value {
|
||||
i.ensureScanned()
|
||||
if i.u != nil {
|
||||
return i.u.ToNumber()
|
||||
}
|
||||
return asciiString(i.s).ToNumber()
|
||||
}
|
||||
|
||||
func (i *importedString) ToBoolean() bool {
|
||||
return len(i.s) != 0
|
||||
}
|
||||
|
||||
func (i *importedString) ToObject(r *Runtime) *Object {
|
||||
return r._newString(i, r.global.StringPrototype)
|
||||
}
|
||||
|
||||
func (i *importedString) SameAs(other Value) bool {
|
||||
return i.StrictEquals(other)
|
||||
}
|
||||
|
||||
func (i *importedString) Equals(other Value) bool {
|
||||
if i.StrictEquals(other) {
|
||||
return true
|
||||
}
|
||||
i.ensureScanned()
|
||||
if i.u != nil {
|
||||
return i.u.Equals(other)
|
||||
}
|
||||
return asciiString(i.s).Equals(other)
|
||||
}
|
||||
|
||||
func (i *importedString) StrictEquals(other Value) bool {
|
||||
switch otherStr := other.(type) {
|
||||
case asciiString:
|
||||
if i.u != nil {
|
||||
return false
|
||||
}
|
||||
return i.s == string(otherStr)
|
||||
case unicodeString:
|
||||
i.ensureScanned()
|
||||
if i.u != nil && i.u.equals(otherStr) {
|
||||
return true
|
||||
}
|
||||
case *importedString:
|
||||
return i.s == otherStr.s
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (i *importedString) Export() interface{} {
|
||||
return i.s
|
||||
}
|
||||
|
||||
func (i *importedString) ExportType() reflect.Type {
|
||||
return reflectTypeString
|
||||
}
|
||||
|
||||
func (i *importedString) baseObject(r *Runtime) *Object {
|
||||
i.ensureScanned()
|
||||
if i.u != nil {
|
||||
return i.u.baseObject(r)
|
||||
}
|
||||
return asciiString(i.s).baseObject(r)
|
||||
}
|
||||
|
||||
func (i *importedString) hash(hasher *maphash.Hash) uint64 {
|
||||
i.ensureScanned()
|
||||
if i.u != nil {
|
||||
return i.u.hash(hasher)
|
||||
}
|
||||
return asciiString(i.s).hash(hasher)
|
||||
}
|
||||
|
||||
func (i *importedString) charAt(idx int) rune {
|
||||
i.ensureScanned()
|
||||
if i.u != nil {
|
||||
return i.u.charAt(idx)
|
||||
}
|
||||
return asciiString(i.s).charAt(idx)
|
||||
}
|
||||
|
||||
func (i *importedString) length() int {
|
||||
i.ensureScanned()
|
||||
if i.u != nil {
|
||||
return i.u.length()
|
||||
}
|
||||
return asciiString(i.s).length()
|
||||
}
|
||||
|
||||
func (i *importedString) concat(v valueString) valueString {
|
||||
if !i.scanned {
|
||||
if v, ok := v.(*importedString); ok {
|
||||
if !v.scanned {
|
||||
return &importedString{s: i.s + v.s}
|
||||
}
|
||||
}
|
||||
i.ensureScanned()
|
||||
}
|
||||
if i.u != nil {
|
||||
return i.u.concat(v)
|
||||
}
|
||||
return asciiString(i.s).concat(v)
|
||||
}
|
||||
|
||||
func (i *importedString) substring(start, end int) valueString {
|
||||
i.ensureScanned()
|
||||
if i.u != nil {
|
||||
return i.u.substring(start, end)
|
||||
}
|
||||
return asciiString(i.s).substring(start, end)
|
||||
}
|
||||
|
||||
func (i *importedString) compareTo(v valueString) int {
|
||||
return strings.Compare(i.s, v.String())
|
||||
}
|
||||
|
||||
func (i *importedString) reader() io.RuneReader {
|
||||
if i.scanned {
|
||||
if i.u != nil {
|
||||
return i.u.reader()
|
||||
}
|
||||
return asciiString(i.s).reader()
|
||||
}
|
||||
return strings.NewReader(i.s)
|
||||
}
|
||||
|
||||
type stringUtf16Reader struct {
|
||||
s string
|
||||
pos int
|
||||
second rune
|
||||
}
|
||||
|
||||
func (s *stringUtf16Reader) ReadRune() (r rune, size int, err error) {
|
||||
if s.second >= 0 {
|
||||
r = s.second
|
||||
s.second = -1
|
||||
size = 1
|
||||
return
|
||||
}
|
||||
if s.pos < len(s.s) {
|
||||
r1, size1 := utf8.DecodeRuneInString(s.s[s.pos:])
|
||||
s.pos += size1
|
||||
size = 1
|
||||
if r1 <= 0xFFFF {
|
||||
r = r1
|
||||
} else {
|
||||
r, s.second = utf16.EncodeRune(r1)
|
||||
}
|
||||
} else {
|
||||
err = io.EOF
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (i *importedString) utf16Reader() io.RuneReader {
|
||||
if i.scanned {
|
||||
if i.u != nil {
|
||||
return i.u.utf16Reader()
|
||||
}
|
||||
return asciiString(i.s).utf16Reader()
|
||||
}
|
||||
return &stringUtf16Reader{
|
||||
s: i.s,
|
||||
second: -1,
|
||||
}
|
||||
}
|
||||
|
||||
func (i *importedString) utf16Runes() []rune {
|
||||
i.ensureScanned()
|
||||
if i.u != nil {
|
||||
return i.u.utf16Runes()
|
||||
}
|
||||
return asciiString(i.s).utf16Runes()
|
||||
}
|
||||
|
||||
func (i *importedString) index(v valueString, start int) int {
|
||||
i.ensureScanned()
|
||||
if i.u != nil {
|
||||
return i.u.index(v, start)
|
||||
}
|
||||
return asciiString(i.s).index(v, start)
|
||||
}
|
||||
|
||||
func (i *importedString) lastIndex(v valueString, pos int) int {
|
||||
i.ensureScanned()
|
||||
if i.u != nil {
|
||||
return i.u.lastIndex(v, pos)
|
||||
}
|
||||
return asciiString(i.s).lastIndex(v, pos)
|
||||
}
|
||||
|
||||
func (i *importedString) toLower() valueString {
|
||||
i.ensureScanned()
|
||||
if i.u != nil {
|
||||
return toLower(i.s)
|
||||
}
|
||||
return asciiString(i.s).toLower()
|
||||
}
|
||||
|
||||
func (i *importedString) toUpper() valueString {
|
||||
i.ensureScanned()
|
||||
if i.u != nil {
|
||||
caser := cases.Upper(language.Und)
|
||||
return newStringValue(caser.String(i.s))
|
||||
}
|
||||
return asciiString(i.s).toUpper()
|
||||
}
|
||||
|
||||
func (i *importedString) toTrimmedUTF8() string {
|
||||
return strings.Trim(i.s, parser.WhitespaceChars)
|
||||
}
|
||||
560
server/vendor/github.com/dop251/goja/string_unicode.go
generated
vendored
Normal file
560
server/vendor/github.com/dop251/goja/string_unicode.go
generated
vendored
Normal file
@@ -0,0 +1,560 @@
|
||||
package goja
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"hash/maphash"
|
||||
"io"
|
||||
"math"
|
||||
"reflect"
|
||||
"strings"
|
||||
"unicode/utf16"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/dop251/goja/parser"
|
||||
"github.com/dop251/goja/unistring"
|
||||
"golang.org/x/text/cases"
|
||||
"golang.org/x/text/language"
|
||||
)
|
||||
|
||||
type unicodeString []uint16
|
||||
|
||||
type unicodeRuneReader struct {
|
||||
s unicodeString
|
||||
pos int
|
||||
}
|
||||
|
||||
type utf16RuneReader struct {
|
||||
s unicodeString
|
||||
pos int
|
||||
}
|
||||
|
||||
// passes through invalid surrogate pairs
|
||||
type lenientUtf16Decoder struct {
|
||||
utf16Reader io.RuneReader
|
||||
prev rune
|
||||
prevSet bool
|
||||
}
|
||||
|
||||
type valueStringBuilder struct {
|
||||
asciiBuilder strings.Builder
|
||||
unicodeBuilder unicodeStringBuilder
|
||||
}
|
||||
|
||||
type unicodeStringBuilder struct {
|
||||
buf []uint16
|
||||
unicode bool
|
||||
}
|
||||
|
||||
var (
|
||||
InvalidRuneError = errors.New("invalid rune")
|
||||
)
|
||||
|
||||
func (rr *utf16RuneReader) ReadRune() (r rune, size int, err error) {
|
||||
if rr.pos < len(rr.s) {
|
||||
r = rune(rr.s[rr.pos])
|
||||
size++
|
||||
rr.pos++
|
||||
return
|
||||
}
|
||||
err = io.EOF
|
||||
return
|
||||
}
|
||||
|
||||
func (rr *lenientUtf16Decoder) ReadRune() (r rune, size int, err error) {
|
||||
if rr.prevSet {
|
||||
r = rr.prev
|
||||
size = 1
|
||||
rr.prevSet = false
|
||||
} else {
|
||||
r, size, err = rr.utf16Reader.ReadRune()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
if isUTF16FirstSurrogate(r) {
|
||||
second, _, err1 := rr.utf16Reader.ReadRune()
|
||||
if err1 != nil {
|
||||
if err1 != io.EOF {
|
||||
err = err1
|
||||
}
|
||||
return
|
||||
}
|
||||
if isUTF16SecondSurrogate(second) {
|
||||
r = utf16.DecodeRune(r, second)
|
||||
size++
|
||||
} else {
|
||||
rr.prev = second
|
||||
rr.prevSet = true
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (rr *unicodeRuneReader) ReadRune() (r rune, size int, err error) {
|
||||
if rr.pos < len(rr.s) {
|
||||
r = rune(rr.s[rr.pos])
|
||||
size++
|
||||
rr.pos++
|
||||
if isUTF16FirstSurrogate(r) {
|
||||
if rr.pos < len(rr.s) {
|
||||
second := rune(rr.s[rr.pos])
|
||||
if isUTF16SecondSurrogate(second) {
|
||||
r = utf16.DecodeRune(r, second)
|
||||
size++
|
||||
rr.pos++
|
||||
} else {
|
||||
err = InvalidRuneError
|
||||
}
|
||||
} else {
|
||||
err = InvalidRuneError
|
||||
}
|
||||
} else if isUTF16SecondSurrogate(r) {
|
||||
err = InvalidRuneError
|
||||
}
|
||||
} else {
|
||||
err = io.EOF
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (b *unicodeStringBuilder) Grow(n int) {
|
||||
if len(b.buf) == 0 {
|
||||
n++
|
||||
}
|
||||
if cap(b.buf)-len(b.buf) < n {
|
||||
buf := make([]uint16, len(b.buf), 2*cap(b.buf)+n)
|
||||
copy(buf, b.buf)
|
||||
b.buf = buf
|
||||
}
|
||||
}
|
||||
|
||||
func (b *unicodeStringBuilder) ensureStarted(initialSize int) {
|
||||
b.Grow(initialSize)
|
||||
if len(b.buf) == 0 {
|
||||
b.buf = append(b.buf, unistring.BOM)
|
||||
}
|
||||
}
|
||||
|
||||
func (b *unicodeStringBuilder) WriteString(s valueString) {
|
||||
b.ensureStarted(s.length())
|
||||
a, u := devirtualizeString(s)
|
||||
if u != nil {
|
||||
b.buf = append(b.buf, u[1:]...)
|
||||
b.unicode = true
|
||||
} else {
|
||||
for i := 0; i < len(a); i++ {
|
||||
b.buf = append(b.buf, uint16(a[i]))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (b *unicodeStringBuilder) String() valueString {
|
||||
if b.unicode {
|
||||
return unicodeString(b.buf)
|
||||
}
|
||||
if len(b.buf) == 0 {
|
||||
return stringEmpty
|
||||
}
|
||||
buf := make([]byte, 0, len(b.buf)-1)
|
||||
for _, c := range b.buf[1:] {
|
||||
buf = append(buf, byte(c))
|
||||
}
|
||||
return asciiString(buf)
|
||||
}
|
||||
|
||||
func (b *unicodeStringBuilder) WriteRune(r rune) {
|
||||
if r <= 0xFFFF {
|
||||
b.ensureStarted(1)
|
||||
b.buf = append(b.buf, uint16(r))
|
||||
if !b.unicode && r >= utf8.RuneSelf {
|
||||
b.unicode = true
|
||||
}
|
||||
} else {
|
||||
b.ensureStarted(2)
|
||||
first, second := utf16.EncodeRune(r)
|
||||
b.buf = append(b.buf, uint16(first), uint16(second))
|
||||
b.unicode = true
|
||||
}
|
||||
}
|
||||
|
||||
func (b *unicodeStringBuilder) writeASCIIString(bytes string) {
|
||||
b.ensureStarted(len(bytes))
|
||||
for _, c := range bytes {
|
||||
b.buf = append(b.buf, uint16(c))
|
||||
}
|
||||
}
|
||||
|
||||
func (b *unicodeStringBuilder) writeUnicodeString(str unicodeString) {
|
||||
b.ensureStarted(str.length())
|
||||
b.buf = append(b.buf, str[1:]...)
|
||||
b.unicode = true
|
||||
}
|
||||
|
||||
func (b *valueStringBuilder) ascii() bool {
|
||||
return len(b.unicodeBuilder.buf) == 0
|
||||
}
|
||||
|
||||
func (b *valueStringBuilder) WriteString(s valueString) {
|
||||
a, u := devirtualizeString(s)
|
||||
if u != nil {
|
||||
b.switchToUnicode(u.length())
|
||||
b.unicodeBuilder.writeUnicodeString(u)
|
||||
} else {
|
||||
if b.ascii() {
|
||||
b.asciiBuilder.WriteString(string(a))
|
||||
} else {
|
||||
b.unicodeBuilder.writeASCIIString(string(a))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (b *valueStringBuilder) WriteASCII(s string) {
|
||||
if b.ascii() {
|
||||
b.asciiBuilder.WriteString(s)
|
||||
} else {
|
||||
b.unicodeBuilder.writeASCIIString(s)
|
||||
}
|
||||
}
|
||||
|
||||
func (b *valueStringBuilder) WriteRune(r rune) {
|
||||
if r < utf8.RuneSelf {
|
||||
if b.ascii() {
|
||||
b.asciiBuilder.WriteByte(byte(r))
|
||||
} else {
|
||||
b.unicodeBuilder.WriteRune(r)
|
||||
}
|
||||
} else {
|
||||
var extraLen int
|
||||
if r <= 0xFFFF {
|
||||
extraLen = 1
|
||||
} else {
|
||||
extraLen = 2
|
||||
}
|
||||
b.switchToUnicode(extraLen)
|
||||
b.unicodeBuilder.WriteRune(r)
|
||||
}
|
||||
}
|
||||
|
||||
func (b *valueStringBuilder) String() valueString {
|
||||
if b.ascii() {
|
||||
return asciiString(b.asciiBuilder.String())
|
||||
}
|
||||
return b.unicodeBuilder.String()
|
||||
}
|
||||
|
||||
func (b *valueStringBuilder) Grow(n int) {
|
||||
if b.ascii() {
|
||||
b.asciiBuilder.Grow(n)
|
||||
} else {
|
||||
b.unicodeBuilder.Grow(n)
|
||||
}
|
||||
}
|
||||
|
||||
func (b *valueStringBuilder) switchToUnicode(extraLen int) {
|
||||
if b.ascii() {
|
||||
b.unicodeBuilder.ensureStarted(b.asciiBuilder.Len() + extraLen)
|
||||
b.unicodeBuilder.writeASCIIString(b.asciiBuilder.String())
|
||||
b.asciiBuilder.Reset()
|
||||
}
|
||||
}
|
||||
|
||||
func (b *valueStringBuilder) WriteSubstring(source valueString, start int, end int) {
|
||||
a, us := devirtualizeString(source)
|
||||
if us == nil {
|
||||
if b.ascii() {
|
||||
b.asciiBuilder.WriteString(string(a[start:end]))
|
||||
} else {
|
||||
b.unicodeBuilder.writeASCIIString(string(a[start:end]))
|
||||
}
|
||||
return
|
||||
}
|
||||
if b.ascii() {
|
||||
uc := false
|
||||
for i := start; i < end; i++ {
|
||||
if us.charAt(i) >= utf8.RuneSelf {
|
||||
uc = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if uc {
|
||||
b.switchToUnicode(end - start + 1)
|
||||
} else {
|
||||
b.asciiBuilder.Grow(end - start + 1)
|
||||
for i := start; i < end; i++ {
|
||||
b.asciiBuilder.WriteByte(byte(us.charAt(i)))
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
b.unicodeBuilder.buf = append(b.unicodeBuilder.buf, us[start+1:end+1]...)
|
||||
b.unicodeBuilder.unicode = true
|
||||
}
|
||||
|
||||
func (s unicodeString) reader() io.RuneReader {
|
||||
return &unicodeRuneReader{
|
||||
s: s[1:],
|
||||
}
|
||||
}
|
||||
|
||||
func (s unicodeString) utf16Reader() io.RuneReader {
|
||||
return &utf16RuneReader{
|
||||
s: s[1:],
|
||||
}
|
||||
}
|
||||
|
||||
func (s unicodeString) utf16Runes() []rune {
|
||||
runes := make([]rune, len(s)-1)
|
||||
for i, ch := range s[1:] {
|
||||
runes[i] = rune(ch)
|
||||
}
|
||||
return runes
|
||||
}
|
||||
|
||||
func (s unicodeString) ToInteger() int64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (s unicodeString) toString() valueString {
|
||||
return s
|
||||
}
|
||||
|
||||
func (s unicodeString) ToString() Value {
|
||||
return s
|
||||
}
|
||||
|
||||
func (s unicodeString) ToFloat() float64 {
|
||||
return math.NaN()
|
||||
}
|
||||
|
||||
func (s unicodeString) ToBoolean() bool {
|
||||
return len(s) > 0
|
||||
}
|
||||
|
||||
func (s unicodeString) toTrimmedUTF8() string {
|
||||
if len(s) == 0 {
|
||||
return ""
|
||||
}
|
||||
return strings.Trim(s.String(), parser.WhitespaceChars)
|
||||
}
|
||||
|
||||
func (s unicodeString) ToNumber() Value {
|
||||
return asciiString(s.toTrimmedUTF8()).ToNumber()
|
||||
}
|
||||
|
||||
func (s unicodeString) ToObject(r *Runtime) *Object {
|
||||
return r._newString(s, r.global.StringPrototype)
|
||||
}
|
||||
|
||||
func (s unicodeString) equals(other unicodeString) bool {
|
||||
if len(s) != len(other) {
|
||||
return false
|
||||
}
|
||||
for i, r := range s {
|
||||
if r != other[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (s unicodeString) SameAs(other Value) bool {
|
||||
return s.StrictEquals(other)
|
||||
}
|
||||
|
||||
func (s unicodeString) Equals(other Value) bool {
|
||||
if s.StrictEquals(other) {
|
||||
return true
|
||||
}
|
||||
|
||||
if o, ok := other.(*Object); ok {
|
||||
return s.Equals(o.toPrimitive())
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (s unicodeString) StrictEquals(other Value) bool {
|
||||
if otherStr, ok := other.(unicodeString); ok {
|
||||
return s.equals(otherStr)
|
||||
}
|
||||
if otherStr, ok := other.(*importedString); ok {
|
||||
otherStr.ensureScanned()
|
||||
if otherStr.u != nil {
|
||||
return s.equals(otherStr.u)
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (s unicodeString) baseObject(r *Runtime) *Object {
|
||||
ss := r.stringSingleton
|
||||
ss.value = s
|
||||
ss.setLength()
|
||||
return ss.val
|
||||
}
|
||||
|
||||
func (s unicodeString) charAt(idx int) rune {
|
||||
return rune(s[idx+1])
|
||||
}
|
||||
|
||||
func (s unicodeString) length() int {
|
||||
return len(s) - 1
|
||||
}
|
||||
|
||||
func (s unicodeString) concat(other valueString) valueString {
|
||||
a, u := devirtualizeString(other)
|
||||
if u != nil {
|
||||
b := make(unicodeString, len(s)+len(u)-1)
|
||||
copy(b, s)
|
||||
copy(b[len(s):], u[1:])
|
||||
return b
|
||||
}
|
||||
b := make([]uint16, len(s)+len(a))
|
||||
copy(b, s)
|
||||
b1 := b[len(s):]
|
||||
for i := 0; i < len(a); i++ {
|
||||
b1[i] = uint16(a[i])
|
||||
}
|
||||
return unicodeString(b)
|
||||
}
|
||||
|
||||
func (s unicodeString) substring(start, end int) valueString {
|
||||
ss := s[start+1 : end+1]
|
||||
for _, c := range ss {
|
||||
if c >= utf8.RuneSelf {
|
||||
b := make(unicodeString, end-start+1)
|
||||
b[0] = unistring.BOM
|
||||
copy(b[1:], ss)
|
||||
return b
|
||||
}
|
||||
}
|
||||
as := make([]byte, end-start)
|
||||
for i, c := range ss {
|
||||
as[i] = byte(c)
|
||||
}
|
||||
return asciiString(as)
|
||||
}
|
||||
|
||||
func (s unicodeString) String() string {
|
||||
return string(utf16.Decode(s[1:]))
|
||||
}
|
||||
|
||||
func (s unicodeString) compareTo(other valueString) int {
|
||||
// TODO handle invalid UTF-16
|
||||
return strings.Compare(s.String(), other.String())
|
||||
}
|
||||
|
||||
func (s unicodeString) index(substr valueString, start int) int {
|
||||
var ss []uint16
|
||||
a, u := devirtualizeString(substr)
|
||||
if u != nil {
|
||||
ss = u[1:]
|
||||
} else {
|
||||
ss = make([]uint16, len(a))
|
||||
for i := 0; i < len(a); i++ {
|
||||
ss[i] = uint16(a[i])
|
||||
}
|
||||
}
|
||||
s1 := s[1:]
|
||||
// TODO: optimise
|
||||
end := len(s1) - len(ss)
|
||||
for start <= end {
|
||||
for i := 0; i < len(ss); i++ {
|
||||
if s1[start+i] != ss[i] {
|
||||
goto nomatch
|
||||
}
|
||||
}
|
||||
|
||||
return start
|
||||
nomatch:
|
||||
start++
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
func (s unicodeString) lastIndex(substr valueString, start int) int {
|
||||
var ss []uint16
|
||||
a, u := devirtualizeString(substr)
|
||||
if u != nil {
|
||||
ss = u[1:]
|
||||
} else {
|
||||
ss = make([]uint16, len(a))
|
||||
for i := 0; i < len(a); i++ {
|
||||
ss[i] = uint16(a[i])
|
||||
}
|
||||
}
|
||||
|
||||
s1 := s[1:]
|
||||
if maxStart := len(s1) - len(ss); start > maxStart {
|
||||
start = maxStart
|
||||
}
|
||||
// TODO: optimise
|
||||
for start >= 0 {
|
||||
for i := 0; i < len(ss); i++ {
|
||||
if s1[start+i] != ss[i] {
|
||||
goto nomatch
|
||||
}
|
||||
}
|
||||
|
||||
return start
|
||||
nomatch:
|
||||
start--
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
func unicodeStringFromRunes(r []rune) unicodeString {
|
||||
return unistring.NewFromRunes(r).AsUtf16()
|
||||
}
|
||||
|
||||
func toLower(s string) valueString {
|
||||
caser := cases.Lower(language.Und)
|
||||
r := []rune(caser.String(s))
|
||||
// Workaround
|
||||
ascii := true
|
||||
for i := 0; i < len(r)-1; i++ {
|
||||
if (i == 0 || r[i-1] != 0x3b1) && r[i] == 0x345 && r[i+1] == 0x3c2 {
|
||||
i++
|
||||
r[i] = 0x3c3
|
||||
}
|
||||
if r[i] >= utf8.RuneSelf {
|
||||
ascii = false
|
||||
}
|
||||
}
|
||||
if ascii {
|
||||
ascii = r[len(r)-1] < utf8.RuneSelf
|
||||
}
|
||||
if ascii {
|
||||
return asciiString(r)
|
||||
}
|
||||
return unicodeStringFromRunes(r)
|
||||
}
|
||||
|
||||
func (s unicodeString) toLower() valueString {
|
||||
return toLower(s.String())
|
||||
}
|
||||
|
||||
func (s unicodeString) toUpper() valueString {
|
||||
caser := cases.Upper(language.Und)
|
||||
return newStringValue(caser.String(s.String()))
|
||||
}
|
||||
|
||||
func (s unicodeString) Export() interface{} {
|
||||
return s.String()
|
||||
}
|
||||
|
||||
func (s unicodeString) ExportType() reflect.Type {
|
||||
return reflectTypeString
|
||||
}
|
||||
|
||||
func (s unicodeString) hash(hash *maphash.Hash) uint64 {
|
||||
_, _ = hash.WriteString(string(unistring.FromUtf16(s)))
|
||||
h := hash.Sum64()
|
||||
hash.Reset()
|
||||
return h
|
||||
}
|
||||
|
||||
func (s unicodeString) string() unistring.String {
|
||||
return unistring.FromUtf16(s)
|
||||
}
|
||||
2
server/vendor/github.com/dop251/goja/token/Makefile
generated
vendored
Normal file
2
server/vendor/github.com/dop251/goja/token/Makefile
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
token_const.go: tokenfmt
|
||||
./$^ | gofmt > $@
|
||||
171
server/vendor/github.com/dop251/goja/token/README.markdown
generated
vendored
Normal file
171
server/vendor/github.com/dop251/goja/token/README.markdown
generated
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
# token
|
||||
--
|
||||
import "github.com/dop251/goja/token"
|
||||
|
||||
Package token defines constants representing the lexical tokens of JavaScript
|
||||
(ECMA5).
|
||||
|
||||
## Usage
|
||||
|
||||
```go
|
||||
const (
|
||||
ILLEGAL
|
||||
EOF
|
||||
COMMENT
|
||||
KEYWORD
|
||||
|
||||
STRING
|
||||
BOOLEAN
|
||||
NULL
|
||||
NUMBER
|
||||
IDENTIFIER
|
||||
|
||||
PLUS // +
|
||||
MINUS // -
|
||||
MULTIPLY // *
|
||||
SLASH // /
|
||||
REMAINDER // %
|
||||
|
||||
AND // &
|
||||
OR // |
|
||||
EXCLUSIVE_OR // ^
|
||||
SHIFT_LEFT // <<
|
||||
SHIFT_RIGHT // >>
|
||||
UNSIGNED_SHIFT_RIGHT // >>>
|
||||
AND_NOT // &^
|
||||
|
||||
ADD_ASSIGN // +=
|
||||
SUBTRACT_ASSIGN // -=
|
||||
MULTIPLY_ASSIGN // *=
|
||||
QUOTIENT_ASSIGN // /=
|
||||
REMAINDER_ASSIGN // %=
|
||||
|
||||
AND_ASSIGN // &=
|
||||
OR_ASSIGN // |=
|
||||
EXCLUSIVE_OR_ASSIGN // ^=
|
||||
SHIFT_LEFT_ASSIGN // <<=
|
||||
SHIFT_RIGHT_ASSIGN // >>=
|
||||
UNSIGNED_SHIFT_RIGHT_ASSIGN // >>>=
|
||||
AND_NOT_ASSIGN // &^=
|
||||
|
||||
LOGICAL_AND // &&
|
||||
LOGICAL_OR // ||
|
||||
INCREMENT // ++
|
||||
DECREMENT // --
|
||||
|
||||
EQUAL // ==
|
||||
STRICT_EQUAL // ===
|
||||
LESS // <
|
||||
GREATER // >
|
||||
ASSIGN // =
|
||||
NOT // !
|
||||
|
||||
BITWISE_NOT // ~
|
||||
|
||||
NOT_EQUAL // !=
|
||||
STRICT_NOT_EQUAL // !==
|
||||
LESS_OR_EQUAL // <=
|
||||
GREATER_OR_EQUAL // >=
|
||||
|
||||
LEFT_PARENTHESIS // (
|
||||
LEFT_BRACKET // [
|
||||
LEFT_BRACE // {
|
||||
COMMA // ,
|
||||
PERIOD // .
|
||||
|
||||
RIGHT_PARENTHESIS // )
|
||||
RIGHT_BRACKET // ]
|
||||
RIGHT_BRACE // }
|
||||
SEMICOLON // ;
|
||||
COLON // :
|
||||
QUESTION_MARK // ?
|
||||
|
||||
IF
|
||||
IN
|
||||
DO
|
||||
|
||||
VAR
|
||||
FOR
|
||||
NEW
|
||||
TRY
|
||||
|
||||
THIS
|
||||
ELSE
|
||||
CASE
|
||||
VOID
|
||||
WITH
|
||||
|
||||
WHILE
|
||||
BREAK
|
||||
CATCH
|
||||
THROW
|
||||
|
||||
RETURN
|
||||
TYPEOF
|
||||
DELETE
|
||||
SWITCH
|
||||
|
||||
DEFAULT
|
||||
FINALLY
|
||||
|
||||
FUNCTION
|
||||
CONTINUE
|
||||
DEBUGGER
|
||||
|
||||
INSTANCEOF
|
||||
)
|
||||
```
|
||||
|
||||
#### type Token
|
||||
|
||||
```go
|
||||
type Token int
|
||||
```
|
||||
|
||||
Token is the set of lexical tokens in JavaScript (ECMA5).
|
||||
|
||||
#### func IsKeyword
|
||||
|
||||
```go
|
||||
func IsKeyword(literal string) (Token, bool)
|
||||
```
|
||||
IsKeyword returns the keyword token if literal is a keyword, a KEYWORD token if
|
||||
the literal is a future keyword (const, let, class, super, ...), or 0 if the
|
||||
literal is not a keyword.
|
||||
|
||||
If the literal is a keyword, IsKeyword returns a second value indicating if the
|
||||
literal is considered a future keyword in strict-mode only.
|
||||
|
||||
7.6.1.2 Future Reserved Words:
|
||||
|
||||
const
|
||||
class
|
||||
enum
|
||||
export
|
||||
extends
|
||||
import
|
||||
super
|
||||
|
||||
7.6.1.2 Future Reserved Words (strict):
|
||||
|
||||
implements
|
||||
interface
|
||||
let
|
||||
package
|
||||
private
|
||||
protected
|
||||
public
|
||||
static
|
||||
|
||||
#### func (Token) String
|
||||
|
||||
```go
|
||||
func (tkn Token) String() string
|
||||
```
|
||||
String returns the string corresponding to the token. For operators, delimiters,
|
||||
and keywords the string is the actual token string (e.g., for the token PLUS,
|
||||
the String() is "+"). For all other tokens the string corresponds to the token
|
||||
name (e.g. for the token IDENTIFIER, the string is "IDENTIFIER").
|
||||
|
||||
--
|
||||
**godocdown** http://github.com/robertkrimen/godocdown
|
||||
122
server/vendor/github.com/dop251/goja/token/token.go
generated
vendored
Normal file
122
server/vendor/github.com/dop251/goja/token/token.go
generated
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
// Package token defines constants representing the lexical tokens of JavaScript (ECMA5).
|
||||
package token
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// Token is the set of lexical tokens in JavaScript (ECMA5).
|
||||
type Token int
|
||||
|
||||
// String returns the string corresponding to the token.
|
||||
// For operators, delimiters, and keywords the string is the actual
|
||||
// token string (e.g., for the token PLUS, the String() is
|
||||
// "+"). For all other tokens the string corresponds to the token
|
||||
// name (e.g. for the token IDENTIFIER, the string is "IDENTIFIER").
|
||||
func (tkn Token) String() string {
|
||||
if tkn == 0 {
|
||||
return "UNKNOWN"
|
||||
}
|
||||
if tkn < Token(len(token2string)) {
|
||||
return token2string[tkn]
|
||||
}
|
||||
return "token(" + strconv.Itoa(int(tkn)) + ")"
|
||||
}
|
||||
|
||||
//lint:ignore U1000 This is not used for anything
|
||||
func (tkn Token) precedence(in bool) int {
|
||||
|
||||
switch tkn {
|
||||
case LOGICAL_OR:
|
||||
return 1
|
||||
|
||||
case LOGICAL_AND:
|
||||
return 2
|
||||
|
||||
case OR, OR_ASSIGN:
|
||||
return 3
|
||||
|
||||
case EXCLUSIVE_OR:
|
||||
return 4
|
||||
|
||||
case AND, AND_ASSIGN:
|
||||
return 5
|
||||
|
||||
case EQUAL,
|
||||
NOT_EQUAL,
|
||||
STRICT_EQUAL,
|
||||
STRICT_NOT_EQUAL:
|
||||
return 6
|
||||
|
||||
case LESS, GREATER, LESS_OR_EQUAL, GREATER_OR_EQUAL, INSTANCEOF:
|
||||
return 7
|
||||
|
||||
case IN:
|
||||
if in {
|
||||
return 7
|
||||
}
|
||||
return 0
|
||||
|
||||
case SHIFT_LEFT, SHIFT_RIGHT, UNSIGNED_SHIFT_RIGHT:
|
||||
fallthrough
|
||||
case SHIFT_LEFT_ASSIGN, SHIFT_RIGHT_ASSIGN, UNSIGNED_SHIFT_RIGHT_ASSIGN:
|
||||
return 8
|
||||
|
||||
case PLUS, MINUS, ADD_ASSIGN, SUBTRACT_ASSIGN:
|
||||
return 9
|
||||
|
||||
case MULTIPLY, SLASH, REMAINDER, MULTIPLY_ASSIGN, QUOTIENT_ASSIGN, REMAINDER_ASSIGN:
|
||||
return 11
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type _keyword struct {
|
||||
token Token
|
||||
futureKeyword bool
|
||||
strict bool
|
||||
}
|
||||
|
||||
// IsKeyword returns the keyword token if literal is a keyword, a KEYWORD token
|
||||
// if the literal is a future keyword (const, let, class, super, ...), or 0 if the literal is not a keyword.
|
||||
//
|
||||
// If the literal is a keyword, IsKeyword returns a second value indicating if the literal
|
||||
// is considered a future keyword in strict-mode only.
|
||||
//
|
||||
// 7.6.1.2 Future Reserved Words:
|
||||
//
|
||||
// const
|
||||
// class
|
||||
// enum
|
||||
// export
|
||||
// extends
|
||||
// import
|
||||
// super
|
||||
//
|
||||
// 7.6.1.2 Future Reserved Words (strict):
|
||||
//
|
||||
// implements
|
||||
// interface
|
||||
// let
|
||||
// package
|
||||
// private
|
||||
// protected
|
||||
// public
|
||||
// static
|
||||
func IsKeyword(literal string) (Token, bool) {
|
||||
if keyword, exists := keywordTable[literal]; exists {
|
||||
if keyword.futureKeyword {
|
||||
return KEYWORD, keyword.strict
|
||||
}
|
||||
return keyword.token, false
|
||||
}
|
||||
return 0, false
|
||||
}
|
||||
|
||||
func IsId(tkn Token) bool {
|
||||
return tkn >= IDENTIFIER
|
||||
}
|
||||
|
||||
func IsUnreservedWord(tkn Token) bool {
|
||||
return tkn > ESCAPED_RESERVED_WORD
|
||||
}
|
||||
400
server/vendor/github.com/dop251/goja/token/token_const.go
generated
vendored
Normal file
400
server/vendor/github.com/dop251/goja/token/token_const.go
generated
vendored
Normal file
@@ -0,0 +1,400 @@
|
||||
package token
|
||||
|
||||
const (
|
||||
_ Token = iota
|
||||
|
||||
ILLEGAL
|
||||
EOF
|
||||
COMMENT
|
||||
|
||||
STRING
|
||||
NUMBER
|
||||
|
||||
PLUS // +
|
||||
MINUS // -
|
||||
MULTIPLY // *
|
||||
EXPONENT // **
|
||||
SLASH // /
|
||||
REMAINDER // %
|
||||
|
||||
AND // &
|
||||
OR // |
|
||||
EXCLUSIVE_OR // ^
|
||||
SHIFT_LEFT // <<
|
||||
SHIFT_RIGHT // >>
|
||||
UNSIGNED_SHIFT_RIGHT // >>>
|
||||
|
||||
ADD_ASSIGN // +=
|
||||
SUBTRACT_ASSIGN // -=
|
||||
MULTIPLY_ASSIGN // *=
|
||||
EXPONENT_ASSIGN // **=
|
||||
QUOTIENT_ASSIGN // /=
|
||||
REMAINDER_ASSIGN // %=
|
||||
|
||||
AND_ASSIGN // &=
|
||||
OR_ASSIGN // |=
|
||||
EXCLUSIVE_OR_ASSIGN // ^=
|
||||
SHIFT_LEFT_ASSIGN // <<=
|
||||
SHIFT_RIGHT_ASSIGN // >>=
|
||||
UNSIGNED_SHIFT_RIGHT_ASSIGN // >>>=
|
||||
|
||||
LOGICAL_AND // &&
|
||||
LOGICAL_OR // ||
|
||||
COALESCE // ??
|
||||
INCREMENT // ++
|
||||
DECREMENT // --
|
||||
|
||||
EQUAL // ==
|
||||
STRICT_EQUAL // ===
|
||||
LESS // <
|
||||
GREATER // >
|
||||
ASSIGN // =
|
||||
NOT // !
|
||||
|
||||
BITWISE_NOT // ~
|
||||
|
||||
NOT_EQUAL // !=
|
||||
STRICT_NOT_EQUAL // !==
|
||||
LESS_OR_EQUAL // <=
|
||||
GREATER_OR_EQUAL // >=
|
||||
|
||||
LEFT_PARENTHESIS // (
|
||||
LEFT_BRACKET // [
|
||||
LEFT_BRACE // {
|
||||
COMMA // ,
|
||||
PERIOD // .
|
||||
|
||||
RIGHT_PARENTHESIS // )
|
||||
RIGHT_BRACKET // ]
|
||||
RIGHT_BRACE // }
|
||||
SEMICOLON // ;
|
||||
COLON // :
|
||||
QUESTION_MARK // ?
|
||||
QUESTION_DOT // ?.
|
||||
ARROW // =>
|
||||
ELLIPSIS // ...
|
||||
BACKTICK // `
|
||||
|
||||
PRIVATE_IDENTIFIER
|
||||
|
||||
// tokens below (and only them) are syntactically valid identifiers
|
||||
|
||||
IDENTIFIER
|
||||
KEYWORD
|
||||
BOOLEAN
|
||||
NULL
|
||||
|
||||
IF
|
||||
IN
|
||||
OF
|
||||
DO
|
||||
|
||||
VAR
|
||||
FOR
|
||||
NEW
|
||||
TRY
|
||||
|
||||
THIS
|
||||
ELSE
|
||||
CASE
|
||||
VOID
|
||||
WITH
|
||||
|
||||
CONST
|
||||
WHILE
|
||||
BREAK
|
||||
CATCH
|
||||
THROW
|
||||
CLASS
|
||||
SUPER
|
||||
|
||||
RETURN
|
||||
TYPEOF
|
||||
DELETE
|
||||
SWITCH
|
||||
|
||||
DEFAULT
|
||||
FINALLY
|
||||
EXTENDS
|
||||
|
||||
FUNCTION
|
||||
CONTINUE
|
||||
DEBUGGER
|
||||
|
||||
INSTANCEOF
|
||||
|
||||
ESCAPED_RESERVED_WORD
|
||||
// Non-reserved keywords below
|
||||
|
||||
LET
|
||||
STATIC
|
||||
ASYNC
|
||||
AWAIT
|
||||
YIELD
|
||||
)
|
||||
|
||||
var token2string = [...]string{
|
||||
ILLEGAL: "ILLEGAL",
|
||||
EOF: "EOF",
|
||||
COMMENT: "COMMENT",
|
||||
KEYWORD: "KEYWORD",
|
||||
STRING: "STRING",
|
||||
BOOLEAN: "BOOLEAN",
|
||||
NULL: "NULL",
|
||||
NUMBER: "NUMBER",
|
||||
IDENTIFIER: "IDENTIFIER",
|
||||
PRIVATE_IDENTIFIER: "PRIVATE_IDENTIFIER",
|
||||
PLUS: "+",
|
||||
MINUS: "-",
|
||||
EXPONENT: "**",
|
||||
MULTIPLY: "*",
|
||||
SLASH: "/",
|
||||
REMAINDER: "%",
|
||||
AND: "&",
|
||||
OR: "|",
|
||||
EXCLUSIVE_OR: "^",
|
||||
SHIFT_LEFT: "<<",
|
||||
SHIFT_RIGHT: ">>",
|
||||
UNSIGNED_SHIFT_RIGHT: ">>>",
|
||||
ADD_ASSIGN: "+=",
|
||||
SUBTRACT_ASSIGN: "-=",
|
||||
MULTIPLY_ASSIGN: "*=",
|
||||
EXPONENT_ASSIGN: "**=",
|
||||
QUOTIENT_ASSIGN: "/=",
|
||||
REMAINDER_ASSIGN: "%=",
|
||||
AND_ASSIGN: "&=",
|
||||
OR_ASSIGN: "|=",
|
||||
EXCLUSIVE_OR_ASSIGN: "^=",
|
||||
SHIFT_LEFT_ASSIGN: "<<=",
|
||||
SHIFT_RIGHT_ASSIGN: ">>=",
|
||||
UNSIGNED_SHIFT_RIGHT_ASSIGN: ">>>=",
|
||||
LOGICAL_AND: "&&",
|
||||
LOGICAL_OR: "||",
|
||||
COALESCE: "??",
|
||||
INCREMENT: "++",
|
||||
DECREMENT: "--",
|
||||
EQUAL: "==",
|
||||
STRICT_EQUAL: "===",
|
||||
LESS: "<",
|
||||
GREATER: ">",
|
||||
ASSIGN: "=",
|
||||
NOT: "!",
|
||||
BITWISE_NOT: "~",
|
||||
NOT_EQUAL: "!=",
|
||||
STRICT_NOT_EQUAL: "!==",
|
||||
LESS_OR_EQUAL: "<=",
|
||||
GREATER_OR_EQUAL: ">=",
|
||||
LEFT_PARENTHESIS: "(",
|
||||
LEFT_BRACKET: "[",
|
||||
LEFT_BRACE: "{",
|
||||
COMMA: ",",
|
||||
PERIOD: ".",
|
||||
RIGHT_PARENTHESIS: ")",
|
||||
RIGHT_BRACKET: "]",
|
||||
RIGHT_BRACE: "}",
|
||||
SEMICOLON: ";",
|
||||
COLON: ":",
|
||||
QUESTION_MARK: "?",
|
||||
QUESTION_DOT: "?.",
|
||||
ARROW: "=>",
|
||||
ELLIPSIS: "...",
|
||||
BACKTICK: "`",
|
||||
IF: "if",
|
||||
IN: "in",
|
||||
OF: "of",
|
||||
DO: "do",
|
||||
VAR: "var",
|
||||
LET: "let",
|
||||
FOR: "for",
|
||||
NEW: "new",
|
||||
TRY: "try",
|
||||
THIS: "this",
|
||||
ELSE: "else",
|
||||
CASE: "case",
|
||||
VOID: "void",
|
||||
WITH: "with",
|
||||
ASYNC: "async",
|
||||
AWAIT: "await",
|
||||
YIELD: "yield",
|
||||
CONST: "const",
|
||||
WHILE: "while",
|
||||
BREAK: "break",
|
||||
CATCH: "catch",
|
||||
THROW: "throw",
|
||||
CLASS: "class",
|
||||
SUPER: "super",
|
||||
RETURN: "return",
|
||||
TYPEOF: "typeof",
|
||||
DELETE: "delete",
|
||||
SWITCH: "switch",
|
||||
STATIC: "static",
|
||||
DEFAULT: "default",
|
||||
FINALLY: "finally",
|
||||
EXTENDS: "extends",
|
||||
FUNCTION: "function",
|
||||
CONTINUE: "continue",
|
||||
DEBUGGER: "debugger",
|
||||
INSTANCEOF: "instanceof",
|
||||
}
|
||||
|
||||
var keywordTable = map[string]_keyword{
|
||||
"if": {
|
||||
token: IF,
|
||||
},
|
||||
"in": {
|
||||
token: IN,
|
||||
},
|
||||
"do": {
|
||||
token: DO,
|
||||
},
|
||||
"var": {
|
||||
token: VAR,
|
||||
},
|
||||
"for": {
|
||||
token: FOR,
|
||||
},
|
||||
"new": {
|
||||
token: NEW,
|
||||
},
|
||||
"try": {
|
||||
token: TRY,
|
||||
},
|
||||
"this": {
|
||||
token: THIS,
|
||||
},
|
||||
"else": {
|
||||
token: ELSE,
|
||||
},
|
||||
"case": {
|
||||
token: CASE,
|
||||
},
|
||||
"void": {
|
||||
token: VOID,
|
||||
},
|
||||
"with": {
|
||||
token: WITH,
|
||||
},
|
||||
"async": {
|
||||
token: ASYNC,
|
||||
},
|
||||
"while": {
|
||||
token: WHILE,
|
||||
},
|
||||
"break": {
|
||||
token: BREAK,
|
||||
},
|
||||
"catch": {
|
||||
token: CATCH,
|
||||
},
|
||||
"throw": {
|
||||
token: THROW,
|
||||
},
|
||||
"return": {
|
||||
token: RETURN,
|
||||
},
|
||||
"typeof": {
|
||||
token: TYPEOF,
|
||||
},
|
||||
"delete": {
|
||||
token: DELETE,
|
||||
},
|
||||
"switch": {
|
||||
token: SWITCH,
|
||||
},
|
||||
"default": {
|
||||
token: DEFAULT,
|
||||
},
|
||||
"finally": {
|
||||
token: FINALLY,
|
||||
},
|
||||
"function": {
|
||||
token: FUNCTION,
|
||||
},
|
||||
"continue": {
|
||||
token: CONTINUE,
|
||||
},
|
||||
"debugger": {
|
||||
token: DEBUGGER,
|
||||
},
|
||||
"instanceof": {
|
||||
token: INSTANCEOF,
|
||||
},
|
||||
"const": {
|
||||
token: CONST,
|
||||
},
|
||||
"class": {
|
||||
token: CLASS,
|
||||
},
|
||||
"enum": {
|
||||
token: KEYWORD,
|
||||
futureKeyword: true,
|
||||
},
|
||||
"export": {
|
||||
token: KEYWORD,
|
||||
futureKeyword: true,
|
||||
},
|
||||
"extends": {
|
||||
token: EXTENDS,
|
||||
},
|
||||
"import": {
|
||||
token: KEYWORD,
|
||||
futureKeyword: true,
|
||||
},
|
||||
"super": {
|
||||
token: SUPER,
|
||||
},
|
||||
/*
|
||||
"implements": {
|
||||
token: KEYWORD,
|
||||
futureKeyword: true,
|
||||
strict: true,
|
||||
},
|
||||
"interface": {
|
||||
token: KEYWORD,
|
||||
futureKeyword: true,
|
||||
strict: true,
|
||||
},*/
|
||||
"let": {
|
||||
token: LET,
|
||||
strict: true,
|
||||
},
|
||||
/*"package": {
|
||||
token: KEYWORD,
|
||||
futureKeyword: true,
|
||||
strict: true,
|
||||
},
|
||||
"private": {
|
||||
token: KEYWORD,
|
||||
futureKeyword: true,
|
||||
strict: true,
|
||||
},
|
||||
"protected": {
|
||||
token: KEYWORD,
|
||||
futureKeyword: true,
|
||||
strict: true,
|
||||
},
|
||||
"public": {
|
||||
token: KEYWORD,
|
||||
futureKeyword: true,
|
||||
strict: true,
|
||||
},*/
|
||||
"static": {
|
||||
token: STATIC,
|
||||
strict: true,
|
||||
},
|
||||
"await": {
|
||||
token: AWAIT,
|
||||
},
|
||||
"yield": {
|
||||
token: YIELD,
|
||||
},
|
||||
"false": {
|
||||
token: BOOLEAN,
|
||||
},
|
||||
"true": {
|
||||
token: BOOLEAN,
|
||||
},
|
||||
"null": {
|
||||
token: NULL,
|
||||
},
|
||||
}
|
||||
222
server/vendor/github.com/dop251/goja/token/tokenfmt
generated
vendored
Normal file
222
server/vendor/github.com/dop251/goja/token/tokenfmt
generated
vendored
Normal file
@@ -0,0 +1,222 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
my (%token, @order, @keywords);
|
||||
|
||||
{
|
||||
my $keywords;
|
||||
my @const;
|
||||
push @const, <<_END_;
|
||||
package token
|
||||
|
||||
const(
|
||||
_ Token = iota
|
||||
_END_
|
||||
|
||||
for (split m/\n/, <<_END_) {
|
||||
ILLEGAL
|
||||
EOF
|
||||
COMMENT
|
||||
KEYWORD
|
||||
|
||||
STRING
|
||||
BOOLEAN
|
||||
NULL
|
||||
NUMBER
|
||||
IDENTIFIER
|
||||
|
||||
PLUS +
|
||||
MINUS -
|
||||
MULTIPLY *
|
||||
SLASH /
|
||||
REMAINDER %
|
||||
|
||||
AND &
|
||||
OR |
|
||||
EXCLUSIVE_OR ^
|
||||
SHIFT_LEFT <<
|
||||
SHIFT_RIGHT >>
|
||||
UNSIGNED_SHIFT_RIGHT >>>
|
||||
AND_NOT &^
|
||||
|
||||
ADD_ASSIGN +=
|
||||
SUBTRACT_ASSIGN -=
|
||||
MULTIPLY_ASSIGN *=
|
||||
QUOTIENT_ASSIGN /=
|
||||
REMAINDER_ASSIGN %=
|
||||
|
||||
AND_ASSIGN &=
|
||||
OR_ASSIGN |=
|
||||
EXCLUSIVE_OR_ASSIGN ^=
|
||||
SHIFT_LEFT_ASSIGN <<=
|
||||
SHIFT_RIGHT_ASSIGN >>=
|
||||
UNSIGNED_SHIFT_RIGHT_ASSIGN >>>=
|
||||
AND_NOT_ASSIGN &^=
|
||||
|
||||
LOGICAL_AND &&
|
||||
LOGICAL_OR ||
|
||||
INCREMENT ++
|
||||
DECREMENT --
|
||||
|
||||
EQUAL ==
|
||||
STRICT_EQUAL ===
|
||||
LESS <
|
||||
GREATER >
|
||||
ASSIGN =
|
||||
NOT !
|
||||
|
||||
BITWISE_NOT ~
|
||||
|
||||
NOT_EQUAL !=
|
||||
STRICT_NOT_EQUAL !==
|
||||
LESS_OR_EQUAL <=
|
||||
GREATER_OR_EQUAL <=
|
||||
|
||||
LEFT_PARENTHESIS (
|
||||
LEFT_BRACKET [
|
||||
LEFT_BRACE {
|
||||
COMMA ,
|
||||
PERIOD .
|
||||
|
||||
RIGHT_PARENTHESIS )
|
||||
RIGHT_BRACKET ]
|
||||
RIGHT_BRACE }
|
||||
SEMICOLON ;
|
||||
COLON :
|
||||
QUESTION_MARK ?
|
||||
|
||||
firstKeyword
|
||||
IF
|
||||
IN
|
||||
DO
|
||||
|
||||
VAR
|
||||
FOR
|
||||
NEW
|
||||
TRY
|
||||
|
||||
THIS
|
||||
ELSE
|
||||
CASE
|
||||
VOID
|
||||
WITH
|
||||
|
||||
WHILE
|
||||
BREAK
|
||||
CATCH
|
||||
THROW
|
||||
|
||||
RETURN
|
||||
TYPEOF
|
||||
DELETE
|
||||
SWITCH
|
||||
|
||||
DEFAULT
|
||||
FINALLY
|
||||
|
||||
FUNCTION
|
||||
CONTINUE
|
||||
DEBUGGER
|
||||
|
||||
INSTANCEOF
|
||||
lastKeyword
|
||||
_END_
|
||||
chomp;
|
||||
|
||||
next if m/^\s*#/;
|
||||
|
||||
my ($name, $symbol) = m/(\w+)\s*(\S+)?/;
|
||||
|
||||
if (defined $symbol) {
|
||||
push @order, $name;
|
||||
push @const, "$name // $symbol";
|
||||
$token{$name} = $symbol;
|
||||
} elsif (defined $name) {
|
||||
$keywords ||= $name eq 'firstKeyword';
|
||||
|
||||
push @const, $name;
|
||||
#$const[-1] .= " Token = iota" if 2 == @const;
|
||||
if ($name =~ m/^([A-Z]+)/) {
|
||||
push @keywords, $name if $keywords;
|
||||
push @order, $name;
|
||||
if ($token{SEMICOLON}) {
|
||||
$token{$name} = lc $1;
|
||||
} else {
|
||||
$token{$name} = $name;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
push @const, "";
|
||||
}
|
||||
|
||||
}
|
||||
push @const, ")";
|
||||
print join "\n", @const, "";
|
||||
}
|
||||
|
||||
{
|
||||
print <<_END_;
|
||||
|
||||
var token2string = [...]string{
|
||||
_END_
|
||||
for my $name (@order) {
|
||||
print "$name: \"$token{$name}\",\n";
|
||||
}
|
||||
print <<_END_;
|
||||
}
|
||||
_END_
|
||||
|
||||
print <<_END_;
|
||||
|
||||
var keywordTable = map[string]_keyword{
|
||||
_END_
|
||||
for my $name (@keywords) {
|
||||
print <<_END_
|
||||
"@{[ lc $name ]}": _keyword{
|
||||
token: $name,
|
||||
},
|
||||
_END_
|
||||
}
|
||||
|
||||
for my $name (qw/
|
||||
const
|
||||
class
|
||||
enum
|
||||
export
|
||||
extends
|
||||
import
|
||||
super
|
||||
/) {
|
||||
print <<_END_
|
||||
"$name": _keyword{
|
||||
token: KEYWORD,
|
||||
futureKeyword: true,
|
||||
},
|
||||
_END_
|
||||
}
|
||||
|
||||
for my $name (qw/
|
||||
implements
|
||||
interface
|
||||
let
|
||||
package
|
||||
private
|
||||
protected
|
||||
public
|
||||
static
|
||||
/) {
|
||||
print <<_END_
|
||||
"$name": _keyword{
|
||||
token: KEYWORD,
|
||||
futureKeyword: true,
|
||||
strict: true,
|
||||
},
|
||||
_END_
|
||||
}
|
||||
|
||||
print <<_END_;
|
||||
}
|
||||
_END_
|
||||
}
|
||||
918
server/vendor/github.com/dop251/goja/typedarrays.go
generated
vendored
Normal file
918
server/vendor/github.com/dop251/goja/typedarrays.go
generated
vendored
Normal file
@@ -0,0 +1,918 @@
|
||||
package goja
|
||||
|
||||
import (
|
||||
"math"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"unsafe"
|
||||
|
||||
"github.com/dop251/goja/unistring"
|
||||
)
|
||||
|
||||
type byteOrder bool
|
||||
|
||||
const (
|
||||
bigEndian byteOrder = false
|
||||
littleEndian byteOrder = true
|
||||
)
|
||||
|
||||
var (
|
||||
nativeEndian byteOrder
|
||||
|
||||
arrayBufferType = reflect.TypeOf(ArrayBuffer{})
|
||||
)
|
||||
|
||||
type typedArrayObjectCtor func(buf *arrayBufferObject, offset, length int, proto *Object) *typedArrayObject
|
||||
|
||||
type arrayBufferObject struct {
|
||||
baseObject
|
||||
detached bool
|
||||
data []byte
|
||||
}
|
||||
|
||||
// ArrayBuffer is a Go wrapper around ECMAScript ArrayBuffer. Calling Runtime.ToValue() on it
|
||||
// returns the underlying ArrayBuffer. Calling Export() on an ECMAScript ArrayBuffer returns a wrapper.
|
||||
// Use Runtime.NewArrayBuffer([]byte) to create one.
|
||||
type ArrayBuffer struct {
|
||||
buf *arrayBufferObject
|
||||
}
|
||||
|
||||
type dataViewObject struct {
|
||||
baseObject
|
||||
viewedArrayBuf *arrayBufferObject
|
||||
byteLen, byteOffset int
|
||||
}
|
||||
|
||||
type typedArray interface {
|
||||
toRaw(Value) uint64
|
||||
get(idx int) Value
|
||||
set(idx int, value Value)
|
||||
getRaw(idx int) uint64
|
||||
setRaw(idx int, raw uint64)
|
||||
less(i, j int) bool
|
||||
swap(i, j int)
|
||||
typeMatch(v Value) bool
|
||||
}
|
||||
|
||||
type uint8Array []uint8
|
||||
type uint8ClampedArray []uint8
|
||||
type int8Array []int8
|
||||
type uint16Array []uint16
|
||||
type int16Array []int16
|
||||
type uint32Array []uint32
|
||||
type int32Array []int32
|
||||
type float32Array []float32
|
||||
type float64Array []float64
|
||||
|
||||
type typedArrayObject struct {
|
||||
baseObject
|
||||
viewedArrayBuf *arrayBufferObject
|
||||
defaultCtor *Object
|
||||
length, offset int
|
||||
elemSize int
|
||||
typedArray typedArray
|
||||
}
|
||||
|
||||
func (a ArrayBuffer) toValue(r *Runtime) Value {
|
||||
if a.buf == nil {
|
||||
return _null
|
||||
}
|
||||
v := a.buf.val
|
||||
if v.runtime != r {
|
||||
panic(r.NewTypeError("Illegal runtime transition of an ArrayBuffer"))
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Bytes returns the underlying []byte for this ArrayBuffer.
|
||||
// For detached ArrayBuffers returns nil.
|
||||
func (a ArrayBuffer) Bytes() []byte {
|
||||
return a.buf.data
|
||||
}
|
||||
|
||||
// Detach the ArrayBuffer. After this, the underlying []byte becomes unreferenced and any attempt
|
||||
// to use this ArrayBuffer results in a TypeError.
|
||||
// Returns false if it was already detached, true otherwise.
|
||||
// Note, this method may only be called from the goroutine that 'owns' the Runtime, it may not
|
||||
// be called concurrently.
|
||||
func (a ArrayBuffer) Detach() bool {
|
||||
if a.buf.detached {
|
||||
return false
|
||||
}
|
||||
a.buf.detach()
|
||||
return true
|
||||
}
|
||||
|
||||
// Detached returns true if the ArrayBuffer is detached.
|
||||
func (a ArrayBuffer) Detached() bool {
|
||||
return a.buf.detached
|
||||
}
|
||||
|
||||
func (r *Runtime) NewArrayBuffer(data []byte) ArrayBuffer {
|
||||
buf := r._newArrayBuffer(r.global.ArrayBufferPrototype, nil)
|
||||
buf.data = data
|
||||
return ArrayBuffer{
|
||||
buf: buf,
|
||||
}
|
||||
}
|
||||
|
||||
func (a *uint8Array) get(idx int) Value {
|
||||
return intToValue(int64((*a)[idx]))
|
||||
}
|
||||
|
||||
func (a *uint8Array) getRaw(idx int) uint64 {
|
||||
return uint64((*a)[idx])
|
||||
}
|
||||
|
||||
func (a *uint8Array) set(idx int, value Value) {
|
||||
(*a)[idx] = toUint8(value)
|
||||
}
|
||||
|
||||
func (a *uint8Array) toRaw(v Value) uint64 {
|
||||
return uint64(toUint8(v))
|
||||
}
|
||||
|
||||
func (a *uint8Array) setRaw(idx int, v uint64) {
|
||||
(*a)[idx] = uint8(v)
|
||||
}
|
||||
|
||||
func (a *uint8Array) less(i, j int) bool {
|
||||
return (*a)[i] < (*a)[j]
|
||||
}
|
||||
|
||||
func (a *uint8Array) swap(i, j int) {
|
||||
(*a)[i], (*a)[j] = (*a)[j], (*a)[i]
|
||||
}
|
||||
|
||||
func (a *uint8Array) typeMatch(v Value) bool {
|
||||
if i, ok := v.(valueInt); ok {
|
||||
return i >= 0 && i <= 255
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (a *uint8ClampedArray) get(idx int) Value {
|
||||
return intToValue(int64((*a)[idx]))
|
||||
}
|
||||
|
||||
func (a *uint8ClampedArray) getRaw(idx int) uint64 {
|
||||
return uint64((*a)[idx])
|
||||
}
|
||||
|
||||
func (a *uint8ClampedArray) set(idx int, value Value) {
|
||||
(*a)[idx] = toUint8Clamp(value)
|
||||
}
|
||||
|
||||
func (a *uint8ClampedArray) toRaw(v Value) uint64 {
|
||||
return uint64(toUint8Clamp(v))
|
||||
}
|
||||
|
||||
func (a *uint8ClampedArray) setRaw(idx int, v uint64) {
|
||||
(*a)[idx] = uint8(v)
|
||||
}
|
||||
|
||||
func (a *uint8ClampedArray) less(i, j int) bool {
|
||||
return (*a)[i] < (*a)[j]
|
||||
}
|
||||
|
||||
func (a *uint8ClampedArray) swap(i, j int) {
|
||||
(*a)[i], (*a)[j] = (*a)[j], (*a)[i]
|
||||
}
|
||||
|
||||
func (a *uint8ClampedArray) typeMatch(v Value) bool {
|
||||
if i, ok := v.(valueInt); ok {
|
||||
return i >= 0 && i <= 255
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (a *int8Array) get(idx int) Value {
|
||||
return intToValue(int64((*a)[idx]))
|
||||
}
|
||||
|
||||
func (a *int8Array) getRaw(idx int) uint64 {
|
||||
return uint64((*a)[idx])
|
||||
}
|
||||
|
||||
func (a *int8Array) set(idx int, value Value) {
|
||||
(*a)[idx] = toInt8(value)
|
||||
}
|
||||
|
||||
func (a *int8Array) toRaw(v Value) uint64 {
|
||||
return uint64(toInt8(v))
|
||||
}
|
||||
|
||||
func (a *int8Array) setRaw(idx int, v uint64) {
|
||||
(*a)[idx] = int8(v)
|
||||
}
|
||||
|
||||
func (a *int8Array) less(i, j int) bool {
|
||||
return (*a)[i] < (*a)[j]
|
||||
}
|
||||
|
||||
func (a *int8Array) swap(i, j int) {
|
||||
(*a)[i], (*a)[j] = (*a)[j], (*a)[i]
|
||||
}
|
||||
|
||||
func (a *int8Array) typeMatch(v Value) bool {
|
||||
if i, ok := v.(valueInt); ok {
|
||||
return i >= math.MinInt8 && i <= math.MaxInt8
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (a *uint16Array) get(idx int) Value {
|
||||
return intToValue(int64((*a)[idx]))
|
||||
}
|
||||
|
||||
func (a *uint16Array) getRaw(idx int) uint64 {
|
||||
return uint64((*a)[idx])
|
||||
}
|
||||
|
||||
func (a *uint16Array) set(idx int, value Value) {
|
||||
(*a)[idx] = toUint16(value)
|
||||
}
|
||||
|
||||
func (a *uint16Array) toRaw(v Value) uint64 {
|
||||
return uint64(toUint16(v))
|
||||
}
|
||||
|
||||
func (a *uint16Array) setRaw(idx int, v uint64) {
|
||||
(*a)[idx] = uint16(v)
|
||||
}
|
||||
|
||||
func (a *uint16Array) less(i, j int) bool {
|
||||
return (*a)[i] < (*a)[j]
|
||||
}
|
||||
|
||||
func (a *uint16Array) swap(i, j int) {
|
||||
(*a)[i], (*a)[j] = (*a)[j], (*a)[i]
|
||||
}
|
||||
|
||||
func (a *uint16Array) typeMatch(v Value) bool {
|
||||
if i, ok := v.(valueInt); ok {
|
||||
return i >= 0 && i <= math.MaxUint16
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (a *int16Array) get(idx int) Value {
|
||||
return intToValue(int64((*a)[idx]))
|
||||
}
|
||||
|
||||
func (a *int16Array) getRaw(idx int) uint64 {
|
||||
return uint64((*a)[idx])
|
||||
}
|
||||
|
||||
func (a *int16Array) set(idx int, value Value) {
|
||||
(*a)[idx] = toInt16(value)
|
||||
}
|
||||
|
||||
func (a *int16Array) toRaw(v Value) uint64 {
|
||||
return uint64(toInt16(v))
|
||||
}
|
||||
|
||||
func (a *int16Array) setRaw(idx int, v uint64) {
|
||||
(*a)[idx] = int16(v)
|
||||
}
|
||||
|
||||
func (a *int16Array) less(i, j int) bool {
|
||||
return (*a)[i] < (*a)[j]
|
||||
}
|
||||
|
||||
func (a *int16Array) swap(i, j int) {
|
||||
(*a)[i], (*a)[j] = (*a)[j], (*a)[i]
|
||||
}
|
||||
|
||||
func (a *int16Array) typeMatch(v Value) bool {
|
||||
if i, ok := v.(valueInt); ok {
|
||||
return i >= math.MinInt16 && i <= math.MaxInt16
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (a *uint32Array) get(idx int) Value {
|
||||
return intToValue(int64((*a)[idx]))
|
||||
}
|
||||
|
||||
func (a *uint32Array) getRaw(idx int) uint64 {
|
||||
return uint64((*a)[idx])
|
||||
}
|
||||
|
||||
func (a *uint32Array) set(idx int, value Value) {
|
||||
(*a)[idx] = toUint32(value)
|
||||
}
|
||||
|
||||
func (a *uint32Array) toRaw(v Value) uint64 {
|
||||
return uint64(toUint32(v))
|
||||
}
|
||||
|
||||
func (a *uint32Array) setRaw(idx int, v uint64) {
|
||||
(*a)[idx] = uint32(v)
|
||||
}
|
||||
|
||||
func (a *uint32Array) less(i, j int) bool {
|
||||
return (*a)[i] < (*a)[j]
|
||||
}
|
||||
|
||||
func (a *uint32Array) swap(i, j int) {
|
||||
(*a)[i], (*a)[j] = (*a)[j], (*a)[i]
|
||||
}
|
||||
|
||||
func (a *uint32Array) typeMatch(v Value) bool {
|
||||
if i, ok := v.(valueInt); ok {
|
||||
return i >= 0 && i <= math.MaxUint32
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (a *int32Array) get(idx int) Value {
|
||||
return intToValue(int64((*a)[idx]))
|
||||
}
|
||||
|
||||
func (a *int32Array) getRaw(idx int) uint64 {
|
||||
return uint64((*a)[idx])
|
||||
}
|
||||
|
||||
func (a *int32Array) set(idx int, value Value) {
|
||||
(*a)[idx] = toInt32(value)
|
||||
}
|
||||
|
||||
func (a *int32Array) toRaw(v Value) uint64 {
|
||||
return uint64(toInt32(v))
|
||||
}
|
||||
|
||||
func (a *int32Array) setRaw(idx int, v uint64) {
|
||||
(*a)[idx] = int32(v)
|
||||
}
|
||||
|
||||
func (a *int32Array) less(i, j int) bool {
|
||||
return (*a)[i] < (*a)[j]
|
||||
}
|
||||
|
||||
func (a *int32Array) swap(i, j int) {
|
||||
(*a)[i], (*a)[j] = (*a)[j], (*a)[i]
|
||||
}
|
||||
|
||||
func (a *int32Array) typeMatch(v Value) bool {
|
||||
if i, ok := v.(valueInt); ok {
|
||||
return i >= math.MinInt32 && i <= math.MaxInt32
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (a *float32Array) get(idx int) Value {
|
||||
return floatToValue(float64((*a)[idx]))
|
||||
}
|
||||
|
||||
func (a *float32Array) getRaw(idx int) uint64 {
|
||||
return uint64(math.Float32bits((*a)[idx]))
|
||||
}
|
||||
|
||||
func (a *float32Array) set(idx int, value Value) {
|
||||
(*a)[idx] = toFloat32(value)
|
||||
}
|
||||
|
||||
func (a *float32Array) toRaw(v Value) uint64 {
|
||||
return uint64(math.Float32bits(toFloat32(v)))
|
||||
}
|
||||
|
||||
func (a *float32Array) setRaw(idx int, v uint64) {
|
||||
(*a)[idx] = math.Float32frombits(uint32(v))
|
||||
}
|
||||
|
||||
func typedFloatLess(x, y float64) bool {
|
||||
xNan := math.IsNaN(x)
|
||||
yNan := math.IsNaN(y)
|
||||
if yNan {
|
||||
return !xNan
|
||||
} else if xNan {
|
||||
return false
|
||||
}
|
||||
if x == 0 && y == 0 { // handle neg zero
|
||||
return math.Signbit(x)
|
||||
}
|
||||
return x < y
|
||||
}
|
||||
|
||||
func (a *float32Array) less(i, j int) bool {
|
||||
return typedFloatLess(float64((*a)[i]), float64((*a)[j]))
|
||||
}
|
||||
|
||||
func (a *float32Array) swap(i, j int) {
|
||||
(*a)[i], (*a)[j] = (*a)[j], (*a)[i]
|
||||
}
|
||||
|
||||
func (a *float32Array) typeMatch(v Value) bool {
|
||||
switch v.(type) {
|
||||
case valueInt, valueFloat:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (a *float64Array) get(idx int) Value {
|
||||
return floatToValue((*a)[idx])
|
||||
}
|
||||
|
||||
func (a *float64Array) getRaw(idx int) uint64 {
|
||||
return math.Float64bits((*a)[idx])
|
||||
}
|
||||
|
||||
func (a *float64Array) set(idx int, value Value) {
|
||||
(*a)[idx] = value.ToFloat()
|
||||
}
|
||||
|
||||
func (a *float64Array) toRaw(v Value) uint64 {
|
||||
return math.Float64bits(v.ToFloat())
|
||||
}
|
||||
|
||||
func (a *float64Array) setRaw(idx int, v uint64) {
|
||||
(*a)[idx] = math.Float64frombits(v)
|
||||
}
|
||||
|
||||
func (a *float64Array) less(i, j int) bool {
|
||||
return typedFloatLess((*a)[i], (*a)[j])
|
||||
}
|
||||
|
||||
func (a *float64Array) swap(i, j int) {
|
||||
(*a)[i], (*a)[j] = (*a)[j], (*a)[i]
|
||||
}
|
||||
|
||||
func (a *float64Array) typeMatch(v Value) bool {
|
||||
switch v.(type) {
|
||||
case valueInt, valueFloat:
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (a *typedArrayObject) _getIdx(idx int) Value {
|
||||
if 0 <= idx && idx < a.length {
|
||||
if !a.viewedArrayBuf.ensureNotDetached(false) {
|
||||
return nil
|
||||
}
|
||||
return a.typedArray.get(idx + a.offset)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *typedArrayObject) getOwnPropStr(name unistring.String) Value {
|
||||
idx, ok := strToIntNum(name)
|
||||
if ok {
|
||||
v := a._getIdx(idx)
|
||||
if v != nil {
|
||||
return &valueProperty{
|
||||
value: v,
|
||||
writable: true,
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
if idx == 0 {
|
||||
return nil
|
||||
}
|
||||
return a.baseObject.getOwnPropStr(name)
|
||||
}
|
||||
|
||||
func (a *typedArrayObject) getOwnPropIdx(idx valueInt) Value {
|
||||
v := a._getIdx(toIntClamp(int64(idx)))
|
||||
if v != nil {
|
||||
return &valueProperty{
|
||||
value: v,
|
||||
writable: true,
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *typedArrayObject) getStr(name unistring.String, receiver Value) Value {
|
||||
idx, ok := strToIntNum(name)
|
||||
if ok {
|
||||
return a._getIdx(idx)
|
||||
}
|
||||
if idx == 0 {
|
||||
return nil
|
||||
}
|
||||
return a.baseObject.getStr(name, receiver)
|
||||
}
|
||||
|
||||
func (a *typedArrayObject) getIdx(idx valueInt, receiver Value) Value {
|
||||
return a._getIdx(toIntClamp(int64(idx)))
|
||||
}
|
||||
|
||||
func (a *typedArrayObject) isValidIntegerIndex(idx int) bool {
|
||||
if a.viewedArrayBuf.ensureNotDetached(false) {
|
||||
if idx >= 0 && idx < a.length {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (a *typedArrayObject) _putIdx(idx int, v Value) {
|
||||
v = v.ToNumber()
|
||||
if a.isValidIntegerIndex(idx) {
|
||||
a.typedArray.set(idx+a.offset, v)
|
||||
}
|
||||
}
|
||||
|
||||
func (a *typedArrayObject) _hasIdx(idx int) bool {
|
||||
return a.isValidIntegerIndex(idx)
|
||||
}
|
||||
|
||||
func (a *typedArrayObject) setOwnStr(p unistring.String, v Value, throw bool) bool {
|
||||
idx, ok := strToIntNum(p)
|
||||
if ok {
|
||||
a._putIdx(idx, v)
|
||||
return true
|
||||
}
|
||||
if idx == 0 {
|
||||
v.ToNumber() // make sure it throws
|
||||
return true
|
||||
}
|
||||
return a.baseObject.setOwnStr(p, v, throw)
|
||||
}
|
||||
|
||||
func (a *typedArrayObject) setOwnIdx(p valueInt, v Value, throw bool) bool {
|
||||
a._putIdx(toIntClamp(int64(p)), v)
|
||||
return true
|
||||
}
|
||||
|
||||
func (a *typedArrayObject) setForeignStr(p unistring.String, v, receiver Value, throw bool) (res bool, handled bool) {
|
||||
return a._setForeignStr(p, a.getOwnPropStr(p), v, receiver, throw)
|
||||
}
|
||||
|
||||
func (a *typedArrayObject) setForeignIdx(p valueInt, v, receiver Value, throw bool) (res bool, handled bool) {
|
||||
return a._setForeignIdx(p, trueValIfPresent(a.hasOwnPropertyIdx(p)), v, receiver, throw)
|
||||
}
|
||||
|
||||
func (a *typedArrayObject) hasOwnPropertyStr(name unistring.String) bool {
|
||||
idx, ok := strToIntNum(name)
|
||||
if ok {
|
||||
return a._hasIdx(idx)
|
||||
}
|
||||
if idx == 0 {
|
||||
return false
|
||||
}
|
||||
return a.baseObject.hasOwnPropertyStr(name)
|
||||
}
|
||||
|
||||
func (a *typedArrayObject) hasOwnPropertyIdx(idx valueInt) bool {
|
||||
return a._hasIdx(toIntClamp(int64(idx)))
|
||||
}
|
||||
|
||||
func (a *typedArrayObject) hasPropertyStr(name unistring.String) bool {
|
||||
idx, ok := strToIntNum(name)
|
||||
if ok {
|
||||
return a._hasIdx(idx)
|
||||
}
|
||||
if idx == 0 {
|
||||
return false
|
||||
}
|
||||
return a.baseObject.hasPropertyStr(name)
|
||||
}
|
||||
|
||||
func (a *typedArrayObject) hasPropertyIdx(idx valueInt) bool {
|
||||
return a.hasOwnPropertyIdx(idx)
|
||||
}
|
||||
|
||||
func (a *typedArrayObject) _defineIdxProperty(idx int, desc PropertyDescriptor, throw bool) bool {
|
||||
if desc.Configurable == FLAG_FALSE || desc.Enumerable == FLAG_FALSE || desc.IsAccessor() || desc.Writable == FLAG_FALSE {
|
||||
a.val.runtime.typeErrorResult(throw, "Cannot redefine property: %d", idx)
|
||||
return false
|
||||
}
|
||||
_, ok := a._defineOwnProperty(unistring.String(strconv.Itoa(idx)), a.getOwnPropIdx(valueInt(idx)), desc, throw)
|
||||
if ok {
|
||||
if !a.isValidIntegerIndex(idx) {
|
||||
a.val.runtime.typeErrorResult(throw, "Invalid typed array index")
|
||||
return false
|
||||
}
|
||||
a._putIdx(idx, desc.Value)
|
||||
return true
|
||||
}
|
||||
return ok
|
||||
}
|
||||
|
||||
func (a *typedArrayObject) defineOwnPropertyStr(name unistring.String, desc PropertyDescriptor, throw bool) bool {
|
||||
idx, ok := strToIntNum(name)
|
||||
if ok {
|
||||
return a._defineIdxProperty(idx, desc, throw)
|
||||
}
|
||||
if idx == 0 {
|
||||
a.viewedArrayBuf.ensureNotDetached(throw)
|
||||
a.val.runtime.typeErrorResult(throw, "Invalid typed array index")
|
||||
return false
|
||||
}
|
||||
return a.baseObject.defineOwnPropertyStr(name, desc, throw)
|
||||
}
|
||||
|
||||
func (a *typedArrayObject) defineOwnPropertyIdx(name valueInt, desc PropertyDescriptor, throw bool) bool {
|
||||
return a._defineIdxProperty(toIntClamp(int64(name)), desc, throw)
|
||||
}
|
||||
|
||||
func (a *typedArrayObject) deleteStr(name unistring.String, throw bool) bool {
|
||||
idx, ok := strToIntNum(name)
|
||||
if ok {
|
||||
if a.isValidIntegerIndex(idx) {
|
||||
a.val.runtime.typeErrorResult(throw, "Cannot delete property '%d' of %s", idx, a.val.String())
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
if idx == 0 {
|
||||
return true
|
||||
}
|
||||
return a.baseObject.deleteStr(name, throw)
|
||||
}
|
||||
|
||||
func (a *typedArrayObject) deleteIdx(idx valueInt, throw bool) bool {
|
||||
if a.viewedArrayBuf.ensureNotDetached(false) && idx >= 0 && int64(idx) < int64(a.length) {
|
||||
a.val.runtime.typeErrorResult(throw, "Cannot delete property '%d' of %s", idx, a.val.String())
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (a *typedArrayObject) stringKeys(all bool, accum []Value) []Value {
|
||||
if accum == nil {
|
||||
accum = make([]Value, 0, a.length)
|
||||
}
|
||||
for i := 0; i < a.length; i++ {
|
||||
accum = append(accum, asciiString(strconv.Itoa(i)))
|
||||
}
|
||||
return a.baseObject.stringKeys(all, accum)
|
||||
}
|
||||
|
||||
type typedArrayPropIter struct {
|
||||
a *typedArrayObject
|
||||
idx int
|
||||
}
|
||||
|
||||
func (i *typedArrayPropIter) next() (propIterItem, iterNextFunc) {
|
||||
if i.idx < i.a.length {
|
||||
name := strconv.Itoa(i.idx)
|
||||
prop := i.a._getIdx(i.idx)
|
||||
i.idx++
|
||||
return propIterItem{name: asciiString(name), value: prop}, i.next
|
||||
}
|
||||
|
||||
return i.a.baseObject.iterateStringKeys()()
|
||||
}
|
||||
|
||||
func (a *typedArrayObject) iterateStringKeys() iterNextFunc {
|
||||
return (&typedArrayPropIter{
|
||||
a: a,
|
||||
}).next
|
||||
}
|
||||
|
||||
func (r *Runtime) _newTypedArrayObject(buf *arrayBufferObject, offset, length, elemSize int, defCtor *Object, arr typedArray, proto *Object) *typedArrayObject {
|
||||
o := &Object{runtime: r}
|
||||
a := &typedArrayObject{
|
||||
baseObject: baseObject{
|
||||
val: o,
|
||||
class: classObject,
|
||||
prototype: proto,
|
||||
extensible: true,
|
||||
},
|
||||
viewedArrayBuf: buf,
|
||||
offset: offset,
|
||||
length: length,
|
||||
elemSize: elemSize,
|
||||
defaultCtor: defCtor,
|
||||
typedArray: arr,
|
||||
}
|
||||
o.self = a
|
||||
a.init()
|
||||
return a
|
||||
|
||||
}
|
||||
|
||||
func (r *Runtime) newUint8ArrayObject(buf *arrayBufferObject, offset, length int, proto *Object) *typedArrayObject {
|
||||
return r._newTypedArrayObject(buf, offset, length, 1, r.global.Uint8Array, (*uint8Array)(&buf.data), proto)
|
||||
}
|
||||
|
||||
func (r *Runtime) newUint8ClampedArrayObject(buf *arrayBufferObject, offset, length int, proto *Object) *typedArrayObject {
|
||||
return r._newTypedArrayObject(buf, offset, length, 1, r.global.Uint8ClampedArray, (*uint8ClampedArray)(&buf.data), proto)
|
||||
}
|
||||
|
||||
func (r *Runtime) newInt8ArrayObject(buf *arrayBufferObject, offset, length int, proto *Object) *typedArrayObject {
|
||||
return r._newTypedArrayObject(buf, offset, length, 1, r.global.Int8Array, (*int8Array)(unsafe.Pointer(&buf.data)), proto)
|
||||
}
|
||||
|
||||
func (r *Runtime) newUint16ArrayObject(buf *arrayBufferObject, offset, length int, proto *Object) *typedArrayObject {
|
||||
return r._newTypedArrayObject(buf, offset, length, 2, r.global.Uint16Array, (*uint16Array)(unsafe.Pointer(&buf.data)), proto)
|
||||
}
|
||||
|
||||
func (r *Runtime) newInt16ArrayObject(buf *arrayBufferObject, offset, length int, proto *Object) *typedArrayObject {
|
||||
return r._newTypedArrayObject(buf, offset, length, 2, r.global.Int16Array, (*int16Array)(unsafe.Pointer(&buf.data)), proto)
|
||||
}
|
||||
|
||||
func (r *Runtime) newUint32ArrayObject(buf *arrayBufferObject, offset, length int, proto *Object) *typedArrayObject {
|
||||
return r._newTypedArrayObject(buf, offset, length, 4, r.global.Uint32Array, (*uint32Array)(unsafe.Pointer(&buf.data)), proto)
|
||||
}
|
||||
|
||||
func (r *Runtime) newInt32ArrayObject(buf *arrayBufferObject, offset, length int, proto *Object) *typedArrayObject {
|
||||
return r._newTypedArrayObject(buf, offset, length, 4, r.global.Int32Array, (*int32Array)(unsafe.Pointer(&buf.data)), proto)
|
||||
}
|
||||
|
||||
func (r *Runtime) newFloat32ArrayObject(buf *arrayBufferObject, offset, length int, proto *Object) *typedArrayObject {
|
||||
return r._newTypedArrayObject(buf, offset, length, 4, r.global.Float32Array, (*float32Array)(unsafe.Pointer(&buf.data)), proto)
|
||||
}
|
||||
|
||||
func (r *Runtime) newFloat64ArrayObject(buf *arrayBufferObject, offset, length int, proto *Object) *typedArrayObject {
|
||||
return r._newTypedArrayObject(buf, offset, length, 8, r.global.Float64Array, (*float64Array)(unsafe.Pointer(&buf.data)), proto)
|
||||
}
|
||||
|
||||
func (o *dataViewObject) getIdxAndByteOrder(getIdx int, littleEndianVal Value, size int) (int, byteOrder) {
|
||||
o.viewedArrayBuf.ensureNotDetached(true)
|
||||
if getIdx+size > o.byteLen {
|
||||
panic(o.val.runtime.newError(o.val.runtime.global.RangeError, "Index %d is out of bounds", getIdx))
|
||||
}
|
||||
getIdx += o.byteOffset
|
||||
var bo byteOrder
|
||||
if littleEndianVal != nil {
|
||||
if littleEndianVal.ToBoolean() {
|
||||
bo = littleEndian
|
||||
} else {
|
||||
bo = bigEndian
|
||||
}
|
||||
} else {
|
||||
bo = nativeEndian
|
||||
}
|
||||
return getIdx, bo
|
||||
}
|
||||
|
||||
func (o *arrayBufferObject) ensureNotDetached(throw bool) bool {
|
||||
if o.detached {
|
||||
o.val.runtime.typeErrorResult(throw, "ArrayBuffer is detached")
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (o *arrayBufferObject) getFloat32(idx int, byteOrder byteOrder) float32 {
|
||||
return math.Float32frombits(o.getUint32(idx, byteOrder))
|
||||
}
|
||||
|
||||
func (o *arrayBufferObject) setFloat32(idx int, val float32, byteOrder byteOrder) {
|
||||
o.setUint32(idx, math.Float32bits(val), byteOrder)
|
||||
}
|
||||
|
||||
func (o *arrayBufferObject) getFloat64(idx int, byteOrder byteOrder) float64 {
|
||||
return math.Float64frombits(o.getUint64(idx, byteOrder))
|
||||
}
|
||||
|
||||
func (o *arrayBufferObject) setFloat64(idx int, val float64, byteOrder byteOrder) {
|
||||
o.setUint64(idx, math.Float64bits(val), byteOrder)
|
||||
}
|
||||
|
||||
func (o *arrayBufferObject) getUint64(idx int, byteOrder byteOrder) uint64 {
|
||||
var b []byte
|
||||
if byteOrder == nativeEndian {
|
||||
b = o.data[idx : idx+8]
|
||||
} else {
|
||||
b = make([]byte, 8)
|
||||
d := o.data[idx : idx+8]
|
||||
b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7] = d[7], d[6], d[5], d[4], d[3], d[2], d[1], d[0]
|
||||
}
|
||||
return *((*uint64)(unsafe.Pointer(&b[0])))
|
||||
}
|
||||
|
||||
func (o *arrayBufferObject) setUint64(idx int, val uint64, byteOrder byteOrder) {
|
||||
if byteOrder == nativeEndian {
|
||||
*(*uint64)(unsafe.Pointer(&o.data[idx])) = val
|
||||
} else {
|
||||
b := (*[8]byte)(unsafe.Pointer(&val))
|
||||
d := o.data[idx : idx+8]
|
||||
d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7] = b[7], b[6], b[5], b[4], b[3], b[2], b[1], b[0]
|
||||
}
|
||||
}
|
||||
|
||||
func (o *arrayBufferObject) getUint32(idx int, byteOrder byteOrder) uint32 {
|
||||
var b []byte
|
||||
if byteOrder == nativeEndian {
|
||||
b = o.data[idx : idx+4]
|
||||
} else {
|
||||
b = make([]byte, 4)
|
||||
d := o.data[idx : idx+4]
|
||||
b[0], b[1], b[2], b[3] = d[3], d[2], d[1], d[0]
|
||||
}
|
||||
return *((*uint32)(unsafe.Pointer(&b[0])))
|
||||
}
|
||||
|
||||
func (o *arrayBufferObject) setUint32(idx int, val uint32, byteOrder byteOrder) {
|
||||
o.ensureNotDetached(true)
|
||||
if byteOrder == nativeEndian {
|
||||
*(*uint32)(unsafe.Pointer(&o.data[idx])) = val
|
||||
} else {
|
||||
b := (*[4]byte)(unsafe.Pointer(&val))
|
||||
d := o.data[idx : idx+4]
|
||||
d[0], d[1], d[2], d[3] = b[3], b[2], b[1], b[0]
|
||||
}
|
||||
}
|
||||
|
||||
func (o *arrayBufferObject) getUint16(idx int, byteOrder byteOrder) uint16 {
|
||||
var b []byte
|
||||
if byteOrder == nativeEndian {
|
||||
b = o.data[idx : idx+2]
|
||||
} else {
|
||||
b = make([]byte, 2)
|
||||
d := o.data[idx : idx+2]
|
||||
b[0], b[1] = d[1], d[0]
|
||||
}
|
||||
return *((*uint16)(unsafe.Pointer(&b[0])))
|
||||
}
|
||||
|
||||
func (o *arrayBufferObject) setUint16(idx int, val uint16, byteOrder byteOrder) {
|
||||
if byteOrder == nativeEndian {
|
||||
*(*uint16)(unsafe.Pointer(&o.data[idx])) = val
|
||||
} else {
|
||||
b := (*[2]byte)(unsafe.Pointer(&val))
|
||||
d := o.data[idx : idx+2]
|
||||
d[0], d[1] = b[1], b[0]
|
||||
}
|
||||
}
|
||||
|
||||
func (o *arrayBufferObject) getUint8(idx int) uint8 {
|
||||
return o.data[idx]
|
||||
}
|
||||
|
||||
func (o *arrayBufferObject) setUint8(idx int, val uint8) {
|
||||
o.data[idx] = val
|
||||
}
|
||||
|
||||
func (o *arrayBufferObject) getInt32(idx int, byteOrder byteOrder) int32 {
|
||||
return int32(o.getUint32(idx, byteOrder))
|
||||
}
|
||||
|
||||
func (o *arrayBufferObject) setInt32(idx int, val int32, byteOrder byteOrder) {
|
||||
o.setUint32(idx, uint32(val), byteOrder)
|
||||
}
|
||||
|
||||
func (o *arrayBufferObject) getInt16(idx int, byteOrder byteOrder) int16 {
|
||||
return int16(o.getUint16(idx, byteOrder))
|
||||
}
|
||||
|
||||
func (o *arrayBufferObject) setInt16(idx int, val int16, byteOrder byteOrder) {
|
||||
o.setUint16(idx, uint16(val), byteOrder)
|
||||
}
|
||||
|
||||
func (o *arrayBufferObject) getInt8(idx int) int8 {
|
||||
return int8(o.data[idx])
|
||||
}
|
||||
|
||||
func (o *arrayBufferObject) setInt8(idx int, val int8) {
|
||||
o.setUint8(idx, uint8(val))
|
||||
}
|
||||
|
||||
func (o *arrayBufferObject) detach() {
|
||||
o.data = nil
|
||||
o.detached = true
|
||||
}
|
||||
|
||||
func (o *arrayBufferObject) exportType() reflect.Type {
|
||||
return arrayBufferType
|
||||
}
|
||||
|
||||
func (o *arrayBufferObject) export(*objectExportCtx) interface{} {
|
||||
return ArrayBuffer{
|
||||
buf: o,
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Runtime) _newArrayBuffer(proto *Object, o *Object) *arrayBufferObject {
|
||||
if o == nil {
|
||||
o = &Object{runtime: r}
|
||||
}
|
||||
b := &arrayBufferObject{
|
||||
baseObject: baseObject{
|
||||
class: classObject,
|
||||
val: o,
|
||||
prototype: proto,
|
||||
extensible: true,
|
||||
},
|
||||
}
|
||||
o.self = b
|
||||
b.init()
|
||||
return b
|
||||
}
|
||||
|
||||
func init() {
|
||||
buf := [2]byte{}
|
||||
*(*uint16)(unsafe.Pointer(&buf[0])) = uint16(0xCAFE)
|
||||
|
||||
switch buf {
|
||||
case [2]byte{0xFE, 0xCA}:
|
||||
nativeEndian = littleEndian
|
||||
case [2]byte{0xCA, 0xFE}:
|
||||
nativeEndian = bigEndian
|
||||
default:
|
||||
panic("Could not determine native endianness.")
|
||||
}
|
||||
}
|
||||
137
server/vendor/github.com/dop251/goja/unistring/string.go
generated
vendored
Normal file
137
server/vendor/github.com/dop251/goja/unistring/string.go
generated
vendored
Normal file
@@ -0,0 +1,137 @@
|
||||
// Package unistring contains an implementation of a hybrid ASCII/UTF-16 string.
|
||||
// For ASCII strings the underlying representation is equivalent to a normal Go string.
|
||||
// For unicode strings the underlying representation is UTF-16 as []uint16 with 0th element set to 0xFEFF.
|
||||
// unicode.String allows representing malformed UTF-16 values (e.g. stand-alone parts of surrogate pairs)
|
||||
// which cannot be represented in UTF-8.
|
||||
// At the same time it is possible to use unicode.String as property keys just as efficiently as simple strings,
|
||||
// (the leading 0xFEFF ensures there is no clash with ASCII string), and it is possible to convert it
|
||||
// to valueString without extra allocations.
|
||||
package unistring
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"unicode/utf16"
|
||||
"unicode/utf8"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
BOM = 0xFEFF
|
||||
)
|
||||
|
||||
type String string
|
||||
|
||||
// Scan checks if the string contains any unicode characters. If it does, converts to an array suitable for creating
|
||||
// a String using FromUtf16, otherwise returns nil.
|
||||
func Scan(s string) []uint16 {
|
||||
utf16Size := 0
|
||||
for ; utf16Size < len(s); utf16Size++ {
|
||||
if s[utf16Size] >= utf8.RuneSelf {
|
||||
goto unicode
|
||||
}
|
||||
}
|
||||
return nil
|
||||
unicode:
|
||||
for _, chr := range s[utf16Size:] {
|
||||
utf16Size++
|
||||
if chr > 0xFFFF {
|
||||
utf16Size++
|
||||
}
|
||||
}
|
||||
|
||||
buf := make([]uint16, utf16Size+1)
|
||||
buf[0] = BOM
|
||||
c := 1
|
||||
for _, chr := range s {
|
||||
if chr <= 0xFFFF {
|
||||
buf[c] = uint16(chr)
|
||||
} else {
|
||||
first, second := utf16.EncodeRune(chr)
|
||||
buf[c] = uint16(first)
|
||||
c++
|
||||
buf[c] = uint16(second)
|
||||
}
|
||||
c++
|
||||
}
|
||||
|
||||
return buf
|
||||
}
|
||||
|
||||
func NewFromString(s string) String {
|
||||
if buf := Scan(s); buf != nil {
|
||||
return FromUtf16(buf)
|
||||
}
|
||||
return String(s)
|
||||
}
|
||||
|
||||
func NewFromRunes(s []rune) String {
|
||||
ascii := true
|
||||
size := 0
|
||||
for _, c := range s {
|
||||
if c >= utf8.RuneSelf {
|
||||
ascii = false
|
||||
if c > 0xFFFF {
|
||||
size++
|
||||
}
|
||||
}
|
||||
size++
|
||||
}
|
||||
if ascii {
|
||||
return String(s)
|
||||
}
|
||||
b := make([]uint16, size+1)
|
||||
b[0] = BOM
|
||||
i := 1
|
||||
for _, c := range s {
|
||||
if c <= 0xFFFF {
|
||||
b[i] = uint16(c)
|
||||
} else {
|
||||
first, second := utf16.EncodeRune(c)
|
||||
b[i] = uint16(first)
|
||||
i++
|
||||
b[i] = uint16(second)
|
||||
}
|
||||
i++
|
||||
}
|
||||
return FromUtf16(b)
|
||||
}
|
||||
|
||||
func FromUtf16(b []uint16) String {
|
||||
var str string
|
||||
hdr := (*reflect.StringHeader)(unsafe.Pointer(&str))
|
||||
hdr.Data = uintptr(unsafe.Pointer(&b[0]))
|
||||
hdr.Len = len(b) * 2
|
||||
|
||||
return String(str)
|
||||
}
|
||||
|
||||
func (s String) String() string {
|
||||
if b := s.AsUtf16(); b != nil {
|
||||
return string(utf16.Decode(b[1:]))
|
||||
}
|
||||
|
||||
return string(s)
|
||||
}
|
||||
|
||||
func (s String) AsUtf16() []uint16 {
|
||||
if len(s) < 4 || len(s)&1 != 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var a []uint16
|
||||
raw := string(s)
|
||||
|
||||
sliceHeader := (*reflect.SliceHeader)(unsafe.Pointer(&a))
|
||||
sliceHeader.Data = (*reflect.StringHeader)(unsafe.Pointer(&raw)).Data
|
||||
|
||||
l := len(raw) / 2
|
||||
|
||||
sliceHeader.Len = l
|
||||
sliceHeader.Cap = l
|
||||
|
||||
if a[0] == BOM {
|
||||
return a
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
1177
server/vendor/github.com/dop251/goja/value.go
generated
vendored
Normal file
1177
server/vendor/github.com/dop251/goja/value.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
5613
server/vendor/github.com/dop251/goja/vm.go
generated
vendored
Normal file
5613
server/vendor/github.com/dop251/goja/vm.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user