[
  {
    "path": ".clog.toml",
    "content": "[clog]\nrepository = \"https://github.com/robertkrimen/otto\"\nsubtitle = \"Release Notes\"\n\n[sections]\n\"Refactors\" = [\"refactor\"]\n\"Chores\" = [\"chore\"]\n\"Continuous Integration\" = [\"ci\"]\n\"Improvements\" = [\"imp\", \"improvement\"]\n\"Features\" = [\"feat\", \"feature\"]\n\"Legacy\" = [\"legacy\"]\n\"QA\" = [\"qa\", \"test\", \"tests\"]\n\"Documentation\" = [\"doc\", \"docs\"]\n"
  },
  {
    "path": ".github/workflows/release-build.yml",
    "content": "name: Build Release\n\non:\n  push:\n    tags:\n      - 'v[0-9]+.[0-9]+.[0-9]+*'\n\njobs:\n  goreleaser:\n    name: Release Go Binary\n    runs-on: [ubuntu-latest]\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n        with:\n          fetch-depth: 0\n      - name: Set up Go\n        uses: actions/setup-go@v5\n        with:\n          go-version: 1.23\n          cache: true\n      - name: Run GoReleaser\n        uses: goreleaser/goreleaser-action@v6\n        with:\n          # either 'goreleaser' (default) or 'goreleaser-pro'\n          distribution: goreleaser\n          version: latest\n          args: release --clean\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n          # Your GoReleaser Pro key, if you are using the 'goreleaser-pro' distribution\n          # GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}\n"
  },
  {
    "path": ".github/workflows/test-lint.yml",
    "content": "name: Go test and lint\n\non:\n  pull_request:\n    branches: 'master'\n\njobs:\n  go-test-lint:\n    strategy:\n      matrix:\n        go: [1.22, 1.23]\n        golangcli: [v1.61.0]\n        os: [ubuntu-latest]\n    runs-on: ${{ matrix.os }}\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n\n      - name: Set up Go\n        uses: actions/setup-go@v5\n        with:\n          go-version: ${{ matrix.go }}\n          cache: true\n\n      - name: Validate go mod / generate\n        run: |\n          go mod tidy\n          go install golang.org/x/tools/cmd/stringer@latest\n          go generate ./...\n          git --no-pager diff && [[ 0 -eq $(git status --porcelain | wc -l) ]]\n\n      - name: Go Lint\n        uses: golangci/golangci-lint-action@v4\n        with:\n          version: ${{ matrix.golangcli }}\n          args: --out-format=colored-line-number\n          skip-pkg-cache: true\n          skip-build-cache: true\n\n      - name: Go Build\n        run: go build ./...\n\n      - name: Go Test\n        run: go test -race -v ./...\n"
  },
  {
    "path": ".gitignore",
    "content": ".test\notto/otto\notto/otto-*\ntools/tester/testdata/\ntools/tester/tester\ntools/gen-jscore/gen-jscore\ntools/gen-tokens/gen-tokens\n.idea\ndist/\n.vscode/\n"
  },
  {
    "path": ".golangci.yml",
    "content": "run:\n  timeout: 6m\n\nlinters-settings:\n  govet:\n    settings:\n      shadow:\n        strict: true\n    enable-all: true\n  goconst:\n    min-len: 2\n    min-occurrences: 4\n  revive:\n    enable-all-rules: false\n    rules:\n    - name: var-naming\n      disabled: true\n  gosec:\n    excludes:\n      - G115 # Too many false positives.\n\nlinters:\n  enable-all: true\n  disable:\n    - dupl\n    - lll\n    - gochecknoglobals\n    - gochecknoinits\n    - funlen\n    - godox\n    - err113\n    - wsl\n    - nlreturn\n    - gomnd\n    - mnd\n    - paralleltest\n    - wrapcheck\n    - testpackage\n    - gocognit\n    - nestif\n    - exhaustive\n    - forcetypeassert\n    - gocyclo\n    - cyclop\n    - varnamelen\n    - maintidx\n    - ireturn\n    - exhaustruct\n    - dupword\n    # Just causes noise\n    - depguard\n    # Deprecated\n    - execinquery\n    # Not needed in go 1.22+\n    - exportloopref\n\nissues:\n  exclude-use-default: false\n  max-same-issues: 0\n  exclude:\n    - Deferring unsafe method \"Close\" on type \"io\\.ReadCloser\"\n  exclude-dirs:\n    - terst\n  exclude-files:\n    - dbg/dbg.go\n    - token/token_const.go\n  exclude-rules:\n    # Field alignment in tests isn't a performance issue.\n    - text: fieldalignment\n      path: _test\\.go\n    - text: Error return value of `fmt\\.Fprint.*` is not checked\n      path: tools/tester/main.go\n\n"
  },
  {
    "path": ".goreleaser.yaml",
    "content": "# When adding options check the documentation at https://goreleaser.com\nbefore:\n  hooks:\n    - go mod tidy\nbuilds:\n  - env:\n      - CGO_ENABLED=0\n    goos:\n      - linux\n      - darwin\n    goarch:\n      - amd64\n      - arm64\n    main: ./otto\n    id: otto\n    binary: otto\nuniversal_binaries:\n  - replace: true\n    id: otto\nchecksum:\n  name_template: 'checksums.txt'\nsnapshot:\n  name_template: \"{{ incpatch .Version }}-next\"\narchives:\n  - id: otto\n    name_template: \"{{ .Binary }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}{{ if .Mips }}_{{ .Mips }}{{ end }}\"\nrelease:\n  header: |\n    <a name=\"{{.Tag}}\"></a>\n    ### {{.Tag}} Release Notes ({{.Date}})\n  footer: |\n    [Full Changelog](https://{{ .ModulePath }}/compare/{{ .PreviousTag }}...{{ .Tag }})\nchangelog:\n  use: github\n  sort: asc\n  filters:\n    exclude:\n    - Merge pull request\n    - Merge remote-tracking branch\n    - Merge branch\n\n  # Group commits messages by given regex and title.\n  # Order value defines the order of the groups.\n  # Proving no regex means all commits will be grouped under the default group.\n  # Groups are disabled when using github-native, as it already groups things by itself.\n  # Matches are performed against strings of the form: \"<abbrev-commit> <title-commit>\".\n  # Regex use RE2 syntax as defined here: https://github.com/google/re2/wiki/Syntax.\n  #\n  # Default is no groups.\n  groups:\n    - title: Features\n      regexp: '^.*?(feat|feature)(\\([[:word:]]+\\))??!?:.+$'\n      order: 0\n    - title: 'Bug fixes'\n      regexp: '^.*?fix(\\([[:word:]]+\\))??!?:.+$'\n      order: 1\n    - title: 'Chores'\n      regexp: '^.*?chore(\\([[:word:]]+\\))??!?:.+$'\n      order: 2\n    - title: 'Quality'\n      regexp: '^.*?(qa|test|tests)(\\([[:word:]]+\\))??!?:.+$'\n      order: 3\n    - title: 'Documentation'\n      regexp: '^.*?(doc|docs)(\\([[:word:]]+\\))??!?:.+$'\n      order: 4\n    - title: 'Continuous Integration'\n      regexp: '^.*?ci(\\([[:word:]]+\\))??!?:.+$'\n      order: 5\n    - title: Other\n      order: 999\n"
  },
  {
    "path": "DESIGN.markdown",
    "content": "* Designate the filename of \"anonymous\" source code by the hash (md5/sha1, etc.)\n"
  },
  {
    "path": "LICENSE",
    "content": "Copyright (c) 2012 Robert Krimen\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n"
  },
  {
    "path": "README.md",
    "content": "# otto\n\n[![GoDoc Reference](https://pkg.go.dev/badge/github.com/robertkrimen/otto.svg)](https://pkg.go.dev/github.com/robertkrimen/otto)\n\n## Basic Usage\n\nPackage otto is a JavaScript parser and interpreter written natively in Go.\n\nTo use import it with the following:\n\n```go\nimport (\n   \"github.com/robertkrimen/otto\"\n)\n```\n\nRun something in the VM\n\n```go\nvm := otto.New()\nvm.Run(`\n    abc = 2 + 2;\n    console.log(\"The value of abc is \" + abc); // 4\n`)\n```\n\nGet a value out of the VM\n\n```go\nif value, err := vm.Get(\"abc\"); err == nil {\n    if value_int, err := value.ToInteger(); err == nil {\n        fmt.Println(value_int)\n    } else {\n        fmt.Printf(\"Error during conversion: %v\\n\", err)\n    }\n} else {\n    fmt.Printf(\"Error getting value: %v\\n\", err)\n}\n```\n\nSet a number\n\n```go\nvm.Set(\"def\", 11)\nvm.Run(`\n    console.log(\"The value of def is \" + def);\n    // The value of def is 11\n`)\n```\n\nSet a string\n\n```go\nvm.Set(\"xyzzy\", \"Nothing happens.\")\nvm.Run(`\n    console.log(xyzzy.length); // 16\n`)\n```\n\nGet the value of an expression\n\n```go\nvalue, _ = vm.Run(\"xyzzy.length\")\n{\n    // value is an int64 with a value of 16\n    value, _ := value.ToInteger()\n}\n```\n\nAn error happens\n\n```go\n_, err = vm.Run(\"abcdefghijlmnopqrstuvwxyz.length\")\nif err != nil {\n    // err = ReferenceError: abcdefghijlmnopqrstuvwxyz is not defined\n    // If there is an error, then value.IsUndefined() is true\n    ...\n}\n```\n\nSet a Go function\n\n```go\nvm.Set(\"sayHello\", func(call otto.FunctionCall) otto.Value {\n    fmt.Printf(\"Hello, %s.\\n\", call.Argument(0).String())\n    return otto.Value{}\n})\n```\n\nSet a Go function that returns something useful\n\n```go\nvm.Set(\"twoPlus\", func(call otto.FunctionCall) otto.Value {\n    right, _ := call.Argument(0).ToInteger()\n    result, _ := vm.ToValue(2 + right)\n    return result\n})\n```\n\nUse the functions in JavaScript\n\n```go\nresult, _ = vm.Run(`\n    sayHello(\"Xyzzy\");      // Hello, Xyzzy.\n    sayHello();             // Hello, undefined\n\n    result = twoPlus(2.0); // 4\n`)\n```\n\n## Parser\n\nA separate parser is available in the parser package if you're interested\nin only building an AST.\n\n[![GoDoc Reference](https://pkg.go.dev/badge/github.com/robertkrimen/otto/parser.svg)](https://pkg.go.dev/github.com/robertkrimen/otto/parser)\n\nParse and return an AST\n\n```go\nfilename := \"\" // A filename is optional\nsrc := `\n    // Sample xyzzy example\n    (function(){\n        if (3.14159 > 0) {\n            console.log(\"Hello, World.\");\n            return;\n        }\n\n        var xyzzy = NaN;\n        console.log(\"Nothing happens.\");\n        return xyzzy;\n    })();\n`\n\n// Parse some JavaScript, yielding a *ast.Program and/or an ErrorList\nprogram, err := parser.ParseFile(nil, filename, src, 0)\n```\n\n## Setup\n\nYou can run (Go) JavaScript from the command line with\n[otto](http://github.com/robertkrimen/otto/tree/master/otto).\n\n```shell\ngo install github.com/robertkrimen/otto/otto@latest\n```\n\nRun JavaScript by entering some source on stdin or by giving otto a filename:\n\n```shell\notto example.js\n```\n\n## Underscore\n\nOptionally include the JavaScript utility-belt library, underscore, with this\nimport:\n\n```go\nimport (\n    \"github.com/robertkrimen/otto\"\n    _ \"github.com/robertkrimen/otto/underscore\"\n)\n\n// Now every otto runtime will be initialized with Underscore.\n```\n\nFor more information: [underscore](http://github.com/robertkrimen/otto/tree/master/underscore)\n\n## Caveat Emptor\n\nThe following are some limitations with otto:\n\n* `use strict` will parse, but does nothing.\n* The regular expression engine ([re2/regexp](https://pkg.go.dev/regexp)) is not fully compatible with the ECMA5 specification.\n* Otto targets ES5. Some ES6 features, e.g. Typed Arrays, are not supported. Pull requests to add functionality are always welcome.\n\n### Regular Expression Incompatibility\n\nGo translates JavaScript-style regular expressions into something that is\n\"regexp\" compatible via `parser.TransformRegExp`. Unfortunately, RegExp requires\nbacktracking for some patterns, and backtracking is not supported by Go\n[re2](https://github.com/google/re2/wiki/syntax).\n\nTherefore, the following syntax is incompatible:\n\n```plaintext\n(?=)  // Lookahead (positive), currently a parsing error\n(?!)  // Lookahead (backhead), currently a parsing error\n\\1    // Backreference (\\1, \\2, \\3, ...), currently a parsing error\n```\n\nA brief discussion of these limitations: [Regexp (?!re)](https://groups.google.com/forum/?fromgroups=#%21topic/golang-nuts/7qgSDWPIh_E)\n\nMore information [about re2](https://github.com/google/re2)\n\nIn addition to the above, re2 (Go) has a different definition for `\\s`: `[\\t\\n\\f\\r\n]`. The JavaScript definition, on the other hand, also includes `\\v`, Unicode\n\"Separator, Space\", etc.\n\n### Halting Problem\n\nIf you want to stop long running executions (like third-party code), you can use\nthe interrupt channel to do this:\n\n```go\npackage main\n\nimport (\n    \"errors\"\n    \"fmt\"\n    \"os\"\n    \"time\"\n\n    \"github.com/robertkrimen/otto\"\n)\n\nvar halt = errors.New(\"Stahp\")\n\nfunc main() {\n    runUnsafe(`var abc = [];`)\n    runUnsafe(`\n    while (true) {\n        // Loop forever\n    }`)\n}\n\nfunc runUnsafe(unsafe string) {\n    start := time.Now()\n    defer func() {\n        duration := time.Since(start)\n        if caught := recover(); caught != nil {\n            if caught == halt {\n                fmt.Fprintf(os.Stderr, \"Some code took too long! Stopping after: %v\\n\", duration)\n                return\n            }\n            panic(caught) // Something else happened, repanic!\n        }\n        fmt.Fprintf(os.Stderr, \"Ran code successfully: %v\\n\", duration)\n    }()\n\n    vm := otto.New()\n    vm.Interrupt = make(chan func(), 1) // The buffer prevents blocking\n    watchdogCleanup := make(chan struct{})\n    defer close(watchdogCleanup)\n\n    go func() {\n        select {\n        case <-time.After(2 * time.Second): // Stop after two seconds\n            vm.Interrupt <- func() {\n                panic(halt)\n            }\n        case <-watchdogCleanup:\n        }\n        close(vm.Interrupt)\n    }()\n\n    vm.Run(unsafe) // Here be dragons (risky code)\n}\n```\n\nWhere is `setTimeout` / `setInterval`?\n\nThese timing functions are not part of the [ECMA-262 specification](https://ecma-international.org/publications-and-standards/standards/ecma-262/).\nThey typically belong to the window object in a browser environment. While it is\npossible to implement similar functionality in Go, it generally requires wrapping\nOtto in an event loop.\n\nFor an example of how this could be done in Go with otto, see [natto](http://github.com/robertkrimen/natto).\n\nHere is some more discussion of the issue:\n\n* [What is Node.js?](http://book.mixu.net/node/ch2.html)\n* [Reentrancy (computing)](http://en.wikipedia.org/wiki/Reentrancy_%28computing%29)\n* [Perl Safe Signals](https://metacpan.org/pod/Perl::Unsafe::Signals)\n\n## Usage\n\n```go\nvar ErrVersion = errors.New(\"version mismatch\")\n```\n\n### type Error\n\n```go\ntype Error struct {}\n```\n\nAn Error represents a runtime error, e.g. a `TypeError`, a `ReferenceError`, etc.\n\n### func (Error) Error\n\n```go\nfunc (err Error) Error() string\n```\n\nError returns a string representation of the error\n\n```plaintext\n    TypeError: 'def' is not a function\n```\n\n### func (Error) String\n\n```go\nfunc (err Error) String() string\n```\n\nString returns a description of the error and a trace of where the error\noccurred.\n\n```plaintext\n    TypeError: 'def' is not a function\n        at xyz (<anonymous>:3:9)\n        at <anonymous>:7:1/\n```\n\n### type FunctionCall\n\n```go\ntype FunctionCall struct {\n    This         Value\n    ArgumentList []Value\n    Otto         *Otto\n}\n```\n\nFunctionCall is an encapsulation of a JavaScript function call.\n\n### func (FunctionCall) Argument\n\n```go\nfunc (self FunctionCall) Argument(index int) Value\n```\n\nArgument will return the value of the argument at the given index.\n\nIf no such argument exists, undefined is returned.\n\n### type Object\n\n```go\ntype Object struct {}\n```\n\nObject is the representation of a JavaScript object.\n\n### func (Object) Call\n\n```go\nfunc (self Object) Call(name string, argumentList ...interface{}) (Value, error)\n```\n\nCall a method on the object.\n\nIt is essentially equivalent to:\n\n```go\nvar method, _ := object.Get(name)\nmethod.Call(object, argumentList...)\n```\n\nAn undefined value and an error will result if:\n\n1. There is an error during conversion of the argument list\n2. The property is not actually a function\n3. An (uncaught) exception is thrown\n\n### func (Object) Class\n\n```go\nfunc (self Object) Class() string\n```\n\nClass will return the class string of the object.\n\nThe return value will (generally) be one of:\n\n```plaintext\n    Object\n    Function\n    Array\n    String\n    Number\n    Boolean\n    Date\n    RegExp\n```\n\n### func (Object) Get\n\n```go\nfunc (self Object) Get(name string) (Value, error)\n```\n\nGet the value of the property with the given name.\n\n### func (Object) Keys\n\n```go\nfunc (self Object) Keys() []string\n```\n\nGet the keys for the object\n\nThis is equivalent to calling Object.keys on the object.\n\n### func (Object) Set\n\n```go\nfunc (self Object) Set(name string, value interface{}) error\n```\n\nSet the property of the given name to the given value.\n\nAn error will result if setting the property triggers an exception (e.g.\nread-only) or if there is an error during conversion of the given value.\n\n### func (Object) Value\n\n```go\nfunc (self Object) Value() Value\n```\n\nValue will return self as a value.\n\n### type Otto\n\n```go\ntype Otto struct {\n    // Interrupt is a channel for interrupting the runtime. You can use this to halt a long running execution, for example.\n    // See \"Halting Problem\" for more information.\n    Interrupt chan func()\n}\n```\n\nOtto is the representation of the JavaScript runtime. Each instance of Otto has\na self-contained namespace.\n\n### func New\n\n```go\nfunc New() *Otto\n```\n\nNew will allocate a new JavaScript runtime\n\n### func Run\n\n```go\nfunc Run(src interface{}) (*Otto, Value, error)\n```\n\nRun will allocate a new JavaScript runtime, run the given source on the\nallocated runtime, and return the runtime, resulting value, and error (if any).\n\nsrc may be a string, a byte slice, a bytes.Buffer, or an io.Reader, but it MUST\nalways be in UTF-8.\n\nsrc may also be a Script.\n\nsrc may also be a Program, but if the AST has been modified, then runtime\nbehavior is undefined.\n\n### func (Otto) Call\n\n```go\nfunc (self Otto) Call(source string, this interface{}, argumentList ...interface{}) (Value, error)\n```\n\nCall the given JavaScript with a given this and arguments.\n\nIf this is nil, then some special handling takes place to determine the proper\nthis value, falling back to a \"standard\" invocation if necessary (where this is\nundefined).\n\nIf source begins with \"new \" (A lowercase new followed by a space), then Call\nwill invoke the function constructor rather than performing a function call. In\nthis case, the this argument has no effect.\n\n```go\n// value is a String object\nvalue, _ := vm.Call(\"Object\", nil, \"Hello, World.\")\n\n// Likewise...\nvalue, _ := vm.Call(\"new Object\", nil, \"Hello, World.\")\n\n// This will perform a concat on the given array and return the result\n// value is [ 1, 2, 3, undefined, 4, 5, 6, 7, \"abc\" ]\nvalue, _ := vm.Call(`[ 1, 2, 3, undefined, 4 ].concat`, nil, 5, 6, 7, \"abc\")\n```\n\n### func (*Otto) Compile\n\n```go\nfunc (self *Otto) Compile(filename string, src interface{}) (*Script, error)\n```\n\nCompile will parse the given source and return a Script value. If there is an error during compilation, it will return nil and an error.\n\n```go\nscript, err := vm.Compile(\"\", `var abc; if (!abc) abc = 0; abc += 2; abc;`)\nvm.Run(script)\n```\n\n### func (*Otto) Copy\n\n```go\nfunc (in *Otto) Copy() *Otto\n```\n\nCopy will create a copy/clone of the runtime.\n\nCopy is useful for saving some time when creating many similar runtimes.\n\nThis method works by walking the original runtime and cloning each object,\nscope, stash, etc. into a new runtime.\n\nBe on the lookout for memory leaks or inadvertent sharing of resources.\n\n### func (Otto) Get\n\n```go\nfunc (self Otto) Get(name string) (Value, error)\n```\n\nGet the value of the top-level binding of the given name.\n\nIf there is an error (like the binding does not exist), then the value will be\nundefined.\n\n### func (Otto) Object\n\n```go\nfunc (self Otto) Object(source string) (*Object, error)\n```\n\nObject will run the given source and return the result as an object.\n\nFor example, accessing an existing object:\n\n```go\nobject, _ := vm.Object(`Number`)\n```\n\nOr, creating a new object:\n\n```go\nobject, _ := vm.Object(`({ xyzzy: \"Nothing happens.\" })`)\n```\n\nOr, creating and assigning an object:\n\n```go\nobject, _ := vm.Object(`xyzzy = {}`)\nobject.Set(\"volume\", 11)\n```\n\nIf there is an error (like the source does not result in an object), then nil\nand an error is returned.\n\n### func (Otto) Run\n\n```go\nfunc (self Otto) Run(src interface{}) (Value, error)\n```\n\nRun will run the given source (parsing it first if necessary), returning the\nresulting value and error (if any)\n\nsrc may be a string, a byte slice, a bytes.Buffer, or an io.Reader, but it MUST\nalways be in UTF-8.\n\nIf the runtime is unable to parse source, then this function will return\nundefined and the parse error (nothing will be evaluated in this case).\n\nsrc may also be a Script.\n\nsrc may also be a Program, but if the AST has been modified, then runtime\nbehavior is undefined.\n\n### func (Otto) Set\n\n```go\nfunc (self Otto) Set(name string, value interface{}) error\n```\n\nSet the top-level binding of the given name to the given value.\n\nSet will automatically apply ToValue to the given value in order to convert it\nto a JavaScript value (type Value).\n\nIf there is an error (like the binding is read-only, or the ToValue conversion\nfails), then an error is returned.\n\nIf the top-level binding does not exist, it will be created.\n\n### func (Otto) ToValue\n\n```go\nfunc (self Otto) ToValue(value interface{}) (Value, error)\n```\n\nToValue will convert an interface{} value to a value digestible by\notto/JavaScript.\n\n### type Script\n\n```go\ntype Script struct {}\n```\n\nScript is a handle for some (reusable) JavaScript. Passing a Script value to a\nrun method will evaluate the JavaScript.\n\n### func (*Script) String\n\n```go\nfunc (self *Script) String() string\n```\n\n### type Value\n\n```go\ntype Value struct {}\n```\n\nValue is the representation of a JavaScript value.\n\n### func FalseValue\n\n```go\nfunc FalseValue() Value\n```\n\nFalseValue will return a Value representing the bool value false.\n\nIt is equivalent to:\n\n```go\nToValue(false)\n```\n\n### func  NaNValue\n\n```go\nfunc NaNValue() Value\n```\n\nNaNValue will return a value representing NaN.\n\nIt is equivalent to:\n\n```go\nToValue(math.NaN())\n```\n\n### func  NullValue\n\n```go\nfunc NullValue() Value\n```\n\nNullValue will return a Value representing null.\n\n### func  ToValue\n\n```go\nfunc ToValue(value interface{}) (Value, error)\n```\n\nToValue will convert an interface{} value to a value digestible by\notto/JavaScript\n\nThis function will not work for advanced types (struct, map, slice/array, etc.)\nand you should use Otto.ToValue instead.\n\n### func  TrueValue\n\n```go\nfunc TrueValue() Value\n```\n\nTrueValue will return a value representing true.\n\nIt is equivalent to:\n\n```go\nToValue(true)\n```\n\n### func UndefinedValue\n\n```go\nfunc UndefinedValue() Value\n```\n\nUndefinedValue will return a Value representing undefined.\n\n### func (Value) Call\n\n```go\nfunc (value Value) Call(this Value, argumentList ...interface{}) (Value, error)\n```\n\nCall the value as a function with the given this value and argument list and\nreturn the result of invocation. It is essentially equivalent to:\n\n```js\n    value.apply(thisValue, argumentList)\n```\n\nA value of undefined and an error will result if:\n\n1. There is an error during conversion of the argument list\n2. The value is not actually a function\n3. An (uncaught) exception is thrown\n\n### func (Value) Class\n\n```go\nfunc (value Value) Class() string\n```\n\nClass will return the class string of the value or the empty string if value is\nnot an object.\n\nThe return value will (generally) be one of:\n\n```plaintext\n    Object\n    Function\n    Array\n    String\n    Number\n    Boolean\n    Date\n    RegExp\n```\n\n### func (Value) Export\n\n```go\nfunc (self Value) Export() (interface{}, error)\n```\n\nExport will attempt to convert the value to a Go representation and return it\nvia an interface{} kind.\n\nExport returns an error, which will always be nil. It is included for backwards\ncompatibility.\n\nIf a reasonable conversion is not possible, then the original value is returned.\n\n```plaintext\n    undefined   -> nil (FIXME?: Should be Value{})\n    null        -> nil\n    boolean     -> bool\n    number      -> A number type (int, float32, uint64, ...)\n    string      -> string\n    Array       -> []interface{}\n    Object      -> map[string]interface{}\n```\n\n### func (Value) IsBoolean\n\n```go\nfunc (value Value) IsBoolean() bool\n```\n\nIsBoolean will return true if value is a boolean (primitive).\n\n### func (Value) IsDefined\n\n```go\nfunc (value Value) IsDefined() bool\n```\n\nIsDefined will return false if the value is undefined, and true otherwise.\n\n### func (Value) IsFunction\n\n```go\nfunc (value Value) IsFunction() bool\n```\n\nIsFunction will return true if value is a function.\n\n### func (Value) IsNaN\n\n```go\nfunc (value Value) IsNaN() bool\n```\n\nIsNaN will return true if value is NaN (or would convert to NaN).\n\n### func (Value) IsNull\n\n```go\nfunc (value Value) IsNull() bool\n```\n\nIsNull will return true if the value is null, and false otherwise.\n\n### func (Value) IsNumber\n\n```go\nfunc (value Value) IsNumber() bool\n```\n\nIsNumber will return true if value is a number (primitive).\n\n### func (Value) IsObject\n\n```go\nfunc (value Value) IsObject() bool\n```\n\nIsObject will return true if value is an object.\n\n### func (Value) IsPrimitive\n\n```go\nfunc (value Value) IsPrimitive() bool\n```\n\nIsPrimitive will return true if value is a primitive.\n\n### func (Value) IsString\n\n```go\nfunc (value Value) IsString() bool\n```\n\nIsString will return true if value is a string (primitive).\n\n### func (Value) IsUndefined\n\n```go\nfunc (value Value) IsUndefined() bool\n```\n\nIsUndefined will return true if the value is undefined, and false otherwise.\n\n### func (Value) Object\n\n```go\nfunc (value Value) Object() *Object\n```\n\nObject will return the object of the value, or nil if value is not an object.\n\nThis method will not do any implicit conversion. For example, calling this\nmethod on a string primitive value will not return a String object.\n\n### func (Value) String\n\n```go\nfunc (value Value) String() string\n```\n\nString will return the value as a string.\n\nThis method will return the empty string if there is an error.\n\n### func (Value) ToBoolean\n\n```go\nfunc (value Value) ToBoolean() (bool, error)\n```\n\nToBoolean will convert the value to a boolean (bool).\n\n```plaintext\n    ToValue(0).ToBoolean() => false\n    ToValue(\"\").ToBoolean() => false\n    ToValue(true).ToBoolean() => true\n    ToValue(1).ToBoolean() => true\n    ToValue(\"Nothing happens\").ToBoolean() => true\n```\n\nIf there is an error during the conversion process (like an uncaught exception),\nthen the result will be false and an error.\n\n### func (Value) ToFloat\n\n```go\nfunc (value Value) ToFloat() (float64, error)\n```\n\nToFloat will convert the value to a number (float64).\n\n```plaintext\n    ToValue(0).ToFloat() => 0.\n    ToValue(1.1).ToFloat() => 1.1\n    ToValue(\"11\").ToFloat() => 11.\n```\n\nIf there is an error during the conversion process (like an uncaught exception),\nthen the result will be 0 and an error.\n\n### func (Value) ToInteger\n\n```go\nfunc (value Value) ToInteger() (int64, error)\n```\n\nToInteger will convert the value to a number (int64).\n\n```plaintext\n    ToValue(0).ToInteger() => 0\n    ToValue(1.1).ToInteger() => 1\n    ToValue(\"11\").ToInteger() => 11\n```\n\nIf there is an error during the conversion process (like an uncaught exception),\nthen the result will be 0 and an error.\n\n### func (Value) ToString\n\n```go\nfunc (value Value) ToString() (string, error)\n```\n\nToString will convert the value to a string (string).\n\n```plaintext\n    ToValue(0).ToString() => \"0\"\n    ToValue(false).ToString() => \"false\"\n    ToValue(1.1).ToString() => \"1.1\"\n    ToValue(\"11\").ToString() => \"11\"\n    ToValue('Nothing happens.').ToString() => \"Nothing happens.\"\n```\n\nIf there is an error during the conversion process (like an uncaught exception),\nthen the result will be the empty string (\"\") and an error.\n"
  },
  {
    "path": "array_test.go",
    "content": "package otto\n\nimport (\n\t\"testing\"\n)\n\nfunc TestArray(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            var abc = [ undefined, \"Nothing happens.\" ];\n            abc.length;\n        `, 2)\n\n\t\ttest(`\n            abc = \"\"+[0, 1, 2, 3];\n            def = [].toString();\n            ghi = [null, 4, \"null\"].toString();\n            [ abc, def, ghi ];\n        `, \"0,1,2,3,,,4,null\")\n\n\t\ttest(`new Array(0).length`, 0)\n\n\t\ttest(`new Array(11).length`, 11)\n\n\t\ttest(`new Array(11, 1).length`, 2)\n\n\t\ttest(`\n            abc = [0, 1, 2, 3];\n            abc.xyzzy = \"Nothing happens.\";\n            delete abc[1];\n            var xyzzy = delete abc.xyzzy;\n            [ abc, xyzzy, abc.xyzzy ];\n        `, \"0,,2,3,true,\")\n\n\t\ttest(`\n            var abc = [0, 1, 2, 3, 4];\n            abc.length = 2;\n            abc;\n        `, \"0,1\")\n\n\t\ttest(`raise:\n            [].length = 3.14159;\n        `, \"RangeError\")\n\n\t\ttest(`raise:\n            new Array(3.14159);\n        `, \"RangeError\")\n\n\t\ttest(`\n            Object.defineProperty(Array.prototype, \"0\", {\n                value: 100,\n                writable: false,\n                configurable: true\n            });\n            abc = [101];\n            abc.hasOwnProperty(\"0\") && abc[0] === 101;\n        `, true)\n\n\t\ttest(`\n            abc = [,,undefined];\n            [ abc.hasOwnProperty(0), abc.hasOwnProperty(1), abc.hasOwnProperty(2) ];\n        `, \"false,false,true\")\n\n\t\ttest(`\n            abc = Object.getOwnPropertyDescriptor(Array, \"prototype\");\n            [   [ typeof Array.prototype ],\n                [ abc.writable, abc.enumerable, abc.configurable ] ];\n        `, \"object,false,false,false\")\n\t})\n}\n\nfunc TestArray_toString(t *testing.T) {\n\ttt(t, func() {\n\t\t{\n\t\t\ttest(`\n                Array.prototype.toString = function() {\n                    return \"Nothing happens.\";\n                }\n                abc = Array.prototype.toString();\n                def = [].toString();\n                ghi = [null, 4, \"null\"].toString();\n\n                [ abc, def, ghi ].join(\",\");\n            `, \"Nothing happens.,Nothing happens.,Nothing happens.\")\n\t\t}\n\n\t\t{\n\t\t\ttest(`\n                Array.prototype.join = undefined\n                abc = Array.prototype.toString()\n                def = [].toString()\n                ghi = [null, 4, \"null\"].toString()\n\n                abc + \",\" + def + \",\" + ghi;\n            `, \"[object Array],[object Array],[object Array]\")\n\t\t}\n\t})\n}\n\nfunc TestArray_toLocaleString(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\tdefer mockUTC()()\n\n\t\ttest(`\n            [ 3.14159, \"abc\", undefined, new Date(0) ].toLocaleString();\n        `, \"3.142,abc,,1970-01-01 00:00:00\")\n\n\t\ttest(`raise:\n            [ { toLocaleString: undefined } ].toLocaleString();\n        `, `TypeError: Array.toLocaleString index[0] \"undefined\" is not callable`)\n\t})\n}\n\nfunc TestArray_concat(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            abc = [0, 1, 2];\n            def = [-1, -2, -3];\n            ghi = abc.concat(def);\n            jkl = abc.concat(def, 3, 4, 5);\n            mno = def.concat(-4, -5, abc);\n\n            [ ghi, jkl, mno ].join(\";\");\n        `, \"0,1,2,-1,-2,-3;0,1,2,-1,-2,-3,3,4,5;-1,-2,-3,-4,-5,0,1,2\")\n\n\t\ttest(`\n            var abc = [,1];\n            var def = abc.concat([], [,]);\n\n            def.getClass = Object.prototype.toString;\n\n            [ def.getClass(), typeof def[0], def[1], typeof def[2], def.length ];\n        `, \"[object Array],undefined,1,undefined,3\")\n\n\t\ttest(`\n            Object.defineProperty(Array.prototype, \"0\", {\n                value: 100,\n                writable: false,\n                configurable: true\n            });\n\n            var abc = Array.prototype.concat.call(101);\n\n            var hasProperty = abc.hasOwnProperty(\"0\");\n            var instanceOfVerify = typeof abc[0] === \"object\";\n            var verifyValue = false;\n            verifyValue = abc[0] == 101;\n\n            var verifyEnumerable = false;\n            for (var property in abc) {\n                if (property === \"0\" && abc.hasOwnProperty(\"0\")) {\n                    verifyEnumerable = true;\n                }\n            }\n\n            var verifyWritable = false;\n            abc[0] = 12;\n            verifyWritable = abc[0] === 12;\n\n            var verifyConfigurable = false;\n            delete abc[0];\n            verifyConfigurable = abc.hasOwnProperty(\"0\");\n\n            [ hasProperty, instanceOfVerify, verifyValue, !verifyConfigurable, verifyEnumerable, verifyWritable ];\n        `, \"true,true,true,true,true,true\")\n\t})\n}\n\nfunc TestArray_splice(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            abc = [0, 1, 2];\n            def = abc.splice(1, 2, 3, 4, 5);\n            ghi = [].concat(abc);\n            jkl = ghi.splice(17, 21, 7, 8, 9);\n            mno = [].concat(abc);\n            pqr = mno.splice(2);\n            [ abc, def, ghi, jkl, mno, pqr ].join(\";\");\n        `, \"0,3,4,5;1,2;0,3,4,5,7,8,9;;0,3;4,5\")\n\t})\n}\n\nfunc TestArray_shift(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            abc = [0, 1, 2];\n            def = abc.shift();\n            ghi = [].concat(abc);\n            jkl = abc.shift();\n            mno = [].concat(abc);\n            pqr = abc.shift();\n            stu = [].concat(abc);\n            vwx = abc.shift();\n\n            [ abc, def, ghi, jkl, mno, pqr, stu, vwx ].join(\";\");\n        `, \";0;1,2;1;2;2;;\")\n\t})\n}\n\nfunc TestArray_push(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            abc = [0];\n            def = abc.push(1);\n            ghi = [].concat(abc);\n            jkl = abc.push(2,3,4);\n\n            [ abc, def, ghi, jkl ].join(\";\");\n        `, \"0,1,2,3,4;2;0,1;5\")\n\t})\n}\n\nfunc TestArray_pop(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            abc = [0,1];\n            def = abc.pop();\n            ghi = [].concat(abc);\n            jkl = abc.pop();\n            mno = [].concat(abc);\n            pqr = abc.pop();\n\n            [ abc, def, ghi, jkl, mno, pqr ].join(\";\");\n        `, \";1;0;0;;\")\n\t})\n}\n\nfunc TestArray_slice(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            abc = [0,1,2,3];\n            def = abc.slice();\n            ghi = abc.slice(1);\n            jkl = abc.slice(3,-1);\n            mno = abc.slice(2,-1);\n            pqr = abc.slice(-1, -10);\n\n            [ abc, def, ghi, jkl, mno, pqr ].join(\";\");\n        `, \"0,1,2,3;0,1,2,3;1,2,3;;2;\")\n\n\t\t// Array.protoype.slice is generic\n\t\ttest(`\n            abc = { 0: 0, 1: 1, 2: 2, 3: 3 };\n            abc.length = 4;\n            def = Array.prototype.slice.call(abc);\n            ghi = Array.prototype.slice.call(abc,1);\n            jkl = Array.prototype.slice.call(abc,3,-1);\n            mno = Array.prototype.slice.call(abc,2,-1);\n            pqr = Array.prototype.slice.call(abc,-1,-10);\n\n            [ abc, def, ghi, jkl, pqr ].join(\";\");\n        `, \"[object Object];0,1,2,3;1,2,3;;\")\n\t})\n}\n\nfunc TestArray_sliceArguments(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            (function(){\n                return Array.prototype.slice.call(arguments, 1)\n            })({}, 1, 2, 3);\n        `, \"1,2,3\")\n\t})\n}\n\nfunc TestArray_unshift(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            abc = [];\n            def = abc.unshift(0);\n            ghi = [].concat(abc);\n            jkl = abc.unshift(1,2,3,4);\n\n            [ abc, def, ghi, jkl ].join(\";\");\n        `, \"1,2,3,4,0;1;0;5\")\n\t})\n}\n\nfunc TestArray_reverse(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            abc = [0,1,2,3].reverse();\n            def = [0,1,2].reverse();\n\n            [ abc, def ];\n        `, \"3,2,1,0,2,1,0\")\n\t})\n}\n\nfunc TestArray_sort(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            abc = [0,1,2,3].sort();\n            def = [3,2,1,0].sort();\n            ghi = [].sort();\n            jkl = [0].sort();\n            mno = [1,0].sort();\n            pqr = [1,5,-10, 100, 8, 72, 401, 0.05].sort();\n            stu = [1,5,-10, 100, 8, 72, 401, 0.05].sort(function(x, y){\n                return x == y ? 0 : x < y ? -1 : 1\n            });\n            vwx = [1,2,3,1,2,3].sort();\n            yza = [1,2,3,1,0,1,-1,0].sort();\n\n            [ abc, def, ghi, jkl, mno, pqr, stu, vwx, yza ].join(\";\");\n        `, \"0,1,2,3;0,1,2,3;;0;0,1;-10,0.05,1,100,401,5,72,8;-10,0.05,1,5,8,72,100,401;1,1,2,2,3,3;-1,0,0,1,1,1,2,3\")\n\n\t\ttest(`Array.prototype.sort.length`, 1)\n\t})\n}\n\nfunc TestArray_isArray(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n        [ Array.isArray.length, Array.isArray(), Array.isArray([]), Array.isArray({}) ];\n        `, \"1,false,true,false\")\n\n\t\ttest(`Array.isArray(Math)`, false)\n\t})\n}\n\nfunc TestArray_indexOf(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`['a', 'b', 'c', 'b'].indexOf('b')`, 1)\n\n\t\ttest(`['a', 'b', 'c', 'b'].indexOf('b', 2)`, 3)\n\n\t\ttest(`['a', 'b', 'c', 'b'].indexOf('b', -2)`, 3)\n\n\t\ttest(`\n            Object.prototype.indexOf = Array.prototype.indexOf;\n            var abc = {0: 'a', 1: 'b', 2: 'c', length: 3};\n            abc.indexOf('c');\n        `, 2)\n\n\t\ttest(`[true].indexOf(true, \"-Infinity\")`, 0)\n\n\t\ttest(`\n            var target = {};\n            Math[3] = target;\n            Math.length = 5;\n            Array.prototype.indexOf.call(Math, target) === 3;\n        `, true)\n\n\t\ttest(`\n            var _NaN = NaN;\n            var abc = new Array(\"NaN\", undefined, 0, false, null, {toString:function(){return NaN}}, \"false\", _NaN, NaN);\n            abc.indexOf(NaN);\n        `, -1)\n\n\t\ttest(`\n            var abc = {toString:function (){return 0}};\n            var def = 1;\n            var ghi = -(4/3);\n            var jkl = new Array(false, undefined, null, \"0\", abc, -1.3333333333333, \"string\", -0, true, +0, def, 1, 0, false, ghi, -(4/3));\n            [ jkl.indexOf(-(4/3)), jkl.indexOf(0), jkl.indexOf(-0), jkl.indexOf(1) ];\n        `, \"14,7,7,10\")\n\t})\n}\n\nfunc TestArray_lastIndexOf(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`['a', 'b', 'c', 'b'].lastIndexOf('b')`, 3)\n\n\t\ttest(`['a', 'b', 'c', 'b'].lastIndexOf('b', 2)`, 1)\n\n\t\ttest(`['a', 'b', 'c', 'b'].lastIndexOf('b', -2)`, 1)\n\n\t\ttest(`\n            Object.prototype.lastIndexOf = Array.prototype.lastIndexOf;\n            var abc = {0: 'a', 1: 'b', 2: 'c', 3: 'b', length: 4};\n            abc.lastIndexOf('b');\n        `, 3)\n\n\t\ttest(`\n            var target = {};\n            Math[3] = target;\n            Math.length = 5;\n            [ Array.prototype.lastIndexOf.call(Math, target) === 3 ];\n        `, \"true\")\n\n\t\ttest(`\n            var _NaN = NaN;\n            var abc = new Array(\"NaN\", undefined, 0, false, null, {toString:function(){return NaN}}, \"false\", _NaN, NaN);\n            abc.lastIndexOf(NaN);\n        `, -1)\n\n\t\ttest(`\n            var abc = {toString:function (){return 0}};\n            var def = 1;\n            var ghi = -(4/3);\n            var jkl = new Array(false, undefined, null, \"0\", abc, -1.3333333333333, \"string\", -0, true, +0, def, 1, 0, false, ghi, -(4/3));\n            [ jkl.lastIndexOf(-(4/3)), jkl.indexOf(0), jkl.indexOf(-0), jkl.indexOf(1) ];\n        `, \"15,7,7,10\")\n\t})\n}\n\nfunc TestArray_every(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`raise: [].every()`, `TypeError: Array.every argument \"undefined\" is not callable`)\n\n\t\ttest(`raise: [].every(\"abc\")`, `TypeError: Array.every argument \"abc\" is not callable`)\n\n\t\ttest(`[].every(function() { return false })`, true)\n\n\t\ttest(`[1,2,3].every(function() { return false })`, false)\n\n\t\ttest(`[1,2,3].every(function() { return true })`, true)\n\n\t\ttest(`[1,2,3].every(function(_, index) { if (index === 1) return true })`, false)\n\n\t\ttest(`\n            var abc = function(value, index, object) {\n                return ('[object Math]' !== Object.prototype.toString.call(object));\n            };\n\n            Math.length = 1;\n            Math[0] = 1;\n            !Array.prototype.every.call(Math, abc);\n        `, true)\n\n\t\ttest(`\n            var def = false;\n\n            var abc = function(value, index, object) {\n                def = true;\n                return this === Math;\n            };\n\n            [11].every(abc, Math) && def;\n        `, true)\n\n\t\ttest(`\n            var def = false;\n\n            var abc = function(value, index, object) {\n                def = true;\n                return Math;\n            };\n\n            [11].every(abc) && def;\n        `, true)\n\t})\n}\n\nfunc TestArray_some(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`raise: [].some(\"abc\")`, `TypeError: Array.some \"abc\" if not callable`)\n\n\t\ttest(`[].some(function() { return true })`, false)\n\n\t\ttest(`[1,2,3].some(function() { return false })`, false)\n\n\t\ttest(`[1,2,3].some(function() { return true })`, true)\n\n\t\ttest(`[1,2,3].some(function(_, index) { if (index === 1) return true })`, true)\n\n\t\ttest(`\n            var abc = function(value, index, object) {\n                return ('[object Math]' !== Object.prototype.toString.call(object));\n            };\n\n            Math.length = 1;\n            Math[0] = 1;\n            !Array.prototype.some.call(Math, abc);\n        `, true)\n\n\t\ttest(`\n            var abc = function(value, index, object) {\n                return this === Math;\n            };\n\n            [11].some(abc, Math);\n        `, true)\n\n\t\ttest(`\n            var abc = function(value, index, object) {\n                return Math;\n            };\n\n            [11].some(abc);\n        `, true)\n\t})\n}\n\nfunc TestArray_forEach(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`raise: [].forEach(\"abc\")`, `TypeError: Array.foreach \"abc\" if not callable`)\n\n\t\ttest(`\n            var abc = 0;\n            [].forEach(function(value) {\n                abc += value;\n            });\n            abc;\n        `, 0)\n\n\t\ttest(`\n            abc = 0;\n            var def = [];\n            [1,2,3].forEach(function(value, index) {\n                abc += value;\n                def.push(index);\n            });\n            [ abc, def ];\n        `, \"6,0,1,2\")\n\n\t\ttest(`\n            var def = false;\n            var abc = function(value, index, object) {\n                def = ('[object Math]' === Object.prototype.toString.call(object));\n            };\n\n            Math.length = 1;\n            Math[0] = 1;\n            Array.prototype.forEach.call(Math, abc);\n            def;\n        `, true)\n\n\t\ttest(`\n            var def = false;\n            var abc = function(value, index, object) {\n                def = this === Math;\n            };\n\n            [11].forEach(abc, Math);\n            def;\n        `, true)\n\t})\n}\n\nfunc TestArray_indexing(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            var abc = new Array(0, 1);\n            var def = abc.length;\n            abc[4294967296] = 10; // 2^32 => 0\n            abc[4294967297] = 11; // 2^32+1 => 1\n            [ def, abc.length, abc[0], abc[1], abc[4294967296] ];\n        `, \"2,2,0,1,10\")\n\n\t\ttest(`\n            abc = new Array(0, 1);\n            def = abc.length;\n            abc[4294967295] = 10;\n            var ghi = abc.length;\n            abc[4294967299] = 12;\n            var jkl = abc.length;\n            abc[4294967294] = 11;\n            [ def, ghi, jkl, abc.length, abc[4294967295], abc[4294967299] ];\n        `, \"2,2,2,4294967295,10,12\")\n\t})\n}\n\nfunc TestArray_map(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`raise: [].map(\"abc\")`, `TypeError: Array.foreach \"abc\" if not callable`)\n\n\t\ttest(`[].map(function() { return 1 }).length`, 0)\n\n\t\ttest(`[1,2,3].map(function(value) { return value * value })`, \"1,4,9\")\n\n\t\ttest(`[1,2,3].map(function(value) { return 1 })`, \"1,1,1\")\n\n\t\ttest(`\n            var abc = function(value, index, object) {\n                return ('[object Math]' === Object.prototype.toString.call(object));\n            };\n\n            Math.length = 1;\n            Math[0] = 1;\n            Array.prototype.map.call(Math, abc)[0];\n        `, true)\n\n\t\ttest(`\n            var abc = function(value, index, object) {\n                return this === Math;\n            };\n\n            [11].map(abc, Math)[0];\n        `, true)\n\t})\n}\n\nfunc TestArray_filter(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`raise: [].filter(\"abc\")`, `TypeError: Array.filter \"abc\" if not callable`)\n\n\t\ttest(`[].filter(function() { return 1 }).length`, 0)\n\n\t\ttest(`[1,2,3].filter(function() { return false }).length`, 0)\n\n\t\ttest(`[1,2,3].filter(function() { return true })`, \"1,2,3\")\n\t})\n}\n\nfunc TestArray_reduce(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`raise: [].reduce(\"abc\")`, `TypeError: Array.reduce \"abc\" if not callable`)\n\n\t\ttest(`raise: [].reduce(function() {})`, `TypeError: Array.reduce \"function() {}\" if not callable`)\n\n\t\ttest(`[].reduce(function() {}, 0)`, 0)\n\n\t\ttest(`[].reduce(function() {}, undefined)`, \"undefined\")\n\n\t\ttest(`['a','b','c'].reduce(function(result, value) { return result+', '+value })`, \"a, b, c\")\n\n\t\ttest(`[1,2,3].reduce(function(result, value) { return result + value }, 4)`, 10)\n\n\t\ttest(`[1,2,3].reduce(function(result, value) { return result + value })`, 6)\n\t})\n}\n\nfunc TestArray_reduceRight(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`raise: [].reduceRight(\"abc\")`, `TypeError: Array.reduceRight \"abc\" if not callable`)\n\n\t\ttest(`raise: [].reduceRight(function() {})`, `TypeError: Array.reduceRight \"function() {}\" if not callable`)\n\n\t\ttest(`[].reduceRight(function() {}, 0)`, 0)\n\n\t\ttest(`[].reduceRight(function() {}, undefined)`, \"undefined\")\n\n\t\ttest(`['a','b','c'].reduceRight(function(result, value) { return result+', '+value })`, \"c, b, a\")\n\n\t\ttest(`[1,2,3].reduceRight(function(result, value) { return result + value }, 4)`, 10)\n\n\t\ttest(`[1,2,3].reduceRight(function(result, value) { return result + value })`, 6)\n\t})\n}\n\nfunc TestArray_defineOwnProperty(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            var abc = [];\n            Object.defineProperty(abc, \"length\", {\n                writable: false\n            });\n            abc.length;\n        `, 0)\n\n\t\ttest(`raise:\n            var abc = [];\n            var exception;\n            Object.defineProperty(abc, \"length\", {\n                writable: false\n            });\n            Object.defineProperty(abc, \"length\", {\n                writable: true\n            });\n        `, `TypeError: Object.DefineOwnProperty: property not configurable or writeable and descriptor not writeable`)\n\t})\n}\n\nfunc TestArray_new(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            var abc = new Array(null);\n            var def = new Array(undefined);\n            [ abc.length, abc[0] === null, def.length, def[0] === undefined ]\n        `, \"1,true,1,true\")\n\n\t\ttest(`\n            var abc = new Array(new Number(0));\n            var def = new Array(new Number(4294967295));\n            [ abc.length, typeof abc[0], abc[0] == 0, def.length, typeof def[0], def[0] == 4294967295 ]\n        `, \"1,object,true,1,object,true\")\n\t})\n}\n"
  },
  {
    "path": "ast/comments.go",
    "content": "package ast\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/robertkrimen/otto/file\"\n)\n\n// CommentPosition determines where the comment is in a given context.\ntype CommentPosition int\n\n// Available comment positions.\nconst (\n\t_ CommentPosition = iota\n\t// LEADING is before the pertinent expression.\n\tLEADING\n\t// TRAILING is after the pertinent expression.\n\tTRAILING\n\t// KEY is before a key in an object.\n\tKEY\n\t// COLON is after a colon in a field declaration.\n\tCOLON\n\t// FINAL is the final comments in a block, not belonging to a specific expression or the comment after a trailing , in an array or object literal.\n\tFINAL\n\t// IF is after an if keyword.\n\tIF\n\t// WHILE is after a while keyword.\n\tWHILE\n\t// DO is after do keyword.\n\tDO\n\t// FOR is after a for keyword.\n\tFOR\n\t// WITH is after a with keyword.\n\tWITH\n\t// TBD is unknown.\n\tTBD\n)\n\n// Comment contains the data of the comment.\ntype Comment struct {\n\tText     string\n\tBegin    file.Idx\n\tPosition CommentPosition\n}\n\n// NewComment creates a new comment.\nfunc NewComment(text string, idx file.Idx) *Comment {\n\tcomment := &Comment{\n\t\tBegin:    idx,\n\t\tText:     text,\n\t\tPosition: TBD,\n\t}\n\n\treturn comment\n}\n\n// String returns a stringified version of the position.\nfunc (cp CommentPosition) String() string {\n\tswitch cp {\n\tcase LEADING:\n\t\treturn \"Leading\"\n\tcase TRAILING:\n\t\treturn \"Trailing\"\n\tcase KEY:\n\t\treturn \"Key\"\n\tcase COLON:\n\t\treturn \"Colon\"\n\tcase FINAL:\n\t\treturn \"Final\"\n\tcase IF:\n\t\treturn \"If\"\n\tcase WHILE:\n\t\treturn \"While\"\n\tcase DO:\n\t\treturn \"Do\"\n\tcase FOR:\n\t\treturn \"For\"\n\tcase WITH:\n\t\treturn \"With\"\n\tdefault:\n\t\treturn \"???\"\n\t}\n}\n\n// String returns a stringified version of the comment.\nfunc (c Comment) String() string {\n\treturn fmt.Sprintf(\"Comment: %v\", c.Text)\n}\n\n// Comments defines the current view of comments from the parser.\ntype Comments struct {\n\t// CommentMap is a reference to the parser comment map\n\tCommentMap CommentMap\n\t// Comments lists the comments scanned, not linked to a node yet\n\tComments []*Comment\n\t// Current is node for which comments are linked to\n\tCurrent Expression\n\n\t// future lists the comments after a line break during a sequence of comments\n\tfuture []*Comment\n\t// wasLineBreak determines if a line break occurred while scanning for comments\n\twasLineBreak bool\n\t// primary determines whether or not processing a primary expression\n\tprimary bool\n\t// afterBlock determines whether or not being after a block statement\n\tafterBlock bool\n}\n\n// NewComments returns a new Comments.\nfunc NewComments() *Comments {\n\tcomments := &Comments{\n\t\tCommentMap: CommentMap{},\n\t}\n\n\treturn comments\n}\n\nfunc (c *Comments) String() string {\n\treturn fmt.Sprintf(\"NODE: %v, Comments: %v, Future: %v(LINEBREAK:%v)\", c.Current, len(c.Comments), len(c.future), c.wasLineBreak)\n}\n\n// FetchAll returns all the currently scanned comments,\n// including those from the next line.\nfunc (c *Comments) FetchAll() []*Comment {\n\tdefer func() {\n\t\tc.Comments = nil\n\t\tc.future = nil\n\t}()\n\n\treturn append(c.Comments, c.future...)\n}\n\n// Fetch returns all the currently scanned comments.\nfunc (c *Comments) Fetch() []*Comment {\n\tdefer func() {\n\t\tc.Comments = nil\n\t}()\n\n\treturn c.Comments\n}\n\n// ResetLineBreak marks the beginning of a new statement.\nfunc (c *Comments) ResetLineBreak() {\n\tc.wasLineBreak = false\n}\n\n// MarkPrimary will mark the context as processing a primary expression.\nfunc (c *Comments) MarkPrimary() {\n\tc.primary = true\n\tc.wasLineBreak = false\n}\n\n// AfterBlock will mark the context as being after a block.\nfunc (c *Comments) AfterBlock() {\n\tc.afterBlock = true\n}\n\n// AddComment adds a comment to the view.\n// Depending on the context, comments are added normally or as post line break.\nfunc (c *Comments) AddComment(comment *Comment) {\n\tif c.primary {\n\t\tif !c.wasLineBreak {\n\t\t\tc.Comments = append(c.Comments, comment)\n\t\t} else {\n\t\t\tc.future = append(c.future, comment)\n\t\t}\n\t} else {\n\t\tif !c.wasLineBreak || (c.Current == nil && !c.afterBlock) {\n\t\t\tc.Comments = append(c.Comments, comment)\n\t\t} else {\n\t\t\tc.future = append(c.future, comment)\n\t\t}\n\t}\n}\n\n// MarkComments will mark the found comments as the given position.\nfunc (c *Comments) MarkComments(position CommentPosition) {\n\tfor _, comment := range c.Comments {\n\t\tif comment.Position == TBD {\n\t\t\tcomment.Position = position\n\t\t}\n\t}\n\tfor _, c := range c.future {\n\t\tif c.Position == TBD {\n\t\t\tc.Position = position\n\t\t}\n\t}\n}\n\n// Unset the current node and apply the comments to the current expression.\n// Resets context variables.\nfunc (c *Comments) Unset() {\n\tif c.Current != nil {\n\t\tc.applyComments(c.Current, c.Current, TRAILING)\n\t\tc.Current = nil\n\t}\n\tc.wasLineBreak = false\n\tc.primary = false\n\tc.afterBlock = false\n}\n\n// SetExpression sets the current expression.\n// It is applied the found comments, unless the previous expression has not been unset.\n// It is skipped if the node is already set or if it is a part of the previous node.\nfunc (c *Comments) SetExpression(node Expression) {\n\t// Skipping same node\n\tif c.Current == node {\n\t\treturn\n\t}\n\tif c.Current != nil && c.Current.Idx1() == node.Idx1() {\n\t\tc.Current = node\n\t\treturn\n\t}\n\tprevious := c.Current\n\tc.Current = node\n\n\t// Apply the found comments and futures to the node and the previous.\n\tc.applyComments(node, previous, TRAILING)\n}\n\n// PostProcessNode applies all found comments to the given node.\nfunc (c *Comments) PostProcessNode(node Node) {\n\tc.applyComments(node, nil, TRAILING)\n}\n\n// applyComments applies both the comments and the future comments to the given node and the previous one,\n// based on the context.\nfunc (c *Comments) applyComments(node, previous Node, position CommentPosition) {\n\tif previous != nil {\n\t\tc.CommentMap.AddComments(previous, c.Comments, position)\n\t\tc.Comments = nil\n\t} else {\n\t\tc.CommentMap.AddComments(node, c.Comments, position)\n\t\tc.Comments = nil\n\t}\n\t// Only apply the future comments to the node if the previous is set.\n\t// This is for detecting end of line comments and which node comments on the following lines belongs to\n\tif previous != nil {\n\t\tc.CommentMap.AddComments(node, c.future, position)\n\t\tc.future = nil\n\t}\n}\n\n// AtLineBreak will mark a line break.\nfunc (c *Comments) AtLineBreak() {\n\tc.wasLineBreak = true\n}\n\n// CommentMap is the data structure where all found comments are stored.\ntype CommentMap map[Node][]*Comment\n\n// AddComment adds a single comment to the map.\nfunc (cm CommentMap) AddComment(node Node, comment *Comment) {\n\tlist := cm[node]\n\tlist = append(list, comment)\n\n\tcm[node] = list\n}\n\n// AddComments adds a slice of comments, given a node and an updated position.\nfunc (cm CommentMap) AddComments(node Node, comments []*Comment, position CommentPosition) {\n\tfor _, comment := range comments {\n\t\tif comment.Position == TBD {\n\t\t\tcomment.Position = position\n\t\t}\n\t\tcm.AddComment(node, comment)\n\t}\n}\n\n// Size returns the size of the map.\nfunc (cm CommentMap) Size() int {\n\tsize := 0\n\tfor _, comments := range cm {\n\t\tsize += len(comments)\n\t}\n\n\treturn size\n}\n\n// MoveComments moves comments with a given position from a node to another.\nfunc (cm CommentMap) MoveComments(from, to Node, position CommentPosition) {\n\tfor i, c := range cm[from] {\n\t\tif c.Position == position {\n\t\t\tcm.AddComment(to, c)\n\n\t\t\t// Remove the comment from the \"from\" slice\n\t\t\tcm[from][i] = cm[from][len(cm[from])-1]\n\t\t\tcm[from][len(cm[from])-1] = nil\n\t\t\tcm[from] = cm[from][:len(cm[from])-1]\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "ast/comments_test.go",
    "content": "package ast\n\nimport (\n\t\"testing\"\n\n\t\"github.com/robertkrimen/otto/file\"\n)\n\nfunc TestCommentMap(t *testing.T) {\n\tstatement := &EmptyStatement{file.Idx(1)}\n\tcomment := &Comment{Begin: 1, Text: \"test\", Position: LEADING}\n\n\tcm := CommentMap{}\n\tcm.AddComment(statement, comment)\n\n\tif cm.Size() != 1 {\n\t\tt.Errorf(\"the number of comments is %v, not 1\", cm.Size())\n\t}\n\n\tif len(cm[statement]) != 1 {\n\t\tt.Errorf(\"the number of comments is %v, not 1\", cm.Size())\n\t}\n\n\tif cm[statement][0].Text != \"test\" {\n\t\tt.Errorf(\"the text is %v, not \\\"test\\\"\", cm[statement][0].Text)\n\t}\n}\n\nfunc TestCommentMap_move(t *testing.T) {\n\tstatement1 := &EmptyStatement{file.Idx(1)}\n\tstatement2 := &EmptyStatement{file.Idx(2)}\n\tcomment := &Comment{Begin: 1, Text: \"test\", Position: LEADING}\n\n\tcm := CommentMap{}\n\tcm.AddComment(statement1, comment)\n\n\tif cm.Size() != 1 {\n\t\tt.Errorf(\"the number of comments is %v, not 1\", cm.Size())\n\t}\n\n\tif len(cm[statement1]) != 1 {\n\t\tt.Errorf(\"the number of comments is %v, not 1\", cm.Size())\n\t}\n\n\tif len(cm[statement2]) != 0 {\n\t\tt.Errorf(\"the number of comments is %v, not 0\", cm.Size())\n\t}\n\n\tcm.MoveComments(statement1, statement2, LEADING)\n\n\tif cm.Size() != 1 {\n\t\tt.Errorf(\"the number of comments is %v, not 1\", cm.Size())\n\t}\n\n\tif len(cm[statement2]) != 1 {\n\t\tt.Errorf(\"the number of comments is %v, not 1\", cm.Size())\n\t}\n\n\tif len(cm[statement1]) != 0 {\n\t\tt.Errorf(\"the number of comments is %v, not 0\", cm.Size())\n\t}\n}\n"
  },
  {
    "path": "ast/node.go",
    "content": "// Package ast declares types representing a JavaScript AST.\n//\n// # Warning\n// The parser and AST interfaces are still works-in-progress (particularly where\n// node types are concerned) and may change in the future.\npackage ast\n\nimport (\n\t\"github.com/robertkrimen/otto/file\"\n\t\"github.com/robertkrimen/otto/token\"\n)\n\n// Node is implemented by types that represent a node.\ntype Node interface {\n\tIdx0() file.Idx // The index of the first character belonging to the node\n\tIdx1() file.Idx // The index of the first character immediately after the node\n}\n\n// Expression is implemented by types that represent an Expression.\ntype Expression interface {\n\tNode\n\texpression()\n}\n\n// ArrayLiteral represents an array literal.\ntype ArrayLiteral struct {\n\tValue        []Expression\n\tLeftBracket  file.Idx\n\tRightBracket file.Idx\n}\n\n// Idx0 implements Node.\nfunc (al *ArrayLiteral) Idx0() file.Idx {\n\treturn al.LeftBracket\n}\n\n// Idx1 implements Node.\nfunc (al *ArrayLiteral) Idx1() file.Idx {\n\treturn al.RightBracket + 1\n}\n\n// expression implements Expression.\nfunc (*ArrayLiteral) expression() {}\n\n// AssignExpression represents an assignment expression.\ntype AssignExpression struct {\n\tLeft     Expression\n\tRight    Expression\n\tOperator token.Token\n}\n\n// Idx0 implements Node.\nfunc (ae *AssignExpression) Idx0() file.Idx {\n\treturn ae.Left.Idx0()\n}\n\n// Idx1 implements Node.\nfunc (ae *AssignExpression) Idx1() file.Idx {\n\treturn ae.Right.Idx1()\n}\n\n// expression implements Expression.\nfunc (*AssignExpression) expression() {}\n\n// BadExpression represents a bad expression.\ntype BadExpression struct {\n\tFrom file.Idx\n\tTo   file.Idx\n}\n\n// Idx0 implements Node.\nfunc (be *BadExpression) Idx0() file.Idx {\n\treturn be.From\n}\n\n// Idx1 implements Node.\nfunc (be *BadExpression) Idx1() file.Idx {\n\treturn be.To\n}\n\n// expression implements Expression.\nfunc (*BadExpression) expression() {}\n\n// BinaryExpression represents a binary expression.\ntype BinaryExpression struct {\n\tLeft       Expression\n\tRight      Expression\n\tOperator   token.Token\n\tComparison bool\n}\n\n// Idx0 implements Node.\nfunc (be *BinaryExpression) Idx0() file.Idx {\n\treturn be.Left.Idx0()\n}\n\n// Idx1 implements Node.\nfunc (be *BinaryExpression) Idx1() file.Idx {\n\treturn be.Right.Idx1()\n}\n\n// expression implements Expression.\nfunc (*BinaryExpression) expression() {}\n\n// BooleanLiteral represents a boolean expression.\ntype BooleanLiteral struct {\n\tLiteral string\n\tIdx     file.Idx\n\tValue   bool\n}\n\n// Idx0 implements Node.\nfunc (bl *BooleanLiteral) Idx0() file.Idx {\n\treturn bl.Idx\n}\n\n// Idx1 implements Node.\nfunc (bl *BooleanLiteral) Idx1() file.Idx {\n\treturn file.Idx(int(bl.Idx) + len(bl.Literal))\n}\n\n// expression implements Expression.\nfunc (*BooleanLiteral) expression() {}\n\n// BracketExpression represents a bracketed expression.\ntype BracketExpression struct {\n\tLeft         Expression\n\tMember       Expression\n\tLeftBracket  file.Idx\n\tRightBracket file.Idx\n}\n\n// Idx0 implements Node.\nfunc (be *BracketExpression) Idx0() file.Idx {\n\treturn be.Left.Idx0()\n}\n\n// Idx1 implements Node.\nfunc (be *BracketExpression) Idx1() file.Idx {\n\treturn be.RightBracket + 1\n}\n\n// expression implements Expression.\nfunc (*BracketExpression) expression() {}\n\n// CallExpression represents a call expression.\ntype CallExpression struct {\n\tCallee           Expression\n\tArgumentList     []Expression\n\tLeftParenthesis  file.Idx\n\tRightParenthesis file.Idx\n}\n\n// Idx0 implements Node.\nfunc (ce *CallExpression) Idx0() file.Idx {\n\treturn ce.Callee.Idx0()\n}\n\n// Idx1 implements Node.\nfunc (ce *CallExpression) Idx1() file.Idx {\n\treturn ce.RightParenthesis + 1\n}\n\n// expression implements Expression.\nfunc (*CallExpression) expression() {}\n\n// ConditionalExpression represents a conditional expression.\ntype ConditionalExpression struct {\n\tTest       Expression\n\tConsequent Expression\n\tAlternate  Expression\n}\n\n// Idx0 implements Node.\nfunc (ce *ConditionalExpression) Idx0() file.Idx {\n\treturn ce.Test.Idx0()\n}\n\n// Idx1 implements Node.\nfunc (ce *ConditionalExpression) Idx1() file.Idx {\n\treturn ce.Alternate.Idx1()\n}\n\n// expression implements Expression.\nfunc (*ConditionalExpression) expression() {}\n\n// DotExpression represents a dot expression.\ntype DotExpression struct {\n\tLeft       Expression\n\tIdentifier *Identifier\n}\n\n// Idx0 implements Node.\nfunc (de *DotExpression) Idx0() file.Idx {\n\treturn de.Left.Idx0()\n}\n\n// Idx1 implements Node.\nfunc (de *DotExpression) Idx1() file.Idx {\n\treturn de.Identifier.Idx1()\n}\n\n// expression implements Expression.\nfunc (*DotExpression) expression() {}\n\n// EmptyExpression represents an empty expression.\ntype EmptyExpression struct {\n\tBegin file.Idx\n\tEnd   file.Idx\n}\n\n// Idx0 implements Node.\nfunc (ee *EmptyExpression) Idx0() file.Idx {\n\treturn ee.Begin\n}\n\n// Idx1 implements Node.\nfunc (ee *EmptyExpression) Idx1() file.Idx {\n\treturn ee.End\n}\n\n// expression implements Expression.\nfunc (*EmptyExpression) expression() {}\n\n// FunctionLiteral represents a function literal.\ntype FunctionLiteral struct {\n\tBody            Statement\n\tName            *Identifier\n\tParameterList   *ParameterList\n\tSource          string\n\tDeclarationList []Declaration\n\tFunction        file.Idx\n}\n\n// Idx0 implements Node.\nfunc (fl *FunctionLiteral) Idx0() file.Idx {\n\treturn fl.Function\n}\n\n// Idx1 implements Node.\nfunc (fl *FunctionLiteral) Idx1() file.Idx {\n\treturn fl.Body.Idx1()\n}\n\n// expression implements Expression.\nfunc (*FunctionLiteral) expression() {}\n\n// Identifier represents an identifier.\ntype Identifier struct {\n\tName string\n\tIdx  file.Idx\n}\n\n// Idx0 implements Node.\nfunc (i *Identifier) Idx0() file.Idx {\n\treturn i.Idx\n}\n\n// Idx1 implements Node.\nfunc (i *Identifier) Idx1() file.Idx {\n\treturn file.Idx(int(i.Idx) + len(i.Name))\n}\n\n// expression implements Expression.\nfunc (*Identifier) expression() {}\n\n// NewExpression represents a new expression.\ntype NewExpression struct {\n\tCallee           Expression\n\tArgumentList     []Expression\n\tNew              file.Idx\n\tLeftParenthesis  file.Idx\n\tRightParenthesis file.Idx\n}\n\n// Idx0 implements Node.\nfunc (ne *NewExpression) Idx0() file.Idx {\n\treturn ne.New\n}\n\n// Idx1 implements Node.\nfunc (ne *NewExpression) Idx1() file.Idx {\n\tif ne.RightParenthesis > 0 {\n\t\treturn ne.RightParenthesis + 1\n\t}\n\treturn ne.Callee.Idx1()\n}\n\n// expression implements Expression.\nfunc (*NewExpression) expression() {}\n\n// NullLiteral represents a null literal.\ntype NullLiteral struct {\n\tLiteral string\n\tIdx     file.Idx\n}\n\n// Idx0 implements Node.\nfunc (nl *NullLiteral) Idx0() file.Idx {\n\treturn nl.Idx\n}\n\n// Idx1 implements Node.\nfunc (nl *NullLiteral) Idx1() file.Idx {\n\treturn file.Idx(int(nl.Idx) + 4)\n}\n\n// expression implements Expression.\nfunc (*NullLiteral) expression() {}\n\n// NumberLiteral represents a number literal.\ntype NumberLiteral struct {\n\tValue   interface{}\n\tLiteral string\n\tIdx     file.Idx\n}\n\n// Idx0 implements Node.\nfunc (nl *NumberLiteral) Idx0() file.Idx {\n\treturn nl.Idx\n}\n\n// Idx1 implements Node.\nfunc (nl *NumberLiteral) Idx1() file.Idx {\n\treturn file.Idx(int(nl.Idx) + len(nl.Literal))\n}\n\n// expression implements Expression.\nfunc (*NumberLiteral) expression() {}\n\n// ObjectLiteral represents an object literal.\ntype ObjectLiteral struct {\n\tValue      []Property\n\tLeftBrace  file.Idx\n\tRightBrace file.Idx\n}\n\n// Idx0 implements Node.\nfunc (ol *ObjectLiteral) Idx0() file.Idx {\n\treturn ol.LeftBrace\n}\n\n// Idx1 implements Node.\nfunc (ol *ObjectLiteral) Idx1() file.Idx {\n\treturn ol.RightBrace + 1\n}\n\n// expression implements Expression.\nfunc (*ObjectLiteral) expression() {}\n\n// ParameterList represents a parameter list.\ntype ParameterList struct {\n\tList    []*Identifier\n\tOpening file.Idx\n\tClosing file.Idx\n}\n\n// Property represents a property.\ntype Property struct {\n\tValue Expression\n\tKey   string\n\tKind  string\n}\n\n// RegExpLiteral represents a regular expression literal.\ntype RegExpLiteral struct {\n\tLiteral string\n\tPattern string\n\tFlags   string\n\tValue   string\n\tIdx     file.Idx\n}\n\n// Idx0 implements Node.\nfunc (rl *RegExpLiteral) Idx0() file.Idx {\n\treturn rl.Idx\n}\n\n// Idx1 implements Node.\nfunc (rl *RegExpLiteral) Idx1() file.Idx {\n\treturn file.Idx(int(rl.Idx) + len(rl.Literal))\n}\n\n// expression implements Expression.\nfunc (*RegExpLiteral) expression() {}\n\n// SequenceExpression represents a sequence literal.\ntype SequenceExpression struct {\n\tSequence []Expression\n}\n\n// Idx0 implements Node.\nfunc (se *SequenceExpression) Idx0() file.Idx {\n\treturn se.Sequence[0].Idx0()\n}\n\n// Idx1 implements Node.\nfunc (se *SequenceExpression) Idx1() file.Idx {\n\treturn se.Sequence[len(se.Sequence)-1].Idx1()\n}\n\n// expression implements Expression.\nfunc (*SequenceExpression) expression() {}\n\n// StringLiteral represents a string literal.\ntype StringLiteral struct {\n\tLiteral string\n\tValue   string\n\tIdx     file.Idx\n}\n\n// Idx0 implements Node.\nfunc (sl *StringLiteral) Idx0() file.Idx {\n\treturn sl.Idx\n}\n\n// Idx1 implements Node.\nfunc (sl *StringLiteral) Idx1() file.Idx {\n\treturn file.Idx(int(sl.Idx) + len(sl.Literal))\n}\n\n// expression implements Expression.\nfunc (*StringLiteral) expression() {}\n\n// ThisExpression represents a this expression.\ntype ThisExpression struct {\n\tIdx file.Idx\n}\n\n// Idx0 implements Node.\nfunc (te *ThisExpression) Idx0() file.Idx {\n\treturn te.Idx\n}\n\n// Idx1 implements Node.\nfunc (te *ThisExpression) Idx1() file.Idx {\n\treturn te.Idx + 4\n}\n\n// expression implements Expression.\nfunc (*ThisExpression) expression() {}\n\n// UnaryExpression represents a unary expression.\ntype UnaryExpression struct {\n\tOperand  Expression\n\tOperator token.Token\n\tIdx      file.Idx\n\tPostfix  bool\n}\n\n// Idx0 implements Node.\nfunc (ue *UnaryExpression) Idx0() file.Idx {\n\tif ue.Postfix {\n\t\treturn ue.Operand.Idx0()\n\t}\n\treturn ue.Idx\n}\n\n// Idx1 implements Node.\nfunc (ue *UnaryExpression) Idx1() file.Idx {\n\tif ue.Postfix {\n\t\treturn ue.Operand.Idx1() + 2 // ++ --\n\t}\n\treturn ue.Operand.Idx1()\n}\n\n// expression implements Expression.\nfunc (*UnaryExpression) expression() {}\n\n// VariableExpression represents a variable expression.\ntype VariableExpression struct {\n\tInitializer Expression\n\tName        string\n\tIdx         file.Idx\n}\n\n// Idx0 implements Node.\nfunc (ve *VariableExpression) Idx0() file.Idx {\n\treturn ve.Idx\n}\n\n// Idx1 implements Node.\nfunc (ve *VariableExpression) Idx1() file.Idx {\n\tif ve.Initializer == nil {\n\t\treturn file.Idx(int(ve.Idx) + len(ve.Name))\n\t}\n\treturn ve.Initializer.Idx1()\n}\n\n// expression implements Expression.\nfunc (*VariableExpression) expression() {}\n\n// Statement is implemented by types which represent a statement.\ntype Statement interface {\n\tNode\n\tstatement()\n}\n\n// BadStatement represents a bad statement.\ntype BadStatement struct {\n\tFrom file.Idx\n\tTo   file.Idx\n}\n\n// Idx0 implements Node.\nfunc (bs *BadStatement) Idx0() file.Idx {\n\treturn bs.From\n}\n\n// Idx1 implements Node.\nfunc (bs *BadStatement) Idx1() file.Idx {\n\treturn bs.To\n}\n\n// expression implements Statement.\nfunc (*BadStatement) statement() {}\n\n// BlockStatement represents a block statement.\ntype BlockStatement struct {\n\tList       []Statement\n\tLeftBrace  file.Idx\n\tRightBrace file.Idx\n}\n\n// Idx0 implements Node.\nfunc (bs *BlockStatement) Idx0() file.Idx {\n\treturn bs.LeftBrace\n}\n\n// Idx1 implements Node.\nfunc (bs *BlockStatement) Idx1() file.Idx {\n\treturn bs.RightBrace + 1\n}\n\n// expression implements Statement.\nfunc (*BlockStatement) statement() {}\n\n// BranchStatement represents a branch statement.\ntype BranchStatement struct {\n\tLabel *Identifier\n\tIdx   file.Idx\n\tToken token.Token\n}\n\n// Idx0 implements Node.\nfunc (bs *BranchStatement) Idx0() file.Idx {\n\treturn bs.Idx\n}\n\n// Idx1 implements Node.\nfunc (bs *BranchStatement) Idx1() file.Idx {\n\tif bs.Label == nil {\n\t\treturn file.Idx(int(bs.Idx) + len(bs.Token.String()))\n\t}\n\treturn bs.Label.Idx1()\n}\n\n// expression implements Statement.\nfunc (*BranchStatement) statement() {}\n\n// CaseStatement represents a case statement.\ntype CaseStatement struct {\n\tTest       Expression\n\tConsequent []Statement\n\tCase       file.Idx\n}\n\n// Idx0 implements Node.\nfunc (cs *CaseStatement) Idx0() file.Idx {\n\treturn cs.Case\n}\n\n// Idx1 implements Node.\nfunc (cs *CaseStatement) Idx1() file.Idx {\n\treturn cs.Consequent[len(cs.Consequent)-1].Idx1()\n}\n\n// expression implements Statement.\nfunc (*CaseStatement) statement() {}\n\n// CatchStatement represents a catch statement.\ntype CatchStatement struct {\n\tBody      Statement\n\tParameter *Identifier\n\tCatch     file.Idx\n}\n\n// Idx0 implements Node.\nfunc (cs *CatchStatement) Idx0() file.Idx {\n\treturn cs.Catch\n}\n\n// Idx1 implements Node.\nfunc (cs *CatchStatement) Idx1() file.Idx {\n\treturn cs.Body.Idx1()\n}\n\n// expression implements Statement.\nfunc (*CatchStatement) statement() {}\n\n// DebuggerStatement represents a debugger statement.\ntype DebuggerStatement struct {\n\tDebugger file.Idx\n}\n\n// Idx0 implements Node.\nfunc (ds *DebuggerStatement) Idx0() file.Idx {\n\treturn ds.Debugger\n}\n\n// Idx1 implements Node.\nfunc (ds *DebuggerStatement) Idx1() file.Idx {\n\treturn ds.Debugger + 8\n}\n\n// expression implements Statement.\nfunc (*DebuggerStatement) statement() {}\n\n// DoWhileStatement represents a do while statement.\ntype DoWhileStatement struct {\n\tTest             Expression\n\tBody             Statement\n\tDo               file.Idx\n\tRightParenthesis file.Idx\n}\n\n// Idx0 implements Node.\nfunc (dws *DoWhileStatement) Idx0() file.Idx {\n\treturn dws.Do\n}\n\n// Idx1 implements Node.\nfunc (dws *DoWhileStatement) Idx1() file.Idx {\n\treturn dws.RightParenthesis + 1\n}\n\n// expression implements Statement.\nfunc (*DoWhileStatement) statement() {}\n\n// EmptyStatement represents a empty statement.\ntype EmptyStatement struct {\n\tSemicolon file.Idx\n}\n\n// Idx0 implements Node.\nfunc (es *EmptyStatement) Idx0() file.Idx {\n\treturn es.Semicolon\n}\n\n// Idx1 implements Node.\nfunc (es *EmptyStatement) Idx1() file.Idx {\n\treturn es.Semicolon + 1\n}\n\n// expression implements Statement.\nfunc (*EmptyStatement) statement() {}\n\n// ExpressionStatement represents a expression statement.\ntype ExpressionStatement struct {\n\tExpression Expression\n}\n\n// Idx0 implements Node.\nfunc (es *ExpressionStatement) Idx0() file.Idx {\n\treturn es.Expression.Idx0()\n}\n\n// Idx1 implements Node.\nfunc (es *ExpressionStatement) Idx1() file.Idx {\n\treturn es.Expression.Idx1()\n}\n\n// expression implements Statement.\nfunc (*ExpressionStatement) statement() {}\n\n// ForInStatement represents a for in statement.\ntype ForInStatement struct {\n\tInto   Expression\n\tSource Expression\n\tBody   Statement\n\tFor    file.Idx\n}\n\n// Idx0 implements Node.\nfunc (fis *ForInStatement) Idx0() file.Idx {\n\treturn fis.For\n}\n\n// Idx1 implements Node.\nfunc (fis *ForInStatement) Idx1() file.Idx {\n\treturn fis.Body.Idx1()\n}\n\n// expression implements Statement.\nfunc (*ForInStatement) statement() {}\n\n// ForStatement represents a for statement.\ntype ForStatement struct {\n\tInitializer Expression\n\tUpdate      Expression\n\tTest        Expression\n\tBody        Statement\n\tFor         file.Idx\n}\n\n// Idx0 implements Node.\nfunc (fs *ForStatement) Idx0() file.Idx {\n\treturn fs.For\n}\n\n// Idx1 implements Node.\nfunc (fs *ForStatement) Idx1() file.Idx {\n\treturn fs.Body.Idx1()\n}\n\n// expression implements Statement.\nfunc (*ForStatement) statement() {}\n\n// FunctionStatement represents a function statement.\ntype FunctionStatement struct {\n\tFunction *FunctionLiteral\n}\n\n// Idx0 implements Node.\nfunc (fs *FunctionStatement) Idx0() file.Idx {\n\treturn fs.Function.Idx0()\n}\n\n// Idx1 implements Node.\nfunc (fs *FunctionStatement) Idx1() file.Idx {\n\treturn fs.Function.Idx1()\n}\n\n// expression implements Statement.\nfunc (*FunctionStatement) statement() {}\n\n// IfStatement represents a if statement.\ntype IfStatement struct {\n\tTest       Expression\n\tConsequent Statement\n\tAlternate  Statement\n\tIf         file.Idx\n}\n\n// Idx0 implements Node.\nfunc (is *IfStatement) Idx0() file.Idx {\n\treturn is.If\n}\n\n// Idx1 implements Node.\nfunc (is *IfStatement) Idx1() file.Idx {\n\tif is.Alternate != nil {\n\t\treturn is.Alternate.Idx1()\n\t}\n\treturn is.Consequent.Idx1()\n}\n\n// expression implements Statement.\nfunc (*IfStatement) statement() {}\n\n// LabelledStatement represents a labelled statement.\ntype LabelledStatement struct {\n\tStatement Statement\n\tLabel     *Identifier\n\tColon     file.Idx\n}\n\n// Idx0 implements Node.\nfunc (ls *LabelledStatement) Idx0() file.Idx {\n\treturn ls.Label.Idx0()\n}\n\n// Idx1 implements Node.\nfunc (ls *LabelledStatement) Idx1() file.Idx {\n\treturn ls.Statement.Idx1()\n}\n\n// expression implements Statement.\nfunc (*LabelledStatement) statement() {}\n\n// ReturnStatement represents a return statement.\ntype ReturnStatement struct {\n\tArgument Expression\n\tReturn   file.Idx\n}\n\n// Idx0 implements Node.\nfunc (rs *ReturnStatement) Idx0() file.Idx {\n\treturn rs.Return\n}\n\n// Idx1 implements Node.\nfunc (rs *ReturnStatement) Idx1() file.Idx {\n\tif rs.Argument != nil {\n\t\treturn rs.Argument.Idx1()\n\t}\n\treturn rs.Return + 6\n}\n\n// expression implements Statement.\nfunc (*ReturnStatement) statement() {}\n\n// SwitchStatement represents a switch statement.\ntype SwitchStatement struct {\n\tDiscriminant Expression\n\tBody         []*CaseStatement\n\tSwitch       file.Idx\n\tDefault      int\n\tRightBrace   file.Idx\n}\n\n// Idx0 implements Node.\nfunc (ss *SwitchStatement) Idx0() file.Idx {\n\treturn ss.Switch\n}\n\n// Idx1 implements Node.\nfunc (ss *SwitchStatement) Idx1() file.Idx {\n\treturn ss.RightBrace + 1\n}\n\n// expression implements Statement.\nfunc (*SwitchStatement) statement() {}\n\n// ThrowStatement represents a throw statement.\ntype ThrowStatement struct {\n\tArgument Expression\n\tThrow    file.Idx\n}\n\n// Idx0 implements Node.\nfunc (ts *ThrowStatement) Idx0() file.Idx {\n\treturn ts.Throw\n}\n\n// Idx1 implements Node.\nfunc (ts *ThrowStatement) Idx1() file.Idx {\n\treturn ts.Argument.Idx1()\n}\n\n// expression implements Statement.\nfunc (*ThrowStatement) statement() {}\n\n// TryStatement represents a try statement.\ntype TryStatement struct {\n\tBody    Statement\n\tFinally Statement\n\tCatch   *CatchStatement\n\tTry     file.Idx\n}\n\n// Idx0 implements Node.\nfunc (ts *TryStatement) Idx0() file.Idx {\n\treturn ts.Try\n}\n\n// Idx1 implements Node.\nfunc (ts *TryStatement) Idx1() file.Idx {\n\tif ts.Finally != nil {\n\t\treturn ts.Finally.Idx1()\n\t}\n\treturn ts.Catch.Idx1()\n}\n\n// expression implements Statement.\nfunc (*TryStatement) statement() {}\n\n// VariableStatement represents a variable statement.\ntype VariableStatement struct {\n\tList []Expression\n\tVar  file.Idx\n}\n\n// Idx0 implements Node.\nfunc (vs *VariableStatement) Idx0() file.Idx {\n\treturn vs.Var\n}\n\n// Idx1 implements Node.\nfunc (vs *VariableStatement) Idx1() file.Idx {\n\treturn vs.List[len(vs.List)-1].Idx1()\n}\n\n// expression implements Statement.\nfunc (*VariableStatement) statement() {}\n\n// WhileStatement represents a while statement.\ntype WhileStatement struct {\n\tTest  Expression\n\tBody  Statement\n\tWhile file.Idx\n}\n\n// Idx0 implements Node.\nfunc (ws *WhileStatement) Idx0() file.Idx {\n\treturn ws.While\n}\n\n// Idx1 implements Node.\nfunc (ws *WhileStatement) Idx1() file.Idx {\n\treturn ws.Body.Idx1()\n}\n\n// expression implements Statement.\nfunc (*WhileStatement) statement() {}\n\n// WithStatement represents a with statement.\ntype WithStatement struct {\n\tObject Expression\n\tBody   Statement\n\tWith   file.Idx\n}\n\n// Idx0 implements Node.\nfunc (ws *WithStatement) Idx0() file.Idx {\n\treturn ws.With\n}\n\n// Idx1 implements Node.\nfunc (ws *WithStatement) Idx1() file.Idx {\n\treturn ws.Body.Idx1()\n}\n\n// expression implements Statement.\nfunc (*WithStatement) statement() {}\n\n// Declaration is implemented by type which represent declarations.\ntype Declaration interface {\n\tdeclaration()\n}\n\n// FunctionDeclaration represents a function declaration.\ntype FunctionDeclaration struct {\n\tFunction *FunctionLiteral\n}\n\nfunc (*FunctionDeclaration) declaration() {}\n\n// VariableDeclaration represents a variable declaration.\ntype VariableDeclaration struct {\n\tList []*VariableExpression\n\tVar  file.Idx\n}\n\n// declaration implements Declaration.\nfunc (*VariableDeclaration) declaration() {}\n\n// Program represents a full program.\ntype Program struct {\n\tFile            *file.File\n\tComments        CommentMap\n\tBody            []Statement\n\tDeclarationList []Declaration\n}\n\n// Idx0 implements Node.\nfunc (p *Program) Idx0() file.Idx {\n\treturn p.Body[0].Idx0()\n}\n\n// Idx1 implements Node.\nfunc (p *Program) Idx1() file.Idx {\n\treturn p.Body[len(p.Body)-1].Idx1()\n}\n"
  },
  {
    "path": "ast/walk.go",
    "content": "package ast\n\nimport \"fmt\"\n\n// Visitor Enter method is invoked for each node encountered by Walk.\n// If the result visitor w is not nil, Walk visits each of the children\n// of node with the visitor v, followed by a call of the Exit method.\ntype Visitor interface {\n\tEnter(n Node) (v Visitor)\n\tExit(n Node)\n}\n\n// Walk traverses an AST in depth-first order: It starts by calling\n// v.Enter(node); node must not be nil. If the visitor v returned by\n// v.Enter(node) is not nil, Walk is invoked recursively with visitor\n// v for each of the non-nil children of node, followed by a call\n// of v.Exit(node).\nfunc Walk(v Visitor, n Node) {\n\tif n == nil {\n\t\treturn\n\t}\n\tif v = v.Enter(n); v == nil {\n\t\treturn\n\t}\n\n\tdefer v.Exit(n)\n\n\tswitch n := n.(type) {\n\tcase *ArrayLiteral:\n\t\tif n != nil {\n\t\t\tfor _, ex := range n.Value {\n\t\t\t\tWalk(v, ex)\n\t\t\t}\n\t\t}\n\tcase *AssignExpression:\n\t\tif n != nil {\n\t\t\tWalk(v, n.Left)\n\t\t\tWalk(v, n.Right)\n\t\t}\n\tcase *BadExpression:\n\tcase *BadStatement:\n\tcase *BinaryExpression:\n\t\tif n != nil {\n\t\t\tWalk(v, n.Left)\n\t\t\tWalk(v, n.Right)\n\t\t}\n\tcase *BlockStatement:\n\t\tif n != nil {\n\t\t\tfor _, s := range n.List {\n\t\t\t\tWalk(v, s)\n\t\t\t}\n\t\t}\n\tcase *BooleanLiteral:\n\tcase *BracketExpression:\n\t\tif n != nil {\n\t\t\tWalk(v, n.Left)\n\t\t\tWalk(v, n.Member)\n\t\t}\n\tcase *BranchStatement:\n\t\tif n != nil {\n\t\t\tWalk(v, n.Label)\n\t\t}\n\tcase *CallExpression:\n\t\tif n != nil {\n\t\t\tWalk(v, n.Callee)\n\t\t\tfor _, a := range n.ArgumentList {\n\t\t\t\tWalk(v, a)\n\t\t\t}\n\t\t}\n\tcase *CaseStatement:\n\t\tif n != nil {\n\t\t\tWalk(v, n.Test)\n\t\t\tfor _, c := range n.Consequent {\n\t\t\t\tWalk(v, c)\n\t\t\t}\n\t\t}\n\tcase *CatchStatement:\n\t\tif n != nil {\n\t\t\tWalk(v, n.Parameter)\n\t\t\tWalk(v, n.Body)\n\t\t}\n\tcase *ConditionalExpression:\n\t\tif n != nil {\n\t\t\tWalk(v, n.Test)\n\t\t\tWalk(v, n.Consequent)\n\t\t\tWalk(v, n.Alternate)\n\t\t}\n\tcase *DebuggerStatement:\n\tcase *DoWhileStatement:\n\t\tif n != nil {\n\t\t\tWalk(v, n.Test)\n\t\t\tWalk(v, n.Body)\n\t\t}\n\tcase *DotExpression:\n\t\tif n != nil {\n\t\t\tWalk(v, n.Left)\n\t\t\tWalk(v, n.Identifier)\n\t\t}\n\tcase *EmptyExpression:\n\tcase *EmptyStatement:\n\tcase *ExpressionStatement:\n\t\tif n != nil {\n\t\t\tWalk(v, n.Expression)\n\t\t}\n\tcase *ForInStatement:\n\t\tif n != nil {\n\t\t\tWalk(v, n.Into)\n\t\t\tWalk(v, n.Source)\n\t\t\tWalk(v, n.Body)\n\t\t}\n\tcase *ForStatement:\n\t\tif n != nil {\n\t\t\tWalk(v, n.Initializer)\n\t\t\tWalk(v, n.Update)\n\t\t\tWalk(v, n.Test)\n\t\t\tWalk(v, n.Body)\n\t\t}\n\tcase *FunctionLiteral:\n\t\tif n != nil {\n\t\t\tWalk(v, n.Name)\n\t\t\tfor _, p := range n.ParameterList.List {\n\t\t\t\tWalk(v, p)\n\t\t\t}\n\t\t\tWalk(v, n.Body)\n\t\t}\n\tcase *FunctionStatement:\n\t\tif n != nil {\n\t\t\tWalk(v, n.Function)\n\t\t}\n\tcase *Identifier:\n\tcase *IfStatement:\n\t\tif n != nil {\n\t\t\tWalk(v, n.Test)\n\t\t\tWalk(v, n.Consequent)\n\t\t\tWalk(v, n.Alternate)\n\t\t}\n\tcase *LabelledStatement:\n\t\tif n != nil {\n\t\t\tWalk(v, n.Label)\n\t\t\tWalk(v, n.Statement)\n\t\t}\n\tcase *NewExpression:\n\t\tif n != nil {\n\t\t\tWalk(v, n.Callee)\n\t\t\tfor _, a := range n.ArgumentList {\n\t\t\t\tWalk(v, a)\n\t\t\t}\n\t\t}\n\tcase *NullLiteral:\n\tcase *NumberLiteral:\n\tcase *ObjectLiteral:\n\t\tif n != nil {\n\t\t\tfor _, p := range n.Value {\n\t\t\t\tWalk(v, p.Value)\n\t\t\t}\n\t\t}\n\tcase *Program:\n\t\tif n != nil {\n\t\t\tfor _, b := range n.Body {\n\t\t\t\tWalk(v, b)\n\t\t\t}\n\t\t}\n\tcase *RegExpLiteral:\n\tcase *ReturnStatement:\n\t\tif n != nil {\n\t\t\tWalk(v, n.Argument)\n\t\t}\n\tcase *SequenceExpression:\n\t\tif n != nil {\n\t\t\tfor _, e := range n.Sequence {\n\t\t\t\tWalk(v, e)\n\t\t\t}\n\t\t}\n\tcase *StringLiteral:\n\tcase *SwitchStatement:\n\t\tif n != nil {\n\t\t\tWalk(v, n.Discriminant)\n\t\t\tfor _, c := range n.Body {\n\t\t\t\tWalk(v, c)\n\t\t\t}\n\t\t}\n\tcase *ThisExpression:\n\tcase *ThrowStatement:\n\t\tif n != nil {\n\t\t\tWalk(v, n.Argument)\n\t\t}\n\tcase *TryStatement:\n\t\tif n != nil {\n\t\t\tWalk(v, n.Body)\n\t\t\tWalk(v, n.Catch)\n\t\t\tWalk(v, n.Finally)\n\t\t}\n\tcase *UnaryExpression:\n\t\tif n != nil {\n\t\t\tWalk(v, n.Operand)\n\t\t}\n\tcase *VariableExpression:\n\t\tif n != nil {\n\t\t\tWalk(v, n.Initializer)\n\t\t}\n\tcase *VariableStatement:\n\t\tif n != nil {\n\t\t\tfor _, e := range n.List {\n\t\t\t\tWalk(v, e)\n\t\t\t}\n\t\t}\n\tcase *WhileStatement:\n\t\tif n != nil {\n\t\t\tWalk(v, n.Test)\n\t\t\tWalk(v, n.Body)\n\t\t}\n\tcase *WithStatement:\n\t\tif n != nil {\n\t\t\tWalk(v, n.Object)\n\t\t\tWalk(v, n.Body)\n\t\t}\n\tdefault:\n\t\tpanic(fmt.Sprintf(\"Walk: unexpected node type %T\", n))\n\t}\n}\n"
  },
  {
    "path": "ast/walk_example_test.go",
    "content": "package ast_test\n\nimport (\n\t\"fmt\"\n\t\"log\"\n\n\t\"github.com/robertkrimen/otto/ast\"\n\t\"github.com/robertkrimen/otto/file\"\n\t\"github.com/robertkrimen/otto/parser\"\n)\n\ntype walkExample struct {\n\tsource string\n\tshift  file.Idx\n}\n\nfunc (w *walkExample) Enter(n ast.Node) ast.Visitor {\n\tif id, ok := n.(*ast.Identifier); ok && id != nil {\n\t\tidx := n.Idx0() + w.shift - 1\n\t\ts := w.source[:idx] + \"new_\" + w.source[idx:]\n\t\tw.source = s\n\t\tw.shift += 4\n\t}\n\tif v, ok := n.(*ast.VariableExpression); ok && v != nil {\n\t\tidx := n.Idx0() + w.shift - 1\n\t\ts := w.source[:idx] + \"varnew_\" + w.source[idx:]\n\t\tw.source = s\n\t\tw.shift += 7\n\t}\n\n\treturn w\n}\n\nfunc (w *walkExample) Exit(n ast.Node) {\n\t// AST node n has had all its children walked. Pop it out of your\n\t// stack, or do whatever processing you need to do, if any.\n}\n\nfunc ExampleVisitor_codeRewrite() {\n\tsource := `var b = function() {test(); try {} catch(e) {} var test = \"test(); var test = 1\"} // test`\n\tprogram, err := parser.ParseFile(nil, \"\", source, 0)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tw := &walkExample{source: source}\n\n\tast.Walk(w, program)\n\n\tfmt.Println(w.source)\n\t// Output: var varnew_b = function() {new_test(); try {} catch(new_e) {} var varnew_test = \"test(); var test = 1\"} // test\n}\n"
  },
  {
    "path": "ast/walk_test.go",
    "content": "package ast_test\n\nimport (\n\t\"testing\"\n\n\t\"github.com/robertkrimen/otto/ast\"\n\t\"github.com/robertkrimen/otto/file\"\n\t\"github.com/robertkrimen/otto/parser\"\n\t\"github.com/stretchr/testify/require\"\n)\n\ntype walker struct {\n\tseen              map[ast.Node]struct{}\n\tsource            string\n\tstack             []ast.Node\n\tshift             file.Idx\n\tduplicate         int\n\tnewExpressionIdx1 file.Idx\n}\n\n// push and pop below are to prove the symmetry of Enter/Exit calls\n\nfunc (w *walker) push(n ast.Node) {\n\tw.stack = append(w.stack, n)\n}\n\nfunc (w *walker) pop(n ast.Node) {\n\tsize := len(w.stack)\n\tif size <= 0 {\n\t\tpanic(\"pop of empty stack\")\n\t}\n\n\tif toPop := w.stack[size-1]; toPop != n {\n\t\tpanic(\"pop: nodes do not equal\")\n\t}\n\n\tw.stack[size-1] = nil\n\tw.stack = w.stack[:size-1]\n}\n\nfunc (w *walker) Enter(n ast.Node) ast.Visitor {\n\tw.push(n)\n\tif _, ok := w.seen[n]; ok {\n\t\t// Skip items we've already seen which occurs due to declarations.\n\t\tw.duplicate++\n\t\treturn w\n\t}\n\n\tw.seen[n] = struct{}{}\n\n\tswitch t := n.(type) {\n\tcase *ast.Identifier:\n\t\tif t != nil {\n\t\t\tidx := n.Idx0() + w.shift - 1\n\t\t\ts := w.source[:idx] + \"IDENT_\" + w.source[idx:]\n\t\t\tw.source = s\n\t\t\tw.shift += 6\n\t\t}\n\tcase *ast.VariableExpression:\n\t\tif t != nil {\n\t\t\tidx := n.Idx0() + w.shift - 1\n\t\t\ts := w.source[:idx] + \"VAR_\" + w.source[idx:]\n\t\t\tw.source = s\n\t\t\tw.shift += 4\n\t\t}\n\tcase *ast.NewExpression:\n\t\tw.newExpressionIdx1 = n.Idx1()\n\t}\n\n\treturn w\n}\n\nfunc (w *walker) Exit(n ast.Node) {\n\tw.pop(n)\n}\n\nfunc TestVisitorRewrite(t *testing.T) {\n\tsource := `var b = function() {\n\t\ttest();\n\t\ttry {} catch(e) {}\n\t\tvar test = \"test(); var test = 1\"\n\t} // test`\n\tprogram, err := parser.ParseFile(nil, \"\", source, 0)\n\trequire.NoError(t, err)\n\n\tw := &walker{\n\t\tsource: source,\n\t\tseen:   make(map[ast.Node]struct{}),\n\t}\n\tast.Walk(w, program)\n\n\txformed := `var VAR_b = function() {\n\t\tIDENT_test();\n\t\ttry {} catch(IDENT_e) {}\n\t\tvar VAR_test = \"test(); var test = 1\"\n\t} // test`\n\n\trequire.Equal(t, xformed, w.source)\n\trequire.Empty(t, w.stack)\n\trequire.Zero(t, w.duplicate)\n}\n\nfunc Test_issue261(t *testing.T) {\n\ttests := map[string]struct {\n\t\tcode string\n\t\twant file.Idx\n\t}{\n\t\t\"no-parenthesis\": {\n\t\t\tcode: `var i = new Image;`,\n\t\t\twant: 18,\n\t\t},\n\t\t\"no-args\": {\n\t\t\tcode: `var i = new Image();`,\n\t\t\twant: 20,\n\t\t},\n\t\t\"two-args\": {\n\t\t\tcode: `var i = new Image(1, 2);`,\n\t\t\twant: 24,\n\t\t},\n\t}\n\n\tfor name, tt := range tests {\n\t\tt.Run(name, func(t *testing.T) {\n\t\t\tprog, err := parser.ParseFile(nil, \"\", tt.code, 0)\n\t\t\trequire.NoError(t, err)\n\n\t\t\tw := &walker{\n\t\t\t\tsource: tt.code,\n\t\t\t\tseen:   make(map[ast.Node]struct{}),\n\t\t\t}\n\t\t\tast.Walk(w, prog)\n\n\t\t\trequire.Equal(t, tt.want, w.newExpressionIdx1)\n\t\t\trequire.Empty(t, w.stack)\n\t\t\trequire.Zero(t, w.duplicate)\n\t\t})\n\t}\n}\n\nfunc TestBadStatement(t *testing.T) {\n\tsource := `\n\tvar abc;\n\tbreak; do {\n\t} while(true);\n`\n\tprogram, err := parser.ParseFile(nil, \"\", source, 0)\n\trequire.ErrorContains(t, err, \"Illegal break statement\")\n\n\tw := &walker{\n\t\tsource: source,\n\t\tseen:   make(map[ast.Node]struct{}),\n\t}\n\n\trequire.NotPanics(t, func() {\n\t\tast.Walk(w, program)\n\t})\n}\n"
  },
  {
    "path": "builtin.go",
    "content": "package otto\n\nimport (\n\t\"encoding/hex\"\n\t\"errors\"\n\t\"math\"\n\t\"net/url\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\t\"unicode/utf16\"\n\t\"unicode/utf8\"\n)\n\n// Global.\nfunc builtinGlobalEval(call FunctionCall) Value {\n\tsrc := call.Argument(0)\n\tif !src.IsString() {\n\t\treturn src\n\t}\n\trt := call.runtime\n\tprogram := rt.cmplParseOrThrow(src.string(), nil)\n\tif !call.eval {\n\t\t// Not a direct call to eval, so we enter the global ExecutionContext\n\t\trt.enterGlobalScope()\n\t\tdefer rt.leaveScope()\n\t}\n\treturnValue := rt.cmplEvaluateNodeProgram(program, true)\n\tif returnValue.isEmpty() {\n\t\treturn Value{}\n\t}\n\treturn returnValue\n}\n\nfunc builtinGlobalIsNaN(call FunctionCall) Value {\n\tvalue := call.Argument(0).float64()\n\treturn boolValue(math.IsNaN(value))\n}\n\nfunc builtinGlobalIsFinite(call FunctionCall) Value {\n\tvalue := call.Argument(0).float64()\n\treturn boolValue(!math.IsNaN(value) && !math.IsInf(value, 0))\n}\n\nfunc digitValue(chr rune) int {\n\tswitch {\n\tcase '0' <= chr && chr <= '9':\n\t\treturn int(chr - '0')\n\tcase 'a' <= chr && chr <= 'z':\n\t\treturn int(chr - 'a' + 10)\n\tcase 'A' <= chr && chr <= 'Z':\n\t\treturn int(chr - 'A' + 10)\n\t}\n\treturn 36 // Larger than any legal digit value\n}\n\nfunc builtinGlobalParseInt(call FunctionCall) Value {\n\tinput := strings.Trim(call.Argument(0).string(), builtinStringTrimWhitespace)\n\tif len(input) == 0 {\n\t\treturn NaNValue()\n\t}\n\n\tradix := int(toInt32(call.Argument(1)))\n\n\tnegative := false\n\tswitch input[0] {\n\tcase '+':\n\t\tinput = input[1:]\n\tcase '-':\n\t\tnegative = true\n\t\tinput = input[1:]\n\t}\n\n\tstrip := true\n\tif radix == 0 {\n\t\tradix = 10\n\t} else {\n\t\tif radix < 2 || radix > 36 {\n\t\t\treturn NaNValue()\n\t\t} else if radix != 16 {\n\t\t\tstrip = false\n\t\t}\n\t}\n\n\tswitch len(input) {\n\tcase 0:\n\t\treturn NaNValue()\n\tcase 1:\n\tdefault:\n\t\tif strip {\n\t\t\tif input[0] == '0' && (input[1] == 'x' || input[1] == 'X') {\n\t\t\t\tinput = input[2:]\n\t\t\t\tradix = 16\n\t\t\t}\n\t\t}\n\t}\n\n\tbase := radix\n\tindex := 0\n\tfor ; index < len(input); index++ {\n\t\tdigit := digitValue(rune(input[index])) // If not ASCII, then an error anyway\n\t\tif digit >= base {\n\t\t\tbreak\n\t\t}\n\t}\n\tinput = input[0:index]\n\n\tvalue, err := strconv.ParseInt(input, radix, 64)\n\tif err != nil {\n\t\tif errors.Is(err, strconv.ErrRange) {\n\t\t\tbase := float64(base)\n\t\t\t// Could just be a very large number (e.g. 0x8000000000000000)\n\t\t\tvar value float64\n\t\t\tfor _, chr := range input {\n\t\t\t\tdigit := float64(digitValue(chr))\n\t\t\t\tif digit >= base {\n\t\t\t\t\treturn NaNValue()\n\t\t\t\t}\n\t\t\t\tvalue = value*base + digit\n\t\t\t}\n\t\t\tif negative {\n\t\t\t\tvalue *= -1\n\t\t\t}\n\t\t\treturn float64Value(value)\n\t\t}\n\t\treturn NaNValue()\n\t}\n\tif negative {\n\t\tvalue *= -1\n\t}\n\n\treturn int64Value(value)\n}\n\nvar (\n\tparseFloatMatchBadSpecial = regexp.MustCompile(`[\\+\\-]?(?:[Ii]nf$|infinity)`)\n\tparseFloatMatchValid      = regexp.MustCompile(`[0-9eE\\+\\-\\.]|Infinity`)\n)\n\nfunc builtinGlobalParseFloat(call FunctionCall) Value {\n\t// Caveat emptor: This implementation does NOT match the specification\n\tinput := strings.Trim(call.Argument(0).string(), builtinStringTrimWhitespace)\n\n\tif parseFloatMatchBadSpecial.MatchString(input) {\n\t\treturn NaNValue()\n\t}\n\tvalue, err := strconv.ParseFloat(input, 64)\n\tif err != nil {\n\t\tfor end := len(input); end > 0; end-- {\n\t\t\tval := input[0:end]\n\t\t\tif !parseFloatMatchValid.MatchString(val) {\n\t\t\t\treturn NaNValue()\n\t\t\t}\n\t\t\tvalue, err = strconv.ParseFloat(val, 64)\n\t\t\tif err == nil {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t\tif err != nil {\n\t\t\treturn NaNValue()\n\t\t}\n\t}\n\treturn float64Value(value)\n}\n\n// encodeURI/decodeURI\n\nfunc encodeDecodeURI(call FunctionCall, escape *regexp.Regexp) Value {\n\tvalue := call.Argument(0)\n\tvar input []uint16\n\tswitch vl := value.value.(type) {\n\tcase []uint16:\n\t\tinput = vl\n\tdefault:\n\t\tinput = utf16.Encode([]rune(value.string()))\n\t}\n\tif len(input) == 0 {\n\t\treturn stringValue(\"\")\n\t}\n\toutput := []byte{}\n\tlength := len(input)\n\tencode := make([]byte, 4)\n\tfor index := 0; index < length; {\n\t\tvalue := input[index]\n\t\tdecode := utf16.Decode(input[index : index+1])\n\t\tif value >= 0xDC00 && value <= 0xDFFF {\n\t\t\tpanic(call.runtime.panicURIError(\"URI malformed\"))\n\t\t}\n\t\tif value >= 0xD800 && value <= 0xDBFF {\n\t\t\tindex++\n\t\t\tif index >= length {\n\t\t\t\tpanic(call.runtime.panicURIError(\"URI malformed\"))\n\t\t\t}\n\t\t\t// input = ..., value, value1, ...\n\t\t\tvalue1 := input[index]\n\t\t\tif value1 < 0xDC00 || value1 > 0xDFFF {\n\t\t\t\tpanic(call.runtime.panicURIError(\"URI malformed\"))\n\t\t\t}\n\t\t\tdecode = []rune{((rune(value) - 0xD800) * 0x400) + (rune(value1) - 0xDC00) + 0x10000}\n\t\t}\n\t\tindex++\n\t\tsize := utf8.EncodeRune(encode, decode[0])\n\t\toutput = append(output, encode[0:size]...)\n\t}\n\n\tbytes := escape.ReplaceAllFunc(output, func(target []byte) []byte {\n\t\t// Probably a better way of doing this\n\t\tif target[0] == ' ' {\n\t\t\treturn []byte(\"%20\")\n\t\t}\n\t\treturn []byte(url.QueryEscape(string(target)))\n\t})\n\treturn stringValue(string(bytes))\n}\n\nvar encodeURIRegexp = regexp.MustCompile(`([^~!@#$&*()=:/,;?+'])`)\n\nfunc builtinGlobalEncodeURI(call FunctionCall) Value {\n\treturn encodeDecodeURI(call, encodeURIRegexp)\n}\n\nvar encodeURIComponentRegexp = regexp.MustCompile(`([^~!*()'])`)\n\nfunc builtinGlobalEncodeURIComponent(call FunctionCall) Value {\n\treturn encodeDecodeURI(call, encodeURIComponentRegexp)\n}\n\n// 3B/2F/3F/3A/40/26/3D/2B/24/2C/23.\nvar decodeURIGuard = regexp.MustCompile(`(?i)(?:%)(3B|2F|3F|3A|40|26|3D|2B|24|2C|23)`)\n\nfunc decodeURI(input string, reserve bool) (string, bool) {\n\tif reserve {\n\t\tinput = decodeURIGuard.ReplaceAllString(input, \"%25$1\")\n\t}\n\tinput = strings.ReplaceAll(input, \"+\", \"%2B\") // Ugly hack to make QueryUnescape work with our use case\n\toutput, err := url.QueryUnescape(input)\n\tif err != nil || !utf8.ValidString(output) {\n\t\treturn \"\", true\n\t}\n\treturn output, false\n}\n\nfunc builtinGlobalDecodeURI(call FunctionCall) Value {\n\toutput, err := decodeURI(call.Argument(0).string(), true)\n\tif err {\n\t\tpanic(call.runtime.panicURIError(\"URI malformed\"))\n\t}\n\treturn stringValue(output)\n}\n\nfunc builtinGlobalDecodeURIComponent(call FunctionCall) Value {\n\toutput, err := decodeURI(call.Argument(0).string(), false)\n\tif err {\n\t\tpanic(call.runtime.panicURIError(\"URI malformed\"))\n\t}\n\treturn stringValue(output)\n}\n\n// escape/unescape\n\nfunc builtinShouldEscape(chr byte) bool {\n\tif 'A' <= chr && chr <= 'Z' || 'a' <= chr && chr <= 'z' || '0' <= chr && chr <= '9' {\n\t\treturn false\n\t}\n\treturn !strings.ContainsRune(\"*_+-./\", rune(chr))\n}\n\nconst escapeBase16 = \"0123456789ABCDEF\"\n\nfunc builtinEscape(input string) string {\n\toutput := make([]byte, 0, len(input))\n\tlength := len(input)\n\tfor index := 0; index < length; {\n\t\tif builtinShouldEscape(input[index]) {\n\t\t\tchr, width := utf8.DecodeRuneInString(input[index:])\n\t\t\tchr16 := utf16.Encode([]rune{chr})[0]\n\t\t\tif 256 > chr16 {\n\t\t\t\toutput = append(output, '%',\n\t\t\t\t\tescapeBase16[chr16>>4],\n\t\t\t\t\tescapeBase16[chr16&15],\n\t\t\t\t)\n\t\t\t} else {\n\t\t\t\toutput = append(output, '%', 'u',\n\t\t\t\t\tescapeBase16[chr16>>12],\n\t\t\t\t\tescapeBase16[(chr16>>8)&15],\n\t\t\t\t\tescapeBase16[(chr16>>4)&15],\n\t\t\t\t\tescapeBase16[chr16&15],\n\t\t\t\t)\n\t\t\t}\n\t\t\tindex += width\n\t\t} else {\n\t\t\toutput = append(output, input[index])\n\t\t\tindex++\n\t\t}\n\t}\n\treturn string(output)\n}\n\nfunc builtinUnescape(input string) string {\n\toutput := make([]rune, 0, len(input))\n\tlength := len(input)\n\tfor index := 0; index < length; {\n\t\tif input[index] == '%' {\n\t\t\tif index <= length-6 && input[index+1] == 'u' {\n\t\t\t\tbyte16, err := hex.DecodeString(input[index+2 : index+6])\n\t\t\t\tif err == nil {\n\t\t\t\t\tvalue := uint16(byte16[0])<<8 + uint16(byte16[1])\n\t\t\t\t\tchr := utf16.Decode([]uint16{value})[0]\n\t\t\t\t\toutput = append(output, chr)\n\t\t\t\t\tindex += 6\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t}\n\t\t\tif index <= length-3 {\n\t\t\t\tbyte8, err := hex.DecodeString(input[index+1 : index+3])\n\t\t\t\tif err == nil {\n\t\t\t\t\tvalue := uint16(byte8[0])\n\t\t\t\t\tchr := utf16.Decode([]uint16{value})[0]\n\t\t\t\t\toutput = append(output, chr)\n\t\t\t\t\tindex += 3\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\toutput = append(output, rune(input[index]))\n\t\tindex++\n\t}\n\treturn string(output)\n}\n\nfunc builtinGlobalEscape(call FunctionCall) Value {\n\treturn stringValue(builtinEscape(call.Argument(0).string()))\n}\n\nfunc builtinGlobalUnescape(call FunctionCall) Value {\n\treturn stringValue(builtinUnescape(call.Argument(0).string()))\n}\n"
  },
  {
    "path": "builtin_array.go",
    "content": "package otto\n\nimport (\n\t\"strconv\"\n\t\"strings\"\n)\n\n// Array\n\nfunc builtinArray(call FunctionCall) Value {\n\treturn objectValue(builtinNewArrayNative(call.runtime, call.ArgumentList))\n}\n\nfunc builtinNewArray(obj *object, argumentList []Value) Value {\n\treturn objectValue(builtinNewArrayNative(obj.runtime, argumentList))\n}\n\nfunc builtinNewArrayNative(rt *runtime, argumentList []Value) *object {\n\tif len(argumentList) == 1 {\n\t\tfirstArgument := argumentList[0]\n\t\tif firstArgument.IsNumber() {\n\t\t\treturn rt.newArray(arrayUint32(rt, firstArgument))\n\t\t}\n\t}\n\treturn rt.newArrayOf(argumentList)\n}\n\nfunc builtinArrayToString(call FunctionCall) Value {\n\tthisObject := call.thisObject()\n\tjoin := thisObject.get(\"join\")\n\tif join.isCallable() {\n\t\tjoin := join.object()\n\t\treturn join.call(call.This, call.ArgumentList, false, nativeFrame)\n\t}\n\treturn builtinObjectToString(call)\n}\n\nfunc builtinArrayToLocaleString(call FunctionCall) Value {\n\tseparator := \",\"\n\tthisObject := call.thisObject()\n\tlength := int64(toUint32(thisObject.get(propertyLength)))\n\tif length == 0 {\n\t\treturn stringValue(\"\")\n\t}\n\tstringList := make([]string, 0, length)\n\tfor index := range length {\n\t\tvalue := thisObject.get(arrayIndexToString(index))\n\t\tstringValue := \"\"\n\t\tswitch value.kind {\n\t\tcase valueEmpty, valueUndefined, valueNull:\n\t\tdefault:\n\t\t\tobj := call.runtime.toObject(value)\n\t\t\ttoLocaleString := obj.get(\"toLocaleString\")\n\t\t\tif !toLocaleString.isCallable() {\n\t\t\t\tpanic(call.runtime.panicTypeError(\"Array.toLocaleString index[%d] %q is not callable\", index, toLocaleString))\n\t\t\t}\n\t\t\tstringValue = toLocaleString.call(call.runtime, objectValue(obj)).string()\n\t\t}\n\t\tstringList = append(stringList, stringValue)\n\t}\n\treturn stringValue(strings.Join(stringList, separator))\n}\n\nfunc builtinArrayConcat(call FunctionCall) Value {\n\tthisObject := call.thisObject()\n\tvalueArray := []Value{}\n\tsource := append([]Value{objectValue(thisObject)}, call.ArgumentList...)\n\tfor _, item := range source {\n\t\tswitch item.kind {\n\t\tcase valueObject:\n\t\t\tobj := item.object()\n\t\t\tif isArray(obj) {\n\t\t\t\tlength := obj.get(propertyLength).number().int64\n\t\t\t\tfor index := range length {\n\t\t\t\t\tname := strconv.FormatInt(index, 10)\n\t\t\t\t\tif obj.hasProperty(name) {\n\t\t\t\t\t\tvalueArray = append(valueArray, obj.get(name))\n\t\t\t\t\t} else {\n\t\t\t\t\t\tvalueArray = append(valueArray, Value{})\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tfallthrough\n\t\tdefault:\n\t\t\tvalueArray = append(valueArray, item)\n\t\t}\n\t}\n\treturn objectValue(call.runtime.newArrayOf(valueArray))\n}\n\nfunc builtinArrayShift(call FunctionCall) Value {\n\tthisObject := call.thisObject()\n\tlength := int64(toUint32(thisObject.get(propertyLength)))\n\tif length == 0 {\n\t\tthisObject.put(propertyLength, int64Value(0), true)\n\t\treturn Value{}\n\t}\n\tfirst := thisObject.get(\"0\")\n\tfor index := int64(1); index < length; index++ {\n\t\tfrom := arrayIndexToString(index)\n\t\tto := arrayIndexToString(index - 1)\n\t\tif thisObject.hasProperty(from) {\n\t\t\tthisObject.put(to, thisObject.get(from), true)\n\t\t} else {\n\t\t\tthisObject.delete(to, true)\n\t\t}\n\t}\n\tthisObject.delete(arrayIndexToString(length-1), true)\n\tthisObject.put(propertyLength, int64Value(length-1), true)\n\treturn first\n}\n\nfunc builtinArrayPush(call FunctionCall) Value {\n\tthisObject := call.thisObject()\n\titemList := call.ArgumentList\n\tindex := int64(toUint32(thisObject.get(propertyLength)))\n\tfor len(itemList) > 0 {\n\t\tthisObject.put(arrayIndexToString(index), itemList[0], true)\n\t\titemList = itemList[1:]\n\t\tindex++\n\t}\n\tlength := int64Value(index)\n\tthisObject.put(propertyLength, length, true)\n\treturn length\n}\n\nfunc builtinArrayPop(call FunctionCall) Value {\n\tthisObject := call.thisObject()\n\tlength := int64(toUint32(thisObject.get(propertyLength)))\n\tif length == 0 {\n\t\tthisObject.put(propertyLength, uint32Value(0), true)\n\t\treturn Value{}\n\t}\n\tlast := thisObject.get(arrayIndexToString(length - 1))\n\tthisObject.delete(arrayIndexToString(length-1), true)\n\tthisObject.put(propertyLength, int64Value(length-1), true)\n\treturn last\n}\n\nfunc builtinArrayJoin(call FunctionCall) Value {\n\tseparator := \",\"\n\targument := call.Argument(0)\n\tif argument.IsDefined() {\n\t\tseparator = argument.string()\n\t}\n\tthisObject := call.thisObject()\n\tlength := int64(toUint32(thisObject.get(propertyLength)))\n\tif length == 0 {\n\t\treturn stringValue(\"\")\n\t}\n\tstringList := make([]string, 0, length)\n\tfor index := range length {\n\t\tvalue := thisObject.get(arrayIndexToString(index))\n\t\tstringValue := \"\"\n\t\tswitch value.kind {\n\t\tcase valueEmpty, valueUndefined, valueNull:\n\t\tdefault:\n\t\t\tstringValue = value.string()\n\t\t}\n\t\tstringList = append(stringList, stringValue)\n\t}\n\treturn stringValue(strings.Join(stringList, separator))\n}\n\nfunc builtinArraySplice(call FunctionCall) Value {\n\tthisObject := call.thisObject()\n\tlength := int64(toUint32(thisObject.get(propertyLength)))\n\n\tstart := valueToRangeIndex(call.Argument(0), length, false)\n\tdeleteCount := length - start\n\tif arg, ok := call.getArgument(1); ok {\n\t\tdeleteCount = valueToRangeIndex(arg, length-start, true)\n\t}\n\tvalueArray := make([]Value, deleteCount)\n\n\tfor index := range deleteCount {\n\t\tindexString := arrayIndexToString(start + index)\n\t\tif thisObject.hasProperty(indexString) {\n\t\t\tvalueArray[index] = thisObject.get(indexString)\n\t\t}\n\t}\n\n\t// 0, <1, 2, 3, 4>, 5, 6, 7\n\t// a, b\n\t// length 8 - delete 4 @ start 1\n\n\titemList := []Value{}\n\titemCount := int64(len(call.ArgumentList))\n\tif itemCount > 2 {\n\t\titemCount -= 2 // Less the first two arguments\n\t\titemList = call.ArgumentList[2:]\n\t} else {\n\t\titemCount = 0\n\t}\n\tif itemCount < deleteCount {\n\t\t// The Object/Array is shrinking\n\t\tstop := length - deleteCount\n\t\t// The new length of the Object/Array before\n\t\t// appending the itemList remainder\n\t\t// Stopping at the lower bound of the insertion:\n\t\t// Move an item from the after the deleted portion\n\t\t// to a position after the inserted portion\n\t\tfor index := start; index < stop; index++ {\n\t\t\tfrom := arrayIndexToString(index + deleteCount) // Position just after deletion\n\t\t\tto := arrayIndexToString(index + itemCount)     // Position just after splice (insertion)\n\t\t\tif thisObject.hasProperty(from) {\n\t\t\t\tthisObject.put(to, thisObject.get(from), true)\n\t\t\t} else {\n\t\t\t\tthisObject.delete(to, true)\n\t\t\t}\n\t\t}\n\t\t// Delete off the end\n\t\t// We don't bother to delete below <stop + itemCount> (if any) since those\n\t\t// will be overwritten anyway\n\t\tfor index := length; index > (stop + itemCount); index-- {\n\t\t\tthisObject.delete(arrayIndexToString(index-1), true)\n\t\t}\n\t} else if itemCount > deleteCount {\n\t\t// The Object/Array is growing\n\t\t// The itemCount is greater than the deleteCount, so we do\n\t\t// not have to worry about overwriting what we should be moving\n\t\t// ---\n\t\t// Starting from the upper bound of the deletion:\n\t\t// Move an item from the after the deleted portion\n\t\t// to a position after the inserted portion\n\t\tfor index := length - deleteCount; index > start; index-- {\n\t\t\tfrom := arrayIndexToString(index + deleteCount - 1)\n\t\t\tto := arrayIndexToString(index + itemCount - 1)\n\t\t\tif thisObject.hasProperty(from) {\n\t\t\t\tthisObject.put(to, thisObject.get(from), true)\n\t\t\t} else {\n\t\t\t\tthisObject.delete(to, true)\n\t\t\t}\n\t\t}\n\t}\n\n\tfor index := range itemCount {\n\t\tthisObject.put(arrayIndexToString(index+start), itemList[index], true)\n\t}\n\tthisObject.put(propertyLength, int64Value(length+itemCount-deleteCount), true)\n\n\treturn objectValue(call.runtime.newArrayOf(valueArray))\n}\n\nfunc builtinArraySlice(call FunctionCall) Value {\n\tthisObject := call.thisObject()\n\n\tlength := int64(toUint32(thisObject.get(propertyLength)))\n\tstart, end := rangeStartEnd(call.ArgumentList, length, false)\n\n\tif start >= end {\n\t\t// Always an empty array\n\t\treturn objectValue(call.runtime.newArray(0))\n\t}\n\tsliceLength := end - start\n\tsliceValueArray := make([]Value, sliceLength)\n\n\tfor index := range sliceLength {\n\t\tfrom := arrayIndexToString(index + start)\n\t\tif thisObject.hasProperty(from) {\n\t\t\tsliceValueArray[index] = thisObject.get(from)\n\t\t}\n\t}\n\n\treturn objectValue(call.runtime.newArrayOf(sliceValueArray))\n}\n\nfunc builtinArrayUnshift(call FunctionCall) Value {\n\tthisObject := call.thisObject()\n\tlength := int64(toUint32(thisObject.get(propertyLength)))\n\titemList := call.ArgumentList\n\titemCount := int64(len(itemList))\n\n\tfor index := length; index > 0; index-- {\n\t\tfrom := arrayIndexToString(index - 1)\n\t\tto := arrayIndexToString(index + itemCount - 1)\n\t\tif thisObject.hasProperty(from) {\n\t\t\tthisObject.put(to, thisObject.get(from), true)\n\t\t} else {\n\t\t\tthisObject.delete(to, true)\n\t\t}\n\t}\n\n\tfor index := range itemCount {\n\t\tthisObject.put(arrayIndexToString(index), itemList[index], true)\n\t}\n\n\tnewLength := int64Value(length + itemCount)\n\tthisObject.put(propertyLength, newLength, true)\n\treturn newLength\n}\n\nfunc builtinArrayReverse(call FunctionCall) Value {\n\tthisObject := call.thisObject()\n\tlength := int64(toUint32(thisObject.get(propertyLength)))\n\n\tlower := struct {\n\t\tname   string\n\t\tindex  int64\n\t\texists bool\n\t}{}\n\tupper := lower\n\n\tlower.index = 0\n\tmiddle := length / 2 // Division will floor\n\n\tfor lower.index != middle {\n\t\tlower.name = arrayIndexToString(lower.index)\n\t\tupper.index = length - lower.index - 1\n\t\tupper.name = arrayIndexToString(upper.index)\n\n\t\tlower.exists = thisObject.hasProperty(lower.name)\n\t\tupper.exists = thisObject.hasProperty(upper.name)\n\n\t\tswitch {\n\t\tcase lower.exists && upper.exists:\n\t\t\tlowerValue := thisObject.get(lower.name)\n\t\t\tupperValue := thisObject.get(upper.name)\n\t\t\tthisObject.put(lower.name, upperValue, true)\n\t\t\tthisObject.put(upper.name, lowerValue, true)\n\t\tcase !lower.exists && upper.exists:\n\t\t\tvalue := thisObject.get(upper.name)\n\t\t\tthisObject.delete(upper.name, true)\n\t\t\tthisObject.put(lower.name, value, true)\n\t\tcase lower.exists && !upper.exists:\n\t\t\tvalue := thisObject.get(lower.name)\n\t\t\tthisObject.delete(lower.name, true)\n\t\t\tthisObject.put(upper.name, value, true)\n\t\t}\n\n\t\tlower.index++\n\t}\n\n\treturn call.This\n}\n\nfunc sortCompare(thisObject *object, index0, index1 uint, compare *object) int {\n\tj := struct {\n\t\tname    string\n\t\tvalue   string\n\t\texists  bool\n\t\tdefined bool\n\t}{}\n\tk := j\n\tj.name = arrayIndexToString(int64(index0))\n\tj.exists = thisObject.hasProperty(j.name)\n\tk.name = arrayIndexToString(int64(index1))\n\tk.exists = thisObject.hasProperty(k.name)\n\n\tswitch {\n\tcase !j.exists && !k.exists:\n\t\treturn 0\n\tcase !j.exists:\n\t\treturn 1\n\tcase !k.exists:\n\t\treturn -1\n\t}\n\n\tx := thisObject.get(j.name)\n\ty := thisObject.get(k.name)\n\tj.defined = x.IsDefined()\n\tk.defined = y.IsDefined()\n\n\tswitch {\n\tcase !j.defined && !k.defined:\n\t\treturn 0\n\tcase !j.defined:\n\t\treturn 1\n\tcase !k.defined:\n\t\treturn -1\n\t}\n\n\tif compare == nil {\n\t\tj.value = x.string()\n\t\tk.value = y.string()\n\n\t\tif j.value == k.value {\n\t\t\treturn 0\n\t\t} else if j.value < k.value {\n\t\t\treturn -1\n\t\t}\n\n\t\treturn 1\n\t}\n\n\treturn toIntSign(compare.call(Value{}, []Value{x, y}, false, nativeFrame))\n}\n\nfunc arraySortSwap(thisObject *object, index0, index1 uint) {\n\tj := struct {\n\t\tname   string\n\t\texists bool\n\t}{}\n\tk := j\n\n\tj.name = arrayIndexToString(int64(index0))\n\tj.exists = thisObject.hasProperty(j.name)\n\tk.name = arrayIndexToString(int64(index1))\n\tk.exists = thisObject.hasProperty(k.name)\n\n\tswitch {\n\tcase j.exists && k.exists:\n\t\tjv := thisObject.get(j.name)\n\t\tkv := thisObject.get(k.name)\n\t\tthisObject.put(j.name, kv, true)\n\t\tthisObject.put(k.name, jv, true)\n\tcase !j.exists && k.exists:\n\t\tvalue := thisObject.get(k.name)\n\t\tthisObject.delete(k.name, true)\n\t\tthisObject.put(j.name, value, true)\n\tcase j.exists && !k.exists:\n\t\tvalue := thisObject.get(j.name)\n\t\tthisObject.delete(j.name, true)\n\t\tthisObject.put(k.name, value, true)\n\t}\n}\n\nfunc arraySortQuickPartition(thisObject *object, left, right, pivot uint, compare *object) (uint, uint) {\n\tarraySortSwap(thisObject, pivot, right) // Right is now the pivot value\n\tcursor := left\n\tcursor2 := left\n\tfor index := left; index < right; index++ {\n\t\tcomparison := sortCompare(thisObject, index, right, compare) // Compare to the pivot value\n\t\tif comparison < 0 {\n\t\t\tarraySortSwap(thisObject, index, cursor)\n\t\t\tif cursor < cursor2 {\n\t\t\t\tarraySortSwap(thisObject, index, cursor2)\n\t\t\t}\n\t\t\tcursor++\n\t\t\tcursor2++\n\t\t} else if comparison == 0 {\n\t\t\tarraySortSwap(thisObject, index, cursor2)\n\t\t\tcursor2++\n\t\t}\n\t}\n\tarraySortSwap(thisObject, cursor2, right)\n\treturn cursor, cursor2\n}\n\nfunc arraySortQuickSort(thisObject *object, left, right uint, compare *object) {\n\tif left < right {\n\t\tmiddle := left + (right-left)/2\n\t\tpivot, pivot2 := arraySortQuickPartition(thisObject, left, right, middle, compare)\n\t\tif pivot > 0 {\n\t\t\tarraySortQuickSort(thisObject, left, pivot-1, compare)\n\t\t}\n\t\tarraySortQuickSort(thisObject, pivot2+1, right, compare)\n\t}\n}\n\nfunc builtinArraySort(call FunctionCall) Value {\n\tthisObject := call.thisObject()\n\tlength := uint(toUint32(thisObject.get(propertyLength)))\n\tcompareValue := call.Argument(0)\n\tcompare := compareValue.object()\n\tif compareValue.IsUndefined() {\n\t} else if !compareValue.isCallable() {\n\t\tpanic(call.runtime.panicTypeError(\"Array.sort value %q is not callable\", compareValue))\n\t}\n\tif length > 1 {\n\t\tarraySortQuickSort(thisObject, 0, length-1, compare)\n\t}\n\treturn call.This\n}\n\nfunc builtinArrayIsArray(call FunctionCall) Value {\n\treturn boolValue(isArray(call.Argument(0).object()))\n}\n\nfunc builtinArrayIndexOf(call FunctionCall) Value {\n\tthisObject, matchValue := call.thisObject(), call.Argument(0)\n\tif length := int64(toUint32(thisObject.get(propertyLength))); length > 0 {\n\t\tindex := int64(0)\n\t\tif len(call.ArgumentList) > 1 {\n\t\t\tindex = call.Argument(1).number().int64\n\t\t}\n\t\tif index < 0 {\n\t\t\tif index += length; index < 0 {\n\t\t\t\tindex = 0\n\t\t\t}\n\t\t} else if index >= length {\n\t\t\tindex = -1\n\t\t}\n\t\tfor ; index >= 0 && index < length; index++ {\n\t\t\tname := arrayIndexToString(index)\n\t\t\tif !thisObject.hasProperty(name) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tvalue := thisObject.get(name)\n\t\t\tif strictEqualityComparison(matchValue, value) {\n\t\t\t\treturn uint32Value(uint32(index))\n\t\t\t}\n\t\t}\n\t}\n\treturn intValue(-1)\n}\n\nfunc builtinArrayLastIndexOf(call FunctionCall) Value {\n\tthisObject, matchValue := call.thisObject(), call.Argument(0)\n\tlength := int64(toUint32(thisObject.get(propertyLength)))\n\tindex := length - 1\n\tif len(call.ArgumentList) > 1 {\n\t\tindex = call.Argument(1).number().int64\n\t}\n\tif 0 > index {\n\t\tindex += length\n\t}\n\tif index > length {\n\t\tindex = length - 1\n\t} else if 0 > index {\n\t\treturn intValue(-1)\n\t}\n\tfor ; index >= 0; index-- {\n\t\tname := arrayIndexToString(index)\n\t\tif !thisObject.hasProperty(name) {\n\t\t\tcontinue\n\t\t}\n\t\tvalue := thisObject.get(name)\n\t\tif strictEqualityComparison(matchValue, value) {\n\t\t\treturn uint32Value(uint32(index))\n\t\t}\n\t}\n\treturn intValue(-1)\n}\n\nfunc builtinArrayEvery(call FunctionCall) Value {\n\tthisObject := call.thisObject()\n\tthis := objectValue(thisObject)\n\tif iterator := call.Argument(0); iterator.isCallable() {\n\t\tlength := int64(toUint32(thisObject.get(propertyLength)))\n\t\tcallThis := call.Argument(1)\n\t\tfor index := range length {\n\t\t\tif key := arrayIndexToString(index); thisObject.hasProperty(key) {\n\t\t\t\tif value := thisObject.get(key); iterator.call(call.runtime, callThis, value, int64Value(index), this).bool() {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\treturn falseValue\n\t\t\t}\n\t\t}\n\t\treturn trueValue\n\t}\n\tpanic(call.runtime.panicTypeError(\"Array.every argument %q is not callable\", call.Argument(0)))\n}\n\nfunc builtinArraySome(call FunctionCall) Value {\n\tthisObject := call.thisObject()\n\tthis := objectValue(thisObject)\n\tif iterator := call.Argument(0); iterator.isCallable() {\n\t\tlength := int64(toUint32(thisObject.get(propertyLength)))\n\t\tcallThis := call.Argument(1)\n\t\tfor index := range length {\n\t\t\tif key := arrayIndexToString(index); thisObject.hasProperty(key) {\n\t\t\t\tif value := thisObject.get(key); iterator.call(call.runtime, callThis, value, int64Value(index), this).bool() {\n\t\t\t\t\treturn trueValue\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn falseValue\n\t}\n\tpanic(call.runtime.panicTypeError(\"Array.some %q if not callable\", call.Argument(0)))\n}\n\nfunc builtinArrayForEach(call FunctionCall) Value {\n\tthisObject := call.thisObject()\n\tthis := objectValue(thisObject)\n\tif iterator := call.Argument(0); iterator.isCallable() {\n\t\tlength := int64(toUint32(thisObject.get(propertyLength)))\n\t\tcallThis := call.Argument(1)\n\t\tfor index := range length {\n\t\t\tif key := arrayIndexToString(index); thisObject.hasProperty(key) {\n\t\t\t\titerator.call(call.runtime, callThis, thisObject.get(key), int64Value(index), this)\n\t\t\t}\n\t\t}\n\t\treturn Value{}\n\t}\n\tpanic(call.runtime.panicTypeError(\"Array.foreach %q if not callable\", call.Argument(0)))\n}\n\nfunc builtinArrayMap(call FunctionCall) Value {\n\tthisObject := call.thisObject()\n\tthis := objectValue(thisObject)\n\tif iterator := call.Argument(0); iterator.isCallable() {\n\t\tlength := int64(toUint32(thisObject.get(propertyLength)))\n\t\tcallThis := call.Argument(1)\n\t\tvalues := make([]Value, length)\n\t\tfor index := range length {\n\t\t\tif key := arrayIndexToString(index); thisObject.hasProperty(key) {\n\t\t\t\tvalues[index] = iterator.call(call.runtime, callThis, thisObject.get(key), index, this)\n\t\t\t} else {\n\t\t\t\tvalues[index] = Value{}\n\t\t\t}\n\t\t}\n\t\treturn objectValue(call.runtime.newArrayOf(values))\n\t}\n\tpanic(call.runtime.panicTypeError(\"Array.foreach %q if not callable\", call.Argument(0)))\n}\n\nfunc builtinArrayFilter(call FunctionCall) Value {\n\tthisObject := call.thisObject()\n\tthis := objectValue(thisObject)\n\tif iterator := call.Argument(0); iterator.isCallable() {\n\t\tlength := int64(toUint32(thisObject.get(propertyLength)))\n\t\tcallThis := call.Argument(1)\n\t\tvalues := make([]Value, 0)\n\t\tfor index := range length {\n\t\t\tif key := arrayIndexToString(index); thisObject.hasProperty(key) {\n\t\t\t\tvalue := thisObject.get(key)\n\t\t\t\tif iterator.call(call.runtime, callThis, value, index, this).bool() {\n\t\t\t\t\tvalues = append(values, value)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn objectValue(call.runtime.newArrayOf(values))\n\t}\n\tpanic(call.runtime.panicTypeError(\"Array.filter %q if not callable\", call.Argument(0)))\n}\n\nfunc builtinArrayReduce(call FunctionCall) Value {\n\tthisObject := call.thisObject()\n\tthis := objectValue(thisObject)\n\tif iterator := call.Argument(0); iterator.isCallable() {\n\t\tinitial := len(call.ArgumentList) > 1\n\t\tstart := call.Argument(1)\n\t\tlength := int64(toUint32(thisObject.get(propertyLength)))\n\t\tindex := int64(0)\n\t\tif length > 0 || initial {\n\t\t\tvar accumulator Value\n\t\t\tif !initial {\n\t\t\t\tfor ; index < length; index++ {\n\t\t\t\t\tif key := arrayIndexToString(index); thisObject.hasProperty(key) {\n\t\t\t\t\t\taccumulator = thisObject.get(key)\n\t\t\t\t\t\tindex++\n\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\taccumulator = start\n\t\t\t}\n\t\t\tfor ; index < length; index++ {\n\t\t\t\tif key := arrayIndexToString(index); thisObject.hasProperty(key) {\n\t\t\t\t\taccumulator = iterator.call(call.runtime, Value{}, accumulator, thisObject.get(key), index, this)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn accumulator\n\t\t}\n\t}\n\tpanic(call.runtime.panicTypeError(\"Array.reduce %q if not callable\", call.Argument(0)))\n}\n\nfunc builtinArrayReduceRight(call FunctionCall) Value {\n\tthisObject := call.thisObject()\n\tthis := objectValue(thisObject)\n\tif iterator := call.Argument(0); iterator.isCallable() {\n\t\tinitial := len(call.ArgumentList) > 1\n\t\tstart := call.Argument(1)\n\t\tlength := int64(toUint32(thisObject.get(propertyLength)))\n\t\tif length > 0 || initial {\n\t\t\tindex := length - 1\n\t\t\tvar accumulator Value\n\t\t\tif !initial {\n\t\t\t\tfor ; index >= 0; index-- {\n\t\t\t\t\tif key := arrayIndexToString(index); thisObject.hasProperty(key) {\n\t\t\t\t\t\taccumulator = thisObject.get(key)\n\t\t\t\t\t\tindex--\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\taccumulator = start\n\t\t\t}\n\t\t\tfor ; index >= 0; index-- {\n\t\t\t\tif key := arrayIndexToString(index); thisObject.hasProperty(key) {\n\t\t\t\t\taccumulator = iterator.call(call.runtime, Value{}, accumulator, thisObject.get(key), key, this)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn accumulator\n\t\t}\n\t}\n\tpanic(call.runtime.panicTypeError(\"Array.reduceRight %q if not callable\", call.Argument(0)))\n}\n"
  },
  {
    "path": "builtin_boolean.go",
    "content": "package otto\n\n// Boolean\n\nfunc builtinBoolean(call FunctionCall) Value {\n\treturn boolValue(call.Argument(0).bool())\n}\n\nfunc builtinNewBoolean(obj *object, argumentList []Value) Value {\n\treturn objectValue(obj.runtime.newBoolean(valueOfArrayIndex(argumentList, 0)))\n}\n\nfunc builtinBooleanToString(call FunctionCall) Value {\n\tvalue := call.This\n\tif !value.IsBoolean() {\n\t\t// Will throw a TypeError if ThisObject is not a Boolean\n\t\tvalue = call.thisClassObject(classBooleanName).primitiveValue()\n\t}\n\treturn stringValue(value.string())\n}\n\nfunc builtinBooleanValueOf(call FunctionCall) Value {\n\tvalue := call.This\n\tif !value.IsBoolean() {\n\t\tvalue = call.thisClassObject(classBooleanName).primitiveValue()\n\t}\n\treturn value\n}\n"
  },
  {
    "path": "builtin_date.go",
    "content": "package otto\n\nimport (\n\t\"math\"\n\t\"time\"\n)\n\n// Date\n\nconst (\n\t// TODO Be like V8?\n\t// builtinDateDateTimeLayout = \"Mon Jan 2 2006 15:04:05 GMT-0700 (MST)\".\n\tbuiltinDateDateTimeLayout = time.RFC1123 // \"Mon, 02 Jan 2006 15:04:05 MST\"\n\tbuiltinDateDateLayout     = \"Mon, 02 Jan 2006\"\n\tbuiltinDateTimeLayout     = \"15:04:05 MST\"\n)\n\n// utcTimeZone is the time zone used for UTC calculations.\n// It is GMT not UTC as that's what Javascript does because toUTCString is\n// actually an alias to toGMTString.\nvar utcTimeZone = time.FixedZone(\"GMT\", 0)\n\nfunc builtinDate(call FunctionCall) Value {\n\tdate := &dateObject{}\n\tdate.Set(newDateTime([]Value{}, time.Local)) //nolint:gosmopolitan\n\treturn stringValue(date.Time().Format(builtinDateDateTimeLayout))\n}\n\nfunc builtinNewDate(obj *object, argumentList []Value) Value {\n\treturn objectValue(obj.runtime.newDate(newDateTime(argumentList, time.Local))) //nolint:gosmopolitan\n}\n\nfunc builtinDateToString(call FunctionCall) Value {\n\tdate := dateObjectOf(call.runtime, call.thisObject())\n\tif date.isNaN {\n\t\treturn stringValue(\"Invalid Date\")\n\t}\n\treturn stringValue(date.Time().Local().Format(builtinDateDateTimeLayout)) //nolint:gosmopolitan\n}\n\nfunc builtinDateToDateString(call FunctionCall) Value {\n\tdate := dateObjectOf(call.runtime, call.thisObject())\n\tif date.isNaN {\n\t\treturn stringValue(\"Invalid Date\")\n\t}\n\treturn stringValue(date.Time().Local().Format(builtinDateDateLayout)) //nolint:gosmopolitan\n}\n\nfunc builtinDateToTimeString(call FunctionCall) Value {\n\tdate := dateObjectOf(call.runtime, call.thisObject())\n\tif date.isNaN {\n\t\treturn stringValue(\"Invalid Date\")\n\t}\n\treturn stringValue(date.Time().Local().Format(builtinDateTimeLayout)) //nolint:gosmopolitan\n}\n\nfunc builtinDateToUTCString(call FunctionCall) Value {\n\tdate := dateObjectOf(call.runtime, call.thisObject())\n\tif date.isNaN {\n\t\treturn stringValue(\"Invalid Date\")\n\t}\n\treturn stringValue(date.Time().In(utcTimeZone).Format(builtinDateDateTimeLayout))\n}\n\nfunc builtinDateToISOString(call FunctionCall) Value {\n\tdate := dateObjectOf(call.runtime, call.thisObject())\n\tif date.isNaN {\n\t\treturn stringValue(\"Invalid Date\")\n\t}\n\treturn stringValue(date.Time().Format(\"2006-01-02T15:04:05.000Z\"))\n}\n\nfunc builtinDateToJSON(call FunctionCall) Value {\n\tobj := call.thisObject()\n\tvalue := obj.DefaultValue(defaultValueHintNumber) // FIXME object.primitiveNumberValue\n\t// FIXME fv.isFinite\n\tif fv := value.float64(); math.IsNaN(fv) || math.IsInf(fv, 0) {\n\t\treturn nullValue\n\t}\n\n\ttoISOString := obj.get(\"toISOString\")\n\tif !toISOString.isCallable() {\n\t\t// FIXME\n\t\tpanic(call.runtime.panicTypeError(\"Date.toJSON toISOString %q is not callable\", toISOString))\n\t}\n\treturn toISOString.call(call.runtime, objectValue(obj), []Value{})\n}\n\nfunc builtinDateToGMTString(call FunctionCall) Value {\n\tdate := dateObjectOf(call.runtime, call.thisObject())\n\tif date.isNaN {\n\t\treturn stringValue(\"Invalid Date\")\n\t}\n\treturn stringValue(date.Time().Format(\"Mon, 02 Jan 2006 15:04:05 GMT\"))\n}\n\nfunc builtinDateGetTime(call FunctionCall) Value {\n\tdate := dateObjectOf(call.runtime, call.thisObject())\n\tif date.isNaN {\n\t\treturn NaNValue()\n\t}\n\t// We do this (convert away from a float) so the user\n\t// does not get something back in exponential notation\n\treturn int64Value(date.Epoch())\n}\n\nfunc builtinDateSetTime(call FunctionCall) Value {\n\tobj := call.thisObject()\n\tdate := dateObjectOf(call.runtime, call.thisObject())\n\tdate.Set(call.Argument(0).float64())\n\tobj.value = date\n\treturn date.Value()\n}\n\nfunc builtinDateBeforeSet(call FunctionCall, argumentLimit int, timeLocal bool) (*object, *dateObject, *ecmaTime, []int) {\n\tobj := call.thisObject()\n\tdate := dateObjectOf(call.runtime, call.thisObject())\n\tif date.isNaN {\n\t\treturn nil, nil, nil, nil\n\t}\n\n\tif argumentLimit > len(call.ArgumentList) {\n\t\targumentLimit = len(call.ArgumentList)\n\t}\n\n\tif argumentLimit == 0 {\n\t\tobj.value = invalidDateObject\n\t\treturn nil, nil, nil, nil\n\t}\n\n\tvalueList := make([]int, argumentLimit)\n\tfor index := range argumentLimit {\n\t\tvalue := call.ArgumentList[index]\n\t\tnm := value.number()\n\t\tswitch nm.kind {\n\t\tcase numberInteger, numberFloat:\n\t\tdefault:\n\t\t\tobj.value = invalidDateObject\n\t\t\treturn nil, nil, nil, nil\n\t\t}\n\t\tvalueList[index] = int(nm.int64)\n\t}\n\tbaseTime := date.Time()\n\tif timeLocal {\n\t\tbaseTime = baseTime.Local() //nolint:gosmopolitan\n\t}\n\tecmaTime := newEcmaTime(baseTime)\n\treturn obj, &date, &ecmaTime, valueList\n}\n\nfunc builtinDateParse(call FunctionCall) Value {\n\tdate := call.Argument(0).string()\n\treturn float64Value(dateParse(date))\n}\n\nfunc builtinDateUTC(call FunctionCall) Value {\n\treturn float64Value(newDateTime(call.ArgumentList, time.UTC))\n}\n\nfunc builtinDateNow(call FunctionCall) Value {\n\tcall.ArgumentList = []Value(nil)\n\treturn builtinDateUTC(call)\n}\n\n// This is a placeholder.\nfunc builtinDateToLocaleString(call FunctionCall) Value {\n\tdate := dateObjectOf(call.runtime, call.thisObject())\n\tif date.isNaN {\n\t\treturn stringValue(\"Invalid Date\")\n\t}\n\treturn stringValue(date.Time().Local().Format(\"2006-01-02 15:04:05\")) //nolint:gosmopolitan\n}\n\n// This is a placeholder.\nfunc builtinDateToLocaleDateString(call FunctionCall) Value {\n\tdate := dateObjectOf(call.runtime, call.thisObject())\n\tif date.isNaN {\n\t\treturn stringValue(\"Invalid Date\")\n\t}\n\treturn stringValue(date.Time().Local().Format(\"2006-01-02\")) //nolint:gosmopolitan\n}\n\n// This is a placeholder.\nfunc builtinDateToLocaleTimeString(call FunctionCall) Value {\n\tdate := dateObjectOf(call.runtime, call.thisObject())\n\tif date.isNaN {\n\t\treturn stringValue(\"Invalid Date\")\n\t}\n\treturn stringValue(date.Time().Local().Format(\"15:04:05\")) //nolint:gosmopolitan\n}\n\nfunc builtinDateValueOf(call FunctionCall) Value {\n\tdate := dateObjectOf(call.runtime, call.thisObject())\n\tif date.isNaN {\n\t\treturn NaNValue()\n\t}\n\treturn date.Value()\n}\n\nfunc builtinDateGetYear(call FunctionCall) Value {\n\t// Will throw a TypeError is ThisObject is nil or\n\t// does not have Class of \"Date\"\n\tdate := dateObjectOf(call.runtime, call.thisObject())\n\tif date.isNaN {\n\t\treturn NaNValue()\n\t}\n\treturn intValue(date.Time().Local().Year() - 1900) //nolint:gosmopolitan\n}\n\nfunc builtinDateGetFullYear(call FunctionCall) Value {\n\t// Will throw a TypeError is ThisObject is nil or\n\t// does not have Class of \"Date\"\n\tdate := dateObjectOf(call.runtime, call.thisObject())\n\tif date.isNaN {\n\t\treturn NaNValue()\n\t}\n\treturn intValue(date.Time().Local().Year()) //nolint:gosmopolitan\n}\n\nfunc builtinDateGetUTCFullYear(call FunctionCall) Value {\n\tdate := dateObjectOf(call.runtime, call.thisObject())\n\tif date.isNaN {\n\t\treturn NaNValue()\n\t}\n\treturn intValue(date.Time().Year())\n}\n\nfunc builtinDateGetMonth(call FunctionCall) Value {\n\tdate := dateObjectOf(call.runtime, call.thisObject())\n\tif date.isNaN {\n\t\treturn NaNValue()\n\t}\n\treturn intValue(dateFromGoMonth(date.Time().Local().Month())) //nolint:gosmopolitan\n}\n\nfunc builtinDateGetUTCMonth(call FunctionCall) Value {\n\tdate := dateObjectOf(call.runtime, call.thisObject())\n\tif date.isNaN {\n\t\treturn NaNValue()\n\t}\n\treturn intValue(dateFromGoMonth(date.Time().Month()))\n}\n\nfunc builtinDateGetDate(call FunctionCall) Value {\n\tdate := dateObjectOf(call.runtime, call.thisObject())\n\tif date.isNaN {\n\t\treturn NaNValue()\n\t}\n\treturn intValue(date.Time().Local().Day()) //nolint:gosmopolitan\n}\n\nfunc builtinDateGetUTCDate(call FunctionCall) Value {\n\tdate := dateObjectOf(call.runtime, call.thisObject())\n\tif date.isNaN {\n\t\treturn NaNValue()\n\t}\n\treturn intValue(date.Time().Day())\n}\n\nfunc builtinDateGetDay(call FunctionCall) Value {\n\t// Actually day of the week\n\tdate := dateObjectOf(call.runtime, call.thisObject())\n\tif date.isNaN {\n\t\treturn NaNValue()\n\t}\n\treturn intValue(dateFromGoDay(date.Time().Local().Weekday())) //nolint:gosmopolitan\n}\n\nfunc builtinDateGetUTCDay(call FunctionCall) Value {\n\tdate := dateObjectOf(call.runtime, call.thisObject())\n\tif date.isNaN {\n\t\treturn NaNValue()\n\t}\n\treturn intValue(dateFromGoDay(date.Time().Weekday()))\n}\n\nfunc builtinDateGetHours(call FunctionCall) Value {\n\tdate := dateObjectOf(call.runtime, call.thisObject())\n\tif date.isNaN {\n\t\treturn NaNValue()\n\t}\n\treturn intValue(date.Time().Local().Hour()) //nolint:gosmopolitan\n}\n\nfunc builtinDateGetUTCHours(call FunctionCall) Value {\n\tdate := dateObjectOf(call.runtime, call.thisObject())\n\tif date.isNaN {\n\t\treturn NaNValue()\n\t}\n\treturn intValue(date.Time().Hour())\n}\n\nfunc builtinDateGetMinutes(call FunctionCall) Value {\n\tdate := dateObjectOf(call.runtime, call.thisObject())\n\tif date.isNaN {\n\t\treturn NaNValue()\n\t}\n\treturn intValue(date.Time().Local().Minute()) //nolint:gosmopolitan\n}\n\nfunc builtinDateGetUTCMinutes(call FunctionCall) Value {\n\tdate := dateObjectOf(call.runtime, call.thisObject())\n\tif date.isNaN {\n\t\treturn NaNValue()\n\t}\n\treturn intValue(date.Time().Minute())\n}\n\nfunc builtinDateGetSeconds(call FunctionCall) Value {\n\tdate := dateObjectOf(call.runtime, call.thisObject())\n\tif date.isNaN {\n\t\treturn NaNValue()\n\t}\n\treturn intValue(date.Time().Local().Second()) //nolint:gosmopolitan\n}\n\nfunc builtinDateGetUTCSeconds(call FunctionCall) Value {\n\tdate := dateObjectOf(call.runtime, call.thisObject())\n\tif date.isNaN {\n\t\treturn NaNValue()\n\t}\n\treturn intValue(date.Time().Second())\n}\n\nfunc builtinDateGetMilliseconds(call FunctionCall) Value {\n\tdate := dateObjectOf(call.runtime, call.thisObject())\n\tif date.isNaN {\n\t\treturn NaNValue()\n\t}\n\treturn intValue(date.Time().Local().Nanosecond() / (100 * 100 * 100)) //nolint:gosmopolitan\n}\n\nfunc builtinDateGetUTCMilliseconds(call FunctionCall) Value {\n\tdate := dateObjectOf(call.runtime, call.thisObject())\n\tif date.isNaN {\n\t\treturn NaNValue()\n\t}\n\treturn intValue(date.Time().Nanosecond() / (100 * 100 * 100))\n}\n\nfunc builtinDateGetTimezoneOffset(call FunctionCall) Value {\n\tdate := dateObjectOf(call.runtime, call.thisObject())\n\tif date.isNaN {\n\t\treturn NaNValue()\n\t}\n\ttimeLocal := date.Time().Local() //nolint:gosmopolitan\n\t// Is this kosher?\n\ttimeLocalAsUTC := time.Date(\n\t\ttimeLocal.Year(),\n\t\ttimeLocal.Month(),\n\t\ttimeLocal.Day(),\n\t\ttimeLocal.Hour(),\n\t\ttimeLocal.Minute(),\n\t\ttimeLocal.Second(),\n\t\ttimeLocal.Nanosecond(),\n\t\ttime.UTC,\n\t)\n\treturn float64Value(date.Time().Sub(timeLocalAsUTC).Seconds() / 60)\n}\n\nfunc builtinDateSetMilliseconds(call FunctionCall) Value {\n\tobj, date, ecmaTime, value := builtinDateBeforeSet(call, 1, true)\n\tif ecmaTime == nil {\n\t\treturn NaNValue()\n\t}\n\n\tecmaTime.millisecond = value[0]\n\n\tdate.SetTime(ecmaTime.goTime())\n\tobj.value = *date\n\treturn date.Value()\n}\n\nfunc builtinDateSetUTCMilliseconds(call FunctionCall) Value {\n\tobj, date, ecmaTime, value := builtinDateBeforeSet(call, 1, false)\n\tif ecmaTime == nil {\n\t\treturn NaNValue()\n\t}\n\n\tecmaTime.millisecond = value[0]\n\n\tdate.SetTime(ecmaTime.goTime())\n\tobj.value = *date\n\treturn date.Value()\n}\n\nfunc builtinDateSetSeconds(call FunctionCall) Value {\n\tobj, date, ecmaTime, value := builtinDateBeforeSet(call, 2, true)\n\tif ecmaTime == nil {\n\t\treturn NaNValue()\n\t}\n\n\tif len(value) > 1 {\n\t\tecmaTime.millisecond = value[1]\n\t}\n\tecmaTime.second = value[0]\n\n\tdate.SetTime(ecmaTime.goTime())\n\tobj.value = *date\n\treturn date.Value()\n}\n\nfunc builtinDateSetUTCSeconds(call FunctionCall) Value {\n\tobj, date, ecmaTime, value := builtinDateBeforeSet(call, 2, false)\n\tif ecmaTime == nil {\n\t\treturn NaNValue()\n\t}\n\n\tif len(value) > 1 {\n\t\tecmaTime.millisecond = value[1]\n\t}\n\tecmaTime.second = value[0]\n\n\tdate.SetTime(ecmaTime.goTime())\n\tobj.value = *date\n\treturn date.Value()\n}\n\nfunc builtinDateSetMinutes(call FunctionCall) Value {\n\tobj, date, ecmaTime, value := builtinDateBeforeSet(call, 3, true)\n\tif ecmaTime == nil {\n\t\treturn NaNValue()\n\t}\n\n\tif len(value) > 2 {\n\t\tecmaTime.millisecond = value[2]\n\t\tecmaTime.second = value[1]\n\t} else if len(value) > 1 {\n\t\tecmaTime.second = value[1]\n\t}\n\tecmaTime.minute = value[0]\n\n\tdate.SetTime(ecmaTime.goTime())\n\tobj.value = *date\n\treturn date.Value()\n}\n\nfunc builtinDateSetUTCMinutes(call FunctionCall) Value {\n\tobj, date, ecmaTime, value := builtinDateBeforeSet(call, 3, false)\n\tif ecmaTime == nil {\n\t\treturn NaNValue()\n\t}\n\n\tif len(value) > 2 {\n\t\tecmaTime.millisecond = value[2]\n\t\tecmaTime.second = value[1]\n\t} else if len(value) > 1 {\n\t\tecmaTime.second = value[1]\n\t}\n\tecmaTime.minute = value[0]\n\n\tdate.SetTime(ecmaTime.goTime())\n\tobj.value = *date\n\treturn date.Value()\n}\n\nfunc builtinDateSetHours(call FunctionCall) Value {\n\tobj, date, ecmaTime, value := builtinDateBeforeSet(call, 4, true)\n\tif ecmaTime == nil {\n\t\treturn NaNValue()\n\t}\n\n\tswitch {\n\tcase len(value) > 3:\n\t\tecmaTime.millisecond = value[3]\n\t\tfallthrough\n\tcase len(value) > 2:\n\t\tecmaTime.second = value[2]\n\t\tfallthrough\n\tcase len(value) > 1:\n\t\tecmaTime.minute = value[1]\n\t}\n\tecmaTime.hour = value[0]\n\n\tdate.SetTime(ecmaTime.goTime())\n\tobj.value = *date\n\treturn date.Value()\n}\n\nfunc builtinDateSetUTCHours(call FunctionCall) Value {\n\tobj, date, ecmaTime, value := builtinDateBeforeSet(call, 4, false)\n\tif ecmaTime == nil {\n\t\treturn NaNValue()\n\t}\n\n\tswitch {\n\tcase len(value) > 3:\n\t\tecmaTime.millisecond = value[3]\n\t\tfallthrough\n\tcase len(value) > 2:\n\t\tecmaTime.second = value[2]\n\t\tfallthrough\n\tcase len(value) > 1:\n\t\tecmaTime.minute = value[1]\n\t}\n\tecmaTime.hour = value[0]\n\n\tdate.SetTime(ecmaTime.goTime())\n\tobj.value = *date\n\treturn date.Value()\n}\n\nfunc builtinDateSetDate(call FunctionCall) Value {\n\tobj, date, ecmaTime, value := builtinDateBeforeSet(call, 1, true)\n\tif ecmaTime == nil {\n\t\treturn NaNValue()\n\t}\n\n\tecmaTime.day = value[0]\n\n\tdate.SetTime(ecmaTime.goTime())\n\tobj.value = *date\n\treturn date.Value()\n}\n\nfunc builtinDateSetUTCDate(call FunctionCall) Value {\n\tobj, date, ecmaTime, value := builtinDateBeforeSet(call, 1, false)\n\tif ecmaTime == nil {\n\t\treturn NaNValue()\n\t}\n\n\tecmaTime.day = value[0]\n\n\tdate.SetTime(ecmaTime.goTime())\n\tobj.value = *date\n\treturn date.Value()\n}\n\nfunc builtinDateSetMonth(call FunctionCall) Value {\n\tobj, date, ecmaTime, value := builtinDateBeforeSet(call, 2, true)\n\tif ecmaTime == nil {\n\t\treturn NaNValue()\n\t}\n\n\tif len(value) > 1 {\n\t\tecmaTime.day = value[1]\n\t}\n\tecmaTime.month = value[0]\n\n\tdate.SetTime(ecmaTime.goTime())\n\tobj.value = *date\n\treturn date.Value()\n}\n\nfunc builtinDateSetUTCMonth(call FunctionCall) Value {\n\tobj, date, ecmaTime, value := builtinDateBeforeSet(call, 2, false)\n\tif ecmaTime == nil {\n\t\treturn NaNValue()\n\t}\n\n\tif len(value) > 1 {\n\t\tecmaTime.day = value[1]\n\t}\n\tecmaTime.month = value[0]\n\n\tdate.SetTime(ecmaTime.goTime())\n\tobj.value = *date\n\treturn date.Value()\n}\n\nfunc builtinDateSetYear(call FunctionCall) Value {\n\tobj, date, ecmaTime, value := builtinDateBeforeSet(call, 1, true)\n\tif ecmaTime == nil {\n\t\treturn NaNValue()\n\t}\n\n\tyear := value[0]\n\tif 0 <= year && year <= 99 {\n\t\tyear += 1900\n\t}\n\tecmaTime.year = year\n\n\tdate.SetTime(ecmaTime.goTime())\n\tobj.value = *date\n\treturn date.Value()\n}\n\nfunc builtinDateSetFullYear(call FunctionCall) Value {\n\tobj, date, ecmaTime, value := builtinDateBeforeSet(call, 3, true)\n\tif ecmaTime == nil {\n\t\treturn NaNValue()\n\t}\n\n\tif len(value) > 2 {\n\t\tecmaTime.day = value[2]\n\t\tecmaTime.month = value[1]\n\t} else if len(value) > 1 {\n\t\tecmaTime.month = value[1]\n\t}\n\tecmaTime.year = value[0]\n\n\tdate.SetTime(ecmaTime.goTime())\n\tobj.value = *date\n\treturn date.Value()\n}\n\nfunc builtinDateSetUTCFullYear(call FunctionCall) Value {\n\tobj, date, ecmaTime, value := builtinDateBeforeSet(call, 3, false)\n\tif ecmaTime == nil {\n\t\treturn NaNValue()\n\t}\n\n\tif len(value) > 2 {\n\t\tecmaTime.day = value[2]\n\t\tecmaTime.month = value[1]\n\t} else if len(value) > 1 {\n\t\tecmaTime.month = value[1]\n\t}\n\tecmaTime.year = value[0]\n\n\tdate.SetTime(ecmaTime.goTime())\n\tobj.value = *date\n\treturn date.Value()\n}\n\n// toUTCString\n// toISOString\n// toJSONString\n// toJSON\n"
  },
  {
    "path": "builtin_error.go",
    "content": "package otto\n\nimport (\n\t\"fmt\"\n)\n\nfunc builtinError(call FunctionCall) Value {\n\treturn objectValue(call.runtime.newError(classErrorName, call.Argument(0), 1))\n}\n\nfunc builtinNewError(obj *object, argumentList []Value) Value {\n\treturn objectValue(obj.runtime.newError(classErrorName, valueOfArrayIndex(argumentList, 0), 0))\n}\n\nfunc builtinErrorToString(call FunctionCall) Value {\n\tthisObject := call.thisObject()\n\tif thisObject == nil {\n\t\tpanic(call.runtime.panicTypeError(\"Error.toString is nil\"))\n\t}\n\n\tname := classErrorName\n\tnameValue := thisObject.get(\"name\")\n\tif nameValue.IsDefined() {\n\t\tname = nameValue.string()\n\t}\n\n\tmessage := \"\"\n\tmessageValue := thisObject.get(\"message\")\n\tif messageValue.IsDefined() {\n\t\tmessage = messageValue.string()\n\t}\n\n\tif len(name) == 0 {\n\t\treturn stringValue(message)\n\t}\n\n\tif len(message) == 0 {\n\t\treturn stringValue(name)\n\t}\n\n\treturn stringValue(fmt.Sprintf(\"%s: %s\", name, message))\n}\n\nfunc (rt *runtime) newEvalError(message Value) *object {\n\to := rt.newErrorObject(\"EvalError\", message, 0)\n\to.prototype = rt.global.EvalErrorPrototype\n\treturn o\n}\n\nfunc builtinEvalError(call FunctionCall) Value {\n\treturn objectValue(call.runtime.newEvalError(call.Argument(0)))\n}\n\nfunc builtinNewEvalError(obj *object, argumentList []Value) Value {\n\treturn objectValue(obj.runtime.newEvalError(valueOfArrayIndex(argumentList, 0)))\n}\n\nfunc (rt *runtime) newTypeError(message Value) *object {\n\to := rt.newErrorObject(\"TypeError\", message, 0)\n\to.prototype = rt.global.TypeErrorPrototype\n\treturn o\n}\n\nfunc builtinTypeError(call FunctionCall) Value {\n\treturn objectValue(call.runtime.newTypeError(call.Argument(0)))\n}\n\nfunc builtinNewTypeError(obj *object, argumentList []Value) Value {\n\treturn objectValue(obj.runtime.newTypeError(valueOfArrayIndex(argumentList, 0)))\n}\n\nfunc (rt *runtime) newRangeError(message Value) *object {\n\to := rt.newErrorObject(\"RangeError\", message, 0)\n\to.prototype = rt.global.RangeErrorPrototype\n\treturn o\n}\n\nfunc builtinRangeError(call FunctionCall) Value {\n\treturn objectValue(call.runtime.newRangeError(call.Argument(0)))\n}\n\nfunc builtinNewRangeError(obj *object, argumentList []Value) Value {\n\treturn objectValue(obj.runtime.newRangeError(valueOfArrayIndex(argumentList, 0)))\n}\n\nfunc (rt *runtime) newURIError(message Value) *object {\n\to := rt.newErrorObject(\"URIError\", message, 0)\n\to.prototype = rt.global.URIErrorPrototype\n\treturn o\n}\n\nfunc (rt *runtime) newReferenceError(message Value) *object {\n\to := rt.newErrorObject(\"ReferenceError\", message, 0)\n\to.prototype = rt.global.ReferenceErrorPrototype\n\treturn o\n}\n\nfunc builtinReferenceError(call FunctionCall) Value {\n\treturn objectValue(call.runtime.newReferenceError(call.Argument(0)))\n}\n\nfunc builtinNewReferenceError(obj *object, argumentList []Value) Value {\n\treturn objectValue(obj.runtime.newReferenceError(valueOfArrayIndex(argumentList, 0)))\n}\n\nfunc (rt *runtime) newSyntaxError(message Value) *object {\n\to := rt.newErrorObject(\"SyntaxError\", message, 0)\n\to.prototype = rt.global.SyntaxErrorPrototype\n\treturn o\n}\n\nfunc builtinSyntaxError(call FunctionCall) Value {\n\treturn objectValue(call.runtime.newSyntaxError(call.Argument(0)))\n}\n\nfunc builtinNewSyntaxError(obj *object, argumentList []Value) Value {\n\treturn objectValue(obj.runtime.newSyntaxError(valueOfArrayIndex(argumentList, 0)))\n}\n\nfunc builtinURIError(call FunctionCall) Value {\n\treturn objectValue(call.runtime.newURIError(call.Argument(0)))\n}\n\nfunc builtinNewURIError(obj *object, argumentList []Value) Value {\n\treturn objectValue(obj.runtime.newURIError(valueOfArrayIndex(argumentList, 0)))\n}\n"
  },
  {
    "path": "builtin_function.go",
    "content": "package otto\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\t\"unicode\"\n\n\t\"github.com/robertkrimen/otto/parser\"\n)\n\n// Function\n\nfunc builtinFunction(call FunctionCall) Value {\n\treturn objectValue(builtinNewFunctionNative(call.runtime, call.ArgumentList))\n}\n\nfunc builtinNewFunction(obj *object, argumentList []Value) Value {\n\treturn objectValue(builtinNewFunctionNative(obj.runtime, argumentList))\n}\n\nfunc argumentList2parameterList(argumentList []Value) []string {\n\tparameterList := make([]string, 0, len(argumentList))\n\tfor _, value := range argumentList {\n\t\ttmp := strings.FieldsFunc(value.string(), func(chr rune) bool {\n\t\t\treturn chr == ',' || unicode.IsSpace(chr)\n\t\t})\n\t\tparameterList = append(parameterList, tmp...)\n\t}\n\treturn parameterList\n}\n\nfunc builtinNewFunctionNative(rt *runtime, argumentList []Value) *object {\n\tvar parameterList, body string\n\tif count := len(argumentList); count > 0 {\n\t\ttmp := make([]string, 0, count-1)\n\t\tfor _, value := range argumentList[0 : count-1] {\n\t\t\ttmp = append(tmp, value.string())\n\t\t}\n\t\tparameterList = strings.Join(tmp, \",\")\n\t\tbody = argumentList[count-1].string()\n\t}\n\n\t// FIXME\n\tfunction, err := parser.ParseFunction(parameterList, body)\n\trt.parseThrow(err) // Will panic/throw appropriately\n\tcmpl := compiler{}\n\tcmplFunction := cmpl.parseExpression(function)\n\n\treturn rt.newNodeFunction(cmplFunction.(*nodeFunctionLiteral), rt.globalStash)\n}\n\nfunc builtinFunctionToString(call FunctionCall) Value {\n\tobj := call.thisClassObject(classFunctionName) // Should throw a TypeError unless Function\n\tswitch fn := obj.value.(type) {\n\tcase nativeFunctionObject:\n\t\treturn stringValue(fmt.Sprintf(\"function %s() { [native code] }\", fn.name))\n\tcase nodeFunctionObject:\n\t\treturn stringValue(fn.node.source)\n\tcase bindFunctionObject:\n\t\treturn stringValue(\"function () { [native code] }\")\n\tdefault:\n\t\tpanic(call.runtime.panicTypeError(\"Function.toString unknown type %T\", obj.value))\n\t}\n}\n\nfunc builtinFunctionApply(call FunctionCall) Value {\n\tif !call.This.isCallable() {\n\t\tpanic(call.runtime.panicTypeError(\"Function.apply %q is not callable\", call.This))\n\t}\n\tthis := call.Argument(0)\n\tif this.IsUndefined() {\n\t\t// FIXME Not ECMA5\n\t\tthis = objectValue(call.runtime.globalObject)\n\t}\n\targumentList := call.Argument(1)\n\tswitch argumentList.kind {\n\tcase valueUndefined, valueNull:\n\t\treturn call.thisObject().call(this, nil, false, nativeFrame)\n\tcase valueObject:\n\tdefault:\n\t\tpanic(call.runtime.panicTypeError(\"Function.apply unknown type %T for second argument\"))\n\t}\n\n\tarrayObject := argumentList.object()\n\tthisObject := call.thisObject()\n\tlength := int64(toUint32(arrayObject.get(propertyLength)))\n\tvalueArray := make([]Value, length)\n\tfor index := range length {\n\t\tvalueArray[index] = arrayObject.get(arrayIndexToString(index))\n\t}\n\treturn thisObject.call(this, valueArray, false, nativeFrame)\n}\n\nfunc builtinFunctionCall(call FunctionCall) Value {\n\tif !call.This.isCallable() {\n\t\tpanic(call.runtime.panicTypeError(\"Function.call %q is not callable\", call.This))\n\t}\n\tthisObject := call.thisObject()\n\tthis := call.Argument(0)\n\tif this.IsUndefined() {\n\t\t// FIXME Not ECMA5\n\t\tthis = objectValue(call.runtime.globalObject)\n\t}\n\tif len(call.ArgumentList) >= 1 {\n\t\treturn thisObject.call(this, call.ArgumentList[1:], false, nativeFrame)\n\t}\n\treturn thisObject.call(this, nil, false, nativeFrame)\n}\n\nfunc builtinFunctionBind(call FunctionCall) Value {\n\ttarget := call.This\n\tif !target.isCallable() {\n\t\tpanic(call.runtime.panicTypeError(\"Function.bind %q is not callable\", call.This))\n\t}\n\ttargetObject := target.object()\n\n\tthis := call.Argument(0)\n\targumentList := call.slice(1)\n\tif this.IsUndefined() {\n\t\t// FIXME Do this elsewhere?\n\t\tthis = objectValue(call.runtime.globalObject)\n\t}\n\n\treturn objectValue(call.runtime.newBoundFunction(targetObject, this, argumentList))\n}\n"
  },
  {
    "path": "builtin_json.go",
    "content": "package otto\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"strings\"\n)\n\ntype builtinJSONParseContext struct {\n\treviver Value\n\tcall    FunctionCall\n}\n\nfunc builtinJSONParse(call FunctionCall) Value {\n\tctx := builtinJSONParseContext{\n\t\tcall: call,\n\t}\n\trevive := false\n\tif reviver := call.Argument(1); reviver.isCallable() {\n\t\trevive = true\n\t\tctx.reviver = reviver\n\t}\n\n\tvar root interface{}\n\terr := json.Unmarshal([]byte(call.Argument(0).string()), &root)\n\tif err != nil {\n\t\tpanic(call.runtime.panicSyntaxError(err.Error()))\n\t}\n\tvalue, exists := builtinJSONParseWalk(ctx, root)\n\tif !exists {\n\t\tvalue = Value{}\n\t}\n\tif revive {\n\t\troot := ctx.call.runtime.newObject()\n\t\troot.put(\"\", value, false)\n\t\treturn builtinJSONReviveWalk(ctx, root, \"\")\n\t}\n\treturn value\n}\n\nfunc builtinJSONReviveWalk(ctx builtinJSONParseContext, holder *object, name string) Value {\n\tvalue := holder.get(name)\n\tif obj := value.object(); obj != nil {\n\t\tif isArray(obj) {\n\t\t\tlength := int64(objectLength(obj))\n\t\t\tfor index := range length {\n\t\t\t\tidxName := arrayIndexToString(index)\n\t\t\t\tidxValue := builtinJSONReviveWalk(ctx, obj, idxName)\n\t\t\t\tif idxValue.IsUndefined() {\n\t\t\t\t\tobj.delete(idxName, false)\n\t\t\t\t} else {\n\t\t\t\t\tobj.defineProperty(idxName, idxValue, 0o111, false)\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tobj.enumerate(false, func(name string) bool {\n\t\t\t\tenumVal := builtinJSONReviveWalk(ctx, obj, name)\n\t\t\t\tif enumVal.IsUndefined() {\n\t\t\t\t\tobj.delete(name, false)\n\t\t\t\t} else {\n\t\t\t\t\tobj.defineProperty(name, enumVal, 0o111, false)\n\t\t\t\t}\n\t\t\t\treturn true\n\t\t\t})\n\t\t}\n\t}\n\treturn ctx.reviver.call(ctx.call.runtime, objectValue(holder), name, value)\n}\n\nfunc builtinJSONParseWalk(ctx builtinJSONParseContext, rawValue interface{}) (Value, bool) {\n\tswitch value := rawValue.(type) {\n\tcase nil:\n\t\treturn nullValue, true\n\tcase bool:\n\t\treturn boolValue(value), true\n\tcase string:\n\t\treturn stringValue(value), true\n\tcase float64:\n\t\treturn float64Value(value), true\n\tcase []interface{}:\n\t\tarrayValue := make([]Value, len(value))\n\t\tfor index, rawValue := range value {\n\t\t\tif value, exists := builtinJSONParseWalk(ctx, rawValue); exists {\n\t\t\t\tarrayValue[index] = value\n\t\t\t}\n\t\t}\n\t\treturn objectValue(ctx.call.runtime.newArrayOf(arrayValue)), true\n\tcase map[string]interface{}:\n\t\tobj := ctx.call.runtime.newObject()\n\t\tfor name, rawValue := range value {\n\t\t\tif value, exists := builtinJSONParseWalk(ctx, rawValue); exists {\n\t\t\t\tobj.put(name, value, false)\n\t\t\t}\n\t\t}\n\t\treturn objectValue(obj), true\n\t}\n\treturn Value{}, false\n}\n\ntype builtinJSONStringifyContext struct {\n\treplacerFunction *Value\n\tgap              string\n\tstack            []*object\n\tpropertyList     []string\n\tcall             FunctionCall\n}\n\nfunc builtinJSONStringify(call FunctionCall) Value {\n\tctx := builtinJSONStringifyContext{\n\t\tcall:  call,\n\t\tstack: []*object{nil},\n\t}\n\treplacer := call.Argument(1).object()\n\tif replacer != nil {\n\t\tif isArray(replacer) {\n\t\t\tlength := objectLength(replacer)\n\t\t\tseen := map[string]bool{}\n\t\t\tpropertyList := make([]string, length)\n\t\t\tlength = 0\n\t\t\tfor index := range propertyList {\n\t\t\t\tvalue := replacer.get(arrayIndexToString(int64(index)))\n\t\t\t\tswitch value.kind {\n\t\t\t\tcase valueObject:\n\t\t\t\t\tswitch value.value.(*object).class {\n\t\t\t\t\tcase classStringName, classNumberName:\n\t\t\t\t\tdefault:\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\tcase valueString, valueNumber:\n\t\t\t\tdefault:\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tname := value.string()\n\t\t\t\tif seen[name] {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tseen[name] = true\n\t\t\t\tlength++\n\t\t\t\tpropertyList[index] = name\n\t\t\t}\n\t\t\tctx.propertyList = propertyList[0:length]\n\t\t} else if replacer.class == classFunctionName {\n\t\t\tvalue := objectValue(replacer)\n\t\t\tctx.replacerFunction = &value\n\t\t}\n\t}\n\tif spaceValue, exists := call.getArgument(2); exists {\n\t\tif spaceValue.kind == valueObject {\n\t\t\tswitch spaceValue.value.(*object).class {\n\t\t\tcase classStringName:\n\t\t\t\tspaceValue = stringValue(spaceValue.string())\n\t\t\tcase classNumberName:\n\t\t\t\tspaceValue = spaceValue.numberValue()\n\t\t\t}\n\t\t}\n\t\tswitch spaceValue.kind {\n\t\tcase valueString:\n\t\t\tvalue := spaceValue.string()\n\t\t\tif len(value) > 10 {\n\t\t\t\tctx.gap = value[0:10]\n\t\t\t} else {\n\t\t\t\tctx.gap = value\n\t\t\t}\n\t\tcase valueNumber:\n\t\t\tvalue := spaceValue.number().int64\n\t\t\tif value > 10 {\n\t\t\t\tvalue = 10\n\t\t\t} else if value < 0 {\n\t\t\t\tvalue = 0\n\t\t\t}\n\t\t\tctx.gap = strings.Repeat(\" \", int(value))\n\t\t}\n\t}\n\tholder := call.runtime.newObject()\n\tholder.put(\"\", call.Argument(0), false)\n\tvalue, exists := builtinJSONStringifyWalk(ctx, \"\", holder)\n\tif !exists {\n\t\treturn Value{}\n\t}\n\tvalueJSON, err := json.Marshal(value)\n\tif err != nil {\n\t\tpanic(call.runtime.panicTypeError(\"JSON.stringify marshal: %s\", err))\n\t}\n\tif ctx.gap != \"\" {\n\t\tvalueJSON1 := bytes.Buffer{}\n\t\tif err = json.Indent(&valueJSON1, valueJSON, \"\", ctx.gap); err != nil {\n\t\t\tpanic(call.runtime.panicTypeError(\"JSON.stringify indent: %s\", err))\n\t\t}\n\t\tvalueJSON = valueJSON1.Bytes()\n\t}\n\treturn stringValue(string(valueJSON))\n}\n\nfunc builtinJSONStringifyWalk(ctx builtinJSONStringifyContext, key string, holder *object) (interface{}, bool) {\n\tvalue := holder.get(key)\n\n\tif value.IsObject() {\n\t\tobj := value.object()\n\t\tif toJSON := obj.get(\"toJSON\"); toJSON.IsFunction() {\n\t\t\tvalue = toJSON.call(ctx.call.runtime, value, key)\n\t\t} else if obj.objectClass.marshalJSON != nil {\n\t\t\t// If the object is a GoStruct or something that implements json.Marshaler\n\t\t\tmarshaler := obj.objectClass.marshalJSON(obj)\n\t\t\tif marshaler != nil {\n\t\t\t\treturn marshaler, true\n\t\t\t}\n\t\t}\n\t}\n\n\tif ctx.replacerFunction != nil {\n\t\tvalue = ctx.replacerFunction.call(ctx.call.runtime, objectValue(holder), key, value)\n\t}\n\n\tif value.kind == valueObject {\n\t\tswitch value.value.(*object).class {\n\t\tcase classBooleanName:\n\t\t\tvalue = value.object().value.(Value)\n\t\tcase classStringName:\n\t\t\tvalue = stringValue(value.string())\n\t\tcase classNumberName:\n\t\t\tvalue = value.numberValue()\n\t\t}\n\t}\n\n\tswitch value.kind {\n\tcase valueBoolean:\n\t\treturn value.bool(), true\n\tcase valueString:\n\t\treturn value.string(), true\n\tcase valueNumber:\n\t\tinteger := value.number()\n\t\tswitch integer.kind {\n\t\tcase numberInteger:\n\t\t\treturn integer.int64, true\n\t\tcase numberFloat:\n\t\t\treturn integer.float64, true\n\t\tdefault:\n\t\t\treturn nil, true\n\t\t}\n\tcase valueNull:\n\t\treturn nil, true\n\tcase valueObject:\n\t\tobjHolder := value.object()\n\t\tif value := value.object(); nil != value {\n\t\t\tfor _, obj := range ctx.stack {\n\t\t\t\tif objHolder == obj {\n\t\t\t\t\tpanic(ctx.call.runtime.panicTypeError(\"Converting circular structure to JSON\"))\n\t\t\t\t}\n\t\t\t}\n\t\t\tctx.stack = append(ctx.stack, value)\n\t\t\tdefer func() { ctx.stack = ctx.stack[:len(ctx.stack)-1] }()\n\t\t}\n\t\tif isArray(objHolder) {\n\t\t\tvar length uint32\n\t\t\tswitch value := objHolder.get(propertyLength).value.(type) {\n\t\t\tcase uint32:\n\t\t\t\tlength = value\n\t\t\tcase int:\n\t\t\t\tif value >= 0 {\n\t\t\t\t\tlength = uint32(value)\n\t\t\t\t}\n\t\t\tdefault:\n\t\t\t\tpanic(ctx.call.runtime.panicTypeError(fmt.Sprintf(\"JSON.stringify: invalid length: %v (%[1]T)\", value)))\n\t\t\t}\n\t\t\tarray := make([]interface{}, length)\n\t\t\tfor index := range array {\n\t\t\t\tname := arrayIndexToString(int64(index))\n\t\t\t\tvalue, _ := builtinJSONStringifyWalk(ctx, name, objHolder)\n\t\t\t\tarray[index] = value\n\t\t\t}\n\t\t\treturn array, true\n\t\t} else if objHolder.class != classFunctionName {\n\t\t\tobj := map[string]interface{}{}\n\t\t\tif ctx.propertyList != nil {\n\t\t\t\tfor _, name := range ctx.propertyList {\n\t\t\t\t\tvalue, exists := builtinJSONStringifyWalk(ctx, name, objHolder)\n\t\t\t\t\tif exists {\n\t\t\t\t\t\tobj[name] = value\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Go maps are without order, so this doesn't conform to the ECMA ordering\n\t\t\t\t// standard, but oh well...\n\t\t\t\tobjHolder.enumerate(false, func(name string) bool {\n\t\t\t\t\tvalue, exists := builtinJSONStringifyWalk(ctx, name, objHolder)\n\t\t\t\t\tif exists {\n\t\t\t\t\t\tobj[name] = value\n\t\t\t\t\t}\n\t\t\t\t\treturn true\n\t\t\t\t})\n\t\t\t}\n\t\t\treturn obj, true\n\t\t}\n\t}\n\treturn nil, false\n}\n"
  },
  {
    "path": "builtin_math.go",
    "content": "package otto\n\nimport (\n\t\"math\"\n\t\"math/rand\"\n)\n\n// Math\n\nfunc builtinMathAbs(call FunctionCall) Value {\n\tnumber := call.Argument(0).float64()\n\treturn float64Value(math.Abs(number))\n}\n\nfunc builtinMathAcos(call FunctionCall) Value {\n\tnumber := call.Argument(0).float64()\n\treturn float64Value(math.Acos(number))\n}\n\nfunc builtinMathAcosh(call FunctionCall) Value {\n\tnumber := call.Argument(0).float64()\n\treturn float64Value(math.Acosh(number))\n}\n\nfunc builtinMathAsin(call FunctionCall) Value {\n\tnumber := call.Argument(0).float64()\n\treturn float64Value(math.Asin(number))\n}\n\nfunc builtinMathAsinh(call FunctionCall) Value {\n\tnumber := call.Argument(0).float64()\n\treturn float64Value(math.Asinh(number))\n}\n\nfunc builtinMathAtan(call FunctionCall) Value {\n\tnumber := call.Argument(0).float64()\n\treturn float64Value(math.Atan(number))\n}\n\nfunc builtinMathAtan2(call FunctionCall) Value {\n\ty := call.Argument(0).float64()\n\tif math.IsNaN(y) {\n\t\treturn NaNValue()\n\t}\n\tx := call.Argument(1).float64()\n\tif math.IsNaN(x) {\n\t\treturn NaNValue()\n\t}\n\treturn float64Value(math.Atan2(y, x))\n}\n\nfunc builtinMathAtanh(call FunctionCall) Value {\n\tnumber := call.Argument(0).float64()\n\treturn float64Value(math.Atanh(number))\n}\n\nfunc builtinMathCbrt(call FunctionCall) Value {\n\tnumber := call.Argument(0).float64()\n\treturn float64Value(math.Cbrt(number))\n}\n\nfunc builtinMathCos(call FunctionCall) Value {\n\tnumber := call.Argument(0).float64()\n\treturn float64Value(math.Cos(number))\n}\n\nfunc builtinMathCeil(call FunctionCall) Value {\n\tnumber := call.Argument(0).float64()\n\treturn float64Value(math.Ceil(number))\n}\n\nfunc builtinMathCosh(call FunctionCall) Value {\n\tnumber := call.Argument(0).float64()\n\treturn float64Value(math.Cosh(number))\n}\n\nfunc builtinMathExp(call FunctionCall) Value {\n\tnumber := call.Argument(0).float64()\n\treturn float64Value(math.Exp(number))\n}\n\nfunc builtinMathExpm1(call FunctionCall) Value {\n\tnumber := call.Argument(0).float64()\n\treturn float64Value(math.Expm1(number))\n}\n\nfunc builtinMathFloor(call FunctionCall) Value {\n\tnumber := call.Argument(0).float64()\n\treturn float64Value(math.Floor(number))\n}\n\nfunc builtinMathLog(call FunctionCall) Value {\n\tnumber := call.Argument(0).float64()\n\treturn float64Value(math.Log(number))\n}\n\nfunc builtinMathLog10(call FunctionCall) Value {\n\tnumber := call.Argument(0).float64()\n\treturn float64Value(math.Log10(number))\n}\n\nfunc builtinMathLog1p(call FunctionCall) Value {\n\tnumber := call.Argument(0).float64()\n\treturn float64Value(math.Log1p(number))\n}\n\nfunc builtinMathLog2(call FunctionCall) Value {\n\tnumber := call.Argument(0).float64()\n\treturn float64Value(math.Log2(number))\n}\n\nfunc builtinMathMax(call FunctionCall) Value {\n\tswitch len(call.ArgumentList) {\n\tcase 0:\n\t\treturn negativeInfinityValue()\n\tcase 1:\n\t\treturn float64Value(call.ArgumentList[0].float64())\n\t}\n\tresult := call.ArgumentList[0].float64()\n\tif math.IsNaN(result) {\n\t\treturn NaNValue()\n\t}\n\tfor _, value := range call.ArgumentList[1:] {\n\t\tvalue := value.float64()\n\t\tif math.IsNaN(value) {\n\t\t\treturn NaNValue()\n\t\t}\n\t\tresult = math.Max(result, value)\n\t}\n\treturn float64Value(result)\n}\n\nfunc builtinMathMin(call FunctionCall) Value {\n\tswitch len(call.ArgumentList) {\n\tcase 0:\n\t\treturn positiveInfinityValue()\n\tcase 1:\n\t\treturn float64Value(call.ArgumentList[0].float64())\n\t}\n\tresult := call.ArgumentList[0].float64()\n\tif math.IsNaN(result) {\n\t\treturn NaNValue()\n\t}\n\tfor _, value := range call.ArgumentList[1:] {\n\t\tvalue := value.float64()\n\t\tif math.IsNaN(value) {\n\t\t\treturn NaNValue()\n\t\t}\n\t\tresult = math.Min(result, value)\n\t}\n\treturn float64Value(result)\n}\n\nfunc builtinMathPow(call FunctionCall) Value {\n\t// TODO Make sure this works according to the specification (15.8.2.13)\n\tx := call.Argument(0).float64()\n\ty := call.Argument(1).float64()\n\tif math.Abs(x) == 1 && math.IsInf(y, 0) {\n\t\treturn NaNValue()\n\t}\n\treturn float64Value(math.Pow(x, y))\n}\n\nfunc builtinMathRandom(call FunctionCall) Value {\n\tvar v float64\n\tif call.runtime.random != nil {\n\t\tv = call.runtime.random()\n\t} else {\n\t\tv = rand.Float64() //nolint:gosec\n\t}\n\treturn float64Value(v)\n}\n\nfunc builtinMathRound(call FunctionCall) Value {\n\tnumber := call.Argument(0).float64()\n\tvalue := math.Floor(number + 0.5)\n\tif value == 0 {\n\t\tvalue = math.Copysign(0, number)\n\t}\n\treturn float64Value(value)\n}\n\nfunc builtinMathSin(call FunctionCall) Value {\n\tnumber := call.Argument(0).float64()\n\treturn float64Value(math.Sin(number))\n}\n\nfunc builtinMathSinh(call FunctionCall) Value {\n\tnumber := call.Argument(0).float64()\n\treturn float64Value(math.Sinh(number))\n}\n\nfunc builtinMathSqrt(call FunctionCall) Value {\n\tnumber := call.Argument(0).float64()\n\treturn float64Value(math.Sqrt(number))\n}\n\nfunc builtinMathTan(call FunctionCall) Value {\n\tnumber := call.Argument(0).float64()\n\treturn float64Value(math.Tan(number))\n}\n\nfunc builtinMathTanh(call FunctionCall) Value {\n\tnumber := call.Argument(0).float64()\n\treturn float64Value(math.Tanh(number))\n}\n\nfunc builtinMathTrunc(call FunctionCall) Value {\n\tnumber := call.Argument(0).float64()\n\treturn float64Value(math.Trunc(number))\n}\n"
  },
  {
    "path": "builtin_number.go",
    "content": "package otto\n\nimport (\n\t\"math\"\n\t\"strconv\"\n\n\t\"golang.org/x/text/language\"\n\t\"golang.org/x/text/message\"\n\t\"golang.org/x/text/number\"\n)\n\n// Number\n\nfunc numberValueFromNumberArgumentList(argumentList []Value) Value {\n\tif len(argumentList) > 0 {\n\t\treturn argumentList[0].numberValue()\n\t}\n\treturn intValue(0)\n}\n\nfunc builtinNumber(call FunctionCall) Value {\n\treturn numberValueFromNumberArgumentList(call.ArgumentList)\n}\n\nfunc builtinNewNumber(obj *object, argumentList []Value) Value {\n\treturn objectValue(obj.runtime.newNumber(numberValueFromNumberArgumentList(argumentList)))\n}\n\nfunc builtinNumberToString(call FunctionCall) Value {\n\t// Will throw a TypeError if ThisObject is not a Number\n\tvalue := call.thisClassObject(classNumberName).primitiveValue()\n\tradix := 10\n\tradixArgument := call.Argument(0)\n\tif radixArgument.IsDefined() {\n\t\tinteger := toIntegerFloat(radixArgument)\n\t\tif integer < 2 || integer > 36 {\n\t\t\tpanic(call.runtime.panicRangeError(\"toString() radix must be between 2 and 36\"))\n\t\t}\n\t\tradix = int(integer)\n\t}\n\tif radix == 10 {\n\t\treturn stringValue(value.string())\n\t}\n\treturn stringValue(numberToStringRadix(value, radix))\n}\n\nfunc builtinNumberValueOf(call FunctionCall) Value {\n\treturn call.thisClassObject(classNumberName).primitiveValue()\n}\n\nfunc builtinNumberToFixed(call FunctionCall) Value {\n\tprecision := toIntegerFloat(call.Argument(0))\n\tif 20 < precision || 0 > precision {\n\t\tpanic(call.runtime.panicRangeError(\"toFixed() precision must be between 0 and 20\"))\n\t}\n\tif call.This.IsNaN() {\n\t\treturn stringValue(\"NaN\")\n\t}\n\tif value := call.This.float64(); math.Abs(value) >= 1e21 {\n\t\treturn stringValue(floatToString(value, 64))\n\t}\n\treturn stringValue(strconv.FormatFloat(call.This.float64(), 'f', int(precision), 64))\n}\n\nfunc builtinNumberToExponential(call FunctionCall) Value {\n\tif call.This.IsNaN() {\n\t\treturn stringValue(\"NaN\")\n\t}\n\tprecision := float64(-1)\n\tif value := call.Argument(0); value.IsDefined() {\n\t\tprecision = toIntegerFloat(value)\n\t\tif 0 > precision {\n\t\t\tpanic(call.runtime.panicRangeError(\"toString() radix must be between 2 and 36\"))\n\t\t}\n\t}\n\treturn stringValue(strconv.FormatFloat(call.This.float64(), 'e', int(precision), 64))\n}\n\nfunc builtinNumberToPrecision(call FunctionCall) Value {\n\tif call.This.IsNaN() {\n\t\treturn stringValue(\"NaN\")\n\t}\n\tvalue := call.Argument(0)\n\tif value.IsUndefined() {\n\t\treturn stringValue(call.This.string())\n\t}\n\tprecision := toIntegerFloat(value)\n\tif 1 > precision {\n\t\tpanic(call.runtime.panicRangeError(\"toPrecision() precision must be greater than 1\"))\n\t}\n\treturn stringValue(strconv.FormatFloat(call.This.float64(), 'g', int(precision), 64))\n}\n\nfunc builtinNumberIsNaN(call FunctionCall) Value {\n\tif len(call.ArgumentList) < 1 {\n\t\treturn boolValue(false)\n\t}\n\treturn boolValue(call.Argument(0).IsNaN())\n}\n\nfunc builtinNumberToLocaleString(call FunctionCall) Value {\n\tvalue := call.thisClassObject(classNumberName).primitiveValue()\n\tlocale := call.Argument(0)\n\tlang := defaultLanguage\n\tif locale.IsDefined() {\n\t\tlang = language.MustParse(locale.string())\n\t}\n\n\tp := message.NewPrinter(lang)\n\treturn stringValue(p.Sprintf(\"%v\", number.Decimal(value.value)))\n}\n"
  },
  {
    "path": "builtin_object.go",
    "content": "package otto\n\nimport (\n\t\"fmt\"\n\t\"strconv\"\n)\n\n// Object\n\nfunc builtinObject(call FunctionCall) Value {\n\tvalue := call.Argument(0)\n\tswitch value.kind {\n\tcase valueUndefined, valueNull:\n\t\treturn objectValue(call.runtime.newObject())\n\t}\n\n\treturn objectValue(call.runtime.toObject(value))\n}\n\nfunc builtinNewObject(obj *object, argumentList []Value) Value {\n\tvalue := valueOfArrayIndex(argumentList, 0)\n\tswitch value.kind {\n\tcase valueNull, valueUndefined:\n\tcase valueNumber, valueString, valueBoolean:\n\t\treturn objectValue(obj.runtime.toObject(value))\n\tcase valueObject:\n\t\treturn value\n\tdefault:\n\t}\n\treturn objectValue(obj.runtime.newObject())\n}\n\nfunc builtinObjectValueOf(call FunctionCall) Value {\n\treturn objectValue(call.thisObject())\n}\n\nfunc builtinObjectHasOwnProperty(call FunctionCall) Value {\n\tpropertyName := call.Argument(0).string()\n\tthisObject := call.thisObject()\n\treturn boolValue(thisObject.hasOwnProperty(propertyName))\n}\n\nfunc builtinObjectIsPrototypeOf(call FunctionCall) Value {\n\tvalue := call.Argument(0)\n\tif !value.IsObject() {\n\t\treturn falseValue\n\t}\n\tprototype := call.toObject(value).prototype\n\tthisObject := call.thisObject()\n\tfor prototype != nil {\n\t\tif thisObject == prototype {\n\t\t\treturn trueValue\n\t\t}\n\t\tprototype = prototype.prototype\n\t}\n\treturn falseValue\n}\n\nfunc builtinObjectPropertyIsEnumerable(call FunctionCall) Value {\n\tpropertyName := call.Argument(0).string()\n\tthisObject := call.thisObject()\n\tprop := thisObject.getOwnProperty(propertyName)\n\tif prop != nil && prop.enumerable() {\n\t\treturn trueValue\n\t}\n\treturn falseValue\n}\n\nfunc builtinObjectToString(call FunctionCall) Value {\n\tvar result string\n\tswitch {\n\tcase call.This.IsUndefined():\n\t\tresult = \"[object Undefined]\"\n\tcase call.This.IsNull():\n\t\tresult = \"[object Null]\"\n\tdefault:\n\t\tresult = fmt.Sprintf(\"[object %s]\", call.thisObject().class)\n\t}\n\treturn stringValue(result)\n}\n\nfunc builtinObjectToLocaleString(call FunctionCall) Value {\n\ttoString := call.thisObject().get(\"toString\")\n\tif !toString.isCallable() {\n\t\tpanic(call.runtime.panicTypeError(\"Object.toLocaleString %q is not callable\", toString))\n\t}\n\treturn toString.call(call.runtime, call.This)\n}\n\nfunc builtinObjectGetPrototypeOf(call FunctionCall) Value {\n\tval := call.Argument(0)\n\tobj := val.object()\n\tif obj == nil {\n\t\tpanic(call.runtime.panicTypeError(\"Object.GetPrototypeOf is nil\"))\n\t}\n\n\tif obj.prototype == nil {\n\t\treturn nullValue\n\t}\n\n\treturn objectValue(obj.prototype)\n}\n\nfunc builtinObjectGetOwnPropertyDescriptor(call FunctionCall) Value {\n\tval := call.Argument(0)\n\tobj := val.object()\n\tif obj == nil {\n\t\tpanic(call.runtime.panicTypeError(\"Object.GetOwnPropertyDescriptor is nil\"))\n\t}\n\n\tname := call.Argument(1).string()\n\tdescriptor := obj.getOwnProperty(name)\n\tif descriptor == nil {\n\t\treturn Value{}\n\t}\n\treturn objectValue(call.runtime.fromPropertyDescriptor(*descriptor))\n}\n\nfunc builtinObjectDefineProperty(call FunctionCall) Value {\n\tval := call.Argument(0)\n\tobj := val.object()\n\tif obj == nil {\n\t\tpanic(call.runtime.panicTypeError(\"Object.DefineProperty is nil\"))\n\t}\n\tname := call.Argument(1).string()\n\tdescriptor := toPropertyDescriptor(call.runtime, call.Argument(2))\n\tobj.defineOwnProperty(name, descriptor, true)\n\treturn val\n}\n\nfunc builtinObjectDefineProperties(call FunctionCall) Value {\n\tval := call.Argument(0)\n\tobj := val.object()\n\tif obj == nil {\n\t\tpanic(call.runtime.panicTypeError(\"Object.DefineProperties is nil\"))\n\t}\n\n\tproperties := call.runtime.toObject(call.Argument(1))\n\tproperties.enumerate(false, func(name string) bool {\n\t\tdescriptor := toPropertyDescriptor(call.runtime, properties.get(name))\n\t\tobj.defineOwnProperty(name, descriptor, true)\n\t\treturn true\n\t})\n\n\treturn val\n}\n\nfunc builtinObjectCreate(call FunctionCall) Value {\n\tprototypeValue := call.Argument(0)\n\tif !prototypeValue.IsNull() && !prototypeValue.IsObject() {\n\t\tpanic(call.runtime.panicTypeError(\"Object.Create is nil\"))\n\t}\n\n\tobj := call.runtime.newObject()\n\tobj.prototype = prototypeValue.object()\n\n\tpropertiesValue := call.Argument(1)\n\tif propertiesValue.IsDefined() {\n\t\tproperties := call.runtime.toObject(propertiesValue)\n\t\tproperties.enumerate(false, func(name string) bool {\n\t\t\tdescriptor := toPropertyDescriptor(call.runtime, properties.get(name))\n\t\t\tobj.defineOwnProperty(name, descriptor, true)\n\t\t\treturn true\n\t\t})\n\t}\n\n\treturn objectValue(obj)\n}\n\nfunc builtinObjectIsExtensible(call FunctionCall) Value {\n\tval := call.Argument(0)\n\tif obj := val.object(); obj != nil {\n\t\treturn boolValue(obj.extensible)\n\t}\n\tpanic(call.runtime.panicTypeError(\"Object.IsExtensible is nil\"))\n}\n\nfunc builtinObjectPreventExtensions(call FunctionCall) Value {\n\tval := call.Argument(0)\n\tif obj := val.object(); obj != nil {\n\t\tobj.extensible = false\n\t\treturn val\n\t}\n\tpanic(call.runtime.panicTypeError(\"Object.PreventExtensions is nil\"))\n}\n\nfunc builtinObjectAssign(call FunctionCall) Value {\n\tif len(call.ArgumentList) < 1 {\n\t\tpanic(call.runtime.panicTypeError(\"Object.assign TypeError: Cannot convert undefined or null to object\"))\n\t}\n\n\ttarget := call.ArgumentList[0]\n\ttargetObj := target.object()\n\tif !target.IsObject() && target.IsNull() && target.IsUndefined() {\n\t\tpanic(call.runtime.panicTypeError(\"Object.assign TypeError: Cannot convert undefined or null to object\"))\n\t}\n\n\tfor _, source := range call.ArgumentList[1:] {\n\t\tif source.IsString() {\n\t\t\tsourceStr := source.string()\n\t\t\tfor i, r := range sourceStr {\n\t\t\t\ttargetObj.put(strconv.Itoa(i), stringValue(string(r)), true)\n\t\t\t}\n\t\t} else if source.IsObject() {\n\t\t\tsourceObj := source.object()\n\t\t\tsourceObj.enumerate(false, func(name string) bool {\n\t\t\t\tdescriptor := sourceObj.getOwnProperty(name)\n\t\t\t\tok := targetObj.defineOwnProperty(name, *descriptor, true)\n\t\t\t\tif !ok {\n\t\t\t\t\tpanic(call.runtime.panicTypeError(\"Object.assign TypeError: Cannot convert undefined or null to object\"))\n\t\t\t\t}\n\t\t\t\treturn true\n\t\t\t})\n\t\t}\n\t}\n\n\treturn objectValue(targetObj)\n}\n\nfunc builtinObjectIsSealed(call FunctionCall) Value {\n\tval := call.Argument(0)\n\tif obj := val.object(); obj != nil {\n\t\tif obj.extensible {\n\t\t\treturn boolValue(false)\n\t\t}\n\t\tresult := true\n\t\tobj.enumerate(true, func(name string) bool {\n\t\t\tprop := obj.getProperty(name)\n\t\t\tif prop.configurable() {\n\t\t\t\tresult = false\n\t\t\t}\n\t\t\treturn true\n\t\t})\n\t\treturn boolValue(result)\n\t}\n\tpanic(call.runtime.panicTypeError(\"Object.IsSealed is nil\"))\n}\n\nfunc builtinObjectSeal(call FunctionCall) Value {\n\tval := call.Argument(0)\n\tif obj := val.object(); obj != nil {\n\t\tobj.enumerate(true, func(name string) bool {\n\t\t\tif prop := obj.getOwnProperty(name); nil != prop && prop.configurable() {\n\t\t\t\tprop.configureOff()\n\t\t\t\tobj.defineOwnProperty(name, *prop, true)\n\t\t\t}\n\t\t\treturn true\n\t\t})\n\t\tobj.extensible = false\n\t\treturn val\n\t}\n\tpanic(call.runtime.panicTypeError(\"Object.Seal is nil\"))\n}\n\nfunc builtinObjectIsFrozen(call FunctionCall) Value {\n\tval := call.Argument(0)\n\tif obj := val.object(); obj != nil {\n\t\tif obj.extensible {\n\t\t\treturn boolValue(false)\n\t\t}\n\t\tresult := true\n\t\tobj.enumerate(true, func(name string) bool {\n\t\t\tprop := obj.getProperty(name)\n\t\t\tif prop.configurable() || prop.writable() {\n\t\t\t\tresult = false\n\t\t\t}\n\t\t\treturn true\n\t\t})\n\t\treturn boolValue(result)\n\t}\n\tpanic(call.runtime.panicTypeError(\"Object.IsFrozen is nil\"))\n}\n\nfunc builtinObjectFreeze(call FunctionCall) Value {\n\tval := call.Argument(0)\n\tif obj := val.object(); obj != nil {\n\t\tobj.enumerate(true, func(name string) bool {\n\t\t\tif prop, update := obj.getOwnProperty(name), false; nil != prop {\n\t\t\t\tif prop.isDataDescriptor() && prop.writable() {\n\t\t\t\t\tprop.writeOff()\n\t\t\t\t\tupdate = true\n\t\t\t\t}\n\t\t\t\tif prop.configurable() {\n\t\t\t\t\tprop.configureOff()\n\t\t\t\t\tupdate = true\n\t\t\t\t}\n\t\t\t\tif update {\n\t\t\t\t\tobj.defineOwnProperty(name, *prop, true)\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true\n\t\t})\n\t\tobj.extensible = false\n\t\treturn val\n\t}\n\tpanic(call.runtime.panicTypeError(\"Object.Freeze is nil\"))\n}\n\nfunc builtinObjectKeys(call FunctionCall) Value {\n\tif obj, keys := call.Argument(0).object(), []Value(nil); nil != obj {\n\t\tobj.enumerate(false, func(name string) bool {\n\t\t\tkeys = append(keys, stringValue(name))\n\t\t\treturn true\n\t\t})\n\t\treturn objectValue(call.runtime.newArrayOf(keys))\n\t}\n\tpanic(call.runtime.panicTypeError(\"Object.Keys is nil\"))\n}\n\nfunc builtinObjectValues(call FunctionCall) Value {\n\tif obj, values := call.Argument(0).object(), []Value(nil); nil != obj {\n\t\tobj.enumerate(false, func(name string) bool {\n\t\t\tvalues = append(values, obj.get(name))\n\t\t\treturn true\n\t\t})\n\t\treturn objectValue(call.runtime.newArrayOf(values))\n\t}\n\tpanic(call.runtime.panicTypeError(\"Object.Values is nil\"))\n}\n\nfunc builtinObjectGetOwnPropertyNames(call FunctionCall) Value {\n\tif obj, propertyNames := call.Argument(0).object(), []Value(nil); nil != obj {\n\t\tobj.enumerate(true, func(name string) bool {\n\t\t\tif obj.hasOwnProperty(name) {\n\t\t\t\tpropertyNames = append(propertyNames, stringValue(name))\n\t\t\t}\n\t\t\treturn true\n\t\t})\n\t\treturn objectValue(call.runtime.newArrayOf(propertyNames))\n\t}\n\n\t// Default to empty array for non object types.\n\treturn objectValue(call.runtime.newArray(0))\n}\n"
  },
  {
    "path": "builtin_regexp.go",
    "content": "package otto\n\nimport (\n\t\"fmt\"\n)\n\n// RegExp\n\nfunc builtinRegExp(call FunctionCall) Value {\n\tpattern := call.Argument(0)\n\tflags := call.Argument(1)\n\tif obj := pattern.object(); obj != nil {\n\t\tif obj.class == classRegExpName && flags.IsUndefined() {\n\t\t\treturn pattern\n\t\t}\n\t}\n\treturn objectValue(call.runtime.newRegExp(pattern, flags))\n}\n\nfunc builtinNewRegExp(obj *object, argumentList []Value) Value {\n\treturn objectValue(obj.runtime.newRegExp(\n\t\tvalueOfArrayIndex(argumentList, 0),\n\t\tvalueOfArrayIndex(argumentList, 1),\n\t))\n}\n\nfunc builtinRegExpToString(call FunctionCall) Value {\n\tthisObject := call.thisObject()\n\tsource := thisObject.get(\"source\").string()\n\tflags := []byte{}\n\tif thisObject.get(\"global\").bool() {\n\t\tflags = append(flags, 'g')\n\t}\n\tif thisObject.get(\"ignoreCase\").bool() {\n\t\tflags = append(flags, 'i')\n\t}\n\tif thisObject.get(\"multiline\").bool() {\n\t\tflags = append(flags, 'm')\n\t}\n\treturn stringValue(fmt.Sprintf(\"/%s/%s\", source, flags))\n}\n\nfunc builtinRegExpExec(call FunctionCall) Value {\n\tthisObject := call.thisObject()\n\ttarget := call.Argument(0).string()\n\tmatch, result := execRegExp(thisObject, target)\n\tif !match {\n\t\treturn nullValue\n\t}\n\treturn objectValue(execResultToArray(call.runtime, target, result))\n}\n\nfunc builtinRegExpTest(call FunctionCall) Value {\n\tthisObject := call.thisObject()\n\ttarget := call.Argument(0).string()\n\tmatch, result := execRegExp(thisObject, target)\n\n\tif !match {\n\t\treturn boolValue(match)\n\t}\n\n\t// Match extract and assign input, $_ and $1 -> $9 on global RegExp.\n\tinput := stringValue(target)\n\tcall.runtime.global.RegExp.defineProperty(\"$_\", input, 0o100, false)\n\tcall.runtime.global.RegExp.defineProperty(\"input\", input, 0o100, false)\n\n\tvar start int\n\tn := 1\n\tre := call.runtime.global.RegExp\n\tempty := stringValue(\"\")\n\tfor i, v := range result[2:] {\n\t\tif i%2 == 0 {\n\t\t\tstart = v\n\t\t} else {\n\t\t\tif v == -1 {\n\t\t\t\t// No match for this part.\n\t\t\t\tre.defineProperty(fmt.Sprintf(\"$%d\", n), empty, 0o100, false)\n\t\t\t} else {\n\t\t\t\tre.defineProperty(fmt.Sprintf(\"$%d\", n), stringValue(target[start:v]), 0o100, false)\n\t\t\t}\n\t\t\tn++\n\t\t\tif n == 10 {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\n\tif n <= 9 {\n\t\t// Erase remaining.\n\t\tfor i := n; i <= 9; i++ {\n\t\t\tre.defineProperty(fmt.Sprintf(\"$%d\", i), empty, 0o100, false)\n\t\t}\n\t}\n\n\treturn boolValue(match)\n}\n\nfunc builtinRegExpCompile(call FunctionCall) Value {\n\t// This (useless) function is deprecated, but is here to provide some\n\t// semblance of compatibility.\n\t// Caveat emptor: it may not be around for long.\n\treturn Value{}\n}\n"
  },
  {
    "path": "builtin_string.go",
    "content": "package otto\n\nimport (\n\t\"bytes\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\t\"unicode/utf16\"\n\t\"unicode/utf8\"\n)\n\n// String\n\nfunc stringValueFromStringArgumentList(argumentList []Value) Value {\n\tif len(argumentList) > 0 {\n\t\treturn stringValue(argumentList[0].string())\n\t}\n\treturn stringValue(\"\")\n}\n\nfunc builtinString(call FunctionCall) Value {\n\treturn stringValueFromStringArgumentList(call.ArgumentList)\n}\n\nfunc builtinNewString(obj *object, argumentList []Value) Value {\n\treturn objectValue(obj.runtime.newString(stringValueFromStringArgumentList(argumentList)))\n}\n\nfunc builtinStringToString(call FunctionCall) Value {\n\treturn call.thisClassObject(classStringName).primitiveValue()\n}\n\nfunc builtinStringValueOf(call FunctionCall) Value {\n\treturn call.thisClassObject(classStringName).primitiveValue()\n}\n\nfunc builtinStringFromCharCode(call FunctionCall) Value {\n\tchrList := make([]uint16, len(call.ArgumentList))\n\tfor index, value := range call.ArgumentList {\n\t\tchrList[index] = toUint16(value)\n\t}\n\treturn string16Value(chrList)\n}\n\nfunc builtinStringCharAt(call FunctionCall) Value {\n\tcheckObjectCoercible(call.runtime, call.This)\n\tidx := int(call.Argument(0).number().int64)\n\tchr := stringAt(call.This.object().stringValue(), idx)\n\tif chr == utf8.RuneError {\n\t\treturn stringValue(\"\")\n\t}\n\treturn stringValue(string(chr))\n}\n\nfunc builtinStringCharCodeAt(call FunctionCall) Value {\n\tcheckObjectCoercible(call.runtime, call.This)\n\tidx := int(call.Argument(0).number().int64)\n\tchr := stringAt(call.This.object().stringValue(), idx)\n\tif chr == utf8.RuneError {\n\t\treturn NaNValue()\n\t}\n\treturn uint16Value(uint16(chr))\n}\n\nfunc builtinStringConcat(call FunctionCall) Value {\n\tcheckObjectCoercible(call.runtime, call.This)\n\tvar value bytes.Buffer\n\tvalue.WriteString(call.This.string())\n\tfor _, item := range call.ArgumentList {\n\t\tvalue.WriteString(item.string())\n\t}\n\treturn stringValue(value.String())\n}\n\nfunc lastIndexRune(s, substr string) int {\n\tif i := strings.LastIndex(s, substr); i >= 0 {\n\t\treturn utf16Length(s[:i])\n\t}\n\treturn -1\n}\n\nfunc indexRune(s, substr string) int {\n\tif i := strings.Index(s, substr); i >= 0 {\n\t\treturn utf16Length(s[:i])\n\t}\n\treturn -1\n}\n\nfunc utf16Length(s string) int {\n\treturn len(utf16.Encode([]rune(s)))\n}\n\nfunc builtinStringIndexOf(call FunctionCall) Value {\n\tcheckObjectCoercible(call.runtime, call.This)\n\tvalue := call.This.string()\n\ttarget := call.Argument(0).string()\n\tif 2 > len(call.ArgumentList) {\n\t\treturn intValue(indexRune(value, target))\n\t}\n\tstart := toIntegerFloat(call.Argument(1))\n\tif 0 > start {\n\t\tstart = 0\n\t} else if start >= float64(len(value)) {\n\t\tif target == \"\" {\n\t\t\treturn intValue(len(value))\n\t\t}\n\t\treturn intValue(-1)\n\t}\n\tindex := indexRune(value[int(start):], target)\n\tif index >= 0 {\n\t\tindex += int(start)\n\t}\n\treturn intValue(index)\n}\n\nfunc builtinStringLastIndexOf(call FunctionCall) Value {\n\tcheckObjectCoercible(call.runtime, call.This)\n\tvalue := call.This.string()\n\ttarget := call.Argument(0).string()\n\tif 2 > len(call.ArgumentList) || call.ArgumentList[1].IsUndefined() {\n\t\treturn intValue(lastIndexRune(value, target))\n\t}\n\tlength := len(value)\n\tif length == 0 {\n\t\treturn intValue(lastIndexRune(value, target))\n\t}\n\tstart := call.ArgumentList[1].number()\n\tif start.kind == numberInfinity { // FIXME\n\t\t// startNumber is infinity, so start is the end of string (start = length)\n\t\treturn intValue(lastIndexRune(value, target))\n\t}\n\tif 0 > start.int64 {\n\t\tstart.int64 = 0\n\t}\n\tend := int(start.int64) + len(target)\n\tif end > length {\n\t\tend = length\n\t}\n\treturn intValue(lastIndexRune(value[:end], target))\n}\n\nfunc builtinStringMatch(call FunctionCall) Value {\n\tcheckObjectCoercible(call.runtime, call.This)\n\ttarget := call.This.string()\n\tmatcherValue := call.Argument(0)\n\tmatcher := matcherValue.object()\n\tif !matcherValue.IsObject() || matcher.class != classRegExpName {\n\t\tmatcher = call.runtime.newRegExp(matcherValue, Value{})\n\t}\n\tglobal := matcher.get(\"global\").bool()\n\tif !global {\n\t\tmatch, result := execRegExp(matcher, target)\n\t\tif !match {\n\t\t\treturn nullValue\n\t\t}\n\t\treturn objectValue(execResultToArray(call.runtime, target, result))\n\t}\n\n\tresult := matcher.regExpValue().regularExpression.FindAllStringIndex(target, -1)\n\tif result == nil {\n\t\tmatcher.put(\"lastIndex\", intValue(0), true)\n\t\treturn Value{} // !match\n\t}\n\tmatchCount := len(result)\n\tvalueArray := make([]Value, matchCount)\n\tfor index := range matchCount {\n\t\tvalueArray[index] = stringValue(target[result[index][0]:result[index][1]])\n\t}\n\tmatcher.put(\"lastIndex\", intValue(result[matchCount-1][1]), true)\n\treturn objectValue(call.runtime.newArrayOf(valueArray))\n}\n\nvar builtinStringReplaceRegexp = regexp.MustCompile(\"\\\\$(?:[\\\\$\\\\&\\\\'\\\\`1-9]|0[1-9]|[1-9][0-9])\")\n\nfunc builtinStringFindAndReplaceString(input []byte, lastIndex int, match []int, target []byte, replaceValue []byte) []byte {\n\tmatchCount := len(match) / 2\n\toutput := input\n\tif match[0] != lastIndex {\n\t\toutput = append(output, target[lastIndex:match[0]]...)\n\t}\n\treplacement := builtinStringReplaceRegexp.ReplaceAllFunc(replaceValue, func(part []byte) []byte {\n\t\t// TODO Check if match[0] or match[1] can be -1 in this scenario\n\t\tswitch part[1] {\n\t\tcase '$':\n\t\t\treturn []byte{'$'}\n\t\tcase '&':\n\t\t\treturn target[match[0]:match[1]]\n\t\tcase '`':\n\t\t\treturn target[:match[0]]\n\t\tcase '\\'':\n\t\t\treturn target[match[1]:]\n\t\t}\n\t\tmatchNumberParse, err := strconv.ParseInt(string(part[1:]), 10, 64)\n\t\tif err != nil {\n\t\t\treturn nil\n\t\t}\n\t\tmatchNumber := int(matchNumberParse)\n\t\tif matchNumber >= matchCount {\n\t\t\treturn nil\n\t\t}\n\t\toffset := 2 * matchNumber\n\t\tif match[offset] != -1 {\n\t\t\treturn target[match[offset]:match[offset+1]]\n\t\t}\n\t\treturn nil // The empty string\n\t})\n\n\treturn append(output, replacement...)\n}\n\nfunc builtinStringReplace(call FunctionCall) Value {\n\tcheckObjectCoercible(call.runtime, call.This)\n\ttarget := []byte(call.This.string())\n\tsearchValue := call.Argument(0)\n\tsearchObject := searchValue.object()\n\n\t// TODO If a capture is -1?\n\tvar search *regexp.Regexp\n\tglobal := false\n\tfind := 1\n\tif searchValue.IsObject() && searchObject.class == classRegExpName {\n\t\tregExp := searchObject.regExpValue()\n\t\tsearch = regExp.regularExpression\n\t\tif regExp.global {\n\t\t\tfind = -1\n\t\t\tglobal = true\n\t\t}\n\t} else {\n\t\tsearch = regexp.MustCompile(regexp.QuoteMeta(searchValue.string()))\n\t}\n\n\tfound := search.FindAllSubmatchIndex(target, find)\n\tif found == nil {\n\t\treturn stringValue(string(target)) // !match\n\t}\n\n\tlastIndex := 0\n\tresult := []byte{}\n\treplaceValue := call.Argument(1)\n\tif replaceValue.isCallable() {\n\t\ttarget := string(target)\n\t\treplace := replaceValue.object()\n\t\tfor _, match := range found {\n\t\t\tif match[0] != lastIndex {\n\t\t\t\tresult = append(result, target[lastIndex:match[0]]...)\n\t\t\t}\n\t\t\tmatchCount := len(match) / 2\n\t\t\targumentList := make([]Value, matchCount+2)\n\t\t\tfor index := range matchCount {\n\t\t\t\toffset := 2 * index\n\t\t\t\tif match[offset] != -1 {\n\t\t\t\t\targumentList[index] = stringValue(target[match[offset]:match[offset+1]])\n\t\t\t\t} else {\n\t\t\t\t\targumentList[index] = Value{}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Replace expects rune offsets not byte offsets.\n\t\t\tstartIndex := utf8.RuneCountInString(target[0:match[0]])\n\t\t\targumentList[matchCount+0] = intValue(startIndex)\n\t\t\targumentList[matchCount+1] = stringValue(target)\n\t\t\treplacement := replace.call(Value{}, argumentList, false, nativeFrame).string()\n\t\t\tresult = append(result, []byte(replacement)...)\n\t\t\tlastIndex = match[1]\n\t\t}\n\t} else {\n\t\treplace := []byte(replaceValue.string())\n\t\tfor _, match := range found {\n\t\t\tresult = builtinStringFindAndReplaceString(result, lastIndex, match, target, replace)\n\t\t\tlastIndex = match[1]\n\t\t}\n\t}\n\n\tif lastIndex != len(target) {\n\t\tresult = append(result, target[lastIndex:]...)\n\t}\n\n\tif global && searchObject != nil {\n\t\tsearchObject.put(\"lastIndex\", intValue(lastIndex), true)\n\t}\n\n\treturn stringValue(string(result))\n}\n\nfunc builtinStringSearch(call FunctionCall) Value {\n\tcheckObjectCoercible(call.runtime, call.This)\n\ttarget := call.This.string()\n\tsearchValue := call.Argument(0)\n\tsearch := searchValue.object()\n\tif !searchValue.IsObject() || search.class != classRegExpName {\n\t\tsearch = call.runtime.newRegExp(searchValue, Value{})\n\t}\n\tresult := search.regExpValue().regularExpression.FindStringIndex(target)\n\tif result == nil {\n\t\treturn intValue(-1)\n\t}\n\treturn intValue(result[0])\n}\n\nfunc builtinStringSplit(call FunctionCall) Value {\n\tcheckObjectCoercible(call.runtime, call.This)\n\ttarget := call.This.string()\n\n\tseparatorValue := call.Argument(0)\n\tlimitValue := call.Argument(1)\n\tlimit := -1\n\tif limitValue.IsDefined() {\n\t\tlimit = int(toUint32(limitValue))\n\t}\n\n\tif limit == 0 {\n\t\treturn objectValue(call.runtime.newArray(0))\n\t}\n\n\tif separatorValue.IsUndefined() {\n\t\treturn objectValue(call.runtime.newArrayOf([]Value{stringValue(target)}))\n\t}\n\n\tif separatorValue.isRegExp() {\n\t\ttargetLength := len(target)\n\t\tsearch := separatorValue.object().regExpValue().regularExpression\n\t\tvalueArray := []Value{}\n\t\tresult := search.FindAllStringSubmatchIndex(target, -1)\n\t\tlastIndex := 0\n\t\tfound := 0\n\n\t\tfor _, match := range result {\n\t\t\tif match[0] == match[1] {\n\t\t\t\t// FIXME Ugh, this is a hack\n\t\t\t\tif match[0] == 0 || match[0] == targetLength {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif lastIndex != match[0] {\n\t\t\t\tvalueArray = append(valueArray, stringValue(target[lastIndex:match[0]]))\n\t\t\t\tfound++\n\t\t\t} else if lastIndex == match[0] {\n\t\t\t\tif lastIndex != -1 {\n\t\t\t\t\tvalueArray = append(valueArray, stringValue(\"\"))\n\t\t\t\t\tfound++\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tlastIndex = match[1]\n\t\t\tif found == limit {\n\t\t\t\tgoto RETURN\n\t\t\t}\n\n\t\t\tcaptureCount := len(match) / 2\n\t\t\tfor index := 1; index < captureCount; index++ {\n\t\t\t\toffset := index * 2\n\t\t\t\tvalue := Value{}\n\t\t\t\tif match[offset] != -1 {\n\t\t\t\t\tvalue = stringValue(target[match[offset]:match[offset+1]])\n\t\t\t\t}\n\t\t\t\tvalueArray = append(valueArray, value)\n\t\t\t\tfound++\n\t\t\t\tif found == limit {\n\t\t\t\t\tgoto RETURN\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif found != limit {\n\t\t\tif lastIndex != targetLength {\n\t\t\t\tvalueArray = append(valueArray, stringValue(target[lastIndex:targetLength]))\n\t\t\t} else {\n\t\t\t\tvalueArray = append(valueArray, stringValue(\"\"))\n\t\t\t}\n\t\t}\n\n\tRETURN:\n\t\treturn objectValue(call.runtime.newArrayOf(valueArray))\n\t} else {\n\t\tseparator := separatorValue.string()\n\n\t\tsplitLimit := limit\n\t\texcess := false\n\t\tif limit > 0 {\n\t\t\tsplitLimit = limit + 1\n\t\t\texcess = true\n\t\t}\n\n\t\tsplit := strings.SplitN(target, separator, splitLimit)\n\n\t\tif excess && len(split) > limit {\n\t\t\tsplit = split[:limit]\n\t\t}\n\n\t\tvalueArray := make([]Value, len(split))\n\t\tfor index, value := range split {\n\t\t\tvalueArray[index] = stringValue(value)\n\t\t}\n\n\t\treturn objectValue(call.runtime.newArrayOf(valueArray))\n\t}\n}\n\n// builtinStringSlice returns the string sliced by the given values\n// which are rune not byte offsets, as per String.prototype.slice.\nfunc builtinStringSlice(call FunctionCall) Value {\n\tcheckObjectCoercible(call.runtime, call.This)\n\ttarget := []rune(call.This.string())\n\n\tlength := int64(len(target))\n\tstart, end := rangeStartEnd(call.ArgumentList, length, false)\n\tif end-start <= 0 {\n\t\treturn stringValue(\"\")\n\t}\n\treturn stringValue(string(target[start:end]))\n}\n\nfunc builtinStringSubstring(call FunctionCall) Value {\n\tcheckObjectCoercible(call.runtime, call.This)\n\ttarget := []rune(call.This.string())\n\n\tlength := int64(len(target))\n\tstart, end := rangeStartEnd(call.ArgumentList, length, true)\n\tif start > end {\n\t\tstart, end = end, start\n\t}\n\treturn stringValue(string(target[start:end]))\n}\n\nfunc builtinStringSubstr(call FunctionCall) Value {\n\ttarget := []rune(call.This.string())\n\n\tsize := int64(len(target))\n\tstart, length := rangeStartLength(call.ArgumentList, size)\n\n\tif start >= size {\n\t\treturn stringValue(\"\")\n\t}\n\n\tif length <= 0 {\n\t\treturn stringValue(\"\")\n\t}\n\n\tif start+length >= size {\n\t\t// Cap length to be to the end of the string\n\t\t// start = 3, length = 5, size = 4 [0, 1, 2, 3]\n\t\t// 4 - 3 = 1\n\t\t// target[3:4]\n\t\tlength = size - start\n\t}\n\n\treturn stringValue(string(target[start : start+length]))\n}\n\nfunc builtinStringStartsWith(call FunctionCall) Value {\n\tcheckObjectCoercible(call.runtime, call.This)\n\ttarget := call.This.string()\n\tsearch := call.Argument(0).string()\n\tlength := len(search)\n\tif length > len(target) {\n\t\treturn boolValue(false)\n\t}\n\treturn boolValue(target[:length] == search)\n}\n\nfunc builtinStringToLowerCase(call FunctionCall) Value {\n\tcheckObjectCoercible(call.runtime, call.This)\n\treturn stringValue(strings.ToLower(call.This.string()))\n}\n\nfunc builtinStringToUpperCase(call FunctionCall) Value {\n\tcheckObjectCoercible(call.runtime, call.This)\n\treturn stringValue(strings.ToUpper(call.This.string()))\n}\n\n// 7.2 Table 2 — Whitespace Characters & 7.3 Table 3 - Line Terminator Characters.\nconst builtinStringTrimWhitespace = \"\\u0009\\u000A\\u000B\\u000C\\u000D\\u0020\\u00A0\\u1680\\u180E\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200A\\u2028\\u2029\\u202F\\u205F\\u3000\\uFEFF\"\n\nfunc builtinStringTrim(call FunctionCall) Value {\n\tcheckObjectCoercible(call.runtime, call.This)\n\treturn toValue(strings.Trim(call.This.string(),\n\t\tbuiltinStringTrimWhitespace))\n}\n\nfunc builtinStringTrimStart(call FunctionCall) Value {\n\treturn builtinStringTrimLeft(call)\n}\n\nfunc builtinStringTrimEnd(call FunctionCall) Value {\n\treturn builtinStringTrimRight(call)\n}\n\n// Mozilla extension, not ECMAScript 5.\nfunc builtinStringTrimLeft(call FunctionCall) Value {\n\tcheckObjectCoercible(call.runtime, call.This)\n\treturn toValue(strings.TrimLeft(call.This.string(),\n\t\tbuiltinStringTrimWhitespace))\n}\n\n// Mozilla extension, not ECMAScript 5.\nfunc builtinStringTrimRight(call FunctionCall) Value {\n\tcheckObjectCoercible(call.runtime, call.This)\n\treturn toValue(strings.TrimRight(call.This.string(),\n\t\tbuiltinStringTrimWhitespace))\n}\n\nfunc builtinStringLocaleCompare(call FunctionCall) Value {\n\tcheckObjectCoercible(call.runtime, call.This)\n\tthis := call.This.string() //nolint:ifshort\n\tthat := call.Argument(0).string()\n\tif this < that {\n\t\treturn intValue(-1)\n\t} else if this == that {\n\t\treturn intValue(0)\n\t}\n\treturn intValue(1)\n}\n\nfunc builtinStringToLocaleLowerCase(call FunctionCall) Value {\n\treturn builtinStringToLowerCase(call)\n}\n\nfunc builtinStringToLocaleUpperCase(call FunctionCall) Value {\n\treturn builtinStringToUpperCase(call)\n}\n"
  },
  {
    "path": "builtin_test.go",
    "content": "package otto\n\nimport (\n\t\"testing\"\n)\n\nfunc TestString_substr(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            [\n                \"uñiçode\".substr(0,1), // \"u\"\n                \"uñiçode\".substr(0,2), // \"uñ\"\n                \"uñiçode\".substr(0,3), // \"uñi\"\n                \"uñiçode\".substr(0,4), // \"uñiç\"\n                \"uñiçode\".substr(0,9), // \"uñiçode\"\n            ];\n        `, \"u,uñ,uñi,uñiç,uñiçode\")\n\n\t\ttest(`\n            [\n                \"abc\".substr(0,1), // \"a\"\n                \"abc\".substr(0,2), // \"ab\"\n                \"abc\".substr(0,3), // \"abc\"\n                \"abc\".substr(0,4), // \"abc\"\n                \"abc\".substr(0,9), // \"abc\"\n            ];\n        `, \"a,ab,abc,abc,abc\")\n\n\t\ttest(`\n            [\n                \"abc\".substr(1,1), // \"b\"\n                \"abc\".substr(1,2), // \"bc\"\n                \"abc\".substr(1,3), // \"bc\"\n                \"abc\".substr(1,4), // \"bc\"\n                \"abc\".substr(1,9), // \"bc\"\n            ];\n        `, \"b,bc,bc,bc,bc\")\n\n\t\ttest(`\n            [\n                \"abc\".substr(2,1), // \"c\"\n                \"abc\".substr(2,2), // \"c\"\n                \"abc\".substr(2,3), // \"c\"\n                \"abc\".substr(2,4), // \"c\"\n                \"abc\".substr(2,9), // \"c\"\n            ];\n        `, \"c,c,c,c,c\")\n\n\t\ttest(`\n            [\n                \"abc\".substr(3,1), // \"\"\n                \"abc\".substr(3,2), // \"\"\n                \"abc\".substr(3,3), // \"\"\n                \"abc\".substr(3,4), // \"\"\n                \"abc\".substr(3,9), // \"\"\n            ];\n        `, \",,,,\")\n\n\t\ttest(`\n            [\n                \"abc\".substr(0), // \"abc\"\n                \"abc\".substr(1), // \"bc\"\n                \"abc\".substr(2), // \"c\"\n                \"abc\".substr(3), // \"\"\n                \"abc\".substr(9), // \"\"\n            ];\n        `, \"abc,bc,c,,\")\n\n\t\ttest(`\n            [\n                \"abc\".substr(-9), // \"abc\"\n                \"abc\".substr(-3), // \"abc\"\n                \"abc\".substr(-2), // \"bc\"\n                \"abc\".substr(-1), // \"c\"\n            ];\n        `, \"abc,abc,bc,c\")\n\n\t\ttest(`\n            [\n                \"abc\".substr(-9, 1), // \"a\"\n                \"abc\".substr(-3, 1), // \"a\"\n                \"abc\".substr(-2, 1), // \"b\"\n                \"abc\".substr(-1, 1), // \"c\"\n                \"abc\".substr(-1, 2), // \"c\"\n            ];\n        `, \"a,a,b,c,c\")\n\n\t\ttest(`\"abcd\".substr(3, 5)`, \"d\")\n\t})\n}\n\nfunc Test_builtin_escape(t *testing.T) {\n\ttt(t, func() {\n\t\tis(builtinEscape(\"abc\"), \"abc\")\n\n\t\tis(builtinEscape(\"=\"), \"%3D\")\n\n\t\tis(builtinEscape(\"abc=%+32\"), \"abc%3D%25+32\")\n\n\t\tis(builtinEscape(\"世界\"), \"%u4E16%u754C\")\n\t})\n}\n\nfunc Test_builtin_unescape(t *testing.T) {\n\ttt(t, func() {\n\t\tis(builtinUnescape(\"abc\"), \"abc\")\n\n\t\tis(builtinUnescape(\"=%3D\"), \"==\")\n\n\t\tis(builtinUnescape(\"abc%3D%25+32\"), \"abc=%+32\")\n\n\t\tis(builtinUnescape(\"%u4E16%u754C\"), \"世界\")\n\t})\n}\n\nfunc TestGlobal_escape(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            [\n                escape(\"abc\"),          // \"abc\"\n                escape(\"=\"),            // \"%3D\"\n                escape(\"abc=%+32\"),     // \"abc%3D%25+32\"\n                escape(\"\\u4e16\\u754c\"), // \"%u4E16%u754C\"\n            ];\n        `, \"abc,%3D,abc%3D%25+32,%u4E16%u754C\")\n\t})\n}\n\nfunc TestGlobal_unescape(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            [\n                unescape(\"abc\"),          // \"abc\"\n                unescape(\"=%3D\"),         // \"==\"\n                unescape(\"abc%3D%25+32\"), // \"abc=%+32\"\n                unescape(\"%u4E16%u754C\"), // \"世界\"\n            ];\n        `, \"abc,==,abc=%+32,世界\")\n\t})\n}\n\nfunc TestNumber_isNaN(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\t\ttest(`Number.isNaN(1)`, false)\n\t\ttest(`Number.isNaN(null)`, false)\n\t\ttest(`Number.isNaN()`, false)\n\t\ttest(`Number.isNaN(Number.NaN)`, true)\n\t\ttest(`Number.isNaN(0+undefined)`, true)\n\t})\n}\n"
  },
  {
    "path": "call_test.go",
    "content": "package otto\n\nimport (\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nconst (\n\ttestAb = \"ab\"\n)\n\nfunc BenchmarkNativeCallWithString(b *testing.B) {\n\tvm := New()\n\terr := vm.Set(\"x\", func(a1 string) {})\n\trequire.NoError(b, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(\"zzz\")`)\n\trequire.NoError(b, err)\n\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc BenchmarkNativeCallWithFloat32(b *testing.B) {\n\tvm := New()\n\terr := vm.Set(\"x\", func(a1 float32) {})\n\trequire.NoError(b, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(1.1)`)\n\trequire.NoError(b, err)\n\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc BenchmarkNativeCallWithFloat64(b *testing.B) {\n\tvm := New()\n\terr := vm.Set(\"x\", func(a1 float64) {})\n\trequire.NoError(b, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(1.1)`)\n\trequire.NoError(b, err)\n\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc BenchmarkNativeCallWithInt(b *testing.B) {\n\tvm := New()\n\terr := vm.Set(\"x\", func(a1 int) {})\n\trequire.NoError(b, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(1)`)\n\trequire.NoError(b, err)\n\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc BenchmarkNativeCallWithUint(b *testing.B) {\n\tvm := New()\n\terr := vm.Set(\"x\", func(a1 uint) {})\n\trequire.NoError(b, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(1)`)\n\trequire.NoError(b, err)\n\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc BenchmarkNativeCallWithInt8(b *testing.B) {\n\tvm := New()\n\terr := vm.Set(\"x\", func(a1 int8) {})\n\trequire.NoError(b, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(1)`)\n\trequire.NoError(b, err)\n\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc BenchmarkNativeCallWithUint8(b *testing.B) {\n\tvm := New()\n\terr := vm.Set(\"x\", func(a1 uint8) {})\n\trequire.NoError(b, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(1)`)\n\trequire.NoError(b, err)\n\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc BenchmarkNativeCallWithInt16(b *testing.B) {\n\tvm := New()\n\terr := vm.Set(\"x\", func(a1 int16) {})\n\trequire.NoError(b, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(1)`)\n\trequire.NoError(b, err)\n\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc BenchmarkNativeCallWithUint16(b *testing.B) {\n\tvm := New()\n\terr := vm.Set(\"x\", func(a1 uint16) {})\n\trequire.NoError(b, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(1)`)\n\trequire.NoError(b, err)\n\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc BenchmarkNativeCallWithInt32(b *testing.B) {\n\tvm := New()\n\terr := vm.Set(\"x\", func(a1 int32) {})\n\trequire.NoError(b, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(1)`)\n\trequire.NoError(b, err)\n\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc BenchmarkNativeCallWithUint32(b *testing.B) {\n\tvm := New()\n\terr := vm.Set(\"x\", func(a1 uint32) {})\n\trequire.NoError(b, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(1)`)\n\trequire.NoError(b, err)\n\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc BenchmarkNativeCallWithInt64(b *testing.B) {\n\tvm := New()\n\terr := vm.Set(\"x\", func(a1 int64) {})\n\trequire.NoError(b, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(1)`)\n\trequire.NoError(b, err)\n\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc BenchmarkNativeCallWithUint64(b *testing.B) {\n\tvm := New()\n\terr := vm.Set(\"x\", func(a1 uint64) {})\n\trequire.NoError(b, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(1)`)\n\trequire.NoError(b, err)\n\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc BenchmarkNativeCallWithStringInt(b *testing.B) {\n\tvm := New()\n\terr := vm.Set(\"x\", func(a1 string, a2 int) {})\n\trequire.NoError(b, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(\"zzz\", 1)`)\n\trequire.NoError(b, err)\n\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc BenchmarkNativeCallWithIntVariadic0(b *testing.B) {\n\tvm := New()\n\terr := vm.Set(\"x\", func(a ...int) {})\n\trequire.NoError(b, err)\n\n\ts, err := vm.Compile(\"test.js\", `x()`)\n\trequire.NoError(b, err)\n\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc BenchmarkNativeCallWithIntVariadic1(b *testing.B) {\n\tvm := New()\n\terr := vm.Set(\"x\", func(a ...int) {})\n\trequire.NoError(b, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(1)`)\n\trequire.NoError(b, err)\n\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc BenchmarkNativeCallWithIntVariadic3(b *testing.B) {\n\tvm := New()\n\terr := vm.Set(\"x\", func(a ...int) {})\n\trequire.NoError(b, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(1, 2, 3)`)\n\trequire.NoError(b, err)\n\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc BenchmarkNativeCallWithIntVariadic10(b *testing.B) {\n\tvm := New()\n\terr := vm.Set(\"x\", func(a ...int) {})\n\trequire.NoError(b, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)`)\n\trequire.NoError(b, err)\n\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc BenchmarkNativeCallWithIntArray0(b *testing.B) {\n\tvm := New()\n\terr := vm.Set(\"x\", func(a []int) {})\n\trequire.NoError(b, err)\n\n\ts, err := vm.Compile(\"test.js\", `x([])`)\n\trequire.NoError(b, err)\n\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc BenchmarkNativeCallWithIntArray1(b *testing.B) {\n\tvm := New()\n\terr := vm.Set(\"x\", func(a []int) {})\n\trequire.NoError(b, err)\n\n\ts, err := vm.Compile(\"test.js\", `x([1])`)\n\trequire.NoError(b, err)\n\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc BenchmarkNativeCallWithIntArray3(b *testing.B) {\n\tvm := New()\n\terr := vm.Set(\"x\", func(a []int) {})\n\trequire.NoError(b, err)\n\n\ts, err := vm.Compile(\"test.js\", `x([1, 2, 3])`)\n\trequire.NoError(b, err)\n\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc BenchmarkNativeCallWithIntArray10(b *testing.B) {\n\tvm := New()\n\terr := vm.Set(\"x\", func(a []int) {})\n\trequire.NoError(b, err)\n\n\ts, err := vm.Compile(\"test.js\", `x([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])`)\n\trequire.NoError(b, err)\n\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc BenchmarkNativeCallWithIntVariadicArray0(b *testing.B) {\n\tvm := New()\n\terr := vm.Set(\"x\", func(a ...int) {})\n\trequire.NoError(b, err)\n\n\ts, err := vm.Compile(\"test.js\", `x([])`)\n\trequire.NoError(b, err)\n\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc BenchmarkNativeCallWithIntVariadicArray1(b *testing.B) {\n\tvm := New()\n\terr := vm.Set(\"x\", func(a ...int) {})\n\trequire.NoError(b, err)\n\n\ts, err := vm.Compile(\"test.js\", `x([1])`)\n\trequire.NoError(b, err)\n\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc BenchmarkNativeCallWithIntVariadicArray3(b *testing.B) {\n\tvm := New()\n\terr := vm.Set(\"x\", func(a ...int) {})\n\trequire.NoError(b, err)\n\n\ts, err := vm.Compile(\"test.js\", `x([1, 2, 3])`)\n\trequire.NoError(b, err)\n\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc BenchmarkNativeCallWithIntVariadicArray10(b *testing.B) {\n\tvm := New()\n\terr := vm.Set(\"x\", func(a ...int) {})\n\trequire.NoError(b, err)\n\n\ts, err := vm.Compile(\"test.js\", `x([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])`)\n\trequire.NoError(b, err)\n\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc BenchmarkNativeCallWithStringIntVariadic0(b *testing.B) {\n\tvm := New()\n\terr := vm.Set(\"x\", func(a1 string, a2 ...int) {})\n\trequire.NoError(b, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(\"a\")`)\n\trequire.NoError(b, err)\n\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc BenchmarkNativeCallWithStringIntVariadic1(b *testing.B) {\n\tvm := New()\n\terr := vm.Set(\"x\", func(a1 string, a2 ...int) {})\n\trequire.NoError(b, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(\"a\", 1)`)\n\trequire.NoError(b, err)\n\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc BenchmarkNativeCallWithStringIntVariadic3(b *testing.B) {\n\tvm := New()\n\terr := vm.Set(\"x\", func(a1 string, a2 ...int) {})\n\trequire.NoError(b, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(\"a\", 1, 2, 3)`)\n\trequire.NoError(b, err)\n\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc BenchmarkNativeCallWithStringIntVariadic10(b *testing.B) {\n\tvm := New()\n\terr := vm.Set(\"x\", func(a1 string, a2 ...int) {})\n\trequire.NoError(b, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(\"a\", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)`)\n\trequire.NoError(b, err)\n\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc BenchmarkNativeCallWithStringIntVariadicArray0(b *testing.B) {\n\tvm := New()\n\terr := vm.Set(\"x\", func(a1 string, a2 ...int) {})\n\trequire.NoError(b, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(\"a\", [])`)\n\trequire.NoError(b, err)\n\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc BenchmarkNativeCallWithStringIntVariadicArray1(b *testing.B) {\n\tvm := New()\n\terr := vm.Set(\"x\", func(a1 string, a2 ...int) {})\n\trequire.NoError(b, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(\"a\", [1])`)\n\trequire.NoError(b, err)\n\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc BenchmarkNativeCallWithStringIntVariadicArray3(b *testing.B) {\n\tvm := New()\n\terr := vm.Set(\"x\", func(a1 string, a2 ...int) {})\n\trequire.NoError(b, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(\"a\", [1, 2, 3])`)\n\trequire.NoError(b, err)\n\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc BenchmarkNativeCallWithStringIntVariadicArray10(b *testing.B) {\n\tvm := New()\n\terr := vm.Set(\"x\", func(a1 string, a2 ...int) {})\n\trequire.NoError(b, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(\"a\", [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])`)\n\trequire.NoError(b, err)\n\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc BenchmarkNativeCallWithMap(b *testing.B) {\n\tvm := New()\n\terr := vm.Set(\"x\", func(a map[string]string) {})\n\trequire.NoError(b, err)\n\n\ts, err := vm.Compile(\"test.js\", `x({a: \"b\", c: \"d\"})`)\n\trequire.NoError(b, err)\n\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc BenchmarkNativeCallWithMapVariadic(b *testing.B) {\n\tvm := New()\n\terr := vm.Set(\"x\", func(a ...map[string]string) {})\n\trequire.NoError(b, err)\n\n\ts, err := vm.Compile(\"test.js\", `x({a: \"b\", c: \"d\"}, {w: \"x\", y: \"z\"})`)\n\trequire.NoError(b, err)\n\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc BenchmarkNativeCallWithMapVariadicArray(b *testing.B) {\n\tvm := New()\n\terr := vm.Set(\"x\", func(a ...map[string]string) {})\n\trequire.NoError(b, err)\n\n\ts, err := vm.Compile(\"test.js\", `x([{a: \"b\", c: \"d\"}, {w: \"x\", y: \"z\"}])`)\n\trequire.NoError(b, err)\n\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc BenchmarkNativeCallWithFunction(b *testing.B) {\n\tvm := New()\n\terr := vm.Set(\"x\", func(a func()) {})\n\trequire.NoError(b, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(function() {})`)\n\trequire.NoError(b, err)\n\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc BenchmarkNativeCallWithFunctionInt(b *testing.B) {\n\tvm := New()\n\terr := vm.Set(\"x\", func(a func(int)) {})\n\trequire.NoError(b, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(function(n) {})`)\n\trequire.NoError(b, err)\n\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc BenchmarkNativeCallWithFunctionString(b *testing.B) {\n\tvm := New()\n\terr := vm.Set(\"x\", func(a func(string)) {})\n\trequire.NoError(b, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(function(n) {})`)\n\trequire.NoError(b, err)\n\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc TestNativeCallWithString(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\n\terr := vm.Set(\"x\", func(a1 string) {\n\t\tif a1 != \"zzz\" {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(\"zzz\")`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestNativeCallWithFloat32(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\n\terr := vm.Set(\"x\", func(a1 float32) {\n\t\tif a1 != 1.1 {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(1.1)`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestNativeCallWithFloat64(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\n\terr := vm.Set(\"x\", func(a1 float64) {\n\t\tif a1 != 1.1 {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(1.1)`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestNativeCallWithInt(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\n\terr := vm.Set(\"x\", func(a1 int) {\n\t\tif a1 != 1 {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(1)`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestNativeCallWithUint(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\n\terr := vm.Set(\"x\", func(a1 uint) {\n\t\tif a1 != 1 {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(1)`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestNativeCallWithInt8(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\n\terr := vm.Set(\"x\", func(a1 int8) {\n\t\tif a1 != 1 {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(1)`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestNativeCallWithUint8(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\n\terr := vm.Set(\"x\", func(a1 uint8) {\n\t\tif a1 != 1 {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(1)`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestNativeCallWithInt16(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\n\terr := vm.Set(\"x\", func(a1 int16) {\n\t\tif a1 != 1 {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(1)`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestNativeCallWithUint16(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\n\terr := vm.Set(\"x\", func(a1 uint16) {\n\t\tif a1 != 1 {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(1)`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestNativeCallWithInt32(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\n\terr := vm.Set(\"x\", func(a1 int32) {\n\t\tif a1 != 1 {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(1)`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestNativeCallWithUint32(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\n\terr := vm.Set(\"x\", func(a1 uint32) {\n\t\tif a1 != 1 {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(1)`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestNativeCallWithInt64(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\n\terr := vm.Set(\"x\", func(a1 int64) {\n\t\tif a1 != 1 {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(1)`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestNativeCallWithUint64(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\n\terr := vm.Set(\"x\", func(a1 uint64) {\n\t\tif a1 != 1 {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(1)`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestNativeCallWithStringInt(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\n\terr := vm.Set(\"x\", func(a1 string, a2 int) {\n\t\tif a1 != \"zzz\" || a2 != 1 {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(\"zzz\", 1)`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestNativeCallWithIntVariadic0(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\n\terr := vm.Set(\"x\", func(a ...int) {\n\t\tif !reflect.DeepEqual(a, []int{}) {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `x()`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestNativeCallWithIntVariadic1(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\n\terr := vm.Set(\"x\", func(a ...int) {\n\t\tif !reflect.DeepEqual(a, []int{1}) {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(1)`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestNativeCallWithIntVariadic3(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\n\terr := vm.Set(\"x\", func(a ...int) {\n\t\tif !reflect.DeepEqual(a, []int{1, 2, 3}) {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(1, 2, 3)`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestNativeCallWithIntVariadic10(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\n\terr := vm.Set(\"x\", func(a ...int) {\n\t\tif !reflect.DeepEqual(a, []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestNativeCallWithIntArray0(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\n\terr := vm.Set(\"x\", func(a []int) {\n\t\tif !reflect.DeepEqual(a, []int{}) {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `x([])`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestNativeCallWithIntArray1(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\n\terr := vm.Set(\"x\", func(a []int) {\n\t\tif !reflect.DeepEqual(a, []int{1}) {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `x([1])`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestNativeCallWithIntArray3(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\n\terr := vm.Set(\"x\", func(a []int) {\n\t\tif !reflect.DeepEqual(a, []int{1, 2, 3}) {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `x([1, 2, 3])`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestNativeCallWithIntArray10(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\n\terr := vm.Set(\"x\", func(a []int) {\n\t\tif !reflect.DeepEqual(a, []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `x([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestNativeCallWithIntVariadicArray0(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\n\terr := vm.Set(\"x\", func(a ...int) {\n\t\tif !reflect.DeepEqual(a, []int{}) {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `x([])`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestNativeCallWithIntVariadicArray1(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\n\terr := vm.Set(\"x\", func(a ...int) {\n\t\tif !reflect.DeepEqual(a, []int{1}) {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `x([1])`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestNativeCallWithIntVariadicArray3(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\n\terr := vm.Set(\"x\", func(a ...int) {\n\t\tif !reflect.DeepEqual(a, []int{1, 2, 3}) {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `x([1, 2, 3])`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestNativeCallWithIntVariadicArray10(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\n\terr := vm.Set(\"x\", func(a ...int) {\n\t\tif !reflect.DeepEqual(a, []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `x([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestNativeCallWithStringIntVariadic0(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\n\terr := vm.Set(\"x\", func(a1 string, a2 ...int) {\n\t\tif a1 != \"a\" || !reflect.DeepEqual(a2, []int{}) {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(\"a\")`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestNativeCallWithStringIntVariadic1(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\n\terr := vm.Set(\"x\", func(a1 string, a2 ...int) {\n\t\tif a1 != \"a\" || !reflect.DeepEqual(a2, []int{1}) {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(\"a\", 1)`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestNativeCallWithStringIntVariadic3(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\n\terr := vm.Set(\"x\", func(a1 string, a2 ...int) {\n\t\tif a1 != \"a\" || !reflect.DeepEqual(a2, []int{1, 2, 3}) {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(\"a\", 1, 2, 3)`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestNativeCallWithStringIntVariadic10(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\n\terr := vm.Set(\"x\", func(a1 string, a2 ...int) {\n\t\tif a1 != \"a\" || !reflect.DeepEqual(a2, []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(\"a\", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestNativeCallWithStringIntVariadicArray0(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\n\terr := vm.Set(\"x\", func(a1 string, a2 ...int) {\n\t\tif a1 != \"a\" || !reflect.DeepEqual(a2, []int{}) {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(\"a\", [])`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestNativeCallWithStringIntVariadicArray1(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\n\terr := vm.Set(\"x\", func(a1 string, a2 ...int) {\n\t\tif a1 != \"a\" || !reflect.DeepEqual(a2, []int{1}) {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(\"a\", [1])`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestNativeCallWithStringIntVariadicArray3(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\n\terr := vm.Set(\"x\", func(a1 string, a2 ...int) {\n\t\tif a1 != \"a\" || !reflect.DeepEqual(a2, []int{1, 2, 3}) {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(\"a\", [1, 2, 3])`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestNativeCallWithStringIntVariadicArray10(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\n\terr := vm.Set(\"x\", func(a1 string, a2 ...int) {\n\t\tif a1 != \"a\" || !reflect.DeepEqual(a2, []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(\"a\", [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestNativeCallWithMap(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\n\terr := vm.Set(\"x\", func(a map[string]string) {\n\t\tif !reflect.DeepEqual(a, map[string]string{\"a\": \"b\", \"c\": \"d\"}) {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `x({a: \"b\", c: \"d\"})`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestNativeCallWithMapVariadic(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\n\terr := vm.Set(\"x\", func(a ...map[string]string) {\n\t\tif !reflect.DeepEqual(a, []map[string]string{{\"a\": \"b\", \"c\": \"d\"}, {\"w\": \"x\", \"y\": \"z\"}}) {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `x({a: \"b\", c: \"d\"}, {w: \"x\", y: \"z\"})`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestNativeCallWithMapVariadicArray(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\n\terr := vm.Set(\"x\", func(a ...map[string]string) {\n\t\tif !reflect.DeepEqual(a, []map[string]string{{\"a\": \"b\", \"c\": \"d\"}, {\"w\": \"x\", \"y\": \"z\"}}) {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `x([{a: \"b\", c: \"d\"}, {w: \"x\", y: \"z\"}])`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestNativeCallWithFunctionVoidBool(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\n\terr := vm.Set(\"x\", func(fn func() bool) {\n\t\tif !fn() {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(function() { return true; })`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestNativeCallWithFunctionIntInt(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\n\terr := vm.Set(\"x\", func(fn func(int) int) {\n\t\tif fn(5) != 5 {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(function(n) { return n; })`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestNativeCallWithFunctionStringString(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\n\terr := vm.Set(\"x\", func(fn func(string) string) {\n\t\tif fn(\"zzz\") != \"zzz\" {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `x(function(n) { return n; })`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\ntype testNativeCallWithStruct struct {\n\tPrefix string\n}\n\ntype testNativeCallWithStructArg struct {\n\tText string\n}\n\nfunc (t testNativeCallWithStruct) MakeStruct(s string) testNativeCallWithStructArg {\n\treturn testNativeCallWithStructArg{Text: s}\n}\n\nfunc (t testNativeCallWithStruct) MakeStructPointer(s string) *testNativeCallWithStructArg {\n\treturn &testNativeCallWithStructArg{Text: s}\n}\n\nfunc (t testNativeCallWithStruct) CallWithStruct(a testNativeCallWithStructArg) string {\n\treturn t.Prefix + a.Text\n}\n\nfunc (t *testNativeCallWithStruct) CallPointerWithStruct(a testNativeCallWithStructArg) string {\n\treturn t.Prefix + a.Text\n}\n\nfunc (t testNativeCallWithStruct) CallWithStructPointer(a *testNativeCallWithStructArg) string {\n\treturn t.Prefix + a.Text\n}\n\nfunc (t *testNativeCallWithStruct) CallPointerWithStructPointer(a *testNativeCallWithStructArg) string {\n\treturn t.Prefix + a.Text\n}\n\nfunc TestNativeCallMethodWithStruct(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\terr := vm.Set(\"x\", testNativeCallWithStruct{Prefix: \"a\"})\n\trequire.NoError(t, err)\n\n\terr = vm.Set(\"t\", func(s string) {\n\t\tif s != testAb {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `t(x.CallWithStruct(x.MakeStruct(\"b\")))`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestNativeCallPointerMethodWithStruct(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\terr := vm.Set(\"x\", &testNativeCallWithStruct{Prefix: \"a\"})\n\trequire.NoError(t, err)\n\n\terr = vm.Set(\"t\", func(s string) {\n\t\tif s != testAb {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `t(x.CallPointerWithStruct(x.MakeStruct(\"b\")))`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestNativeCallMethodWithStructPointer(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\terr := vm.Set(\"x\", testNativeCallWithStruct{Prefix: \"a\"})\n\trequire.NoError(t, err)\n\n\terr = vm.Set(\"t\", func(s string) {\n\t\tif s != testAb {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `t(x.CallWithStructPointer(x.MakeStructPointer(\"b\")))`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestNativeCallPointerMethodWithStructPointer(t *testing.T) {\n\tvm := New()\n\n\tcalled := false\n\terr := vm.Set(\"x\", &testNativeCallWithStruct{Prefix: \"a\"})\n\trequire.NoError(t, err)\n\n\terr = vm.Set(\"t\", func(s string) {\n\t\tif s != testAb {\n\t\t\tt.Fail()\n\t\t}\n\n\t\tcalled = true\n\t})\n\trequire.NoError(t, err)\n\n\ts, err := vm.Compile(\"test.js\", `t(x.CallPointerWithStructPointer(x.MakeStructPointer(\"b\")))`)\n\trequire.NoError(t, err)\n\n\tif _, err = vm.Run(s); err != nil {\n\t\tt.Logf(\"err should have been nil; was %s\\n\", err.Error())\n\t\tt.Fail()\n\t}\n\n\tif !called {\n\t\tt.Fail()\n\t}\n}\n\nfunc TestNativeCallNilInterfaceArg(t *testing.T) {\n\tvm := New()\n\terr := vm.Set(\"f1\", func(v interface{}) {})\n\trequire.NoError(t, err)\n\n\t_, err = vm.Call(\"f1\", nil, nil)\n\trequire.NoError(t, err)\n}\n"
  },
  {
    "path": "clone.go",
    "content": "package otto\n\nimport (\n\t\"fmt\"\n)\n\ntype cloner struct {\n\truntime     *runtime\n\tobj         map[*object]*object\n\tobjectstash map[*objectStash]*objectStash\n\tdclstash    map[*dclStash]*dclStash\n\tfnstash     map[*fnStash]*fnStash\n}\n\nfunc (rt *runtime) clone() *runtime {\n\trt.lck.Lock()\n\tdefer rt.lck.Unlock()\n\n\tout := &runtime{\n\t\tdebugger:   rt.debugger,\n\t\trandom:     rt.random,\n\t\tstackLimit: rt.stackLimit,\n\t\ttraceLimit: rt.traceLimit,\n\t}\n\n\tc := cloner{\n\t\truntime:     out,\n\t\tobj:         make(map[*object]*object),\n\t\tobjectstash: make(map[*objectStash]*objectStash),\n\t\tdclstash:    make(map[*dclStash]*dclStash),\n\t\tfnstash:     make(map[*fnStash]*fnStash),\n\t}\n\n\tglobalObject := c.object(rt.globalObject)\n\tout.globalStash = out.newObjectStash(globalObject, nil)\n\tout.globalObject = globalObject\n\tout.global = global{\n\t\tc.object(rt.global.Object),\n\t\tc.object(rt.global.Function),\n\t\tc.object(rt.global.Array),\n\t\tc.object(rt.global.String),\n\t\tc.object(rt.global.Boolean),\n\t\tc.object(rt.global.Number),\n\t\tc.object(rt.global.Math),\n\t\tc.object(rt.global.Date),\n\t\tc.object(rt.global.RegExp),\n\t\tc.object(rt.global.Error),\n\t\tc.object(rt.global.EvalError),\n\t\tc.object(rt.global.TypeError),\n\t\tc.object(rt.global.RangeError),\n\t\tc.object(rt.global.ReferenceError),\n\t\tc.object(rt.global.SyntaxError),\n\t\tc.object(rt.global.URIError),\n\t\tc.object(rt.global.JSON),\n\n\t\tc.object(rt.global.ObjectPrototype),\n\t\tc.object(rt.global.FunctionPrototype),\n\t\tc.object(rt.global.ArrayPrototype),\n\t\tc.object(rt.global.StringPrototype),\n\t\tc.object(rt.global.BooleanPrototype),\n\t\tc.object(rt.global.NumberPrototype),\n\t\tc.object(rt.global.DatePrototype),\n\t\tc.object(rt.global.RegExpPrototype),\n\t\tc.object(rt.global.ErrorPrototype),\n\t\tc.object(rt.global.EvalErrorPrototype),\n\t\tc.object(rt.global.TypeErrorPrototype),\n\t\tc.object(rt.global.RangeErrorPrototype),\n\t\tc.object(rt.global.ReferenceErrorPrototype),\n\t\tc.object(rt.global.SyntaxErrorPrototype),\n\t\tc.object(rt.global.URIErrorPrototype),\n\t}\n\n\tout.eval = out.globalObject.property[\"eval\"].value.(Value).value.(*object)\n\tout.globalObject.prototype = out.global.ObjectPrototype\n\n\t// Not sure if this is necessary, but give some help to the GC\n\tc.runtime = nil\n\tc.obj = nil\n\tc.objectstash = nil\n\tc.dclstash = nil\n\tc.fnstash = nil\n\n\treturn out\n}\n\nfunc (c *cloner) object(in *object) *object {\n\tif out, exists := c.obj[in]; exists {\n\t\treturn out\n\t}\n\tout := &object{}\n\tc.obj[in] = out\n\treturn in.objectClass.clone(in, out, c)\n}\n\nfunc (c *cloner) dclStash(in *dclStash) (*dclStash, bool) {\n\tif out, exists := c.dclstash[in]; exists {\n\t\treturn out, true\n\t}\n\tout := &dclStash{}\n\tc.dclstash[in] = out\n\treturn out, false\n}\n\nfunc (c *cloner) objectStash(in *objectStash) (*objectStash, bool) {\n\tif out, exists := c.objectstash[in]; exists {\n\t\treturn out, true\n\t}\n\tout := &objectStash{}\n\tc.objectstash[in] = out\n\treturn out, false\n}\n\nfunc (c *cloner) fnStash(in *fnStash) (*fnStash, bool) {\n\tif out, exists := c.fnstash[in]; exists {\n\t\treturn out, true\n\t}\n\tout := &fnStash{}\n\tc.fnstash[in] = out\n\treturn out, false\n}\n\nfunc (c *cloner) value(in Value) Value {\n\tout := in\n\tif value, ok := in.value.(*object); ok {\n\t\tout.value = c.object(value)\n\t}\n\treturn out\n}\n\nfunc (c *cloner) valueArray(in []Value) []Value {\n\tout := make([]Value, len(in))\n\tfor index, value := range in {\n\t\tout[index] = c.value(value)\n\t}\n\treturn out\n}\n\nfunc (c *cloner) stash(in stasher) stasher {\n\tif in == nil {\n\t\treturn nil\n\t}\n\treturn in.clone(c)\n}\n\nfunc (c *cloner) property(in property) property {\n\tout := in\n\n\tswitch value := in.value.(type) {\n\tcase Value:\n\t\tout.value = c.value(value)\n\tcase propertyGetSet:\n\t\tp := propertyGetSet{}\n\t\tif value[0] != nil {\n\t\t\tp[0] = c.object(value[0])\n\t\t}\n\t\tif value[1] != nil {\n\t\t\tp[1] = c.object(value[1])\n\t\t}\n\t\tout.value = p\n\tdefault:\n\t\tpanic(fmt.Errorf(\"in.value.(Value) != true; in.value is %T\", in.value))\n\t}\n\n\treturn out\n}\n\nfunc (c *cloner) dclProperty(in dclProperty) dclProperty {\n\tout := in\n\tout.value = c.value(in.value)\n\treturn out\n}\n"
  },
  {
    "path": "clone_test.go",
    "content": "package otto\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestCloneGetterSetter(t *testing.T) {\n\tvm := New()\n\n\t_, err := vm.Run(`var x = Object.create(null, {\n    x: {\n      get: function() {},\n      set: function() {},\n    },\n  })`)\n\trequire.NoError(t, err)\n\trequire.NotPanics(t, func() {\n\t\tvm.Copy()\n\t})\n}\n"
  },
  {
    "path": "cmpl.go",
    "content": "package otto\n\nimport (\n\t\"github.com/robertkrimen/otto/ast\"\n\t\"github.com/robertkrimen/otto/file\"\n)\n\ntype compiler struct {\n\tfile    *file.File\n\tprogram *ast.Program\n}\n"
  },
  {
    "path": "cmpl_evaluate.go",
    "content": "package otto\n\nimport (\n\t\"strconv\"\n)\n\nfunc (rt *runtime) cmplEvaluateNodeProgram(node *nodeProgram, eval bool) Value {\n\tif !eval {\n\t\trt.enterGlobalScope()\n\t\tdefer rt.leaveScope()\n\t}\n\trt.cmplFunctionDeclaration(node.functionList)\n\trt.cmplVariableDeclaration(node.varList)\n\trt.scope.frame.file = node.file\n\treturn rt.cmplEvaluateNodeStatementList(node.body)\n}\n\nfunc (rt *runtime) cmplCallNodeFunction(function *object, stash *fnStash, node *nodeFunctionLiteral, argumentList []Value) Value {\n\tindexOfParameterName := make([]string, len(argumentList))\n\t// function(abc, def, ghi)\n\t// indexOfParameterName[0] = \"abc\"\n\t// indexOfParameterName[1] = \"def\"\n\t// indexOfParameterName[2] = \"ghi\"\n\t// ...\n\n\targumentsFound := false\n\tfor index, name := range node.parameterList {\n\t\tif name == \"arguments\" {\n\t\t\targumentsFound = true\n\t\t}\n\t\tvalue := Value{}\n\t\tif index < len(argumentList) {\n\t\t\tvalue = argumentList[index]\n\t\t\tindexOfParameterName[index] = name\n\t\t}\n\t\t// strict = false\n\t\trt.scope.lexical.setValue(name, value, false)\n\t}\n\n\tif !argumentsFound {\n\t\targuments := rt.newArgumentsObject(indexOfParameterName, stash, len(argumentList))\n\t\targuments.defineProperty(\"callee\", objectValue(function), 0o101, false)\n\t\tstash.arguments = arguments\n\t\t// strict = false\n\t\trt.scope.lexical.setValue(\"arguments\", objectValue(arguments), false)\n\t\tfor index := range argumentList {\n\t\t\tif index < len(node.parameterList) {\n\t\t\t\tcontinue\n\t\t\t}\n\t\t\tindexAsString := strconv.FormatInt(int64(index), 10)\n\t\t\targuments.defineProperty(indexAsString, argumentList[index], 0o111, false)\n\t\t}\n\t}\n\n\trt.cmplFunctionDeclaration(node.functionList)\n\trt.cmplVariableDeclaration(node.varList)\n\n\tresult := rt.cmplEvaluateNodeStatement(node.body)\n\tif result.kind == valueResult {\n\t\treturn result\n\t}\n\n\treturn Value{}\n}\n\nfunc (rt *runtime) cmplFunctionDeclaration(list []*nodeFunctionLiteral) {\n\texecutionContext := rt.scope\n\teval := executionContext.eval\n\tstash := executionContext.variable\n\n\tfor _, function := range list {\n\t\tname := function.name\n\t\tvalue := rt.cmplEvaluateNodeExpression(function)\n\t\tif !stash.hasBinding(name) {\n\t\t\tstash.createBinding(name, eval, value)\n\t\t} else {\n\t\t\t// TODO 10.5.5.e\n\t\t\tstash.setBinding(name, value, false) // TODO strict\n\t\t}\n\t}\n}\n\nfunc (rt *runtime) cmplVariableDeclaration(list []string) {\n\texecutionContext := rt.scope\n\teval := executionContext.eval\n\tstash := executionContext.variable\n\n\tfor _, name := range list {\n\t\tif !stash.hasBinding(name) {\n\t\t\tstash.createBinding(name, eval, Value{}) // TODO strict?\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "cmpl_evaluate_expression.go",
    "content": "package otto\n\nimport (\n\t\"fmt\"\n\t\"math\"\n\tgoruntime \"runtime\"\n\n\t\"github.com/robertkrimen/otto/token\"\n)\n\nfunc (rt *runtime) cmplEvaluateNodeExpression(node nodeExpression) Value {\n\t// Allow interpreter interruption\n\t// If the Interrupt channel is nil, then\n\t// we avoid runtime.Gosched() overhead (if any)\n\t// FIXME: Test this\n\tif rt.otto.Interrupt != nil {\n\t\tgoruntime.Gosched()\n\t\tselect {\n\t\tcase value := <-rt.otto.Interrupt:\n\t\t\tvalue()\n\t\tdefault:\n\t\t}\n\t}\n\n\tswitch node := node.(type) {\n\tcase *nodeArrayLiteral:\n\t\treturn rt.cmplEvaluateNodeArrayLiteral(node)\n\n\tcase *nodeAssignExpression:\n\t\treturn rt.cmplEvaluateNodeAssignExpression(node)\n\n\tcase *nodeBinaryExpression:\n\t\tif node.comparison {\n\t\t\treturn rt.cmplEvaluateNodeBinaryExpressionComparison(node)\n\t\t}\n\t\treturn rt.cmplEvaluateNodeBinaryExpression(node)\n\n\tcase *nodeBracketExpression:\n\t\treturn rt.cmplEvaluateNodeBracketExpression(node)\n\n\tcase *nodeCallExpression:\n\t\treturn rt.cmplEvaluateNodeCallExpression(node, nil)\n\n\tcase *nodeConditionalExpression:\n\t\treturn rt.cmplEvaluateNodeConditionalExpression(node)\n\n\tcase *nodeDotExpression:\n\t\treturn rt.cmplEvaluateNodeDotExpression(node)\n\n\tcase *nodeFunctionLiteral:\n\t\tlocal := rt.scope.lexical\n\t\tif node.name != \"\" {\n\t\t\tlocal = rt.newDeclarationStash(local)\n\t\t}\n\n\t\tvalue := objectValue(rt.newNodeFunction(node, local))\n\t\tif node.name != \"\" {\n\t\t\tlocal.createBinding(node.name, false, value)\n\t\t}\n\t\treturn value\n\n\tcase *nodeIdentifier:\n\t\tname := node.name\n\t\t// TODO Should be true or false (strictness) depending on context\n\t\t// getIdentifierReference should not return nil, but we check anyway and panic\n\t\t// so as not to propagate the nil into something else\n\t\treference := getIdentifierReference(rt, rt.scope.lexical, name, false, at(node.idx))\n\t\tif reference == nil {\n\t\t\t// Should never get here!\n\t\t\tpanic(hereBeDragons(\"referenceError == nil: \" + name))\n\t\t}\n\t\treturn toValue(reference)\n\n\tcase *nodeLiteral:\n\t\treturn node.value\n\n\tcase *nodeNewExpression:\n\t\treturn rt.cmplEvaluateNodeNewExpression(node)\n\n\tcase *nodeObjectLiteral:\n\t\treturn rt.cmplEvaluateNodeObjectLiteral(node)\n\n\tcase *nodeRegExpLiteral:\n\t\treturn objectValue(rt.newRegExpDirect(node.pattern, node.flags))\n\n\tcase *nodeSequenceExpression:\n\t\treturn rt.cmplEvaluateNodeSequenceExpression(node)\n\n\tcase *nodeThisExpression:\n\t\treturn objectValue(rt.scope.this)\n\n\tcase *nodeUnaryExpression:\n\t\treturn rt.cmplEvaluateNodeUnaryExpression(node)\n\n\tcase *nodeVariableExpression:\n\t\treturn rt.cmplEvaluateNodeVariableExpression(node)\n\tdefault:\n\t\tpanic(fmt.Sprintf(\"unknown node type: %T\", node))\n\t}\n}\n\nfunc (rt *runtime) cmplEvaluateNodeArrayLiteral(node *nodeArrayLiteral) Value {\n\tvalueArray := []Value{}\n\n\tfor _, node := range node.value {\n\t\tif node == nil {\n\t\t\tvalueArray = append(valueArray, emptyValue)\n\t\t} else {\n\t\t\tvalueArray = append(valueArray, rt.cmplEvaluateNodeExpression(node).resolve())\n\t\t}\n\t}\n\n\tresult := rt.newArrayOf(valueArray)\n\n\treturn objectValue(result)\n}\n\nfunc (rt *runtime) cmplEvaluateNodeAssignExpression(node *nodeAssignExpression) Value {\n\tleft := rt.cmplEvaluateNodeExpression(node.left)\n\tright := rt.cmplEvaluateNodeExpression(node.right)\n\trightValue := right.resolve()\n\n\tresult := rightValue\n\tif node.operator != token.ASSIGN {\n\t\tresult = rt.calculateBinaryExpression(node.operator, left, rightValue)\n\t}\n\n\trt.putValue(left.reference(), result)\n\n\treturn result\n}\n\nfunc (rt *runtime) cmplEvaluateNodeBinaryExpression(node *nodeBinaryExpression) Value {\n\tleft := rt.cmplEvaluateNodeExpression(node.left)\n\tleftValue := left.resolve()\n\n\tswitch node.operator {\n\t// Logical\n\tcase token.LOGICAL_AND:\n\t\tif !leftValue.bool() {\n\t\t\treturn leftValue\n\t\t}\n\t\tright := rt.cmplEvaluateNodeExpression(node.right)\n\t\treturn right.resolve()\n\tcase token.LOGICAL_OR:\n\t\tif leftValue.bool() {\n\t\t\treturn leftValue\n\t\t}\n\t\tright := rt.cmplEvaluateNodeExpression(node.right)\n\t\treturn right.resolve()\n\t}\n\n\treturn rt.calculateBinaryExpression(node.operator, leftValue, rt.cmplEvaluateNodeExpression(node.right))\n}\n\nfunc (rt *runtime) cmplEvaluateNodeBinaryExpressionComparison(node *nodeBinaryExpression) Value {\n\tleft := rt.cmplEvaluateNodeExpression(node.left).resolve()\n\tright := rt.cmplEvaluateNodeExpression(node.right).resolve()\n\n\treturn boolValue(rt.calculateComparison(node.operator, left, right))\n}\n\nfunc (rt *runtime) cmplEvaluateNodeBracketExpression(node *nodeBracketExpression) Value {\n\ttarget := rt.cmplEvaluateNodeExpression(node.left)\n\ttargetValue := target.resolve()\n\tmember := rt.cmplEvaluateNodeExpression(node.member)\n\tmemberValue := member.resolve()\n\n\t// TODO Pass in base value as-is, and defer toObject till later?\n\tobj, err := rt.objectCoerce(targetValue)\n\tif err != nil {\n\t\tpanic(rt.panicTypeError(\"Cannot access member %q of %s\", memberValue.string(), err, at(node.idx)))\n\t}\n\treturn toValue(newPropertyReference(rt, obj, memberValue.string(), false, at(node.idx)))\n}\n\nfunc (rt *runtime) cmplEvaluateNodeCallExpression(node *nodeCallExpression, withArgumentList []interface{}) Value {\n\tthis := Value{}\n\tcallee := rt.cmplEvaluateNodeExpression(node.callee)\n\n\targumentList := []Value{}\n\tif withArgumentList != nil {\n\t\targumentList = rt.toValueArray(withArgumentList...)\n\t} else {\n\t\tfor _, argumentNode := range node.argumentList {\n\t\t\targumentList = append(argumentList, rt.cmplEvaluateNodeExpression(argumentNode).resolve())\n\t\t}\n\t}\n\n\teval := false // Whether this call is a (candidate for) direct call to eval\n\tname := \"\"\n\tif rf := callee.reference(); rf != nil {\n\t\tswitch rf := rf.(type) {\n\t\tcase *propertyReference:\n\t\t\tname = rf.name\n\t\t\tthis = objectValue(rf.base)\n\t\t\teval = rf.name == \"eval\" // Possible direct eval\n\t\tcase *stashReference:\n\t\t\t// TODO ImplicitThisValue\n\t\t\tname = rf.name\n\t\t\teval = rf.name == \"eval\" // Possible direct eval\n\t\tdefault:\n\t\t\t// FIXME?\n\t\t\tpanic(rt.panicTypeError(\"unexpected callee type %T to node call expression\", rf))\n\t\t}\n\t}\n\n\tatv := at(-1)\n\tswitch callee := node.callee.(type) {\n\tcase *nodeIdentifier:\n\t\tatv = at(callee.idx)\n\tcase *nodeDotExpression:\n\t\tatv = at(callee.idx)\n\tcase *nodeBracketExpression:\n\t\tatv = at(callee.idx)\n\t}\n\n\tfrm := frame{\n\t\tcallee: name,\n\t\tfile:   rt.scope.frame.file,\n\t}\n\n\tvl := callee.resolve()\n\tif !vl.IsFunction() {\n\t\tif name == \"\" {\n\t\t\t// FIXME Maybe typeof?\n\t\t\tpanic(rt.panicTypeError(\"%v is not a function\", vl, atv))\n\t\t}\n\t\tpanic(rt.panicTypeError(\"%q is not a function\", name, atv))\n\t}\n\n\trt.scope.frame.offset = int(atv)\n\n\treturn vl.object().call(this, argumentList, eval, frm)\n}\n\nfunc (rt *runtime) cmplEvaluateNodeConditionalExpression(node *nodeConditionalExpression) Value {\n\ttest := rt.cmplEvaluateNodeExpression(node.test)\n\ttestValue := test.resolve()\n\tif testValue.bool() {\n\t\treturn rt.cmplEvaluateNodeExpression(node.consequent)\n\t}\n\treturn rt.cmplEvaluateNodeExpression(node.alternate)\n}\n\nfunc (rt *runtime) cmplEvaluateNodeDotExpression(node *nodeDotExpression) Value {\n\ttarget := rt.cmplEvaluateNodeExpression(node.left)\n\ttargetValue := target.resolve()\n\t// TODO Pass in base value as-is, and defer toObject till later?\n\tobj, err := rt.objectCoerce(targetValue)\n\tif err != nil {\n\t\tpanic(rt.panicTypeError(\"Cannot access member %q of %s\", node.identifier, err, at(node.idx)))\n\t}\n\treturn toValue(newPropertyReference(rt, obj, node.identifier, false, at(node.idx)))\n}\n\nfunc (rt *runtime) cmplEvaluateNodeNewExpression(node *nodeNewExpression) Value {\n\tcallee := rt.cmplEvaluateNodeExpression(node.callee)\n\n\targumentList := []Value{}\n\tfor _, argumentNode := range node.argumentList {\n\t\targumentList = append(argumentList, rt.cmplEvaluateNodeExpression(argumentNode).resolve())\n\t}\n\n\tvar name string\n\tif rf := callee.reference(); rf != nil {\n\t\tswitch rf := rf.(type) {\n\t\tcase *propertyReference:\n\t\t\tname = rf.name\n\t\tcase *stashReference:\n\t\t\tname = rf.name\n\t\tdefault:\n\t\t\tpanic(rt.panicTypeError(\"node new expression unexpected callee type %T\", rf))\n\t\t}\n\t}\n\n\tatv := at(-1)\n\tswitch callee := node.callee.(type) {\n\tcase *nodeIdentifier:\n\t\tatv = at(callee.idx)\n\tcase *nodeDotExpression:\n\t\tatv = at(callee.idx)\n\tcase *nodeBracketExpression:\n\t\tatv = at(callee.idx)\n\t}\n\n\tvl := callee.resolve()\n\tif !vl.IsFunction() {\n\t\tif name == \"\" {\n\t\t\t// FIXME Maybe typeof?\n\t\t\tpanic(rt.panicTypeError(\"%v is not a function\", vl, atv))\n\t\t}\n\t\tpanic(rt.panicTypeError(\"'%s' is not a function\", name, atv))\n\t}\n\n\trt.scope.frame.offset = int(atv)\n\n\treturn vl.object().construct(argumentList)\n}\n\nfunc (rt *runtime) cmplEvaluateNodeObjectLiteral(node *nodeObjectLiteral) Value {\n\tresult := rt.newObject()\n\tfor _, prop := range node.value {\n\t\tswitch prop.kind {\n\t\tcase \"value\":\n\t\t\tresult.defineProperty(prop.key, rt.cmplEvaluateNodeExpression(prop.value).resolve(), 0o111, false)\n\t\tcase \"get\":\n\t\t\tgetter := rt.newNodeFunction(prop.value.(*nodeFunctionLiteral), rt.scope.lexical)\n\t\t\tdescriptor := property{}\n\t\t\tdescriptor.mode = 0o211\n\t\t\tdescriptor.value = propertyGetSet{getter, nil}\n\t\t\tresult.defineOwnProperty(prop.key, descriptor, false)\n\t\tcase \"set\":\n\t\t\tsetter := rt.newNodeFunction(prop.value.(*nodeFunctionLiteral), rt.scope.lexical)\n\t\t\tdescriptor := property{}\n\t\t\tdescriptor.mode = 0o211\n\t\t\tdescriptor.value = propertyGetSet{nil, setter}\n\t\t\tresult.defineOwnProperty(prop.key, descriptor, false)\n\t\tdefault:\n\t\t\tpanic(fmt.Sprintf(\"unknown node object literal property kind %T\", prop.kind))\n\t\t}\n\t}\n\n\treturn objectValue(result)\n}\n\nfunc (rt *runtime) cmplEvaluateNodeSequenceExpression(node *nodeSequenceExpression) Value {\n\tvar result Value\n\tfor _, node := range node.sequence {\n\t\tresult = rt.cmplEvaluateNodeExpression(node)\n\t\tresult = result.resolve()\n\t}\n\treturn result\n}\n\nfunc (rt *runtime) cmplEvaluateNodeUnaryExpression(node *nodeUnaryExpression) Value {\n\ttarget := rt.cmplEvaluateNodeExpression(node.operand)\n\tswitch node.operator {\n\tcase token.TYPEOF, token.DELETE:\n\t\tif target.kind == valueReference && target.reference().invalid() {\n\t\t\tif node.operator == token.TYPEOF {\n\t\t\t\treturn stringValue(\"undefined\")\n\t\t\t}\n\t\t\treturn trueValue\n\t\t}\n\t}\n\n\tswitch node.operator {\n\tcase token.NOT:\n\t\ttargetValue := target.resolve()\n\t\tif targetValue.bool() {\n\t\t\treturn falseValue\n\t\t}\n\t\treturn trueValue\n\tcase token.BITWISE_NOT:\n\t\ttargetValue := target.resolve()\n\t\tintegerValue := toInt32(targetValue)\n\t\treturn int32Value(^integerValue)\n\tcase token.PLUS:\n\t\ttargetValue := target.resolve()\n\t\treturn float64Value(targetValue.float64())\n\tcase token.MINUS:\n\t\ttargetValue := target.resolve()\n\t\tvalue := targetValue.float64()\n\t\t// TODO Test this\n\t\tsign := float64(-1)\n\t\tif math.Signbit(value) {\n\t\t\tsign = 1\n\t\t}\n\t\treturn float64Value(math.Copysign(value, sign))\n\tcase token.INCREMENT:\n\t\ttargetValue := target.resolve()\n\t\tif node.postfix {\n\t\t\t// Postfix++\n\t\t\toldValue := targetValue.float64()\n\t\t\tnewValue := float64Value(+1 + oldValue)\n\t\t\trt.putValue(target.reference(), newValue)\n\t\t\treturn float64Value(oldValue)\n\t\t}\n\n\t\t// ++Prefix\n\t\tnewValue := float64Value(+1 + targetValue.float64())\n\t\trt.putValue(target.reference(), newValue)\n\t\treturn newValue\n\tcase token.DECREMENT:\n\t\ttargetValue := target.resolve()\n\t\tif node.postfix {\n\t\t\t// Postfix--\n\t\t\toldValue := targetValue.float64()\n\t\t\tnewValue := float64Value(-1 + oldValue)\n\t\t\trt.putValue(target.reference(), newValue)\n\t\t\treturn float64Value(oldValue)\n\t\t}\n\n\t\t// --Prefix\n\t\tnewValue := float64Value(-1 + targetValue.float64())\n\t\trt.putValue(target.reference(), newValue)\n\t\treturn newValue\n\tcase token.VOID:\n\t\ttarget.resolve() // FIXME Side effect?\n\t\treturn Value{}\n\tcase token.DELETE:\n\t\treference := target.reference()\n\t\tif reference == nil {\n\t\t\treturn trueValue\n\t\t}\n\t\treturn boolValue(target.reference().delete())\n\tcase token.TYPEOF:\n\t\ttargetValue := target.resolve()\n\t\tswitch targetValue.kind {\n\t\tcase valueUndefined:\n\t\t\treturn stringValue(\"undefined\")\n\t\tcase valueNull:\n\t\t\treturn stringValue(\"object\")\n\t\tcase valueBoolean:\n\t\t\treturn stringValue(\"boolean\")\n\t\tcase valueNumber:\n\t\t\treturn stringValue(\"number\")\n\t\tcase valueString:\n\t\t\treturn stringValue(\"string\")\n\t\tcase valueObject:\n\t\t\tif targetValue.object().isCall() {\n\t\t\t\treturn stringValue(\"function\")\n\t\t\t}\n\t\t\treturn stringValue(\"object\")\n\t\tdefault:\n\t\t\t// FIXME ?\n\t\t}\n\t}\n\n\tpanic(hereBeDragons())\n}\n\nfunc (rt *runtime) cmplEvaluateNodeVariableExpression(node *nodeVariableExpression) Value {\n\tif node.initializer != nil {\n\t\t// FIXME If reference is nil\n\t\tleft := getIdentifierReference(rt, rt.scope.lexical, node.name, false, at(node.idx))\n\t\tright := rt.cmplEvaluateNodeExpression(node.initializer)\n\t\trightValue := right.resolve()\n\n\t\trt.putValue(left, rightValue)\n\t}\n\treturn stringValue(node.name)\n}\n"
  },
  {
    "path": "cmpl_evaluate_statement.go",
    "content": "package otto\n\nimport (\n\t\"fmt\"\n\tgoruntime \"runtime\"\n\n\t\"github.com/robertkrimen/otto/token\"\n)\n\nfunc (rt *runtime) cmplEvaluateNodeStatement(node nodeStatement) Value {\n\t// Allow interpreter interruption\n\t// If the Interrupt channel is nil, then\n\t// we avoid runtime.Gosched() overhead (if any)\n\t// FIXME: Test this\n\tif rt.otto.Interrupt != nil {\n\t\tgoruntime.Gosched()\n\t\tselect {\n\t\tcase value := <-rt.otto.Interrupt:\n\t\t\tvalue()\n\t\tdefault:\n\t\t}\n\t}\n\n\tswitch node := node.(type) {\n\tcase *nodeBlockStatement:\n\t\tlabels := rt.labels\n\t\trt.labels = nil\n\n\t\tvalue := rt.cmplEvaluateNodeStatementList(node.list)\n\t\tif value.kind == valueResult {\n\t\t\tif value.evaluateBreak(labels) == resultBreak {\n\t\t\t\treturn emptyValue\n\t\t\t}\n\t\t}\n\t\treturn value\n\n\tcase *nodeBranchStatement:\n\t\ttarget := node.label\n\t\tswitch node.branch { // FIXME Maybe node.kind? node.operator?\n\t\tcase token.BREAK:\n\t\t\treturn toValue(newBreakResult(target))\n\t\tcase token.CONTINUE:\n\t\t\treturn toValue(newContinueResult(target))\n\t\tdefault:\n\t\t\tpanic(fmt.Errorf(\"unknown node branch token %T\", node))\n\t\t}\n\n\tcase *nodeDebuggerStatement:\n\t\tif rt.debugger != nil {\n\t\t\trt.debugger(rt.otto)\n\t\t}\n\t\treturn emptyValue // Nothing happens.\n\n\tcase *nodeDoWhileStatement:\n\t\treturn rt.cmplEvaluateNodeDoWhileStatement(node)\n\n\tcase *nodeEmptyStatement:\n\t\treturn emptyValue\n\n\tcase *nodeExpressionStatement:\n\t\treturn rt.cmplEvaluateNodeExpression(node.expression)\n\n\tcase *nodeForInStatement:\n\t\treturn rt.cmplEvaluateNodeForInStatement(node)\n\n\tcase *nodeForStatement:\n\t\treturn rt.cmplEvaluateNodeForStatement(node)\n\n\tcase *nodeIfStatement:\n\t\treturn rt.cmplEvaluateNodeIfStatement(node)\n\n\tcase *nodeLabelledStatement:\n\t\trt.labels = append(rt.labels, node.label)\n\t\tdefer func() {\n\t\t\tif len(rt.labels) > 0 {\n\t\t\t\trt.labels = rt.labels[:len(rt.labels)-1] // Pop the label\n\t\t\t} else {\n\t\t\t\trt.labels = nil\n\t\t\t}\n\t\t}()\n\t\treturn rt.cmplEvaluateNodeStatement(node.statement)\n\n\tcase *nodeReturnStatement:\n\t\tif node.argument != nil {\n\t\t\treturn toValue(newReturnResult(rt.cmplEvaluateNodeExpression(node.argument).resolve()))\n\t\t}\n\t\treturn toValue(newReturnResult(Value{}))\n\n\tcase *nodeSwitchStatement:\n\t\treturn rt.cmplEvaluateNodeSwitchStatement(node)\n\n\tcase *nodeThrowStatement:\n\t\tvalue := rt.cmplEvaluateNodeExpression(node.argument).resolve()\n\t\tpanic(newException(value))\n\n\tcase *nodeTryStatement:\n\t\treturn rt.cmplEvaluateNodeTryStatement(node)\n\n\tcase *nodeVariableStatement:\n\t\t// Variables are already defined, this is initialization only\n\t\tfor _, variable := range node.list {\n\t\t\trt.cmplEvaluateNodeVariableExpression(variable.(*nodeVariableExpression))\n\t\t}\n\t\treturn emptyValue\n\n\tcase *nodeWhileStatement:\n\t\treturn rt.cmplEvaluateModeWhileStatement(node)\n\n\tcase *nodeWithStatement:\n\t\treturn rt.cmplEvaluateNodeWithStatement(node)\n\tdefault:\n\t\tpanic(fmt.Errorf(\"unknown node statement type %T\", node))\n\t}\n}\n\nfunc (rt *runtime) cmplEvaluateNodeStatementList(list []nodeStatement) Value {\n\tvar result Value\n\tfor _, node := range list {\n\t\tvalue := rt.cmplEvaluateNodeStatement(node)\n\t\tswitch value.kind {\n\t\tcase valueResult:\n\t\t\treturn value\n\t\tcase valueEmpty:\n\t\tdefault:\n\t\t\t// We have getValue here to (for example) trigger a\n\t\t\t// ReferenceError (of the not defined variety)\n\t\t\t// Not sure if this is the best way to error out early\n\t\t\t// for such errors or if there is a better way\n\t\t\t// TODO Do we still need this?\n\t\t\tresult = value.resolve()\n\t\t}\n\t}\n\treturn result\n}\n\nfunc (rt *runtime) cmplEvaluateNodeDoWhileStatement(node *nodeDoWhileStatement) Value {\n\tlabels := append(rt.labels, \"\") //nolint:gocritic\n\trt.labels = nil\n\n\ttest := node.test\n\n\tresult := emptyValue\nresultBreak:\n\tfor {\n\t\tfor _, node := range node.body {\n\t\t\tvalue := rt.cmplEvaluateNodeStatement(node)\n\t\t\tswitch value.kind {\n\t\t\tcase valueResult:\n\t\t\t\tswitch value.evaluateBreakContinue(labels) {\n\t\t\t\tcase resultReturn:\n\t\t\t\t\treturn value\n\t\t\t\tcase resultBreak:\n\t\t\t\t\tbreak resultBreak\n\t\t\t\tcase resultContinue:\n\t\t\t\t\tgoto resultContinue\n\t\t\t\t}\n\t\t\tcase valueEmpty:\n\t\t\tdefault:\n\t\t\t\tresult = value\n\t\t\t}\n\t\t}\n\tresultContinue:\n\t\tif !rt.cmplEvaluateNodeExpression(test).resolve().bool() {\n\t\t\t// Stahp: do ... while (false)\n\t\t\tbreak\n\t\t}\n\t}\n\treturn result\n}\n\nfunc (rt *runtime) cmplEvaluateNodeForInStatement(node *nodeForInStatement) Value {\n\tlabels := append(rt.labels, \"\") //nolint:gocritic\n\trt.labels = nil\n\n\tsource := rt.cmplEvaluateNodeExpression(node.source)\n\tsourceValue := source.resolve()\n\n\tswitch sourceValue.kind {\n\tcase valueUndefined, valueNull:\n\t\treturn emptyValue\n\t}\n\n\tsourceObject := rt.toObject(sourceValue)\n\n\tinto := node.into\n\tbody := node.body\n\n\tresult := emptyValue\n\tobj := sourceObject\n\tfor obj != nil {\n\t\tenumerateValue := emptyValue\n\t\tobj.enumerate(false, func(name string) bool {\n\t\t\tinto := rt.cmplEvaluateNodeExpression(into)\n\t\t\t// In the case of: for (var abc in def) ...\n\t\t\tif into.reference() == nil {\n\t\t\t\tidentifier := into.string()\n\t\t\t\t// TODO Should be true or false (strictness) depending on context\n\t\t\t\tinto = toValue(getIdentifierReference(rt, rt.scope.lexical, identifier, false, -1))\n\t\t\t}\n\t\t\trt.putValue(into.reference(), stringValue(name))\n\t\t\tfor _, node := range body {\n\t\t\t\tvalue := rt.cmplEvaluateNodeStatement(node)\n\t\t\t\tswitch value.kind {\n\t\t\t\tcase valueResult:\n\t\t\t\t\tswitch value.evaluateBreakContinue(labels) {\n\t\t\t\t\tcase resultReturn:\n\t\t\t\t\t\tenumerateValue = value\n\t\t\t\t\t\treturn false\n\t\t\t\t\tcase resultBreak:\n\t\t\t\t\t\tobj = nil\n\t\t\t\t\t\treturn false\n\t\t\t\t\tcase resultContinue:\n\t\t\t\t\t\treturn true\n\t\t\t\t\t}\n\t\t\t\tcase valueEmpty:\n\t\t\t\tdefault:\n\t\t\t\t\tenumerateValue = value\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true\n\t\t})\n\t\tif obj == nil {\n\t\t\tbreak\n\t\t}\n\t\tobj = obj.prototype\n\t\tif !enumerateValue.isEmpty() {\n\t\t\tresult = enumerateValue\n\t\t}\n\t}\n\treturn result\n}\n\nfunc (rt *runtime) cmplEvaluateNodeForStatement(node *nodeForStatement) Value {\n\tlabels := append(rt.labels, \"\") //nolint:gocritic\n\trt.labels = nil\n\n\tinitializer := node.initializer\n\ttest := node.test\n\tupdate := node.update\n\tbody := node.body\n\n\tif initializer != nil {\n\t\tinitialResult := rt.cmplEvaluateNodeExpression(initializer)\n\t\tinitialResult.resolve() // Side-effect trigger\n\t}\n\n\tresult := emptyValue\nresultBreak:\n\tfor {\n\t\tif test != nil {\n\t\t\ttestResult := rt.cmplEvaluateNodeExpression(test)\n\t\t\ttestResultValue := testResult.resolve()\n\t\t\tif !testResultValue.bool() {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\t// this is to prevent for cycles with no body from running forever\n\t\tif len(body) == 0 && rt.otto.Interrupt != nil {\n\t\t\tgoruntime.Gosched()\n\t\t\tselect {\n\t\t\tcase value := <-rt.otto.Interrupt:\n\t\t\t\tvalue()\n\t\t\tdefault:\n\t\t\t}\n\t\t}\n\n\t\tfor _, node := range body {\n\t\t\tvalue := rt.cmplEvaluateNodeStatement(node)\n\t\t\tswitch value.kind {\n\t\t\tcase valueResult:\n\t\t\t\tswitch value.evaluateBreakContinue(labels) {\n\t\t\t\tcase resultReturn:\n\t\t\t\t\treturn value\n\t\t\t\tcase resultBreak:\n\t\t\t\t\tbreak resultBreak\n\t\t\t\tcase resultContinue:\n\t\t\t\t\tgoto resultContinue\n\t\t\t\t}\n\t\t\tcase valueEmpty:\n\t\t\tdefault:\n\t\t\t\tresult = value\n\t\t\t}\n\t\t}\n\tresultContinue:\n\t\tif update != nil {\n\t\t\tupdateResult := rt.cmplEvaluateNodeExpression(update)\n\t\t\tupdateResult.resolve() // Side-effect trigger\n\t\t}\n\t}\n\treturn result\n}\n\nfunc (rt *runtime) cmplEvaluateNodeIfStatement(node *nodeIfStatement) Value {\n\ttest := rt.cmplEvaluateNodeExpression(node.test)\n\ttestValue := test.resolve()\n\tif testValue.bool() {\n\t\treturn rt.cmplEvaluateNodeStatement(node.consequent)\n\t} else if node.alternate != nil {\n\t\treturn rt.cmplEvaluateNodeStatement(node.alternate)\n\t}\n\n\treturn emptyValue\n}\n\nfunc (rt *runtime) cmplEvaluateNodeSwitchStatement(node *nodeSwitchStatement) Value {\n\tlabels := append(rt.labels, \"\") //nolint:gocritic\n\trt.labels = nil\n\n\tdiscriminantResult := rt.cmplEvaluateNodeExpression(node.discriminant)\n\ttarget := node.defaultIdx\n\n\tfor index, clause := range node.body {\n\t\ttest := clause.test\n\t\tif test != nil {\n\t\t\tif rt.calculateComparison(token.STRICT_EQUAL, discriminantResult, rt.cmplEvaluateNodeExpression(test)) {\n\t\t\t\ttarget = index\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\n\tresult := emptyValue\n\tif target != -1 {\n\t\tfor _, clause := range node.body[target:] {\n\t\t\tfor _, statement := range clause.consequent {\n\t\t\t\tvalue := rt.cmplEvaluateNodeStatement(statement)\n\t\t\t\tswitch value.kind {\n\t\t\t\tcase valueResult:\n\t\t\t\t\tswitch value.evaluateBreak(labels) {\n\t\t\t\t\tcase resultReturn:\n\t\t\t\t\t\treturn value\n\t\t\t\t\tcase resultBreak:\n\t\t\t\t\t\treturn emptyValue\n\t\t\t\t\t}\n\t\t\t\tcase valueEmpty:\n\t\t\t\tdefault:\n\t\t\t\t\tresult = value\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn result\n}\n\nfunc (rt *runtime) cmplEvaluateNodeTryStatement(node *nodeTryStatement) Value {\n\ttryCatchValue, exep := rt.tryCatchEvaluate(func() Value {\n\t\treturn rt.cmplEvaluateNodeStatement(node.body)\n\t})\n\n\tif exep && node.catch != nil {\n\t\touter := rt.scope.lexical\n\t\trt.scope.lexical = rt.newDeclarationStash(outer)\n\t\tdefer func() {\n\t\t\trt.scope.lexical = outer\n\t\t}()\n\t\t// TODO If necessary, convert TypeError<runtime> => TypeError\n\t\t// That, is, such errors can be thrown despite not being JavaScript \"native\"\n\t\t// strict = false\n\t\trt.scope.lexical.setValue(node.catch.parameter, tryCatchValue, false)\n\n\t\t// FIXME node.CatchParameter\n\t\t// FIXME node.Catch\n\t\ttryCatchValue, exep = rt.tryCatchEvaluate(func() Value {\n\t\t\treturn rt.cmplEvaluateNodeStatement(node.catch.body)\n\t\t})\n\t}\n\n\tif node.finally != nil {\n\t\tfinallyValue := rt.cmplEvaluateNodeStatement(node.finally)\n\t\tif finallyValue.kind == valueResult {\n\t\t\treturn finallyValue\n\t\t}\n\t}\n\n\tif exep {\n\t\tpanic(newException(tryCatchValue))\n\t}\n\n\treturn tryCatchValue\n}\n\nfunc (rt *runtime) cmplEvaluateModeWhileStatement(node *nodeWhileStatement) Value {\n\ttest := node.test\n\tbody := node.body\n\tlabels := append(rt.labels, \"\") //nolint:gocritic\n\trt.labels = nil\n\n\tresult := emptyValue\nresultBreakContinue:\n\tfor {\n\t\tif !rt.cmplEvaluateNodeExpression(test).resolve().bool() {\n\t\t\t// Stahp: while (false) ...\n\t\t\tbreak\n\t\t}\n\t\tfor _, node := range body {\n\t\t\tvalue := rt.cmplEvaluateNodeStatement(node)\n\t\t\tswitch value.kind {\n\t\t\tcase valueResult:\n\t\t\t\tswitch value.evaluateBreakContinue(labels) {\n\t\t\t\tcase resultReturn:\n\t\t\t\t\treturn value\n\t\t\t\tcase resultBreak:\n\t\t\t\t\tbreak resultBreakContinue\n\t\t\t\tcase resultContinue:\n\t\t\t\t\tcontinue resultBreakContinue\n\t\t\t\t}\n\t\t\tcase valueEmpty:\n\t\t\tdefault:\n\t\t\t\tresult = value\n\t\t\t}\n\t\t}\n\t}\n\treturn result\n}\n\nfunc (rt *runtime) cmplEvaluateNodeWithStatement(node *nodeWithStatement) Value {\n\tobj := rt.cmplEvaluateNodeExpression(node.object)\n\touter := rt.scope.lexical\n\tlexical := rt.newObjectStash(rt.toObject(obj.resolve()), outer)\n\trt.scope.lexical = lexical\n\tdefer func() {\n\t\trt.scope.lexical = outer\n\t}()\n\n\treturn rt.cmplEvaluateNodeStatement(node.body)\n}\n"
  },
  {
    "path": "cmpl_parse.go",
    "content": "package otto\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/robertkrimen/otto/ast\"\n\t\"github.com/robertkrimen/otto/file\"\n\t\"github.com/robertkrimen/otto/token\"\n)\n\nvar (\n\ttrueLiteral    = &nodeLiteral{value: boolValue(true)}\n\tfalseLiteral   = &nodeLiteral{value: boolValue(false)}\n\tnullLiteral    = &nodeLiteral{value: nullValue}\n\temptyStatement = &nodeEmptyStatement{}\n)\n\nfunc (cmpl *compiler) parseExpression(expr ast.Expression) nodeExpression {\n\tif expr == nil {\n\t\treturn nil\n\t}\n\n\tswitch expr := expr.(type) {\n\tcase *ast.ArrayLiteral:\n\t\tout := &nodeArrayLiteral{\n\t\t\tvalue: make([]nodeExpression, len(expr.Value)),\n\t\t}\n\t\tfor i, value := range expr.Value {\n\t\t\tout.value[i] = cmpl.parseExpression(value)\n\t\t}\n\t\treturn out\n\n\tcase *ast.AssignExpression:\n\t\treturn &nodeAssignExpression{\n\t\t\toperator: expr.Operator,\n\t\t\tleft:     cmpl.parseExpression(expr.Left),\n\t\t\tright:    cmpl.parseExpression(expr.Right),\n\t\t}\n\n\tcase *ast.BinaryExpression:\n\t\treturn &nodeBinaryExpression{\n\t\t\toperator:   expr.Operator,\n\t\t\tleft:       cmpl.parseExpression(expr.Left),\n\t\t\tright:      cmpl.parseExpression(expr.Right),\n\t\t\tcomparison: expr.Comparison,\n\t\t}\n\n\tcase *ast.BooleanLiteral:\n\t\tif expr.Value {\n\t\t\treturn trueLiteral\n\t\t}\n\t\treturn falseLiteral\n\n\tcase *ast.BracketExpression:\n\t\treturn &nodeBracketExpression{\n\t\t\tidx:    expr.Left.Idx0(),\n\t\t\tleft:   cmpl.parseExpression(expr.Left),\n\t\t\tmember: cmpl.parseExpression(expr.Member),\n\t\t}\n\n\tcase *ast.CallExpression:\n\t\tout := &nodeCallExpression{\n\t\t\tcallee:       cmpl.parseExpression(expr.Callee),\n\t\t\targumentList: make([]nodeExpression, len(expr.ArgumentList)),\n\t\t}\n\t\tfor i, value := range expr.ArgumentList {\n\t\t\tout.argumentList[i] = cmpl.parseExpression(value)\n\t\t}\n\t\treturn out\n\n\tcase *ast.ConditionalExpression:\n\t\treturn &nodeConditionalExpression{\n\t\t\ttest:       cmpl.parseExpression(expr.Test),\n\t\t\tconsequent: cmpl.parseExpression(expr.Consequent),\n\t\t\talternate:  cmpl.parseExpression(expr.Alternate),\n\t\t}\n\n\tcase *ast.DotExpression:\n\t\treturn &nodeDotExpression{\n\t\t\tidx:        expr.Left.Idx0(),\n\t\t\tleft:       cmpl.parseExpression(expr.Left),\n\t\t\tidentifier: expr.Identifier.Name,\n\t\t}\n\n\tcase *ast.EmptyExpression:\n\t\treturn nil\n\n\tcase *ast.FunctionLiteral:\n\t\tname := \"\"\n\t\tif expr.Name != nil {\n\t\t\tname = expr.Name.Name\n\t\t}\n\t\tout := &nodeFunctionLiteral{\n\t\t\tname:   name,\n\t\t\tbody:   cmpl.parseStatement(expr.Body),\n\t\t\tsource: expr.Source,\n\t\t\tfile:   cmpl.file,\n\t\t}\n\t\tif expr.ParameterList != nil {\n\t\t\tlist := expr.ParameterList.List\n\t\t\tout.parameterList = make([]string, len(list))\n\t\t\tfor i, value := range list {\n\t\t\t\tout.parameterList[i] = value.Name\n\t\t\t}\n\t\t}\n\t\tfor _, value := range expr.DeclarationList {\n\t\t\tswitch value := value.(type) {\n\t\t\tcase *ast.FunctionDeclaration:\n\t\t\t\tout.functionList = append(out.functionList, cmpl.parseExpression(value.Function).(*nodeFunctionLiteral))\n\t\t\tcase *ast.VariableDeclaration:\n\t\t\t\tfor _, value := range value.List {\n\t\t\t\t\tout.varList = append(out.varList, value.Name)\n\t\t\t\t}\n\t\t\tdefault:\n\t\t\t\tpanic(fmt.Sprintf(\"parse expression unknown function declaration type %T\", value))\n\t\t\t}\n\t\t}\n\t\treturn out\n\n\tcase *ast.Identifier:\n\t\treturn &nodeIdentifier{\n\t\t\tidx:  expr.Idx,\n\t\t\tname: expr.Name,\n\t\t}\n\n\tcase *ast.NewExpression:\n\t\tout := &nodeNewExpression{\n\t\t\tcallee:       cmpl.parseExpression(expr.Callee),\n\t\t\targumentList: make([]nodeExpression, len(expr.ArgumentList)),\n\t\t}\n\t\tfor i, value := range expr.ArgumentList {\n\t\t\tout.argumentList[i] = cmpl.parseExpression(value)\n\t\t}\n\t\treturn out\n\n\tcase *ast.NullLiteral:\n\t\treturn nullLiteral\n\n\tcase *ast.NumberLiteral:\n\t\treturn &nodeLiteral{\n\t\t\tvalue: toValue(expr.Value),\n\t\t}\n\n\tcase *ast.ObjectLiteral:\n\t\tout := &nodeObjectLiteral{\n\t\t\tvalue: make([]nodeProperty, len(expr.Value)),\n\t\t}\n\t\tfor i, value := range expr.Value {\n\t\t\tout.value[i] = nodeProperty{\n\t\t\t\tkey:   value.Key,\n\t\t\t\tkind:  value.Kind,\n\t\t\t\tvalue: cmpl.parseExpression(value.Value),\n\t\t\t}\n\t\t}\n\t\treturn out\n\n\tcase *ast.RegExpLiteral:\n\t\treturn &nodeRegExpLiteral{\n\t\t\tflags:   expr.Flags,\n\t\t\tpattern: expr.Pattern,\n\t\t}\n\n\tcase *ast.SequenceExpression:\n\t\tout := &nodeSequenceExpression{\n\t\t\tsequence: make([]nodeExpression, len(expr.Sequence)),\n\t\t}\n\t\tfor i, value := range expr.Sequence {\n\t\t\tout.sequence[i] = cmpl.parseExpression(value)\n\t\t}\n\t\treturn out\n\n\tcase *ast.StringLiteral:\n\t\treturn &nodeLiteral{\n\t\t\tvalue: stringValue(expr.Value),\n\t\t}\n\n\tcase *ast.ThisExpression:\n\t\treturn &nodeThisExpression{}\n\n\tcase *ast.UnaryExpression:\n\t\treturn &nodeUnaryExpression{\n\t\t\toperator: expr.Operator,\n\t\t\toperand:  cmpl.parseExpression(expr.Operand),\n\t\t\tpostfix:  expr.Postfix,\n\t\t}\n\n\tcase *ast.VariableExpression:\n\t\treturn &nodeVariableExpression{\n\t\t\tidx:         expr.Idx0(),\n\t\t\tname:        expr.Name,\n\t\t\tinitializer: cmpl.parseExpression(expr.Initializer),\n\t\t}\n\tdefault:\n\t\tpanic(fmt.Errorf(\"parse expression unknown node type %T\", expr))\n\t}\n}\n\nfunc (cmpl *compiler) parseStatement(stmt ast.Statement) nodeStatement {\n\tif stmt == nil {\n\t\treturn nil\n\t}\n\n\tswitch stmt := stmt.(type) {\n\tcase *ast.BlockStatement:\n\t\tout := &nodeBlockStatement{\n\t\t\tlist: make([]nodeStatement, len(stmt.List)),\n\t\t}\n\t\tfor i, value := range stmt.List {\n\t\t\tout.list[i] = cmpl.parseStatement(value)\n\t\t}\n\t\treturn out\n\n\tcase *ast.BranchStatement:\n\t\tout := &nodeBranchStatement{\n\t\t\tbranch: stmt.Token,\n\t\t}\n\t\tif stmt.Label != nil {\n\t\t\tout.label = stmt.Label.Name\n\t\t}\n\t\treturn out\n\n\tcase *ast.DebuggerStatement:\n\t\treturn &nodeDebuggerStatement{}\n\n\tcase *ast.DoWhileStatement:\n\t\tout := &nodeDoWhileStatement{\n\t\t\ttest: cmpl.parseExpression(stmt.Test),\n\t\t}\n\t\tbody := cmpl.parseStatement(stmt.Body)\n\t\tif block, ok := body.(*nodeBlockStatement); ok {\n\t\t\tout.body = block.list\n\t\t} else {\n\t\t\tout.body = append(out.body, body)\n\t\t}\n\t\treturn out\n\n\tcase *ast.EmptyStatement:\n\t\treturn emptyStatement\n\n\tcase *ast.ExpressionStatement:\n\t\treturn &nodeExpressionStatement{\n\t\t\texpression: cmpl.parseExpression(stmt.Expression),\n\t\t}\n\n\tcase *ast.ForInStatement:\n\t\tout := &nodeForInStatement{\n\t\t\tinto:   cmpl.parseExpression(stmt.Into),\n\t\t\tsource: cmpl.parseExpression(stmt.Source),\n\t\t}\n\t\tbody := cmpl.parseStatement(stmt.Body)\n\t\tif block, ok := body.(*nodeBlockStatement); ok {\n\t\t\tout.body = block.list\n\t\t} else {\n\t\t\tout.body = append(out.body, body)\n\t\t}\n\t\treturn out\n\n\tcase *ast.ForStatement:\n\t\tout := &nodeForStatement{\n\t\t\tinitializer: cmpl.parseExpression(stmt.Initializer),\n\t\t\tupdate:      cmpl.parseExpression(stmt.Update),\n\t\t\ttest:        cmpl.parseExpression(stmt.Test),\n\t\t}\n\t\tbody := cmpl.parseStatement(stmt.Body)\n\t\tif block, ok := body.(*nodeBlockStatement); ok {\n\t\t\tout.body = block.list\n\t\t} else {\n\t\t\tout.body = append(out.body, body)\n\t\t}\n\t\treturn out\n\n\tcase *ast.FunctionStatement:\n\t\treturn emptyStatement\n\n\tcase *ast.IfStatement:\n\t\treturn &nodeIfStatement{\n\t\t\ttest:       cmpl.parseExpression(stmt.Test),\n\t\t\tconsequent: cmpl.parseStatement(stmt.Consequent),\n\t\t\talternate:  cmpl.parseStatement(stmt.Alternate),\n\t\t}\n\n\tcase *ast.LabelledStatement:\n\t\treturn &nodeLabelledStatement{\n\t\t\tlabel:     stmt.Label.Name,\n\t\t\tstatement: cmpl.parseStatement(stmt.Statement),\n\t\t}\n\n\tcase *ast.ReturnStatement:\n\t\treturn &nodeReturnStatement{\n\t\t\targument: cmpl.parseExpression(stmt.Argument),\n\t\t}\n\n\tcase *ast.SwitchStatement:\n\t\tout := &nodeSwitchStatement{\n\t\t\tdiscriminant: cmpl.parseExpression(stmt.Discriminant),\n\t\t\tdefaultIdx:   stmt.Default,\n\t\t\tbody:         make([]*nodeCaseStatement, len(stmt.Body)),\n\t\t}\n\t\tfor i, clause := range stmt.Body {\n\t\t\tout.body[i] = &nodeCaseStatement{\n\t\t\t\ttest:       cmpl.parseExpression(clause.Test),\n\t\t\t\tconsequent: make([]nodeStatement, len(clause.Consequent)),\n\t\t\t}\n\t\t\tfor j, value := range clause.Consequent {\n\t\t\t\tout.body[i].consequent[j] = cmpl.parseStatement(value)\n\t\t\t}\n\t\t}\n\t\treturn out\n\n\tcase *ast.ThrowStatement:\n\t\treturn &nodeThrowStatement{\n\t\t\targument: cmpl.parseExpression(stmt.Argument),\n\t\t}\n\n\tcase *ast.TryStatement:\n\t\tout := &nodeTryStatement{\n\t\t\tbody:    cmpl.parseStatement(stmt.Body),\n\t\t\tfinally: cmpl.parseStatement(stmt.Finally),\n\t\t}\n\t\tif stmt.Catch != nil {\n\t\t\tout.catch = &nodeCatchStatement{\n\t\t\t\tparameter: stmt.Catch.Parameter.Name,\n\t\t\t\tbody:      cmpl.parseStatement(stmt.Catch.Body),\n\t\t\t}\n\t\t}\n\t\treturn out\n\n\tcase *ast.VariableStatement:\n\t\tout := &nodeVariableStatement{\n\t\t\tlist: make([]nodeExpression, len(stmt.List)),\n\t\t}\n\t\tfor i, value := range stmt.List {\n\t\t\tout.list[i] = cmpl.parseExpression(value)\n\t\t}\n\t\treturn out\n\n\tcase *ast.WhileStatement:\n\t\tout := &nodeWhileStatement{\n\t\t\ttest: cmpl.parseExpression(stmt.Test),\n\t\t}\n\t\tbody := cmpl.parseStatement(stmt.Body)\n\t\tif block, ok := body.(*nodeBlockStatement); ok {\n\t\t\tout.body = block.list\n\t\t} else {\n\t\t\tout.body = append(out.body, body)\n\t\t}\n\t\treturn out\n\n\tcase *ast.WithStatement:\n\t\treturn &nodeWithStatement{\n\t\t\tobject: cmpl.parseExpression(stmt.Object),\n\t\t\tbody:   cmpl.parseStatement(stmt.Body),\n\t\t}\n\tdefault:\n\t\tpanic(fmt.Sprintf(\"parse statement: unknown type %T\", stmt))\n\t}\n}\n\nfunc cmplParse(in *ast.Program) *nodeProgram {\n\tcmpl := compiler{\n\t\tprogram: in,\n\t}\n\tif cmpl.program != nil {\n\t\tcmpl.file = cmpl.program.File\n\t}\n\n\treturn cmpl.parse()\n}\n\nfunc (cmpl *compiler) parse() *nodeProgram {\n\tout := &nodeProgram{\n\t\tbody: make([]nodeStatement, len(cmpl.program.Body)),\n\t\tfile: cmpl.program.File,\n\t}\n\tfor i, value := range cmpl.program.Body {\n\t\tout.body[i] = cmpl.parseStatement(value)\n\t}\n\tfor _, value := range cmpl.program.DeclarationList {\n\t\tswitch value := value.(type) {\n\t\tcase *ast.FunctionDeclaration:\n\t\t\tout.functionList = append(out.functionList, cmpl.parseExpression(value.Function).(*nodeFunctionLiteral))\n\t\tcase *ast.VariableDeclaration:\n\t\t\tfor _, value := range value.List {\n\t\t\t\tout.varList = append(out.varList, value.Name)\n\t\t\t}\n\t\tdefault:\n\t\t\tpanic(fmt.Sprintf(\"Here be dragons: cmpl.parseProgram.DeclarationList(%T)\", value))\n\t\t}\n\t}\n\treturn out\n}\n\ntype nodeProgram struct {\n\tfile         *file.File\n\tbody         []nodeStatement\n\tvarList      []string\n\tfunctionList []*nodeFunctionLiteral\n}\n\ntype node interface{}\n\ntype (\n\tnodeExpression interface {\n\t\tnode\n\t\texpressionNode()\n\t}\n\n\tnodeArrayLiteral struct {\n\t\tvalue []nodeExpression\n\t}\n\n\tnodeAssignExpression struct {\n\t\tleft     nodeExpression\n\t\tright    nodeExpression\n\t\toperator token.Token\n\t}\n\n\tnodeBinaryExpression struct {\n\t\tleft       nodeExpression\n\t\tright      nodeExpression\n\t\toperator   token.Token\n\t\tcomparison bool\n\t}\n\n\tnodeBracketExpression struct {\n\t\tleft   nodeExpression\n\t\tmember nodeExpression\n\t\tidx    file.Idx\n\t}\n\n\tnodeCallExpression struct {\n\t\tcallee       nodeExpression\n\t\targumentList []nodeExpression\n\t}\n\n\tnodeConditionalExpression struct {\n\t\ttest       nodeExpression\n\t\tconsequent nodeExpression\n\t\talternate  nodeExpression\n\t}\n\n\tnodeDotExpression struct {\n\t\tleft       nodeExpression\n\t\tidentifier string\n\t\tidx        file.Idx\n\t}\n\n\tnodeFunctionLiteral struct {\n\t\tbody          nodeStatement\n\t\tfile          *file.File\n\t\tname          string\n\t\tsource        string\n\t\tparameterList []string\n\t\tvarList       []string\n\t\tfunctionList  []*nodeFunctionLiteral\n\t}\n\n\tnodeIdentifier struct {\n\t\tname string\n\t\tidx  file.Idx\n\t}\n\n\tnodeLiteral struct {\n\t\tvalue Value\n\t}\n\n\tnodeNewExpression struct {\n\t\tcallee       nodeExpression\n\t\targumentList []nodeExpression\n\t}\n\n\tnodeObjectLiteral struct {\n\t\tvalue []nodeProperty\n\t}\n\n\tnodeProperty struct {\n\t\tvalue nodeExpression\n\t\tkey   string\n\t\tkind  string\n\t}\n\n\tnodeRegExpLiteral struct {\n\t\tflags   string\n\t\tpattern string // Value?\n\t}\n\n\tnodeSequenceExpression struct {\n\t\tsequence []nodeExpression\n\t}\n\n\tnodeThisExpression struct{}\n\n\tnodeUnaryExpression struct {\n\t\toperand  nodeExpression\n\t\toperator token.Token\n\t\tpostfix  bool\n\t}\n\n\tnodeVariableExpression struct {\n\t\tinitializer nodeExpression\n\t\tname        string\n\t\tidx         file.Idx\n\t}\n)\n\ntype (\n\tnodeStatement interface {\n\t\tnode\n\t\tstatementNode()\n\t}\n\n\tnodeBlockStatement struct {\n\t\tlist []nodeStatement\n\t}\n\n\tnodeBranchStatement struct {\n\t\tlabel  string\n\t\tbranch token.Token\n\t}\n\n\tnodeCaseStatement struct {\n\t\ttest       nodeExpression\n\t\tconsequent []nodeStatement\n\t}\n\n\tnodeCatchStatement struct {\n\t\tbody      nodeStatement\n\t\tparameter string\n\t}\n\n\tnodeDebuggerStatement struct{}\n\n\tnodeDoWhileStatement struct {\n\t\ttest nodeExpression\n\t\tbody []nodeStatement\n\t}\n\n\tnodeEmptyStatement struct{}\n\n\tnodeExpressionStatement struct {\n\t\texpression nodeExpression\n\t}\n\n\tnodeForInStatement struct {\n\t\tinto   nodeExpression\n\t\tsource nodeExpression\n\t\tbody   []nodeStatement\n\t}\n\n\tnodeForStatement struct {\n\t\tinitializer nodeExpression\n\t\tupdate      nodeExpression\n\t\ttest        nodeExpression\n\t\tbody        []nodeStatement\n\t}\n\n\tnodeIfStatement struct {\n\t\ttest       nodeExpression\n\t\tconsequent nodeStatement\n\t\talternate  nodeStatement\n\t}\n\n\tnodeLabelledStatement struct {\n\t\tstatement nodeStatement\n\t\tlabel     string\n\t}\n\n\tnodeReturnStatement struct {\n\t\targument nodeExpression\n\t}\n\n\tnodeSwitchStatement struct {\n\t\tdiscriminant nodeExpression\n\t\tbody         []*nodeCaseStatement\n\t\tdefaultIdx   int\n\t}\n\n\tnodeThrowStatement struct {\n\t\targument nodeExpression\n\t}\n\n\tnodeTryStatement struct {\n\t\tbody    nodeStatement\n\t\tcatch   *nodeCatchStatement\n\t\tfinally nodeStatement\n\t}\n\n\tnodeVariableStatement struct {\n\t\tlist []nodeExpression\n\t}\n\n\tnodeWhileStatement struct {\n\t\ttest nodeExpression\n\t\tbody []nodeStatement\n\t}\n\n\tnodeWithStatement struct {\n\t\tobject nodeExpression\n\t\tbody   nodeStatement\n\t}\n)\n\n// expressionNode.\nfunc (*nodeArrayLiteral) expressionNode()          {}\nfunc (*nodeAssignExpression) expressionNode()      {}\nfunc (*nodeBinaryExpression) expressionNode()      {}\nfunc (*nodeBracketExpression) expressionNode()     {}\nfunc (*nodeCallExpression) expressionNode()        {}\nfunc (*nodeConditionalExpression) expressionNode() {}\nfunc (*nodeDotExpression) expressionNode()         {}\nfunc (*nodeFunctionLiteral) expressionNode()       {}\nfunc (*nodeIdentifier) expressionNode()            {}\nfunc (*nodeLiteral) expressionNode()               {}\nfunc (*nodeNewExpression) expressionNode()         {}\nfunc (*nodeObjectLiteral) expressionNode()         {}\nfunc (*nodeRegExpLiteral) expressionNode()         {}\nfunc (*nodeSequenceExpression) expressionNode()    {}\nfunc (*nodeThisExpression) expressionNode()        {}\nfunc (*nodeUnaryExpression) expressionNode()       {}\nfunc (*nodeVariableExpression) expressionNode()    {}\n\n// statementNode\n\nfunc (*nodeBlockStatement) statementNode()      {}\nfunc (*nodeBranchStatement) statementNode()     {}\nfunc (*nodeCaseStatement) statementNode()       {}\nfunc (*nodeCatchStatement) statementNode()      {}\nfunc (*nodeDebuggerStatement) statementNode()   {}\nfunc (*nodeDoWhileStatement) statementNode()    {}\nfunc (*nodeEmptyStatement) statementNode()      {}\nfunc (*nodeExpressionStatement) statementNode() {}\nfunc (*nodeForInStatement) statementNode()      {}\nfunc (*nodeForStatement) statementNode()        {}\nfunc (*nodeIfStatement) statementNode()         {}\nfunc (*nodeLabelledStatement) statementNode()   {}\nfunc (*nodeReturnStatement) statementNode()     {}\nfunc (*nodeSwitchStatement) statementNode()     {}\nfunc (*nodeThrowStatement) statementNode()      {}\nfunc (*nodeTryStatement) statementNode()        {}\nfunc (*nodeVariableStatement) statementNode()   {}\nfunc (*nodeWhileStatement) statementNode()      {}\nfunc (*nodeWithStatement) statementNode()       {}\n"
  },
  {
    "path": "cmpl_test.go",
    "content": "package otto\n\nimport (\n\t\"testing\"\n\n\t\"github.com/robertkrimen/otto/parser\"\n)\n\nfunc Test_cmpl(t *testing.T) {\n\ttt(t, func() {\n\t\tvm := New()\n\n\t\ttest := func(src string, expect ...interface{}) {\n\t\t\tprogram, err := parser.ParseFile(nil, \"\", src, 0)\n\t\t\tis(err, nil)\n\t\t\t{\n\t\t\t\tprogram := cmplParse(program)\n\t\t\t\tvalue := vm.runtime.cmplEvaluateNodeProgram(program, false)\n\t\t\t\tif len(expect) > 0 {\n\t\t\t\t\tis(value, expect[0])\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ttest(``, Value{})\n\n\t\ttest(`var abc = 1; abc;`, 1)\n\n\t\ttest(`var abc = 1 + 1; abc;`, 2)\n\n\t\ttest(`1 + 2;`, 3)\n\t})\n}\n\nfunc TestParse_cmpl(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := func(src string) {\n\t\t\tprogram, err := parser.ParseFile(nil, \"\", src, 0)\n\t\t\tis(err, nil)\n\t\t\tis(cmplParse(program), \"!=\", nil)\n\t\t}\n\n\t\ttest(``)\n\n\t\ttest(`var abc = 1; abc;`)\n\n\t\ttest(`\n            function abc() {\n                return;\n            }\n        `)\n\t})\n}\n"
  },
  {
    "path": "console.go",
    "content": "package otto\n\nimport (\n\t\"fmt\"\n\t\"os\"\n\t\"strings\"\n)\n\nfunc formatForConsole(argumentList []Value) string {\n\toutput := []string{}\n\tfor _, argument := range argumentList {\n\t\toutput = append(output, fmt.Sprintf(\"%v\", argument))\n\t}\n\treturn strings.Join(output, \" \")\n}\n\nfunc builtinConsoleLog(call FunctionCall) Value {\n\tfmt.Fprintln(os.Stdout, formatForConsole(call.ArgumentList)) //nolint:errcheck // Nothing we can do if this fails.\n\treturn Value{}\n}\n\nfunc builtinConsoleError(call FunctionCall) Value {\n\tfmt.Fprintln(os.Stdout, formatForConsole(call.ArgumentList)) //nolint:errcheck // Nothing we can do if this fails.\n\treturn Value{}\n}\n\n// Nothing happens.\nfunc builtinConsoleDir(call FunctionCall) Value {\n\treturn Value{}\n}\n\nfunc builtinConsoleTime(call FunctionCall) Value {\n\treturn Value{}\n}\n\nfunc builtinConsoleTimeEnd(call FunctionCall) Value {\n\treturn Value{}\n}\n\nfunc builtinConsoleTrace(call FunctionCall) Value {\n\treturn Value{}\n}\n\nfunc builtinConsoleAssert(call FunctionCall) Value {\n\treturn Value{}\n}\n"
  },
  {
    "path": "consts.go",
    "content": "package otto\n\nconst (\n\t// Common classes.\n\tclassStringName   = \"String\"\n\tclassGoArrayName  = \"GoArray\"\n\tclassGoSliceName  = \"GoSlice\"\n\tclassNumberName   = \"Number\"\n\tclassDateName     = \"Date\"\n\tclassArrayName    = \"Array\"\n\tclassFunctionName = \"Function\"\n\tclassObjectName   = \"Object\"\n\tclassRegExpName   = \"RegExp\"\n\tclassBooleanName  = \"Boolean\"\n\tclassMathName     = \"Math\"\n\tclassJSONName     = \"JSON\"\n\n\t// Error classes.\n\tclassErrorName          = \"Error\"\n\tclassEvalErrorName      = \"EvalError\"\n\tclassTypeErrorName      = \"TypeError\"\n\tclassRangeErrorName     = \"RangeError\"\n\tclassReferenceErrorName = \"ReferenceError\"\n\tclassSyntaxErrorName    = \"SyntaxError\"\n\tclassURIErrorName       = \"URIError\"\n\n\t// Common properties.\n\tpropertyName        = \"name\"\n\tpropertyLength      = \"length\"\n\tpropertyPrototype   = \"prototype\"\n\tpropertyConstructor = \"constructor\"\n\n\t// Common methods.\n\tmethodToString = \"toString\"\n)\n"
  },
  {
    "path": "date_test.go",
    "content": "package otto\n\nimport (\n\t\"math\"\n\t\"testing\"\n\t\"time\"\n)\n\nfunc mockTimeLocal(location *time.Location) func() {\n\tlocal := time.Local\n\ttime.Local = location\n\treturn func() {\n\t\ttime.Local = local\n\t}\n}\n\n// Passing or failing should not be dependent on what time zone we're in.\nfunc mockUTC() func() {\n\treturn mockTimeLocal(time.UTC)\n}\n\nfunc TestDate(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\tdefer mockUTC()()\n\n\t\ttime0 := time.Unix(1348616313, 47*1000*1000).Local()\n\n\t\ttest(`Date`, \"function Date() { [native code] }\")\n\t\ttest(`new Date(0).toUTCString()`, \"Thu, 01 Jan 1970 00:00:00 GMT\")\n\t\ttest(`new Date(0).toGMTString()`, \"Thu, 01 Jan 1970 00:00:00 GMT\")\n\t\ttest(`new Date('2023').toGMTString()`, \"Sun, 01 Jan 2023 00:00:00 GMT\")\n\t\ttest(`new Date('2023/02').toGMTString()`, \"Wed, 01 Feb 2023 00:00:00 GMT\")\n\t\ttest(`new Date('2023/02/23').toGMTString()`, \"Thu, 23 Feb 2023 00:00:00 GMT\")\n\t\ttest(`new Date('2023/02/23 11:23:57').toGMTString()`, \"Thu, 23 Feb 2023 11:23:57 GMT\")\n\t\tif false {\n\t\t\t// TODO toLocale{Date,Time}String\n\t\t\ttest(`new Date(0).toLocaleString()`, \"\")\n\t\t\ttest(`new Date(0).toLocaleDateString()`, \"\")\n\t\t\ttest(`new Date(0).toLocaleTimeString()`, \"\")\n\t\t}\n\t\ttest(`new Date(1348616313).getTime()`, 1348616313)\n\t\ttest(`new Date(1348616313).toUTCString()`, \"Fri, 16 Jan 1970 14:36:56 GMT\")\n\t\ttest(`abc = new Date(1348616313047); abc.toUTCString()`, \"Tue, 25 Sep 2012 23:38:33 GMT\")\n\t\ttest(`abc.getYear()`, time0.Year()-1900)\n\t\ttest(`abc.getFullYear()`, time0.Year())\n\t\ttest(`abc.getUTCFullYear()`, 2012)\n\t\ttest(`abc.getMonth()`, int(time0.Month())-1) // Remember, the JavaScript month is 0-based\n\t\ttest(`abc.getUTCMonth()`, 8)\n\t\ttest(`abc.getDate()`, time0.Day())\n\t\ttest(`abc.getUTCDate()`, 25)\n\t\ttest(`abc.getDay()`, int(time0.Weekday()))\n\t\ttest(`abc.getUTCDay()`, 2)\n\t\ttest(`abc.getHours()`, time0.Hour())\n\t\ttest(`abc.getUTCHours()`, 23)\n\t\ttest(`abc.getMinutes()`, time0.Minute())\n\t\ttest(`abc.getUTCMinutes()`, 38)\n\t\ttest(`abc.getSeconds()`, time0.Second())\n\t\ttest(`abc.getUTCSeconds()`, 33)\n\t\ttest(`abc.getMilliseconds()`, time0.Nanosecond()/(1000*1000)) // In honor of the 47%\n\t\ttest(`abc.getUTCMilliseconds()`, 47)\n\t\t_, offset := time0.Zone()\n\t\ttest(`abc.getTimezoneOffset()`, offset/-60)\n\n\t\ttest(`new Date(\"Xyzzy\").getTime()`, math.NaN())\n\n\t\ttest(`abc.setFullYear(2011); abc.toUTCString()`, \"Sun, 25 Sep 2011 23:38:33 GMT\")\n\t\ttest(`new Date(12564504e5).toUTCString()`, \"Sun, 25 Oct 2009 06:00:00 GMT\")\n\t\ttest(`new Date(2009, 9, 25).toUTCString()`, \"Sun, 25 Oct 2009 00:00:00 GMT\")\n\t\ttest(`+(new Date(2009, 9, 25))`, int64(1256428800000))\n\n\t\tformat := \"Mon, 2 Jan 2006 15:04:05 MST\"\n\n\t\ttime1 := time.Unix(1256450400, 0)\n\t\ttime0 = time.Date(time1.Year(), time1.Month(), time1.Day(), time1.Hour(), time1.Minute(), time1.Second(), 2001*1000*1000, time1.Location()).In(utcTimeZone)\n\t\ttest(`abc = new Date(12564504e5); abc.setMilliseconds(2001); abc.toUTCString()`, time0.Format(format))\n\n\t\ttime0 = time.Date(time1.Year(), time1.Month(), time1.Day(), time1.Hour(), time1.Minute(), 61, time1.Nanosecond(), time1.Location()).In(utcTimeZone)\n\t\ttest(`abc = new Date(12564504e5); abc.setSeconds(\"61\"); abc.toUTCString()`, time0.Format(format))\n\n\t\ttime0 = time.Date(time1.Year(), time1.Month(), time1.Day(), time1.Hour(), 61, time1.Second(), time1.Nanosecond(), time1.Location()).In(utcTimeZone)\n\t\ttest(`abc = new Date(12564504e5); abc.setMinutes(\"61\"); abc.toUTCString()`, time0.Format(format))\n\n\t\ttime0 = time.Date(time1.Year(), time1.Month(), time1.Day(), 5, time1.Minute(), time1.Second(), time1.Nanosecond(), time1.Location()).In(utcTimeZone)\n\t\ttest(`abc = new Date(12564504e5); abc.setHours(\"5\"); abc.toUTCString()`, time0.Format(format))\n\n\t\ttime0 = time.Date(time1.Year(), time1.Month(), 26, time1.Hour(), time1.Minute(), time1.Second(), time1.Nanosecond(), time1.Location()).In(utcTimeZone)\n\t\ttest(`abc = new Date(12564504e5); abc.setDate(\"26\"); abc.toUTCString()`, time0.Format(format))\n\n\t\ttime0 = time.Date(time1.Year(), 10, time1.Day(), time1.Hour(), time1.Minute(), time1.Second(), time1.Nanosecond(), time1.Location()).In(utcTimeZone)\n\t\ttest(`abc = new Date(12564504e5); abc.setMonth(9); abc.toUTCString()`, time0.Format(format))\n\t\ttest(`abc = new Date(12564504e5); abc.setMonth(\"09\"); abc.toUTCString()`, time0.Format(format))\n\n\t\ttime0 = time.Date(time1.Year(), 11, time1.Day(), time1.Hour(), time1.Minute(), time1.Second(), time1.Nanosecond(), time1.Location()).In(utcTimeZone)\n\t\ttest(`abc = new Date(12564504e5); abc.setMonth(\"10\"); abc.toUTCString()`, time0.Format(format))\n\n\t\ttime0 = time.Date(2010, time1.Month(), time1.Day(), time1.Hour(), time1.Minute(), time1.Second(), time1.Nanosecond(), time1.Location()).In(utcTimeZone)\n\t\ttest(`abc = new Date(12564504e5); abc.setFullYear(2010); abc.toUTCString()`, time0.Format(format))\n\n\t\ttest(`new Date(\"2001-01-01T10:01:02.000\").getTime()`, int64(978343262000))\n\n\t\t// Date()\n\t\ttest(`typeof Date()`, \"string\")\n\t\ttest(`typeof Date(2006, 1, 2)`, \"string\")\n\n\t\ttest(`\n            abc = Object.getOwnPropertyDescriptor(Date, \"parse\");\n            [ abc.value === Date.parse, abc.writable, abc.enumerable, abc.configurable ];\n        `, \"true,true,false,true\")\n\n\t\ttest(`\n            abc = Object.getOwnPropertyDescriptor(Date.prototype, \"toTimeString\");\n            [ abc.value === Date.prototype.toTimeString, abc.writable, abc.enumerable, abc.configurable ];\n        `, \"true,true,false,true\")\n\n\t\ttest(`\n            var abc = Object.getOwnPropertyDescriptor(Date, \"prototype\");\n            [   [ typeof Date.prototype ],\n                [ abc.writable, abc.enumerable, abc.configurable ] ];\n        `, \"object,false,false,false\")\n\t})\n}\n\nfunc TestDate_parse(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\tdefer mockUTC()()\n\n\t\ttest(`Date.parse(\"2001-01-01T10:01:02.000\")`, int64(978343262000))\n\n\t\ttest(`Date.parse(\"2006-01-02T15:04:05.000\")`, int64(1136214245000))\n\n\t\ttest(`Date.parse(\"2006\")`, int64(1136073600000))\n\n\t\ttest(`Date.parse(\"1970-01-16T14:36:56+00:00\")`, 1348616000)\n\n\t\ttest(`Date.parse(\"1970-01-16T14:36:56.313+00:00\")`, 1348616313)\n\n\t\ttest(`Date.parse(\"1970-01-16T14:36:56.000\")`, 1348616000)\n\n\t\ttest(`Date.parse.length`, 1)\n\t})\n}\n\nfunc TestDate_UTC(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\tdefer mockUTC()()\n\n\t\ttest(`Date.UTC(2009, 9, 25)`, int64(1256428800000))\n\n\t\ttest(`Date.UTC.length`, 7)\n\t})\n}\n\nfunc TestDate_now(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\tdefer mockUTC()()\n\n\t\t// FIXME I think this too risky\n\t\ttest(`+(\"\"+Date.now()).substr(0, 10)`, float64(epochToInteger(timeToEpoch(time.Now()))/1000))\n\n\t\ttest(`Date.now() - Date.now(1,2,3) < 24 * 60 * 60`, true)\n\t})\n}\n\nfunc TestDate_toISOString(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\tdefer mockUTC()()\n\n\t\ttest(`new Date(0).toISOString()`, \"1970-01-01T00:00:00.000Z\")\n\t})\n}\n\nfunc TestDate_toJSON(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\tdefer mockUTC()()\n\n\t\ttest(`new Date(0).toJSON()`, \"1970-01-01T00:00:00.000Z\")\n\t})\n}\n\nfunc TestDate_setYear(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\tdefer mockUTC()()\n\n\t\ttest(`new Date(12564504e5).setYear(96)`, int64(846223200000))\n\n\t\ttest(`new Date(12564504e5).setYear(1996)`, int64(846223200000))\n\n\t\ttest(`new Date(12564504e5).setYear(2000)`, int64(972453600000))\n\t})\n}\n\nfunc TestDateDefaultValue(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\tdefer mockUTC()()\n\n\t\ttest(`\n        var date = new Date();\n        date + 0 === date.toString() + \"0\";\n    `, true)\n\t})\n}\n\nfunc TestDate_April1978(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\tdefer mockUTC()()\n\n\t\ttest(`\n            var abc = new Date(1978,3);\n            [ abc.getYear(), abc.getMonth(), abc.valueOf() ];\n        `, \"78,3,260236800000\")\n\t})\n}\n\nfunc TestDate_setMilliseconds(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\tdefer mockUTC()()\n\n\t\ttest(`\n            abc = new Date();\n            def = abc.setMilliseconds();\n            [ abc, def ];\n        `, \"Invalid Date,NaN\")\n\t})\n}\n\nfunc TestDate_new(t *testing.T) {\n\t// FIXME?\n\t// This is probably incorrect, due to differences in Go date/time handling\n\t// versus ECMA date/time handling, but we'll leave this here for\n\t// future reference\n\n\tif true {\n\t\treturn\n\t}\n\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\tdefer mockUTC()()\n\n\t\ttest(`\n            [\n                new Date(1899, 11).valueOf(),\n                new Date(1899, 12).valueOf(),\n                new Date(1900, 0).valueOf()\n            ]\n        `, \"-2211638400000,-2208960000000,-2208960000000\")\n\t})\n}\n\nfunc TestDateComparison(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\tdefer mockUTC()()\n\n\t\ttest(`\n            var now0 = Date.now();\n            var now1 = (new Date()).toString();\n            [ now0 === now1, Math.abs(now0 - Date.parse(now1)) <= 1000 ];\n        `, \"false,true\")\n\t})\n}\n\nfunc TestDate_setSeconds(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\tdefer mockUTC()()\n\n\t\ttest(`\n            abc = new Date(1980, 10);\n            def = new Date(abc);\n\n            abc.setSeconds(10, 12);\n\n            def.setSeconds(10);\n            def.setMilliseconds(12);\n\n            abc.valueOf() === def.valueOf();\n        `, true)\n\n\t\ttest(`\n            abc = new Date(1980, 10);\n            def = new Date(abc);\n\n            abc.setUTCSeconds(10, 12);\n\n            def.setUTCSeconds(10);\n            def.setUTCMilliseconds(12);\n\n            abc.valueOf() === def.valueOf();\n        `, true)\n\n\t\ttest(`Date.prototype.setSeconds.length`, 2)\n\t\ttest(`Date.prototype.setUTCSeconds.length`, 2)\n\t})\n}\n\nfunc TestDate_setMinutes(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\tdefer mockUTC()()\n\n\t\ttest(`\n            abc = new Date(1980, 10);\n            def = new Date(abc);\n\n            abc.setMinutes(8, 10, 12);\n\n            def.setMinutes(8);\n            def.setSeconds(10);\n            def.setMilliseconds(12);\n\n            abc.valueOf() === def.valueOf();\n        `, true)\n\n\t\ttest(`\n            abc = new Date(1980, 10);\n            def = new Date(abc);\n\n            abc.setUTCMinutes(8, 10, 12);\n\n            def.setUTCMinutes(8);\n            def.setUTCSeconds(10);\n            def.setUTCMilliseconds(12);\n\n            abc.valueOf() === def.valueOf();\n        `, true)\n\n\t\ttest(`Date.prototype.setMinutes.length`, 3)\n\t\ttest(`Date.prototype.setUTCMinutes.length`, 3)\n\t})\n}\n\nfunc TestDate_setHours(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\tdefer mockUTC()()\n\n\t\ttest(`\n            abc = new Date(1980, 10);\n            def = new Date(abc);\n\n            abc.setHours(6, 8, 10, 12);\n\n            def.setHours(6);\n            def.setMinutes(8);\n            def.setSeconds(10);\n            def.setMilliseconds(12);\n\n            abc.valueOf() === def.valueOf();\n        `, true)\n\n\t\ttest(`\n            abc = new Date(1980, 10);\n            def = new Date(abc);\n\n            abc.setUTCHours(6, 8, 10, 12);\n\n            def.setUTCHours(6);\n            def.setUTCMinutes(8);\n            def.setUTCSeconds(10);\n            def.setUTCMilliseconds(12);\n\n            abc.valueOf() === def.valueOf();\n        `, true)\n\n\t\ttest(`Date.prototype.setHours.length`, 4)\n\t\ttest(`Date.prototype.setUTCHours.length`, 4)\n\t})\n}\n\nfunc TestDate_setMonth(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\tdefer mockUTC()()\n\n\t\ttest(`\n            abc = new Date(1980, 10);\n            def = new Date(abc);\n\n            abc.setMonth(6, 8);\n\n            def.setMonth(6);\n            def.setDate(8);\n\n            abc.valueOf() === def.valueOf();\n        `, true)\n\n\t\ttest(`\n            abc = new Date(1980, 10);\n            def = new Date(abc);\n\n            abc.setUTCMonth(6, 8);\n\n            def.setUTCMonth(6);\n            def.setUTCDate(8);\n\n            abc.valueOf() === def.valueOf();\n        `, true)\n\n\t\ttest(`Date.prototype.setMonth.length`, 2)\n\t\ttest(`Date.prototype.setUTCMonth.length`, 2)\n\t})\n}\n\nfunc TestDate_setFullYear(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\tdefer mockUTC()()\n\n\t\ttest(`\n            abc = new Date(1980, 10);\n            def = new Date(abc);\n\n            abc.setFullYear(1981, 6, 8);\n\n            def.setFullYear(1981);\n            def.setMonth(6);\n            def.setDate(8);\n\n            abc.valueOf() === def.valueOf();\n        `, true)\n\n\t\ttest(`\n            abc = new Date(1980, 10);\n            def = new Date(abc);\n\n            abc.setUTCFullYear(1981, 6, 8);\n\n            def.setUTCFullYear(1981);\n            def.setUTCMonth(6);\n            def.setUTCDate(8);\n\n            abc.valueOf() === def.valueOf();\n        `, true)\n\n\t\ttest(`Date.prototype.setFullYear.length`, 3)\n\t\ttest(`Date.prototype.setUTCFullYear.length`, 3)\n\t})\n}\n\nfunc TestDate_setTime(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\tdefer mockUTC()()\n\n\t\ttest(`\n            var abc = new Date(1999, 6, 1);\n            var def = new Date();\n            def.setTime(abc.getTime());\n            [ def, abc.valueOf() == def.valueOf() ];\n        `, \"Thu, 01 Jul 1999 00:00:00 UTC,true\")\n\n\t\ttest(`Date.prototype.setTime.length`, 1)\n\t})\n}\n"
  },
  {
    "path": "dbg/dbg.go",
    "content": "// This file was AUTOMATICALLY GENERATED by dbg-import (smuggol) from github.com/robertkrimen/dbg\n\n/*\nPackage dbg is a println/printf/log-debugging utility library.\n\n\timport (\n\t    Dbg \"github.com/robertkrimen/dbg\"\n\t)\n\n\tdbg, dbgf := Dbg.New()\n\n\tdbg(\"Emit some debug stuff\", []byte{120, 121, 122, 122, 121}, math.Pi)\n\t# \"2013/01/28 16:50:03 Emit some debug stuff [120 121 122 122 121] 3.141592653589793\"\n\n\tdbgf(\"With a %s formatting %.2f\", \"little\", math.Pi)\n\t# \"2013/01/28 16:51:55 With a little formatting (3.14)\"\n\n\tdbgf(\"%/fatal//A fatal debug statement: should not be here\")\n\t# \"A fatal debug statement: should not be here\"\n\t# ...and then, os.Exit(1)\n\n\tdbgf(\"%/panic//Can also panic %s\", \"this\")\n\t# \"Can also panic this\"\n\t# ...as a panic, equivalent to: panic(\"Can also panic this\")\n\n\tdbgf(\"Any %s arguments without a corresponding %%\", \"extra\", \"are treated like arguments to dbg()\")\n\t# \"2013/01/28 17:14:40 Any extra arguments (without a corresponding %) are treated like arguments to dbg()\"\n\n\tdbgf(\"%d %d\", 1, 2, 3, 4, 5)\n\t# \"2013/01/28 17:16:32 Another example: 1 2 3 4 5\"\n\n\tdbgf(\"%@: Include the function name for a little context (via %s)\", \"%@\")\n\t# \"2013... github.com/robertkrimen/dbg.TestSynopsis: Include the function name for a little context (via %@)\"\n\nBy default, dbg uses log (log.Println, log.Printf, log.Panic, etc.) for output.\nHowever, you can also provide your own output destination by invoking dbg.New with\na customization function:\n\n\timport (\n\t    \"bytes\"\n\t    Dbg \"github.com/robertkrimen/dbg\"\n\t    \"os\"\n\t)\n\n\t# dbg to os.Stderr\n\tdbg, dbgf := Dbg.New(func(dbgr *Dbgr) {\n\t    dbgr.SetOutput(os.Stderr)\n\t})\n\n\t# A slightly contrived example:\n\tvar buffer bytes.Buffer\n\tdbg, dbgf := New(func(dbgr *Dbgr) {\n\t    dbgr.SetOutput(&buffer)\n\t})\n*/\npackage dbg\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"os\"\n\t\"regexp\"\n\tgoruntime \"runtime\"\n\t\"strings\"\n\t\"unicode\"\n)\n\ntype _frmt struct {\n\tctl          string\n\tformat       string\n\toperandCount int\n\tpanic        bool\n\tfatal        bool\n\tcheck        bool\n}\n\nvar (\n\tctlTest = regexp.MustCompile(`^\\s*%/`)\n\tctlScan = regexp.MustCompile(`%?/(panic|fatal|check)(?:\\s|$)`)\n)\n\nfunc operandCount(format string) int {\n\tcount := 0\n\tend := len(format)\n\tfor at := 0; at < end; {\n\t\tfor at < end && format[at] != '%' {\n\t\t\tat++\n\t\t}\n\t\tat++\n\t\tif at < end {\n\t\t\tif format[at] != '%' && format[at] != '@' {\n\t\t\t\tcount++\n\t\t\t}\n\t\t\tat++\n\t\t}\n\t}\n\treturn count\n}\n\nfunc parseFormat(format string) (frmt _frmt) {\n\tif ctlTest.MatchString(format) {\n\t\tformat = strings.TrimLeftFunc(format, unicode.IsSpace)\n\t\tindex := strings.Index(format, \"//\")\n\t\tif index != -1 {\n\t\t\tfrmt.ctl = format[0:index]\n\t\t\tformat = format[index+2:] // Skip the second slash via +2 (instead of +1)\n\t\t} else {\n\t\t\tfrmt.ctl = format\n\t\t\tformat = \"\"\n\t\t}\n\t\tfor _, tmp := range ctlScan.FindAllStringSubmatch(frmt.ctl, -1) {\n\t\t\tfor _, value := range tmp[1:] {\n\t\t\t\tswitch value {\n\t\t\t\tcase \"panic\":\n\t\t\t\t\tfrmt.panic = true\n\t\t\t\tcase \"fatal\":\n\t\t\t\t\tfrmt.fatal = true\n\t\t\t\tcase \"check\":\n\t\t\t\t\tfrmt.check = true\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tfrmt.format = format\n\tfrmt.operandCount = operandCount(format)\n\treturn\n}\n\ntype Dbgr struct {\n\temit emit\n}\n\ntype DbgFunction func(values ...interface{})\n\nfunc NewDbgr() *Dbgr {\n\treturn &Dbgr{}\n}\n\n/*\nNew will create and return a pair of debugging functions. You can customize where\nthey output to by passing in an (optional) customization function:\n\n\timport (\n\t    Dbg \"github.com/robertkrimen/dbg\"\n\t    \"os\"\n\t)\n\n\t# dbg to os.Stderr\n\tdbg, dbgf := Dbg.New(func(dbgr *Dbgr) {\n\t    dbgr.SetOutput(os.Stderr)\n\t})\n*/\nfunc New(options ...interface{}) (dbg DbgFunction, dbgf DbgFunction) {\n\tdbgr := NewDbgr()\n\tif len(options) > 0 {\n\t\tif fn, ok := options[0].(func(*Dbgr)); ok {\n\t\t\tfn(dbgr)\n\t\t}\n\t}\n\treturn dbgr.DbgDbgf()\n}\n\nfunc (d Dbgr) Dbg(values ...interface{}) {\n\td.getEmit().emit(_frmt{}, \"\", values...)\n}\n\nfunc (d Dbgr) Dbgf(values ...interface{}) {\n\td.dbgf(values...)\n}\n\nfunc (d Dbgr) DbgDbgf() (dbg DbgFunction, dbgf DbgFunction) {\n\tdbg = func(vl ...interface{}) {\n\t\td.Dbg(vl...)\n\t}\n\tdbgf = func(vl ...interface{}) {\n\t\td.dbgf(vl...)\n\t}\n\treturn dbg, dbgf // Redundant, but...\n}\n\nfunc (d Dbgr) dbgf(values ...interface{}) {\n\tvar frmt _frmt\n\tif len(values) > 0 {\n\t\ttmp := fmt.Sprint(values[0])\n\t\tfrmt = parseFormat(tmp)\n\t\tvalues = values[1:]\n\t}\n\n\tbuf := bytes.Buffer{}\n\tformat := frmt.format\n\tend := len(format)\n\tfor at := 0; at < end; {\n\t\tlast := at\n\t\tfor at < end && format[at] != '%' {\n\t\t\tat++\n\t\t}\n\t\tif at > last {\n\t\t\tbuf.WriteString(format[last:at])\n\t\t}\n\t\tif at >= end {\n\t\t\tbreak\n\t\t}\n\t\t// format[at] == '%'\n\t\tat++\n\t\t// format[at] == ?\n\t\tif format[at] == '@' {\n\t\t\tdepth := 2\n\t\t\tpc, _, _, _ := goruntime.Caller(depth)\n\t\t\tname := goruntime.FuncForPC(pc).Name()\n\t\t\tbuf.WriteString(name)\n\t\t} else {\n\t\t\tbuf.WriteString(format[at-1 : at+1])\n\t\t}\n\t\tat++\n\t}\n\n\t//valuesF := append([]interface{}{}, values[0:frmt.operandCount]...)\n\tvaluesF := values[0:frmt.operandCount]\n\tvaluesDbg := values[frmt.operandCount:]\n\tif len(valuesDbg) > 0 {\n\t\t// Adjust frmt.format:\n\t\t// (%v instead of %s because: frmt.check)\n\t\ttmp := format\n\t\tif len(tmp) > 0 {\n\t\t\tif unicode.IsSpace(rune(tmp[len(tmp)-1])) {\n\t\t\t\tbuf.WriteString(\"%v\")\n\t\t\t} else {\n\t\t\t\tbuf.WriteString(\" %v\")\n\t\t\t}\n\t\t} else if frmt.check {\n\t\t\t// Performing a check, so no output\n\t\t} else {\n\t\t\tbuf.WriteString(\"%v\")\n\t\t}\n\n\t\t// Adjust valuesF:\n\t\tif !frmt.check {\n\t\t\ttmp := []string{}\n\t\t\tfor _, value := range valuesDbg {\n\t\t\t\ttmp = append(tmp, fmt.Sprintf(\"%v\", value))\n\t\t\t}\n\t\t\t// First, make a copy of valuesF, so we avoid overwriting valuesDbg when appending\n\t\t\tvaluesF = append([]interface{}{}, valuesF...)\n\t\t\tvaluesF = append(valuesF, strings.Join(tmp, \" \"))\n\t\t}\n\t}\n\n\tformat = buf.String()\n\tif frmt.check {\n\t\t// We do not actually emit to the log, but panic if\n\t\t// a non-nil value is detected (e.g. a non-nil error)\n\t\tfor _, value := range valuesDbg {\n\t\t\tif value != nil {\n\t\t\t\tif format == \"\" {\n\t\t\t\t\tpanic(value)\n\t\t\t\t} else {\n\t\t\t\t\tpanic(fmt.Sprintf(format, append(valuesF, value)...))\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else {\n\t\td.getEmit().emit(frmt, format, valuesF...)\n\t}\n}\n\n// Idiot-proof &Dbgr{}, etc.\nfunc (d *Dbgr) getEmit() emit {\n\tif d.emit == nil {\n\t\td.emit = standardEmit()\n\t}\n\treturn d.emit\n}\n\n// SetOutput will accept the following as a destination for output:\n//\n//\t*log.Logger         Print*/Panic*/Fatal* of the logger\n//\tio.Writer           -\n//\tnil                 Reset to the default output (os.Stderr)\n//\t\"log\"               Print*/Panic*/Fatal* via the \"log\" package\nfunc (d *Dbgr) SetOutput(output interface{}) {\n\tif output == nil {\n\t\td.emit = standardEmit()\n\t\treturn\n\t}\n\tswitch output := output.(type) {\n\tcase *log.Logger:\n\t\td.emit = emitLogger{\n\t\t\tlogger: output,\n\t\t}\n\t\treturn\n\tcase io.Writer:\n\t\td.emit = emitWriter{\n\t\t\twriter: output,\n\t\t}\n\t\treturn\n\tcase string:\n\t\tif output == \"log\" {\n\t\t\td.emit = emitLog{}\n\t\t\treturn\n\t\t}\n\t}\n\tpanic(output)\n}\n\n// ======== //\n// = emit = //\n// ======== //\n\nfunc standardEmit() emit {\n\treturn emitWriter{\n\t\twriter: os.Stderr,\n\t}\n}\n\nfunc ln(tmp string) string {\n\tlength := len(tmp)\n\tif length > 0 && tmp[length-1] != '\\n' {\n\t\treturn tmp + \"\\n\"\n\t}\n\treturn tmp\n}\n\ntype emit interface {\n\temit(_frmt, string, ...interface{})\n}\n\ntype emitWriter struct {\n\twriter io.Writer\n}\n\nfunc (ew emitWriter) emit(frmt _frmt, format string, values ...interface{}) {\n\tif format == \"\" {\n\t\tfmt.Fprintln(ew.writer, values...)\n\t} else {\n\t\tif frmt.panic {\n\t\t\tpanic(fmt.Sprintf(format, values...))\n\t\t}\n\t\tfmt.Fprintf(ew.writer, ln(format), values...)\n\t\tif frmt.fatal {\n\t\t\tos.Exit(1)\n\t\t}\n\t}\n}\n\ntype emitLogger struct {\n\tlogger *log.Logger\n}\n\nfunc (el emitLogger) emit(frmt _frmt, format string, values ...interface{}) {\n\tif format == \"\" {\n\t\tel.logger.Println(values...)\n\t} else {\n\t\tif frmt.panic {\n\t\t\tel.logger.Panicf(format, values...)\n\t\t} else if frmt.fatal {\n\t\t\tel.logger.Fatalf(format, values...)\n\t\t} else {\n\t\t\tel.logger.Printf(format, values...)\n\t\t}\n\t}\n}\n\ntype emitLog struct {\n}\n\nfunc (el emitLog) emit(frmt _frmt, format string, values ...interface{}) {\n\tif format == \"\" {\n\t\tlog.Println(values...)\n\t} else {\n\t\tif frmt.panic {\n\t\t\tlog.Panicf(format, values...)\n\t\t} else if frmt.fatal {\n\t\t\tlog.Fatalf(format, values...)\n\t\t} else {\n\t\t\tlog.Printf(format, values...)\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "dbg.go",
    "content": "// This file was AUTOMATICALLY GENERATED by dbg-import (smuggol) for github.com/robertkrimen/dbg\n\npackage otto\n\nimport (\n\tDbg \"github.com/robertkrimen/otto/dbg\"\n)\n\nvar dbg, dbgf = Dbg.New()\n"
  },
  {
    "path": "documentation_test.go",
    "content": "package otto\n\nimport (\n\t\"fmt\"\n\t\"os\"\n)\n\nfunc ExampleSynopsis() { //nolint:govet\n\tvm := New()\n\t_, err := vm.Run(`\n        abc = 2 + 2;\n        console.log(\"The value of abc is \" + abc); // 4\n    `)\n\tif err != nil {\n\t\tfmt.Fprintln(os.Stderr, err)\n\t\treturn\n\t}\n\n\tvalue, err := vm.Get(\"abc\")\n\tif err != nil {\n\t\tfmt.Fprintln(os.Stderr, err)\n\t\treturn\n\t}\n\n\tiv, err := value.ToInteger()\n\tif err != nil {\n\t\tfmt.Fprintln(os.Stderr, err)\n\t\treturn\n\t}\n\tfmt.Println(iv)\n\n\terr = vm.Set(\"def\", 11)\n\tif err != nil {\n\t\tfmt.Fprintln(os.Stderr, err)\n\t\treturn\n\t}\n\t_, err = vm.Run(`\n        console.log(\"The value of def is \" + def);\n    `)\n\tif err != nil {\n\t\tfmt.Fprintln(os.Stderr, err)\n\t\treturn\n\t}\n\n\terr = vm.Set(\"xyzzy\", \"Nothing happens.\")\n\tif err != nil {\n\t\tfmt.Fprintln(os.Stderr, err)\n\t\treturn\n\t}\n\t_, err = vm.Run(`\n        console.log(xyzzy.length);\n    `)\n\tif err != nil {\n\t\tfmt.Fprintln(os.Stderr, err)\n\t\treturn\n\t}\n\n\tvalue, err = vm.Run(\"xyzzy.length\")\n\tif err != nil {\n\t\tfmt.Fprintln(os.Stderr, err)\n\t\treturn\n\t}\n\n\tiv, err = value.ToInteger()\n\tif err != nil {\n\t\tfmt.Fprintln(os.Stderr, err)\n\t\treturn\n\t}\n\tfmt.Println(iv)\n\n\tvalue, err = vm.Run(\"abcdefghijlmnopqrstuvwxyz.length\")\n\tfmt.Println(value)\n\tfmt.Println(err) // Expected error.\n\n\terr = vm.Set(\"sayHello\", func(call FunctionCall) Value {\n\t\tfmt.Printf(\"Hello, %s.\\n\", call.Argument(0).String())\n\t\treturn UndefinedValue()\n\t})\n\tif err != nil {\n\t\tfmt.Fprintln(os.Stderr, err)\n\t\treturn\n\t}\n\n\terr = vm.Set(\"twoPlus\", func(call FunctionCall) Value {\n\t\tright, _ := call.Argument(0).ToInteger()\n\t\tresult, _ := vm.ToValue(2 + right)\n\t\treturn result\n\t})\n\tif err != nil {\n\t\tfmt.Fprintln(os.Stderr, err)\n\t\treturn\n\t}\n\n\tvalue, err = vm.Run(`\n        sayHello(\"Xyzzy\");\n        sayHello();\n\n        result = twoPlus(2.0);\n    `)\n\tif err != nil {\n\t\tfmt.Fprintln(os.Stderr, err)\n\t\treturn\n\t}\n\tfmt.Println(value)\n\n\t// Output:\n\t// The value of abc is 4\n\t// 4\n\t// The value of def is 11\n\t// 16\n\t// 16\n\t// undefined\n\t// ReferenceError: 'abcdefghijlmnopqrstuvwxyz' is not defined\n\t// Hello, Xyzzy.\n\t// Hello, undefined.\n\t// 4\n}\n\nfunc ExampleConsole() { //nolint:govet\n\tvm := New()\n\tconsole := map[string]interface{}{\n\t\t\"log\": func(call FunctionCall) Value {\n\t\t\tfmt.Println(\"console.log:\", formatForConsole(call.ArgumentList))\n\t\t\treturn UndefinedValue()\n\t\t},\n\t}\n\n\terr := vm.Set(\"console\", console)\n\tif err != nil {\n\t\tpanic(fmt.Errorf(\"console error: %w\", err))\n\t}\n\n\tvalue, err := vm.Run(`console.log(\"Hello, World.\");`)\n\tfmt.Println(value)\n\tfmt.Println(err)\n\n\t// Output:\n\t// console.log: Hello, World.\n\t// undefined\n\t// <nil>\n}\n"
  },
  {
    "path": "error.go",
    "content": "package otto\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\n\t\"github.com/robertkrimen/otto/file\"\n)\n\ntype exception struct {\n\tvalue interface{}\n}\n\nfunc newException(value interface{}) *exception {\n\treturn &exception{\n\t\tvalue: value,\n\t}\n}\n\nfunc (e *exception) eject() interface{} {\n\tvalue := e.value\n\te.value = nil // Prevent Go from holding on to the value, whatever it is\n\treturn value\n}\n\ntype ottoError struct {\n\tname    string\n\tmessage string\n\ttrace   []frame\n\n\toffset int\n}\n\nfunc (e ottoError) format() string {\n\tif len(e.name) == 0 {\n\t\treturn e.message\n\t}\n\tif len(e.message) == 0 {\n\t\treturn e.name\n\t}\n\treturn fmt.Sprintf(\"%s: %s\", e.name, e.message)\n}\n\nfunc (e ottoError) formatWithStack() string {\n\tstr := e.format() + \"\\n\"\n\tfor _, frm := range e.trace {\n\t\tstr += \"    at \" + frm.location() + \"\\n\"\n\t}\n\treturn str\n}\n\ntype frame struct {\n\tfn         interface{}\n\tfile       *file.File\n\tnativeFile string\n\tcallee     string\n\tnativeLine int\n\toffset     int\n\tnative     bool\n}\n\nvar nativeFrame = frame{}\n\ntype at int\n\nfunc (fr frame) location() string {\n\tstr := \"<unknown>\"\n\n\tswitch {\n\tcase fr.native:\n\t\tstr = \"<native code>\"\n\t\tif fr.nativeFile != \"\" && fr.nativeLine != 0 {\n\t\t\tstr = fmt.Sprintf(\"%s:%d\", fr.nativeFile, fr.nativeLine)\n\t\t}\n\tcase fr.file != nil:\n\t\tif p := fr.file.Position(file.Idx(fr.offset)); p != nil {\n\t\t\tpath, line, column := p.Filename, p.Line, p.Column\n\n\t\t\tif path == \"\" {\n\t\t\t\tpath = \"<anonymous>\"\n\t\t\t}\n\n\t\t\tstr = fmt.Sprintf(\"%s:%d:%d\", path, line, column)\n\t\t}\n\t}\n\n\tif fr.callee != \"\" {\n\t\tstr = fmt.Sprintf(\"%s (%s)\", fr.callee, str)\n\t}\n\n\treturn str\n}\n\n// An Error represents a runtime error, e.g. a TypeError, a ReferenceError, etc.\ntype Error struct {\n\tottoError\n}\n\n// Error returns a description of the error\n//\n//\tTypeError: 'def' is not a function\nfunc (e Error) Error() string {\n\treturn e.format()\n}\n\n// String returns a description of the error and a trace of where the\n// error occurred.\n//\n//\tTypeError: 'def' is not a function\n//\t    at xyz (<anonymous>:3:9)\n//\t    at <anonymous>:7:1/\nfunc (e Error) String() string {\n\treturn e.formatWithStack()\n}\n\n// GoString returns a description of the error and a trace of where the\n// error occurred. Printing with %#v will trigger this behaviour.\nfunc (e Error) GoString() string {\n\treturn e.formatWithStack()\n}\n\nfunc (e ottoError) describe(format string, in ...interface{}) string {\n\treturn fmt.Sprintf(format, in...)\n}\n\nfunc (e ottoError) messageValue() Value {\n\tif e.message == \"\" {\n\t\treturn Value{}\n\t}\n\treturn stringValue(e.message)\n}\n\nfunc (rt *runtime) typeErrorResult(throw bool) bool {\n\tif throw {\n\t\tpanic(rt.panicTypeError())\n\t}\n\treturn false\n}\n\nfunc newError(rt *runtime, name string, stackFramesToPop int, in ...interface{}) ottoError {\n\terr := ottoError{\n\t\tname:   name,\n\t\toffset: -1,\n\t}\n\tdescription := \"\"\n\tlength := len(in)\n\n\tif rt != nil && rt.scope != nil {\n\t\tcurScope := rt.scope\n\n\t\tfor range stackFramesToPop {\n\t\t\tif curScope.outer != nil {\n\t\t\t\tcurScope = curScope.outer\n\t\t\t}\n\t\t}\n\n\t\tfrm := curScope.frame\n\n\t\tif length > 0 {\n\t\t\tif atv, ok := in[length-1].(at); ok {\n\t\t\t\tin = in[0 : length-1]\n\t\t\t\tif curScope != nil {\n\t\t\t\t\tfrm.offset = int(atv)\n\t\t\t\t}\n\t\t\t\tlength--\n\t\t\t}\n\t\t\tif length > 0 {\n\t\t\t\tdescription, in = in[0].(string), in[1:]\n\t\t\t}\n\t\t}\n\n\t\tlimit := rt.traceLimit\n\n\t\terr.trace = append(err.trace, frm)\n\t\tif curScope != nil {\n\t\t\tfor curScope = curScope.outer; curScope != nil; curScope = curScope.outer {\n\t\t\t\tif limit--; limit == 0 {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\n\t\t\t\tif curScope.frame.offset >= 0 {\n\t\t\t\t\terr.trace = append(err.trace, curScope.frame)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else if length > 0 {\n\t\tdescription, in = in[0].(string), in[1:]\n\t}\n\terr.message = err.describe(description, in...)\n\n\treturn err\n}\n\nfunc (rt *runtime) panicTypeError(argumentList ...interface{}) *exception {\n\treturn &exception{\n\t\tvalue: newError(rt, \"TypeError\", 0, argumentList...),\n\t}\n}\n\nfunc (rt *runtime) panicReferenceError(argumentList ...interface{}) *exception {\n\treturn &exception{\n\t\tvalue: newError(rt, \"ReferenceError\", 0, argumentList...),\n\t}\n}\n\nfunc (rt *runtime) panicURIError(argumentList ...interface{}) *exception {\n\treturn &exception{\n\t\tvalue: newError(rt, \"URIError\", 0, argumentList...),\n\t}\n}\n\nfunc (rt *runtime) panicSyntaxError(argumentList ...interface{}) *exception {\n\treturn &exception{\n\t\tvalue: newError(rt, \"SyntaxError\", 0, argumentList...),\n\t}\n}\n\nfunc (rt *runtime) panicRangeError(argumentList ...interface{}) *exception {\n\treturn &exception{\n\t\tvalue: newError(rt, \"RangeError\", 0, argumentList...),\n\t}\n}\n\nfunc catchPanic(function func()) (err error) {\n\tdefer func() {\n\t\tif caught := recover(); caught != nil {\n\t\t\tif excep, ok := caught.(*exception); ok {\n\t\t\t\tcaught = excep.eject()\n\t\t\t}\n\t\t\tswitch caught := caught.(type) {\n\t\t\tcase *Error:\n\t\t\t\terr = caught\n\t\t\t\treturn\n\t\t\tcase ottoError:\n\t\t\t\terr = &Error{caught}\n\t\t\t\treturn\n\t\t\tcase Value:\n\t\t\t\tif vl := caught.object(); vl != nil {\n\t\t\t\t\tif vl, ok := vl.value.(ottoError); ok {\n\t\t\t\t\t\terr = &Error{vl}\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\terr = errors.New(caught.string())\n\t\t\t\treturn\n\t\t\t}\n\t\t\tpanic(caught)\n\t\t}\n\t}()\n\tfunction()\n\treturn nil\n}\n"
  },
  {
    "path": "error_native_test.go",
    "content": "package otto\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\n// this is its own file because the tests in it rely on the line numbers of\n// some of the functions defined here. putting it in with the rest of the\n// tests would probably be annoying.\n\nfunc TestErrorContextNative(t *testing.T) {\n\ttt(t, func() {\n\t\tvm := New()\n\n\t\terr := vm.Set(\"N\", func(c FunctionCall) Value {\n\t\t\tv, err := c.Argument(0).Call(NullValue())\n\t\t\tif err != nil {\n\t\t\t\tpanic(err)\n\t\t\t}\n\t\t\treturn v\n\t\t})\n\t\trequire.NoError(t, err)\n\n\t\ts, err := vm.Compile(\"test.js\", `\n\t\t\tfunction F() { throw new Error('wow'); }\n\t\t\tfunction G() { return N(F); }\n\t\t`)\n\t\trequire.NoError(t, err)\n\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(t, err)\n\n\t\tf1, err := vm.Get(\"G\")\n\t\trequire.NoError(t, err)\n\t\t_, err = f1.Call(NullValue())\n\t\trequire.Error(t, err)\n\t\terr1 := asError(t, err)\n\t\tis(err1.message, \"wow\")\n\t\tis(len(err1.trace), 3)\n\t\tis(err1.trace[0].location(), \"F (test.js:2:29)\")\n\t\tis(err1.trace[1].location(), \"github.com/robertkrimen/otto.TestErrorContextNative.func1.1 (error_native_test.go:17)\")\n\t\tis(err1.trace[2].location(), \"G (test.js:3:26)\")\n\t})\n}\n"
  },
  {
    "path": "error_test.go",
    "content": "package otto\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestError(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            [ Error.prototype.name, Error.prototype.message, Error.prototype.hasOwnProperty(\"message\") ];\n        `, \"Error,,true\")\n\t})\n}\n\nfunc TestError_instanceof(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`(new TypeError()) instanceof Error`, true)\n\t})\n}\n\nfunc TestPanicValue(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, vm := test()\n\n\t\tvm.Set(\"abc\", func(call FunctionCall) Value {\n\t\t\tvalue, err := call.Otto.Run(`({ def: 3.14159 })`)\n\t\t\tis(err, nil)\n\t\t\tpanic(value)\n\t\t})\n\n\t\ttest(`\n            try {\n                abc();\n            }\n            catch (err) {\n                error = err;\n            }\n            [ error instanceof Error, error.message, error.def ];\n        `, \"false,,3.14159\")\n\t})\n}\n\nfunc Test_catchPanic(t *testing.T) {\n\ttt(t, func() {\n\t\tvm := New()\n\n\t\t_, err := vm.Run(`\n            A syntax error that\n            does not define\n            var;\n                abc;\n        `)\n\t\tis(err, \"!=\", nil)\n\n\t\t_, err = vm.Call(`abc.def`, nil)\n\t\tis(err, \"!=\", nil)\n\t})\n}\n\nfunc asError(t *testing.T, err error) *Error {\n\tt.Helper()\n\tvar oerr *Error\n\trequire.ErrorAs(t, err, &oerr)\n\treturn oerr\n}\n\nfunc TestErrorContext(t *testing.T) {\n\ttt(t, func() {\n\t\tvm := New()\n\n\t\t_, err := vm.Run(`\n            undefined();\n        `)\n\t\t{\n\t\t\terr := asError(t, err)\n\t\t\tis(err.message, `\"undefined\" is not a function`)\n\t\t\tis(len(err.trace), 1)\n\t\t\tis(err.trace[0].location(), \"<anonymous>:2:13\")\n\t\t}\n\n\t\t_, err = vm.Run(`\n            ({}).abc();\n        `)\n\t\t{\n\t\t\terr := asError(t, err)\n\t\t\tis(err.message, `\"abc\" is not a function`)\n\t\t\tis(len(err.trace), 1)\n\t\t\tis(err.trace[0].location(), \"<anonymous>:2:14\")\n\t\t}\n\n\t\t_, err = vm.Run(`\n            (\"abc\").abc();\n        `)\n\t\t{\n\t\t\terr := asError(t, err)\n\t\t\tis(err.message, `\"abc\" is not a function`)\n\t\t\tis(len(err.trace), 1)\n\t\t\tis(err.trace[0].location(), \"<anonymous>:2:14\")\n\t\t}\n\n\t\t_, err = vm.Run(`\n            var ghi = \"ghi\";\n            ghi();\n        `)\n\t\t{\n\t\t\terr := asError(t, err)\n\t\t\tis(err.message, `\"ghi\" is not a function`)\n\t\t\tis(len(err.trace), 1)\n\t\t\tis(err.trace[0].location(), \"<anonymous>:3:13\")\n\t\t}\n\n\t\t_, err = vm.Run(`\n            function def() {\n                undefined();\n            }\n            function abc() {\n                def();\n            }\n            abc();\n        `)\n\t\t{\n\t\t\terr := asError(t, err)\n\t\t\tis(err.message, `\"undefined\" is not a function`)\n\t\t\tis(len(err.trace), 3)\n\t\t\tis(err.trace[0].location(), \"def (<anonymous>:3:17)\")\n\t\t\tis(err.trace[1].location(), \"abc (<anonymous>:6:17)\")\n\t\t\tis(err.trace[2].location(), \"<anonymous>:8:13\")\n\t\t}\n\n\t\t_, err = vm.Run(`\n            function abc() {\n                xyz();\n            }\n            abc();\n        `)\n\t\t{\n\t\t\terr := asError(t, err)\n\t\t\tis(err.message, \"'xyz' is not defined\")\n\t\t\tis(len(err.trace), 2)\n\t\t\tis(err.trace[0].location(), \"abc (<anonymous>:3:17)\")\n\t\t\tis(err.trace[1].location(), \"<anonymous>:5:13\")\n\t\t}\n\n\t\t_, err = vm.Run(`\n            mno + 1;\n        `)\n\t\t{\n\t\t\terr := asError(t, err)\n\t\t\tis(err.message, \"'mno' is not defined\")\n\t\t\tis(len(err.trace), 1)\n\t\t\tis(err.trace[0].location(), \"<anonymous>:2:13\")\n\t\t}\n\n\t\t_, err = vm.Run(`\n            eval(\"xyz();\");\n        `)\n\t\t{\n\t\t\terr := asError(t, err)\n\t\t\tis(err.message, \"'xyz' is not defined\")\n\t\t\tis(len(err.trace), 1)\n\t\t\tis(err.trace[0].location(), \"<anonymous>:1:1\")\n\t\t}\n\n\t\t_, err = vm.Run(`\n            xyzzy = \"Nothing happens.\"\n            eval(\"xyzzy();\");\n        `)\n\t\t{\n\t\t\terr := asError(t, err)\n\t\t\tis(err.message, `\"xyzzy\" is not a function`)\n\t\t\tis(len(err.trace), 1)\n\t\t\tis(err.trace[0].location(), \"<anonymous>:1:1\")\n\t\t}\n\n\t\t_, err = vm.Run(`\n            throw Error(\"xyzzy\");\n        `)\n\t\t{\n\t\t\terr := asError(t, err)\n\t\t\tis(err.message, \"xyzzy\")\n\t\t\tis(len(err.trace), 1)\n\t\t\tis(err.trace[0].location(), \"<anonymous>:2:19\")\n\t\t}\n\n\t\t_, err = vm.Run(`\n            throw new Error(\"xyzzy\");\n        `)\n\t\t{\n\t\t\terr := asError(t, err)\n\t\t\tis(err.message, \"xyzzy\")\n\t\t\tis(len(err.trace), 1)\n\t\t\tis(err.trace[0].location(), \"<anonymous>:2:23\")\n\t\t}\n\n\t\tscript1, err := vm.Compile(\"file1.js\",\n\t\t\t`function A() {\n\t\t\t\tthrow new Error(\"test\");\n\t\t\t}\n\n\t\t\tfunction C() {\n\t\t\t\tvar o = null;\n\t\t\t\to.prop = 1;\n\t\t\t}\n\t\t`)\n\t\tis(err, nil)\n\n\t\t_, err = vm.Run(script1)\n\t\tis(err, nil)\n\n\t\tscript2, err := vm.Compile(\"file2.js\",\n\t\t\t`function B() {\n\t\t\t\tA()\n\t\t\t}\n\t\t`)\n\t\tis(err, nil)\n\n\t\t_, err = vm.Run(script2)\n\t\tis(err, nil)\n\n\t\tscript3, err := vm.Compile(\"file3.js\", \"B()\")\n\t\tis(err, nil)\n\n\t\t_, err = vm.Run(script3)\n\t\t{\n\t\t\terr := asError(t, err)\n\t\t\tis(err.message, \"test\")\n\t\t\tis(len(err.trace), 3)\n\t\t\tis(err.trace[0].location(), \"A (file1.js:2:15)\")\n\t\t\tis(err.trace[1].location(), \"B (file2.js:2:5)\")\n\t\t\tis(err.trace[2].location(), \"file3.js:1:1\")\n\t\t}\n\n\t\t{\n\t\t\tf, _ := vm.Get(\"B\")\n\t\t\t_, err = f.Call(UndefinedValue())\n\t\t\terr1 := asError(t, err)\n\t\t\tis(err1.message, \"test\")\n\t\t\tis(len(err1.trace), 2)\n\t\t\tis(err1.trace[0].location(), \"A (file1.js:2:15)\")\n\t\t\tis(err1.trace[1].location(), \"B (file2.js:2:5)\")\n\t\t}\n\n\t\t{\n\t\t\tf, _ := vm.Get(\"C\")\n\t\t\t_, err = f.Call(UndefinedValue())\n\t\t\terr1 := asError(t, err)\n\t\t\tis(err1.message, `Cannot access member \"prop\" of null`)\n\t\t\tis(len(err1.trace), 1)\n\t\t\tis(err1.trace[0].location(), \"C (file1.js:7:5)\")\n\t\t}\n\t})\n}\n\nfunc TestMakeCustomErrorReturn(t *testing.T) {\n\ttt(t, func() {\n\t\tvm := New()\n\n\t\terr := vm.Set(\"A\", func(c FunctionCall) Value {\n\t\t\treturn vm.MakeCustomError(\"CarrotError\", \"carrots is life, carrots is love\")\n\t\t})\n\t\trequire.NoError(t, err)\n\n\t\ts, err := vm.Compile(\"test.js\", `\n\t\t\tfunction B() { return A(); }\n\t\t\tfunction C() { return B(); }\n\t\t\tfunction D() { return C(); }\n\t\t`)\n\t\trequire.NoError(t, err)\n\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(t, err)\n\n\t\tv, err := vm.Call(\"D\", nil)\n\t\trequire.NoError(t, err)\n\n\t\tis(v.Class(), classErrorName)\n\n\t\tname, err := v.Object().Get(\"name\")\n\t\trequire.NoError(t, err)\n\t\tis(name.String(), \"CarrotError\")\n\n\t\tmessage, err := v.Object().Get(\"message\")\n\t\trequire.NoError(t, err)\n\t\tis(message.String(), \"carrots is life, carrots is love\")\n\n\t\tstr, err := v.Object().Call(\"toString\")\n\t\trequire.NoError(t, err)\n\t\tis(str, \"CarrotError: carrots is life, carrots is love\")\n\n\t\ti, err := v.Export()\n\t\trequire.NoError(t, err)\n\t\tt.Logf(\"%#v\\n\", i)\n\t})\n}\n\nfunc TestMakeCustomError(t *testing.T) {\n\ttt(t, func() {\n\t\tvm := New()\n\n\t\terr := vm.Set(\"A\", func(c FunctionCall) Value {\n\t\t\tpanic(vm.MakeCustomError(\"CarrotError\", \"carrots is life, carrots is love\"))\n\t\t})\n\t\trequire.NoError(t, err)\n\n\t\ts, err := vm.Compile(\"test.js\", `\n\t\t\tfunction B() { A(); }\n\t\t\tfunction C() { B(); }\n\t\t\tfunction D() { C(); }\n\t\t`)\n\t\trequire.NoError(t, err)\n\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(t, err)\n\n\t\t_, err = vm.Call(\"D\", nil)\n\t\trequire.EqualError(t, err, \"CarrotError: carrots is life, carrots is love\")\n\n\t\ter := asError(t, err)\n\t\tis(er.name, \"CarrotError\")\n\t\tis(er.message, \"carrots is life, carrots is love\")\n\t})\n}\n\nfunc TestMakeCustomErrorFreshVM(t *testing.T) {\n\ttt(t, func() {\n\t\tvm := New()\n\t\te := vm.MakeCustomError(\"CarrotError\", \"carrots is life, carrots is love\")\n\n\t\tstr, err := e.ToString()\n\t\trequire.NoError(t, err)\n\n\t\tis(str, \"CarrotError: carrots is life, carrots is love\")\n\t})\n}\n\nfunc TestMakeTypeError(t *testing.T) {\n\ttt(t, func() {\n\t\tvm := New()\n\n\t\terr := vm.Set(\"A\", func(c FunctionCall) Value {\n\t\t\tpanic(vm.MakeTypeError(\"these aren't my glasses\"))\n\t\t})\n\t\trequire.NoError(t, err)\n\n\t\ts, err := vm.Compile(\"test.js\", `\n\t\t\tfunction B() { A(); }\n\t\t\tfunction C() { B(); }\n\t\t\tfunction D() { C(); }\n\t\t`)\n\t\trequire.NoError(t, err)\n\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(t, err)\n\n\t\t_, err = vm.Call(\"D\", nil)\n\t\trequire.EqualError(t, err, \"TypeError: these aren't my glasses\")\n\n\t\ter := asError(t, err)\n\t\tis(er.name, \"TypeError\")\n\t\tis(er.message, \"these aren't my glasses\")\n\t})\n}\n\nfunc TestMakeRangeError(t *testing.T) {\n\ttt(t, func() {\n\t\tvm := New()\n\n\t\terr := vm.Set(\"A\", func(c FunctionCall) Value {\n\t\t\tpanic(vm.MakeRangeError(\"too many\"))\n\t\t})\n\t\trequire.NoError(t, err)\n\n\t\ts, err := vm.Compile(\"test.js\", `\n\t\t\tfunction B() { A(); }\n\t\t\tfunction C() { B(); }\n\t\t\tfunction D() { C(); }\n\t\t`)\n\t\trequire.NoError(t, err)\n\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(t, err)\n\n\t\t_, err = vm.Call(\"D\", nil)\n\t\trequire.EqualError(t, err, \"RangeError: too many\")\n\n\t\ter := asError(t, err)\n\t\tis(er.name, \"RangeError\")\n\t\tis(er.message, \"too many\")\n\t})\n}\n\nfunc TestMakeSyntaxError(t *testing.T) {\n\ttt(t, func() {\n\t\tvm := New()\n\n\t\terr := vm.Set(\"A\", func(c FunctionCall) Value {\n\t\t\tpanic(vm.MakeSyntaxError(\"i think you meant \\\"you're\\\"\"))\n\t\t})\n\t\trequire.NoError(t, err)\n\n\t\ts, err := vm.Compile(\"test.js\", `\n\t\t\tfunction B() { A(); }\n\t\t\tfunction C() { B(); }\n\t\t\tfunction D() { C(); }\n\t\t`)\n\t\trequire.NoError(t, err)\n\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(t, err)\n\n\t\t_, err = vm.Call(\"D\", nil)\n\t\trequire.EqualError(t, err, \"SyntaxError: i think you meant \\\"you're\\\"\")\n\n\t\ter := asError(t, err)\n\t\tis(er.name, \"SyntaxError\")\n\t\tis(er.message, \"i think you meant \\\"you're\\\"\")\n\t})\n}\n\nfunc TestErrorStackProperty(t *testing.T) {\n\ttt(t, func() {\n\t\tvm := New()\n\n\t\ts, err := vm.Compile(\"test.js\", `\n\t\t\tfunction A() { throw new TypeError('uh oh'); }\n\t\t\tfunction B() { return A(); }\n\t\t\tfunction C() { return B(); }\n\n\t\t\tvar s = null;\n\n\t\t\ttry { C(); } catch (e) { s = e.stack; }\n\n\t\t\ts;\n\t\t`)\n\t\trequire.NoError(t, err)\n\n\t\tv, err := vm.Run(s)\n\t\trequire.NoError(t, err)\n\n\t\tis(v.String(), \"TypeError: uh oh\\n    at A (test.js:2:29)\\n    at B (test.js:3:26)\\n    at C (test.js:4:26)\\n    at test.js:8:10\\n\")\n\t})\n}\n\nfunc TestErrorMessageContainingFormatCharacters(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, tester := test()\n\n\t\ttester.Set(\"F\", func(call FunctionCall) Value {\n\t\t\treturn call.Otto.MakeCustomError(call.ArgumentList[0].String(), call.ArgumentList[1].String())\n\t\t})\n\n\t\ttest(\"Error('literal percent-s: %s')\", \"Error: literal percent-s: %s\")\n\t\ttest(\"new Error('literal percent-s: %s')\", \"Error: literal percent-s: %s\")\n\t\ttest(\"F('TestError', 'literal percent-s: %s')\", \"TestError: literal percent-s: %s\")\n\t\ttest(\"raise: throw Error('literal percent-s: %s')\", \"Error: literal percent-s: %s\")\n\t\ttest(\"raise: throw new Error('literal percent-s: %s')\", \"Error: literal percent-s: %s\")\n\t\ttest(\"raise: throw F('TestError', 'literal percent-s: %s')\", \"TestError: literal percent-s: %s\")\n\t})\n}\n"
  },
  {
    "path": "evaluate.go",
    "content": "package otto\n\nimport (\n\t\"fmt\"\n\t\"math\"\n\t\"strings\"\n\n\t\"github.com/robertkrimen/otto/token\"\n)\n\nfunc (rt *runtime) evaluateMultiply(left float64, right float64) Value { //nolint:unused\n\t// TODO 11.5.1\n\treturn Value{}\n}\n\nfunc (rt *runtime) evaluateDivide(left float64, right float64) Value {\n\tif math.IsNaN(left) || math.IsNaN(right) {\n\t\treturn NaNValue()\n\t}\n\tif math.IsInf(left, 0) && math.IsInf(right, 0) {\n\t\treturn NaNValue()\n\t}\n\tif left == 0 && right == 0 {\n\t\treturn NaNValue()\n\t}\n\tif math.IsInf(left, 0) {\n\t\tif math.Signbit(left) == math.Signbit(right) {\n\t\t\treturn positiveInfinityValue()\n\t\t}\n\t\treturn negativeInfinityValue()\n\t}\n\tif math.IsInf(right, 0) {\n\t\tif math.Signbit(left) == math.Signbit(right) {\n\t\t\treturn positiveZeroValue()\n\t\t}\n\t\treturn negativeZeroValue()\n\t}\n\tif right == 0 {\n\t\tif math.Signbit(left) == math.Signbit(right) {\n\t\t\treturn positiveInfinityValue()\n\t\t}\n\t\treturn negativeInfinityValue()\n\t}\n\treturn float64Value(left / right)\n}\n\nfunc (rt *runtime) evaluateModulo(left float64, right float64) Value { //nolint:unused\n\t// TODO 11.5.3\n\treturn Value{}\n}\n\nfunc (rt *runtime) calculateBinaryExpression(operator token.Token, left Value, right Value) Value {\n\tleftValue := left.resolve()\n\n\tswitch operator {\n\t// Additive\n\tcase token.PLUS:\n\t\tleftValue = toPrimitiveValue(leftValue)\n\t\trightValue := right.resolve()\n\t\trightValue = toPrimitiveValue(rightValue)\n\n\t\tif leftValue.IsString() || rightValue.IsString() {\n\t\t\treturn stringValue(strings.Join([]string{leftValue.string(), rightValue.string()}, \"\"))\n\t\t}\n\t\treturn float64Value(leftValue.float64() + rightValue.float64())\n\tcase token.MINUS:\n\t\trightValue := right.resolve()\n\t\treturn float64Value(leftValue.float64() - rightValue.float64())\n\n\t\t// Multiplicative\n\tcase token.MULTIPLY:\n\t\trightValue := right.resolve()\n\t\treturn float64Value(leftValue.float64() * rightValue.float64())\n\tcase token.SLASH:\n\t\trightValue := right.resolve()\n\t\treturn rt.evaluateDivide(leftValue.float64(), rightValue.float64())\n\tcase token.REMAINDER:\n\t\trightValue := right.resolve()\n\t\treturn float64Value(math.Mod(leftValue.float64(), rightValue.float64()))\n\n\t\t// Logical\n\tcase token.LOGICAL_AND:\n\t\tleft := leftValue.bool()\n\t\tif !left {\n\t\t\treturn falseValue\n\t\t}\n\t\treturn boolValue(right.resolve().bool())\n\tcase token.LOGICAL_OR:\n\t\tleft := leftValue.bool()\n\t\tif left {\n\t\t\treturn trueValue\n\t\t}\n\t\treturn boolValue(right.resolve().bool())\n\n\t\t// Bitwise\n\tcase token.AND:\n\t\trightValue := right.resolve()\n\t\treturn int32Value(toInt32(leftValue) & toInt32(rightValue))\n\tcase token.OR:\n\t\trightValue := right.resolve()\n\t\treturn int32Value(toInt32(leftValue) | toInt32(rightValue))\n\tcase token.EXCLUSIVE_OR:\n\t\trightValue := right.resolve()\n\t\treturn int32Value(toInt32(leftValue) ^ toInt32(rightValue))\n\n\t\t// Shift\n\t\t// (Masking of 0x1f is to restrict the shift to a maximum of 31 places)\n\tcase token.SHIFT_LEFT:\n\t\trightValue := right.resolve()\n\t\treturn int32Value(toInt32(leftValue) << (toUint32(rightValue) & 0x1f))\n\tcase token.SHIFT_RIGHT:\n\t\trightValue := right.resolve()\n\t\treturn int32Value(toInt32(leftValue) >> (toUint32(rightValue) & 0x1f))\n\tcase token.UNSIGNED_SHIFT_RIGHT:\n\t\trightValue := right.resolve()\n\t\t// Shifting an unsigned integer is a logical shift\n\t\treturn uint32Value(toUint32(leftValue) >> (toUint32(rightValue) & 0x1f))\n\n\tcase token.INSTANCEOF:\n\t\trightValue := right.resolve()\n\t\tif !rightValue.IsObject() {\n\t\t\tpanic(rt.panicTypeError(\"invalid kind %s for instanceof (expected object)\", rightValue.kind))\n\t\t}\n\t\treturn boolValue(rightValue.object().hasInstance(leftValue))\n\n\tcase token.IN:\n\t\trightValue := right.resolve()\n\t\tif !rightValue.IsObject() {\n\t\t\tpanic(rt.panicTypeError(\"invalid kind %s for in (expected object)\", rightValue.kind))\n\t\t}\n\t\treturn boolValue(rightValue.object().hasProperty(leftValue.string()))\n\t}\n\n\tpanic(hereBeDragons(operator))\n}\n\ntype lessThanResult int\n\nconst (\n\tlessThanFalse lessThanResult = iota\n\tlessThanTrue\n\tlessThanUndefined\n)\n\nfunc calculateLessThan(left Value, right Value, leftFirst bool) lessThanResult {\n\tvar x, y Value\n\tif leftFirst {\n\t\tx = toNumberPrimitive(left)\n\t\ty = toNumberPrimitive(right)\n\t} else {\n\t\ty = toNumberPrimitive(right)\n\t\tx = toNumberPrimitive(left)\n\t}\n\n\tvar result bool\n\tif x.kind != valueString || y.kind != valueString {\n\t\tx, y := x.float64(), y.float64()\n\t\tif math.IsNaN(x) || math.IsNaN(y) {\n\t\t\treturn lessThanUndefined\n\t\t}\n\t\tresult = x < y\n\t} else {\n\t\tx, y := x.string(), y.string()\n\t\tresult = x < y\n\t}\n\n\tif result {\n\t\treturn lessThanTrue\n\t}\n\n\treturn lessThanFalse\n}\n\n// FIXME Probably a map is not the most efficient way to do this.\nvar lessThanTable [4](map[lessThanResult]bool) = [4](map[lessThanResult]bool){\n\t// <\n\tmap[lessThanResult]bool{\n\t\tlessThanFalse:     false,\n\t\tlessThanTrue:      true,\n\t\tlessThanUndefined: false,\n\t},\n\n\t// >\n\tmap[lessThanResult]bool{\n\t\tlessThanFalse:     false,\n\t\tlessThanTrue:      true,\n\t\tlessThanUndefined: false,\n\t},\n\n\t// <=\n\tmap[lessThanResult]bool{\n\t\tlessThanFalse:     true,\n\t\tlessThanTrue:      false,\n\t\tlessThanUndefined: false,\n\t},\n\n\t// >=\n\tmap[lessThanResult]bool{\n\t\tlessThanFalse:     true,\n\t\tlessThanTrue:      false,\n\t\tlessThanUndefined: false,\n\t},\n}\n\nfunc (rt *runtime) calculateComparison(comparator token.Token, left Value, right Value) bool {\n\t// FIXME Use strictEqualityComparison?\n\t// TODO This might be redundant now (with regards to evaluateComparison)\n\tx := left.resolve()\n\ty := right.resolve()\n\n\tvar kindEqualKind bool\n\tvar negate bool\n\tresult := true\n\n\tswitch comparator {\n\tcase token.LESS:\n\t\tresult = lessThanTable[0][calculateLessThan(x, y, true)]\n\tcase token.GREATER:\n\t\tresult = lessThanTable[1][calculateLessThan(y, x, false)]\n\tcase token.LESS_OR_EQUAL:\n\t\tresult = lessThanTable[2][calculateLessThan(y, x, false)]\n\tcase token.GREATER_OR_EQUAL:\n\t\tresult = lessThanTable[3][calculateLessThan(x, y, true)]\n\tcase token.STRICT_NOT_EQUAL:\n\t\tnegate = true\n\t\tfallthrough\n\tcase token.STRICT_EQUAL:\n\t\tif x.kind != y.kind {\n\t\t\tresult = false\n\t\t} else {\n\t\t\tkindEqualKind = true\n\t\t}\n\tcase token.NOT_EQUAL:\n\t\tnegate = true\n\t\tfallthrough\n\tcase token.EQUAL:\n\t\tswitch {\n\t\tcase x.kind == y.kind:\n\t\t\tkindEqualKind = true\n\t\tcase x.kind <= valueNull && y.kind <= valueNull:\n\t\t\tresult = true\n\t\tcase x.kind <= valueNull || y.kind <= valueNull:\n\t\t\tresult = false\n\t\tcase x.kind <= valueString && y.kind <= valueString:\n\t\t\tresult = x.float64() == y.float64()\n\t\tcase x.kind == valueBoolean:\n\t\t\tresult = rt.calculateComparison(token.EQUAL, float64Value(x.float64()), y)\n\t\tcase y.kind == valueBoolean:\n\t\t\tresult = rt.calculateComparison(token.EQUAL, x, float64Value(y.float64()))\n\t\tcase x.kind == valueObject:\n\t\t\tresult = rt.calculateComparison(token.EQUAL, toPrimitiveValue(x), y)\n\t\tcase y.kind == valueObject:\n\t\t\tresult = rt.calculateComparison(token.EQUAL, x, toPrimitiveValue(y))\n\t\tdefault:\n\t\t\tpanic(fmt.Sprintf(\"unknown types for equal: %v ==? %v\", x, y))\n\t\t}\n\tdefault:\n\t\tpanic(\"unknown comparator \" + comparator.String())\n\t}\n\n\tif kindEqualKind {\n\t\tswitch x.kind {\n\t\tcase valueUndefined, valueNull:\n\t\t\tresult = true\n\t\tcase valueNumber:\n\t\t\tx := x.float64()\n\t\t\ty := y.float64()\n\t\t\tif math.IsNaN(x) || math.IsNaN(y) {\n\t\t\t\tresult = false\n\t\t\t} else {\n\t\t\t\tresult = x == y\n\t\t\t}\n\t\tcase valueString:\n\t\t\tresult = x.string() == y.string()\n\t\tcase valueBoolean:\n\t\t\tresult = x.bool() == y.bool()\n\t\tcase valueObject:\n\t\t\tresult = x.object() == y.object()\n\t\tdefault:\n\t\t\tgoto ERROR\n\t\t}\n\t}\n\n\tif negate {\n\t\tresult = !result\n\t}\n\n\treturn result\n\nERROR:\n\tpanic(hereBeDragons(\"%v (%v) %s %v (%v)\", x, x.kind, comparator, y, y.kind))\n}\n"
  },
  {
    "path": "file/file.go",
    "content": "// Package file encapsulates the file abstractions used by the ast & parser.\npackage file\n\nimport (\n\t\"fmt\"\n\t\"strings\"\n\n\t\"gopkg.in/sourcemap.v1\"\n)\n\n// Idx is a compact encoding of a source position within a file set.\n// It can be converted into a Position for a more convenient, but much\n// larger, representation.\ntype Idx int\n\n// Position describes an arbitrary source position\n// including the filename, line, and column location.\ntype Position struct {\n\tFilename string // The filename where the error occurred, if any\n\tOffset   int    // The src offset\n\tLine     int    // The line number, starting at 1\n\tColumn   int    // The column number, starting at 1 (The character count)\n}\n\n// A Position is valid if the line number is > 0.\n\nfunc (p *Position) isValid() bool {\n\treturn p.Line > 0\n}\n\n// String returns a string in one of several forms:\n//\n//\tfile:line:column    A valid position with filename\n//\tline:column         A valid position without filename\n//\tfile                An invalid position with filename\n//\t-                   An invalid position without filename\nfunc (p *Position) String() string {\n\tstr := p.Filename\n\tif p.isValid() {\n\t\tif str != \"\" {\n\t\t\tstr += \":\"\n\t\t}\n\t\tstr += fmt.Sprintf(\"%d:%d\", p.Line, p.Column)\n\t}\n\tif str == \"\" {\n\t\tstr = \"-\"\n\t}\n\treturn str\n}\n\n// A FileSet represents a set of source files.\ntype FileSet struct {\n\tlast  *File\n\tfiles []*File\n}\n\n// AddFile adds a new file with the given filename and src.\n//\n// This an internal method, but exported for cross-package use.\nfunc (fs *FileSet) AddFile(filename, src string) int {\n\tbase := fs.nextBase()\n\tfile := &File{\n\t\tname: filename,\n\t\tsrc:  src,\n\t\tbase: base,\n\t}\n\tfs.files = append(fs.files, file)\n\tfs.last = file\n\treturn base\n}\n\nfunc (fs *FileSet) nextBase() int {\n\tif fs.last == nil {\n\t\treturn 1\n\t}\n\treturn fs.last.base + len(fs.last.src) + 1\n}\n\n// File returns the File at idx or nil if not found.\nfunc (fs *FileSet) File(idx Idx) *File {\n\tfor _, file := range fs.files {\n\t\tif idx <= Idx(file.base+len(file.src)) {\n\t\t\treturn file\n\t\t}\n\t}\n\treturn nil\n}\n\n// Position converts an Idx in the FileSet into a Position.\nfunc (fs *FileSet) Position(idx Idx) *Position {\n\tfor _, file := range fs.files {\n\t\tif idx <= Idx(file.base+len(file.src)) {\n\t\t\treturn file.Position(idx - Idx(file.base))\n\t\t}\n\t}\n\n\treturn nil\n}\n\n// File represents a file to parse.\ntype File struct {\n\tsm   *sourcemap.Consumer\n\tname string\n\tsrc  string\n\tbase int\n}\n\n// NewFile returns a new file with the given filename, src and base.\nfunc NewFile(filename, src string, base int) *File {\n\treturn &File{\n\t\tname: filename,\n\t\tsrc:  src,\n\t\tbase: base,\n\t}\n}\n\n// WithSourceMap sets the source map of fl.\nfunc (fl *File) WithSourceMap(sm *sourcemap.Consumer) *File {\n\tfl.sm = sm\n\treturn fl\n}\n\n// Name returns the name of fl.\nfunc (fl *File) Name() string {\n\treturn fl.name\n}\n\n// Source returns the source of fl.\nfunc (fl *File) Source() string {\n\treturn fl.src\n}\n\n// Base returns the base of fl.\nfunc (fl *File) Base() int {\n\treturn fl.base\n}\n\n// Position returns the position at idx or nil if not valid.\nfunc (fl *File) Position(idx Idx) *Position {\n\tposition := &Position{}\n\n\toffset := int(idx) - fl.base\n\n\tif offset >= len(fl.src) || offset < 0 {\n\t\treturn nil\n\t}\n\n\tsrc := fl.src[:offset]\n\n\tposition.Filename = fl.name\n\tposition.Offset = offset\n\tposition.Line = strings.Count(src, \"\\n\") + 1\n\n\tif index := strings.LastIndex(src, \"\\n\"); index >= 0 {\n\t\tposition.Column = offset - index\n\t} else {\n\t\tposition.Column = len(src) + 1\n\t}\n\n\tif fl.sm != nil {\n\t\tif f, _, l, c, ok := fl.sm.Source(position.Line, position.Column); ok {\n\t\t\tposition.Filename, position.Line, position.Column = f, l, c\n\t\t}\n\t}\n\n\treturn position\n}\n"
  },
  {
    "path": "function_stack_test.go",
    "content": "package otto\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\n// this is its own file because the tests in it rely on the line numbers of\n// some of the functions defined here. putting it in with the rest of the\n// tests would probably be annoying.\n\nfunc TestFunction_stack(t *testing.T) {\n\ttt(t, func() {\n\t\tvm := New()\n\n\t\ts, err := vm.Compile(\"fake.js\", `function X(fn1, fn2, fn3) { fn1(fn2, fn3); }`)\n\t\trequire.NoError(t, err)\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(t, err)\n\n\t\texpected := []frame{\n\t\t\t{native: true, nativeFile: \"function_stack_test.go\", nativeLine: 36, offset: 0, callee: \"github.com/robertkrimen/otto.TestFunction_stack.func1.2\"},\n\t\t\t{native: true, nativeFile: \"function_stack_test.go\", nativeLine: 29, offset: 0, callee: \"github.com/robertkrimen/otto.TestFunction_stack.func1.1\"},\n\t\t\t{native: false, nativeFile: \"\", nativeLine: 0, offset: 29, callee: \"X\", file: s.program.file},\n\t\t\t{native: false, nativeFile: \"\", nativeLine: 0, offset: 29, callee: \"X\", file: s.program.file},\n\t\t}\n\n\t\terr = vm.Set(\"A\", func(c FunctionCall) Value {\n\t\t\t_, err = c.Argument(0).Call(UndefinedValue())\n\t\t\trequire.NoError(t, err)\n\t\t\treturn UndefinedValue()\n\t\t})\n\t\trequire.NoError(t, err)\n\n\t\terr = vm.Set(\"B\", func(c FunctionCall) Value {\n\t\t\tdepth := 0\n\t\t\tfor s := c.Otto.runtime.scope; s != nil; s = s.outer {\n\t\t\t\t// these properties are tested explicitly so that we don't test `.fn`,\n\t\t\t\t// which will differ from run to run\n\t\t\t\tis(s.frame.native, expected[depth].native)\n\t\t\t\tis(s.frame.nativeFile, expected[depth].nativeFile)\n\t\t\t\tis(s.frame.nativeLine, expected[depth].nativeLine)\n\t\t\t\tis(s.frame.offset, expected[depth].offset)\n\t\t\t\tis(s.frame.callee, expected[depth].callee)\n\t\t\t\tis(s.frame.file, expected[depth].file)\n\t\t\t\tdepth++\n\t\t\t}\n\n\t\t\tis(depth, 4)\n\n\t\t\treturn UndefinedValue()\n\t\t})\n\t\trequire.NoError(t, err)\n\n\t\tx, err := vm.Get(\"X\")\n\t\trequire.NoError(t, err)\n\t\ta, err := vm.Get(\"A\")\n\t\trequire.NoError(t, err)\n\t\tb, err := vm.Get(\"B\")\n\t\trequire.NoError(t, err)\n\n\t\t_, err = x.Call(UndefinedValue(), x, a, b)\n\t\trequire.NoError(t, err)\n\t})\n}\n"
  },
  {
    "path": "function_test.go",
    "content": "package otto\n\nimport (\n\t\"testing\"\n)\n\nfunc TestFunction(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            var abc = Object.getOwnPropertyDescriptor(Function, \"prototype\");\n            [   [ typeof Function.prototype, typeof Function.prototype.length, Function.prototype.length ],\n                [ abc.writable, abc.enumerable, abc.configurable ] ];\n        `, \"function,number,0,false,false,false\")\n\t})\n}\n\nfunc Test_argumentList2parameterList(t *testing.T) {\n\ttt(t, func() {\n\t\tis(argumentList2parameterList([]Value{toValue(\"abc, def\"), toValue(\"ghi\")}), []string{\"abc\", \"def\", \"ghi\"})\n\t})\n}\n\nfunc TestFunction_new(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`raise:\n            new Function({});\n        `, \"SyntaxError: (anonymous): Line 2:9 Unexpected identifier\")\n\n\t\ttest(`\n            var abc = Function(\"def, ghi\", \"jkl\", \"return def+ghi+jkl\");\n            [ typeof abc, abc instanceof Function, abc(\"ab\", \"ba\", 1) ];\n        `, \"function,true,abba1\")\n\n\t\ttest(`raise:\n            var abc = {\n                toString: function() { throw 1; }\n            };\n            var def = {\n                toString: function() { throw 2; }\n            };\n            var ghi = new Function(abc, def);\n            ghi;\n        `, \"1\")\n\n\t\t// S15.3.2.1_A3_T10\n\t\ttest(`raise:\n            var abc = {\n                toString: function() { return \"z;x\"; }\n            };\n            var def = \"return this\";\n            var ghi = new Function(abc, def);\n            ghi;\n        `, \"SyntaxError: (anonymous): Line 1:12 Unexpected token ;\")\n\n\t\ttest(`raise:\n            var abc;\n            var def = \"return true\";\n            var ghi = new Function(null, def);\n            ghi;\n        `, \"SyntaxError: (anonymous): Line 1:11 Unexpected token null\")\n\t})\n}\n\nfunc TestFunction_apply(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`Function.prototype.apply.length`, 2)\n\t\ttest(`String.prototype.substring.apply(\"abc\", [1, 11])`, \"bc\")\n\t})\n}\n\nfunc TestFunction_call(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`Function.prototype.call.length`, 1)\n\t\ttest(`String.prototype.substring.call(\"abc\", 1, 11)`, \"bc\")\n\t})\n}\n\nfunc TestFunctionArguments(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\t// Should not be able to delete arguments\n\t\ttest(`\n            function abc(def, arguments){\n                delete def;\n                return def;\n            }\n            abc(1);\n        `, 1)\n\n\t\t// Again, should not be able to delete arguments\n\t\ttest(`\n            function abc(def){\n                delete def;\n                return def;\n            }\n            abc(1);\n        `, 1)\n\n\t\t// Test typeof of a function argument\n\t\ttest(`\n            function abc(def, ghi, jkl){\n                return typeof jkl\n            }\n            abc(\"1st\", \"2nd\", \"3rd\", \"4th\", \"5th\");\n        `, \"string\")\n\n\t\ttest(`\n            function abc(def, ghi, jkl){\n                arguments[0] = 3.14;\n                arguments[1] = 'Nothing happens';\n                arguments[2] = 42;\n                if (3.14 === def && 'Nothing happens' === ghi && 42 === jkl)\n                    return true;\n            }\n            abc(-1, 4.2, 314);\n        `, true)\n\t})\n}\n\nfunc TestFunctionDeclarationInFunction(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\t// Function declarations happen AFTER parameter/argument declarations\n\t\t// That is, a function declared within a function will shadow/overwrite\n\t\t// declared parameters\n\n\t\ttest(`\n            function abc(def){\n                return def;\n                function def(){\n                    return 1;\n                }\n            }\n            typeof abc();\n        `, \"function\")\n\t})\n}\n\nfunc TestArguments_defineOwnProperty(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            var abc;\n            var def = true;\n            var ghi = {};\n            (function (a, b, c) {\n                Object.defineProperty(arguments, \"0\", {\n                    value: 42,\n                    writable: false,\n                    enumerable: false,\n                    configurable: false\n                });\n                Object.defineProperty(arguments, \"1\", {\n                    value: 3.14,\n                    configurable: true,\n                    enumerable: true\n                });\n                abc = Object.getOwnPropertyDescriptor(arguments, \"0\");\n                for (var name in arguments) {\n                    ghi[name] = (ghi[name] || 0) + 1;\n                    if (name === \"0\") {\n                        def = false;\n                    }\n                }\n            }(0, 1, 2));\n            [ abc.value, abc.writable, abc.enumerable, abc.configurable, def, ghi[\"1\"] ];\n        `, \"42,false,false,false,true,1\")\n\t})\n}\n\nfunc TestFunction_bind(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\tdefer mockUTC()()\n\n\t\ttest(`\n            abc = function(){\n                return \"abc\";\n            };\n            def = abc.bind();\n            [ typeof def.prototype, typeof def.hasOwnProperty, def.hasOwnProperty(\"caller\"), def.hasOwnProperty(\"arguments\"), def() ];\n        `, \"object,function,true,true,abc\")\n\n\t\ttest(`\n            abc = function(){\n                return arguments[1];\n            };\n            def = abc.bind(undefined, \"abc\");\n            ghi = abc.bind(undefined, \"abc\", \"ghi\");\n            [ def(), def(\"def\"), ghi(\"def\") ];\n        `, \",def,ghi\")\n\n\t\ttest(`\n            var abc = function () {};\n            var ghi;\n            try {\n                Object.defineProperty(Function.prototype, \"xyzzy\", {\n                    value: 1001,\n                    writable: true,\n                    enumerable: true,\n                    configurable: true\n                });\n                var def = abc.bind({});\n                ghi = !def.hasOwnProperty(\"xyzzy\") && ghi.xyzzy === 1001;\n            } finally {\n                delete Function.prototype.xyzzy;\n            }\n            [ ghi ];\n        `, \"true\")\n\n\t\ttest(`\n            var abc = function (def, ghi) {};\n            var jkl = abc.bind({});\n            var mno = abc.bind({}, 1, 2);\n            [ jkl.length, mno.length ];\n        `, \"2,0\")\n\n\t\ttest(`raise:\n            Math.bind();\n        `, `TypeError: \"bind\" is not a function`)\n\n\t\ttest(`\n            function construct(fn, arguments) {\n                var bound = Function.prototype.bind.apply(fn, [null].concat(arguments));\n                return new bound();\n            }\n            var abc = construct(Date, [1957, 4, 27]);\n            Object.prototype.toString.call(abc);\n        `, \"[object Date]\")\n\n\t\ttest(`\n            var fn = function (x, y, z) {\n                var result = {};\n                result.abc = x + y + z;\n                result.def = arguments[0] === \"a\" && arguments.length === 3;\n                return result;\n            };\n            var newFn = Function.prototype.bind.call(fn, {}, \"a\", \"b\", \"c\");\n            var result = new newFn();\n            [ result.hasOwnProperty(\"abc\"), result.hasOwnProperty(\"def\"), result.abc, result.def ];\n        `, \"true,true,abc,true\")\n\n\t\ttest(`\n            abc = function(){\n                return \"abc\";\n            };\n            def = abc.bind();\n            def.toString();\n        `, \"function () { [native code] }\")\n\t})\n}\n\nfunc TestFunction_toString(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`raise:\n            Function.prototype.toString.call(undefined);\n        `, \"TypeError: Function.Class environment != Function\")\n\n\t\ttest(`\n            abc = function()   {       return -1    ;\n}\n            1;\n            abc.toString();\n        `, \"function()   {       return -1    ;\\n}\")\n\t})\n}\n\nfunc TestFunction_length(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`function a(x, y) {}; a.length`, 2)\n\t})\n}\n\nfunc TestFunction_name(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`function a() {}; a.name`, \"a\")\n\n\t\ttest(`function a() {}; var b = a.bind(); b.name`, \"bound a\")\n\t})\n}\n\nfunc TestFunction_caller(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, vm := test()\n\n\t\tvm.Set(\"n\", func(v Value) Value {\n\t\t\tr, err := v.Call(UndefinedValue())\n\t\t\tif err != nil {\n\t\t\t\tpanic(err)\n\t\t\t}\n\n\t\t\treturn r\n\t\t})\n\n\t\ttest(`\n            function a() { return a.caller; };\n            a()\n        `, NullValue())\n\n\t\ttest(`\n            function a() { return a.caller === b; };\n            function b() { return a(); }\n            b()\n        `, true)\n\n\t\ttest(`\n            function a() { return a.caller === b && b.caller === c; }\n            function b() { return a(); }\n            function c() { return b(); }\n            c();\n        `, true)\n\n\t\ttest(`\n            function a() { return a.caller === b && b.caller === n && n.caller === c; }\n            function b() { return a(); }\n            function c() { return n(b); }\n            c()\n        `, true)\n\n\t\ttest(`\n            function e() { return e.caller === g && f.caller === g && g.caller === f; }\n            function f(n) { return g(n - 1); }\n            function g(n) { return n > 0 ? f(n) : e(); }\n            f(2);\n        `, true)\n\t})\n}\n"
  },
  {
    "path": "functional_benchmark_test.go",
    "content": "package otto\n\nimport (\n\t\"math/rand\"\n\t\"strconv\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestGoSliceQuickSort(t *testing.T) {\n\ttestGoSliceSort(t, \"quickSort(testSlice, 0, testSlice.length-1);\", jsQuickSort)\n}\n\nfunc TestGoSliceHeapSort(t *testing.T) {\n\ttestGoSliceSort(t, \"heapSort(testSlice)\", jsHeapSort)\n}\n\nfunc TestJsArrayQuicksort(t *testing.T) {\n\ttestJsArraySort(t, \"quickSort(testSlice, 0, testSlice.length-1);\", jsQuickSort)\n}\n\nfunc TestJsArrayHeapSort(t *testing.T) {\n\ttestJsArraySort(t, \"heapSort(testSlice)\", jsHeapSort)\n}\n\nfunc TestJsArrayMergeSort(t *testing.T) {\n\ttestJsArraySort(t, \"testSlice = mergeSort(testSlice)\", jsMergeSort)\n}\n\nfunc TestCryptoAes(t *testing.T) {\n\ttt(t, func() {\n\t\t_, vm := test()\n\t\t_, err := vm.Run(jsCryptoAES)\n\t\tis(err, nil)\n\t})\n}\n\nfunc BenchmarkGoSliceQuickSort100000000(b *testing.B) {\n\tbenchmarkGoSliceSort(b, 100000000, \"quickSort(testSlice, 0, testSlice.length-1);\", jsQuickSort)\n}\n\nfunc BenchmarkGoSliceHeapSort100000000(b *testing.B) {\n\tbenchmarkGoSliceSort(b, 100000000, \"heapSort(testSlice);\", jsHeapSort)\n}\n\nfunc BenchmarkJsArrayQuickSort500(b *testing.B) {\n\tbenchmarkJsArraySort(b, 500, \"quickSort(testSlice, 0, testSlice.length-1);\", jsQuickSort)\n}\n\nfunc BenchmarkJsArrayMergeSort500(b *testing.B) {\n\tbenchmarkJsArraySort(b, 500, \"mergeSort(testSlice);\", jsMergeSort)\n}\n\nfunc BenchmarkJsArrayHeapSort500(b *testing.B) {\n\tbenchmarkJsArraySort(b, 500, \"heapSort(testSlice);\", jsHeapSort)\n}\n\nfunc BenchmarkCryptoAES(b *testing.B) {\n\tvm := New()\n\n\t// Make sure VM creation time is not counted in runtime test\n\tb.ResetTimer()\n\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err := vm.Run(jsCryptoAES)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc testGoSliceSort(t *testing.T, sortFuncCall string, sortCode string) {\n\tt.Helper()\n\ttt(t, func() {\n\t\ttest, vm := test()\n\n\t\t// inject quicksort code\n\t\t_, err := vm.Run(sortCode)\n\t\tis(err, nil)\n\n\t\ttestSlice := []int{5, 3, 2, 4, 1}\n\t\tvm.Set(\"testSlice\", testSlice)\n\t\t_, err = vm.Run(sortFuncCall)\n\t\tis(err, nil)\n\n\t\tis(test(`testSlice[0]`).export(), 1)\n\t\tis(test(`testSlice[1]`).export(), 2)\n\t\tis(test(`testSlice[2]`).export(), 3)\n\t\tis(test(`testSlice[3]`).export(), 4)\n\t\tis(test(`testSlice[4]`).export(), 5)\n\n\t\tis(testSlice[0], 1)\n\t\tis(testSlice[1], 2)\n\t\tis(testSlice[2], 3)\n\t\tis(testSlice[3], 4)\n\t\tis(testSlice[4], 5)\n\t})\n}\n\nfunc testJsArraySort(t *testing.T, sortFuncCall string, sortCode string) {\n\tt.Helper()\n\ttt(t, func() {\n\t\ttest, vm := test()\n\n\t\t// inject quicksort code\n\t\t_, err := vm.Run(sortCode)\n\t\trequire.NoError(t, err)\n\n\t\t_, err = vm.Run(\"var testSlice = [5, 3, 2, 4, 1];\")\n\t\trequire.NoError(t, err)\n\t\t_, err = vm.Run(sortFuncCall)\n\t\trequire.NoError(t, err)\n\n\t\tis(test(`testSlice[0]`).export(), 1)\n\t\tis(test(`testSlice[1]`).export(), 2)\n\t\tis(test(`testSlice[2]`).export(), 3)\n\t\tis(test(`testSlice[3]`).export(), 4)\n\t\tis(test(`testSlice[4]`).export(), 5)\n\t})\n}\n\nfunc benchmarkGoSliceSort(b *testing.B, size int, sortFuncCall string, sortCode string) {\n\tb.Helper()\n\t// generate arbitrary slice of 'size'\n\ttestSlice := make([]int, size)\n\tfor i := range size {\n\t\ttestSlice[i] = rand.Int() //nolint:gosec\n\t}\n\n\tvm := New()\n\n\t// inject the sorting code\n\t_, err := vm.Run(sortCode)\n\trequire.NoError(b, err)\n\n\t// Reset timer - everything until this point may have taken a long time\n\tb.ResetTimer()\n\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(sortFuncCall)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc benchmarkJsArraySort(b *testing.B, size int, sortFuncCall string, sortCode string) {\n\tb.Helper()\n\t// generate arbitrary slice of 'size'\n\ttestSlice := make([]string, size)\n\tfor i := range testSlice {\n\t\ttestSlice[i] = strconv.Itoa(rand.Int()) //nolint:gosec\n\t}\n\n\tjsArrayString := \"[\" + strings.Join(testSlice, \",\") + \"]\"\n\n\tvm := New()\n\n\t// inject the test array\n\t_, err := vm.Run(\"testSlice = \" + jsArrayString)\n\trequire.NoError(b, err)\n\n\t// inject the sorting code\n\t_, err = vm.Run(sortCode)\n\trequire.NoError(b, err)\n\n\t// Reset timer - everything until this point may have taken a long time\n\tb.ResetTimer()\n\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(sortFuncCall)\n\t\trequire.NoError(b, err)\n\t}\n}\n\n/**********************************************************************************************************************/\n// Appendix - all the Javascript algorithm code constants\n\nconst jsQuickSort = `\nfunction quickSort(arr, left, right){\n   var len = arr.length,\n   pivot,\n   partitionIndex;\n\n\n  if(left < right){\n    pivot = right;\n    partitionIndex = partition(arr, pivot, left, right);\n\n   // sort left and right\n   quickSort(arr, left, partitionIndex - 1);\n   quickSort(arr, partitionIndex + 1, right);\n  }\n  return arr;\n}\n\nfunction partition(arr, pivot, left, right){\n   var pivotValue = arr[pivot],\n       partitionIndex = left;\n\n   for(var i = left; i < right; i++){\n    if(arr[i] < pivotValue){\n      swap(arr, i, partitionIndex);\n      partitionIndex++;\n    }\n  }\n  swap(arr, right, partitionIndex);\n  return partitionIndex;\n}\n\n\n\nfunction swap(arr, i, j){\n   var temp = arr[i];\n   arr[i] = arr[j];\n   arr[j] = temp;\n}\n\n\t`\n\nconst jsMergeSort = `\n\nfunction mergeSort(arr){\n   var len = arr.length;\n   if(len <2)\n      return arr;\n   var mid = Math.floor(len/2),\n       left = arr.slice(0,mid),\n       right =arr.slice(mid);\n   // send left and right to the mergeSort to broke it down into pieces\n   // then merge those\n   return merge(mergeSort(left),mergeSort(right));\n}\n\n\nfunction merge(left, right){\n  var result = [],\n      lLen = left.length,\n      rLen = right.length,\n      l = 0,\n      r = 0;\n  while(l < lLen && r < rLen){\n     if(left[l] < right[r]){\n       result.push(left[l++]);\n     }\n     else{\n       result.push(right[r++]);\n    }\n  }\n  // remaining part needs to be addred to the result\n  return result.concat(left.slice(l)).concat(right.slice(r));\n}\n\n`\n\nconst jsHeapSort = `\n\nfunction heapSort(arr){\n  var len = arr.length,\n      end = len-1;\n\n  heapify(arr, len);\n\n  while(end > 0){\n   swap(arr, end--, 0);\n   siftDown(arr, 0, end);\n  }\n  return arr;\n}\n\n\nfunction heapify(arr, len){\n   // break the array into root + two sides, to create tree (heap)\n   var mid = Math.floor((len-2)/2);\n   while(mid >= 0){\n    siftDown(arr, mid--, len-1);\n  }\n}\n\nfunction siftDown(arr, start, end){\n   var root = start,\n       child = root*2 + 1,\n       toSwap = root;\n   while(child <= end){\n      if(arr[toSwap] < arr[child]){\n        swap(arr, toSwap, child);\n      }\n      if(child+1 <= end && arr[toSwap] < arr[child+1]){\n        swap(arr, toSwap, child+1)\n      }\n      if(toSwap != root){\n         swap(arr, root, toSwap);\n         root = toSwap;\n      }\n      else{\n         return;\n      }\n      toSwap = root;\n      child = root*2+1\n  }\n}\n\n\nfunction swap(arr, i, j){\n  var temp = arr[i];\n  arr[i] = arr[j];\n  arr[j] = temp;\n}\n\n\n`\n\n// Copied from JetStream benchmarking suite\n// http://browserbench.org/JetStream/sources/crypto-aes.js\nconst jsCryptoAES = `\n/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */\n\n/*\n * AES Cipher function: encrypt 'input' with Rijndael algorithm\n *\n *   takes   byte-array 'input' (16 bytes)\n *           2D byte-array key schedule 'w' (Nr+1 x Nb bytes)\n *\n *   applies Nr rounds (10/12/14) using key schedule w for 'add round key' stage\n *\n *   returns byte-array encrypted value (16 bytes)\n */\nfunction Cipher(input, w) {    // main Cipher function [Â§5.1]\n  var Nb = 4;               // block size (in words): no of columns in state (fixed at 4 for AES)\n  var Nr = w.length/Nb - 1; // no of rounds: 10/12/14 for 128/192/256-bit keys\n\n  var state = [[],[],[],[]];  // initialise 4xNb byte-array 'state' with input [Â§3.4]\n  for (var i=0; i<4*Nb; i++) state[i%4][Math.floor(i/4)] = input[i];\n\n  state = AddRoundKey(state, w, 0, Nb);\n\n  for (var round=1; round<Nr; round++) {\n    state = SubBytes(state, Nb);\n    state = ShiftRows(state, Nb);\n    state = MixColumns(state, Nb);\n    state = AddRoundKey(state, w, round, Nb);\n  }\n\n  state = SubBytes(state, Nb);\n  state = ShiftRows(state, Nb);\n  state = AddRoundKey(state, w, Nr, Nb);\n\n  var output = new Array(4*Nb);  // convert state to 1-d array before returning [Â§3.4]\n  for (var i=0; i<4*Nb; i++) output[i] = state[i%4][Math.floor(i/4)];\n  return output;\n}\n\n\nfunction SubBytes(s, Nb) {    // apply SBox to state S [Â§5.1.1]\n  for (var r=0; r<4; r++) {\n    for (var c=0; c<Nb; c++) s[r][c] = Sbox[s[r][c]];\n  }\n  return s;\n}\n\n\nfunction ShiftRows(s, Nb) {    // shift row r of state S left by r bytes [Â§5.1.2]\n  var t = new Array(4);\n  for (var r=1; r<4; r++) {\n    for (var c=0; c<4; c++) t[c] = s[r][(c+r)%Nb];  // shift into temp copy\n    for (var c=0; c<4; c++) s[r][c] = t[c];         // and copy back\n  }          // note that this will work for Nb=4,5,6, but not 7,8 (always 4 for AES):\n  return s;  // see fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.311.pdf\n}\n\n\nfunction MixColumns(s, Nb) {   // combine bytes of each col of state S [Â§5.1.3]\n  for (var c=0; c<4; c++) {\n    var a = new Array(4);  // 'a' is a copy of the current column from 's'\n    var b = new Array(4);  // 'b' is aâ€¢{02} in GF(2^8)\n    for (var i=0; i<4; i++) {\n      a[i] = s[i][c];\n      b[i] = s[i][c]&0x80 ? s[i][c]<<1 ^ 0x011b : s[i][c]<<1;\n    }\n    // a[n] ^ b[n] is aâ€¢{03} in GF(2^8)\n    s[0][c] = b[0] ^ a[1] ^ b[1] ^ a[2] ^ a[3]; // 2*a0 + 3*a1 + a2 + a3\n    s[1][c] = a[0] ^ b[1] ^ a[2] ^ b[2] ^ a[3]; // a0 * 2*a1 + 3*a2 + a3\n    s[2][c] = a[0] ^ a[1] ^ b[2] ^ a[3] ^ b[3]; // a0 + a1 + 2*a2 + 3*a3\n    s[3][c] = a[0] ^ b[0] ^ a[1] ^ a[2] ^ b[3]; // 3*a0 + a1 + a2 + 2*a3\n  }\n  return s;\n}\n\n\nfunction AddRoundKey(state, w, rnd, Nb) {  // xor Round Key into state S [Â§5.1.4]\n  for (var r=0; r<4; r++) {\n    for (var c=0; c<Nb; c++) state[r][c] ^= w[rnd*4+c][r];\n  }\n  return state;\n}\n\n\nfunction KeyExpansion(key) {  // generate Key Schedule (byte-array Nr+1 x Nb) from Key [Â§5.2]\n  var Nb = 4;            // block size (in words): no of columns in state (fixed at 4 for AES)\n  var Nk = key.length/4  // key length (in words): 4/6/8 for 128/192/256-bit keys\n  var Nr = Nk + 6;       // no of rounds: 10/12/14 for 128/192/256-bit keys\n\n  var w = new Array(Nb*(Nr+1));\n  var temp = new Array(4);\n\n  for (var i=0; i<Nk; i++) {\n    var r = [key[4*i], key[4*i+1], key[4*i+2], key[4*i+3]];\n    w[i] = r;\n  }\n\n  for (var i=Nk; i<(Nb*(Nr+1)); i++) {\n    w[i] = new Array(4);\n    for (var t=0; t<4; t++) temp[t] = w[i-1][t];\n    if (i % Nk == 0) {\n      temp = SubWord(RotWord(temp));\n      for (var t=0; t<4; t++) temp[t] ^= Rcon[i/Nk][t];\n    } else if (Nk > 6 && i%Nk == 4) {\n      temp = SubWord(temp);\n    }\n    for (var t=0; t<4; t++) w[i][t] = w[i-Nk][t] ^ temp[t];\n  }\n\n  return w;\n}\n\nfunction SubWord(w) {    // apply SBox to 4-byte word w\n  for (var i=0; i<4; i++) w[i] = Sbox[w[i]];\n  return w;\n}\n\nfunction RotWord(w) {    // rotate 4-byte word w left by one byte\n  w[4] = w[0];\n  for (var i=0; i<4; i++) w[i] = w[i+1];\n  return w;\n}\n\n\n// Sbox is pre-computed multiplicative inverse in GF(2^8) used in SubBytes and KeyExpansion [Â§5.1.1]\nvar Sbox =  [0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5,0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,\n             0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0,0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,\n             0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc,0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,\n             0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a,0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,\n             0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0,0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,\n             0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b,0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,\n             0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85,0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,\n             0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5,0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,\n             0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17,0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,\n             0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88,0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,\n             0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c,0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,\n             0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9,0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,\n             0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6,0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,\n             0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e,0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,\n             0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94,0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,\n             0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68,0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16];\n\n// Rcon is Round Constant used for the Key Expansion [1st col is 2^(r-1) in GF(2^8)] [Â§5.2]\nvar Rcon = [ [0x00, 0x00, 0x00, 0x00],\n             [0x01, 0x00, 0x00, 0x00],\n             [0x02, 0x00, 0x00, 0x00],\n             [0x04, 0x00, 0x00, 0x00],\n             [0x08, 0x00, 0x00, 0x00],\n             [0x10, 0x00, 0x00, 0x00],\n             [0x20, 0x00, 0x00, 0x00],\n             [0x40, 0x00, 0x00, 0x00],\n             [0x80, 0x00, 0x00, 0x00],\n             [0x1b, 0x00, 0x00, 0x00],\n             [0x36, 0x00, 0x00, 0x00] ];\n\n\n/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */\n\n/*\n * Use AES to encrypt 'plaintext' with 'password' using 'nBits' key, in 'Counter' mode of operation\n *                           - see http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf\n *   for each block\n *   - outputblock = cipher(counter, key)\n *   - cipherblock = plaintext xor outputblock\n */\nfunction AESEncryptCtr(plaintext, password, nBits) {\n  if (!(nBits==128 || nBits==192 || nBits==256)) return '';  // standard allows 128/192/256 bit keys\n\n  // for this example script, generate the key by applying Cipher to 1st 16/24/32 chars of password;\n  // for real-world applications, a more secure approach would be to hash the password e.g. with SHA-1\n  var nBytes = nBits/8;  // no bytes in key\n  var pwBytes = new Array(nBytes);\n  for (var i=0; i<nBytes; i++) pwBytes[i] = password.charCodeAt(i) & 0xff;\n  var key = Cipher(pwBytes, KeyExpansion(pwBytes));\n  key = key.concat(key.slice(0, nBytes-16));  // key is now 16/24/32 bytes long\n\n  // initialise counter block (NIST SP800-38A Â§B.2): millisecond time-stamp for nonce in 1st 8 bytes,\n  // block counter in 2nd 8 bytes\n  var blockSize = 16;  // block size fixed at 16 bytes / 128 bits (Nb=4) for AES\n  var counterBlock = new Array(blockSize);  // block size fixed at 16 bytes / 128 bits (Nb=4) for AES\n  var nonce = (new Date()).getTime();  // milliseconds since 1-Jan-1970\n\n  // encode nonce in two stages to cater for JavaScript 32-bit limit on bitwise ops\n  for (var i=0; i<4; i++) counterBlock[i] = (nonce >>> i*8) & 0xff;\n  for (var i=0; i<4; i++) counterBlock[i+4] = (nonce/0x100000000 >>> i*8) & 0xff;\n\n  // generate key schedule - an expansion of the key into distinct Key Rounds for each round\n  var keySchedule = KeyExpansion(key);\n\n  var blockCount = Math.ceil(plaintext.length/blockSize);\n  var ciphertext = new Array(blockCount);  // ciphertext as array of strings\n\n  for (var b=0; b<blockCount; b++) {\n    // set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)\n    // again done in two stages for 32-bit ops\n    for (var c=0; c<4; c++) counterBlock[15-c] = (b >>> c*8) & 0xff;\n    for (var c=0; c<4; c++) counterBlock[15-c-4] = (b/0x100000000 >>> c*8)\n\n    var cipherCntr = Cipher(counterBlock, keySchedule);  // -- encrypt counter block --\n\n    // calculate length of final block:\n    var blockLength = b<blockCount-1 ? blockSize : (plaintext.length-1)%blockSize+1;\n\n    var ct = '';\n    for (var i=0; i<blockLength; i++) {  // -- xor plaintext with ciphered counter byte-by-byte --\n      var plaintextByte = plaintext.charCodeAt(b*blockSize+i);\n      var cipherByte = plaintextByte ^ cipherCntr[i];\n      ct += String.fromCharCode(cipherByte);\n    }\n    // ct is now ciphertext for this block\n\n    ciphertext[b] = escCtrlChars(ct);  // escape troublesome characters in ciphertext\n  }\n\n  // convert the nonce to a string to go on the front of the ciphertext\n  var ctrTxt = '';\n  for (var i=0; i<8; i++) ctrTxt += String.fromCharCode(counterBlock[i]);\n  ctrTxt = escCtrlChars(ctrTxt);\n\n  // use '-' to separate blocks, use Array.join to concatenate arrays of strings for efficiency\n  return ctrTxt + '-' + ciphertext.join('-');\n}\n\n\n/*\n * Use AES to decrypt 'ciphertext' with 'password' using 'nBits' key, in Counter mode of operation\n *\n *   for each block\n *   - outputblock = cipher(counter, key)\n *   - cipherblock = plaintext xor outputblock\n */\nfunction AESDecryptCtr(ciphertext, password, nBits) {\n  if (!(nBits==128 || nBits==192 || nBits==256)) return '';  // standard allows 128/192/256 bit keys\n\n  var nBytes = nBits/8;  // no bytes in key\n  var pwBytes = new Array(nBytes);\n  for (var i=0; i<nBytes; i++) pwBytes[i] = password.charCodeAt(i) & 0xff;\n  var pwKeySchedule = KeyExpansion(pwBytes);\n  var key = Cipher(pwBytes, pwKeySchedule);\n  key = key.concat(key.slice(0, nBytes-16));  // key is now 16/24/32 bytes long\n\n  var keySchedule = KeyExpansion(key);\n\n  ciphertext = ciphertext.split('-');  // split ciphertext into array of block-length strings\n\n  // recover nonce from 1st element of ciphertext\n  var blockSize = 16;  // block size fixed at 16 bytes / 128 bits (Nb=4) for AES\n  var counterBlock = new Array(blockSize);\n  var ctrTxt = unescCtrlChars(ciphertext[0]);\n  for (var i=0; i<8; i++) counterBlock[i] = ctrTxt.charCodeAt(i);\n\n  var plaintext = new Array(ciphertext.length-1);\n\n  for (var b=1; b<ciphertext.length; b++) {\n    // set counter (block #) in last 8 bytes of counter block (leaving nonce in 1st 8 bytes)\n    for (var c=0; c<4; c++) counterBlock[15-c] = ((b-1) >>> c*8) & 0xff;\n    for (var c=0; c<4; c++) counterBlock[15-c-4] = ((b/0x100000000-1) >>> c*8) & 0xff;\n\n    var cipherCntr = Cipher(counterBlock, keySchedule);  // encrypt counter block\n\n    ciphertext[b] = unescCtrlChars(ciphertext[b]);\n\n    var pt = '';\n    for (var i=0; i<ciphertext[b].length; i++) {\n      // -- xor plaintext with ciphered counter byte-by-byte --\n      var ciphertextByte = ciphertext[b].charCodeAt(i);\n      var plaintextByte = ciphertextByte ^ cipherCntr[i];\n      pt += String.fromCharCode(plaintextByte);\n    }\n    // pt is now plaintext for this block\n\n    plaintext[b-1] = pt;  // b-1 'cos no initial nonce block in plaintext\n  }\n\n  return plaintext.join('');\n}\n\n/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */\n\nfunction escCtrlChars(str) {  // escape control chars which might cause problems handling ciphertext\n  return str.replace(/[\\0\\t\\n\\v\\f\\r\\xa0'\"!-]/g, function(c) { return '!' + c.charCodeAt(0) + '!'; });\n}  // \\xa0 to cater for bug in Firefox; include '-' to leave it free for use as a block marker\n\nfunction unescCtrlChars(str) {  // unescape potentially problematic control characters\n  return str.replace(/!\\d\\d?\\d?!/g, function(c) { return String.fromCharCode(c.slice(1,-1)); });\n}\n/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */\n\n/*\n * if escCtrlChars()/unescCtrlChars() still gives problems, use encodeBase64()/decodeBase64() instead\n */\nvar b64 = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\";\n\nfunction encodeBase64(str) {  // http://tools.ietf.org/html/rfc4648\n   var o1, o2, o3, h1, h2, h3, h4, bits, i=0, enc='';\n\n   str = encodeUTF8(str);  // encode multi-byte chars into UTF-8 for byte-array\n\n   do {  // pack three octets into four hexets\n      o1 = str.charCodeAt(i++);\n      o2 = str.charCodeAt(i++);\n      o3 = str.charCodeAt(i++);\n\n      bits = o1<<16 | o2<<8 | o3;\n\n      h1 = bits>>18 & 0x3f;\n      h2 = bits>>12 & 0x3f;\n      h3 = bits>>6 & 0x3f;\n      h4 = bits & 0x3f;\n\n      // end of string? index to '=' in b64\n      if (isNaN(o3)) h4 = 64;\n      if (isNaN(o2)) h3 = 64;\n\n      // use hexets to index into b64, and append result to encoded string\n      enc += b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4);\n   } while (i < str.length);\n\n   return enc;\n}\n\nfunction decodeBase64(str) {\n   var o1, o2, o3, h1, h2, h3, h4, bits, i=0, enc='';\n\n   do {  // unpack four hexets into three octets using index points in b64\n      h1 = b64.indexOf(str.charAt(i++));\n      h2 = b64.indexOf(str.charAt(i++));\n      h3 = b64.indexOf(str.charAt(i++));\n      h4 = b64.indexOf(str.charAt(i++));\n\n      bits = h1<<18 | h2<<12 | h3<<6 | h4;\n\n      o1 = bits>>16 & 0xff;\n      o2 = bits>>8 & 0xff;\n      o3 = bits & 0xff;\n\n      if (h3 == 64)      enc += String.fromCharCode(o1);\n      else if (h4 == 64) enc += String.fromCharCode(o1, o2);\n      else               enc += String.fromCharCode(o1, o2, o3);\n   } while (i < str.length);\n\n   return decodeUTF8(enc);  // decode UTF-8 byte-array back to Unicode\n}\n\nfunction encodeUTF8(str) {  // encode multi-byte string into utf-8 multiple single-byte characters\n  str = str.replace(\n      /[\\u0080-\\u07ff]/g,  // U+0080 - U+07FF = 2-byte chars\n      function(c) {\n        var cc = c.charCodeAt(0);\n        return String.fromCharCode(0xc0 | cc>>6, 0x80 | cc&0x3f); }\n    );\n  str = str.replace(\n      /[\\u0800-\\uffff]/g,  // U+0800 - U+FFFF = 3-byte chars\n      function(c) {\n        var cc = c.charCodeAt(0);\n        return String.fromCharCode(0xe0 | cc>>12, 0x80 | cc>>6&0x3F, 0x80 | cc&0x3f); }\n    );\n  return str;\n}\n\nfunction decodeUTF8(str) {  // decode utf-8 encoded string back into multi-byte characters\n  str = str.replace(\n      /[\\u00c0-\\u00df][\\u0080-\\u00bf]/g,                 // 2-byte chars\n      function(c) {\n        var cc = (c.charCodeAt(0)&0x1f)<<6 | c.charCodeAt(1)&0x3f;\n        return String.fromCharCode(cc); }\n    );\n  str = str.replace(\n      /[\\u00e0-\\u00ef][\\u0080-\\u00bf][\\u0080-\\u00bf]/g,  // 3-byte chars\n      function(c) {\n        var cc = (c.charCodeAt(0)&0x0f)<<12 | (c.charCodeAt(1)&0x3f<<6) | c.charCodeAt(2)&0x3f;\n        return String.fromCharCode(cc); }\n    );\n  return str;\n}\n\n\nfunction byteArrayToHexStr(b) {  // convert byte array to hex string for displaying test vectors\n  var s = '';\n  for (var i=0; i<b.length; i++) s += b[i].toString(16) + ' ';\n  return s;\n}\n\n/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  */\n\n\nvar plainText = \"ROMEO: But, soft! what light through yonder window breaks?\\n\\\nIt is the east, and Juliet is the sun.\\n\\\nArise, fair sun, and kill the envious moon,\\n\\\nWho is already sick and pale with grief,\\n\\\nThat thou her maid art far more fair than she:\\n\\\nBe not her maid, since she is envious;\\n\\\nHer vestal livery is but sick and green\\n\\\nAnd none but fools do wear it; cast it off.\\n\\\nIt is my lady, O, it is my love!\\n\\\nO, that she knew she were!\\n\\\nShe speaks yet she says nothing: what of that?\\n\\\nHer eye discourses; I will answer it.\\n\\\nI am too bold, 'tis not to me she speaks:\\n\\\nTwo of the fairest stars in all the heaven,\\n\\\nHaving some business, do entreat her eyes\\n\\\nTo twinkle in their spheres till they return.\\n\\\nWhat if her eyes were there, they in her head?\\n\\\nThe brightness of her cheek would shame those stars,\\n\\\nAs daylight doth a lamp; her eyes in heaven\\n\\\nWould through the airy region stream so bright\\n\\\nThat birds would sing and think it were not night.\\n\\\nSee, how she leans her cheek upon her hand!\\n\\\nO, that I were a glove upon that hand,\\n\\\nThat I might touch that cheek!\\n\\\nJULIET: Ay me!\\n\\\nROMEO: She speaks:\\n\\\nO, speak again, bright angel! for thou art\\n\\\nAs glorious to this night, being o'er my head\\n\\\nAs is a winged messenger of heaven\\n\\\nUnto the white-upturned wondering eyes\\n\\\nOf mortals that fall back to gaze on him\\n\\\nWhen he bestrides the lazy-pacing clouds\\n\\\nAnd sails upon the bosom of the air.\";\n\nvar password = \"O Romeo, Romeo! wherefore art thou Romeo?\";\n\nvar cipherText = AESEncryptCtr(plainText, password, 256);\nvar decryptedText = AESDecryptCtr(cipherText, password, 256);\n\nif (decryptedText != plainText)\n    throw \"ERROR: bad result: expected \" + plainText + \" but got \" + decryptedText;\n`\n"
  },
  {
    "path": "generate.go",
    "content": "package otto\n\n//go:generate go run ./tools/gen-jscore -output inline.go\n//go:generate stringer -type=valueKind -trimprefix=value -output=value_kind.gen.go\n"
  },
  {
    "path": "global.go",
    "content": "package otto\n\nimport (\n\t\"strconv\"\n\t\"time\"\n)\n\nvar (\n\tprototypeValueObject   = interface{}(nil)\n\tprototypeValueFunction = nativeFunctionObject{\n\t\tcall: func(_ FunctionCall) Value {\n\t\t\treturn Value{}\n\t\t},\n\t}\n\tprototypeValueString = stringASCII(\"\")\n\t// TODO Make this just false?\n\tprototypeValueBoolean = Value{\n\t\tkind:  valueBoolean,\n\t\tvalue: false,\n\t}\n\tprototypeValueNumber = Value{\n\t\tkind:  valueNumber,\n\t\tvalue: 0,\n\t}\n\tprototypeValueDate = dateObject{\n\t\tepoch: 0,\n\t\tisNaN: false,\n\t\ttime:  time.Unix(0, 0).UTC(),\n\t\tvalue: Value{\n\t\t\tkind:  valueNumber,\n\t\t\tvalue: 0,\n\t\t},\n\t}\n\tprototypeValueRegExp = regExpObject{\n\t\tregularExpression: nil,\n\t\tglobal:            false,\n\t\tignoreCase:        false,\n\t\tmultiline:         false,\n\t\tsource:            \"\",\n\t\tflags:             \"\",\n\t}\n)\n\nfunc newContext() *runtime {\n\trt := &runtime{}\n\n\trt.globalStash = rt.newObjectStash(nil, nil)\n\trt.globalObject = rt.globalStash.object\n\n\trt.newContext()\n\n\trt.eval = rt.globalObject.property[\"eval\"].value.(Value).value.(*object)\n\trt.globalObject.prototype = rt.global.ObjectPrototype\n\n\treturn rt\n}\n\nfunc (rt *runtime) newBaseObject() *object {\n\treturn newObject(rt, \"\")\n}\n\nfunc (rt *runtime) newClassObject(class string) *object {\n\treturn newObject(rt, class)\n}\n\nfunc (rt *runtime) newPrimitiveObject(class string, value Value) *object {\n\to := rt.newClassObject(class)\n\to.value = value\n\treturn o\n}\n\nfunc (o *object) primitiveValue() Value {\n\tswitch value := o.value.(type) {\n\tcase Value:\n\t\treturn value\n\tcase stringObjecter:\n\t\treturn stringValue(value.String())\n\t}\n\treturn Value{}\n}\n\nfunc (o *object) hasPrimitive() bool { //nolint:unused\n\tswitch o.value.(type) {\n\tcase Value, stringObjecter:\n\t\treturn true\n\t}\n\treturn false\n}\n\nfunc (rt *runtime) newObject() *object {\n\to := rt.newClassObject(classObjectName)\n\to.prototype = rt.global.ObjectPrototype\n\treturn o\n}\n\nfunc (rt *runtime) newArray(length uint32) *object {\n\to := rt.newArrayObject(length)\n\to.prototype = rt.global.ArrayPrototype\n\treturn o\n}\n\nfunc (rt *runtime) newArrayOf(valueArray []Value) *object {\n\to := rt.newArray(uint32(len(valueArray)))\n\tfor index, value := range valueArray {\n\t\tif value.isEmpty() {\n\t\t\tcontinue\n\t\t}\n\t\to.defineProperty(strconv.FormatInt(int64(index), 10), value, 0o111, false)\n\t}\n\treturn o\n}\n\nfunc (rt *runtime) newString(value Value) *object {\n\to := rt.newStringObject(value)\n\to.prototype = rt.global.StringPrototype\n\treturn o\n}\n\nfunc (rt *runtime) newBoolean(value Value) *object {\n\to := rt.newBooleanObject(value)\n\to.prototype = rt.global.BooleanPrototype\n\treturn o\n}\n\nfunc (rt *runtime) newNumber(value Value) *object {\n\to := rt.newNumberObject(value)\n\to.prototype = rt.global.NumberPrototype\n\treturn o\n}\n\nfunc (rt *runtime) newRegExp(patternValue Value, flagsValue Value) *object {\n\tpattern := \"\"\n\tflags := \"\"\n\tif obj := patternValue.object(); obj != nil && obj.class == classRegExpName {\n\t\tif flagsValue.IsDefined() {\n\t\t\tpanic(rt.panicTypeError(\"Cannot supply flags when constructing one RegExp from another\"))\n\t\t}\n\t\tregExp := obj.regExpValue()\n\t\tpattern = regExp.source\n\t\tflags = regExp.flags\n\t} else {\n\t\tif patternValue.IsDefined() {\n\t\t\tpattern = patternValue.string()\n\t\t}\n\t\tif flagsValue.IsDefined() {\n\t\t\tflags = flagsValue.string()\n\t\t}\n\t}\n\n\treturn rt.newRegExpDirect(pattern, flags)\n}\n\nfunc (rt *runtime) newRegExpDirect(pattern string, flags string) *object {\n\to := rt.newRegExpObject(pattern, flags)\n\to.prototype = rt.global.RegExpPrototype\n\treturn o\n}\n\n// TODO Should (probably) be one argument, right? This is redundant.\nfunc (rt *runtime) newDate(epoch float64) *object {\n\to := rt.newDateObject(epoch)\n\to.prototype = rt.global.DatePrototype\n\treturn o\n}\n\nfunc (rt *runtime) newError(name string, message Value, stackFramesToPop int) *object {\n\tswitch name {\n\tcase \"EvalError\":\n\t\treturn rt.newEvalError(message)\n\tcase \"TypeError\":\n\t\treturn rt.newTypeError(message)\n\tcase \"RangeError\":\n\t\treturn rt.newRangeError(message)\n\tcase \"ReferenceError\":\n\t\treturn rt.newReferenceError(message)\n\tcase \"SyntaxError\":\n\t\treturn rt.newSyntaxError(message)\n\tcase \"URIError\":\n\t\treturn rt.newURIError(message)\n\t}\n\n\tobj := rt.newErrorObject(name, message, stackFramesToPop)\n\tobj.prototype = rt.global.ErrorPrototype\n\tif name != \"\" {\n\t\tobj.defineProperty(\"name\", stringValue(name), 0o111, false)\n\t}\n\treturn obj\n}\n\nfunc (rt *runtime) newNativeFunction(name, file string, line int, fn nativeFunction) *object {\n\to := rt.newNativeFunctionObject(name, file, line, fn, 0)\n\to.prototype = rt.global.FunctionPrototype\n\tprototype := rt.newObject()\n\to.defineProperty(\"prototype\", objectValue(prototype), 0o100, false)\n\tprototype.defineProperty(\"constructor\", objectValue(o), 0o100, false)\n\treturn o\n}\n\nfunc (rt *runtime) newNodeFunction(node *nodeFunctionLiteral, scopeEnvironment stasher) *object {\n\t// TODO Implement 13.2 fully\n\to := rt.newNodeFunctionObject(node, scopeEnvironment)\n\to.prototype = rt.global.FunctionPrototype\n\tprototype := rt.newObject()\n\to.defineProperty(\"prototype\", objectValue(prototype), 0o100, false)\n\tprototype.defineProperty(\"constructor\", objectValue(o), 0o101, false)\n\treturn o\n}\n\n// FIXME Only in one place...\nfunc (rt *runtime) newBoundFunction(target *object, this Value, argumentList []Value) *object {\n\to := rt.newBoundFunctionObject(target, this, argumentList)\n\to.prototype = rt.global.FunctionPrototype\n\tprototype := rt.newObject()\n\to.defineProperty(\"prototype\", objectValue(prototype), 0o100, false)\n\tprototype.defineProperty(\"constructor\", objectValue(o), 0o100, false)\n\treturn o\n}\n"
  },
  {
    "path": "global_test.go",
    "content": "package otto\n\nimport (\n\t\"fmt\"\n\t\"math\"\n\t\"strings\"\n\t\"testing\"\n)\n\nfunc TestGlobal(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, vm := test()\n\n\t\truntime := vm.vm.runtime\n\n\t\t{\n\t\t\tcall := func(obj interface{}, src string, argumentList ...interface{}) Value {\n\t\t\t\tvar tgt *Object\n\t\t\t\tswitch obj := obj.(type) {\n\t\t\t\tcase Value:\n\t\t\t\t\ttgt = obj.Object()\n\t\t\t\tcase *Object:\n\t\t\t\t\ttgt = obj\n\t\t\t\tcase *object:\n\t\t\t\t\ttgt = objectValue(obj).Object()\n\t\t\t\tdefault:\n\t\t\t\t\tpanic(\"Here be dragons.\")\n\t\t\t\t}\n\t\t\t\tvalue, err := tgt.Call(src, argumentList...)\n\t\t\t\tis(err, nil)\n\t\t\t\treturn value\n\t\t\t}\n\n\t\t\t// FIXME enterGlobalScope\n\t\t\tif false {\n\t\t\t\tvalue := runtime.scope.lexical.getBinding(classObjectName, false).object().call(UndefinedValue(), []Value{toValue(runtime.newObject())}, false, nativeFrame)\n\t\t\t\tis(value.IsObject(), true)\n\t\t\t\tis(value, \"[object Object]\")\n\t\t\t\tis(value.object().prototype == runtime.global.ObjectPrototype, true)\n\t\t\t\tis(value.object().prototype == runtime.global.Object.get(\"prototype\").object(), true)\n\t\t\t\tis(value.object().get(\"toString\"), \"function toString() { [native code] }\")\n\t\t\t\tis(call(value.Object(), \"hasOwnProperty\", \"hasOwnProperty\"), false)\n\n\t\t\t\tis(call(value.object().get(\"toString\").object().prototype, \"toString\"), \"function () { [native code] }\") // TODO Is this right?\n\t\t\t\tis(value.object().get(\"toString\").object().get(\"toString\"), \"function toString() { [native code] }\")\n\t\t\t\tis(value.object().get(\"toString\").object().get(\"toString\").object(), \"function toString() { [native code] }\")\n\n\t\t\t\tis(call(value.object(), \"propertyIsEnumerable\", \"isPrototypeOf\"), false)\n\t\t\t\tvalue.object().put(\"xyzzy\", stringValue(\"Nothing happens.\"), false)\n\t\t\t\tis(call(value, \"propertyIsEnumerable\", \"isPrototypeOf\"), false)\n\t\t\t\tis(call(value, \"propertyIsEnumerable\", \"xyzzy\"), true)\n\t\t\t\tis(value.object().get(\"xyzzy\"), \"Nothing happens.\")\n\n\t\t\t\tis(call(runtime.scope.lexical.getBinding(classObjectName, false), \"isPrototypeOf\", value), false)\n\t\t\t\tis(call(runtime.scope.lexical.getBinding(classObjectName, false).object().get(\"prototype\"), \"isPrototypeOf\", value), true)\n\t\t\t\tis(call(runtime.scope.lexical.getBinding(classFunctionName, false), \"isPrototypeOf\", value), false)\n\n\t\t\t\tis(runtime.newObject().prototype == runtime.global.Object.get(\"prototype\").object(), true)\n\n\t\t\t\tabc := runtime.newBoolean(boolValue(true))\n\t\t\t\tis(objectValue(abc), \"true\") // TODO Call primitive?\n\t\t\t}\n\t\t}\n\n\t\ttest(`new Number().constructor == Number`, true)\n\n\t\ttest(`this.hasOwnProperty`, \"function hasOwnProperty() { [native code] }\")\n\n\t\ttest(`eval.length === 1`, true)\n\t\ttest(`eval.prototype === undefined`, true)\n\t\ttest(`raise: new eval()`, \"TypeError: function eval() { [native code] } is not a constructor\")\n\n\t\ttest(`\n            [\n                [ delete undefined, undefined ],\n                [ delete NaN, NaN ],\n                [ delete Infinity, Infinity ],\n            ];\n        `, \"false,,false,NaN,false,Infinity\")\n\n\t\ttest(`\n            Object.getOwnPropertyNames(Function('return this')()).sort();\n        `, \"Array,Boolean,Date,Error,EvalError,Function,Infinity,JSON,Math,NaN,Number,Object,RangeError,ReferenceError,RegExp,String,SyntaxError,TypeError,URIError,console,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,escape,eval,isFinite,isNaN,parseFloat,parseInt,undefined,unescape\")\n\n\t\t// __defineGetter__,__defineSetter__,__lookupGetter__,__lookupSetter__,constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf\n\t\ttest(`\n            Object.getOwnPropertyNames(Object.prototype).sort();\n        `, \"constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf\")\n\n\t\t// arguments,caller,length,name,prototype\n\t\ttest(`\n            Object.getOwnPropertyNames(EvalError).sort();\n        `, \"length,prototype\")\n\n\t\ttest(`\n            var abc = [];\n            var def = [EvalError, RangeError, ReferenceError, SyntaxError, TypeError, URIError];\n            for (constructor in def) {\n                abc.push(def[constructor] === def[constructor].prototype.constructor);\n            }\n            def = [Array, Boolean, Date, Function, Number, Object, RegExp, String, SyntaxError];\n            for (constructor in def) {\n                abc.push(def[constructor] === def[constructor].prototype.constructor);\n            }\n            abc;\n        `, \"true,true,true,true,true,true,true,true,true,true,true,true,true,true,true\")\n\n\t\ttest(`\n            [ Array.prototype.constructor === Array, Array.constructor === Function ];\n        `, \"true,true\")\n\n\t\ttest(`\n            [ Number.prototype.constructor === Number, Number.constructor === Function ];\n        `, \"true,true\")\n\n\t\ttest(`\n            [ Function.prototype.constructor === Function, Function.constructor === Function ];\n        `, \"true,true\")\n\t})\n}\n\nfunc TestGlobalLength(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            [ Object.length, Function.length, RegExp.length, Math.length ];\n        `, \"1,1,2,\")\n\t})\n}\n\nfunc TestGlobalError(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            [ TypeError.length, TypeError(), TypeError(\"Nothing happens.\") ];\n        `, \"1,TypeError,TypeError: Nothing happens.\")\n\n\t\ttest(`\n            [ URIError.length, URIError(), URIError(\"Nothing happens.\") ];\n        `, \"1,URIError,URIError: Nothing happens.\")\n\t})\n}\n\nfunc TestGlobalReadOnly(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`Number.POSITIVE_INFINITY`, math.Inf(1))\n\n\t\ttest(`\n            Number.POSITIVE_INFINITY = 1;\n        `, 1)\n\n\t\ttest(`Number.POSITIVE_INFINITY`, math.Inf(1))\n\n\t\ttest(`\n            Number.POSITIVE_INFINITY = 1;\n            Number.POSITIVE_INFINITY;\n        `, math.Inf(1))\n\t})\n}\n\nfunc Test_isNaN(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`isNaN(0)`, false)\n\t\ttest(`isNaN(\"Xyzzy\")`, true)\n\t\ttest(`isNaN()`, true)\n\t\ttest(`isNaN(NaN)`, true)\n\t\ttest(`isNaN(Infinity)`, false)\n\n\t\ttest(`isNaN.length === 1`, true)\n\t\ttest(`isNaN.prototype === undefined`, true)\n\t})\n}\n\nfunc Test_isFinite(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`isFinite(0)`, true)\n\t\ttest(`isFinite(\"Xyzzy\")`, false)\n\t\ttest(`isFinite()`, false)\n\t\ttest(`isFinite(NaN)`, false)\n\t\ttest(`isFinite(Infinity)`, false)\n\t\ttest(`isFinite(new Number(451));`, true)\n\n\t\ttest(`isFinite.length === 1`, true)\n\t\ttest(`isFinite.prototype === undefined`, true)\n\t})\n}\n\nfunc Test_parseInt(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`parseInt(\"0\")`, 0)\n\t\ttest(`parseInt(\"11\")`, 11)\n\t\ttest(`parseInt(\" 11\")`, 11)\n\t\ttest(`parseInt(\"11 \")`, 11)\n\t\ttest(`parseInt(\" 11 \")`, 11)\n\t\ttest(`parseInt(\" 11\\n\")`, 11)\n\t\ttest(`parseInt(\" 11\\n\", 16)`, 17)\n\n\t\ttest(`parseInt(\"Xyzzy\")`, naN)\n\n\t\ttest(`parseInt(\" 0x11\\n\", 16)`, 17)\n\t\ttest(`parseInt(\"0x0aXyzzy\", 16)`, 10)\n\t\ttest(`parseInt(\"0x1\", 0)`, 1)\n\t\ttest(`parseInt(\"0x10000000000000000000\", 16)`, float64(75557863725914323419136))\n\n\t\ttest(`parseInt.length === 2`, true)\n\t\ttest(`parseInt.prototype === undefined`, true)\n\t})\n}\n\nfunc Test_parseFloat(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`parseFloat(\"0\")`, 0)\n\t\ttest(`parseFloat(\"11\")`, 11)\n\t\ttest(`parseFloat(\" 11\")`, 11)\n\t\ttest(`parseFloat(\"11 \")`, 11)\n\t\ttest(`parseFloat(\" 11 \")`, 11)\n\t\ttest(`parseFloat(\" 11\\n\")`, 11)\n\t\ttest(`parseFloat(\" 11\\n\", 16)`, 11)\n\t\ttest(`parseFloat(\"11.1\")`, 11.1)\n\n\t\ttest(`parseFloat(\"Xyzzy\")`, naN)\n\n\t\ttest(`parseFloat(\" 0x11\\n\", 16)`, 0)\n\t\ttest(`parseFloat(\"0x0a\")`, 0)\n\t\ttest(`parseFloat(\"0x0aXyzzy\")`, 0)\n\t\ttest(`parseFloat(\"Infinity\")`, infinity)\n\t\ttest(`parseFloat(\"infinity\")`, naN)\n\t\ttest(`parseFloat(\"0x\")`, 0)\n\t\ttest(`parseFloat(\"11x\")`, 11)\n\t\ttest(`parseFloat(\"Infinity1\")`, infinity)\n\n\t\ttest(`parseFloat.length === 1`, true)\n\t\ttest(`parseFloat.prototype === undefined`, true)\n\t})\n}\n\nfunc Test_encodeURI(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`encodeURI(\"http://example.com/ Nothing happens.\")`, \"http://example.com/%20Nothing%20happens.\")\n\t\ttest(`encodeURI(\"http://example.com/ _^#\")`, \"http://example.com/%20_%5E#\")\n\t\ttest(`encodeURI(String.fromCharCode(\"0xE000\"))`, \"%EE%80%80\")\n\t\ttest(`encodeURI(String.fromCharCode(\"0xFFFD\"))`, \"%EF%BF%BD\")\n\t\ttest(`raise: encodeURI(String.fromCharCode(\"0xDC00\"))`, \"URIError: URI malformed\")\n\n\t\ttest(`encodeURI.length === 1`, true)\n\t\ttest(`encodeURI.prototype === undefined`, true)\n\t})\n}\n\nfunc Test_encodeURIComponent(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`encodeURIComponent(\"http://example.com/ Nothing happens.\")`, \"http%3A%2F%2Fexample.com%2F%20Nothing%20happens.\")\n\t\ttest(`encodeURIComponent(\"http://example.com/ _^#\")`, \"http%3A%2F%2Fexample.com%2F%20_%5E%23\")\n\t})\n}\n\nfunc Test_decodeURI(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`decodeURI(encodeURI(\"http://example.com/ Nothing happens.\"))`, \"http://example.com/ Nothing happens.\")\n\t\ttest(`decodeURI(encodeURI(\"http://example.com/ _^#\"))`, \"http://example.com/ _^#\")\n\t\ttest(`raise: decodeURI(\"http://example.com/ _^#%\")`, \"URIError: URI malformed\")\n\t\ttest(`raise: decodeURI(\"%DF%7F\")`, \"URIError: URI malformed\")\n\t\tfor _, check := range strings.Fields(\"+ %3B %2F %3F %3A %40 %26 %3D %2B %24 %2C %23\") {\n\t\t\ttest(fmt.Sprintf(`decodeURI(\"%s\")`, check), check)\n\t\t}\n\n\t\ttest(`decodeURI.length === 1`, true)\n\t\ttest(`decodeURI.prototype === undefined`, true)\n\t})\n}\n\nfunc Test_decodeURIComponent(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`decodeURIComponent(encodeURI(\"http://example.com/ Nothing happens.\"))`, \"http://example.com/ Nothing happens.\")\n\t\ttest(`decodeURIComponent(encodeURI(\"http://example.com/ _^#\"))`, \"http://example.com/ _^#\")\n\n\t\ttest(`decodeURIComponent.length === 1`, true)\n\t\ttest(`decodeURIComponent.prototype === undefined`, true)\n\n\t\ttest(`\n        var global = Function('return this')();\n        var abc = Object.getOwnPropertyDescriptor(global, \"decodeURIComponent\");\n        [ abc.value === global.decodeURIComponent, abc.writable, abc.enumerable, abc.configurable ];\n    `, \"true,true,false,true\")\n\t})\n}\n\nfunc TestGlobal_skipEnumeration(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            var found = [];\n            for (var test in this) {\n                if (false ||\n                    test === 'NaN' ||\n                    test === 'undefined' ||\n                    test === 'Infinity' ||\n                    false) {\n                    found.push(test)\n                }\n            }\n            found.length;\n        `, 0)\n\n\t\ttest(`\n            var found = [];\n            for (var test in this) {\n                if (false ||\n                    test === 'Object' ||\n                    test === 'Function' ||\n                    test === 'String' ||\n                    test === 'Number' ||\n                    test === 'Array' ||\n                    test === 'Boolean' ||\n                    test === 'Date' ||\n                    test === 'RegExp' ||\n                    test === 'Error' ||\n                    test === 'EvalError' ||\n                    test === 'RangeError' ||\n                    test === 'ReferenceError' ||\n                    test === 'SyntaxError' ||\n                    test === 'TypeError' ||\n                    test === 'URIError' ||\n                    false) {\n                    found.push(test)\n                }\n            }\n            found.length;\n        `, 0)\n\t})\n}\n"
  },
  {
    "path": "go.mod",
    "content": "module github.com/robertkrimen/otto\n\ngo 1.22\n\nrequire (\n\tgithub.com/stretchr/testify v1.8.1\n\tgolang.org/x/text v0.4.0\n\tgopkg.in/readline.v1 v1.0.0-20160726135117-62c6fe619375\n\tgopkg.in/sourcemap.v1 v1.0.5\n\tgopkg.in/yaml.v3 v3.0.1\n)\n\nrequire (\n\tgithub.com/chzyer/test v1.0.0 // indirect\n\tgithub.com/davecgh/go-spew v1.1.1 // indirect\n\tgithub.com/pmezard/go-difflib v1.0.0 // indirect\n)\n"
  },
  {
    "path": "go.sum",
    "content": "github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM=\ngithub.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ=\ngithub.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04=\ngithub.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8=\ngithub.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=\ngithub.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=\ngithub.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=\ngithub.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=\ngithub.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=\ngithub.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=\ngithub.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=\ngithub.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=\ngithub.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=\ngithub.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=\ngithub.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=\ngolang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=\ngolang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=\ngopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=\ngopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=\ngopkg.in/readline.v1 v1.0.0-20160726135117-62c6fe619375 h1:hPki/oSSWOLiI9Gc9jyIoj33O3j29fUc9PlLha2yDj0=\ngopkg.in/readline.v1 v1.0.0-20160726135117-62c6fe619375/go.mod h1:lNEQeAhU009zbRxng+XOj5ITVgY24WcbNnQopyfKoYQ=\ngopkg.in/sourcemap.v1 v1.0.5 h1:inv58fC9f9J3TK2Y2R1NPntXEn3/wjWHkonhIUODNTI=\ngopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78=\ngopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\ngopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=\ngopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=\n"
  },
  {
    "path": "inline.go",
    "content": "// Code generated by tools/gen-jscore. DO NOT EDIT.\n\npackage otto\n\nimport (\n\t\"math\"\n)\n\nfunc (rt *runtime) newContext() {\n\t// Order here is import as definitions depend on each other.\n\n\t// Object prototype.\n\trt.global.ObjectPrototype = &object{\n\t\truntime:     rt,\n\t\tclass:       classObjectName,\n\t\tobjectClass: classObject,\n\t\tprototype:   nil,\n\t\textensible:  true,\n\t\tvalue:       prototypeValueObject,\n\t}\n\n\t// Function prototype.\n\trt.global.FunctionPrototype = &object{\n\t\truntime:     rt,\n\t\tclass:       classFunctionName,\n\t\tobjectClass: classObject,\n\t\tprototype:   rt.global.ObjectPrototype,\n\t\textensible:  true,\n\t\tvalue:       prototypeValueFunction,\n\t}\n\n\t// Object prototype property definition.\n\trt.global.ObjectPrototype.property = map[string]property{\n\t\t\"hasOwnProperty\": {\n\t\t\tmode: 0o101,\n\t\t\tvalue: Value{\n\t\t\t\tkind: valueObject,\n\t\t\t\tvalue: &object{\n\t\t\t\t\truntime:     rt,\n\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\textensible:  true,\n\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\tvalue: \"hasOwnProperty\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t},\n\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\tname: \"hasOwnProperty\",\n\t\t\t\t\t\tcall: builtinObjectHasOwnProperty,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t\"isPrototypeOf\": {\n\t\t\tmode: 0o101,\n\t\t\tvalue: Value{\n\t\t\t\tkind: valueObject,\n\t\t\t\tvalue: &object{\n\t\t\t\t\truntime:     rt,\n\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\textensible:  true,\n\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\tvalue: \"isPrototypeOf\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t},\n\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\tname: \"isPrototypeOf\",\n\t\t\t\t\t\tcall: builtinObjectIsPrototypeOf,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t\"propertyIsEnumerable\": {\n\t\t\tmode: 0o101,\n\t\t\tvalue: Value{\n\t\t\t\tkind: valueObject,\n\t\t\t\tvalue: &object{\n\t\t\t\t\truntime:     rt,\n\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\textensible:  true,\n\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\tvalue: \"propertyIsEnumerable\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t},\n\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\tname: \"propertyIsEnumerable\",\n\t\t\t\t\t\tcall: builtinObjectPropertyIsEnumerable,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tmethodToString: {\n\t\t\tmode: 0o101,\n\t\t\tvalue: Value{\n\t\t\t\tkind: valueObject,\n\t\t\t\tvalue: &object{\n\t\t\t\t\truntime:     rt,\n\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\textensible:  true,\n\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\tvalue: \"toString\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t},\n\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\tname: methodToString,\n\t\t\t\t\t\tcall: builtinObjectToString,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t\"valueOf\": {\n\t\t\tmode: 0o101,\n\t\t\tvalue: Value{\n\t\t\t\tkind: valueObject,\n\t\t\t\tvalue: &object{\n\t\t\t\t\truntime:     rt,\n\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\textensible:  true,\n\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\tvalue: \"valueOf\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t},\n\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\tname: \"valueOf\",\n\t\t\t\t\t\tcall: builtinObjectValueOf,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t\"toLocaleString\": {\n\t\t\tmode: 0o101,\n\t\t\tvalue: Value{\n\t\t\t\tkind: valueObject,\n\t\t\t\tvalue: &object{\n\t\t\t\t\truntime:     rt,\n\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\textensible:  true,\n\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\tvalue: \"toLocaleString\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t},\n\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\tname: \"toLocaleString\",\n\t\t\t\t\t\tcall: builtinObjectToLocaleString,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t}\n\trt.global.ObjectPrototype.propertyOrder = []string{\n\t\tpropertyConstructor,\n\t\t\"hasOwnProperty\",\n\t\t\"isPrototypeOf\",\n\t\t\"propertyIsEnumerable\",\n\t\tmethodToString,\n\t\t\"valueOf\",\n\t\t\"toLocaleString\",\n\t}\n\n\t// Function prototype property definition.\n\trt.global.FunctionPrototype.property = map[string]property{\n\t\tmethodToString: {\n\t\t\tmode: 0o101,\n\t\t\tvalue: Value{\n\t\t\t\tkind: valueObject,\n\t\t\t\tvalue: &object{\n\t\t\t\t\truntime:     rt,\n\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\textensible:  true,\n\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\tvalue: \"toString\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t},\n\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\tname: methodToString,\n\t\t\t\t\t\tcall: builtinFunctionToString,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t\"apply\": {\n\t\t\tmode: 0o101,\n\t\t\tvalue: Value{\n\t\t\t\tkind: valueObject,\n\t\t\t\tvalue: &object{\n\t\t\t\t\truntime:     rt,\n\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\textensible:  true,\n\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\tvalue: 2,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\tvalue: \"apply\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t},\n\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\tname: \"apply\",\n\t\t\t\t\t\tcall: builtinFunctionApply,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t\"call\": {\n\t\t\tmode: 0o101,\n\t\t\tvalue: Value{\n\t\t\t\tkind: valueObject,\n\t\t\t\tvalue: &object{\n\t\t\t\t\truntime:     rt,\n\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\textensible:  true,\n\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\tvalue: \"call\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t},\n\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\tname: \"call\",\n\t\t\t\t\t\tcall: builtinFunctionCall,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t\"bind\": {\n\t\t\tmode: 0o101,\n\t\t\tvalue: Value{\n\t\t\t\tkind: valueObject,\n\t\t\t\tvalue: &object{\n\t\t\t\t\truntime:     rt,\n\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\textensible:  true,\n\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\tvalue: \"bind\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t},\n\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\tname: \"bind\",\n\t\t\t\t\t\tcall: builtinFunctionBind,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tpropertyLength: {\n\t\t\tmode: 0,\n\t\t\tvalue: Value{\n\t\t\t\tkind:  valueNumber,\n\t\t\t\tvalue: 0,\n\t\t\t},\n\t\t},\n\t}\n\trt.global.FunctionPrototype.propertyOrder = []string{\n\t\tmethodToString,\n\t\t\"apply\",\n\t\t\"call\",\n\t\t\"bind\",\n\t\tpropertyConstructor,\n\t\tpropertyLength,\n\t}\n\n\t// Object definition.\n\trt.global.Object = &object{\n\t\truntime:     rt,\n\t\tclass:       classFunctionName,\n\t\tobjectClass: classObject,\n\t\tprototype:   rt.global.FunctionPrototype,\n\t\textensible:  true,\n\t\tvalue: nativeFunctionObject{\n\t\t\tname:      classObjectName,\n\t\t\tcall:      builtinObject,\n\t\t\tconstruct: builtinNewObject,\n\t\t},\n\t\tproperty: map[string]property{\n\t\t\tpropertyLength: {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\tvalue: 1,\n\t\t\t\t},\n\t\t\t},\n\t\t\tpropertyPrototype: {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueObject,\n\t\t\t\t\tvalue: rt.global.ObjectPrototype,\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"getPrototypeOf\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"getPrototypeOf\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"getPrototypeOf\",\n\t\t\t\t\t\t\tcall: builtinObjectGetPrototypeOf,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"assign\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"assign\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"assign\",\n\t\t\t\t\t\t\tcall: builtinObjectAssign,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"getOwnPropertyDescriptor\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 2,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"getOwnPropertyDescriptor\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"getOwnPropertyDescriptor\",\n\t\t\t\t\t\t\tcall: builtinObjectGetOwnPropertyDescriptor,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"defineProperty\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 3,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"defineProperty\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"defineProperty\",\n\t\t\t\t\t\t\tcall: builtinObjectDefineProperty,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"defineProperties\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 2,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"defineProperties\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"defineProperties\",\n\t\t\t\t\t\t\tcall: builtinObjectDefineProperties,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"create\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 2,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"create\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"create\",\n\t\t\t\t\t\t\tcall: builtinObjectCreate,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"isExtensible\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"isExtensible\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"isExtensible\",\n\t\t\t\t\t\t\tcall: builtinObjectIsExtensible,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"preventExtensions\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"preventExtensions\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"preventExtensions\",\n\t\t\t\t\t\t\tcall: builtinObjectPreventExtensions,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"isSealed\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"isSealed\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"isSealed\",\n\t\t\t\t\t\t\tcall: builtinObjectIsSealed,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"seal\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"seal\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"seal\",\n\t\t\t\t\t\t\tcall: builtinObjectSeal,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"isFrozen\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"isFrozen\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"isFrozen\",\n\t\t\t\t\t\t\tcall: builtinObjectIsFrozen,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"freeze\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"freeze\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"freeze\",\n\t\t\t\t\t\t\tcall: builtinObjectFreeze,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"keys\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"keys\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"keys\",\n\t\t\t\t\t\t\tcall: builtinObjectKeys,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"values\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"values\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"values\",\n\t\t\t\t\t\t\tcall: builtinObjectValues,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"getOwnPropertyNames\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"getOwnPropertyNames\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"getOwnPropertyNames\",\n\t\t\t\t\t\t\tcall: builtinObjectGetOwnPropertyNames,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tpropertyOrder: []string{\n\t\t\tpropertyLength,\n\t\t\tpropertyPrototype,\n\t\t\t\"getPrototypeOf\",\n\t\t\t\"assign\",\n\t\t\t\"getOwnPropertyDescriptor\",\n\t\t\t\"defineProperty\",\n\t\t\t\"defineProperties\",\n\t\t\t\"create\",\n\t\t\t\"isExtensible\",\n\t\t\t\"preventExtensions\",\n\t\t\t\"isSealed\",\n\t\t\t\"seal\",\n\t\t\t\"isFrozen\",\n\t\t\t\"freeze\",\n\t\t\t\"keys\",\n\t\t\t\"values\",\n\t\t\t\"getOwnPropertyNames\",\n\t\t},\n\t}\n\n\t// Object constructor definition.\n\trt.global.ObjectPrototype.property[propertyConstructor] = property{\n\t\tmode: 0o101,\n\t\tvalue: Value{\n\t\t\tkind:  valueObject,\n\t\t\tvalue: rt.global.Object,\n\t\t},\n\t}\n\n\t// Function definition.\n\trt.global.Function = &object{\n\t\truntime:     rt,\n\t\tclass:       classFunctionName,\n\t\tobjectClass: classObject,\n\t\tprototype:   rt.global.FunctionPrototype,\n\t\textensible:  true,\n\t\tvalue: nativeFunctionObject{\n\t\t\tname:      classFunctionName,\n\t\t\tcall:      builtinFunction,\n\t\t\tconstruct: builtinNewFunction,\n\t\t},\n\t\tproperty: map[string]property{\n\t\t\tpropertyLength: {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\tvalue: 1,\n\t\t\t\t},\n\t\t\t},\n\t\t\tpropertyPrototype: {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueObject,\n\t\t\t\t\tvalue: rt.global.FunctionPrototype,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tpropertyOrder: []string{\n\t\t\tpropertyLength,\n\t\t\tpropertyPrototype,\n\t\t},\n\t}\n\n\t// Function constructor definition.\n\trt.global.FunctionPrototype.property[propertyConstructor] = property{\n\t\tmode: 0o101,\n\t\tvalue: Value{\n\t\t\tkind:  valueObject,\n\t\t\tvalue: rt.global.Function,\n\t\t},\n\t}\n\n\t// Array prototype.\n\trt.global.ArrayPrototype = &object{\n\t\truntime:     rt,\n\t\tclass:       classArrayName,\n\t\tobjectClass: classArray,\n\t\tprototype:   rt.global.ObjectPrototype,\n\t\textensible:  true,\n\t\tvalue:       nil,\n\t\tproperty: map[string]property{\n\t\t\tpropertyLength: {\n\t\t\t\tmode: 0o100,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\tvalue: uint32(0),\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"concat\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"concat\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"concat\",\n\t\t\t\t\t\t\tcall: builtinArrayConcat,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"lastIndexOf\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"lastIndexOf\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"lastIndexOf\",\n\t\t\t\t\t\t\tcall: builtinArrayLastIndexOf,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"pop\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"pop\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"pop\",\n\t\t\t\t\t\t\tcall: builtinArrayPop,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"push\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"push\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"push\",\n\t\t\t\t\t\t\tcall: builtinArrayPush,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"reverse\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"reverse\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"reverse\",\n\t\t\t\t\t\t\tcall: builtinArrayReverse,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"shift\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"shift\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"shift\",\n\t\t\t\t\t\t\tcall: builtinArrayShift,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"unshift\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"unshift\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"unshift\",\n\t\t\t\t\t\t\tcall: builtinArrayUnshift,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"slice\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 2,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"slice\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"slice\",\n\t\t\t\t\t\t\tcall: builtinArraySlice,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"sort\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"sort\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"sort\",\n\t\t\t\t\t\t\tcall: builtinArraySort,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"splice\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 2,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"splice\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"splice\",\n\t\t\t\t\t\t\tcall: builtinArraySplice,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"indexOf\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"indexOf\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"indexOf\",\n\t\t\t\t\t\t\tcall: builtinArrayIndexOf,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"join\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"join\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"join\",\n\t\t\t\t\t\t\tcall: builtinArrayJoin,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"forEach\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"forEach\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"forEach\",\n\t\t\t\t\t\t\tcall: builtinArrayForEach,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"filter\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"filter\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"filter\",\n\t\t\t\t\t\t\tcall: builtinArrayFilter,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"map\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"map\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"map\",\n\t\t\t\t\t\t\tcall: builtinArrayMap,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"every\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"every\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"every\",\n\t\t\t\t\t\t\tcall: builtinArrayEvery,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"some\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"some\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"some\",\n\t\t\t\t\t\t\tcall: builtinArraySome,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"reduce\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"reduce\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"reduce\",\n\t\t\t\t\t\t\tcall: builtinArrayReduce,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"reduceRight\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"reduceRight\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"reduceRight\",\n\t\t\t\t\t\t\tcall: builtinArrayReduceRight,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"toLocaleString\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"toLocaleString\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"toLocaleString\",\n\t\t\t\t\t\t\tcall: builtinArrayToLocaleString,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tmethodToString: {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"toString\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: methodToString,\n\t\t\t\t\t\t\tcall: builtinArrayToString,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tpropertyOrder: []string{\n\t\t\tpropertyLength,\n\t\t\tpropertyConstructor,\n\t\t\t\"concat\",\n\t\t\t\"lastIndexOf\",\n\t\t\t\"pop\",\n\t\t\t\"push\",\n\t\t\t\"reverse\",\n\t\t\t\"shift\",\n\t\t\t\"unshift\",\n\t\t\t\"slice\",\n\t\t\t\"sort\",\n\t\t\t\"splice\",\n\t\t\t\"indexOf\",\n\t\t\t\"join\",\n\t\t\t\"forEach\",\n\t\t\t\"filter\",\n\t\t\t\"map\",\n\t\t\t\"every\",\n\t\t\t\"some\",\n\t\t\t\"reduce\",\n\t\t\t\"reduceRight\",\n\t\t\t\"toLocaleString\",\n\t\t\tmethodToString,\n\t\t},\n\t}\n\n\t// Array definition.\n\trt.global.Array = &object{\n\t\truntime:     rt,\n\t\tclass:       classFunctionName,\n\t\tobjectClass: classObject,\n\t\tprototype:   rt.global.FunctionPrototype,\n\t\textensible:  true,\n\t\tvalue: nativeFunctionObject{\n\t\t\tname:      classArrayName,\n\t\t\tcall:      builtinArray,\n\t\t\tconstruct: builtinNewArray,\n\t\t},\n\t\tproperty: map[string]property{\n\t\t\tpropertyLength: {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\tvalue: 1,\n\t\t\t\t},\n\t\t\t},\n\t\t\tpropertyPrototype: {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueObject,\n\t\t\t\t\tvalue: rt.global.ArrayPrototype,\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"isArray\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"isArray\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"isArray\",\n\t\t\t\t\t\t\tcall: builtinArrayIsArray,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tpropertyOrder: []string{\n\t\t\tpropertyLength,\n\t\t\tpropertyPrototype,\n\t\t\t\"isArray\",\n\t\t},\n\t}\n\n\t// Array constructor definition.\n\trt.global.ArrayPrototype.property[propertyConstructor] = property{\n\t\tmode: 0o101,\n\t\tvalue: Value{\n\t\t\tkind:  valueObject,\n\t\t\tvalue: rt.global.Array,\n\t\t},\n\t}\n\n\t// String prototype.\n\trt.global.StringPrototype = &object{\n\t\truntime:     rt,\n\t\tclass:       classStringName,\n\t\tobjectClass: classString,\n\t\tprototype:   rt.global.ObjectPrototype,\n\t\textensible:  true,\n\t\tvalue:       prototypeValueString,\n\t\tproperty: map[string]property{\n\t\t\tpropertyLength: {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\tvalue: int(0),\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"charAt\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"charAt\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"charAt\",\n\t\t\t\t\t\t\tcall: builtinStringCharAt,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"charCodeAt\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"charCodeAt\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"charCodeAt\",\n\t\t\t\t\t\t\tcall: builtinStringCharCodeAt,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"concat\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"concat\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"concat\",\n\t\t\t\t\t\t\tcall: builtinStringConcat,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"indexOf\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"indexOf\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"indexOf\",\n\t\t\t\t\t\t\tcall: builtinStringIndexOf,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"lastIndexOf\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"lastIndexOf\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"lastIndexOf\",\n\t\t\t\t\t\t\tcall: builtinStringLastIndexOf,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"localeCompare\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"localeCompare\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"localeCompare\",\n\t\t\t\t\t\t\tcall: builtinStringLocaleCompare,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"match\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"match\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"match\",\n\t\t\t\t\t\t\tcall: builtinStringMatch,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"replace\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 2,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"replace\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"replace\",\n\t\t\t\t\t\t\tcall: builtinStringReplace,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"search\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"search\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"search\",\n\t\t\t\t\t\t\tcall: builtinStringSearch,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"slice\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 2,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"slice\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"slice\",\n\t\t\t\t\t\t\tcall: builtinStringSlice,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"split\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 2,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"split\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"split\",\n\t\t\t\t\t\t\tcall: builtinStringSplit,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"substr\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 2,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"substr\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"substr\",\n\t\t\t\t\t\t\tcall: builtinStringSubstr,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"substring\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 2,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"substring\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"substring\",\n\t\t\t\t\t\t\tcall: builtinStringSubstring,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"startsWith\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"startsWith\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"startsWith\",\n\t\t\t\t\t\t\tcall: builtinStringStartsWith,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tmethodToString: {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"toString\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: methodToString,\n\t\t\t\t\t\t\tcall: builtinStringToString,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"trim\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"trim\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"trim\",\n\t\t\t\t\t\t\tcall: builtinStringTrim,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"trimLeft\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"trimLeft\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"trimLeft\",\n\t\t\t\t\t\t\tcall: builtinStringTrimLeft,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"trimRight\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"trimRight\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"trimRight\",\n\t\t\t\t\t\t\tcall: builtinStringTrimRight,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"trimStart\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"trimStart\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"trimStart\",\n\t\t\t\t\t\t\tcall: builtinStringTrimStart,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"trimEnd\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"trimEnd\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"trimEnd\",\n\t\t\t\t\t\t\tcall: builtinStringTrimEnd,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"toLocaleLowerCase\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"toLocaleLowerCase\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"toLocaleLowerCase\",\n\t\t\t\t\t\t\tcall: builtinStringToLocaleLowerCase,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"toLocaleUpperCase\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"toLocaleUpperCase\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"toLocaleUpperCase\",\n\t\t\t\t\t\t\tcall: builtinStringToLocaleUpperCase,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"toLowerCase\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"toLowerCase\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"toLowerCase\",\n\t\t\t\t\t\t\tcall: builtinStringToLowerCase,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"toUpperCase\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"toUpperCase\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"toUpperCase\",\n\t\t\t\t\t\t\tcall: builtinStringToUpperCase,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"valueOf\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"valueOf\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"valueOf\",\n\t\t\t\t\t\t\tcall: builtinStringValueOf,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tpropertyOrder: []string{\n\t\t\tpropertyLength,\n\t\t\tpropertyConstructor,\n\t\t\t\"charAt\",\n\t\t\t\"charCodeAt\",\n\t\t\t\"concat\",\n\t\t\t\"indexOf\",\n\t\t\t\"lastIndexOf\",\n\t\t\t\"localeCompare\",\n\t\t\t\"match\",\n\t\t\t\"replace\",\n\t\t\t\"search\",\n\t\t\t\"slice\",\n\t\t\t\"split\",\n\t\t\t\"substr\",\n\t\t\t\"substring\",\n\t\t\t\"startsWith\",\n\t\t\tmethodToString,\n\t\t\t\"trim\",\n\t\t\t\"trimLeft\",\n\t\t\t\"trimRight\",\n\t\t\t\"trimStart\",\n\t\t\t\"trimEnd\",\n\t\t\t\"toLocaleLowerCase\",\n\t\t\t\"toLocaleUpperCase\",\n\t\t\t\"toLowerCase\",\n\t\t\t\"toUpperCase\",\n\t\t\t\"valueOf\",\n\t\t},\n\t}\n\n\t// String definition.\n\trt.global.String = &object{\n\t\truntime:     rt,\n\t\tclass:       classFunctionName,\n\t\tobjectClass: classObject,\n\t\tprototype:   rt.global.FunctionPrototype,\n\t\textensible:  true,\n\t\tvalue: nativeFunctionObject{\n\t\t\tname:      classStringName,\n\t\t\tcall:      builtinString,\n\t\t\tconstruct: builtinNewString,\n\t\t},\n\t\tproperty: map[string]property{\n\t\t\tpropertyLength: {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\tvalue: 1,\n\t\t\t\t},\n\t\t\t},\n\t\t\tpropertyPrototype: {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueObject,\n\t\t\t\t\tvalue: rt.global.StringPrototype,\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"fromCharCode\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"fromCharCode\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"fromCharCode\",\n\t\t\t\t\t\t\tcall: builtinStringFromCharCode,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tpropertyOrder: []string{\n\t\t\tpropertyLength,\n\t\t\tpropertyPrototype,\n\t\t\t\"fromCharCode\",\n\t\t},\n\t}\n\n\t// String constructor definition.\n\trt.global.StringPrototype.property[propertyConstructor] = property{\n\t\tmode: 0o101,\n\t\tvalue: Value{\n\t\t\tkind:  valueObject,\n\t\t\tvalue: rt.global.String,\n\t\t},\n\t}\n\n\t// Boolean prototype.\n\trt.global.BooleanPrototype = &object{\n\t\truntime:     rt,\n\t\tclass:       classBooleanName,\n\t\tobjectClass: classObject,\n\t\tprototype:   rt.global.ObjectPrototype,\n\t\textensible:  true,\n\t\tvalue:       prototypeValueBoolean,\n\t\tproperty: map[string]property{\n\t\t\tmethodToString: {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"toString\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: methodToString,\n\t\t\t\t\t\t\tcall: builtinBooleanToString,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"valueOf\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"valueOf\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"valueOf\",\n\t\t\t\t\t\t\tcall: builtinBooleanValueOf,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tpropertyOrder: []string{\n\t\t\tpropertyConstructor,\n\t\t\tmethodToString,\n\t\t\t\"valueOf\",\n\t\t},\n\t}\n\n\t// Boolean definition.\n\trt.global.Boolean = &object{\n\t\truntime:     rt,\n\t\tclass:       classFunctionName,\n\t\tobjectClass: classObject,\n\t\tprototype:   rt.global.FunctionPrototype,\n\t\textensible:  true,\n\t\tvalue: nativeFunctionObject{\n\t\t\tname:      classBooleanName,\n\t\t\tcall:      builtinBoolean,\n\t\t\tconstruct: builtinNewBoolean,\n\t\t},\n\t\tproperty: map[string]property{\n\t\t\tpropertyLength: {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\tvalue: 1,\n\t\t\t\t},\n\t\t\t},\n\t\t\tpropertyPrototype: {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueObject,\n\t\t\t\t\tvalue: rt.global.BooleanPrototype,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tpropertyOrder: []string{\n\t\t\tpropertyLength,\n\t\t\tpropertyPrototype,\n\t\t},\n\t}\n\n\t// Boolean constructor definition.\n\trt.global.BooleanPrototype.property[propertyConstructor] = property{\n\t\tmode: 0o101,\n\t\tvalue: Value{\n\t\t\tkind:  valueObject,\n\t\t\tvalue: rt.global.Boolean,\n\t\t},\n\t}\n\n\t// Number prototype.\n\trt.global.NumberPrototype = &object{\n\t\truntime:     rt,\n\t\tclass:       classNumberName,\n\t\tobjectClass: classObject,\n\t\tprototype:   rt.global.ObjectPrototype,\n\t\textensible:  true,\n\t\tvalue:       prototypeValueNumber,\n\t\tproperty: map[string]property{\n\t\t\t\"toExponential\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"toExponential\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"toExponential\",\n\t\t\t\t\t\t\tcall: builtinNumberToExponential,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"toFixed\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"toFixed\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"toFixed\",\n\t\t\t\t\t\t\tcall: builtinNumberToFixed,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"toPrecision\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"toPrecision\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"toPrecision\",\n\t\t\t\t\t\t\tcall: builtinNumberToPrecision,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tmethodToString: {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"toString\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: methodToString,\n\t\t\t\t\t\t\tcall: builtinNumberToString,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"valueOf\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"valueOf\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"valueOf\",\n\t\t\t\t\t\t\tcall: builtinNumberValueOf,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"toLocaleString\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"toLocaleString\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"toLocaleString\",\n\t\t\t\t\t\t\tcall: builtinNumberToLocaleString,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tpropertyOrder: []string{\n\t\t\tpropertyConstructor,\n\t\t\t\"toExponential\",\n\t\t\t\"toFixed\",\n\t\t\t\"toPrecision\",\n\t\t\tmethodToString,\n\t\t\t\"valueOf\",\n\t\t\t\"toLocaleString\",\n\t\t},\n\t}\n\n\t// Number definition.\n\trt.global.Number = &object{\n\t\truntime:     rt,\n\t\tclass:       classFunctionName,\n\t\tobjectClass: classObject,\n\t\tprototype:   rt.global.FunctionPrototype,\n\t\textensible:  true,\n\t\tvalue: nativeFunctionObject{\n\t\t\tname:      classNumberName,\n\t\t\tcall:      builtinNumber,\n\t\t\tconstruct: builtinNewNumber,\n\t\t},\n\t\tproperty: map[string]property{\n\t\t\tpropertyLength: {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\tvalue: 1,\n\t\t\t\t},\n\t\t\t},\n\t\t\tpropertyPrototype: {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueObject,\n\t\t\t\t\tvalue: rt.global.NumberPrototype,\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"isNaN\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"isNaN\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"isNaN\",\n\t\t\t\t\t\t\tcall: builtinNumberIsNaN,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"MAX_VALUE\": {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\tvalue: math.MaxFloat64,\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"MIN_VALUE\": {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\tvalue: math.SmallestNonzeroFloat64,\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"NaN\": {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\tvalue: math.NaN(),\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"NEGATIVE_INFINITY\": {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\tvalue: math.Inf(-1),\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"POSITIVE_INFINITY\": {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\tvalue: math.Inf(+1),\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tpropertyOrder: []string{\n\t\t\tpropertyLength,\n\t\t\tpropertyPrototype,\n\t\t\t\"isNaN\",\n\t\t\t\"MAX_VALUE\",\n\t\t\t\"MIN_VALUE\",\n\t\t\t\"NaN\",\n\t\t\t\"NEGATIVE_INFINITY\",\n\t\t\t\"POSITIVE_INFINITY\",\n\t\t},\n\t}\n\n\t// Number constructor definition.\n\trt.global.NumberPrototype.property[propertyConstructor] = property{\n\t\tmode: 0o101,\n\t\tvalue: Value{\n\t\t\tkind:  valueObject,\n\t\t\tvalue: rt.global.Number,\n\t\t},\n\t}\n\n\t// Math definition.\n\trt.global.Math = &object{\n\t\truntime:     rt,\n\t\tclass:       classMathName,\n\t\tobjectClass: classObject,\n\t\tprototype:   rt.global.ObjectPrototype,\n\t\textensible:  true,\n\t\tproperty: map[string]property{\n\t\t\t\"abs\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"abs\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"abs\",\n\t\t\t\t\t\t\tcall: builtinMathAbs,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"acos\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"acos\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"acos\",\n\t\t\t\t\t\t\tcall: builtinMathAcos,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"acosh\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"acosh\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"acosh\",\n\t\t\t\t\t\t\tcall: builtinMathAcosh,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"asin\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"asin\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"asin\",\n\t\t\t\t\t\t\tcall: builtinMathAsin,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"asinh\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"asinh\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"asinh\",\n\t\t\t\t\t\t\tcall: builtinMathAsinh,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"atan\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"atan\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"atan\",\n\t\t\t\t\t\t\tcall: builtinMathAtan,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"atanh\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"atanh\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"atanh\",\n\t\t\t\t\t\t\tcall: builtinMathAtanh,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"atan2\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"atan2\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"atan2\",\n\t\t\t\t\t\t\tcall: builtinMathAtan2,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"cbrt\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"cbrt\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"cbrt\",\n\t\t\t\t\t\t\tcall: builtinMathCbrt,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"ceil\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"ceil\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"ceil\",\n\t\t\t\t\t\t\tcall: builtinMathCeil,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"cos\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"cos\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"cos\",\n\t\t\t\t\t\t\tcall: builtinMathCos,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"cosh\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"cosh\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"cosh\",\n\t\t\t\t\t\t\tcall: builtinMathCosh,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"exp\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"exp\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"exp\",\n\t\t\t\t\t\t\tcall: builtinMathExp,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"expm1\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"expm1\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"expm1\",\n\t\t\t\t\t\t\tcall: builtinMathExpm1,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"floor\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"floor\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"floor\",\n\t\t\t\t\t\t\tcall: builtinMathFloor,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"log\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"log\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"log\",\n\t\t\t\t\t\t\tcall: builtinMathLog,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"log10\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"log10\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"log10\",\n\t\t\t\t\t\t\tcall: builtinMathLog10,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"log1p\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"log1p\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"log1p\",\n\t\t\t\t\t\t\tcall: builtinMathLog1p,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"log2\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"log2\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"log2\",\n\t\t\t\t\t\t\tcall: builtinMathLog2,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"max\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 2,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"max\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"max\",\n\t\t\t\t\t\t\tcall: builtinMathMax,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"min\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 2,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"min\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"min\",\n\t\t\t\t\t\t\tcall: builtinMathMin,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"pow\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 2,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"pow\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"pow\",\n\t\t\t\t\t\t\tcall: builtinMathPow,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"random\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"random\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"random\",\n\t\t\t\t\t\t\tcall: builtinMathRandom,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"round\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"round\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"round\",\n\t\t\t\t\t\t\tcall: builtinMathRound,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"sin\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"sin\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"sin\",\n\t\t\t\t\t\t\tcall: builtinMathSin,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"sinh\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"sinh\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"sinh\",\n\t\t\t\t\t\t\tcall: builtinMathSinh,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"sqrt\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"sqrt\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"sqrt\",\n\t\t\t\t\t\t\tcall: builtinMathSqrt,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"tan\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"tan\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"tan\",\n\t\t\t\t\t\t\tcall: builtinMathTan,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"tanh\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"tanh\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"tanh\",\n\t\t\t\t\t\t\tcall: builtinMathTanh,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"trunc\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"trunc\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"trunc\",\n\t\t\t\t\t\t\tcall: builtinMathTrunc,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"E\": {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\tvalue: math.E,\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"LN10\": {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\tvalue: math.Ln10,\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"LN2\": {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\tvalue: math.Ln2,\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"LOG10E\": {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\tvalue: math.Log10E,\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"LOG2E\": {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\tvalue: math.Log2E,\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"PI\": {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\tvalue: math.Pi,\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"SQRT1_2\": {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\tvalue: sqrt1_2,\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"SQRT2\": {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\tvalue: math.Sqrt2,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tpropertyOrder: []string{\n\t\t\t\"abs\",\n\t\t\t\"acos\",\n\t\t\t\"acosh\",\n\t\t\t\"asin\",\n\t\t\t\"asinh\",\n\t\t\t\"atan\",\n\t\t\t\"atanh\",\n\t\t\t\"atan2\",\n\t\t\t\"cbrt\",\n\t\t\t\"ceil\",\n\t\t\t\"cos\",\n\t\t\t\"cosh\",\n\t\t\t\"exp\",\n\t\t\t\"expm1\",\n\t\t\t\"floor\",\n\t\t\t\"log\",\n\t\t\t\"log10\",\n\t\t\t\"log1p\",\n\t\t\t\"log2\",\n\t\t\t\"max\",\n\t\t\t\"min\",\n\t\t\t\"pow\",\n\t\t\t\"random\",\n\t\t\t\"round\",\n\t\t\t\"sin\",\n\t\t\t\"sinh\",\n\t\t\t\"sqrt\",\n\t\t\t\"tan\",\n\t\t\t\"tanh\",\n\t\t\t\"trunc\",\n\t\t\t\"E\",\n\t\t\t\"LN10\",\n\t\t\t\"LN2\",\n\t\t\t\"LOG10E\",\n\t\t\t\"LOG2E\",\n\t\t\t\"PI\",\n\t\t\t\"SQRT1_2\",\n\t\t\t\"SQRT2\",\n\t\t},\n\t}\n\n\t// Date prototype.\n\trt.global.DatePrototype = &object{\n\t\truntime:     rt,\n\t\tclass:       classDateName,\n\t\tobjectClass: classObject,\n\t\tprototype:   rt.global.ObjectPrototype,\n\t\textensible:  true,\n\t\tvalue:       prototypeValueDate,\n\t\tproperty: map[string]property{\n\t\t\tmethodToString: {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"toString\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: methodToString,\n\t\t\t\t\t\t\tcall: builtinDateToString,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"toDateString\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"toDateString\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"toDateString\",\n\t\t\t\t\t\t\tcall: builtinDateToDateString,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"toTimeString\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"toTimeString\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"toTimeString\",\n\t\t\t\t\t\t\tcall: builtinDateToTimeString,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"toISOString\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"toISOString\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"toISOString\",\n\t\t\t\t\t\t\tcall: builtinDateToISOString,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"toUTCString\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"toUTCString\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"toUTCString\",\n\t\t\t\t\t\t\tcall: builtinDateToUTCString,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"toGMTString\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"toGMTString\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"toGMTString\",\n\t\t\t\t\t\t\tcall: builtinDateToGMTString,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"getDate\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"getDate\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"getDate\",\n\t\t\t\t\t\t\tcall: builtinDateGetDate,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"setDate\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"setDate\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"setDate\",\n\t\t\t\t\t\t\tcall: builtinDateSetDate,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"getDay\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"getDay\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"getDay\",\n\t\t\t\t\t\t\tcall: builtinDateGetDay,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"getFullYear\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"getFullYear\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"getFullYear\",\n\t\t\t\t\t\t\tcall: builtinDateGetFullYear,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"setFullYear\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 3,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"setFullYear\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"setFullYear\",\n\t\t\t\t\t\t\tcall: builtinDateSetFullYear,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"getHours\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"getHours\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"getHours\",\n\t\t\t\t\t\t\tcall: builtinDateGetHours,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"setHours\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 4,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"setHours\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"setHours\",\n\t\t\t\t\t\t\tcall: builtinDateSetHours,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"getMilliseconds\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"getMilliseconds\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"getMilliseconds\",\n\t\t\t\t\t\t\tcall: builtinDateGetMilliseconds,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"setMilliseconds\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"setMilliseconds\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"setMilliseconds\",\n\t\t\t\t\t\t\tcall: builtinDateSetMilliseconds,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"getMinutes\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"getMinutes\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"getMinutes\",\n\t\t\t\t\t\t\tcall: builtinDateGetMinutes,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"setMinutes\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 3,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"setMinutes\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"setMinutes\",\n\t\t\t\t\t\t\tcall: builtinDateSetMinutes,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"getMonth\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"getMonth\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"getMonth\",\n\t\t\t\t\t\t\tcall: builtinDateGetMonth,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"setMonth\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 2,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"setMonth\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"setMonth\",\n\t\t\t\t\t\t\tcall: builtinDateSetMonth,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"getSeconds\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"getSeconds\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"getSeconds\",\n\t\t\t\t\t\t\tcall: builtinDateGetSeconds,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"setSeconds\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 2,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"setSeconds\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"setSeconds\",\n\t\t\t\t\t\t\tcall: builtinDateSetSeconds,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"getTime\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"getTime\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"getTime\",\n\t\t\t\t\t\t\tcall: builtinDateGetTime,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"setTime\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"setTime\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"setTime\",\n\t\t\t\t\t\t\tcall: builtinDateSetTime,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"getTimezoneOffset\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"getTimezoneOffset\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"getTimezoneOffset\",\n\t\t\t\t\t\t\tcall: builtinDateGetTimezoneOffset,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"getUTCDate\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"getUTCDate\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"getUTCDate\",\n\t\t\t\t\t\t\tcall: builtinDateGetUTCDate,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"setUTCDate\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"setUTCDate\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"setUTCDate\",\n\t\t\t\t\t\t\tcall: builtinDateSetUTCDate,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"getUTCDay\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"getUTCDay\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"getUTCDay\",\n\t\t\t\t\t\t\tcall: builtinDateGetUTCDay,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"getUTCFullYear\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"getUTCFullYear\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"getUTCFullYear\",\n\t\t\t\t\t\t\tcall: builtinDateGetUTCFullYear,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"setUTCFullYear\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 3,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"setUTCFullYear\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"setUTCFullYear\",\n\t\t\t\t\t\t\tcall: builtinDateSetUTCFullYear,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"getUTCHours\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"getUTCHours\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"getUTCHours\",\n\t\t\t\t\t\t\tcall: builtinDateGetUTCHours,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"setUTCHours\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 4,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"setUTCHours\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"setUTCHours\",\n\t\t\t\t\t\t\tcall: builtinDateSetUTCHours,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"getUTCMilliseconds\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"getUTCMilliseconds\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"getUTCMilliseconds\",\n\t\t\t\t\t\t\tcall: builtinDateGetUTCMilliseconds,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"setUTCMilliseconds\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"setUTCMilliseconds\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"setUTCMilliseconds\",\n\t\t\t\t\t\t\tcall: builtinDateSetUTCMilliseconds,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"getUTCMinutes\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"getUTCMinutes\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"getUTCMinutes\",\n\t\t\t\t\t\t\tcall: builtinDateGetUTCMinutes,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"setUTCMinutes\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 3,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"setUTCMinutes\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"setUTCMinutes\",\n\t\t\t\t\t\t\tcall: builtinDateSetUTCMinutes,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"getUTCMonth\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"getUTCMonth\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"getUTCMonth\",\n\t\t\t\t\t\t\tcall: builtinDateGetUTCMonth,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"setUTCMonth\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 2,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"setUTCMonth\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"setUTCMonth\",\n\t\t\t\t\t\t\tcall: builtinDateSetUTCMonth,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"getUTCSeconds\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"getUTCSeconds\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"getUTCSeconds\",\n\t\t\t\t\t\t\tcall: builtinDateGetUTCSeconds,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"setUTCSeconds\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 2,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"setUTCSeconds\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"setUTCSeconds\",\n\t\t\t\t\t\t\tcall: builtinDateSetUTCSeconds,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"valueOf\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"valueOf\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"valueOf\",\n\t\t\t\t\t\t\tcall: builtinDateValueOf,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"getYear\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"getYear\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"getYear\",\n\t\t\t\t\t\t\tcall: builtinDateGetYear,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"setYear\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"setYear\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"setYear\",\n\t\t\t\t\t\t\tcall: builtinDateSetYear,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"toJSON\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"toJSON\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"toJSON\",\n\t\t\t\t\t\t\tcall: builtinDateToJSON,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"toLocaleString\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"toLocaleString\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"toLocaleString\",\n\t\t\t\t\t\t\tcall: builtinDateToLocaleString,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"toLocaleDateString\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"toLocaleDateString\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"toLocaleDateString\",\n\t\t\t\t\t\t\tcall: builtinDateToLocaleDateString,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"toLocaleTimeString\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"toLocaleTimeString\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"toLocaleTimeString\",\n\t\t\t\t\t\t\tcall: builtinDateToLocaleTimeString,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tpropertyOrder: []string{\n\t\t\tpropertyConstructor,\n\t\t\tmethodToString,\n\t\t\t\"toDateString\",\n\t\t\t\"toTimeString\",\n\t\t\t\"toISOString\",\n\t\t\t\"toUTCString\",\n\t\t\t\"toGMTString\",\n\t\t\t\"getDate\",\n\t\t\t\"setDate\",\n\t\t\t\"getDay\",\n\t\t\t\"getFullYear\",\n\t\t\t\"setFullYear\",\n\t\t\t\"getHours\",\n\t\t\t\"setHours\",\n\t\t\t\"getMilliseconds\",\n\t\t\t\"setMilliseconds\",\n\t\t\t\"getMinutes\",\n\t\t\t\"setMinutes\",\n\t\t\t\"getMonth\",\n\t\t\t\"setMonth\",\n\t\t\t\"getSeconds\",\n\t\t\t\"setSeconds\",\n\t\t\t\"getTime\",\n\t\t\t\"setTime\",\n\t\t\t\"getTimezoneOffset\",\n\t\t\t\"getUTCDate\",\n\t\t\t\"setUTCDate\",\n\t\t\t\"getUTCDay\",\n\t\t\t\"getUTCFullYear\",\n\t\t\t\"setUTCFullYear\",\n\t\t\t\"getUTCHours\",\n\t\t\t\"setUTCHours\",\n\t\t\t\"getUTCMilliseconds\",\n\t\t\t\"setUTCMilliseconds\",\n\t\t\t\"getUTCMinutes\",\n\t\t\t\"setUTCMinutes\",\n\t\t\t\"getUTCMonth\",\n\t\t\t\"setUTCMonth\",\n\t\t\t\"getUTCSeconds\",\n\t\t\t\"setUTCSeconds\",\n\t\t\t\"valueOf\",\n\t\t\t\"getYear\",\n\t\t\t\"setYear\",\n\t\t\t\"toJSON\",\n\t\t\t\"toLocaleString\",\n\t\t\t\"toLocaleDateString\",\n\t\t\t\"toLocaleTimeString\",\n\t\t},\n\t}\n\n\t// Date definition.\n\trt.global.Date = &object{\n\t\truntime:     rt,\n\t\tclass:       classFunctionName,\n\t\tobjectClass: classObject,\n\t\tprototype:   rt.global.FunctionPrototype,\n\t\textensible:  true,\n\t\tvalue: nativeFunctionObject{\n\t\t\tname:      classDateName,\n\t\t\tcall:      builtinDate,\n\t\t\tconstruct: builtinNewDate,\n\t\t},\n\t\tproperty: map[string]property{\n\t\t\tpropertyLength: {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\tvalue: 7,\n\t\t\t\t},\n\t\t\t},\n\t\t\tpropertyPrototype: {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueObject,\n\t\t\t\t\tvalue: rt.global.DatePrototype,\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"parse\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"parse\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"parse\",\n\t\t\t\t\t\t\tcall: builtinDateParse,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"UTC\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 7,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"UTC\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"UTC\",\n\t\t\t\t\t\t\tcall: builtinDateUTC,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"now\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"now\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"now\",\n\t\t\t\t\t\t\tcall: builtinDateNow,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tpropertyOrder: []string{\n\t\t\tpropertyLength,\n\t\t\tpropertyPrototype,\n\t\t\t\"parse\",\n\t\t\t\"UTC\",\n\t\t\t\"now\",\n\t\t},\n\t}\n\n\t// Date constructor definition.\n\trt.global.DatePrototype.property[propertyConstructor] = property{\n\t\tmode: 0o101,\n\t\tvalue: Value{\n\t\t\tkind:  valueObject,\n\t\t\tvalue: rt.global.Date,\n\t\t},\n\t}\n\n\t// RegExp prototype.\n\trt.global.RegExpPrototype = &object{\n\t\truntime:     rt,\n\t\tclass:       classRegExpName,\n\t\tobjectClass: classObject,\n\t\tprototype:   rt.global.ObjectPrototype,\n\t\textensible:  true,\n\t\tvalue:       prototypeValueRegExp,\n\t\tproperty: map[string]property{\n\t\t\t\"exec\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"exec\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"exec\",\n\t\t\t\t\t\t\tcall: builtinRegExpExec,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"compile\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"compile\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"compile\",\n\t\t\t\t\t\t\tcall: builtinRegExpCompile,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\tmethodToString: {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"toString\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: methodToString,\n\t\t\t\t\t\t\tcall: builtinRegExpToString,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"test\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"test\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"test\",\n\t\t\t\t\t\t\tcall: builtinRegExpTest,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tpropertyOrder: []string{\n\t\t\tpropertyConstructor,\n\t\t\t\"exec\",\n\t\t\t\"compile\",\n\t\t\tmethodToString,\n\t\t\t\"test\",\n\t\t},\n\t}\n\n\t// RegExp definition.\n\trt.global.RegExp = &object{\n\t\truntime:     rt,\n\t\tclass:       classFunctionName,\n\t\tobjectClass: classObject,\n\t\tprototype:   rt.global.FunctionPrototype,\n\t\textensible:  true,\n\t\tvalue: nativeFunctionObject{\n\t\t\tname:      classRegExpName,\n\t\t\tcall:      builtinRegExp,\n\t\t\tconstruct: builtinNewRegExp,\n\t\t},\n\t\tproperty: map[string]property{\n\t\t\tpropertyLength: {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\tvalue: 2,\n\t\t\t\t},\n\t\t\t},\n\t\t\tpropertyPrototype: {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueObject,\n\t\t\t\t\tvalue: rt.global.RegExpPrototype,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tpropertyOrder: []string{\n\t\t\tpropertyLength,\n\t\t\tpropertyPrototype,\n\t\t},\n\t}\n\n\t// RegExp constructor definition.\n\trt.global.RegExpPrototype.property[propertyConstructor] = property{\n\t\tmode: 0o101,\n\t\tvalue: Value{\n\t\t\tkind:  valueObject,\n\t\t\tvalue: rt.global.RegExp,\n\t\t},\n\t}\n\n\t// Error prototype.\n\trt.global.ErrorPrototype = &object{\n\t\truntime:     rt,\n\t\tclass:       classErrorName,\n\t\tobjectClass: classObject,\n\t\tprototype:   rt.global.ObjectPrototype,\n\t\textensible:  true,\n\t\tvalue:       nil,\n\t\tproperty: map[string]property{\n\t\t\t\"name\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueString,\n\t\t\t\t\tvalue: classErrorName,\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"message\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueString,\n\t\t\t\t\tvalue: \"\",\n\t\t\t\t},\n\t\t\t},\n\t\t\tmethodToString: {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"toString\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: methodToString,\n\t\t\t\t\t\t\tcall: builtinErrorToString,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tpropertyOrder: []string{\n\t\t\tpropertyConstructor,\n\t\t\t\"name\",\n\t\t\t\"message\",\n\t\t\tmethodToString,\n\t\t},\n\t}\n\n\t// Error definition.\n\trt.global.Error = &object{\n\t\truntime:     rt,\n\t\tclass:       classFunctionName,\n\t\tobjectClass: classObject,\n\t\tprototype:   rt.global.FunctionPrototype,\n\t\textensible:  true,\n\t\tvalue: nativeFunctionObject{\n\t\t\tname:      classErrorName,\n\t\t\tcall:      builtinError,\n\t\t\tconstruct: builtinNewError,\n\t\t},\n\t\tproperty: map[string]property{\n\t\t\tpropertyLength: {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\tvalue: 1,\n\t\t\t\t},\n\t\t\t},\n\t\t\tpropertyPrototype: {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueObject,\n\t\t\t\t\tvalue: rt.global.ErrorPrototype,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tpropertyOrder: []string{\n\t\t\tpropertyLength,\n\t\t\tpropertyPrototype,\n\t\t},\n\t}\n\n\t// Error constructor definition.\n\trt.global.ErrorPrototype.property[propertyConstructor] = property{\n\t\tmode: 0o101,\n\t\tvalue: Value{\n\t\t\tkind:  valueObject,\n\t\t\tvalue: rt.global.Error,\n\t\t},\n\t}\n\n\t// EvalError prototype.\n\trt.global.EvalErrorPrototype = &object{\n\t\truntime:     rt,\n\t\tclass:       classEvalErrorName,\n\t\tobjectClass: classObject,\n\t\tprototype:   rt.global.ErrorPrototype,\n\t\textensible:  true,\n\t\tvalue:       nil,\n\t\tproperty: map[string]property{\n\t\t\t\"name\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueString,\n\t\t\t\t\tvalue: classEvalErrorName,\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"message\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueString,\n\t\t\t\t\tvalue: \"\",\n\t\t\t\t},\n\t\t\t},\n\t\t\tmethodToString: {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"toString\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: methodToString,\n\t\t\t\t\t\t\tcall: builtinErrorToString,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tpropertyOrder: []string{\n\t\t\tpropertyConstructor,\n\t\t\t\"name\",\n\t\t\t\"message\",\n\t\t\tmethodToString,\n\t\t},\n\t}\n\n\t// EvalError definition.\n\trt.global.EvalError = &object{\n\t\truntime:     rt,\n\t\tclass:       classFunctionName,\n\t\tobjectClass: classObject,\n\t\tprototype:   rt.global.FunctionPrototype,\n\t\textensible:  true,\n\t\tvalue: nativeFunctionObject{\n\t\t\tname:      classEvalErrorName,\n\t\t\tcall:      builtinEvalError,\n\t\t\tconstruct: builtinNewEvalError,\n\t\t},\n\t\tproperty: map[string]property{\n\t\t\tpropertyLength: {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\tvalue: 1,\n\t\t\t\t},\n\t\t\t},\n\t\t\tpropertyPrototype: {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueObject,\n\t\t\t\t\tvalue: rt.global.EvalErrorPrototype,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tpropertyOrder: []string{\n\t\t\tpropertyLength,\n\t\t\tpropertyPrototype,\n\t\t},\n\t}\n\n\t// EvalError constructor definition.\n\trt.global.EvalErrorPrototype.property[propertyConstructor] = property{\n\t\tmode: 0o101,\n\t\tvalue: Value{\n\t\t\tkind:  valueObject,\n\t\t\tvalue: rt.global.EvalError,\n\t\t},\n\t}\n\n\t// TypeError prototype.\n\trt.global.TypeErrorPrototype = &object{\n\t\truntime:     rt,\n\t\tclass:       classTypeErrorName,\n\t\tobjectClass: classObject,\n\t\tprototype:   rt.global.ErrorPrototype,\n\t\textensible:  true,\n\t\tvalue:       nil,\n\t\tproperty: map[string]property{\n\t\t\t\"name\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueString,\n\t\t\t\t\tvalue: classTypeErrorName,\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"message\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueString,\n\t\t\t\t\tvalue: \"\",\n\t\t\t\t},\n\t\t\t},\n\t\t\tmethodToString: {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"toString\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: methodToString,\n\t\t\t\t\t\t\tcall: builtinErrorToString,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tpropertyOrder: []string{\n\t\t\tpropertyConstructor,\n\t\t\t\"name\",\n\t\t\t\"message\",\n\t\t\tmethodToString,\n\t\t},\n\t}\n\n\t// TypeError definition.\n\trt.global.TypeError = &object{\n\t\truntime:     rt,\n\t\tclass:       classFunctionName,\n\t\tobjectClass: classObject,\n\t\tprototype:   rt.global.FunctionPrototype,\n\t\textensible:  true,\n\t\tvalue: nativeFunctionObject{\n\t\t\tname:      classTypeErrorName,\n\t\t\tcall:      builtinTypeError,\n\t\t\tconstruct: builtinNewTypeError,\n\t\t},\n\t\tproperty: map[string]property{\n\t\t\tpropertyLength: {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\tvalue: 1,\n\t\t\t\t},\n\t\t\t},\n\t\t\tpropertyPrototype: {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueObject,\n\t\t\t\t\tvalue: rt.global.TypeErrorPrototype,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tpropertyOrder: []string{\n\t\t\tpropertyLength,\n\t\t\tpropertyPrototype,\n\t\t},\n\t}\n\n\t// TypeError constructor definition.\n\trt.global.TypeErrorPrototype.property[propertyConstructor] = property{\n\t\tmode: 0o101,\n\t\tvalue: Value{\n\t\t\tkind:  valueObject,\n\t\t\tvalue: rt.global.TypeError,\n\t\t},\n\t}\n\n\t// RangeError prototype.\n\trt.global.RangeErrorPrototype = &object{\n\t\truntime:     rt,\n\t\tclass:       classRangeErrorName,\n\t\tobjectClass: classObject,\n\t\tprototype:   rt.global.ErrorPrototype,\n\t\textensible:  true,\n\t\tvalue:       nil,\n\t\tproperty: map[string]property{\n\t\t\t\"name\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueString,\n\t\t\t\t\tvalue: classRangeErrorName,\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"message\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueString,\n\t\t\t\t\tvalue: \"\",\n\t\t\t\t},\n\t\t\t},\n\t\t\tmethodToString: {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"toString\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: methodToString,\n\t\t\t\t\t\t\tcall: builtinErrorToString,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tpropertyOrder: []string{\n\t\t\tpropertyConstructor,\n\t\t\t\"name\",\n\t\t\t\"message\",\n\t\t\tmethodToString,\n\t\t},\n\t}\n\n\t// RangeError definition.\n\trt.global.RangeError = &object{\n\t\truntime:     rt,\n\t\tclass:       classFunctionName,\n\t\tobjectClass: classObject,\n\t\tprototype:   rt.global.FunctionPrototype,\n\t\textensible:  true,\n\t\tvalue: nativeFunctionObject{\n\t\t\tname:      classRangeErrorName,\n\t\t\tcall:      builtinRangeError,\n\t\t\tconstruct: builtinNewRangeError,\n\t\t},\n\t\tproperty: map[string]property{\n\t\t\tpropertyLength: {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\tvalue: 1,\n\t\t\t\t},\n\t\t\t},\n\t\t\tpropertyPrototype: {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueObject,\n\t\t\t\t\tvalue: rt.global.RangeErrorPrototype,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tpropertyOrder: []string{\n\t\t\tpropertyLength,\n\t\t\tpropertyPrototype,\n\t\t},\n\t}\n\n\t// RangeError constructor definition.\n\trt.global.RangeErrorPrototype.property[propertyConstructor] = property{\n\t\tmode: 0o101,\n\t\tvalue: Value{\n\t\t\tkind:  valueObject,\n\t\t\tvalue: rt.global.RangeError,\n\t\t},\n\t}\n\n\t// ReferenceError prototype.\n\trt.global.ReferenceErrorPrototype = &object{\n\t\truntime:     rt,\n\t\tclass:       classReferenceErrorName,\n\t\tobjectClass: classObject,\n\t\tprototype:   rt.global.ErrorPrototype,\n\t\textensible:  true,\n\t\tvalue:       nil,\n\t\tproperty: map[string]property{\n\t\t\t\"name\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueString,\n\t\t\t\t\tvalue: classReferenceErrorName,\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"message\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueString,\n\t\t\t\t\tvalue: \"\",\n\t\t\t\t},\n\t\t\t},\n\t\t\tmethodToString: {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"toString\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: methodToString,\n\t\t\t\t\t\t\tcall: builtinErrorToString,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tpropertyOrder: []string{\n\t\t\tpropertyConstructor,\n\t\t\t\"name\",\n\t\t\t\"message\",\n\t\t\tmethodToString,\n\t\t},\n\t}\n\n\t// ReferenceError definition.\n\trt.global.ReferenceError = &object{\n\t\truntime:     rt,\n\t\tclass:       classFunctionName,\n\t\tobjectClass: classObject,\n\t\tprototype:   rt.global.FunctionPrototype,\n\t\textensible:  true,\n\t\tvalue: nativeFunctionObject{\n\t\t\tname:      classReferenceErrorName,\n\t\t\tcall:      builtinReferenceError,\n\t\t\tconstruct: builtinNewReferenceError,\n\t\t},\n\t\tproperty: map[string]property{\n\t\t\tpropertyLength: {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\tvalue: 1,\n\t\t\t\t},\n\t\t\t},\n\t\t\tpropertyPrototype: {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueObject,\n\t\t\t\t\tvalue: rt.global.ReferenceErrorPrototype,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tpropertyOrder: []string{\n\t\t\tpropertyLength,\n\t\t\tpropertyPrototype,\n\t\t},\n\t}\n\n\t// ReferenceError constructor definition.\n\trt.global.ReferenceErrorPrototype.property[propertyConstructor] = property{\n\t\tmode: 0o101,\n\t\tvalue: Value{\n\t\t\tkind:  valueObject,\n\t\t\tvalue: rt.global.ReferenceError,\n\t\t},\n\t}\n\n\t// SyntaxError prototype.\n\trt.global.SyntaxErrorPrototype = &object{\n\t\truntime:     rt,\n\t\tclass:       classSyntaxErrorName,\n\t\tobjectClass: classObject,\n\t\tprototype:   rt.global.ErrorPrototype,\n\t\textensible:  true,\n\t\tvalue:       nil,\n\t\tproperty: map[string]property{\n\t\t\t\"name\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueString,\n\t\t\t\t\tvalue: classSyntaxErrorName,\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"message\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueString,\n\t\t\t\t\tvalue: \"\",\n\t\t\t\t},\n\t\t\t},\n\t\t\tmethodToString: {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"toString\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: methodToString,\n\t\t\t\t\t\t\tcall: builtinErrorToString,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tpropertyOrder: []string{\n\t\t\tpropertyConstructor,\n\t\t\t\"name\",\n\t\t\t\"message\",\n\t\t\tmethodToString,\n\t\t},\n\t}\n\n\t// SyntaxError definition.\n\trt.global.SyntaxError = &object{\n\t\truntime:     rt,\n\t\tclass:       classFunctionName,\n\t\tobjectClass: classObject,\n\t\tprototype:   rt.global.FunctionPrototype,\n\t\textensible:  true,\n\t\tvalue: nativeFunctionObject{\n\t\t\tname:      classSyntaxErrorName,\n\t\t\tcall:      builtinSyntaxError,\n\t\t\tconstruct: builtinNewSyntaxError,\n\t\t},\n\t\tproperty: map[string]property{\n\t\t\tpropertyLength: {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\tvalue: 1,\n\t\t\t\t},\n\t\t\t},\n\t\t\tpropertyPrototype: {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueObject,\n\t\t\t\t\tvalue: rt.global.SyntaxErrorPrototype,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tpropertyOrder: []string{\n\t\t\tpropertyLength,\n\t\t\tpropertyPrototype,\n\t\t},\n\t}\n\n\t// SyntaxError constructor definition.\n\trt.global.SyntaxErrorPrototype.property[propertyConstructor] = property{\n\t\tmode: 0o101,\n\t\tvalue: Value{\n\t\t\tkind:  valueObject,\n\t\t\tvalue: rt.global.SyntaxError,\n\t\t},\n\t}\n\n\t// URIError prototype.\n\trt.global.URIErrorPrototype = &object{\n\t\truntime:     rt,\n\t\tclass:       classURIErrorName,\n\t\tobjectClass: classObject,\n\t\tprototype:   rt.global.ErrorPrototype,\n\t\textensible:  true,\n\t\tvalue:       nil,\n\t\tproperty: map[string]property{\n\t\t\t\"name\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueString,\n\t\t\t\t\tvalue: classURIErrorName,\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"message\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueString,\n\t\t\t\t\tvalue: \"\",\n\t\t\t\t},\n\t\t\t},\n\t\t\tmethodToString: {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"toString\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: methodToString,\n\t\t\t\t\t\t\tcall: builtinErrorToString,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tpropertyOrder: []string{\n\t\t\tpropertyConstructor,\n\t\t\t\"name\",\n\t\t\t\"message\",\n\t\t\tmethodToString,\n\t\t},\n\t}\n\n\t// URIError definition.\n\trt.global.URIError = &object{\n\t\truntime:     rt,\n\t\tclass:       classFunctionName,\n\t\tobjectClass: classObject,\n\t\tprototype:   rt.global.FunctionPrototype,\n\t\textensible:  true,\n\t\tvalue: nativeFunctionObject{\n\t\t\tname:      classURIErrorName,\n\t\t\tcall:      builtinURIError,\n\t\t\tconstruct: builtinNewURIError,\n\t\t},\n\t\tproperty: map[string]property{\n\t\t\tpropertyLength: {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\tvalue: 1,\n\t\t\t\t},\n\t\t\t},\n\t\t\tpropertyPrototype: {\n\t\t\t\tmode: 0,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind:  valueObject,\n\t\t\t\t\tvalue: rt.global.URIErrorPrototype,\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tpropertyOrder: []string{\n\t\t\tpropertyLength,\n\t\t\tpropertyPrototype,\n\t\t},\n\t}\n\n\t// URIError constructor definition.\n\trt.global.URIErrorPrototype.property[propertyConstructor] = property{\n\t\tmode: 0o101,\n\t\tvalue: Value{\n\t\t\tkind:  valueObject,\n\t\t\tvalue: rt.global.URIError,\n\t\t},\n\t}\n\n\t// JSON definition.\n\trt.global.JSON = &object{\n\t\truntime:     rt,\n\t\tclass:       classJSONName,\n\t\tobjectClass: classObject,\n\t\tprototype:   rt.global.ObjectPrototype,\n\t\textensible:  true,\n\t\tproperty: map[string]property{\n\t\t\t\"parse\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 2,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"parse\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"parse\",\n\t\t\t\t\t\t\tcall: builtinJSONParse,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"stringify\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 3,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"stringify\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"stringify\",\n\t\t\t\t\t\t\tcall: builtinJSONStringify,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tpropertyOrder: []string{\n\t\t\t\"parse\",\n\t\t\t\"stringify\",\n\t\t},\n\t}\n\n\t// Global properties.\n\trt.globalObject.property = map[string]property{\n\t\t\"eval\": {\n\t\t\tmode: 0o101,\n\t\t\tvalue: Value{\n\t\t\t\tkind: valueObject,\n\t\t\t\tvalue: &object{\n\t\t\t\t\truntime:     rt,\n\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\textensible:  true,\n\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\tvalue: \"eval\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t},\n\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\tname: \"eval\",\n\t\t\t\t\t\tcall: builtinGlobalEval,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t\"parseInt\": {\n\t\t\tmode: 0o101,\n\t\t\tvalue: Value{\n\t\t\t\tkind: valueObject,\n\t\t\t\tvalue: &object{\n\t\t\t\t\truntime:     rt,\n\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\textensible:  true,\n\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\tvalue: 2,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\tvalue: \"parseInt\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t},\n\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\tname: \"parseInt\",\n\t\t\t\t\t\tcall: builtinGlobalParseInt,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t\"parseFloat\": {\n\t\t\tmode: 0o101,\n\t\t\tvalue: Value{\n\t\t\t\tkind: valueObject,\n\t\t\t\tvalue: &object{\n\t\t\t\t\truntime:     rt,\n\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\textensible:  true,\n\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\tvalue: \"parseFloat\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t},\n\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\tname: \"parseFloat\",\n\t\t\t\t\t\tcall: builtinGlobalParseFloat,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t\"isNaN\": {\n\t\t\tmode: 0o101,\n\t\t\tvalue: Value{\n\t\t\t\tkind: valueObject,\n\t\t\t\tvalue: &object{\n\t\t\t\t\truntime:     rt,\n\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\textensible:  true,\n\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\tvalue: \"isNaN\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t},\n\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\tname: \"isNaN\",\n\t\t\t\t\t\tcall: builtinGlobalIsNaN,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t\"isFinite\": {\n\t\t\tmode: 0o101,\n\t\t\tvalue: Value{\n\t\t\t\tkind: valueObject,\n\t\t\t\tvalue: &object{\n\t\t\t\t\truntime:     rt,\n\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\textensible:  true,\n\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\tvalue: \"isFinite\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t},\n\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\tname: \"isFinite\",\n\t\t\t\t\t\tcall: builtinGlobalIsFinite,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t\"decodeURI\": {\n\t\t\tmode: 0o101,\n\t\t\tvalue: Value{\n\t\t\t\tkind: valueObject,\n\t\t\t\tvalue: &object{\n\t\t\t\t\truntime:     rt,\n\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\textensible:  true,\n\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\tvalue: \"decodeURI\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t},\n\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\tname: \"decodeURI\",\n\t\t\t\t\t\tcall: builtinGlobalDecodeURI,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t\"decodeURIComponent\": {\n\t\t\tmode: 0o101,\n\t\t\tvalue: Value{\n\t\t\t\tkind: valueObject,\n\t\t\t\tvalue: &object{\n\t\t\t\t\truntime:     rt,\n\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\textensible:  true,\n\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\tvalue: \"decodeURIComponent\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t},\n\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\tname: \"decodeURIComponent\",\n\t\t\t\t\t\tcall: builtinGlobalDecodeURIComponent,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t\"encodeURI\": {\n\t\t\tmode: 0o101,\n\t\t\tvalue: Value{\n\t\t\t\tkind: valueObject,\n\t\t\t\tvalue: &object{\n\t\t\t\t\truntime:     rt,\n\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\textensible:  true,\n\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\tvalue: \"encodeURI\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t},\n\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\tname: \"encodeURI\",\n\t\t\t\t\t\tcall: builtinGlobalEncodeURI,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t\"encodeURIComponent\": {\n\t\t\tmode: 0o101,\n\t\t\tvalue: Value{\n\t\t\t\tkind: valueObject,\n\t\t\t\tvalue: &object{\n\t\t\t\t\truntime:     rt,\n\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\textensible:  true,\n\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\tvalue: \"encodeURIComponent\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t},\n\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\tname: \"encodeURIComponent\",\n\t\t\t\t\t\tcall: builtinGlobalEncodeURIComponent,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t\"escape\": {\n\t\t\tmode: 0o101,\n\t\t\tvalue: Value{\n\t\t\t\tkind: valueObject,\n\t\t\t\tvalue: &object{\n\t\t\t\t\truntime:     rt,\n\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\textensible:  true,\n\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\tvalue: \"escape\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t},\n\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\tname: \"escape\",\n\t\t\t\t\t\tcall: builtinGlobalEscape,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\t\"unescape\": {\n\t\t\tmode: 0o101,\n\t\t\tvalue: Value{\n\t\t\t\tkind: valueObject,\n\t\t\t\tvalue: &object{\n\t\t\t\t\truntime:     rt,\n\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\textensible:  true,\n\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\tvalue: 1,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\tvalue: \"unescape\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t},\n\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\tname: \"unescape\",\n\t\t\t\t\t\tcall: builtinGlobalUnescape,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tclassObjectName: {\n\t\t\tmode: 0o101,\n\t\t\tvalue: Value{\n\t\t\t\tkind:  valueObject,\n\t\t\t\tvalue: rt.global.Object,\n\t\t\t},\n\t\t},\n\t\tclassFunctionName: {\n\t\t\tmode: 0o101,\n\t\t\tvalue: Value{\n\t\t\t\tkind:  valueObject,\n\t\t\t\tvalue: rt.global.Function,\n\t\t\t},\n\t\t},\n\t\tclassArrayName: {\n\t\t\tmode: 0o101,\n\t\t\tvalue: Value{\n\t\t\t\tkind:  valueObject,\n\t\t\t\tvalue: rt.global.Array,\n\t\t\t},\n\t\t},\n\t\tclassStringName: {\n\t\t\tmode: 0o101,\n\t\t\tvalue: Value{\n\t\t\t\tkind:  valueObject,\n\t\t\t\tvalue: rt.global.String,\n\t\t\t},\n\t\t},\n\t\tclassBooleanName: {\n\t\t\tmode: 0o101,\n\t\t\tvalue: Value{\n\t\t\t\tkind:  valueObject,\n\t\t\t\tvalue: rt.global.Boolean,\n\t\t\t},\n\t\t},\n\t\tclassNumberName: {\n\t\t\tmode: 0o101,\n\t\t\tvalue: Value{\n\t\t\t\tkind:  valueObject,\n\t\t\t\tvalue: rt.global.Number,\n\t\t\t},\n\t\t},\n\t\tclassMathName: {\n\t\t\tmode: 0o101,\n\t\t\tvalue: Value{\n\t\t\t\tkind:  valueObject,\n\t\t\t\tvalue: rt.global.Math,\n\t\t\t},\n\t\t},\n\t\tclassDateName: {\n\t\t\tmode: 0o101,\n\t\t\tvalue: Value{\n\t\t\t\tkind:  valueObject,\n\t\t\t\tvalue: rt.global.Date,\n\t\t\t},\n\t\t},\n\t\tclassRegExpName: {\n\t\t\tmode: 0o101,\n\t\t\tvalue: Value{\n\t\t\t\tkind:  valueObject,\n\t\t\t\tvalue: rt.global.RegExp,\n\t\t\t},\n\t\t},\n\t\tclassErrorName: {\n\t\t\tmode: 0o101,\n\t\t\tvalue: Value{\n\t\t\t\tkind:  valueObject,\n\t\t\t\tvalue: rt.global.Error,\n\t\t\t},\n\t\t},\n\t\tclassEvalErrorName: {\n\t\t\tmode: 0o101,\n\t\t\tvalue: Value{\n\t\t\t\tkind:  valueObject,\n\t\t\t\tvalue: rt.global.EvalError,\n\t\t\t},\n\t\t},\n\t\tclassTypeErrorName: {\n\t\t\tmode: 0o101,\n\t\t\tvalue: Value{\n\t\t\t\tkind:  valueObject,\n\t\t\t\tvalue: rt.global.TypeError,\n\t\t\t},\n\t\t},\n\t\tclassRangeErrorName: {\n\t\t\tmode: 0o101,\n\t\t\tvalue: Value{\n\t\t\t\tkind:  valueObject,\n\t\t\t\tvalue: rt.global.RangeError,\n\t\t\t},\n\t\t},\n\t\tclassReferenceErrorName: {\n\t\t\tmode: 0o101,\n\t\t\tvalue: Value{\n\t\t\t\tkind:  valueObject,\n\t\t\t\tvalue: rt.global.ReferenceError,\n\t\t\t},\n\t\t},\n\t\tclassSyntaxErrorName: {\n\t\t\tmode: 0o101,\n\t\t\tvalue: Value{\n\t\t\t\tkind:  valueObject,\n\t\t\t\tvalue: rt.global.SyntaxError,\n\t\t\t},\n\t\t},\n\t\tclassURIErrorName: {\n\t\t\tmode: 0o101,\n\t\t\tvalue: Value{\n\t\t\t\tkind:  valueObject,\n\t\t\t\tvalue: rt.global.URIError,\n\t\t\t},\n\t\t},\n\t\tclassJSONName: {\n\t\t\tmode: 0o101,\n\t\t\tvalue: Value{\n\t\t\t\tkind:  valueObject,\n\t\t\t\tvalue: rt.global.JSON,\n\t\t\t},\n\t\t},\n\t\t\"undefined\": {\n\t\t\tmode: 0,\n\t\t\tvalue: Value{\n\t\t\t\tkind: valueUndefined,\n\t\t\t},\n\t\t},\n\t\t\"NaN\": {\n\t\t\tmode: 0,\n\t\t\tvalue: Value{\n\t\t\t\tkind:  valueNumber,\n\t\t\t\tvalue: math.NaN(),\n\t\t\t},\n\t\t},\n\t\t\"Infinity\": {\n\t\t\tmode: 0,\n\t\t\tvalue: Value{\n\t\t\t\tkind:  valueNumber,\n\t\t\t\tvalue: math.Inf(+1),\n\t\t\t},\n\t\t},\n\t}\n\n\t// Global property order.\n\trt.globalObject.propertyOrder = []string{\n\t\t\"eval\",\n\t\t\"parseInt\",\n\t\t\"parseFloat\",\n\t\t\"isNaN\",\n\t\t\"isFinite\",\n\t\t\"decodeURI\",\n\t\t\"decodeURIComponent\",\n\t\t\"encodeURI\",\n\t\t\"encodeURIComponent\",\n\t\t\"escape\",\n\t\t\"unescape\",\n\t\tclassObjectName,\n\t\tclassFunctionName,\n\t\tclassArrayName,\n\t\tclassStringName,\n\t\tclassBooleanName,\n\t\tclassNumberName,\n\t\tclassMathName,\n\t\tclassDateName,\n\t\tclassRegExpName,\n\t\tclassErrorName,\n\t\tclassEvalErrorName,\n\t\tclassTypeErrorName,\n\t\tclassRangeErrorName,\n\t\tclassReferenceErrorName,\n\t\tclassSyntaxErrorName,\n\t\tclassURIErrorName,\n\t\tclassJSONName,\n\t\t\"undefined\",\n\t\t\"NaN\",\n\t\t\"Infinity\",\n\t}\n}\n\nfunc (rt *runtime) newConsole() *object {\n\treturn &object{\n\t\truntime:     rt,\n\t\tclass:       classObjectName,\n\t\tobjectClass: classObject,\n\t\tprototype:   rt.global.ObjectPrototype,\n\t\textensible:  true,\n\t\tproperty: map[string]property{\n\t\t\t\"log\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"log\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"log\",\n\t\t\t\t\t\t\tcall: builtinConsoleLog,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"debug\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"debug\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"debug\",\n\t\t\t\t\t\t\tcall: builtinConsoleLog,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"info\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"info\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"info\",\n\t\t\t\t\t\t\tcall: builtinConsoleLog,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"error\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"error\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"error\",\n\t\t\t\t\t\t\tcall: builtinConsoleError,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"warn\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"warn\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"warn\",\n\t\t\t\t\t\t\tcall: builtinConsoleError,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"dir\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"dir\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"dir\",\n\t\t\t\t\t\t\tcall: builtinConsoleDir,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"time\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"time\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"time\",\n\t\t\t\t\t\t\tcall: builtinConsoleTime,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"timeEnd\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"timeEnd\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"timeEnd\",\n\t\t\t\t\t\t\tcall: builtinConsoleTimeEnd,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"trace\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"trace\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"trace\",\n\t\t\t\t\t\t\tcall: builtinConsoleTrace,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t\t\"assert\": {\n\t\t\t\tmode: 0o101,\n\t\t\t\tvalue: Value{\n\t\t\t\t\tkind: valueObject,\n\t\t\t\t\tvalue: &object{\n\t\t\t\t\t\truntime:     rt,\n\t\t\t\t\t\tclass:       classFunctionName,\n\t\t\t\t\t\tobjectClass: classObject,\n\t\t\t\t\t\tprototype:   rt.global.FunctionPrototype,\n\t\t\t\t\t\textensible:  true,\n\t\t\t\t\t\tproperty: map[string]property{\n\t\t\t\t\t\t\tpropertyLength: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueNumber,\n\t\t\t\t\t\t\t\t\tvalue: 0,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tpropertyName: {\n\t\t\t\t\t\t\t\tmode: 0,\n\t\t\t\t\t\t\t\tvalue: Value{\n\t\t\t\t\t\t\t\t\tkind:  valueString,\n\t\t\t\t\t\t\t\t\tvalue: \"assert\",\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpropertyOrder: []string{\n\t\t\t\t\t\t\tpropertyLength,\n\t\t\t\t\t\t\tpropertyName,\n\t\t\t\t\t\t},\n\t\t\t\t\t\tvalue: nativeFunctionObject{\n\t\t\t\t\t\t\tname: \"assert\",\n\t\t\t\t\t\t\tcall: builtinConsoleAssert,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tpropertyOrder: []string{\n\t\t\t\"log\",\n\t\t\t\"debug\",\n\t\t\t\"info\",\n\t\t\t\"error\",\n\t\t\t\"warn\",\n\t\t\t\"dir\",\n\t\t\t\"time\",\n\t\t\t\"timeEnd\",\n\t\t\t\"trace\",\n\t\t\t\"assert\",\n\t\t},\n\t}\n}\n\nfunc intValue(value int) Value {\n\treturn Value{\n\t\tkind:  valueNumber,\n\t\tvalue: value,\n\t}\n}\n\nfunc int32Value(value int32) Value {\n\treturn Value{\n\t\tkind:  valueNumber,\n\t\tvalue: value,\n\t}\n}\n\nfunc int64Value(value int64) Value {\n\treturn Value{\n\t\tkind:  valueNumber,\n\t\tvalue: value,\n\t}\n}\n\nfunc uint16Value(value uint16) Value {\n\treturn Value{\n\t\tkind:  valueNumber,\n\t\tvalue: value,\n\t}\n}\n\nfunc uint32Value(value uint32) Value {\n\treturn Value{\n\t\tkind:  valueNumber,\n\t\tvalue: value,\n\t}\n}\n\nfunc float64Value(value float64) Value {\n\treturn Value{\n\t\tkind:  valueNumber,\n\t\tvalue: value,\n\t}\n}\n\nfunc stringValue(value string) Value {\n\treturn Value{\n\t\tkind:  valueString,\n\t\tvalue: value,\n\t}\n}\n\nfunc string16Value(value []uint16) Value {\n\treturn Value{\n\t\tkind:  valueString,\n\t\tvalue: value,\n\t}\n}\n\nfunc boolValue(value bool) Value {\n\treturn Value{\n\t\tkind:  valueBoolean,\n\t\tvalue: value,\n\t}\n}\n\nfunc objectValue(value *object) Value {\n\treturn Value{\n\t\tkind:  valueObject,\n\t\tvalue: value,\n\t}\n}\n"
  },
  {
    "path": "inline_test.go",
    "content": "package otto\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestGetOwnPropertyNames(t *testing.T) {\n\tvm := New()\n\t// Commented out values aren't implemented yet.\n\ttests := map[string][]string{\n\t\t\"Object.prototype\": {\n\t\t\t\"constructor\",\n\t\t\t// \"__defineGetter__\",\n\t\t\t// \"__defineSetter__\",\n\t\t\t\"hasOwnProperty\",\n\t\t\t// \"__lookupGetter__\",\n\t\t\t// \"__lookupSetter__\",\n\t\t\t\"isPrototypeOf\",\n\t\t\t\"propertyIsEnumerable\",\n\t\t\t\"toString\",\n\t\t\t\"valueOf\",\n\t\t\t// \"__proto__\",\n\t\t\t\"toLocaleString\",\n\t\t},\n\t\t\"Array.prototype\": {\n\t\t\t\"length\",\n\t\t\t\"constructor\",\n\t\t\t// \"at\",\n\t\t\t\"concat\",\n\t\t\t// \"copyWithin\",\n\t\t\t// \"fill\",\n\t\t\t// \"find\",\n\t\t\t// \"findIndex\",\n\t\t\t\"lastIndexOf\",\n\t\t\t\"pop\",\n\t\t\t\"push\",\n\t\t\t\"reverse\",\n\t\t\t\"shift\",\n\t\t\t\"unshift\",\n\t\t\t\"slice\",\n\t\t\t\"sort\",\n\t\t\t\"splice\",\n\t\t\t// \"includes\",\n\t\t\t\"indexOf\",\n\t\t\t\"join\",\n\t\t\t// \"keys\",\n\t\t\t// \"entries\",\n\t\t\t// \"values\",\n\t\t\t\"forEach\",\n\t\t\t\"filter\",\n\t\t\t// \"flat\",\n\t\t\t// \"flatMap\",\n\t\t\t\"map\",\n\t\t\t\"every\",\n\t\t\t\"some\",\n\t\t\t\"reduce\",\n\t\t\t\"reduceRight\",\n\t\t\t\"toLocaleString\",\n\t\t\t\"toString\",\n\t\t\t// \"findLast\",\n\t\t\t// \"findLastIndex\",\n\t\t},\n\t\t\"String.prototype\": {\n\t\t\t\"length\",\n\t\t\t\"constructor\",\n\t\t\t// \"anchor\",\n\t\t\t// \"at\",\n\t\t\t// \"big\",\n\t\t\t// \"blink\",\n\t\t\t// \"bold\",\n\t\t\t\"charAt\",\n\t\t\t\"charCodeAt\",\n\t\t\t// \"codePointAt\",\n\t\t\t\"concat\",\n\t\t\t// \"endsWith\",\n\t\t\t// \"fontcolor\",\n\t\t\t// \"fontsize\",\n\t\t\t// \"fixed\",\n\t\t\t// \"includes\",\n\t\t\t\"indexOf\",\n\t\t\t// \"italics\",\n\t\t\t\"lastIndexOf\",\n\t\t\t// \"link\",\n\t\t\t\"localeCompare\",\n\t\t\t\"match\",\n\t\t\t// \"matchAll\",\n\t\t\t// \"normalize\",\n\t\t\t// \"padEnd\",\n\t\t\t// \"padStart\",\n\t\t\t// \"repeat\",\n\t\t\t\"replace\",\n\t\t\t// \"replaceAll\",\n\t\t\t\"search\",\n\t\t\t\"slice\",\n\t\t\t// \"small\",\n\t\t\t\"split\",\n\t\t\t// \"strike\",\n\t\t\t// \"sub\",\n\t\t\t\"substr\",\n\t\t\t\"substring\",\n\t\t\t// \"sup\",\n\t\t\t\"startsWith\",\n\t\t\t\"toString\",\n\t\t\t\"trim\",\n\t\t\t\"trimLeft\",\n\t\t\t\"trimRight\",\n\t\t\t\"trimStart\",\n\t\t\t\"trimEnd\",\n\t\t\t\"toLocaleLowerCase\",\n\t\t\t\"toLocaleUpperCase\",\n\t\t\t\"toLowerCase\",\n\t\t\t\"toUpperCase\",\n\t\t\t\"valueOf\",\n\t\t},\n\t\t\"Boolean.prototype\": {\n\t\t\t\"constructor\",\n\t\t\t\"toString\",\n\t\t\t\"valueOf\",\n\t\t},\n\t\t\"Number.prototype\": {\n\t\t\t\"constructor\",\n\t\t\t\"toExponential\",\n\t\t\t\"toFixed\",\n\t\t\t\"toPrecision\",\n\t\t\t\"toString\",\n\t\t\t\"valueOf\",\n\t\t\t\"toLocaleString\",\n\t\t},\n\t\t\"Math\": {\n\t\t\t\"abs\",\n\t\t\t\"acos\",\n\t\t\t\"acosh\",\n\t\t\t\"asin\",\n\t\t\t\"asinh\",\n\t\t\t\"atan\",\n\t\t\t\"atanh\",\n\t\t\t\"atan2\",\n\t\t\t\"cbrt\",\n\t\t\t\"ceil\",\n\t\t\t// \"clz32\",\n\t\t\t\"cos\",\n\t\t\t\"cosh\",\n\t\t\t\"exp\",\n\t\t\t\"expm1\",\n\t\t\t\"floor\",\n\t\t\t// \"fround\",\n\t\t\t// \"hypot\",\n\t\t\t// \"imul\",\n\t\t\t\"log\",\n\t\t\t\"log10\",\n\t\t\t\"log1p\",\n\t\t\t\"log2\",\n\t\t\t\"max\",\n\t\t\t\"min\",\n\t\t\t\"pow\",\n\t\t\t\"random\",\n\t\t\t\"round\",\n\t\t\t// \"sign\",\n\t\t\t\"sin\",\n\t\t\t\"sinh\",\n\t\t\t\"sqrt\",\n\t\t\t\"tan\",\n\t\t\t\"tanh\",\n\t\t\t\"trunc\",\n\t\t\t\"E\",\n\t\t\t\"LN10\",\n\t\t\t\"LN2\",\n\t\t\t\"LOG10E\",\n\t\t\t\"LOG2E\",\n\t\t\t\"PI\",\n\t\t\t\"SQRT1_2\",\n\t\t\t\"SQRT2\",\n\t\t},\n\t\t\"Date.prototype\": {\n\t\t\t\"constructor\",\n\t\t\t\"toString\",\n\t\t\t\"toDateString\",\n\t\t\t\"toTimeString\",\n\t\t\t\"toISOString\",\n\t\t\t\"toUTCString\",\n\t\t\t\"toGMTString\",\n\t\t\t\"getDate\",\n\t\t\t\"setDate\",\n\t\t\t\"getDay\",\n\t\t\t\"getFullYear\",\n\t\t\t\"setFullYear\",\n\t\t\t\"getHours\",\n\t\t\t\"setHours\",\n\t\t\t\"getMilliseconds\",\n\t\t\t\"setMilliseconds\",\n\t\t\t\"getMinutes\",\n\t\t\t\"setMinutes\",\n\t\t\t\"getMonth\",\n\t\t\t\"setMonth\",\n\t\t\t\"getSeconds\",\n\t\t\t\"setSeconds\",\n\t\t\t\"getTime\",\n\t\t\t\"setTime\",\n\t\t\t\"getTimezoneOffset\",\n\t\t\t\"getUTCDate\",\n\t\t\t\"setUTCDate\",\n\t\t\t\"getUTCDay\",\n\t\t\t\"getUTCFullYear\",\n\t\t\t\"setUTCFullYear\",\n\t\t\t\"getUTCHours\",\n\t\t\t\"setUTCHours\",\n\t\t\t\"getUTCMilliseconds\",\n\t\t\t\"setUTCMilliseconds\",\n\t\t\t\"getUTCMinutes\",\n\t\t\t\"setUTCMinutes\",\n\t\t\t\"getUTCMonth\",\n\t\t\t\"setUTCMonth\",\n\t\t\t\"getUTCSeconds\",\n\t\t\t\"setUTCSeconds\",\n\t\t\t\"valueOf\",\n\t\t\t\"getYear\",\n\t\t\t\"setYear\",\n\t\t\t\"toJSON\",\n\t\t\t\"toLocaleString\",\n\t\t\t\"toLocaleDateString\",\n\t\t\t\"toLocaleTimeString\",\n\t\t},\n\t\t\"RegExp.prototype\": {\n\t\t\t\"constructor\",\n\t\t\t\"exec\",\n\t\t\t// \"dotAll\",\n\t\t\t// \"flags\",\n\t\t\t// \"global\",\n\t\t\t// \"hasIndices\",\n\t\t\t// \"ignoreCase\",\n\t\t\t// \"multiline\",\n\t\t\t// \"source\",\n\t\t\t// \"sticky\",\n\t\t\t// \"unicode\",\n\t\t\t\"compile\",\n\t\t\t\"toString\",\n\t\t\t\"test\",\n\t\t},\n\t\t\"Error.prototype\": {\n\t\t\t\"constructor\",\n\t\t\t\"name\",\n\t\t\t\"message\",\n\t\t\t\"toString\",\n\t\t},\n\t\t\"EvalError.prototype\": {\n\t\t\t\"constructor\",\n\t\t\t\"name\",\n\t\t\t\"message\",\n\t\t\t\"toString\",\n\t\t},\n\t\t\"TypeError.prototype\": {\n\t\t\t\"constructor\",\n\t\t\t\"name\",\n\t\t\t\"message\",\n\t\t\t\"toString\",\n\t\t},\n\t\t\"ReferenceError.prototype\": {\n\t\t\t\"constructor\",\n\t\t\t\"name\",\n\t\t\t\"message\",\n\t\t\t\"toString\",\n\t\t},\n\t\t\"SyntaxError.prototype\": {\n\t\t\t\"constructor\",\n\t\t\t\"name\",\n\t\t\t\"message\",\n\t\t\t\"toString\",\n\t\t},\n\t\t\"URIError.prototype\": {\n\t\t\t\"constructor\",\n\t\t\t\"name\",\n\t\t\t\"message\",\n\t\t\t\"toString\",\n\t\t},\n\t\t\"JSON\": {\n\t\t\t\"parse\",\n\t\t\t\"stringify\",\n\t\t},\n\t\t\"NaN\":      {},\n\t\t\"Infinity\": {},\n\t}\n\tfor _, v := range []string{\n\t\t\"eval\", \"parseInt\", \"parseFloat\", \"isNaN\", \"isFinite\",\n\t\t\"decodeURI\", \"decodeURIComponent\", \"encodeURI\", \"encodeURIComponent\",\n\t\t\"escape\", \"unescape\",\n\t} {\n\t\ttests[v] = []string{\"length\", \"name\"}\n\t}\n\tfor name, expected := range tests {\n\t\tt.Run(name, func(t *testing.T) {\n\t\t\tval, err := vm.Run(fmt.Sprintf(\"Object.getOwnPropertyNames(%s)\", name))\n\t\t\trequire.NoErrorf(t, err, \"%#v\", err)\n\n\t\t\texport, err := val.Export()\n\t\t\trequire.NoError(t, err)\n\t\t\tif len(expected) == 0 {\n\t\t\t\t// Zero length doesn't know type.\n\t\t\t\trequire.Equal(t, []interface{}{}, export)\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\trequire.Equal(t, expected, export)\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "issue_test.go",
    "content": "package otto\n\nimport (\n\t\"database/sql\"\n\t\"database/sql/driver\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc Test_issue116(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n\t\t\t[1,-1].sort(function(a, b) {\n\t\t\t\treturn a - b;\n\t\t\t});\n        `, \"-1,1\")\n\t})\n}\n\nfunc Test_issue262(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\t// 11.13.1-1-1\n\t\ttest(`raise:\n            eval(\"42 = 42;\");\n        `, \"SyntaxError: (anonymous): Line 1:1 invalid left-hand side in assignment\")\n\t})\n}\n\nfunc Test_issue5(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`'abc' === 'def'`, false)\n\t\ttest(`'\\t' === '\\r'`, false)\n\t})\n}\n\nfunc Test_issue13(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, tester := test()\n\t\tvm := tester.vm\n\n\t\tvalue, err := vm.ToValue(map[string]interface{}{\n\t\t\t\"string\": \"Xyzzy\",\n\t\t\t\"number\": 42,\n\t\t\t\"array\":  []string{\"def\", \"ghi\"},\n\t\t})\n\t\trequire.NoError(t, err)\n\n\t\tfn, err := vm.Object(`\n            (function(value){\n                return \"\"+[value.string, value.number, value.array]\n            })\n        `)\n\t\trequire.NoError(t, err)\n\n\t\tresult, err := fn.Value().Call(fn.Value(), value)\n\t\trequire.NoError(t, err)\n\n\t\tis(result.string(), \"Xyzzy,42,def,ghi\")\n\n\t\tanything := struct {\n\t\t\tAbc interface{}\n\t\t}{\n\t\t\tAbc: map[string]interface{}{\n\t\t\t\t\"def\": []interface{}{\n\t\t\t\t\t[]interface{}{\n\t\t\t\t\t\t\"a\", \"b\", \"c\", \"\", \"d\", \"e\",\n\t\t\t\t\t},\n\t\t\t\t\tmap[string]interface{}{\n\t\t\t\t\t\t\"jkl\": \"Nothing happens.\",\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\t\"ghi\": -1,\n\t\t\t},\n\t\t}\n\n\t\terr = vm.Set(\"anything\", anything)\n\t\trequire.NoError(t, err)\n\t\ttest(`\n            [\n                anything,\n                \"~\",\n                anything.Abc,\n                \"~\",\n                anything.Abc.def,\n                \"~\",\n                anything.Abc.def[1].jkl,\n                \"~\",\n                anything.Abc.ghi,\n            ];\n        `, \"[object Object],~,[object Object],~,a,b,c,,d,e,[object Object],~,Nothing happens.,~,-1\")\n\t})\n}\n\nfunc Test_issue16(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, vm := test()\n\n\t\ttest(`\n            var def = {\n                \"abc\": [\"abc\"],\n                \"xyz\": [\"xyz\"]\n            };\n            def.abc.concat(def.xyz);\n        `, \"abc,xyz\")\n\n\t\tvm.Set(\"ghi\", []string{\"jkl\", \"mno\"})\n\n\t\ttest(`\n            def.abc.concat(def.xyz).concat(ghi);\n        `, \"abc,xyz,jkl,mno\")\n\n\t\ttest(`\n            ghi.concat(def.abc.concat(def.xyz));\n        `, \"jkl,mno,abc,xyz\")\n\n\t\tvm.Set(\"pqr\", []interface{}{\"jkl\", 42, 3.14159, true})\n\n\t\ttest(`\n            pqr.concat(ghi, def.abc, def, def.xyz);\n        `, \"jkl,42,3.14159,true,jkl,mno,abc,[object Object],xyz\")\n\n\t\ttest(`\n            pqr.concat(ghi, def.abc, def, def.xyz).length;\n        `, 9)\n\t})\n}\n\nfunc Test_issue21(t *testing.T) {\n\ttt(t, func() {\n\t\tvm1 := New()\n\t\t_, err := vm1.Run(`\n            abc = {}\n            abc.ghi = \"Nothing happens.\";\n            var jkl = 0;\n            abc.def = function() {\n                jkl += 1;\n                return 1;\n            }\n        `)\n\t\trequire.NoError(t, err)\n\t\tabc, err := vm1.Get(\"abc\")\n\t\trequire.NoError(t, err)\n\n\t\tvm2 := New()\n\t\terr = vm2.Set(\"cba\", abc)\n\t\trequire.NoError(t, err)\n\t\t_, err = vm2.Run(`\n            var pqr = 0;\n            cba.mno = function() {\n                pqr -= 1;\n                return 1;\n            }\n            cba.def();\n            cba.def();\n            cba.def();\n        `)\n\t\trequire.NoError(t, err)\n\n\t\tjkl, err := vm1.Get(\"jkl\")\n\t\trequire.NoError(t, err)\n\t\tis(jkl, 3)\n\n\t\t_, err = vm1.Run(`\n            abc.mno();\n            abc.mno();\n            abc.mno();\n        `)\n\t\trequire.NoError(t, err)\n\n\t\tpqr, err := vm2.Get(\"pqr\")\n\t\trequire.NoError(t, err)\n\t\tis(pqr, -3)\n\t})\n}\n\nfunc Test_issue24(t *testing.T) {\n\ttt(t, func() {\n\t\t_, vm := test()\n\n\t\t{\n\t\t\tvm.Set(\"abc\", []string{\"abc\", \"def\", \"ghi\"})\n\t\t\tvalue, err := vm.Get(\"abc\")\n\t\t\trequire.NoError(t, err)\n\t\t\texport, _ := value.Export()\n\t\t\t{\n\t\t\t\tvalue, valid := export.([]string)\n\t\t\t\tis(valid, true)\n\n\t\t\t\tis(value[0], \"abc\")\n\t\t\t\tis(value[2], \"ghi\")\n\t\t\t}\n\t\t}\n\n\t\t{\n\t\t\tvm.Set(\"abc\", [...]string{\"abc\", \"def\", \"ghi\"})\n\t\t\tvalue, err := vm.Get(\"abc\")\n\t\t\trequire.NoError(t, err)\n\t\t\texport, _ := value.Export()\n\t\t\t{\n\t\t\t\tvalue, valid := export.([3]string)\n\t\t\t\tis(valid, true)\n\n\t\t\t\tis(value[0], \"abc\")\n\t\t\t\tis(value[2], \"ghi\")\n\t\t\t}\n\t\t}\n\n\t\t{\n\t\t\tvm.Set(\"abc\", &[...]string{\"abc\", \"def\", \"ghi\"})\n\t\t\tvalue, err := vm.Get(\"abc\")\n\t\t\trequire.NoError(t, err)\n\t\t\texport, _ := value.Export()\n\t\t\t{\n\t\t\t\tvalue, valid := export.(*[3]string)\n\t\t\t\tis(valid, true)\n\n\t\t\t\tis(value[0], \"abc\")\n\t\t\t\tis(value[2], \"ghi\")\n\t\t\t}\n\t\t}\n\n\t\t{\n\t\t\tvm.Set(\"abc\", map[int]string{0: \"abc\", 1: \"def\", 2: \"ghi\"})\n\t\t\tvalue, err := vm.Get(\"abc\")\n\t\t\trequire.NoError(t, err)\n\t\t\texport, _ := value.Export()\n\t\t\t{\n\t\t\t\tvalue, valid := export.(map[int]string)\n\t\t\t\tis(valid, true)\n\n\t\t\t\tis(value[0], \"abc\")\n\t\t\t\tis(value[2], \"ghi\")\n\t\t\t}\n\t\t}\n\n\t\t{\n\t\t\tvm.Set(\"abc\", abcStruct{Abc: true, Ghi: \"Nothing happens.\"})\n\t\t\tvalue, err := vm.Get(\"abc\")\n\t\t\trequire.NoError(t, err)\n\t\t\texport, _ := value.Export()\n\t\t\t{\n\t\t\t\tvalue, valid := export.(abcStruct)\n\t\t\t\tis(valid, true)\n\n\t\t\t\tis(value.Abc, true)\n\t\t\t\tis(value.Ghi, \"Nothing happens.\")\n\t\t\t}\n\t\t}\n\n\t\t{\n\t\t\tvm.Set(\"abc\", &abcStruct{Abc: true, Ghi: \"Nothing happens.\"})\n\t\t\tvalue, err := vm.Get(\"abc\")\n\t\t\trequire.NoError(t, err)\n\t\t\texport, _ := value.Export()\n\t\t\t{\n\t\t\t\tvalue, valid := export.(*abcStruct)\n\t\t\t\tis(valid, true)\n\n\t\t\t\tis(value.Abc, true)\n\t\t\t\tis(value.Ghi, \"Nothing happens.\")\n\t\t\t}\n\t\t}\n\t})\n}\n\nfunc Test_issue39(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            var abc = 0, def = [], ghi = function() {\n                if (abc < 10) return ++abc;\n                return undefined;\n            }\n            for (var jkl; (jkl = ghi());) def.push(jkl);\n            def;\n        `, \"1,2,3,4,5,6,7,8,9,10\")\n\n\t\ttest(`\n            var abc = [\"1\", \"2\", \"3\", \"4\"];\n            var def = [];\n            for (var ghi; (ghi = abc.shift());) {\n                def.push(ghi);\n            }\n            def;\n        `, \"1,2,3,4\")\n\t})\n}\n\nfunc Test_issue64(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, vm := test()\n\n\t\tdefer mockTimeLocal(time.UTC)()\n\n\t\tabc := map[string]interface{}{\n\t\t\t\"time\": time.Unix(0, 0),\n\t\t}\n\t\tvm.Set(\"abc\", abc)\n\n\t\tdef := struct {\n\t\t\tPublic  string\n\t\t\tprivate string\n\t\t}{\n\t\t\t\"Public\", \"private\",\n\t\t}\n\t\tvm.Set(\"def\", def)\n\n\t\ttest(`\"sec\" in abc.time`, false)\n\n\t\ttest(`\n            [ \"Public\" in def, \"private\" in def, def.Public, def.private ];\n        `, \"true,false,Public,\")\n\n\t\ttest(`JSON.stringify(abc)`, `{\"time\":\"1970-01-01T00:00:00Z\"}`)\n\t})\n}\n\nfunc Test_issue73(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, vm := test()\n\n\t\tvm.Set(\"abc\", [4]int{3, 2, 1, 0})\n\n\t\ttest(`\n            var def = [ 0, 1, 2, 3 ];\n            JSON.stringify(def) + JSON.stringify(abc);\n        `, \"[0,1,2,3][3,2,1,0]\")\n\t})\n}\n\nfunc Test_7_3_1(t *testing.T) {\n\ttt(t, func() {\n\t\ttest(`\n            eval(\"var test7_3_1\\u2028abc = 66;\");\n            [ abc, typeof test7_3_1 ];\n        `, \"66,undefined\")\n\t})\n}\n\nfunc Test_7_3_3(t *testing.T) {\n\ttt(t, func() {\n\t\ttest(`raise:\n            eval(\"//\\u2028 =;\");\n        `, \"SyntaxError: Unexpected token =\")\n\t})\n}\n\nfunc Test_S7_3_A2_1_T1(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`raise:\n            eval(\"'\\u000Astr\\u000Aing\\u000A'\")\n        `, \"SyntaxError: (anonymous): Line 1:1 Unexpected token ILLEGAL\")\n\t})\n}\n\nfunc Test_S7_8_3_A2_1_T1(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            [ .0 === 0.0, .0, .1 === 0.1, .1 ]\n        `, \"true,0,true,0.1\")\n\t})\n}\n\nfunc Test_S7_8_4_A4_2_T3(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            \"\\a\"\n        `, \"a\")\n\t})\n}\n\nfunc Test_S7_9_A1(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            var def;\n            abc: for (var i = 0; i <= 0; i++) {\n                for (var j = 0; j <= 1; j++) {\n                    if (j === 0) {\n                        continue abc;\n                    } else {\n                        def = true;\n                    }\n                }\n            }\n            [ def, i, j ];\n        `, \",1,0\")\n\t})\n}\n\nfunc Test_S7_9_A3(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            (function(){\n                return\n                1;\n            })()\n        `, \"undefined\")\n\t})\n}\n\nfunc Test_7_3_10(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            eval(\"var \\u0061\\u0062\\u0063 = 3.14159;\");\n            abc;\n        `, 3.14159)\n\n\t\ttest(`\n            abc = undefined;\n            eval(\"var \\\\u0061\\\\u0062\\\\u0063 = 3.14159;\");\n            abc;\n        `, 3.14159)\n\t})\n}\n\nfunc Test_bug(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\t// 10.4.2-1-5\n\t\ttest(`\n            \"abc\\\ndef\"\n        `, \"abcdef\")\n\n\t\ttest(`\n            eval(\"'abc';\\\n            'def'\")\n        `, \"def\")\n\n\t\t// S12.6.1_A10\n\t\ttest(`\n            var abc = 0;\n            do {\n                if(typeof(def) === \"function\"){\n                    abc = -1;\n                    break;\n                } else {\n                    abc = 1;\n                    break;\n                }\n            } while(function def(){});\n            abc;\n        `, 1)\n\n\t\t// S12.7_A7\n\t\ttest(`raise:\n            abc:\n            while (true) {\n                eval(\"continue abc\");\n            }\n        `, \"SyntaxError: (anonymous): Line 1:1 Undefined label 'abc'\")\n\n\t\t// S15.1.2.1_A3.3_T3\n\t\ttest(`raise:\n            eval(\"return\");\n        `, \"SyntaxError: (anonymous): Line 1:1 Illegal return statement\")\n\n\t\t// 15.2.3.3-2-33\n\t\ttest(`\n            var abc = { \"AB\\n\\\\cd\": 1 };\n            Object.getOwnPropertyDescriptor(abc, \"AB\\n\\\\cd\").value;\n        `, 1)\n\n\t\t// S15.3_A2_T1\n\t\ttest(`raise:\n            Function.call(this, \"var x / = 1;\");\n        `, \"SyntaxError: (anonymous): Line 2:7 Unexpected token / (and 3 more errors)\")\n\n\t\t// ?\n\t\ttest(`\n            (function(){\n                var abc = [];\n                (function(){\n                    abc.push(0);\n                    abc.push(1);\n                })(undefined);\n                if ((function(){ return true; })()) {\n                    (function(){\n                        abc.push(2);\n                    })();\n                }\n                return abc;\n            })();\n        `, \"0,1,2\")\n\n\t\tif false {\n\t\t\t// 15.9.5.43-0-10\n\t\t\t// Should be an invalid date\n\t\t\ttest(`\n                date = new Date(1970, 0, -99999999, 0, 0, 0, 1);\n            `, \"\")\n\t\t}\n\n\t\t// S7.8.3_A1.2_T1\n\t\ttest(`\n            [ 0e1, 1e1, 2e1, 3e1, 4e1, 5e1, 6e1, 7e1, 8e1, 9e1 ];\n        `, \"0,10,20,30,40,50,60,70,80,90\")\n\n\t\t// S15.10.2.7_A3_T2\n\t\ttest(`\n            var abc = /\\s+abc\\s+/.exec(\"\\t abc def\");\n            [ abc.length, abc.index, abc.input, abc ];\n        `, \"1,0,\\t abc def,\\t abc \")\n\t})\n}\n\nfunc Test_issue79(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, vm := test()\n\n\t\tvm.Set(\"abc\", []abcStruct{\n\t\t\t{\n\t\t\t\tGhi: \"一\",\n\t\t\t\tDef: 1,\n\t\t\t},\n\t\t\t{\n\t\t\t\tDef: 3,\n\t\t\t\tGhi: \"三\",\n\t\t\t},\n\t\t\t{\n\t\t\t\tDef: 2,\n\t\t\t\tGhi: \"二\",\n\t\t\t},\n\t\t\t{\n\t\t\t\tDef: 4,\n\t\t\t\tGhi: \"四\",\n\t\t\t},\n\t\t})\n\n\t\ttest(`\n            abc.sort(function(a,b){ return b.Def-a.Def });\n            def = [];\n            for (i = 0; i < abc.length; i++) {\n                def.push(abc[i].String())\n            }\n            def;\n        `, \"四,三,二,一\")\n\t})\n}\n\nfunc Test_issue80(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            JSON.stringify([\n                1401868959,\n                14018689591,\n                140186895901,\n                1401868959001,\n                14018689590001,\n                140186895900001,\n                1401868959000001,\n            ]);\n        `, \"[1401868959,14018689591,140186895901,1401868959001,14018689590001,140186895900001,1401868959000001]\")\n\t})\n}\n\nfunc Test_issue86(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, tester := test()\n\n\t\ttest(`\n\t\t\tvar obj = Object.create({}, {\n\t\t\t\tabc: {\n\t\t\t\t\tget: function(){\n\t\t\t\t\t\treturn 1;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t});\n\t\t\tobj.abc;\n\t\t`, 1)\n\n\t\tv, err := tester.vm.Copy().Run(`obj.abc;`)\n\t\tis(is(v, 1), is(nil, err))\n\t})\n}\n\nfunc Test_issue87(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, vm := test()\n\n\t\ttest(`\n            var def = 0;\n            abc: {\n                for (;;) {\n                    def = !1;\n                    break abc;\n                }\n                def = !0;\n            }\n            def;\n        `, false)\n\n\t\t_, err := vm.Run(`\n/*\nCryptoJS v3.1.2\ncode.google.com/p/crypto-js\n(c) 2009-2013 by Jeff Mott. All rights reserved.\ncode.google.com/p/crypto-js/wiki/License\n*/\nvar CryptoJS=CryptoJS||function(h,s){var f={},g=f.lib={},q=function(){},m=g.Base={extend:function(a){q.prototype=this;var c=new q;a&&c.mixIn(a);c.hasOwnProperty(\"init\")||(c.init=function(){c.$super.init.apply(this,arguments)});c.init.prototype=c;c.$super=this;return c},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var c in a)a.hasOwnProperty(c)&&(this[c]=a[c]);a.hasOwnProperty(\"toString\")&&(this.toString=a.toString)},clone:function(){return this.init.prototype.extend(this)}},\nr=g.WordArray=m.extend({init:function(a,c){a=this.words=a||[];this.sigBytes=c!=s?c:4*a.length},toString:function(a){return(a||k).stringify(this)},concat:function(a){var c=this.words,d=a.words,b=this.sigBytes;a=a.sigBytes;this.clamp();if(b%4)for(var e=0;e<a;e++)c[b+e>>>2]|=(d[e>>>2]>>>24-8*(e%4)&255)<<24-8*((b+e)%4);else if(65535<d.length)for(e=0;e<a;e+=4)c[b+e>>>2]=d[e>>>2];else c.push.apply(c,d);this.sigBytes+=a;return this},clamp:function(){var a=this.words,c=this.sigBytes;a[c>>>2]&=4294967295<<\n32-8*(c%4);a.length=h.ceil(c/4)},clone:function(){var a=m.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var c=[],d=0;d<a;d+=4)c.push(4294967296*h.random()|0);return new r.init(c,a)}}),l=f.enc={},k=l.Hex={stringify:function(a){var c=a.words;a=a.sigBytes;for(var d=[],b=0;b<a;b++){var e=c[b>>>2]>>>24-8*(b%4)&255;d.push((e>>>4).toString(16));d.push((e&15).toString(16))}return d.join(\"\")},parse:function(a){for(var c=a.length,d=[],b=0;b<c;b+=2)d[b>>>3]|=parseInt(a.substr(b,\n2),16)<<24-4*(b%8);return new r.init(d,c/2)}},n=l.Latin1={stringify:function(a){var c=a.words;a=a.sigBytes;for(var d=[],b=0;b<a;b++)d.push(String.fromCharCode(c[b>>>2]>>>24-8*(b%4)&255));return d.join(\"\")},parse:function(a){for(var c=a.length,d=[],b=0;b<c;b++)d[b>>>2]|=(a.charCodeAt(b)&255)<<24-8*(b%4);return new r.init(d,c)}},j=l.Utf8={stringify:function(a){try{return decodeURIComponent(escape(n.stringify(a)))}catch(c){throw Error(\"Malformed UTF-8 data\");}},parse:function(a){return n.parse(unescape(encodeURIComponent(a)))}},\nu=g.BufferedBlockAlgorithm=m.extend({reset:function(){this._data=new r.init;this._nDataBytes=0},_append:function(a){\"string\"==typeof a&&(a=j.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(a){var c=this._data,d=c.words,b=c.sigBytes,e=this.blockSize,f=b/(4*e),f=a?h.ceil(f):h.max((f|0)-this._minBufferSize,0);a=f*e;b=h.min(4*a,b);if(a){for(var g=0;g<a;g+=e)this._doProcessBlock(d,g);g=d.splice(0,a);c.sigBytes-=b}return new r.init(g,b)},clone:function(){var a=m.clone.call(this);\na._data=this._data.clone();return a},_minBufferSize:0});g.Hasher=u.extend({cfg:m.extend(),init:function(a){this.cfg=this.cfg.extend(a);this.reset()},reset:function(){u.reset.call(this);this._doReset()},update:function(a){this._append(a);this._process();return this},finalize:function(a){a&&this._append(a);return this._doFinalize()},blockSize:16,_createHelper:function(a){return function(c,d){return(new a.init(d)).finalize(c)}},_createHmacHelper:function(a){return function(c,d){return(new t.HMAC.init(a,\nd)).finalize(c)}}});var t=f.algo={};return f}(Math);\n(function(h){for(var s=CryptoJS,f=s.lib,g=f.WordArray,q=f.Hasher,f=s.algo,m=[],r=[],l=function(a){return 4294967296*(a-(a|0))|0},k=2,n=0;64>n;){var j;a:{j=k;for(var u=h.sqrt(j),t=2;t<=u;t++)if(!(j%t)){j=!1;break a}j=!0}j&&(8>n&&(m[n]=l(h.pow(k,0.5))),r[n]=l(h.pow(k,1/3)),n++);k++}var a=[],f=f.SHA256=q.extend({_doReset:function(){this._hash=new g.init(m.slice(0))},_doProcessBlock:function(c,d){for(var b=this._hash.words,e=b[0],f=b[1],g=b[2],j=b[3],h=b[4],m=b[5],n=b[6],q=b[7],p=0;64>p;p++){if(16>p)a[p]=\nc[d+p]|0;else{var k=a[p-15],l=a[p-2];a[p]=((k<<25|k>>>7)^(k<<14|k>>>18)^k>>>3)+a[p-7]+((l<<15|l>>>17)^(l<<13|l>>>19)^l>>>10)+a[p-16]}k=q+((h<<26|h>>>6)^(h<<21|h>>>11)^(h<<7|h>>>25))+(h&m^~h&n)+r[p]+a[p];l=((e<<30|e>>>2)^(e<<19|e>>>13)^(e<<10|e>>>22))+(e&f^e&g^f&g);q=n;n=m;m=h;h=j+k|0;j=g;g=f;f=e;e=k+l|0}b[0]=b[0]+e|0;b[1]=b[1]+f|0;b[2]=b[2]+g|0;b[3]=b[3]+j|0;b[4]=b[4]+h|0;b[5]=b[5]+m|0;b[6]=b[6]+n|0;b[7]=b[7]+q|0},_doFinalize:function(){var a=this._data,d=a.words,b=8*this._nDataBytes,e=8*a.sigBytes;\nd[e>>>5]|=128<<24-e%32;d[(e+64>>>9<<4)+14]=h.floor(b/4294967296);d[(e+64>>>9<<4)+15]=b;a.sigBytes=4*d.length;this._process();return this._hash},clone:function(){var a=q.clone.call(this);a._hash=this._hash.clone();return a}});s.SHA256=q._createHelper(f);s.HmacSHA256=q._createHmacHelper(f)})(Math);\n(function(){var h=CryptoJS,s=h.enc.Utf8;h.algo.HMAC=h.lib.Base.extend({init:function(f,g){f=this._hasher=new f.init;\"string\"==typeof g&&(g=s.parse(g));var h=f.blockSize,m=4*h;g.sigBytes>m&&(g=f.finalize(g));g.clamp();for(var r=this._oKey=g.clone(),l=this._iKey=g.clone(),k=r.words,n=l.words,j=0;j<h;j++)k[j]^=1549556828,n[j]^=909522486;r.sigBytes=l.sigBytes=m;this.reset()},reset:function(){var f=this._hasher;f.reset();f.update(this._iKey)},update:function(f){this._hasher.update(f);return this},finalize:function(f){var g=\nthis._hasher;f=g.finalize(f);g.reset();return g.finalize(this._oKey.clone().concat(f))}})})();\n        `)\n\t\trequire.NoError(t, err)\n\n\t\ttest(`CryptoJS.HmacSHA256(\"Message\", \"secret\");`, \"aa747c502a898200f9e4fa21bac68136f886a0e27aec70ba06daf2e2a5cb5597\")\n\t})\n}\n\nfunc Test_S9_3_1_A2(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n\t\t\tNumber(\"\\u0009\\u000C\\u0020\\u00A0\\u000B\\u000A\\u000D\\u2028\\u2029\\u1680\\u180E\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200A\\u202F\\u205F\\u3000\") === 0;\n        `, true)\n\n\t\ttest(`\n\t\t\tNumber(\"\\u180E\") === 0;\n        `, true)\n\t})\n}\n\nfunc Test_S15_1_2_2_A2_T10(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n\t\t\tparseInt(\"\\u180E\" + \"1\") === parseInt(\"1\");\n        `, true)\n\n\t\ttest(`\n\t\t\tparseInt(\"\\u180E\" + \"\\u180E\" + \"\\u180E\" + \"1\") === parseInt(\"1\");\n        `, true)\n\t})\n}\n\nfunc Test_S15_1_2_3_A2_T10(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n\t\t\tparseFloat(\"\\u180E\" + \"1.1\") === parseFloat(\"1.1\");\n        `, true)\n\n\t\ttest(`\n\t\t\tparseFloat(\"\\u180E\" + \"\\u180E\" + \"\\u180E\" + \"1.1\") === parseFloat(\"1.1\");\n        `, true)\n\t})\n}\n\nfunc Test_issue234(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n\t\t\tvar abc = \"6E6E6EF72905D973E8FEF9F38F01AC4D95A600E6A6E1.C1DBF2F71A5F8C9EB04B75E7A879B4C90C25313A\".split(\"\");\n\t\t\tabc.splice(0, 2);\n\t\t`, \"6,E\")\n\t})\n}\n\nfunc Test_issue186(t *testing.T) {\n\ttests := []struct {\n\t\terr    error\n\t\tname   string\n\t\tscript string\n\t}{\n\t\t{\n\t\t\tname:   \"missing\",\n\t\t\tscript: `abc(\"a\",\"b\")`,\n\t\t\terr:    errors.New(\"RangeError: expected 3 argument(s); got 2\"),\n\t\t},\n\t\t{\n\t\t\tname:   \"too-many\",\n\t\t\tscript: `abc(\"a\",\"b\",\"c\",\"d\")`,\n\t\t\terr:    errors.New(\"RangeError: expected 3 argument(s); got 4\"),\n\t\t},\n\t\t{\n\t\t\tname:   \"valid-conversion\",\n\t\t\tscript: `abc(1,2,3)`,\n\t\t},\n\t\t{\n\t\t\tname:   \"valid-type\",\n\t\t\tscript: `num(1,2,3)`,\n\t\t},\n\t\t{\n\t\t\tname:   \"invalid-type-conversion\",\n\t\t\tscript: `num(\"a\",\"b\",\"c\")`,\n\t\t\terr:    errors.New(`TypeError: can't convert from \"string\" to \"int\"`),\n\t\t},\n\t}\n\n\tvm := New()\n\terr := vm.Set(\"abc\", func(a string, b string, c string) int {\n\t\treturn 1\n\t})\n\trequire.NoError(t, err)\n\terr = vm.Set(\"num\", func(a int, b int, c int) int {\n\t\treturn 1\n\t})\n\trequire.NoError(t, err)\n\n\tfor _, tc := range tests {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\t_, err = vm.Run(tc.script)\n\t\t\tif tc.err != nil {\n\t\t\t\trequire.Error(t, err)\n\t\t\t\trequire.Equal(t, tc.err.Error(), err.Error())\n\t\t\t\treturn\n\t\t\t}\n\t\t\trequire.NoError(t, err)\n\t\t})\n\t}\n}\n\nfunc Test_issue266(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n\t\t\t[0.5, 0.8, 0.2].sort(function(a, b) {\n\t\t\t\treturn a - b;\n\t\t\t});\n        `, \"0.2,0.5,0.8\")\n\n\t\ttest(`\n\t\t\t[2147483647, -1, 1].sort(function(a, b) {\n\t\t\t\treturn a - b;\n\t\t\t});\n        `, \"-1,1,2147483647\")\n\n\t\ttest(`\n\t\t\t[2e11, -2e11, 0].sort(function(a, b) {\n\t\t\t\treturn a - b;\n\t\t\t});\n        `, \"-200000000000,0,200000000000\")\n\t})\n}\n\nfunc Test_issue369(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, tester := test()\n\n\t\ttype Test struct {\n\t\t\tValue string\n\t\t}\n\n\t\ttype PtrTest struct {\n\t\t\t*Test\n\t\t}\n\n\t\ttestItem := Test{\n\t\t\tValue: \"A test value\",\n\t\t}\n\n\t\tptrTestItem := PtrTest{\n\t\t\tTest: &testItem,\n\t\t}\n\n\t\ttester.Set(\"testVariable\", ptrTestItem)\n\n\t\ttest(`\n\t\tJSON.stringify(testVariable);\n\t`, `{\"Test\":{\"Value\":\"A test value\"}}`)\n\t})\n}\n\n// testResult is a test driver.Result.\ntype testResult struct{}\n\nfunc (r *testResult) LastInsertId() (int64, error) {\n\treturn 0, errors.New(\"not supported\")\n}\n\nfunc (r *testResult) RowsAffected() (int64, error) {\n\treturn 1, nil\n}\n\n// testStmt is a test driver.Stmt.\ntype testStmt struct{}\n\n// Close implements driver.Stmt.\nfunc (s *testStmt) Close() error {\n\treturn nil\n}\n\n// NumInput implements driver.Stmt.\nfunc (s *testStmt) NumInput() int {\n\treturn -1\n}\n\n// Exec implements driver.Stmt.\nfunc (s *testStmt) Exec(args []driver.Value) (driver.Result, error) {\n\treturn &testResult{}, nil\n}\n\n// Query implements driver.Stmt.\nfunc (s *testStmt) Query(args []driver.Value) (driver.Rows, error) {\n\treturn nil, errors.New(\"not supported\")\n}\n\n// testConn is a test driver.Conn.\ntype testConn struct{}\n\n// Prepare implements driver.Conn.\nfunc (c *testConn) Prepare(query string) (driver.Stmt, error) {\n\treturn &testStmt{}, nil\n}\n\n// Close implements driver.Conn.\nfunc (c *testConn) Close() error {\n\treturn nil\n}\n\n// Begin implements driver.Conn.\nfunc (c *testConn) Begin() (driver.Tx, error) {\n\treturn nil, errors.New(\"not supported\")\n}\n\n// testDriver is test driver.Driver.\ntype testDriver struct{}\n\n// Open implements driver.Driver.\nfunc (db *testDriver) Open(name string) (driver.Conn, error) {\n\treturn &testConn{}, nil\n}\n\nfunc Test_issue390(t *testing.T) {\n\tsql.Register(\"testDriver\", &testDriver{})\n\tdb, err := sql.Open(\"testDriver\", \"test.db\")\n\trequire.NoError(t, err)\n\n\t_, err = db.Exec(\"CREATE TABLE IF NOT EXISTS log (message)\")\n\trequire.NoError(t, err)\n\n\tvm := New()\n\terr = vm.Set(\"db\", db)\n\trequire.NoError(t, err)\n\tval, err := vm.Run(`\n\t\tdb.Exec(\"CREATE TABLE log (message)\")\n\t\tvar results = db.Exec(\"INSERT INTO log(message) VALUES(?)\", \"test123\");\n\t\tvar res = results[0];\n\t\tvar err = results[1];\n\t\tif (typeof err !== 'undefined') {\n\t\t\tresult = err\n\t\t} else {\n\t\t\tresults = res.RowsAffected()\n\t\t\tvar rows = results[0];\n\t\t\tvar err = results[1];\n\t\t\tif (typeof err !== 'undefined') {\n\t\t\t\tresult = err\n\t\t\t} else {\n\t\t\t\tresult = rows;\n\t\t\t}\n\t\t}\n\t\tresult`,\n\t)\n\trequire.NoError(t, err)\n\trows, err := val.ToInteger()\n\trequire.NoError(t, err)\n\trequire.Equal(t, int64(1), rows)\n}\n\ntype testSetType struct {\n\tString string\n\tArray  [1]string\n\tSlice  []string\n}\n\nfunc Test_issue386(t *testing.T) {\n\tvar msg testSetType\n\tmsg.String = \"string\"\n\tmsg.Slice = []string{\"slice\"}\n\tmsg.Array[0] = \"array\"\n\n\tvm := New()\n\terr := vm.Set(\"msg\", &msg)\n\trequire.NoError(t, err)\n\n\ttests := map[string]string{\n\t\t\"string\": `\n\t\t\tmsg.TypeMessage = 'something';\n\t\t\tmsg.TypeMessage;`,\n\t\t\"array\": `\n\t\t\tmsg.Array[0] = 'something';\n\t\t\tmsg.Array[0]`,\n\t\t\"slice\": `\n\t\t\tmsg.Slice[0] = 'something';\n\t\t\tmsg.Slice[0]`,\n\t}\n\n\tfor name, code := range tests {\n\t\tt.Run(name, func(t *testing.T) {\n\t\t\tval, err2 := vm.Run(code)\n\t\t\trequire.NoError(t, err2)\n\t\t\trequire.Equal(t, \"something\", val.String())\n\t\t})\n\t}\n}\n\nfunc Test_issue383(t *testing.T) {\n\tvm := New()\n\terr := vm.Set(\"panicFunc\", func(call FunctionCall) Value {\n\t\tpanic(\"test\")\n\t})\n\trequire.NoError(t, err)\n\t_, err = vm.Run(`\n\t\ttry {\n\t\t\tpanicFunc()\n\t\t} catch (err) {\n\t\t\tconsole.log(\"panic triggered:\", err)\n\t\t}\n\t`)\n\trequire.NoError(t, err)\n}\n\nfunc Test_issue357(t *testing.T) {\n\tvm := New()\n\tarr := []string{\"wow\", \"hey\"}\n\terr := vm.Set(\"arr\", arr)\n\trequire.NoError(t, err)\n\n\tval, err := vm.Run(`\n\t\tarr.push('another', 'more');\n\t\tarr;\n\t`)\n\trequire.NoError(t, err)\n\tiface, err := val.Export()\n\trequire.NoError(t, err)\n\n\tslice, ok := iface.([]string)\n\trequire.True(t, ok)\n\n\trequire.Equal(t, []string{\"wow\", \"hey\", \"another\", \"more\"}, slice)\n}\n\nfunc Test_issue302(t *testing.T) {\n\ttests := map[string]struct {\n\t\tcode string\n\t\twant string\n\t}{\n\t\t\"underflow\": {\n\t\t\tcode: \"new Date(9223372036855).toUTCString();\",\n\t\t\twant: \"Fri, 11 Apr 2262 23:47:16 GMT\",\n\t\t},\n\t\t\"after-2262\": {\n\t\t\tcode: \"new Date('2263-04-11T23:47:16.855Z').toUTCString();\",\n\t\t\twant: \"Sat, 11 Apr 2263 23:47:16 GMT\",\n\t\t},\n\t\t\"before-1677\": {\n\t\t\tcode: \"new Date('1676-09-21T00:12:43.146Z').toUTCString();\",\n\t\t\twant: \"Mon, 21 Sep 1676 00:12:43 GMT\",\n\t\t},\n\t}\n\n\tvm := New()\n\tfor name, tt := range tests {\n\t\tt.Run(name, func(t *testing.T) {\n\t\t\tval, err := vm.Run(tt.code)\n\t\t\trequire.NoError(t, err)\n\n\t\t\texp, err := val.Export()\n\t\t\trequire.NoError(t, err)\n\t\t\trequire.Equal(t, tt.want, exp)\n\t\t})\n\t}\n}\n\nfunc Test_issue329(t *testing.T) {\n\tvm := New()\n\tval, err := vm.Run(`\n\t\trun(c);\n\t\tvar stackLen;\n\t\tfunction run(fn) {\n\t\t\ttry {\n\t\t\t\tfn();\n\t\t\t} catch (err) {\n\t\t\t\tstackLen = err.stack.split(/\\n/).length;\n\t\t\t}\n\t\t};\n\n\t\tfunction c() { d() }\n\t\tfunction d() { return 'x'.join(',') }\n\t\tstackLen;\n\t`)\n\trequire.NoError(t, err)\n\tlength, err := val.Export()\n\trequire.NoError(t, err)\n\trequire.Equal(t, uint32(6), length)\n}\n\nfunc Test_issue317(t *testing.T) {\n\tvm := New()\n\ttests := map[string]struct {\n\t\tinput  string\n\t\tregexp string\n\t\twant   string\n\t}{\n\t\t\"match-all\": {\n\t\t\tinput:  \"all-11-22-33-44-55-66-77-88-99-XX\",\n\t\t\tregexp: \"(1+)-(2+)-(3+)-(4+)-(5+)-(6+)-(7+)-(8+)-(9+)-(X+)\",\n\t\t\twant:   \"all-11-22-33-44-55-66-77-88-99-XX,11,22,33,44,55,66,77,88,99\",\n\t\t},\n\t\t\"match-partial\": {\n\t\t\tinput:  \"partial-11-22-33-44-55-66-77-88-99-XX\",\n\t\t\tregexp: \"(1+)-(2+)-(3+)-(4+)-(5+)\",\n\t\t\twant:   \"partial-11-22-33-44-55-66-77-88-99-XX,11,22,33,44,55,,,,\",\n\t\t},\n\t\t\"no-match\": {\n\t\t\tinput:  \"no-22-33-44-55-66-77-88-99-XX\",\n\t\t\tregexp: \"(1+)-(2+)-(3+)-(4+)-(5+)-(6+)-(7+)-(8+)-(9+)-(X+)\",\n\t\t\twant:   \"\",\n\t\t},\n\t\t\"missing-match\": {\n\t\t\tinput:  \"data:image/png;base64,\",\n\t\t\tregexp: \"^data:(.*?)(;(.*?))??(;base64)?,\",\n\t\t\twant:   \"data:image/png;base64,,image/png,,,;base64,,,,,\",\n\t\t},\n\t}\n\n\tprevious := \",,,,,,,,,\"\n\tfor name, tt := range tests {\n\t\tt.Run(name, func(t *testing.T) {\n\t\t\terr := vm.Set(\"val\", tt.input)\n\t\t\trequire.NoError(t, err)\n\n\t\t\terr = vm.Set(\"regexp\", tt.regexp)\n\t\t\trequire.NoError(t, err)\n\n\t\t\tval, err := vm.Run(`\n\t\t\t\tvar parts = [];\n\t\t\t\tnew RegExp(regexp).test(val);\n\t\t\t\tparts.push(\n\t\t\t\t\tRegExp.$_, RegExp.$1, RegExp.$2, RegExp.$3, RegExp.$4,\n\t\t\t\t\tRegExp.$5, RegExp.$6, RegExp.$7, RegExp.$8, RegExp.$9\n\t\t\t\t);\n\t\t\t\tparts.join(\",\");\n\t\t\t`)\n\t\t\trequire.NoError(t, err)\n\n\t\t\t// If no match occurs the previous values will remain.\n\t\t\tif tt.want == \"\" {\n\t\t\t\ttt.want = previous\n\t\t\t}\n\t\t\tprevious = tt.want\n\n\t\t\texp, err := val.Export()\n\t\t\trequire.NoError(t, err)\n\t\t\trequire.Equal(t, tt.want, exp)\n\t\t})\n\t}\n}\n\nfunc Test_issue252(t *testing.T) {\n\tin := map[string]interface{}{\n\t\t\"attr\": []interface{}{\"string\"},\n\t}\n\texpected := map[string]interface{}{\n\t\t\"attr\": []string{\"changed\"},\n\t}\n\n\tvm := New()\n\terr := vm.Set(\"In\", in)\n\trequire.NoError(t, err)\n\n\tresult, err := vm.Run(`(function fn() {\n\t\tvar tmp = In;\n\t\ttmp.attr = [\"changed\"];\n\t\treturn tmp;\n\t})()`)\n\trequire.NoError(t, err)\n\n\tactual, err := result.Export()\n\trequire.NoError(t, err)\n\trequire.Equal(t, expected, actual)\n\n\texpBs, err := json.Marshal(expected)\n\trequire.NoError(t, err)\n\tactBs, err := json.Marshal(actual)\n\trequire.NoError(t, err)\n\trequire.Equal(t, expBs, actBs)\n}\n\nfunc Test_issue177(t *testing.T) {\n\tvm := New()\n\tval, err := vm.Run(`\n\t\tvar ii = 33;\n\t\tvar ret = [3, 2, 1].reduce(\n\t\t\tfunction(pv, cv, ci, a) {\n\t\t\t\treturn pv + cv + ci;\n\t\t\t}\n\t\t);\n\t\tret;\n\t`)\n\trequire.NoError(t, err)\n\texp, err := val.Export()\n\trequire.NoError(t, err)\n\trequire.EqualValues(t, 9, exp)\n}\n\nfunc Test_issue285(t *testing.T) {\n\tvm := New()\n\tval, err := vm.Run(`(1451).toLocaleString('en-US')`)\n\trequire.NoError(t, err)\n\texp, err := val.Export()\n\trequire.NoError(t, err)\n\trequire.Equal(t, \"1,451\", exp)\n}\n"
  },
  {
    "path": "json_test.go",
    "content": "package otto\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc BenchmarkJSON_parse(b *testing.B) {\n\tvm := New()\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err := vm.Run(`JSON.parse(\"1\")`)\n\t\trequire.NoError(b, err)\n\t\t_, err = vm.Run(`JSON.parse(\"[1,2,3]\")`)\n\t\trequire.NoError(b, err)\n\t\t_, err = vm.Run(`JSON.parse('{\"a\":{\"x\":100,\"y\":110},\"b\":[10,20,30],\"c\":\"zazazaza\"}')`)\n\t\trequire.NoError(b, err)\n\t\t_, err = vm.Run(`JSON.parse(\"[1,2,3]\", function(k, v) { return undefined })`)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc TestJSON_parse(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            JSON.parse(\"1\");\n        `, 1)\n\n\t\ttest(`\n            JSON.parse(\"null\");\n        `, \"null\") // TODO Can we make this nil?\n\n\t\ttest(`\n            var abc = JSON.parse('\"a\\uFFFFbc\"');\n            [ abc[0], abc[2], abc[3], abc.length ];\n        `, \"a,b,c,4\")\n\n\t\ttest(`\n            JSON.parse(\"[1, 2, 3]\");\n        `, \"1,2,3\")\n\n\t\ttest(`\n            JSON.parse('{ \"abc\": 1, \"def\":2 }').abc;\n        `, 1)\n\n\t\ttest(`\n            JSON.parse('{ \"abc\": { \"x\": 100, \"y\": 110 }, \"def\": [ 10, 20 ,30 ], \"ghi\": \"zazazaza\" }').def;\n        `, \"10,20,30\")\n\n\t\ttest(`raise:\n            JSON.parse(\"12\\t\\r\\n 34\");\n        `, \"SyntaxError: invalid character '3' after top-level value\")\n\n\t\ttest(`\n            JSON.parse(\"[1, 2, 3]\", function() { return undefined });\n        `, \"undefined\")\n\n\t\ttest(`raise:\n            JSON.parse(\"\");\n        `, \"SyntaxError: unexpected end of JSON input\")\n\n\t\ttest(`raise:\n            JSON.parse(\"[1, 2, 3\");\n        `, \"SyntaxError: unexpected end of JSON input\")\n\n\t\ttest(`raise:\n            JSON.parse(\"[1, 2, ; abc=10\");\n        `, \"SyntaxError: invalid character ';' looking for beginning of value\")\n\n\t\ttest(`raise:\n            JSON.parse(\"[1, 2, function(){}]\");\n        `, \"SyntaxError: invalid character 'u' in literal false (expecting 'a')\")\n\t})\n}\n\nfunc TestJSON_stringify(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\tdefer mockUTC()()\n\n\t\ttest(`\n            JSON.stringify(function(){});\n        `, \"undefined\")\n\n\t\ttest(`\n            JSON.stringify(new Boolean(false));\n        `, \"false\")\n\n\t\ttest(`\n            JSON.stringify({a1: {b1: [1,2,3,4], b2: {c1: 1, c2: 2}}, a2: 'a2'}, null, -5);\n        `, `{\"a1\":{\"b1\":[1,2,3,4],\"b2\":{\"c1\":1,\"c2\":2}},\"a2\":\"a2\"}`)\n\n\t\ttest(`\n            JSON.stringify(undefined);\n        `, \"undefined\")\n\n\t\ttest(`\n            JSON.stringify(1);\n        `, \"1\")\n\n\t\ttest(`\n            JSON.stringify(\"abc def\");\n        `, \"\\\"abc def\\\"\")\n\n\t\ttest(`\n            JSON.stringify(3.14159);\n        `, \"3.14159\")\n\n\t\ttest(`\n            JSON.stringify([]);\n        `, \"[]\")\n\n\t\ttest(`\n            JSON.stringify([1, 2, 3]);\n        `, \"[1,2,3]\")\n\n\t\ttest(`\n            JSON.stringify([true, false, null]);\n        `, \"[true,false,null]\")\n\n\t\ttest(`\n            JSON.stringify({\n                abc: { x: 100, y: 110 },\n                def: [ 10, 20, 30 ],\n                ghi: \"zazazaza\"\n            });\n        `, `{\"abc\":{\"x\":100,\"y\":110},\"def\":[10,20,30],\"ghi\":\"zazazaza\"}`)\n\n\t\ttest(`\n            JSON.stringify([\n                'e',\n                {pluribus: 'unum'}\n            ], null, '\\t');\n        `, \"[\\n\\t\\\"e\\\",\\n\\t{\\n\\t\\t\\\"pluribus\\\": \\\"unum\\\"\\n\\t}\\n]\")\n\n\t\ttest(`\n            JSON.stringify(new Date(0));\n        `, `\"1970-01-01T00:00:00.000Z\"`)\n\n\t\ttest(`\n            JSON.stringify([ new Date(0) ], function(key, value){\n                return this[key] instanceof Date ? 'Date(' + this[key] + ')' : value\n            });\n        `, `[\"Date(Thu, 01 Jan 1970 00:00:00 UTC)\"]`)\n\n\t\ttest(`\n            JSON.stringify({\n                abc: 1,\n                def: 2,\n                ghi: 3\n            }, ['abc','def']);\n        `, `{\"abc\":1,\"def\":2}`)\n\n\t\ttest(`raise:\n            var abc = {\n                def: null\n            };\n            abc.def = abc;\n            JSON.stringify(abc)\n        `, \"TypeError: Converting circular structure to JSON\")\n\n\t\ttest(`raise:\n            var abc= [ null ];\n            abc[0] = abc;\n            JSON.stringify(abc);\n        `, \"TypeError: Converting circular structure to JSON\")\n\n\t\ttest(`raise:\n            var abc = {\n                def: {}\n            };\n            abc.def.ghi = abc;\n            JSON.stringify(abc)\n        `, \"TypeError: Converting circular structure to JSON\")\n\n\t\ttest(`\n            var ghi = { \"pi\": 3.14159 };\n            var abc = {\n                def: {}\n            };\n            abc.ghi = ghi;\n            abc.def.ghi = ghi;\n            JSON.stringify(abc);\n        `, `{\"def\":{\"ghi\":{\"pi\":3.14159}},\"ghi\":{\"pi\":3.14159}}`)\n\t})\n}\n"
  },
  {
    "path": "locale.go",
    "content": "package otto\n\nimport \"golang.org/x/text/language\"\n\nvar defaultLanguage = language.MustParse(\"en-US\")\n"
  },
  {
    "path": "math_test.go",
    "content": "package otto\n\nimport (\n\t\"math\"\n\t\"testing\"\n)\n\nvar (\n\tnaN      = math.NaN()\n\tinfinity = math.Inf(1)\n)\n\nfunc TestMath_toString(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`Math.toString()`, \"[object Math]\")\n\t})\n}\n\nfunc TestMath_abs(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`Math.abs(NaN)`, naN)\n\t\ttest(`Math.abs(2)`, 2)\n\t\ttest(`Math.abs(-2)`, 2)\n\t\ttest(`Math.abs(-Infinity)`, infinity)\n\n\t\ttest(`Math.acos(0.5)`, 1.0471975511965976)\n\n\t\ttest(`Math.abs('-1')`, 1)\n\t\ttest(`Math.abs(-2)`, 2)\n\t\ttest(`Math.abs(null)`, 0)\n\t\ttest(`Math.abs(\"string\")`, naN)\n\t\ttest(`Math.abs()`, naN)\n\t})\n}\n\nfunc TestMath_acos(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`Math.acos(NaN)`, naN)\n\t\ttest(`Math.acos(2)`, naN)\n\t\ttest(`Math.acos(-2)`, naN)\n\t\ttest(`1/Math.acos(1)`, infinity)\n\n\t\ttest(`Math.acos(0.5)`, 1.0471975511965976)\n\t})\n}\n\nfunc TestMath_acosh(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`Math.acosh(-1)`, naN)\n\t\ttest(`Math.acosh(0)`, naN)\n\t\ttest(`Math.acosh(0.999999999999)`, naN)\n\t\ttest(`1/Math.acosh(1)`, infinity)\n\t\ttest(`Math.acosh(Infinity)`, infinity)\n\t\ttest(`Math.acosh(2)`, 1.3169578969248166)\n\t\ttest(`Math.acosh(2.5)`, 1.566799236972411)\n\t})\n}\n\nfunc TestMath_asin(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`Math.asin(NaN)`, naN)\n\t\ttest(`Math.asin(2)`, naN)\n\t\ttest(`Math.asin(-2)`, naN)\n\t\ttest(`1/Math.asin(0)`, infinity)\n\t\ttest(`1/Math.asin(-0)`, -infinity)\n\n\t\ttest(`Math.asin(0.5)`, 0.5235987755982989)\n\t})\n}\n\nfunc TestMath_asinh(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`Math.asinh(-1)`, -0.881373587019543)\n\t\ttest(`Math.asinh(1)`, 0.881373587019543)\n\t\ttest(`Math.asinh(-0)`, -0)\n\t\ttest(`Math.asinh(0)`, 0)\n\t\ttest(`Math.asinh(-Infinity)`, -infinity)\n\t\ttest(`Math.asinh(Infinity)`, infinity)\n\t\ttest(`Math.asinh(2)`, 1.4436354751788103)\n\t})\n}\n\nfunc TestMath_atan(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`Math.atan(NaN)`, naN)\n\t\ttest(`1/Math.atan(0)`, infinity)\n\t\ttest(`1/Math.atan(-0)`, -infinity)\n\t\ttest(`Math.atan(Infinity)`, 1.5707963267948966)\n\t\ttest(`Math.atan(-Infinity)`, -1.5707963267948966)\n\n\t\t// freebsd/386 1.03 => 0.4636476090008061\n\t\t// darwin 1.03 => 0.46364760900080604\n\t\ttest(`Math.atan(0.5).toPrecision(10)`, \"0.463647609\")\n\t})\n}\n\nfunc TestMath_atan2(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`Math.atan2()`, naN)\n\t\ttest(`Math.atan2(NaN)`, naN)\n\t\ttest(`Math.atan2(0, NaN)`, naN)\n\n\t\ttest(`Math.atan2(1, 0)`, 1.5707963267948966)\n\t\ttest(`Math.atan2(1, -0)`, 1.5707963267948966)\n\n\t\ttest(`1/Math.atan2(0, 1)`, infinity)\n\t\ttest(`1/Math.atan2(0, 0)`, infinity)\n\t\ttest(`Math.atan2(0, -0)`, 3.141592653589793)\n\t\ttest(`Math.atan2(0, -1)`, 3.141592653589793)\n\n\t\ttest(`1/Math.atan2(-0, 1)`, -infinity)\n\t\ttest(`1/Math.atan2(-0, 0)`, -infinity)\n\t\ttest(`Math.atan2(-0, -0)`, -3.141592653589793)\n\t\ttest(`Math.atan2(-0, -1)`, -3.141592653589793)\n\n\t\ttest(`Math.atan2(-1, 0)`, -1.5707963267948966)\n\t\ttest(`Math.atan2(-1, -0)`, -1.5707963267948966)\n\n\t\ttest(`1/Math.atan2(1, Infinity)`, infinity)\n\t\ttest(`Math.atan2(1, -Infinity)`, 3.141592653589793)\n\t\ttest(`1/Math.atan2(-1, Infinity)`, -infinity)\n\t\ttest(`Math.atan2(-1, -Infinity)`, -3.141592653589793)\n\n\t\ttest(`Math.atan2(Infinity, 1)`, 1.5707963267948966)\n\t\ttest(`Math.atan2(-Infinity, 1)`, -1.5707963267948966)\n\n\t\ttest(`Math.atan2(Infinity, Infinity)`, 0.7853981633974483)\n\t\ttest(`Math.atan2(Infinity, -Infinity)`, 2.356194490192345)\n\t\ttest(`Math.atan2(-Infinity, Infinity)`, -0.7853981633974483)\n\t\ttest(`Math.atan2(-Infinity, -Infinity)`, -2.356194490192345)\n\t})\n}\n\nfunc TestMath_atanh(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`Math.atanh(-2)`, naN)\n\t\ttest(`Math.atanh(2)`, naN)\n\t\ttest(`Math.atanh(-1)`, -infinity)\n\t\ttest(`Math.atanh(1)`, infinity)\n\t\ttest(`Math.atanh(0)`, 0)\n\t\ttest(`Math.atanh(0.5)`, 0.5493061443340548)\n\t})\n}\n\nfunc TestMath_cbrt(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`Math.cbrt(NaN)`, naN)\n\t\ttest(`Math.cbrt(-1)`, -1)\n\t\ttest(`Math.cbrt(1)`, 1)\n\t\ttest(`Math.cbrt(-0)`, -0)\n\t\ttest(`Math.cbrt(0)`, 0)\n\t\ttest(`Math.cbrt(-Infinity)`, -infinity)\n\t\ttest(`Math.cbrt(Infinity)`, infinity)\n\t\ttest(`Math.cbrt(null)`, 0)\n\t\ttest(`Math.cbrt(2)`, 1.2599210498948732)\n\t})\n}\n\nfunc TestMath_ceil(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`Math.ceil(NaN)`, naN)\n\t\ttest(`Math.ceil(+0)`, 0)\n\t\ttest(`1/Math.ceil(-0)`, -infinity)\n\t\ttest(`Math.ceil(Infinity)`, infinity)\n\t\ttest(`Math.ceil(-Infinity)`, -infinity)\n\t\ttest(`1/Math.ceil(-0.5)`, -infinity)\n\n\t\ttest(`Math.ceil(-11)`, -11)\n\t\ttest(`Math.ceil(-0.5)`, 0)\n\t\ttest(`Math.ceil(1.5)`, 2)\n\t})\n}\n\nfunc TestMath_cos(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`Math.cos(NaN)`, naN)\n\t\ttest(`Math.cos(+0)`, 1)\n\t\ttest(`Math.cos(-0)`, 1)\n\t\ttest(`Math.cos(Infinity)`, naN)\n\t\ttest(`Math.cos(-Infinity)`, naN)\n\n\t\ttest(`Math.cos(0.5)`, 0.8775825618903728)\n\t})\n}\n\nfunc TestMath_cosh(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`Math.cosh(0)`, 1)\n\t\ttest(`Math.cosh(1)`, 1.5430806348152437)\n\t\ttest(`Math.cosh(-1)`, 1.5430806348152437)\n\t})\n}\n\nfunc TestMath_exp(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`Math.exp(NaN)`, naN)\n\t\ttest(`Math.exp(+0)`, 1)\n\t\ttest(`Math.exp(-0)`, 1)\n\t\ttest(`Math.exp(Infinity)`, infinity)\n\t\ttest(`Math.exp(-Infinity)`, 0)\n\t})\n}\n\nfunc TestMath_expm1(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`Math.expm1(0)`, 0)\n\t\ttest(`Math.expm1(1)`, 1.718281828459045)\n\t\ttest(`Math.expm1(-1)`, -0.6321205588285577)\n\t\ttest(`Math.expm1(2)`, 6.38905609893065)\n\t\ttest(`Math.expm1(\"foo\")`, naN)\n\t})\n}\n\nfunc TestMath_floor(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`Math.floor(NaN)`, naN)\n\t\ttest(`Math.floor(+0)`, 0)\n\t\ttest(`1/Math.floor(-0)`, -infinity)\n\t\ttest(`Math.floor(Infinity)`, infinity)\n\t\ttest(`Math.floor(-Infinity)`, -infinity)\n\n\t\ttest(`Math.floor(-11)`, -11)\n\t\ttest(`Math.floor(-0.5)`, -1)\n\t\ttest(`Math.floor(1.5)`, 1)\n\t})\n}\n\nfunc TestMath_log(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`Math.log(NaN)`, naN)\n\t\ttest(`Math.log(-1)`, naN)\n\t\ttest(`Math.log(+0)`, -infinity)\n\t\ttest(`Math.log(-0)`, -infinity)\n\t\ttest(`1/Math.log(1)`, infinity)\n\t\ttest(`Math.log(Infinity)`, infinity)\n\n\t\ttest(`Math.log(0.5)`, -0.6931471805599453)\n\t})\n}\n\nfunc TestMath_log10(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`Math.log10(100000)`, 5)\n\t\ttest(`Math.log10(-2)`, naN)\n\t\ttest(`Math.log10(2)`, 0.3010299956639812)\n\t\ttest(`Math.log10(1)`, 0)\n\t\ttest(`Math.log10(-0)`, -infinity)\n\t\ttest(`Math.log10(0)`, -infinity)\n\t\ttest(`Math.log10(Infinity)`, infinity)\n\t})\n}\n\nfunc TestMath_log1p(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`Math.log1p(-2)`, naN)\n\t\ttest(`Math.log1p(-1)`, -infinity)\n\t\ttest(`Math.log1p(1)`, 0.6931471805599453)\n\t\ttest(`Math.log1p(-0)`, -0)\n\t\ttest(`Math.log1p(0)`, 0)\n\t\ttest(`Math.log1p(Infinity)`, infinity)\n\t})\n}\n\nfunc TestMath_log2(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`Math.log2(-2)`, naN)\n\t\ttest(`Math.log2(-0)`, -infinity)\n\t\ttest(`Math.log2(0)`, -infinity)\n\t\ttest(`Math.log2(1)`, 0)\n\t\ttest(`Math.log2(2)`, 1)\n\t\ttest(`Math.log2(5)`, 2.321928094887362)\n\t\ttest(`Math.log2(1024)`, 10)\n\t\ttest(`Math.log2(Infinity)`, infinity)\n\t})\n}\n\nfunc TestMath_max(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`Math.max(-11, -1, 0, 1, 2, 3, 11)`, 11)\n\t})\n}\n\nfunc TestMath_min(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`Math.min(-11, -1, 0, 1, 2, 3, 11)`, -11)\n\t})\n}\n\nfunc TestMath_pow(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`Math.pow(0, NaN)`, naN)\n\t\ttest(`Math.pow(0, 0)`, 1)\n\t\ttest(`Math.pow(NaN, 0)`, 1)\n\t\ttest(`Math.pow(0, -0)`, 1)\n\t\ttest(`Math.pow(NaN, -0)`, 1)\n\t\ttest(`Math.pow(NaN, 1)`, naN)\n\t\ttest(`Math.pow(2, Infinity)`, infinity)\n\t\ttest(`1/Math.pow(2, -Infinity)`, infinity)\n\t\ttest(`Math.pow(1, Infinity)`, naN)\n\t\ttest(`Math.pow(1, -Infinity)`, naN)\n\t\ttest(`1/Math.pow(0.1, Infinity)`, infinity)\n\t\ttest(`Math.pow(0.1, -Infinity)`, infinity)\n\t\ttest(`Math.pow(Infinity, 1)`, infinity)\n\t\ttest(`1/Math.pow(Infinity, -1)`, infinity)\n\t\ttest(`Math.pow(-Infinity, 1)`, -infinity)\n\t\ttest(`Math.pow(-Infinity, 2)`, infinity)\n\t\ttest(`1/Math.pow(-Infinity, -1)`, -infinity)\n\t\ttest(`1/Math.pow(-Infinity, -2)`, infinity)\n\t\ttest(`1/Math.pow(0, 1)`, infinity)\n\t\ttest(`Math.pow(0, -1)`, infinity)\n\t\ttest(`1/Math.pow(-0, 1)`, -infinity)\n\t\ttest(`1/Math.pow(-0, 2)`, infinity)\n\t\ttest(`Math.pow(-0, -1)`, -infinity)\n\t\ttest(`Math.pow(-0, -2)`, infinity)\n\t\ttest(`Math.pow(-1, 0.1)`, naN)\n\n\t\ttest(`\n            [ Math.pow(-1, +Infinity), Math.pow(1, Infinity) ];\n        `, \"NaN,NaN\")\n\t})\n}\n\nfunc TestMath_round(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`Math.round(NaN)`, naN)\n\t\ttest(`1/Math.round(0)`, infinity)\n\t\ttest(`1/Math.round(-0)`, -infinity)\n\t\ttest(`Math.round(Infinity)`, infinity)\n\t\ttest(`Math.round(-Infinity)`, -infinity)\n\t\ttest(`1/Math.round(0.1)`, infinity)\n\t\ttest(`1/Math.round(-0.1)`, -infinity)\n\n\t\ttest(`Math.round(3.5)`, 4)\n\t\ttest(`Math.round(-3.5)`, -3)\n\t})\n}\n\nfunc TestMath_sin(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`Math.sin(NaN)`, naN)\n\t\ttest(`1/Math.sin(+0)`, infinity)\n\t\ttest(`1/Math.sin(-0)`, -infinity)\n\t\ttest(`Math.sin(Infinity)`, naN)\n\t\ttest(`Math.sin(-Infinity)`, naN)\n\n\t\ttest(`Math.sin(0.5)`, 0.479425538604203)\n\t})\n}\n\nfunc TestMath_sinh(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`Math.sinh(-Infinity)`, -infinity)\n\t\ttest(`Math.sinh(Infinity)`, infinity)\n\t\ttest(`Math.sinh(-0)`, -0)\n\t\ttest(`Math.sinh(0)`, 0)\n\t\ttest(`Math.sinh(-1)`, -1.1752011936438014)\n\t\ttest(`Math.sinh(1)`, 1.1752011936438014)\n\t\ttest(`Math.sinh(2)`, 3.626860407847019)\n\t})\n}\n\nfunc TestMath_sqrt(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`Math.sqrt(NaN)`, naN)\n\t\ttest(`Math.sqrt(-1)`, naN)\n\t\ttest(`1/Math.sqrt(+0)`, infinity)\n\t\ttest(`1/Math.sqrt(-0)`, -infinity)\n\t\ttest(`Math.sqrt(Infinity)`, infinity)\n\n\t\ttest(`Math.sqrt(2)`, 1.4142135623730951)\n\t})\n}\n\nfunc TestMath_tan(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`Math.tan(NaN)`, naN)\n\t\ttest(`1/Math.tan(+0)`, infinity)\n\t\ttest(`1/Math.tan(-0)`, -infinity)\n\t\ttest(`Math.tan(Infinity)`, naN)\n\t\ttest(`Math.tan(-Infinity)`, naN)\n\n\t\ttest(`Math.tan(0.5)`, 0.5463024898437905)\n\t})\n}\n\nfunc TestMath_tanh(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`Math.tanh(Infinity)`, 1)\n\t\ttest(`Math.tanh(-Infinity)`, -1)\n\t\ttest(`Math.tanh(-1)`, -0.7615941559557649)\n\t\ttest(`Math.tanh(1)`, 0.7615941559557649)\n\t\ttest(`Math.tanh(-0)`, -0)\n\t\ttest(`Math.tanh(0)`, 0)\n\t})\n}\n\nfunc TestMath_trunc(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`Math.trunc(-Infinity)`, -infinity)\n\t\ttest(`Math.trunc(Infinity)`, infinity)\n\t\ttest(`Math.trunc(-0.123)`, -0)\n\t\ttest(`Math.trunc(0.123)`, 0)\n\t\ttest(`Math.trunc(-0)`, -0)\n\t\ttest(`Math.trunc(0)`, 0)\n\t\ttest(`Math.trunc(\"-1.123\")`, -1)\n\t\ttest(`Math.trunc(13.37)`, 13)\n\t\ttest(`Math.trunc(42.84)`, 42)\n\t})\n}\n"
  },
  {
    "path": "native_stack_test.go",
    "content": "package otto\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestNativeStackFrames(t *testing.T) {\n\ttt(t, func() {\n\t\tvm := New()\n\n\t\ts, err := vm.Compile(\"input.js\", `\n\t\t\tfunction A() { ext1(); }\n\t\t\tfunction B() { ext2(); }\n\t\t\tA();\n\t\t`)\n\t\trequire.NoError(t, err)\n\n\t\terr = vm.Set(\"ext1\", func(c FunctionCall) Value {\n\t\t\tif _, err = c.Otto.Eval(\"B()\"); err != nil {\n\t\t\t\tpanic(err)\n\t\t\t}\n\n\t\t\treturn UndefinedValue()\n\t\t})\n\t\trequire.NoError(t, err)\n\n\t\terr = vm.Set(\"ext2\", func(c FunctionCall) Value {\n\t\t\t{\n\t\t\t\t// no limit, include innermost native frames\n\t\t\t\tctx := c.Otto.ContextSkip(-1, false)\n\n\t\t\t\tis(ctx.Stacktrace, []string{\n\t\t\t\t\t\"github.com/robertkrimen/otto.TestNativeStackFrames.func1.2 (native_stack_test.go:29)\",\n\t\t\t\t\t\"B (input.js:3:19)\",\n\t\t\t\t\t\"github.com/robertkrimen/otto.TestNativeStackFrames.func1.1 (native_stack_test.go:20)\",\n\t\t\t\t\t\"A (input.js:2:19)\", \"input.js:4:4\",\n\t\t\t\t})\n\n\t\t\t\tis(ctx.Callee, \"github.com/robertkrimen/otto.TestNativeStackFrames.func1.2\")\n\t\t\t\tis(ctx.Filename, \"native_stack_test.go\")\n\t\t\t\tis(ctx.Line, 29)\n\t\t\t\tis(ctx.Column, 0)\n\t\t\t}\n\n\t\t\t{\n\t\t\t\t// no limit, skip innermost native frames\n\t\t\t\tctx := c.Otto.ContextSkip(-1, true)\n\n\t\t\t\tis(ctx.Stacktrace, []string{\n\t\t\t\t\t\"B (input.js:3:19)\",\n\t\t\t\t\t\"github.com/robertkrimen/otto.TestNativeStackFrames.func1.1 (native_stack_test.go:20)\",\n\t\t\t\t\t\"A (input.js:2:19)\", \"input.js:4:4\",\n\t\t\t\t})\n\n\t\t\t\tis(ctx.Callee, \"B\")\n\t\t\t\tis(ctx.Filename, \"input.js\")\n\t\t\t\tis(ctx.Line, 3)\n\t\t\t\tis(ctx.Column, 19)\n\t\t\t}\n\n\t\t\tif _, err = c.Otto.Eval(\"ext3()\"); err != nil {\n\t\t\t\tpanic(err)\n\t\t\t}\n\n\t\t\treturn UndefinedValue()\n\t\t})\n\t\trequire.NoError(t, err)\n\n\t\terr = vm.Set(\"ext3\", func(c FunctionCall) Value {\n\t\t\t{\n\t\t\t\t// no limit, include innermost native frames\n\t\t\t\tctx := c.Otto.ContextSkip(-1, false)\n\n\t\t\t\tis(ctx.Stacktrace, []string{\n\t\t\t\t\t\"github.com/robertkrimen/otto.TestNativeStackFrames.func1.3 (native_stack_test.go:71)\",\n\t\t\t\t\t\"github.com/robertkrimen/otto.TestNativeStackFrames.func1.2 (native_stack_test.go:29)\",\n\t\t\t\t\t\"B (input.js:3:19)\",\n\t\t\t\t\t\"github.com/robertkrimen/otto.TestNativeStackFrames.func1.1 (native_stack_test.go:20)\",\n\t\t\t\t\t\"A (input.js:2:19)\", \"input.js:4:4\",\n\t\t\t\t})\n\n\t\t\t\tis(ctx.Callee, \"github.com/robertkrimen/otto.TestNativeStackFrames.func1.3\")\n\t\t\t\tis(ctx.Filename, \"native_stack_test.go\")\n\t\t\t\tis(ctx.Line, 71)\n\t\t\t\tis(ctx.Column, 0)\n\t\t\t}\n\n\t\t\t{\n\t\t\t\t// no limit, skip innermost native frames\n\t\t\t\tctx := c.Otto.ContextSkip(-1, true)\n\n\t\t\t\tis(ctx.Stacktrace, []string{\n\t\t\t\t\t\"B (input.js:3:19)\",\n\t\t\t\t\t\"github.com/robertkrimen/otto.TestNativeStackFrames.func1.1 (native_stack_test.go:20)\",\n\t\t\t\t\t\"A (input.js:2:19)\", \"input.js:4:4\",\n\t\t\t\t})\n\n\t\t\t\tis(ctx.Callee, \"B\")\n\t\t\t\tis(ctx.Filename, \"input.js\")\n\t\t\t\tis(ctx.Line, 3)\n\t\t\t\tis(ctx.Column, 19)\n\t\t\t}\n\n\t\t\treturn UndefinedValue()\n\t\t})\n\t\trequire.NoError(t, err)\n\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(t, err)\n\t})\n}\n"
  },
  {
    "path": "number_test.go",
    "content": "package otto\n\nimport (\n\t\"testing\"\n)\n\nfunc TestNumber(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            var abc = Object.getOwnPropertyDescriptor(Number, \"prototype\");\n            [   [ typeof Number.prototype ],\n                [ abc.writable, abc.enumerable, abc.configurable ] ];\n        `, \"object,false,false,false\")\n\t})\n}\n\nfunc TestNumber_toString(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            new Number(451).toString();\n        `, \"451\")\n\n\t\ttest(`\n            new Number(451).toString(10);\n        `, \"451\")\n\n\t\ttest(`\n            new Number(451).toString(8);\n        `, \"703\")\n\n\t\ttest(`raise:\n            new Number(451).toString(1);\n        `, \"RangeError: toString() radix must be between 2 and 36\")\n\n\t\ttest(`raise:\n            new Number(451).toString(Infinity);\n        `, \"RangeError: toString() radix must be between 2 and 36\")\n\n\t\ttest(`\n            new Number(NaN).toString()\n        `, \"NaN\")\n\n\t\ttest(`\n            new Number(Infinity).toString()\n        `, \"Infinity\")\n\n\t\ttest(`\n            new Number(Infinity).toString(16)\n        `, \"Infinity\")\n\n\t\ttest(`\n            [\n                Number.prototype.toString(undefined),\n                new Number().toString(undefined),\n                new Number(0).toString(undefined),\n                new Number(-1).toString(undefined),\n                new Number(1).toString(undefined),\n                new Number(Number.NaN).toString(undefined),\n                new Number(Number.POSITIVE_INFINITY).toString(undefined),\n                new Number(Number.NEGATIVE_INFINITY).toString(undefined)\n            ]\n        `, \"0,0,0,-1,1,NaN,Infinity,-Infinity\")\n\t})\n}\n\nfunc TestNumber_toFixed(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`new Number(451).toFixed(2)`, \"451.00\")\n\t\ttest(`12345.6789.toFixed()`, \"12346\")\n\t\ttest(`12345.6789.toFixed(1)`, \"12345.7\")\n\t\ttest(`12345.6789.toFixed(6)`, \"12345.678900\")\n\t\ttest(`(1.23e-20).toFixed(2)`, \"0.00\")\n\t\ttest(`2.34.toFixed(1)`, \"2.3\") // FIXME Wtf? \"2.3\"\n\t\ttest(`-2.34.toFixed(1)`, -2.3) // FIXME Wtf? -2.3\n\t\ttest(`(-2.34).toFixed(1)`, \"-2.3\")\n\n\t\ttest(`raise:\n            new Number(\"a\").toFixed(Number.POSITIVE_INFINITY);\n        `, \"RangeError: toFixed() precision must be between 0 and 20\")\n\n\t\ttest(`\n            [\n                new Number(1e21).toFixed(),\n                new Number(1e21).toFixed(0),\n                new Number(1e21).toFixed(1),\n                new Number(1e21).toFixed(1.1),\n                new Number(1e21).toFixed(0.9),\n                new Number(1e21).toFixed(\"1\"),\n                new Number(1e21).toFixed(\"1.1\"),\n                new Number(1e21).toFixed(\"0.9\"),\n                new Number(1e21).toFixed(Number.NaN),\n                new Number(1e21).toFixed(\"some string\")\n            ];\n    `, \"1e+21,1e+21,1e+21,1e+21,1e+21,1e+21,1e+21,1e+21,1e+21,1e+21\")\n\n\t\ttest(`raise:\n            new Number(1e21).toFixed(Number.POSITIVE_INFINITY);\n        `, \"RangeError: toFixed() precision must be between 0 and 20\")\n\t})\n}\n\nfunc TestNumber_toExponential(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`new Number(451).toExponential(2)`, \"4.51e+02\")\n\t\ttest(`77.1234.toExponential()`, \"7.71234e+01\")\n\t\ttest(`77.1234.toExponential(4)`, \"7.7123e+01\")\n\t\ttest(`77.1234.toExponential(2)`, \"7.71e+01\")\n\t\ttest(`77 .toExponential()`, \"7.7e+01\")\n\t})\n}\n\nfunc TestNumber_toPrecision(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`new Number(451).toPrecision()`, \"451\")\n\t\ttest(`new Number(451).toPrecision(1)`, \"5e+02\")\n\t\ttest(`5.123456.toPrecision()`, \"5.123456\")\n\t\ttest(`5.123456.toPrecision(5)`, \"5.1235\")\n\t\ttest(`5.123456.toPrecision(2)`, \"5.1\")\n\t\ttest(`5.123456.toPrecision(1)`, \"5\")\n\t})\n}\n\nfunc TestNumber_toLocaleString(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            [\n                new Number(4510).toLocaleString(),\n                new Number(4510).toLocaleString('en-US'),\n\t\t\t\tnew Number(4510).toLocaleString('nl-NL')\n            ];\n        `, \"4,510,4,510,4.510\")\n\t})\n}\n\nfunc TestValue_number(t *testing.T) {\n\ttt(t, func() {\n\t\tnm := toValue(0.0).number()\n\t\tis(nm.kind, numberInteger)\n\n\t\tnm = toValue(3.14159).number()\n\t\tis(nm.kind, numberFloat)\n\t})\n}\n\nfunc Test_NaN(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            [ NaN === NaN, NaN == NaN ];\n        `, \"false,false\")\n\t})\n}\n"
  },
  {
    "path": "object.go",
    "content": "package otto\n\ntype object struct {\n\tvalue         interface{}\n\truntime       *runtime\n\tobjectClass   *objectClass\n\tprototype     *object\n\tproperty      map[string]property\n\tclass         string\n\tpropertyOrder []string\n\textensible    bool\n}\n\nfunc newObject(rt *runtime, class string) *object {\n\to := &object{\n\t\truntime:     rt,\n\t\tclass:       class,\n\t\tobjectClass: classObject,\n\t\tproperty:    make(map[string]property),\n\t\textensible:  true,\n\t}\n\treturn o\n}\n\n// 8.12\n\n// 8.12.1.\nfunc (o *object) getOwnProperty(name string) *property {\n\treturn o.objectClass.getOwnProperty(o, name)\n}\n\n// 8.12.2.\nfunc (o *object) getProperty(name string) *property {\n\treturn o.objectClass.getProperty(o, name)\n}\n\n// 8.12.3.\nfunc (o *object) get(name string) Value {\n\treturn o.objectClass.get(o, name)\n}\n\n// 8.12.4.\nfunc (o *object) canPut(name string) bool {\n\treturn o.objectClass.canPut(o, name)\n}\n\n// 8.12.5.\nfunc (o *object) put(name string, value Value, throw bool) {\n\to.objectClass.put(o, name, value, throw)\n}\n\n// 8.12.6.\nfunc (o *object) hasProperty(name string) bool {\n\treturn o.objectClass.hasProperty(o, name)\n}\n\nfunc (o *object) hasOwnProperty(name string) bool {\n\treturn o.objectClass.hasOwnProperty(o, name)\n}\n\ntype defaultValueHint int\n\nconst (\n\tdefaultValueNoHint defaultValueHint = iota\n\tdefaultValueHintString\n\tdefaultValueHintNumber\n)\n\n// 8.12.8.\nfunc (o *object) DefaultValue(hint defaultValueHint) Value {\n\tif hint == defaultValueNoHint {\n\t\tif o.class == classDateName {\n\t\t\t// Date exception\n\t\t\thint = defaultValueHintString\n\t\t} else {\n\t\t\thint = defaultValueHintNumber\n\t\t}\n\t}\n\tmethodSequence := []string{\"valueOf\", \"toString\"}\n\tif hint == defaultValueHintString {\n\t\tmethodSequence = []string{\"toString\", \"valueOf\"}\n\t}\n\tfor _, methodName := range methodSequence {\n\t\tmethod := o.get(methodName)\n\t\t// FIXME This is redundant...\n\t\tif method.isCallable() {\n\t\t\tresult := method.object().call(objectValue(o), nil, false, nativeFrame)\n\t\t\tif result.IsPrimitive() {\n\t\t\t\treturn result\n\t\t\t}\n\t\t}\n\t}\n\n\tpanic(o.runtime.panicTypeError(\"Object.DefaultValue unknown\"))\n}\n\nfunc (o *object) String() string {\n\treturn o.DefaultValue(defaultValueHintString).string()\n}\n\nfunc (o *object) defineProperty(name string, value Value, mode propertyMode, throw bool) bool { //nolint:unparam\n\treturn o.defineOwnProperty(name, property{value, mode}, throw)\n}\n\n// 8.12.9.\nfunc (o *object) defineOwnProperty(name string, descriptor property, throw bool) bool {\n\treturn o.objectClass.defineOwnProperty(o, name, descriptor, throw)\n}\n\nfunc (o *object) delete(name string, throw bool) bool {\n\treturn o.objectClass.delete(o, name, throw)\n}\n\nfunc (o *object) enumerate(all bool, each func(string) bool) {\n\to.objectClass.enumerate(o, all, each)\n}\n\nfunc (o *object) readProperty(name string) (property, bool) {\n\tprop, exists := o.property[name]\n\treturn prop, exists\n}\n\nfunc (o *object) writeProperty(name string, value interface{}, mode propertyMode) {\n\tif value == nil {\n\t\tvalue = Value{}\n\t}\n\tif _, exists := o.property[name]; !exists {\n\t\to.propertyOrder = append(o.propertyOrder, name)\n\t}\n\to.property[name] = property{value, mode}\n}\n\nfunc (o *object) deleteProperty(name string) {\n\tif _, exists := o.property[name]; !exists {\n\t\treturn\n\t}\n\n\tdelete(o.property, name)\n\tfor index, prop := range o.propertyOrder {\n\t\tif name == prop {\n\t\t\tif index == len(o.propertyOrder)-1 {\n\t\t\t\to.propertyOrder = o.propertyOrder[:index]\n\t\t\t} else {\n\t\t\t\to.propertyOrder = append(o.propertyOrder[:index], o.propertyOrder[index+1:]...)\n\t\t\t}\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "object_class.go",
    "content": "package otto\n\nimport (\n\t\"encoding/json\"\n)\n\ntype objectClass struct {\n\tgetOwnProperty    func(*object, string) *property\n\tgetProperty       func(*object, string) *property\n\tget               func(*object, string) Value\n\tcanPut            func(*object, string) bool\n\tput               func(*object, string, Value, bool)\n\thasProperty       func(*object, string) bool\n\thasOwnProperty    func(*object, string) bool\n\tdefineOwnProperty func(*object, string, property, bool) bool\n\tdelete            func(*object, string, bool) bool\n\tenumerate         func(*object, bool, func(string) bool)\n\tclone             func(*object, *object, *cloner) *object\n\tmarshalJSON       func(*object) json.Marshaler\n}\n\nfunc objectEnumerate(obj *object, all bool, each func(string) bool) {\n\tfor _, name := range obj.propertyOrder {\n\t\tif all || obj.property[name].enumerable() {\n\t\t\tif !each(name) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n}\n\nvar classObject,\n\tclassArray,\n\tclassString,\n\tclassArguments,\n\tclassGoStruct,\n\tclassGoMap,\n\tclassGoArray,\n\tclassGoSlice *objectClass\n\nfunc init() {\n\tclassObject = &objectClass{\n\t\tobjectGetOwnProperty,\n\t\tobjectGetProperty,\n\t\tobjectGet,\n\t\tobjectCanPut,\n\t\tobjectPut,\n\t\tobjectHasProperty,\n\t\tobjectHasOwnProperty,\n\t\tobjectDefineOwnProperty,\n\t\tobjectDelete,\n\t\tobjectEnumerate,\n\t\tobjectClone,\n\t\tnil,\n\t}\n\n\tclassArray = &objectClass{\n\t\tobjectGetOwnProperty,\n\t\tobjectGetProperty,\n\t\tobjectGet,\n\t\tobjectCanPut,\n\t\tobjectPut,\n\t\tobjectHasProperty,\n\t\tobjectHasOwnProperty,\n\t\tarrayDefineOwnProperty,\n\t\tobjectDelete,\n\t\tobjectEnumerate,\n\t\tobjectClone,\n\t\tnil,\n\t}\n\n\tclassString = &objectClass{\n\t\tstringGetOwnProperty,\n\t\tobjectGetProperty,\n\t\tobjectGet,\n\t\tobjectCanPut,\n\t\tobjectPut,\n\t\tobjectHasProperty,\n\t\tobjectHasOwnProperty,\n\t\tobjectDefineOwnProperty,\n\t\tobjectDelete,\n\t\tstringEnumerate,\n\t\tobjectClone,\n\t\tnil,\n\t}\n\n\tclassArguments = &objectClass{\n\t\targumentsGetOwnProperty,\n\t\tobjectGetProperty,\n\t\targumentsGet,\n\t\tobjectCanPut,\n\t\tobjectPut,\n\t\tobjectHasProperty,\n\t\tobjectHasOwnProperty,\n\t\targumentsDefineOwnProperty,\n\t\targumentsDelete,\n\t\tobjectEnumerate,\n\t\tobjectClone,\n\t\tnil,\n\t}\n\n\tclassGoStruct = &objectClass{\n\t\tgoStructGetOwnProperty,\n\t\tobjectGetProperty,\n\t\tobjectGet,\n\t\tgoStructCanPut,\n\t\tgoStructPut,\n\t\tobjectHasProperty,\n\t\tobjectHasOwnProperty,\n\t\tobjectDefineOwnProperty,\n\t\tobjectDelete,\n\t\tgoStructEnumerate,\n\t\tobjectClone,\n\t\tgoStructMarshalJSON,\n\t}\n\n\tclassGoMap = &objectClass{\n\t\tgoMapGetOwnProperty,\n\t\tobjectGetProperty,\n\t\tobjectGet,\n\t\tobjectCanPut,\n\t\tobjectPut,\n\t\tobjectHasProperty,\n\t\tobjectHasOwnProperty,\n\t\tgoMapDefineOwnProperty,\n\t\tgoMapDelete,\n\t\tgoMapEnumerate,\n\t\tobjectClone,\n\t\tnil,\n\t}\n\n\tclassGoArray = &objectClass{\n\t\tgoArrayGetOwnProperty,\n\t\tobjectGetProperty,\n\t\tobjectGet,\n\t\tobjectCanPut,\n\t\tobjectPut,\n\t\tobjectHasProperty,\n\t\tobjectHasOwnProperty,\n\t\tgoArrayDefineOwnProperty,\n\t\tgoArrayDelete,\n\t\tgoArrayEnumerate,\n\t\tobjectClone,\n\t\tnil,\n\t}\n\n\tclassGoSlice = &objectClass{\n\t\tgoSliceGetOwnProperty,\n\t\tobjectGetProperty,\n\t\tobjectGet,\n\t\tobjectCanPut,\n\t\tobjectPut,\n\t\tobjectHasProperty,\n\t\tobjectHasOwnProperty,\n\t\tgoSliceDefineOwnProperty,\n\t\tgoSliceDelete,\n\t\tgoSliceEnumerate,\n\t\tobjectClone,\n\t\tnil,\n\t}\n}\n\n// Allons-y\n\n// 8.12.1.\nfunc objectGetOwnProperty(obj *object, name string) *property {\n\t// Return a _copy_ of the prop\n\tprop, exists := obj.readProperty(name)\n\tif !exists {\n\t\treturn nil\n\t}\n\treturn &prop\n}\n\n// 8.12.2.\nfunc objectGetProperty(obj *object, name string) *property {\n\tprop := obj.getOwnProperty(name)\n\tif prop != nil {\n\t\treturn prop\n\t}\n\tif obj.prototype != nil {\n\t\treturn obj.prototype.getProperty(name)\n\t}\n\treturn nil\n}\n\n// 8.12.3.\nfunc objectGet(obj *object, name string) Value {\n\tif prop := obj.getProperty(name); prop != nil {\n\t\treturn prop.get(obj)\n\t}\n\treturn Value{}\n}\n\n// 8.12.4.\nfunc objectCanPut(obj *object, name string) bool {\n\tcanPut, _, _ := objectCanPutDetails(obj, name)\n\treturn canPut\n}\n\nfunc objectCanPutDetails(obj *object, name string) (canPut bool, prop *property, setter *object) { //nolint:nonamedreturns\n\tprop = obj.getOwnProperty(name)\n\tif prop != nil {\n\t\tswitch propertyValue := prop.value.(type) {\n\t\tcase Value:\n\t\t\treturn prop.writable(), prop, nil\n\t\tcase propertyGetSet:\n\t\t\tsetter = propertyValue[1]\n\t\t\treturn setter != nil, prop, setter\n\t\tdefault:\n\t\t\tpanic(obj.runtime.panicTypeError(\"unexpected type %T to Object.CanPutDetails\", prop.value))\n\t\t}\n\t}\n\n\tif obj.prototype == nil {\n\t\treturn obj.extensible, nil, nil\n\t}\n\n\tprop = obj.prototype.getProperty(name)\n\tif prop == nil {\n\t\treturn obj.extensible, nil, nil\n\t}\n\n\tswitch propertyValue := prop.value.(type) {\n\tcase Value:\n\t\tif !obj.extensible {\n\t\t\treturn false, nil, nil\n\t\t}\n\t\treturn prop.writable(), nil, nil\n\tcase propertyGetSet:\n\t\tsetter = propertyValue[1]\n\t\treturn setter != nil, prop, setter\n\tdefault:\n\t\tpanic(obj.runtime.panicTypeError(\"unexpected type %T to Object.CanPutDetails\", prop.value))\n\t}\n}\n\n// 8.12.5.\nfunc objectPut(obj *object, name string, value Value, throw bool) {\n\tif true {\n\t\t// Shortcut...\n\t\t//\n\t\t// So, right now, every class is using objectCanPut and every class\n\t\t// is using objectPut.\n\t\t//\n\t\t// If that were to no longer be the case, we would have to have\n\t\t// something to detect that here, so that we do not use an\n\t\t// incompatible canPut routine\n\t\tcanPut, prop, setter := objectCanPutDetails(obj, name)\n\t\tswitch {\n\t\tcase !canPut:\n\t\t\tobj.runtime.typeErrorResult(throw)\n\t\tcase setter != nil:\n\t\t\tsetter.call(toValue(obj), []Value{value}, false, nativeFrame)\n\t\tcase prop != nil:\n\t\t\tprop.value = value\n\t\t\tobj.defineOwnProperty(name, *prop, throw)\n\t\tdefault:\n\t\t\tobj.defineProperty(name, value, 0o111, throw)\n\t\t}\n\t\treturn\n\t}\n\n\t// The long way...\n\t//\n\t// Right now, code should never get here, see above\n\tif !obj.canPut(name) {\n\t\tobj.runtime.typeErrorResult(throw)\n\t\treturn\n\t}\n\n\tprop := obj.getOwnProperty(name)\n\tif prop == nil {\n\t\tprop = obj.getProperty(name)\n\t\tif prop != nil {\n\t\t\tif getSet, isAccessor := prop.value.(propertyGetSet); isAccessor {\n\t\t\t\tgetSet[1].call(toValue(obj), []Value{value}, false, nativeFrame)\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t\tobj.defineProperty(name, value, 0o111, throw)\n\t\treturn\n\t}\n\n\tswitch propertyValue := prop.value.(type) {\n\tcase Value:\n\t\tprop.value = value\n\t\tobj.defineOwnProperty(name, *prop, throw)\n\tcase propertyGetSet:\n\t\tif propertyValue[1] != nil {\n\t\t\tpropertyValue[1].call(toValue(obj), []Value{value}, false, nativeFrame)\n\t\t\treturn\n\t\t}\n\t\tif throw {\n\t\t\tpanic(obj.runtime.panicTypeError(\"Object.Put nil second parameter to propertyGetSet\"))\n\t\t}\n\tdefault:\n\t\tpanic(obj.runtime.panicTypeError(\"Object.Put unexpected type %T\", prop.value))\n\t}\n}\n\n// 8.12.6.\nfunc objectHasProperty(obj *object, name string) bool {\n\treturn obj.getProperty(name) != nil\n}\n\nfunc objectHasOwnProperty(obj *object, name string) bool {\n\treturn obj.getOwnProperty(name) != nil\n}\n\n// 8.12.9.\nfunc objectDefineOwnProperty(obj *object, name string, descriptor property, throw bool) bool {\n\treject := func(reason string) bool {\n\t\tif throw {\n\t\t\tpanic(obj.runtime.panicTypeError(\"Object.DefineOwnProperty: %s\", reason))\n\t\t}\n\t\treturn false\n\t}\n\n\tprop, exists := obj.readProperty(name)\n\tif !exists {\n\t\tif !obj.extensible {\n\t\t\treturn reject(\"not exists and not extensible\")\n\t\t}\n\t\tif newGetSet, isAccessor := descriptor.value.(propertyGetSet); isAccessor {\n\t\t\tif newGetSet[0] == &nilGetSetObject {\n\t\t\t\tnewGetSet[0] = nil\n\t\t\t}\n\t\t\tif newGetSet[1] == &nilGetSetObject {\n\t\t\t\tnewGetSet[1] = nil\n\t\t\t}\n\t\t\tdescriptor.value = newGetSet\n\t\t}\n\t\tobj.writeProperty(name, descriptor.value, descriptor.mode)\n\t\treturn true\n\t}\n\n\tif descriptor.isEmpty() {\n\t\treturn true\n\t}\n\n\t// TODO Per 8.12.9.6 - We should shortcut here (returning true) if\n\t// the current and new (define) properties are the same\n\n\tconfigurable := prop.configurable()\n\tif !configurable {\n\t\tif descriptor.configurable() {\n\t\t\treturn reject(\"property and descriptor not configurable\")\n\t\t}\n\t\t// Test that, if enumerable is set on the property descriptor, then it should\n\t\t// be the same as the existing property\n\t\tif descriptor.enumerateSet() && descriptor.enumerable() != prop.enumerable() {\n\t\t\treturn reject(\"property not configurable and enumerable miss match\")\n\t\t}\n\t}\n\n\tvalue, isDataDescriptor := prop.value.(Value)\n\tgetSet, _ := prop.value.(propertyGetSet)\n\tswitch {\n\tcase descriptor.isGenericDescriptor():\n\t\t// GenericDescriptor\n\tcase isDataDescriptor != descriptor.isDataDescriptor():\n\t\t// DataDescriptor <=> AccessorDescriptor\n\t\tif !configurable {\n\t\t\treturn reject(\"property descriptor not configurable\")\n\t\t}\n\tcase isDataDescriptor && descriptor.isDataDescriptor():\n\t\t// DataDescriptor <=> DataDescriptor\n\t\tif !configurable {\n\t\t\tif !prop.writable() && descriptor.writable() {\n\t\t\t\treturn reject(\"property not configurable or writeable and descriptor not writeable\")\n\t\t\t}\n\t\t\tif !prop.writable() {\n\t\t\t\tif descriptor.value != nil && !sameValue(value, descriptor.value.(Value)) {\n\t\t\t\t\treturn reject(\"property not configurable or writeable and descriptor not the same\")\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\tdefault:\n\t\t// AccessorDescriptor <=> AccessorDescriptor\n\t\tnewGetSet, _ := descriptor.value.(propertyGetSet)\n\t\tpresentGet, presentSet := true, true\n\t\tif newGetSet[0] == &nilGetSetObject {\n\t\t\t// Present, but nil\n\t\t\tnewGetSet[0] = nil\n\t\t} else if newGetSet[0] == nil {\n\t\t\t// Missing, not even nil\n\t\t\tnewGetSet[0] = getSet[0]\n\t\t\tpresentGet = false\n\t\t}\n\t\tif newGetSet[1] == &nilGetSetObject {\n\t\t\t// Present, but nil\n\t\t\tnewGetSet[1] = nil\n\t\t} else if newGetSet[1] == nil {\n\t\t\t// Missing, not even nil\n\t\t\tnewGetSet[1] = getSet[1]\n\t\t\tpresentSet = false\n\t\t}\n\t\tif !configurable {\n\t\t\tif (presentGet && (getSet[0] != newGetSet[0])) || (presentSet && (getSet[1] != newGetSet[1])) {\n\t\t\t\treturn reject(\"access descriptor not configurable\")\n\t\t\t}\n\t\t}\n\t\tdescriptor.value = newGetSet\n\t}\n\n\t// This section will preserve attributes of\n\t// the original property, if necessary\n\tvalue1 := descriptor.value\n\tif value1 == nil {\n\t\tvalue1 = prop.value\n\t} else if newGetSet, isAccessor := descriptor.value.(propertyGetSet); isAccessor {\n\t\tif newGetSet[0] == &nilGetSetObject {\n\t\t\tnewGetSet[0] = nil\n\t\t}\n\t\tif newGetSet[1] == &nilGetSetObject {\n\t\t\tnewGetSet[1] = nil\n\t\t}\n\t\tvalue1 = newGetSet\n\t}\n\tmode1 := descriptor.mode\n\tif mode1&0o222 != 0 {\n\t\t// TODO Factor this out into somewhere testable\n\t\t// (Maybe put into switch ...)\n\t\tmode0 := prop.mode\n\t\tif mode1&0o200 != 0 {\n\t\t\tif descriptor.isDataDescriptor() {\n\t\t\t\tmode1 &= ^0o200 // Turn off \"writable\" missing\n\t\t\t\tmode1 |= (mode0 & 0o100)\n\t\t\t}\n\t\t}\n\t\tif mode1&0o20 != 0 {\n\t\t\tmode1 |= (mode0 & 0o10)\n\t\t}\n\t\tif mode1&0o2 != 0 {\n\t\t\tmode1 |= (mode0 & 0o1)\n\t\t}\n\t\tmode1 &= 0o311 // 0311 to preserve the non-setting on \"writable\"\n\t}\n\tobj.writeProperty(name, value1, mode1)\n\n\treturn true\n}\n\nfunc objectDelete(obj *object, name string, throw bool) bool {\n\tprop := obj.getOwnProperty(name)\n\tif prop == nil {\n\t\treturn true\n\t}\n\tif prop.configurable() {\n\t\tobj.deleteProperty(name)\n\t\treturn true\n\t}\n\treturn obj.runtime.typeErrorResult(throw)\n}\n\nfunc objectClone(in *object, out *object, clone *cloner) *object {\n\t*out = *in\n\n\tout.runtime = clone.runtime\n\tif out.prototype != nil {\n\t\tout.prototype = clone.object(in.prototype)\n\t}\n\tout.property = make(map[string]property, len(in.property))\n\tout.propertyOrder = make([]string, len(in.propertyOrder))\n\tcopy(out.propertyOrder, in.propertyOrder)\n\tfor index, prop := range in.property {\n\t\tout.property[index] = clone.property(prop)\n\t}\n\n\tswitch value := in.value.(type) {\n\tcase nativeFunctionObject:\n\t\tout.value = value\n\tcase bindFunctionObject:\n\t\tout.value = bindFunctionObject{\n\t\t\ttarget:       clone.object(value.target),\n\t\t\tthis:         clone.value(value.this),\n\t\t\targumentList: clone.valueArray(value.argumentList),\n\t\t}\n\tcase nodeFunctionObject:\n\t\tout.value = nodeFunctionObject{\n\t\t\tnode:  value.node,\n\t\t\tstash: clone.stash(value.stash),\n\t\t}\n\tcase argumentsObject:\n\t\tout.value = value.clone(clone)\n\t}\n\n\treturn out\n}\n"
  },
  {
    "path": "object_test.go",
    "content": "package otto\n\nimport (\n\t\"testing\"\n)\n\nfunc TestObject_(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\tobj := newObject(nil, \"\")\n\t\tis(obj != nil, true)\n\n\t\tobj.put(\"xyzzy\", toValue(\"Nothing happens.\"), true)\n\t\tis(obj.get(\"xyzzy\"), \"Nothing happens.\")\n\n\t\ttest(`\n            var abc = Object.getOwnPropertyDescriptor(Object, \"prototype\");\n            [ [ typeof Object.prototype, abc.writable, abc.enumerable, abc.configurable ],\n            ];\n        `, \"object,false,false,false\")\n\t})\n}\n\nfunc TestStringObject(t *testing.T) {\n\ttt(t, func() {\n\t\tobj := New().runtime.newStringObject(toValue(\"xyzzy\"))\n\t\tis(obj.get(\"1\"), \"y\")\n\t\tis(obj.get(\"10\"), \"undefined\")\n\t\tis(obj.get(\"2\"), \"z\")\n\t})\n}\n\nfunc TestObject_getPrototypeOf(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            abc = {};\n            def = Object.getPrototypeOf(abc);\n            ghi = Object.getPrototypeOf(def);\n            [abc,def,ghi,ghi+\"\"];\n        `, \"[object Object],[object Object],,null\")\n\n\t\ttest(`\n            abc = Object.getOwnPropertyDescriptor(Object, \"getPrototypeOf\");\n            [ abc.value === Object.getPrototypeOf, abc.writable, abc.enumerable, abc.configurable ];\n        `, \"true,true,false,true\")\n\t})\n}\n\nfunc TestObject_new(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            [ new Object(\"abc\"), new Object(2+2) ];\n        `, \"abc,4\")\n\t})\n}\n\nfunc TestObject_create(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`raise: Object.create()`, \"TypeError: Object.Create is nil\")\n\n\t\ttest(`\n            var abc = Object.create(null)\n            var def = Object.create({x: 10, y: 20})\n            var ghi = Object.create(Object.prototype)\n\n            var jkl = Object.create({x: 10, y: 20}, {\n                z: {\n                    value: 30,\n                    writable: true\n                },\n                // sum: {\n                //     get: function() {\n                //         return this.x + this.y + this.z\n                //     }\n                // }\n            });\n            [ abc.prototype, def.x, def.y, ghi, jkl.x, jkl.y, jkl.z ]\n        `, \",10,20,[object Object],10,20,30\")\n\n\t\ttest(`\n            var properties = {};\n            Object.defineProperty(properties, \"abc\", {\n                value: {},\n                enumerable: false\n            });\n            var mno = Object.create({}, properties);\n            mno.hasOwnProperty(\"abc\");\n        `, false)\n\t})\n}\n\nfunc TestObject_toLocaleString(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            ({}).toLocaleString();\n        `, \"[object Object]\")\n\n\t\ttest(`\n            object = {\n                toString: function() {\n                    return \"Nothing happens.\";\n                }\n            };\n            object.toLocaleString();\n        `, \"Nothing happens.\")\n\t})\n}\n\nfunc TestObject_isExtensible(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`raise:\n            Object.isExtensible();\n        `, \"TypeError: Object.IsExtensible is nil\")\n\n\t\t// FIXME terst, Why raise?\n\t\ttest(`raise:\n            Object.isExtensible({});\n        `, true)\n\n\t\ttest(`Object.isExtensible.length`, 1)\n\t\ttest(`Object.isExtensible.prototype`, \"undefined\")\n\t})\n}\n\nfunc TestObject_preventExtensions(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`raise:\n            Object.preventExtensions()\n        `, \"TypeError: Object.PreventExtensions is nil\")\n\n\t\ttest(`raise:\n            var abc = { def: true };\n            var ghi = Object.preventExtensions(abc);\n            [ ghi.def === true, Object.isExtensible(abc), Object.isExtensible(ghi) ];\n        `, \"true,false,false\")\n\n\t\ttest(`\n            var abc = new String();\n            var def = Object.isExtensible(abc);\n            Object.preventExtensions(abc);\n            var ghi = false;\n            try {\n                Object.defineProperty(abc, \"0\", { value: \"~\" });\n            } catch (err) {\n                ghi = err instanceof TypeError;\n            }\n            [ def, ghi, abc.hasOwnProperty(\"0\"), typeof abc[0] ];\n        `, \"true,true,false,undefined\")\n\n\t\ttest(`Object.preventExtensions.length`, 1)\n\t\ttest(`Object.preventExtensions.prototype`, \"undefined\")\n\t})\n}\n\nfunc TestObject_isSealed(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`Object.isSealed.length`, 1)\n\t\ttest(`Object.isSealed.prototype`, \"undefined\")\n\t})\n}\n\nfunc TestObject_seal(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`raise: Object.seal()`, \"TypeError: Object.Seal is nil\")\n\n\t\ttest(`\n            var abc = {a:1,b:1,c:3};\n            var sealed = Object.isSealed(abc);\n            Object.seal(abc);\n            [sealed, Object.isSealed(abc)];\n        `, \"false,true\")\n\n\t\ttest(`\n            var abc = {a:1,b:1,c:3};\n            var sealed = Object.isSealed(abc);\n            var caught = false;\n            Object.seal(abc);\n            abc.b = 5;\n            Object.defineProperty(abc, \"a\", {value:4});\n            try {\n                Object.defineProperty(abc, \"a\", {value:42,enumerable:false});\n            } catch (e) {\n                caught = e instanceof TypeError;\n            }\n            [sealed, Object.isSealed(abc), caught, abc.a, abc.b];\n        `, \"false,true,true,4,5\")\n\n\t\ttest(`Object.seal.length`, 1)\n\t\ttest(`Object.seal.prototype`, \"undefined\")\n\t})\n}\n\nfunc TestObject_isFrozen(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`raise: Object.isFrozen()`, \"TypeError: Object.IsFrozen is nil\")\n\t\ttest(`Object.isFrozen(Object.preventExtensions({a:1}))`, false)\n\t\ttest(`Object.isFrozen({})`, false)\n\n\t\ttest(`\n            var abc = {};\n            Object.defineProperty(abc, \"def\", {\n                value: \"def\",\n                writable: true,\n                configurable: false\n            });\n            Object.preventExtensions(abc);\n            !Object.isFrozen(abc);\n        `, true)\n\n\t\ttest(`Object.isFrozen.length`, 1)\n\t\ttest(`Object.isFrozen.prototype`, \"undefined\")\n\t})\n}\n\nfunc TestObject_freeze(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`raise: Object.freeze()`, \"TypeError: Object.Freeze is nil\")\n\n\t\ttest(`\n            var abc = {a:1,b:2,c:3};\n            var frozen = Object.isFrozen(abc);\n            Object.freeze(abc);\n            abc.b = 5;\n            [frozen, Object.isFrozen(abc), abc.b];\n        `, \"false,true,2\")\n\n\t\ttest(`\n            var abc = {a:1,b:2,c:3};\n            var frozen = Object.isFrozen(abc);\n            var caught = false;\n            Object.freeze(abc);\n            abc.b = 5;\n            try {\n                Object.defineProperty(abc, \"a\", {value:4});\n            } catch (e) {\n                caught = e instanceof TypeError;\n            }\n            [frozen, Object.isFrozen(abc), caught, abc.a, abc.b];\n        `, \"false,true,true,1,2\")\n\n\t\ttest(`Object.freeze.length`, 1)\n\t\ttest(`Object.freeze.prototype`, \"undefined\")\n\t})\n}\n\nfunc TestObject_defineProperty(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            (function(abc, def, ghi){\n                Object.defineProperty(arguments, \"0\", {\n                    enumerable: false\n                });\n                return true;\n            })(0, 1, 2);\n        `, true)\n\n\t\ttest(`\n            var abc = {};\n            abc.def = 3.14; // Default: writable: true, enumerable: true, configurable: true\n\n            Object.defineProperty(abc, \"def\", {\n                value: 42\n            });\n\n            var ghi = Object.getOwnPropertyDescriptor(abc, \"def\");\n            [ ghi.value, ghi.writable, ghi.enumerable, ghi.configurable ];\n        `, \"42,true,true,true\")\n\n\t\t// Test that we handle the case of DefineOwnProperty\n\t\t// where [[Writable]] is something but [[Value]] is not\n\t\ttest(`\n            var abc = [];\n            Object.defineProperty(abc, \"0\", { writable: false });\n            0 in abc;\n        `, true)\n\n\t\t// Test that we handle the case of DefineOwnProperty\n\t\t// where [[Writable]] is something but [[Value]] is not\n\t\t// (and the property originally had something for [[Value]]\n\t\ttest(`\n            abc = {\n                def: 42\n            };\n            Object.defineProperty(abc, \"def\", { writable: false });\n            abc.def;\n        `, 42)\n\t})\n}\n\nfunc TestObject_assign(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\t// Test 1: Assigning two empty objects should return an empty object.\n\t\ttest(`JSON.stringify(Object.assign({}, {}))`, \"{}\")\n\n\t\t// Test 2: Single source assignment.\n\t\ttest(`JSON.stringify(Object.assign({}, {a: 1}))`, \"{\\\"a\\\":1}\")\n\n\t\t// Test 3: Multiple sources with later properties overriding earlier ones.\n\t\ttest(`JSON.stringify(Object.assign({a: 1, c: 5}, {a: 2}, {b: 3}))`, \"{\\\"a\\\":2,\\\"b\\\":3,\\\"c\\\":5}\")\n\n\t\t// Test 4: Merging objects with overlapping keys.\n\t\ttest(`JSON.stringify(Object.assign({a: 1, b: 2}, {b: 3, c: 4}))`, \"{\\\"a\\\":1,\\\"b\\\":3,\\\"c\\\":4}\")\n\n\t\t// Test 5: Sources that are null or undefined should be ignored.\n\t\ttest(`JSON.stringify(Object.assign({a: 1}, null, undefined, {b: 2}))`, \"{\\\"a\\\":1,\\\"b\\\":2}\")\n\n\t\t// Test 6: When a string is used as a source, its characters are assigned as indexed properties.\n\t\ttest(`JSON.stringify(Object.assign({}, \"abc\"))`, \"{\\\"0\\\":\\\"a\\\",\\\"1\\\":\\\"b\\\",\\\"2\\\":\\\"c\\\"}\")\n\n\t\t// // Test 7: The return value should be the target object.\n\t\ttest(`(function(){ var o = {x:1}; var r = Object.assign(o, {y:2}); return (o === r).toString(); })()`, \"true\")\n\n\t\t// Test 8: Non-enumerable properties should not be copied.\n\t\ttest(`(function(){\n            var target = {};\n            var source = {};\n            Object.defineProperty(source, \"hidden\", { value: 42, enumerable: false });\n            Object.assign(target, source);\n            return target.hasOwnProperty(\"hidden\").toString();\n\t\t})()`, \"false\")\n\n\t\t// Test 9: Using a number as a source should not add any properties.\n\t\ttest(`JSON.stringify(Object.assign({}, 123))`, \"{}\")\n\n\t\t// Test 10: Using a boolean as a source should not add any properties.\n\t\ttest(`JSON.stringify(Object.assign({}, true))`, \"{}\")\n\n\t\t// Test 11: Arrays are objects, so their indexed elements are copied.\n\t\ttest(`JSON.stringify(Object.assign({}, [1,2,3]))`, \"{\\\"0\\\":1,\\\"1\\\":2,\\\"2\\\":3}\")\n\t})\n}\n\nfunc TestObject_keys(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`Object.keys({ abc:undefined, def:undefined })`, \"abc,def\")\n\n\t\ttest(`\n            function abc() {\n                this.abc = undefined;\n                this.def = undefined;\n            }\n            Object.keys(new abc())\n        `, \"abc,def\")\n\n\t\ttest(`\n            function def() {\n                this.ghi = undefined;\n            }\n            def.prototype = new abc();\n            Object.keys(new def());\n        `, \"ghi\")\n\n\t\ttest(`\n            var ghi = Object.create(\n                {\n                    abc: undefined,\n                    def: undefined\n                },\n                {\n                    ghi: { value: undefined, enumerable: true },\n                    jkl: { value: undefined, enumerable: false }\n                }\n            );\n            Object.keys(ghi);\n        `, \"ghi\")\n\n\t\ttest(`\n            (function(abc, def, ghi){\n                return Object.keys(arguments)\n            })(undefined, undefined);\n        `, \"0,1\")\n\n\t\ttest(`\n            (function(abc, def, ghi){\n                return Object.keys(arguments)\n            })(undefined, undefined, undefined, undefined);\n        `, \"0,1,2,3\")\n\t})\n}\n\nfunc TestObject_values(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`Object.values({ abc:\"first_example\", def:\"second_example\" })`, \"first_example,second_example\")\n\n\t\ttest(`\n\t\t\tfunction abc() {\n\t\t\t\tthis.abc = \"first_example\";\n\t\t\t\tthis.def = \"second_example\";\n\t\t\t}\n\t\t\tObject.values(new abc())\n\t\t`, \"first_example,second_example\")\n\n\t\ttest(`\n\t\t\tfunction def() {\n\t\t\t\tthis.ghi = \"third_example\"\n\t\t\t}\n\t\t\tdef.prototype = new abc();\n\t\t\tObject.values(new def());\n\t\t`, \"third_example\")\n\n\t\ttest(`\n\t\t\tvar arr = [1, 2, 3];\n\t\t\tObject.values(arr);\n\t\t`, \"1,2,3\")\n\n\t\ttest(`\n\t\t\tvar arr = [{\"abc\": \"first_example\"}, {\"def\": \"second_example\"}];\n\t\t\tObject.values(arr);\n\t\t`, \"[object Object],[object Object]\")\n\t})\n}\n\nfunc TestObject_getOwnPropertyNames(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`Object.getOwnPropertyNames({ abc:undefined, def:undefined })`, \"abc,def\")\n\n\t\ttest(`\n            var ghi = Object.create(\n                {\n                    abc: undefined,\n                    def: undefined\n                },\n                {\n                    ghi: { value: undefined, enumerable: true },\n                    jkl: { value: undefined, enumerable: false }\n                }\n            );\n            Object.getOwnPropertyNames(ghi)\n        `, \"ghi,jkl\")\n\t})\n}\n\nfunc TestObjectGetterSetter(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`raise:\n            Object.create({}, {\n                abc: {\n                    get: function(){\n                        return \"true\";\n                    },\n                    writable: true\n                }\n            }).abc;\n        `, \"TypeError: toPropertyDescriptor descriptor writeSet\")\n\n\t\ttest(`raise:\n            Object.create({}, {\n                abc: {\n                    get: function(){\n                        return \"true\";\n                    },\n                    writable: false\n                }\n            }).abc;\n        `, \"TypeError: toPropertyDescriptor descriptor writeSet\")\n\n\t\ttest(`\n            Object.create({}, {\n                abc: {\n                    get: function(){\n                        return \"true\";\n                    }\n                }\n            }).abc;\n        `, \"true\")\n\n\t\ttest(`\n            Object.create({xyz:true},{abc:{get:function(){return this.xyx}}}).abc;\n            Object.create({\n                    xyz: true\n                }, {\n                abc: {\n                    get: function(){\n                        return this.xyz;\n                    }\n                }\n            }).abc;\n        `, true)\n\n\t\ttest(`\n            var abc = false;\n            var def = Object.create({}, {\n                xyz: {\n                    set: function(value) {\n                        abc = value;\n                    }\n                }\n            });\n            def.xyz = true;\n            [ abc ];\n        `, \"true\")\n\n\t\ttest(`\n            var abc = {};\n            Object.defineProperty(abc, \"def\", {\n                value: \"xyzzy\",\n                configurable: true\n            });\n            Object.preventExtensions(abc);\n            Object.defineProperty(abc, \"def\", {\n                get: function() {\n                    return 5;\n                }\n            });\n            var def = Object.getOwnPropertyDescriptor(abc, \"def\");\n            [ abc.def, typeof def.get, typeof def.set, typeof def.value, def.configurable, def.enumerable, typeof def.writable ];\n        `, \"5,function,undefined,undefined,true,false,undefined\")\n\n\t\ttest(`\n            var abc = {};\n            Object.defineProperty(abc, \"def\", {\n                get: function() {\n                    return 5;\n                }\n                configurable: true\n            });\n            Object.preventExtensions(abc);\n            Object.defineProperty(abc, \"def\", {\n                value: \"xyzzy\",\n            });\n            var def = Object.getOwnPropertyDescriptor(abc, \"def\");\n            [ abc.def, typeof def.get, typeof def.set, def.value, def.configurable, def.enumerable, def.writable ];\n        `, \"xyzzy,undefined,undefined,xyzzy,true,false,false\")\n\n\t\ttest(`\n            var abc = {};\n\n            function _get0() {\n                return 10;\n            }\n\n            function _set(value) {\n                abc.def = value;\n            }\n\n            Object.defineProperty(abc, \"ghi\", {\n                get: _get0,\n                set: _set,\n                configurable: true\n            });\n\n            function _get1() {\n                return 20;\n            }\n\n            Object.defineProperty(abc, \"ghi\", {\n                get: _get0\n            });\n\n            var descriptor = Object.getOwnPropertyDescriptor(abc, \"ghi\");\n            [ typeof descriptor.set ];\n        `, \"function\")\n\n\t\ttest(`raise:\n            var abc = [];\n            Object.defineProperty(abc, \"length\", {\n                get: function () {\n                    return 2;\n                }\n            });\n        `, `TypeError: Array.DefineOwnProperty [\"function () {\\n                    return 2;\\n                }\" <nil>] is not a value`)\n\n\t\ttest(`\n            var abc = {};\n\n            var getter = function() {\n                return 1;\n            }\n\n            Object.defineProperty(abc, \"def\", {\n                get: getter,\n                configurable: false\n            });\n\n            var jkl = undefined;\n            try {\n                Object.defineProperty(abc, \"def\", {\n                    get: undefined\n                });\n            }\n            catch (err) {\n                jkl = err;\n            }\n            var ghi = Object.getOwnPropertyDescriptor(abc, \"def\");\n            [ jkl instanceof TypeError, ghi.get === getter, ghi.configurable, ghi.enumerable ];\n        `, \"true,true,false,false\")\n\n\t\ttest(`\n            var abc = {};\n\n            var getter = function() {\n                return 1;\n            };\n\n            Object.defineProperty(abc, \"def\", {\n                get: getter\n            });\n\n            Object.defineProperty(abc, \"def\", {\n                set: undefined\n            });\n\n            var ghi = Object.getOwnPropertyDescriptor(abc, \"def\");\n            [ ghi.get === getter, ghi.set === undefined, ghi.configurable, ghi.enumerable ];\n        `, \"true,true,false,false\")\n\n\t\ttest(`\n            var abc = {};\n\n            var getter = function() {\n                return 1;\n            };\n\n            Object.defineProperty(abc, \"def\", {\n                get: getter\n            });\n\n            var jkl = undefined;\n            try {\n                Object.defineProperty(abc, \"def\", {\n                    set: function() {}\n                });\n            }\n            catch (err) {\n                jkl = err;\n            }\n\n            var ghi = Object.getOwnPropertyDescriptor(abc, \"def\");\n            [ jkl instanceof TypeError, ghi.get === getter, ghi.set, ghi.configurable, ghi.enumerable ];\n        `, \"true,true,,false,false\")\n\n\t\ttest(`\n            var abc = {};\n            var def = \"xyzzy\";\n\n            Object.defineProperty(abc, \"ghi\", {\n                get: undefined,\n                set: function(value) {\n                    def = value;\n                },\n                enumerable: true,\n                configurable: true\n            });\n\n            var hasOwn = abc.hasOwnProperty(\"ghi\");\n            var descriptor = Object.getOwnPropertyDescriptor(abc, \"ghi\");\n\n            [ hasOwn, typeof descriptor.get ];\n        `, \"true,undefined\")\n\n\t\ttest(`\n            var abc = \"xyzzy\";\n            Object.defineProperty(Array.prototype, \"abc\", {\n                get: function () {\n                    return abc;\n                },\n                set: function (value) {\n                    abc = value;\n                },\n                enumerable: true,\n                configurable: true\n            });\n            var def = [];\n            def.abc = 3.14159;\n            [ def.hasOwnProperty(\"abc\"), def.abc, abc ];\n        `, \"false,3.14159,3.14159\")\n\t})\n}\n\nfunc TestProperty(t *testing.T) {\n\ttt(t, func() {\n\t\tprop := property{}\n\t\tprop.writeOn()\n\t\tis(prop.writeSet(), true)\n\n\t\tprop.writeClear()\n\t\tis(prop.writeSet(), false)\n\n\t\tprop.writeOff()\n\t\tis(prop.writeSet(), true)\n\n\t\tprop.writeClear()\n\t\tis(prop.writeSet(), false)\n\t})\n}\n"
  },
  {
    "path": "otto/main.go",
    "content": "package main\n\nimport (\n\t\"errors\"\n\t\"flag\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\n\t\"github.com/robertkrimen/otto\"\n\t\"github.com/robertkrimen/otto/underscore\"\n)\n\nvar flagUnderscore *bool = flag.Bool(\"underscore\", true, \"Load underscore into the runtime environment\")\n\nfunc readSource(filename string) ([]byte, error) {\n\tif filename == \"\" || filename == \"-\" {\n\t\treturn io.ReadAll(os.Stdin)\n\t}\n\treturn os.ReadFile(filename) //nolint:gosec\n}\n\nfunc main() {\n\tflag.Parse()\n\n\tif !*flagUnderscore {\n\t\tunderscore.Disable()\n\t}\n\n\terr := func() error {\n\t\tsrc, err := readSource(flag.Arg(0))\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tvm := otto.New()\n\t\t_, err = vm.Run(src)\n\t\treturn err\n\t}()\n\tif err != nil {\n\t\tvar oerr *otto.Error\n\t\tif errors.As(err, &oerr) {\n\t\t\tfmt.Fprint(os.Stderr, oerr.String())\n\t\t} else {\n\t\t\tfmt.Fprintln(os.Stderr, err)\n\t\t}\n\t\tos.Exit(64)\n\t}\n}\n"
  },
  {
    "path": "otto.go",
    "content": "/*\nPackage otto is a JavaScript parser and interpreter written natively in Go.\n\nhttp://godoc.org/github.com/robertkrimen/otto\n\n\timport (\n\t    \"github.com/robertkrimen/otto\"\n\t)\n\nRun something in the VM\n\n\tvm := otto.New()\n\tvm.Run(`\n\t    abc = 2 + 2;\n\t\tconsole.log(\"The value of abc is \" + abc); // 4\n\t`)\n\nGet a value out of the VM\n\n\tvalue, err := vm.Get(\"abc\")\n\t\tvalue, _ := value.ToInteger()\n\t}\n\nSet a number\n\n\tvm.Set(\"def\", 11)\n\tvm.Run(`\n\t\tconsole.log(\"The value of def is \" + def);\n\t\t// The value of def is 11\n\t`)\n\nSet a string\n\n\tvm.Set(\"xyzzy\", \"Nothing happens.\")\n\tvm.Run(`\n\t\tconsole.log(xyzzy.length); // 16\n\t`)\n\nGet the value of an expression\n\n\tvalue, _ = vm.Run(\"xyzzy.length\")\n\t// iv is an int64 with a value of 16\n\tiv, _ := value.ToInteger()\n\nAn error happens\n\n\tvalue, err = vm.Run(\"abcdefghijlmnopqrstuvwxyz.length\")\n\tif err != nil {\n\t\t// err = ReferenceError: abcdefghijlmnopqrstuvwxyz is not defined\n\t\t// If there is an error, then value.IsUndefined() is true\n\t\t...\n\t}\n\nSet a Go function\n\n\tvm.Set(\"sayHello\", func(call otto.FunctionCall) otto.Value {\n\t    fmt.Printf(\"Hello, %s.\\n\", call.Argument(0).String())\n\t    return otto.Value{}\n\t})\n\nSet a Go function that returns something useful\n\n\tvm.Set(\"twoPlus\", func(call otto.FunctionCall) otto.Value {\n\t    right, _ := call.Argument(0).ToInteger()\n\t    result, _ := vm.ToValue(2 + right)\n\t    return result\n\t})\n\nUse the functions in JavaScript\n\n\tresult, _ = vm.Run(`\n\t    sayHello(\"Xyzzy\");      // Hello, Xyzzy.\n\t    sayHello();             // Hello, undefined\n\n\t    result = twoPlus(2.0); // 4\n\t`)\n\n# Parser\n\nA separate parser is available in the parser package if you're just interested in building an AST.\n\nhttp://godoc.org/github.com/robertkrimen/otto/parser\n\nParse and return an AST\n\n\tfilename := \"\" // A filename is optional\n\tsrc := `\n\t    // Sample xyzzy example\n\t    (function(){\n\t        if (3.14159 > 0) {\n\t            console.log(\"Hello, World.\");\n\t            return;\n\t        }\n\n\t        var xyzzy = NaN;\n\t        console.log(\"Nothing happens.\");\n\t        return xyzzy;\n\t    })();\n\t`\n\n\t// Parse some JavaScript, yielding a *ast.Program and/or an ErrorList\n\tprogram, err := parser.ParseFile(nil, filename, src, 0)\n\notto\n\nYou can run (Go) JavaScript from the commandline with: http://github.com/robertkrimen/otto/tree/master/otto\n\n\t$ go get -v github.com/robertkrimen/otto/otto\n\nRun JavaScript by entering some source on stdin or by giving otto a filename:\n\n\t$ otto example.js\n\nunderscore\n\nOptionally include the JavaScript utility-belt library, underscore, with this import:\n\n\timport (\n\t\t\"github.com/robertkrimen/otto\"\n\t\t_ \"github.com/robertkrimen/otto/underscore\"\n\t)\n\n\t// Now every otto runtime will come loaded with underscore\n\nFor more information: http://github.com/robertkrimen/otto/tree/master/underscore\n\n# Caveat Emptor\n\nThe following are some limitations with otto:\n\n  - \"use strict\" will parse, but does nothing.\n  - The regular expression engine (re2/regexp) is not fully compatible with the ECMA5 specification.\n  - Otto targets ES5. ES6 features (eg: Typed Arrays) are not supported.\n\n# Regular Expression Incompatibility\n\nGo translates JavaScript-style regular expressions into something that is \"regexp\" compatible via `parser.TransformRegExp`.\nUnfortunately, RegExp requires backtracking for some patterns, and backtracking is not supported by the standard Go engine: https://code.google.com/p/re2/wiki/Syntax\n\nTherefore, the following syntax is incompatible:\n\n\t(?=)  // Lookahead (positive), currently a parsing error\n\t(?!)  // Lookahead (backhead), currently a parsing error\n\t\\1    // Backreference (\\1, \\2, \\3, ...), currently a parsing error\n\nA brief discussion of these limitations: \"Regexp (?!re)\" https://groups.google.com/forum/?fromgroups=#%21topic/golang-nuts/7qgSDWPIh_E\n\nMore information about re2: https://code.google.com/p/re2/\n\nIn addition to the above, re2 (Go) has a different definition for \\s: [\\t\\n\\f\\r ].\nThe JavaScript definition, on the other hand, also includes \\v, Unicode \"Separator, Space\", etc.\n\n# Halting Problem\n\nIf you want to stop long running executions (like third-party code), you can use the interrupt channel to do this:\n\n\tpackage main\n\n\timport (\n\t    \"errors\"\n\t    \"fmt\"\n\t    \"os\"\n\t    \"time\"\n\n\t    \"github.com/robertkrimen/otto\"\n\t)\n\n\tvar halt = errors.New(\"Stahp\")\n\n\tfunc main() {\n\t    runUnsafe(`var abc = [];`)\n\t    runUnsafe(`\n\t    while (true) {\n\t        // Loop forever\n\t    }`)\n\t}\n\n\tfunc runUnsafe(unsafe string) {\n\t    start := time.Now()\n\t    defer func() {\n\t        duration := time.Since(start)\n\t        if caught := recover(); caught != nil {\n\t            if caught == halt {\n\t                fmt.Fprintf(os.Stderr, \"Some code took to long! Stopping after: %v\\n\", duration)\n\t                return\n\t            }\n\t            panic(caught) // Something else happened, repanic!\n\t        }\n\t        fmt.Fprintf(os.Stderr, \"Ran code successfully: %v\\n\", duration)\n\t    }()\n\n\t    vm := otto.New()\n\t    vm.Interrupt = make(chan func(), 1) // The buffer prevents blocking\n\n\t    go func() {\n\t        time.Sleep(2 * time.Second) // Stop after two seconds\n\t        vm.Interrupt <- func() {\n\t            panic(halt)\n\t        }\n\t    }()\n\n\t    vm.Run(unsafe) // Here be dragons (risky code)\n\t}\n\nWhere is setTimeout/setInterval?\n\nThese timing functions are not actually part of the ECMA-262 specification. Typically, they belong to the `windows` object (in the browser).\nIt would not be difficult to provide something like these via Go, but you probably want to wrap otto in an event loop in that case.\n\nFor an example of how this could be done in Go with otto, see natto:\n\nhttp://github.com/robertkrimen/natto\n\nHere is some more discussion of the issue:\n\n* http://book.mixu.net/node/ch2.html\n* http://en.wikipedia.org/wiki/Reentrancy_%28computing%29\n* http://aaroncrane.co.uk/2009/02/perl_safe_signals/\n*/\npackage otto\n\nimport (\n\t\"encoding/json\"\n\t\"errors\"\n\t\"strings\"\n\n\t\"github.com/robertkrimen/otto/file\"\n\t\"github.com/robertkrimen/otto/registry\"\n)\n\n// Otto is the representation of the JavaScript runtime.\n// Each instance of Otto has a self-contained namespace.\ntype Otto struct {\n\t// Interrupt is a channel for interrupting the runtime. You can use this to halt a long running execution, for example.\n\t// See \"Halting Problem\" for more information.\n\tInterrupt chan func()\n\truntime   *runtime\n}\n\n// New will allocate a new JavaScript runtime.\nfunc New() *Otto {\n\to := &Otto{\n\t\truntime: newContext(),\n\t}\n\to.runtime.otto = o\n\to.runtime.traceLimit = 10\n\tif err := o.Set(\"console\", o.runtime.newConsole()); err != nil {\n\t\tpanic(err)\n\t}\n\n\tregistry.Apply(func(entry registry.Entry) {\n\t\tif _, err := o.Run(entry.Source()); err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t})\n\n\treturn o\n}\n\nfunc (o *Otto) clone() *Otto {\n\tn := &Otto{\n\t\truntime: o.runtime.clone(),\n\t}\n\tn.runtime.otto = n\n\treturn n\n}\n\n// Run will allocate a new JavaScript runtime, run the given source\n// on the allocated runtime, and return the runtime, resulting value, and\n// error (if any).\n//\n// src may be a string, a byte slice, a bytes.Buffer, or an io.Reader, but it MUST always be in UTF-8.\n//\n// src may also be a Script.\n//\n// src may also be a Program, but if the AST has been modified, then runtime behavior is undefined.\nfunc Run(src interface{}) (*Otto, Value, error) {\n\totto := New()\n\tvalue, err := otto.Run(src) // This already does safety checking\n\treturn otto, value, err\n}\n\n// Run will run the given source (parsing it first if necessary), returning the resulting value and error (if any)\n//\n// src may be a string, a byte slice, a bytes.Buffer, or an io.Reader, but it MUST always be in UTF-8.\n//\n// If the runtime is unable to parse source, then this function will return undefined and the parse error (nothing\n// will be evaluated in this case).\n//\n// src may also be a Script.\n//\n// src may also be a Program, but if the AST has been modified, then runtime behavior is undefined.\nfunc (o Otto) Run(src interface{}) (Value, error) {\n\tvalue, err := o.runtime.cmplRun(src, nil)\n\tif !value.safe() {\n\t\tvalue = Value{}\n\t}\n\treturn value, err\n}\n\n// Eval will do the same thing as Run, except without leaving the current scope.\n//\n// By staying in the same scope, the code evaluated has access to everything\n// already defined in the current stack frame. This is most useful in, for\n// example, a debugger call.\nfunc (o Otto) Eval(src interface{}) (Value, error) {\n\tif o.runtime.scope == nil {\n\t\to.runtime.enterGlobalScope()\n\t\tdefer o.runtime.leaveScope()\n\t}\n\n\tvalue, err := o.runtime.cmplEval(src, nil)\n\tif !value.safe() {\n\t\tvalue = Value{}\n\t}\n\treturn value, err\n}\n\n// Get the value of the top-level binding of the given name.\n//\n// If there is an error (like the binding does not exist), then the value\n// will be undefined.\nfunc (o Otto) Get(name string) (Value, error) {\n\tvalue := Value{}\n\terr := catchPanic(func() {\n\t\tvalue = o.getValue(name)\n\t})\n\tif !value.safe() {\n\t\tvalue = Value{}\n\t}\n\treturn value, err\n}\n\nfunc (o Otto) getValue(name string) Value {\n\treturn o.runtime.globalStash.getBinding(name, false)\n}\n\n// Set the top-level binding of the given name to the given value.\n//\n// Set will automatically apply ToValue to the given value in order\n// to convert it to a JavaScript value (type Value).\n//\n// If there is an error (like the binding is read-only, or the ToValue conversion\n// fails), then an error is returned.\n//\n// If the top-level binding does not exist, it will be created.\nfunc (o Otto) Set(name string, value interface{}) error {\n\tval, err := o.ToValue(value)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn catchPanic(func() {\n\t\to.setValue(name, val)\n\t})\n}\n\nfunc (o Otto) setValue(name string, value Value) {\n\to.runtime.globalStash.setValue(name, value, false)\n}\n\n// SetDebuggerHandler sets the debugger handler to fn.\nfunc (o Otto) SetDebuggerHandler(fn func(vm *Otto)) {\n\to.runtime.debugger = fn\n}\n\n// SetRandomSource sets the random source to fn.\nfunc (o Otto) SetRandomSource(fn func() float64) {\n\to.runtime.random = fn\n}\n\n// SetStackDepthLimit sets an upper limit to the depth of the JavaScript\n// stack. In simpler terms, this limits the number of \"nested\" function calls\n// you can make in a particular interpreter instance.\n//\n// Note that this doesn't take into account the Go stack depth. If your\n// JavaScript makes a call to a Go function, otto won't keep track of what\n// happens outside the interpreter. So if your Go function is infinitely\n// recursive, you're still in trouble.\nfunc (o Otto) SetStackDepthLimit(limit int) {\n\to.runtime.stackLimit = limit\n}\n\n// SetStackTraceLimit sets an upper limit to the number of stack frames that\n// otto will use when formatting an error's stack trace. By default, the limit\n// is 10. This is consistent with V8 and SpiderMonkey.\n//\n// TODO: expose via `Error.stackTraceLimit`.\nfunc (o Otto) SetStackTraceLimit(limit int) {\n\to.runtime.traceLimit = limit\n}\n\n// MakeCustomError creates a new Error object with the given name and message,\n// returning it as a Value.\nfunc (o Otto) MakeCustomError(name, message string) Value {\n\treturn o.runtime.toValue(o.runtime.newError(name, o.runtime.toValue(message), 0))\n}\n\n// MakeRangeError creates a new RangeError object with the given message,\n// returning it as a Value.\nfunc (o Otto) MakeRangeError(message string) Value {\n\treturn o.runtime.toValue(o.runtime.newRangeError(o.runtime.toValue(message)))\n}\n\n// MakeSyntaxError creates a new SyntaxError object with the given message,\n// returning it as a Value.\nfunc (o Otto) MakeSyntaxError(message string) Value {\n\treturn o.runtime.toValue(o.runtime.newSyntaxError(o.runtime.toValue(message)))\n}\n\n// MakeTypeError creates a new TypeError object with the given message,\n// returning it as a Value.\nfunc (o Otto) MakeTypeError(message string) Value {\n\treturn o.runtime.toValue(o.runtime.newTypeError(o.runtime.toValue(message)))\n}\n\n// Context is a structure that contains information about the current execution\n// context.\ntype Context struct {\n\tThis       Value\n\tSymbols    map[string]Value\n\tFilename   string\n\tCallee     string\n\tStacktrace []string\n\tLine       int\n\tColumn     int\n}\n\n// Context returns the current execution context of the vm, traversing up to\n// ten stack frames, and skipping any innermost native function stack frames.\nfunc (o Otto) Context() Context {\n\treturn o.ContextSkip(10, true)\n}\n\n// ContextLimit returns the current execution context of the vm, with a\n// specific limit on the number of stack frames to traverse, skipping any\n// innermost native function stack frames.\nfunc (o Otto) ContextLimit(limit int) Context {\n\treturn o.ContextSkip(limit, true)\n}\n\n// ContextSkip returns the current execution context of the vm, with a\n// specific limit on the number of stack frames to traverse, optionally\n// skipping any innermost native function stack frames.\nfunc (o Otto) ContextSkip(limit int, skipNative bool) Context {\n\t// Ensure we are operating in a scope\n\tif o.runtime.scope == nil {\n\t\to.runtime.enterGlobalScope()\n\t\tdefer o.runtime.leaveScope()\n\t}\n\n\tcurScope := o.runtime.scope\n\tfrm := curScope.frame\n\n\tfor skipNative && frm.native && curScope.outer != nil {\n\t\tcurScope = curScope.outer\n\t\tfrm = curScope.frame\n\t}\n\n\t// Get location information\n\tvar ctx Context\n\tctx.Filename = \"<unknown>\"\n\tctx.Callee = frm.callee\n\n\tswitch {\n\tcase frm.native:\n\t\tctx.Filename = frm.nativeFile\n\t\tctx.Line = frm.nativeLine\n\t\tctx.Column = 0\n\tcase frm.file != nil:\n\t\tctx.Filename = \"<anonymous>\"\n\n\t\tif p := frm.file.Position(file.Idx(frm.offset)); p != nil {\n\t\t\tctx.Line = p.Line\n\t\t\tctx.Column = p.Column\n\n\t\t\tif p.Filename != \"\" {\n\t\t\t\tctx.Filename = p.Filename\n\t\t\t}\n\t\t}\n\t}\n\n\t// Get the current scope this Value\n\tctx.This = objectValue(curScope.this)\n\n\t// Build stacktrace (up to 10 levels deep)\n\tctx.Symbols = make(map[string]Value)\n\tctx.Stacktrace = append(ctx.Stacktrace, frm.location())\n\tfor limit != 0 {\n\t\t// Get variables\n\t\tstash := curScope.lexical\n\t\tfor {\n\t\t\tfor _, name := range getStashProperties(stash) {\n\t\t\t\tif _, ok := ctx.Symbols[name]; !ok {\n\t\t\t\t\tctx.Symbols[name] = stash.getBinding(name, true)\n\t\t\t\t}\n\t\t\t}\n\t\t\tstash = stash.outer()\n\t\t\tif stash == nil || stash.outer() == nil {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tcurScope = curScope.outer\n\t\tif curScope == nil {\n\t\t\tbreak\n\t\t}\n\t\tif curScope.frame.offset >= 0 {\n\t\t\tctx.Stacktrace = append(ctx.Stacktrace, curScope.frame.location())\n\t\t}\n\t\tlimit--\n\t}\n\n\treturn ctx\n}\n\n// Call the given JavaScript with a given this and arguments.\n//\n// If this is nil, then some special handling takes place to determine the proper\n// this value, falling back to a \"standard\" invocation if necessary (where this is\n// undefined).\n//\n// If source begins with \"new \" (A lowercase new followed by a space), then\n// Call will invoke the function constructor rather than performing a function call.\n// In this case, the this argument has no effect.\n//\n//\t// value is a String object\n//\tvalue, _ := vm.Call(\"Object\", nil, \"Hello, World.\")\n//\n//\t// Likewise...\n//\tvalue, _ := vm.Call(\"new Object\", nil, \"Hello, World.\")\n//\n//\t// This will perform a concat on the given array and return the result\n//\t// value is [ 1, 2, 3, undefined, 4, 5, 6, 7, \"abc\" ]\n//\tvalue, _ := vm.Call(`[ 1, 2, 3, undefined, 4 ].concat`, nil, 5, 6, 7, \"abc\")\nfunc (o Otto) Call(source string, this interface{}, argumentList ...interface{}) (Value, error) {\n\tthisValue := Value{}\n\n\tconstruct := false\n\tif strings.HasPrefix(source, \"new \") {\n\t\tsource = source[4:]\n\t\tconstruct = true\n\t}\n\n\t// FIXME enterGlobalScope\n\to.runtime.enterGlobalScope()\n\tdefer func() {\n\t\to.runtime.leaveScope()\n\t}()\n\n\tif !construct && this == nil {\n\t\tprogram, err := o.runtime.cmplParse(\"\", source+\"()\", nil)\n\t\tif err == nil {\n\t\t\tif node, ok := program.body[0].(*nodeExpressionStatement); ok {\n\t\t\t\tif node, ok2 := node.expression.(*nodeCallExpression); ok2 {\n\t\t\t\t\tvar value Value\n\t\t\t\t\tif err = catchPanic(func() {\n\t\t\t\t\t\tvalue = o.runtime.cmplEvaluateNodeCallExpression(node, argumentList)\n\t\t\t\t\t}); err != nil {\n\t\t\t\t\t\treturn Value{}, err\n\t\t\t\t\t}\n\t\t\t\t\treturn value, nil\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else {\n\t\tvalue, err := o.ToValue(this)\n\t\tif err != nil {\n\t\t\treturn Value{}, err\n\t\t}\n\t\tthisValue = value\n\t}\n\n\tval := thisValue\n\tfn, err := o.Run(source)\n\tif err != nil {\n\t\treturn Value{}, err\n\t}\n\n\tif construct {\n\t\tresult, err2 := fn.constructSafe(o.runtime, val, argumentList...)\n\t\tif err2 != nil {\n\t\t\treturn Value{}, err2\n\t\t}\n\t\treturn result, nil\n\t}\n\n\tresult, err := fn.Call(val, argumentList...)\n\tif err != nil {\n\t\treturn Value{}, err\n\t}\n\treturn result, nil\n}\n\n// Object will run the given source and return the result as an object.\n//\n// For example, accessing an existing object:\n//\n//\tobject, _ := vm.Object(`Number`)\n//\n// Or, creating a new object:\n//\n//\tobject, _ := vm.Object(`({ xyzzy: \"Nothing happens.\" })`)\n//\n// Or, creating and assigning an object:\n//\n//\tobject, _ := vm.Object(`xyzzy = {}`)\n//\tobject.Set(\"volume\", 11)\n//\n// If there is an error (like the source does not result in an object), then\n// nil and an error is returned.\nfunc (o Otto) Object(source string) (*Object, error) {\n\tvalue, err := o.runtime.cmplRun(source, nil)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif value.IsObject() {\n\t\treturn value.Object(), nil\n\t}\n\treturn nil, errors.New(\"value is not an object\")\n}\n\n// ToValue will convert an interface{} value to a value digestible by otto/JavaScript.\nfunc (o Otto) ToValue(value interface{}) (Value, error) {\n\treturn o.runtime.safeToValue(value)\n}\n\n// Copy will create a copy/clone of the runtime.\n//\n// Copy is useful for saving some time when creating many similar runtimes.\n//\n// This method works by walking the original runtime and cloning each object, scope, stash,\n// etc. into a new runtime.\n//\n// Be on the lookout for memory leaks or inadvertent sharing of resources.\nfunc (o *Otto) Copy() *Otto {\n\tout := &Otto{\n\t\truntime: o.runtime.clone(),\n\t}\n\tout.runtime.otto = out\n\treturn out\n}\n\n// Object is the representation of a JavaScript object.\ntype Object struct {\n\tobject *object\n\tvalue  Value\n}\n\n// Call a method on the object.\n//\n// It is essentially equivalent to:\n//\n//\tvar method, _ := object.Get(name)\n//\tmethod.Call(object, argumentList...)\n//\n// An undefined value and an error will result if:\n//\n//  1. There is an error during conversion of the argument list\n//  2. The property is not actually a function\n//  3. An (uncaught) exception is thrown\nfunc (o Object) Call(name string, argumentList ...interface{}) (Value, error) {\n\t// TODO: Insert an example using JavaScript below...\n\t// e.g., Object(\"JSON\").Call(\"stringify\", ...)\n\n\tfunction, err := o.Get(name)\n\tif err != nil {\n\t\treturn Value{}, err\n\t}\n\treturn function.Call(o.Value(), argumentList...)\n}\n\n// Value returns the value of o.\nfunc (o Object) Value() Value {\n\treturn o.value\n}\n\n// Get the value of the property with the given name.\nfunc (o Object) Get(name string) (Value, error) {\n\tvalue := Value{}\n\terr := catchPanic(func() {\n\t\tvalue = o.object.get(name)\n\t})\n\tif !value.safe() {\n\t\tvalue = Value{}\n\t}\n\treturn value, err\n}\n\n// Set the property of the given name to the given value.\n//\n// An error will result if the setting the property triggers an exception (i.e. read-only),\n// or there is an error during conversion of the given value.\nfunc (o Object) Set(name string, value interface{}) error {\n\tval, err := o.object.runtime.safeToValue(value)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\treturn catchPanic(func() {\n\t\to.object.put(name, val, true)\n\t})\n}\n\n// Keys gets the keys for the given object.\n//\n// Equivalent to calling Object.keys on the object.\nfunc (o Object) Keys() []string {\n\tvar keys []string\n\to.object.enumerate(false, func(name string) bool {\n\t\tkeys = append(keys, name)\n\t\treturn true\n\t})\n\treturn keys\n}\n\n// KeysByParent gets the keys (and those of the parents) for the given object,\n// in order of \"closest\" to \"furthest\".\nfunc (o Object) KeysByParent() [][]string {\n\tvar a [][]string\n\n\tfor o := o.object; o != nil; o = o.prototype {\n\t\tvar l []string\n\n\t\to.enumerate(false, func(name string) bool {\n\t\t\tl = append(l, name)\n\t\t\treturn true\n\t\t})\n\n\t\ta = append(a, l)\n\t}\n\n\treturn a\n}\n\n// Class will return the class string of the object.\n//\n// The return value will (generally) be one of:\n//\n//\tObject\n//\tFunction\n//\tArray\n//\tString\n//\tNumber\n//\tBoolean\n//\tDate\n//\tRegExp\nfunc (o Object) Class() string {\n\treturn o.object.class\n}\n\n// MarshalJSON implements json.Marshaller.\nfunc (o Object) MarshalJSON() ([]byte, error) {\n\tvar goValue interface{}\n\tswitch value := o.object.value.(type) {\n\tcase *goStructObject:\n\t\tgoValue = value.value.Interface()\n\tcase *goMapObject:\n\t\tgoValue = value.value.Interface()\n\tcase *goArrayObject:\n\t\tgoValue = value.value.Interface()\n\tcase *goSliceObject:\n\t\tgoValue = value.value.Interface()\n\tdefault:\n\t\t// It's a JS object; pass it to JSON.stringify:\n\t\tvar result []byte\n\t\terr := catchPanic(func() {\n\t\t\tresultVal := builtinJSONStringify(FunctionCall{\n\t\t\t\truntime:      o.object.runtime,\n\t\t\t\tArgumentList: []Value{o.value},\n\t\t\t})\n\t\t\tresult = []byte(resultVal.String())\n\t\t})\n\t\treturn result, err\n\t}\n\treturn json.Marshal(goValue)\n}\n"
  },
  {
    "path": "otto_.go",
    "content": "package otto\n\nimport (\n\t\"fmt\"\n\t\"regexp\"\n\tgoruntime \"runtime\"\n\t\"strconv\"\n)\n\nvar isIdentifierRegexp *regexp.Regexp = regexp.MustCompile(`^[a-zA-Z\\$][a-zA-Z0-9\\$]*$`)\n\nfunc isIdentifier(value string) bool {\n\treturn isIdentifierRegexp.MatchString(value)\n}\n\nfunc (rt *runtime) toValueArray(arguments ...interface{}) []Value {\n\tlength := len(arguments)\n\tif length == 1 {\n\t\tif valueArray, ok := arguments[0].([]Value); ok {\n\t\t\treturn valueArray\n\t\t}\n\t\treturn []Value{rt.toValue(arguments[0])}\n\t}\n\n\tvalueArray := make([]Value, length)\n\tfor index, value := range arguments {\n\t\tvalueArray[index] = rt.toValue(value)\n\t}\n\n\treturn valueArray\n}\n\nfunc stringToArrayIndex(name string) int64 {\n\tindex, err := strconv.ParseInt(name, 10, 64)\n\tif err != nil {\n\t\treturn -1\n\t}\n\tif index < 0 {\n\t\treturn -1\n\t}\n\tif index >= maxUint32 {\n\t\t// The value 2^32 (or above) is not a valid index because\n\t\t// you cannot store a uint32 length for an index of uint32\n\t\treturn -1\n\t}\n\treturn index\n}\n\nfunc isUint32(value int64) bool {\n\treturn value >= 0 && value <= maxUint32\n}\n\nfunc arrayIndexToString(index int64) string {\n\treturn strconv.FormatInt(index, 10)\n}\n\nfunc valueOfArrayIndex(array []Value, index int) Value {\n\tvalue, _ := getValueOfArrayIndex(array, index)\n\treturn value\n}\n\nfunc getValueOfArrayIndex(array []Value, index int) (Value, bool) {\n\tif index >= 0 && index < len(array) {\n\t\tvalue := array[index]\n\t\tif !value.isEmpty() {\n\t\t\treturn value, true\n\t\t}\n\t}\n\treturn Value{}, false\n}\n\n// A range index can be anything from 0 up to length. It is NOT safe to use as an index\n// to an array, but is useful for slicing and in some ECMA algorithms.\nfunc valueToRangeIndex(indexValue Value, length int64, negativeIsZero bool) int64 {\n\tindex := indexValue.number().int64\n\tif negativeIsZero {\n\t\tif index < 0 {\n\t\t\tindex = 0\n\t\t}\n\t\t// minimum(index, length)\n\t\tif index >= length {\n\t\t\tindex = length\n\t\t}\n\t\treturn index\n\t}\n\n\tif index < 0 {\n\t\tindex += length\n\t\tif index < 0 {\n\t\t\tindex = 0\n\t\t}\n\t} else if index > length {\n\t\tindex = length\n\t}\n\treturn index\n}\n\nfunc rangeStartEnd(array []Value, size int64, negativeIsZero bool) (start, end int64) { //nolint:nonamedreturns\n\tstart = valueToRangeIndex(valueOfArrayIndex(array, 0), size, negativeIsZero)\n\tif len(array) == 1 {\n\t\t// If there is only the start argument, then end = size\n\t\tend = size\n\t\treturn\n\t}\n\n\t// Assuming the argument is undefined...\n\tend = size\n\tendValue := valueOfArrayIndex(array, 1)\n\tif !endValue.IsUndefined() {\n\t\t// Which it is not, so get the value as an array index\n\t\tend = valueToRangeIndex(endValue, size, negativeIsZero)\n\t}\n\treturn\n}\n\nfunc rangeStartLength(source []Value, size int64) (start, length int64) { //nolint:nonamedreturns\n\tstart = valueToRangeIndex(valueOfArrayIndex(source, 0), size, false)\n\n\t// Assume the second argument is missing or undefined\n\tlength = size\n\tif len(source) == 1 {\n\t\t// If there is only the start argument, then length = size\n\t\treturn start, length\n\t}\n\n\tlengthValue := valueOfArrayIndex(source, 1)\n\tif !lengthValue.IsUndefined() {\n\t\t// Which it is not, so get the value as an array index\n\t\tlength = lengthValue.number().int64\n\t}\n\treturn start, length\n}\n\nfunc hereBeDragons(arguments ...interface{}) string {\n\tpc, _, _, _ := goruntime.Caller(1) //nolint:dogsled\n\tname := goruntime.FuncForPC(pc).Name()\n\tmessage := \"Here be dragons -- \" + name\n\tif len(arguments) > 0 {\n\t\tmessage += \": \"\n\t\targument0 := fmt.Sprintf(\"%s\", arguments[0])\n\t\tif len(arguments) == 1 {\n\t\t\tmessage += argument0\n\t\t} else {\n\t\t\tmessage += fmt.Sprintf(argument0, arguments[1:]...)\n\t\t}\n\t} else {\n\t\tmessage += \".\"\n\t}\n\treturn message\n}\n"
  },
  {
    "path": "otto_error_test.go",
    "content": "package otto\n\nimport (\n\t\"testing\"\n)\n\nfunc TestOttoError(t *testing.T) {\n\ttt(t, func() {\n\t\tvm := New()\n\n\t\t_, err := vm.Run(`throw \"Xyzzy\"`)\n\t\tis(err, \"Xyzzy\")\n\n\t\t_, err = vm.Run(`throw new TypeError()`)\n\t\tis(err, \"TypeError\")\n\n\t\t_, err = vm.Run(`throw new TypeError(\"Nothing happens.\")`)\n\t\tis(err, \"TypeError: Nothing happens.\")\n\n\t\t_, err = ToValue([]byte{})\n\t\tis(err, \"TypeError: invalid value (slice): missing runtime: [] ([]uint8)\")\n\n\t\t_, err = vm.Run(`\n            (function(){\n                return abcdef.length\n            })()\n        `)\n\t\tis(err, \"ReferenceError: 'abcdef' is not defined\")\n\n\t\t_, err = vm.Run(`\n            function start() {\n            }\n\n            start()\n\n                xyzzy()\n        `)\n\t\tis(err, \"ReferenceError: 'xyzzy' is not defined\")\n\n\t\t_, err = vm.Run(`\n            // Just a comment\n\n            xyzzy\n        `)\n\t\tis(err, \"ReferenceError: 'xyzzy' is not defined\")\n\t})\n}\n"
  },
  {
    "path": "otto_test.go",
    "content": "package otto\n\nimport (\n\t\"bytes\"\n\t\"errors\"\n\t\"io\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/robertkrimen/otto/parser\"\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestOtto(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(\"xyzzy = 2\", 2)\n\n\t\ttest(\"xyzzy + 2\", 4)\n\n\t\ttest(\"xyzzy += 16\", 18)\n\n\t\ttest(\"xyzzy\", 18)\n\n\t\ttest(`\n            (function(){\n                return 1\n            })()\n        `, 1)\n\n\t\ttest(`\n            (function(){\n                return 1\n            }).call(this)\n        `, 1)\n\n\t\ttest(`\n            (function(){\n                var result\n                (function(){\n                    result = -1\n                })()\n                return result\n            })()\n        `, -1)\n\n\t\ttest(`\n            var abc = 1\n            abc || (abc = -1)\n            abc\n        `, 1)\n\n\t\ttest(`\n            var abc = (function(){ 1 === 1 })();\n            abc;\n        `, \"undefined\")\n\t})\n}\n\nfunc TestFunction__(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            function abc() {\n                return 1;\n            };\n            abc();\n        `, 1)\n\t})\n}\n\nfunc TestIf(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            abc = undefined;\n            def = undefined;\n            if (true) abc = 1\n            else abc = 2;\n            if (false) {\n                def = 3;\n            }\n            else def = 4;\n\n            [ abc, def ];\n        `, \"1,4\")\n\n\t\ttest(`\n            if (1) {\n                abc = 1;\n            }\n            else {\n                abc = 0;\n            }\n            abc;\n        `, 1)\n\n\t\ttest(`\n            if (0) {\n                abc = 1;\n            }\n            else {\n                abc = 0;\n            }\n            abc;\n        `, 0)\n\n\t\ttest(`\n            abc = 0;\n            if (0) {\n                abc = 1;\n            }\n            abc;\n        `, 0)\n\n\t\ttest(`\n            abc = 0;\n            if (abc) {\n                abc = 1;\n            }\n            abc;\n        `, 0)\n\t})\n}\n\nfunc TestSequence(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            1, 2, 3;\n        `, 3)\n\t})\n}\n\nfunc TestCall(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            Math.pow(3, 2);\n        `, 9)\n\t})\n}\n\nfunc TestRunFunctionWithSetArguments(t *testing.T) {\n\ttt(t, func() {\n\t\tvm := New()\n\t\t_, err := vm.Run(`var sillyFunction = function(record){record.silly = true; record.answer *= -1};`)\n\t\trequire.NoError(t, err)\n\t\trecord := map[string]interface{}{\"foo\": \"bar\", \"answer\": 42}\n\t\t// Set performs a conversion that allows the map to be addressed as a Javascript object\n\t\terr = vm.Set(\"argument\", record)\n\t\trequire.NoError(t, err)\n\t\t_, err = vm.Run(\"sillyFunction(argument)\")\n\t\trequire.NoError(t, err)\n\n\t\tis(record[\"answer\"].(float64), -42)\n\t\tis(record[\"silly\"].(bool), true)\n\t})\n}\n\nfunc TestRunFunctionWithArgumentsPassedToCall(t *testing.T) {\n\ttt(t, func() {\n\t\tvm := New()\n\t\t_, err := vm.Run(`var sillyFunction = function(record){record.silly = true; record.answer *= -1};`)\n\t\trequire.NoError(t, err)\n\t\trecord := map[string]interface{}{\"foo\": \"bar\", \"answer\": 42}\n\t\t_, err = vm.Call(\"sillyFunction\", nil, record)\n\t\trequire.NoError(t, err)\n\n\t\tis(record[\"answer\"].(float64), -42)\n\t\tis(record[\"silly\"].(bool), true)\n\t})\n}\n\nfunc TestMember(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            abc = [ 0, 1, 2 ];\n            def = {\n                \"abc\": 0,\n                \"def\": 1,\n                \"ghi\": 2,\n            };\n            [ abc[2], def.abc, abc[1], def.def ];\n        `, \"2,0,1,1\")\n\t})\n}\n\nfunc Test_this(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            typeof this;\n        `, \"object\")\n\t})\n}\n\nfunc TestWhile(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            limit = 4\n            abc = 0\n            while (limit) {\n                abc = abc + 1\n                limit = limit - 1\n            }\n            abc;\n        `, 4)\n\t})\n}\n\nfunc TestSwitch_break(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            var abc = true;\n            var ghi = \"Xyzzy\";\n            while (abc) {\n                switch ('def') {\n                case 'def':\n                    break;\n                }\n                ghi = \"Nothing happens.\";\n                abc = false;\n            }\n            ghi;\n        `, \"Nothing happens.\")\n\n\t\ttest(`\n            var abc = true;\n            var ghi = \"Xyzzy\";\n            WHILE:\n            while (abc) {\n                switch ('def') {\n                case 'def':\n                    break WHILE;\n                }\n                ghi = \"Nothing happens.\"\n                abc = false\n            }\n            ghi;\n        `, \"Xyzzy\")\n\n\t\ttest(`\n            var ghi = \"Xyzzy\";\n            FOR:\n            for (;;) {\n                switch ('def') {\n                case 'def':\n                    break FOR;\n                    ghi = \"\";\n                }\n                ghi = \"Nothing happens.\";\n            }\n            ghi;\n        `, \"Xyzzy\")\n\n\t\ttest(`\n            var ghi = \"Xyzzy\";\n            FOR:\n            for (var jkl in {}) {\n                switch ('def') {\n                case 'def':\n                    break FOR;\n                    ghi = \"Something happens.\";\n                }\n                ghi = \"Nothing happens.\";\n            }\n            ghi;\n        `, \"Xyzzy\")\n\n\t\ttest(`\n            var ghi = \"Xyzzy\";\n            function jkl() {\n                switch ('def') {\n                case 'def':\n                    break;\n                    ghi = \"\";\n                }\n                ghi = \"Nothing happens.\";\n            }\n            while (abc) {\n                jkl();\n                abc = false;\n                ghi = \"Something happens.\";\n            }\n            ghi;\n        `, \"Something happens.\")\n\t})\n}\n\nfunc TestTryFinally(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            var abc;\n            try {\n                abc = 1;\n            }\n            finally {\n                abc = 2;\n            }\n            abc;\n        `, 2)\n\n\t\ttest(`\n            var abc = false, def = 0;\n            do {\n                def += 1;\n                if (def > 100) {\n                    break;\n                }\n                try {\n                    continue;\n                }\n                finally {\n                    abc = true;\n                }\n            }\n            while(!abc && def < 10)\n            def;\n        `, 1)\n\n\t\ttest(`\n            var abc = false, def = 0, ghi = 0;\n            do {\n                def += 1;\n                if (def > 100) {\n                    break;\n                }\n                try {\n                    throw 0;\n                }\n                catch (jkl) {\n                    continue;\n                }\n                finally {\n                    abc = true;\n                    ghi = 11;\n                }\n                ghi -= 1;\n            }\n            while(!abc && def < 10)\n            ghi;\n        `, 11)\n\n\t\ttest(`\n            var abc = 0, def = 0;\n            do {\n                try {\n                    abc += 1;\n                    throw \"ghi\";\n                }\n                finally {\n                    def = 1;\n                    continue;\n                }\n                def -= 1;\n            }\n            while (abc < 2)\n            [ abc, def ];\n        `, \"2,1\")\n\t})\n}\n\nfunc TestTryCatch(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            var abc = 1;\n            try {\n                throw 4;\n                abc = -1;\n            }\n            catch (xyzzy) {\n                abc += xyzzy + 1;\n            }\n            abc;\n        `, 6)\n\n\t\ttest(`\n            abc = 1;\n            var def;\n            try {\n                try {\n                    throw 4;\n                    abc = -1;\n                }\n                catch (xyzzy) {\n                    abc += xyzzy + 1;\n                    throw 64;\n                }\n            }\n            catch (xyzzy) {\n                def = xyzzy;\n                abc = -2;\n            }\n            [ def, abc ];\n        `, \"64,-2\")\n\t})\n}\n\nfunc TestWith(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            var def;\n            with({ abc: 9 }) {\n                def = abc;\n            }\n            def;\n        `, 9)\n\n\t\ttest(`\n            var def;\n            with({ abc: function(){\n                return 11;\n            } }) {\n                def = abc();\n            }\n            def;\n        `, 11)\n\t})\n}\n\nfunc TestSwitch(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            var abc = 0;\n            switch (0) {\n            default:\n                abc += 1;\n            case 1:\n                abc += 2;\n            case 2:\n                abc += 4;\n            case 3:\n                abc += 8;\n            }\n            abc;\n        `, 15)\n\n\t\ttest(`\n            abc = 0;\n            switch (3) {\n            default:\n                abc += 1;\n            case 1:\n                abc += 2;\n            case 2:\n                abc += 4;\n            case 3:\n                abc += 8;\n            }\n            abc;\n        `, 8)\n\n\t\ttest(`\n            abc = 0;\n            switch (60) {\n            case 1:\n                abc += 2;\n            case 2:\n                abc += 4;\n            case 3:\n                abc += 8;\n            }\n            abc;\n        `, 0)\n\t})\n}\n\nfunc TestForIn(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            var abc;\n            for (property in { a: 1 }) {\n                abc = property;\n            }\n            abc;\n        `, \"a\")\n\n\t\ttest(`\n            var ghi;\n            for (property in new String(\"xyzzy\")) {\n                ghi = property;\n            }\n            ghi;\n        `, \"4\")\n\t})\n}\n\nfunc TestFor(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            var abc = 7;\n            for (i = 0; i < 3; i += 1) {\n                abc += 1;\n            }\n            abc;\n        `, 10)\n\n\t\ttest(`\n            abc = 7;\n            for (i = 0; i < 3; i += 1) {\n                abc += 1;\n                if (i == 1) {\n                    break;\n                }\n            }\n            abc;\n        `, 9)\n\n\t\ttest(`\n            abc = 7;\n            for (i = 0; i < 3; i += 1) {\n                if (i == 2) {\n                    continue;\n                }\n                abc += 1;\n            }\n            abc;\n        `, 9)\n\n\t\ttest(`\n            abc = 0;\n            for (;;) {\n                abc += 1;\n                if (abc == 3)\n                    break;\n            }\n            abc;\n        `, 3)\n\n\t\ttest(`\n            for (abc = 0; ;) {\n                abc += 1;\n                if (abc == 3)\n                    break;\n            }\n            abc;\n        `, 3)\n\n\t\ttest(`\n            for (abc = 0; ; abc += 1) {\n                abc += 1;\n                if (abc == 3)\n                    break;\n            }\n            abc;\n        `, 3)\n\t})\n}\n\nfunc TestLabelled(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\t// TODO Add emergency break\n\n\t\ttest(`\n            xyzzy: for (var abc = 0; abc <= 0; abc++) {\n                for (var def = 0; def <= 1; def++) {\n                    if (def === 0) {\n                        continue xyzzy;\n                    } else {\n                    }\n                }\n            }\n        `)\n\n\t\ttest(`\n            abc = 0\n            def:\n            while (true) {\n                while (true) {\n                    abc = abc + 1\n                    if (abc > 11) {\n                        break def;\n                    }\n                }\n            }\n            abc;\n        `, 12)\n\n\t\ttest(`\n            abc = 0\n            def:\n            do {\n                do {\n                    abc = abc + 1\n                    if (abc > 11) {\n                        break def;\n                    }\n                } while (true)\n            } while (true)\n            abc;\n        `, 12)\n\t})\n}\n\nfunc TestConditional(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            [ true ? false : true, true ? 1 : 0, false ? 3.14159 : \"abc\" ];\n        `, \"false,1,abc\")\n\t})\n}\n\nfunc TestArrayLiteral(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            [ 1, , 3.14159 ];\n        `, \"1,,3.14159\")\n\t})\n}\n\nfunc TestAssignment(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            var abc = 1;\n            abc;\n        `, 1)\n\n\t\ttest(`\n            abc += 2;\n            abc;\n        `, 3)\n\t})\n}\n\nfunc TestBinaryOperation(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`0 == 1`, false)\n\t\ttest(`1 == \"1\"`, true)\n\t\ttest(`0 === 1`, false)\n\t\ttest(`1 === \"1\"`, false)\n\t\ttest(`\"1\" === \"1\"`, true)\n\t})\n}\n\nfunc Test_typeof(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`typeof abc`, \"undefined\")\n\t\ttest(`typeof abc === 'undefined'`, true)\n\t\ttest(`typeof {}`, \"object\")\n\t\ttest(`typeof null`, \"object\")\n\t})\n}\n\nfunc Test_PrimitiveValueObjectValue(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\tNumber11 := test(`new Number(11)`)\n\t\tis(Number11.float64(), 11)\n\t})\n}\n\nfunc Test_eval(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\t// FIXME terst, Is this correct?\n\t\ttest(`\n            var abc = 1;\n        `, \"undefined\")\n\n\t\ttest(`\n            eval(\"abc += 1\");\n        `, 2)\n\n\t\ttest(`\n            (function(){\n                var abc = 11;\n                eval(\"abc += 1\");\n                return abc;\n            })();\n        `, 12)\n\t\ttest(`abc`, 2)\n\n\t\ttest(`\n            (function(){\n                try {\n                    eval(\"var prop = \\\\u2029;\");\n                    return false;\n                } catch (abc) {\n                    return [ abc instanceof SyntaxError, abc.toString() ];\n                }\n            })();\n        `, \"true,SyntaxError: (anonymous): Line 1:12 Unexpected token ILLEGAL (and 1 more errors)\")\n\n\t\ttest(`\n            function abc(){\n                this.THIS = eval(\"this\");\n            }\n            var def = new abc();\n            def === def.THIS;\n        `, true)\n\t})\n}\n\nfunc Test_evalDirectIndirect(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\t// (function () {return this;}()).abc = \"global\";\n\t\ttest(`\n            var abc = \"global\";\n            (function(){\n                try {\n                    var _eval = eval;\n                    var abc = \"function\";\n                    return [\n                        _eval(\"\\'global\\' === abc\"),  // eval (Indirect)\n                        eval(\"\\'function\\' === abc\"), // eval (Direct)\n                    ];\n                } finally {\n                    delete this.abc;\n                }\n            })();\n        `, \"true,true\")\n\t})\n}\n\nfunc TestError_URIError(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`new URIError() instanceof URIError`, true)\n\n\t\ttest(`\n            var abc\n            try {\n                decodeURI(\"http://example.com/ _^#%\")\n            }\n            catch (def) {\n                abc = def instanceof URIError\n            }\n            abc\n        `, true)\n\t})\n}\n\nfunc TestTo(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\t{\n\t\t\tvalue, _ := test(`\"11\"`).ToFloat()\n\t\t\tis(value, float64(11))\n\t\t}\n\n\t\t{\n\t\t\tvalue, _ := test(`\"11\"`).ToInteger()\n\t\t\tis(value, int64(11))\n\n\t\t\tvalue, _ = test(`1.1`).ToInteger()\n\t\t\tis(value, int64(1))\n\t\t}\n\t})\n}\n\nfunc TestShouldError(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`raise:\n            xyzzy\n                throw new TypeError(\"Nothing happens.\")\n        `, \"ReferenceError: 'xyzzy' is not defined\")\n\t})\n}\n\nfunc TestAPI(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, vm := test()\n\n\t\ttest(`\n            String.prototype.xyzzy = function(){\n                return this.length + 11 + (arguments[0] || 0)\n            }\n            abc = new String(\"xyzzy\")\n            def = \"Nothing happens.\"\n            abc.xyzzy()\n        `, 16)\n\t\tabc, _ := vm.Get(\"abc\")\n\t\tdef, _ := vm.Get(\"def\")\n\t\tobj := abc.Object()\n\t\tresult, _ := obj.Call(\"xyzzy\")\n\t\tis(result, 16)\n\t\tresult, _ = obj.Call(\"xyzzy\", 1)\n\t\tis(result, 17)\n\t\tvalue, _ := obj.Get(\"xyzzy\")\n\t\tresult, _ = value.Call(def)\n\t\tis(result, 27)\n\t\tresult, _ = value.Call(def, 3)\n\t\tis(result, 30)\n\t\tobj = value.Object() // Object xyzzy\n\t\tresult, _ = obj.Value().Call(def, 3)\n\t\tis(result, 30)\n\n\t\ttest(`\n            abc = {\n                'abc': 1,\n                'def': false,\n                3.14159: NaN,\n            };\n            abc['abc'];\n        `, 1)\n\t\tabc, err := vm.Get(\"abc\")\n\t\trequire.NoError(t, err)\n\t\tobj = abc.Object() // Object abc\n\t\tvalue, err = obj.Get(\"abc\")\n\t\trequire.NoError(t, err)\n\t\tis(value, 1)\n\t\tis(obj.Keys(), []string{\"abc\", \"def\", \"3.14159\"})\n\n\t\ttest(`\n            abc = [ 0, 1, 2, 3.14159, \"abc\", , ];\n            abc.def = true;\n        `)\n\t\tabc, err = vm.Get(\"abc\")\n\t\trequire.NoError(t, err)\n\t\tobj = abc.Object() // Object abc\n\t\tis(obj.Keys(), []string{\"0\", \"1\", \"2\", \"3\", \"4\", \"def\"})\n\t})\n}\n\nfunc TestObjectKeys(t *testing.T) {\n\ttt(t, func() {\n\t\tvm := New()\n\t\t_, err := vm.Eval(`var x = Object.create(null); x.a = 1`)\n\t\trequire.NoError(t, err)\n\t\t_, err = vm.Eval(`var y = Object.create(x); y.b = 2`)\n\t\trequire.NoError(t, err)\n\n\t\to1, err := vm.Object(\"x\")\n\t\trequire.NoError(t, err)\n\t\tis(o1.Keys(), []string{\"a\"})\n\t\tis(o1.KeysByParent(), [][]string{{\"a\"}})\n\n\t\to2, err := vm.Object(\"y\")\n\t\trequire.NoError(t, err)\n\t\tis(o2.Keys(), []string{\"b\"})\n\t\tis(o2.KeysByParent(), [][]string{{\"b\"}, {\"a\"}})\n\t})\n}\n\nfunc TestUnicode(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`var abc = eval(\"\\\"a\\uFFFFa\\\"\");`, \"undefined\")\n\n\t\ttest(`abc.length`, 3)\n\n\t\ttest(`abc != \"aa\"`, true)\n\n\t\ttest(\"abc[1] === \\\"\\uFFFF\\\"\", true)\n\t})\n}\n\nfunc TestDotMember(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            abc = {\n                ghi: 11,\n            }\n            abc.def = \"Xyzzy\"\n            abc.null = \"Nothing happens.\"\n        `)\n\t\ttest(`abc.def`, \"Xyzzy\")\n\t\ttest(`abc.null`, \"Nothing happens.\")\n\t\ttest(`abc.ghi`, 11)\n\n\t\ttest(`\n            abc = {\n                null: 11,\n            }\n        `)\n\t\ttest(`abc.def`, \"undefined\")\n\t\ttest(`abc.null`, 11)\n\t\ttest(`abc.ghi`, \"undefined\")\n\t})\n}\n\nfunc Test_stringToFloat(t *testing.T) {\n\ttt(t, func() {\n\t\tis(parseNumber(\"10e10000\"), infinity)\n\t\tis(parseNumber(\"10e10_.\"), naN)\n\t})\n}\n\nfunc Test_delete(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            delete 42;\n        `, true)\n\n\t\ttest(`\n            var abc = delete $_undefined_$;\n            abc = abc && delete ($_undefined_$);\n            abc;\n        `, true)\n\n\t\t// delete should not trigger get()\n\t\ttest(`\n            var abc = {\n                get def() {\n                    throw \"Test_delete: delete should not trigger get()\"\n                }\n            };\n            delete abc.def\n        `, true)\n\t})\n}\n\nfunc TestObject_defineOwnProperty(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            var object = {};\n\n            var descriptor = new Boolean(false);\n            descriptor.configurable = true;\n\n            Object.defineProperties(object, {\n                property: descriptor\n            });\n\n            var abc = object.hasOwnProperty(\"property\");\n            delete object.property;\n            var def = object.hasOwnProperty(\"property\");\n\n            [ abc, def ];\n        `, \"true,false\")\n\n\t\ttest(`\n            var object = [0, 1, 2];\n            Object.defineProperty(object, \"0\", {\n                value: 42,\n                writable: false,\n                enumerable: false,\n                configurable: false\n            });\n            var abc = Object.getOwnPropertyDescriptor(object, \"0\");\n            [ abc.value, abc.writable, abc.enumerable, abc.configurable ];\n        `, \"42,false,false,false\")\n\n\t\ttest(`\n            var abc = { \"xyzzy\": 42 };\n            var def = Object.defineProperties(abc, \"\");\n            abc === def;\n        `, true)\n\t})\n}\n\nfunc Test_assignmentEvaluationOrder(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            var abc = 0;\n            ((abc = 1) & abc);\n        `, 1)\n\n\t\ttest(`\n            var abc = 0;\n            (abc & (abc = 1));\n        `, 0)\n\t})\n}\n\nfunc TestOttoCall(t *testing.T) {\n\ttt(t, func() {\n\t\tvm := New()\n\n\t\t_, err := vm.Run(`\n            var abc = {\n                ghi: 1,\n                def: function(def){\n                    var ghi = 0;\n                    if (this.ghi) {\n                        ghi = this.ghi;\n                    }\n                    return \"def: \" + (def + 3.14159 + ghi);\n                }\n            };\n            function structFunc(s) {\n                return s.Val;\n            }\n        `)\n\t\trequire.NoError(t, err)\n\n\t\tvalue, err := vm.Call(`abc.def`, nil, 2)\n\t\trequire.NoError(t, err)\n\t\tis(value, \"def: 6.14159\")\n\n\t\tvalue, err = vm.Call(`abc.def`, \"\", 2)\n\t\trequire.NoError(t, err)\n\t\tis(value, \"def: 5.14159\")\n\n\t\t// Do not attempt to do a ToValue on a this of nil\n\t\tvalue, err = vm.Call(`jkl.def`, nil, 1, 2, 3)\n\t\tis(err, \"!=\", nil)\n\t\tis(value, \"undefined\")\n\n\t\tvalue, err = vm.Call(`[ 1, 2, 3, undefined, 4 ].concat`, nil, 5, 6, 7, \"abc\")\n\t\trequire.NoError(t, err)\n\t\tis(value, \"1,2,3,,4,5,6,7,abc\")\n\n\t\ts := struct{ Val int }{Val: 10}\n\t\tvalue, err = vm.Call(\"structFunc\", nil, s)\n\t\trequire.NoError(t, err)\n\t\tis(value, 10)\n\t})\n}\n\nfunc TestOttoCall_new(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, vm := test()\n\n\t\tvm.Set(\"abc\", func(call FunctionCall) Value {\n\t\t\tvalue, err := call.Otto.Call(`new Object`, nil, \"Nothing happens.\")\n\t\t\trequire.NoError(t, err)\n\t\t\treturn value\n\t\t})\n\t\ttest(`\n            def = abc();\n            [ def, def instanceof String ];\n        `, \"Nothing happens.,true\")\n\t})\n}\n\nfunc TestOttoCall_newWithBrackets(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, vm := test()\n\n\t\t_, err := vm.Run(`var a = {default: function B(x) { this.x = x; } }`)\n\t\trequire.NoError(t, err)\n\n\t\ttest(`(new a['default'](1)).x`, 1)\n\t})\n}\n\nfunc TestOttoCall_throw(t *testing.T) {\n\t// FIXME? (Been broken for a while)\n\t// Looks like this has been broken for a while... what\n\t// behavior do we want here?\n\n\tif true {\n\t\treturn\n\t}\n\n\ttt(t, func() {\n\t\ttest, vm := test()\n\n\t\tvm.Set(\"abc\", func(call FunctionCall) Value {\n\t\t\tif false {\n\t\t\t\t_, err := call.Otto.Call(`throw eval`, nil, \"({ def: 3.14159 })\")\n\t\t\t\trequire.NoError(t, err)\n\t\t\t}\n\t\t\t_, err := call.Otto.Call(`throw Error`, nil, \"abcdef\")\n\t\t\trequire.NoError(t, err)\n\t\t\treturn Value{}\n\t\t})\n\t\t// TODO try { abc(); } catch (err) { error = err }\n\t\t// Possible unrelated error case:\n\t\t// If error is not declared beforehand, is later referencing it a ReferenceError?\n\t\t// Should the catch { } declare error in the outer scope?\n\t\ttest(`\n            var error;\n            try {\n                abc();\n            }\n            catch (err) {\n                error = err;\n            }\n            [ error instanceof Error, error.message, error.def ];\n        `, \"true,abcdef,\")\n\n\t\tvm.Set(\"def\", func(call FunctionCall) Value {\n\t\t\t_, err := call.Otto.Call(`throw new Object`, nil, 3.14159)\n\t\t\trequire.NoError(t, err)\n\t\t\treturn UndefinedValue()\n\t\t})\n\t\ttest(`\n            try {\n                def();\n            }\n            catch (err) {\n                error = err;\n            }\n            [ error instanceof Error, error.message, error.def, typeof error, error, error instanceof Number ];\n        `, \"false,,,object,3.14159,true\")\n\t})\n}\n\nfunc TestOttoCopy(t *testing.T) {\n\ttt(t, func() {\n\t\tvm0 := New()\n\t\t_, err := vm0.Run(`\n            var abc = function() {\n                return \"Xyzzy\";\n            };\n\n            function def() {\n                return abc() + (0 + {});\n            }\n        `)\n\t\trequire.NoError(t, err)\n\n\t\tvalue, err := vm0.Run(`\n            def();\n        `)\n\t\trequire.NoError(t, err)\n\t\tis(value, \"Xyzzy0[object Object]\")\n\n\t\tvm1 := vm0.Copy()\n\t\tvalue, err = vm1.Run(`\n            def();\n        `)\n\t\trequire.NoError(t, err)\n\t\tis(value, \"Xyzzy0[object Object]\")\n\n\t\t_, err = vm1.Run(`\n            abc = function() {\n                return 3.14159;\n            };\n        `)\n\t\trequire.NoError(t, err)\n\t\tvalue, err = vm1.Run(`\n            def();\n        `)\n\t\trequire.NoError(t, err)\n\t\tis(value, \"3.141590[object Object]\")\n\n\t\tvalue, err = vm0.Run(`\n            def();\n        `)\n\t\trequire.NoError(t, err)\n\t\tis(value, \"Xyzzy0[object Object]\")\n\n\t\t{\n\t\t\tvm01 := New()\n\t\t\t_, err2 := vm01.Run(`\n                var global = (function () {return this;}())\n                var abc = 0;\n                var vm = \"vm0\";\n\n                var def = (function(){\n                    var jkl = 0;\n                    var abc = function() {\n                        global.abc += 1;\n                        jkl += 1;\n                        return 1;\n                    };\n\n                    return function() {\n                        return [ vm, global.abc, jkl, abc() ];\n                    };\n                })();\n            `)\n\t\t\trequire.NoError(t, err2)\n\n\t\t\tvalue2, err2 := vm01.Run(`\n                def();\n            `)\n\t\t\trequire.NoError(t, err2)\n\t\t\tis(value2, \"vm0,0,0,1\")\n\n\t\t\tvm11 := vm01.Copy()\n\t\t\terr2 = vm11.Set(\"vm\", \"vm1\")\n\t\t\trequire.NoError(t, err2)\n\t\t\tvalue2, err2 = vm11.Run(`\n                def();\n            `)\n\t\t\trequire.NoError(t, err2)\n\t\t\tis(value2, \"vm1,1,1,1\")\n\n\t\t\tvalue2, err2 = vm01.Run(`\n                def();\n            `)\n\t\t\trequire.NoError(t, err2)\n\t\t\tis(value2, \"vm0,1,1,1\")\n\n\t\t\tvalue2, err2 = vm11.Run(`\n                def();\n            `)\n\t\t\trequire.NoError(t, err2)\n\t\t\tis(value2, \"vm1,2,2,1\")\n\t\t}\n\t})\n}\n\nfunc TestOttoCall_clone(t *testing.T) {\n\ttt(t, func() {\n\t\tvm := New().clone()\n\t\trt := vm.runtime\n\n\t\t{\n\t\t\t// FIXME terst, Check how this comparison is done\n\t\t\tis(rt.global.Array.prototype, rt.global.FunctionPrototype)\n\t\t\tis(rt.global.ArrayPrototype, \"!=\", nil)\n\t\t\tis(rt.global.Array.runtime, rt)\n\t\t\tis(rt.global.Array.prototype.runtime, rt)\n\t\t\tis(rt.global.Array.get(\"prototype\").object().runtime, rt)\n\t\t}\n\n\t\t{\n\t\t\tvalue, err := vm.Run(`[ 1, 2, 3 ].toString()`)\n\t\t\trequire.NoError(t, err)\n\t\t\tis(value, \"1,2,3\")\n\t\t}\n\n\t\t{\n\t\t\tvalue, err := vm.Run(`[ 1, 2, 3 ]`)\n\t\t\trequire.NoError(t, err)\n\t\t\tis(value, \"1,2,3\")\n\t\t\tobj := value.object()\n\t\t\tis(obj, \"!=\", nil)\n\t\t\tis(obj.prototype, rt.global.ArrayPrototype)\n\n\t\t\tvalue, err = vm.Run(`Array.prototype`)\n\t\t\trequire.NoError(t, err)\n\t\t\tobj = value.object()\n\t\t\tis(obj.runtime, rt)\n\t\t\tis(obj, \"!=\", nil)\n\t\t\tis(obj, rt.global.ArrayPrototype)\n\t\t}\n\n\t\t{\n\t\t\totto1 := New()\n\t\t\t_, err := otto1.Run(`\n                var abc = 1;\n                var def = 2;\n            `)\n\t\t\trequire.NoError(t, err)\n\n\t\t\totto2 := otto1.clone()\n\t\t\tvalue, err := otto2.Run(`abc += 1; abc;`)\n\t\t\trequire.NoError(t, err)\n\t\t\tis(value, 2)\n\n\t\t\tvalue, err = otto1.Run(`abc += 4; abc;`)\n\t\t\trequire.NoError(t, err)\n\t\t\tis(value, 5)\n\t\t}\n\n\t\t{\n\t\t\tvm1 := New()\n\t\t\t_, err := vm1.Run(`\n                var abc = 1;\n                var def = function(value) {\n                    abc += value;\n                    return abc;\n                }\n            `)\n\t\t\trequire.NoError(t, err)\n\n\t\t\tvm2 := vm1.clone()\n\t\t\tvalue, err := vm2.Run(`def(1)`)\n\t\t\trequire.NoError(t, err)\n\t\t\tis(value, 2)\n\n\t\t\tvalue, err = vm1.Run(`def(4)`)\n\t\t\trequire.NoError(t, err)\n\t\t\tis(value, 5)\n\t\t}\n\n\t\t{\n\t\t\tvm1 := New()\n\t\t\t_, err := vm1.Run(`\n                var abc = {\n                    ghi: 1,\n                    jkl: function(value) {\n                        this.ghi += value;\n                        return this.ghi;\n                    }\n                };\n                var def = {\n                    abc: abc\n                };\n            `)\n\t\t\trequire.NoError(t, err)\n\n\t\t\totto2 := vm1.clone()\n\t\t\tvalue, err := otto2.Run(`def.abc.jkl(1)`)\n\t\t\trequire.NoError(t, err)\n\t\t\tis(value, 2)\n\n\t\t\tvalue, err = vm1.Run(`def.abc.jkl(4)`)\n\t\t\trequire.NoError(t, err)\n\t\t\tis(value, 5)\n\t\t}\n\n\t\t{\n\t\t\tvm1 := New()\n\t\t\t_, err := vm1.Run(`\n                var abc = function() { return \"abc\"; };\n                var def = function() { return \"def\"; };\n            `)\n\t\t\trequire.NoError(t, err)\n\n\t\t\tvm2 := vm1.clone()\n\t\t\tvalue, err := vm2.Run(`\n                [ abc.toString(), def.toString() ];\n            `)\n\t\t\trequire.NoError(t, err)\n\t\t\tis(value, `function() { return \"abc\"; },function() { return \"def\"; }`)\n\n\t\t\t_, err = vm2.Run(`\n                var def = function() { return \"ghi\"; };\n            `)\n\t\t\trequire.NoError(t, err)\n\n\t\t\tvalue, err = vm1.Run(`\n                [ abc.toString(), def.toString() ];\n            `)\n\t\t\trequire.NoError(t, err)\n\t\t\tis(value, `function() { return \"abc\"; },function() { return \"def\"; }`)\n\n\t\t\tvalue, err = vm2.Run(`\n                [ abc.toString(), def.toString() ];\n            `)\n\t\t\trequire.NoError(t, err)\n\t\t\tis(value, `function() { return \"abc\"; },function() { return \"ghi\"; }`)\n\t\t}\n\t})\n}\n\nfunc TestOttoRun(t *testing.T) {\n\ttt(t, func() {\n\t\tvm := New()\n\n\t\tprogram, err := parser.ParseFile(nil, \"\", \"\", 0)\n\t\trequire.NoError(t, err)\n\t\tvalue, err := vm.Run(program)\n\t\trequire.NoError(t, err)\n\t\tis(value, UndefinedValue())\n\n\t\tprogram, err = parser.ParseFile(nil, \"\", \"2 + 2\", 0)\n\t\trequire.NoError(t, err)\n\t\tvalue, err = vm.Run(program)\n\t\trequire.NoError(t, err)\n\t\tis(value, 4)\n\t\tvalue, err = vm.Run(program)\n\t\trequire.NoError(t, err)\n\t\tis(value, 4)\n\n\t\tprogram, err = parser.ParseFile(nil, \"\", \"var abc; if (!abc) abc = 0; abc += 2; abc;\", 0)\n\t\trequire.NoError(t, err)\n\t\tvalue, err = vm.Run(program)\n\t\trequire.NoError(t, err)\n\t\tis(value, 2)\n\t\tvalue, err = vm.Run(program)\n\t\trequire.NoError(t, err)\n\t\tis(value, 4)\n\t\tvalue, err = vm.Run(program)\n\t\trequire.NoError(t, err)\n\t\tis(value, 6)\n\n\t\t{\n\t\t\tsrc := []byte(\"var abc; if (!abc) abc = 0; abc += 2; abc;\")\n\t\t\tvalue, err = vm.Run(src)\n\t\t\trequire.NoError(t, err)\n\t\t\tis(value, 8)\n\n\t\t\tvalue, err = vm.Run(bytes.NewBuffer(src))\n\t\t\trequire.NoError(t, err)\n\t\t\tis(value, 10)\n\n\t\t\tvalue, err = vm.Run(io.Reader(bytes.NewBuffer(src)))\n\t\t\trequire.NoError(t, err)\n\t\t\tis(value, 12)\n\t\t}\n\n\t\t{\n\t\t\tscript, err2 := vm.Compile(\"\", `var abc; if (!abc) abc = 0; abc += 2; abc;`)\n\t\t\trequire.NoError(t, err2)\n\n\t\t\tvalue, err2 = vm.Run(script)\n\t\t\trequire.NoError(t, err2)\n\t\t\tis(value, 14)\n\n\t\t\tvalue, err2 = vm.Run(script)\n\t\t\trequire.NoError(t, err2)\n\t\t\tis(value, 16)\n\n\t\t\tis(script.String(), \"// \\nvar abc; if (!abc) abc = 0; abc += 2; abc;\")\n\t\t}\n\t})\n}\n\n// This generates functions to be used by the test below. The arguments are\n// `src`, which is something that otto can execute, and `expected`, which is\n// what the result of executing `src` should be.\nfunc makeTestOttoEvalFunction(t *testing.T, src, expected interface{}) func(c FunctionCall) Value {\n\tt.Helper()\n\treturn func(c FunctionCall) Value {\n\t\tv, err := c.Otto.Eval(src)\n\t\trequire.NoError(t, err)\n\n\t\ti, err := v.Export()\n\t\trequire.NoError(t, err)\n\n\t\tis(i, expected)\n\n\t\treturn v\n\t}\n}\n\nfunc TestOttoEval(t *testing.T) {\n\ttt(t, func() {\n\t\tvm := New()\n\n\t\terr := vm.Set(\"x1\", makeTestOttoEvalFunction(t, `a`, 1))\n\t\trequire.NoError(t, err)\n\t\terr = vm.Set(\"y1\", makeTestOttoEvalFunction(t, `b`, \"hello\"))\n\t\trequire.NoError(t, err)\n\t\terr = vm.Set(\"z1\", makeTestOttoEvalFunction(t, `c`, true))\n\t\trequire.NoError(t, err)\n\t\terr = vm.Set(\"w\", makeTestOttoEvalFunction(t, `a = 2; b = 'what'; c = false; null`, nil))\n\t\trequire.NoError(t, err)\n\t\terr = vm.Set(\"x2\", makeTestOttoEvalFunction(t, `a`, 2))\n\t\trequire.NoError(t, err)\n\t\terr = vm.Set(\"y2\", makeTestOttoEvalFunction(t, `b`, \"what\"))\n\t\trequire.NoError(t, err)\n\t\terr = vm.Set(\"z2\", makeTestOttoEvalFunction(t, `c`, false))\n\t\trequire.NoError(t, err)\n\n\t\t// note that these variables are defined in the scope of function `t`,\n\t\t// so would not usually be available to the functions called below.\n\t\t//\n\t\t// this is _not_ the recommended use case for `Eval` - instead it's\n\t\t// intended to be used in `debugger` handlers. this code here is the\n\t\t// equivalent of reading behind the current stack frame in C...\n\t\t// technically valid, but completely insane.\n\t\t//\n\t\t// makes for a good test case though.\n\t\t_, err = vm.Run(`(function t() {\n            var a = 1;\n            var b = 'hello';\n            var c = true;\n\n            x1();\n            y1();\n            z1();\n            w();\n            x2();\n            y2();\n            z2();\n        }())`)\n\t\trequire.NoError(t, err)\n\t})\n\n\t// this test makes sure that `Eval` doesn't explode if the VM doesn't have\n\t// a scope other than global defined.\n\ttt(t, func() {\n\t\tvm := New()\n\n\t\t_, err := vm.Eval(\"null\")\n\t\trequire.NoError(t, err)\n\n\t\terr = vm.Set(\"a\", 1)\n\t\trequire.NoError(t, err)\n\t\terr = vm.Set(\"b\", 2)\n\t\trequire.NoError(t, err)\n\n\t\tv, err := vm.Eval(\"a + b\")\n\t\trequire.NoError(t, err)\n\t\tr, err := v.Export()\n\t\trequire.NoError(t, err)\n\t\tis(r, 3)\n\t})\n}\n\nfunc TestOttoContext(t *testing.T) {\n\t// These are all the builtin global scope symbols\n\tbuiltins := []string{\n\t\t\"escape\",\n\t\t\"URIError\",\n\t\tclassRegExpName,\n\t\t\"ReferenceError\",\n\t\t\"parseFloat\",\n\t\t\"parseInt\",\n\t\t\"SyntaxError\",\n\t\t\"decodeURIComponent\",\n\t\t\"encodeURIComponent\",\n\t\t\"Infinity\",\n\t\t\"JSON\",\n\t\t\"isNaN\",\n\t\t\"unescape\",\n\t\t\"decodeURI\",\n\t\tclassObjectName,\n\t\tclassFunctionName,\n\t\t\"RangeError\",\n\t\tclassErrorName,\n\t\t\"get_context\",\n\t\t\"eval\",\n\t\tclassNumberName,\n\t\t\"Math\",\n\t\t\"NaN\",\n\t\tclassDateName,\n\t\tclassBooleanName,\n\t\t\"console\",\n\t\t\"encodeURI\",\n\t\t\"EvalError\",\n\t\tclassArrayName,\n\t\t\"TypeError\",\n\t\tclassStringName,\n\t\t\"isFinite\",\n\t\t\"undefined\",\n\t}\n\n\ttt(t, func() {\n\t\tvm := New()\n\n\t\terr := vm.Set(\"get_context\", func(c FunctionCall) Value {\n\t\t\tctx := c.Otto.Context()\n\t\t\tis(ctx.Callee, \"f1\")\n\t\t\tis(ctx.Filename, \"<anonymous>\")\n\t\t\tis(ctx.Line, 8)\n\t\t\tis(ctx.Column, 5)\n\t\t\tis(ctx.Stacktrace, []string{\n\t\t\t\t\"f1 (<anonymous>:8:5)\",\n\t\t\t\t\"f2 (<anonymous>:15:5)\",\n\t\t\t\t\"f3 (<anonymous>:19:5)\",\n\t\t\t\t\"t (<anonymous>:22:4)\",\n\t\t\t})\n\t\t\tis(len(ctx.Symbols), 9+len(builtins))\n\t\t\tis(ctx.Symbols[\"a\"], 1)\n\t\t\tis(ctx.Symbols[\"b\"], \"hello\")\n\t\t\tis(ctx.Symbols[\"c\"], true)\n\t\t\tis(ctx.Symbols[\"j\"], 2)\n\t\t\tis(ctx.Symbols[\"f1\"].IsFunction(), true)\n\t\t\tis(ctx.Symbols[\"f2\"].IsFunction(), true)\n\t\t\tis(ctx.Symbols[\"f3\"].IsFunction(), true)\n\t\t\tis(ctx.Symbols[\"t\"].IsFunction(), true)\n\t\t\tcallee, _ := ctx.Symbols[\"arguments\"].Object().Get(\"callee\")\n\t\t\tis(callee.IsDefined(), true)\n\n\t\t\treturn Value{}\n\t\t})\n\t\trequire.NoError(t, err)\n\n\t\t_, err = vm.Run(`(function t() {\n\t\t\tvar a = 1;\n\t\t\tvar b = 'hello';\n\t\t\tvar c = true;\n\n\t\t\tfunction f1() {\n\t\t\t\tvar j = 2;\n\t\t\t\tget_context();\n\t\t\t\t(function() {\n\t\t\t\t\tvar d = 4;\n\t\t\t\t})()\n\t\t\t}\n\n\t\t\tfunction f2() {\n\t\t\t\tf1();\n\t\t\t}\n\n\t\t\tfunction f3() {\n\t\t\t\tf2();\n\t\t\t}\n\n\t\t\tf3();\n\n\t\t\ta = 2;\n\t\t\tb = 'goodbye';\n\t\t\tc = false;\n\t\t}())`)\n\n\t\trequire.NoError(t, err)\n\t})\n\n\t// this test makes sure that `Context` works on global scope by default, if\n\t// there is not a current scope.\n\ttt(t, func() {\n\t\tvm := New()\n\n\t\terr := vm.Set(\"get_context\", func(c FunctionCall) Value {\n\t\t\tctx := c.Otto.Context()\n\t\t\tis(ctx.Callee, \"\")\n\t\t\tis(ctx.Filename, \"<anonymous>\")\n\t\t\tis(ctx.Line, 3)\n\t\t\tis(ctx.Column, 4)\n\t\t\tis(ctx.Stacktrace, []string{\"<anonymous>:3:4\"})\n\t\t\tis(len(ctx.Symbols), 2+len(builtins))\n\t\t\tis(ctx.Symbols[\"a\"], 1)\n\t\t\tis(ctx.Symbols[\"b\"], UndefinedValue())\n\n\t\t\treturn Value{}\n\t\t})\n\t\trequire.NoError(t, err)\n\n\t\t_, err = vm.Run(`\n\t\t\tvar a = 1;\n\t\t\tget_context()\n\t\t\tvar b = 2;\n\t\t`)\n\t\trequire.NoError(t, err)\n\t})\n\n\t// this test makes sure variables are shadowed correctly.\n\ttt(t, func() {\n\t\tvm := New()\n\n\t\terr := vm.Set(\"check_context\", func(c FunctionCall) Value {\n\t\t\tn, err := c.Argument(0).ToInteger()\n\t\t\trequire.NoError(t, err)\n\n\t\t\tctx := c.Otto.Context()\n\t\t\tis(ctx.Symbols[\"a\"], n)\n\n\t\t\treturn Value{}\n\t\t})\n\t\trequire.NoError(t, err)\n\n\t\t_, err = vm.Run(`\n            var a = 1;\n            check_context(1);\n            (function() {\n                var a = 2;\n                check_context(2);\n            }());\n            (function(a) {\n                check_context(3);\n            }(3));\n            (function(a) {\n                check_context(4);\n            }).call(null, 4);\n            check_context(1);\n        `)\n\t\trequire.NoError(t, err)\n\t})\n}\n\nfunc Test_objectLength(t *testing.T) {\n\ttt(t, func() {\n\t\t_, vm := test()\n\n\t\tvalue := vm.Set(\"abc\", []string{\"jkl\", \"mno\"})\n\t\tis(objectLength(value.object()), 2)\n\n\t\tvalue, _ = vm.Run(`[1, 2, 3]`)\n\t\tis(objectLength(value.object()), 3)\n\n\t\tvalue, _ = vm.Run(`new String(\"abcdefghi\")`)\n\t\tis(objectLength(value.object()), 9)\n\n\t\tvalue, _ = vm.Run(`\"abcdefghi\"`)\n\t\tis(objectLength(value.object()), 0)\n\t})\n}\n\nfunc Test_stackLimit(t *testing.T) {\n\t// JavaScript stack depth before entering `a` is 5; becomes 6 after\n\t// entering. setting the maximum stack depth to 5 should result in an\n\t// error ocurring at that 5 -> 6 boundary.\n\tcode := `\n        function a() {}\n        function b() { a(); }\n        function c() { b(); }\n        function d() { c(); }\n        function e() { d(); }\n        e();\n    `\n\n\t// has no error\n\ttt(t, func() {\n\t\t_, vm := test()\n\n\t\t_, err := vm.Run(code)\n\t\trequire.NoError(t, err)\n\t})\n\n\t// has error\n\ttt(t, func() {\n\t\t_, vm := test()\n\n\t\tvm.vm.SetStackDepthLimit(2)\n\n\t\t_, err := vm.Run(code)\n\t\trequire.Error(t, err)\n\t})\n\n\t// has error\n\ttt(t, func() {\n\t\t_, vm := test()\n\n\t\tvm.vm.SetStackDepthLimit(5)\n\n\t\t_, err := vm.Run(code)\n\t\trequire.Error(t, err)\n\t})\n\n\t// has no error\n\ttt(t, func() {\n\t\t_, vm := test()\n\n\t\tvm.vm.SetStackDepthLimit(6)\n\n\t\t_, err := vm.Run(code)\n\t\trequire.NoError(t, err)\n\t})\n\n\t// has no error\n\ttt(t, func() {\n\t\t_, vm := test()\n\n\t\tvm.vm.SetStackDepthLimit(1)\n\t\tvm.vm.SetStackDepthLimit(0)\n\n\t\t_, err := vm.Run(code)\n\t\trequire.NoError(t, err)\n\t})\n}\n\nfunc TestOttoInterrupt(t *testing.T) {\n\ttests := []struct {\n\t\tname   string\n\t\tscript string\n\t}{\n\t\t{\n\t\t\tname:   \"empty-for-loop\",\n\t\t\tscript: \"for(;;) {}\",\n\t\t},\n\t\t{\n\t\t\tname:   \"empty-do-while\",\n\t\t\tscript: \"do{} while(true)\",\n\t\t},\n\t}\n\n\thalt := errors.New(\"interrupt\")\n\tfor _, tc := range tests {\n\t\tt.Run(tc.name, func(t *testing.T) {\n\t\t\tvm := New()\n\t\t\tvm.Interrupt = make(chan func(), 1)\n\t\t\tec := make(chan error, 1)\n\t\t\tgo func() {\n\t\t\t\tdefer func() {\n\t\t\t\t\tif caught := recover(); caught != nil {\n\t\t\t\t\t\tif caught == halt { //nolint:errorlint\n\t\t\t\t\t\t\tec <- nil\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t}\n\t\t\t\t\t\tpanic(caught)\n\t\t\t\t\t}\n\t\t\t\t}()\n\t\t\t\t_, err := vm.Run(tc.script)\n\t\t\t\tec <- err\n\t\t\t}()\n\n\t\t\t// Give the vm chance to execute the loop.\n\t\t\ttime.Sleep(time.Millisecond * 100)\n\t\t\tvm.Interrupt <- func() { panic(halt) }\n\n\t\t\tselect {\n\t\t\tcase <-time.After(time.Second):\n\t\t\t\tt.Fatal(\"timeout\")\n\t\t\tcase err := <-ec:\n\t\t\t\trequire.NoError(t, err)\n\t\t\t}\n\t\t})\n\t}\n}\n\nfunc BenchmarkNew(b *testing.B) {\n\tfor i := 0; i < b.N; i++ {\n\t\tNew()\n\t}\n}\n\nfunc BenchmarkClone(b *testing.B) {\n\tvm := New()\n\tb.ResetTimer()\n\tfor i := 0; i < b.N; i++ {\n\t\tvm.clone()\n\t}\n}\n"
  },
  {
    "path": "panic_test.go",
    "content": "package otto\n\nimport (\n\t\"testing\"\n)\n\nfunc Test_panic(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\t// Test that property.value is set to something if writable is set\n\t\t// to something\n\t\ttest(`\n            var abc = [];\n            Object.defineProperty(abc, \"0\", { writable: false });\n            Object.defineProperty(abc, \"0\", { writable: false });\n            \"0\" in abc;\n        `, true)\n\n\t\ttest(`raise:\n            var abc = [];\n            Object.defineProperty(abc, \"0\", { writable: false });\n            Object.defineProperty(abc, \"0\", { value: false, writable: false });\n        `, \"TypeError: Array.DefineOwnProperty Object.DefineOwnProperty failed\")\n\n\t\t// Test that a regular expression can contain \\c0410 (CYRILLIC CAPITAL LETTER A)\n\t\t// without panicking\n\t\ttest(`\n            var abc = 0x0410;\n            var def = String.fromCharCode(abc);\n            new RegExp(\"\\\\c\" + def).exec(def);\n        `, \"null\")\n\n\t\t// Test transforming a transformable regular expression without a panic\n\t\ttest(`\n\t\t    new RegExp(\"\\\\u0000\");\n            new RegExp(\"\\\\undefined\").test(\"undefined\");\n        `, true)\n\t})\n}\n"
  },
  {
    "path": "parser/comments_test.go",
    "content": "package parser\n\nimport (\n\t\"fmt\"\n\t\"reflect\"\n\t\"testing\"\n\n\t\"github.com/robertkrimen/otto/ast\"\n)\n\nfunc checkComments(actual []*ast.Comment, expected []string, position ast.CommentPosition) error {\n\tvar comments []*ast.Comment\n\tfor _, c := range actual {\n\t\tif c.Position == position {\n\t\t\tcomments = append(comments, c)\n\t\t}\n\t}\n\n\tif len(comments) != len(expected) {\n\t\treturn fmt.Errorf(\"the number of comments is not correct. %v != %v\", len(comments), len(expected))\n\t}\n\n\tfor i, v := range comments {\n\t\tif v.Text != expected[i] {\n\t\t\treturn fmt.Errorf(\"comments do not match: %q != %q\", v.Text, expected[i])\n\t\t}\n\t\tif v.Position != position {\n\t\t\treturn fmt.Errorf(\"comment positions do not match: %d != %d\", position, v.Position)\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc displayComments(m ast.CommentMap) {\n\tfmt.Printf(\"Displaying comments:\\n\") //nolint:forbidigo\n\tfor n, comments := range m {\n\t\tfmt.Printf(\"%v %v:\\n\", reflect.TypeOf(n), n) //nolint:forbidigo\n\t\tfor i, comment := range comments {\n\t\t\tfmt.Printf(\" [%v] %v @ %v\\n\", i, comment.Text, comment.Position) //nolint:forbidigo\n\t\t}\n\t}\n}\n\nfunc TestParser_comments(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := func(source string, chk interface{}) (*parser, *ast.Program) {\n\t\t\tparser, program, err := testParseWithMode(source, StoreComments)\n\t\t\tis(firstErr(err), chk)\n\n\t\t\t// Check unresolved comments\n\n\t\t\treturn parser, program\n\t\t}\n\n\t\tvar err error\n\t\tvar p *parser\n\t\tvar program *ast.Program\n\n\t\tp, program = test(\"q=2;// Hej\\nv = 0\", nil)\n\t\tis(len(program.Body), 2)\n\t\terr = checkComments((p.comments.CommentMap)[program.Body[1]], []string{\" Hej\"}, ast.LEADING)\n\t\tis(err, nil)\n\n\t\t// Assignment\n\t\tp, program = test(\"i = /*test=*/ 2\", nil)\n\t\tis(len(program.Body), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0]], []string{}, ast.LEADING), nil)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.AssignExpression).Right], []string{\"test=\"}, ast.LEADING), nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// Conditional, before consequent\n\t\tp, program = test(\"i ? /*test?*/ 2 : 3\", nil)\n\t\tis(len(program.Body), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0]], []string{}, ast.LEADING), nil)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.ConditionalExpression).Consequent], []string{\"test?\"}, ast.LEADING), nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// Conditional, after consequent\n\t\tp, program = test(\"i ? 2 /*test?*/ : 3\", nil)\n\t\tis(len(program.Body), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0]], []string{}, ast.LEADING), nil)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.ConditionalExpression).Consequent], []string{\"test?\"}, ast.TRAILING), nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// Conditional, before alternate\n\t\tp, program = test(\"i ? 2 : /*test:*/ 3\", nil)\n\t\tis(len(program.Body), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0]], []string{}, ast.LEADING), nil)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.ConditionalExpression).Alternate], []string{\"test:\"}, ast.LEADING), nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// Logical OR\n\t\tp, program = test(\"i || /*test||*/ 2\", nil)\n\t\tis(len(program.Body), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0]], []string{}, ast.LEADING), nil)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.BinaryExpression).Right], []string{\"test||\"}, ast.LEADING), nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// Logical AND\n\t\tp, program = test(\"i && /*test&&*/ 2\", nil)\n\t\tis(len(program.Body), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0]], []string{}, ast.LEADING), nil)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.BinaryExpression).Right], []string{\"test&&\"}, ast.LEADING), nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// Bitwise OR\n\t\tp, program = test(\"i | /*test|*/ 2\", nil)\n\t\tis(len(program.Body), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0]], []string{}, ast.LEADING), nil)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.BinaryExpression).Right], []string{\"test|\"}, ast.LEADING), nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// Exclusive OR\n\t\tp, program = test(\"i ^ /*test^*/ 2\", nil)\n\t\tis(len(program.Body), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0]], []string{}, ast.LEADING), nil)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.BinaryExpression).Right], []string{\"test^\"}, ast.LEADING), nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// Bitwise AND\n\t\tp, program = test(\"i & /*test&*/ 2\", nil)\n\t\tis(len(program.Body), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0]], []string{}, ast.LEADING), nil)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.BinaryExpression).Right], []string{\"test&\"}, ast.LEADING), nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// Equality\n\t\tp, program = test(\"i == /*test==*/ 2\", nil)\n\t\tis(len(program.Body), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0]], []string{}, ast.LEADING), nil)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.BinaryExpression).Right], []string{\"test==\"}, ast.LEADING), nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// Relational, <\n\t\tp, program = test(\"i < /*test<*/ 2\", nil)\n\t\tis(len(program.Body), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0]], []string{}, ast.LEADING), nil)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.BinaryExpression).Right], []string{\"test<\"}, ast.LEADING), nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// Relational, instanceof\n\t\tp, program = test(\"i instanceof /*testinstanceof*/ thing\", nil)\n\t\tis(len(program.Body), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0]], []string{}, ast.LEADING), nil)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.BinaryExpression).Right], []string{\"testinstanceof\"}, ast.LEADING), nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// Shift left\n\t\tp, program = test(\"i << /*test<<*/ 2\", nil)\n\t\tis(len(program.Body), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0]], []string{}, ast.LEADING), nil)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.BinaryExpression).Right], []string{\"test<<\"}, ast.LEADING), nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// +\n\t\tp, program = test(\"i + /*test+*/ 2\", nil)\n\t\tis(len(program.Body), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0]], []string{}, ast.LEADING), nil)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.BinaryExpression).Right], []string{\"test+\"}, ast.LEADING), nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// *\n\t\tp, program = test(\"i * /*test**/ 2\", nil)\n\t\tis(len(program.Body), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0]], []string{}, ast.LEADING), nil)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.BinaryExpression).Right], []string{\"test*\"}, ast.LEADING), nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// Unary prefix, ++\n\t\tp, program = test(\"++/*test++*/i\", nil)\n\t\tis(len(program.Body), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0]], []string{}, ast.LEADING), nil)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.UnaryExpression).Operand], []string{\"test++\"}, ast.LEADING), nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// Unary prefix, delete\n\t\tp, program = test(\"delete /*testdelete*/ i\", nil)\n\t\tis(len(program.Body), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0]], []string{}, ast.LEADING), nil)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.UnaryExpression).Operand], []string{\"testdelete\"}, ast.LEADING), nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// Unary postfix, ++\n\t\tp, program = test(\"i/*test++*/++\", nil)\n\t\tis(len(program.Body), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0]], []string{}, ast.LEADING), nil)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.UnaryExpression).Operand], []string{\"test++\"}, ast.TRAILING), nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// + pt 2\n\t\tp, program = test(\"i /*test+*/ + 2\", nil)\n\t\tis(len(program.Body), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0]], []string{}, ast.LEADING), nil)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.BinaryExpression).Left], []string{\"test+\"}, ast.TRAILING), nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// Multiple comments for a single node\n\t\tp, program = test(\"i /*test+*/ /*test+2*/ + 2\", nil)\n\t\tis(len(program.Body), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0]], []string{}, ast.LEADING), nil)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.BinaryExpression).Left], []string{\"test+\", \"test+2\"}, ast.TRAILING), nil)\n\t\tis(p.comments.CommentMap.Size(), 2)\n\n\t\t// Multiple comments for multiple nodes\n\t\tp, program = test(\"i /*test1*/ + 2 /*test2*/ + a /*test3*/ * x /*test4*/\", nil)\n\t\tis(len(program.Body), 1)\n\t\tis(p.comments.CommentMap.Size(), 4)\n\n\t\t// Leading comment\n\t\tp, program = test(\"/*leadingtest*/i + 2\", nil)\n\t\tis(len(program.Body), 1)\n\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement)], []string{\"leadingtest\"}, ast.LEADING), nil)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.BinaryExpression).Left], []string{}, ast.TRAILING), nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// Leading comment, with semicolon\n\t\tp, program = test(\"/*leadingtest;*/;i + 2\", nil)\n\t\tis(len(program.Body), 2)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[1]], []string{\"leadingtest;\"}, ast.LEADING), nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// Arrays\n\t\tp, program = test(\"[1, 2 /*test2*/, 3]\", nil)\n\t\tis(len(program.Body), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.ArrayLiteral).Value[1]], []string{\"test2\"}, ast.TRAILING), nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// Function calls\n\t\tp, program = test(\"fun(a,b) //test\", nil)\n\t\tis(len(program.Body), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.CallExpression)], []string{\"test\"}, ast.TRAILING), nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// Function calls, pt 2\n\t\tp, program = test(\"fun(a/*test1*/,b)\", nil)\n\t\tis(len(program.Body), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.CallExpression).ArgumentList[0]], []string{\"test1\"}, ast.TRAILING), nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// Function calls, pt 3\n\t\tp, program = test(\"fun(/*test1*/a,b)\", nil)\n\t\tis(len(program.Body), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.CallExpression).ArgumentList[0]], []string{\"test1\"}, ast.LEADING), nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// Arrays pt 2\n\t\tp, program = test(`[\"abc\".substr(0,1)/*testa*/,\n            \"abc.substr(0,2)\"];`, nil)\n\t\tis(len(program.Body), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.ArrayLiteral).Value[0]], []string{\"testa\"}, ast.TRAILING), nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// Arrays pt 3\n\t\tp, program = test(`[a, //test\n            b];`, nil)\n\t\tis(len(program.Body), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.ArrayLiteral).Value[1]], []string{\"test\"}, ast.LEADING), nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// Arrays pt 4\n\t\tp, program = test(`[a, //test\n\t\tb, c];`, nil)\n\t\tis(len(program.Body), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.ArrayLiteral).Value[1]], []string{\"test\"}, ast.LEADING), nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// Arrays pt 5\n\t\tp, program = test(`\n[\n\t\"a1\", // \"a\"\n\t\"a2\", // \"ab\"\n];\n        `, nil)\n\t\tis(p.comments.CommentMap.Size(), 2)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.ArrayLiteral).Value[1]], []string{\" \\\"a\\\"\"}, ast.LEADING), nil)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.ArrayLiteral)], []string{\" \\\"ab\\\"\"}, ast.FINAL), nil)\n\n\t\t// Arrays pt 6\n\t\tp, program = test(`[a, /*test*/ b, c];`, nil)\n\t\tis(len(program.Body), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.ArrayLiteral).Value[1]], []string{\"test\"}, ast.LEADING), nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// Arrays pt 7 - Empty node\n\t\tp, program = test(`[a,,/*test2*/,];`, nil)\n\t\tis(len(program.Body), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.ArrayLiteral).Value[2]], []string{\"test2\"}, ast.TRAILING), nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// Arrays pt 8 - Trailing node\n\t\tp, program = test(`[a,,,/*test2*/];`, nil)\n\t\tis(len(program.Body), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.ArrayLiteral)], []string{\"test2\"}, ast.FINAL), nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// Arrays pt 9 - Leading node\n\t\tp, program = test(`[/*test2*/a,,,];`, nil)\n\t\tis(len(program.Body), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.ArrayLiteral).Value[0]], []string{\"test2\"}, ast.LEADING), nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// Object literal\n\t\tp, program = test(\"obj = {a: 1, b: 2 /*test2*/, c: 3}\", nil)\n\t\tis(len(program.Body), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.AssignExpression).Right.(*ast.ObjectLiteral).Value[1].Value], []string{\"test2\"}, ast.TRAILING), nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// Object literal, pt 2\n\t\tp, program = test(\"obj = {/*test2*/a: 1, b: 2, c: 3}\", nil)\n\t\tis(len(program.Body), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.AssignExpression).Right.(*ast.ObjectLiteral).Value[0].Value], []string{\"test2\"}, ast.KEY), nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// Object literal, pt 3\n\t\tp, program = test(\"obj = {x/*test2*/: 1, y: 2, z: 3}\", nil)\n\t\tis(len(program.Body), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.AssignExpression).Right.(*ast.ObjectLiteral).Value[0].Value], []string{\"test2\"}, ast.COLON), nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// Object literal, pt 4\n\t\tp, program = test(\"obj = {x: /*test2*/1, y: 2, z: 3}\", nil)\n\t\tis(len(program.Body), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.AssignExpression).Right.(*ast.ObjectLiteral).Value[0].Value], []string{\"test2\"}, ast.LEADING), nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// Object literal, pt 5\n\t\tp, program = test(\"obj = {x: 1/*test2*/, y: 2, z: 3}\", nil)\n\t\tis(len(program.Body), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.AssignExpression).Right.(*ast.ObjectLiteral).Value[0].Value], []string{\"test2\"}, ast.TRAILING), nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// Object literal, pt 6\n\t\tp, program = test(\"obj = {x: 1, y: 2, z: 3/*test2*/}\", nil)\n\t\tis(len(program.Body), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.AssignExpression).Right.(*ast.ObjectLiteral).Value[2].Value], []string{\"test2\"}, ast.TRAILING), nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// Object literal, pt 7 - trailing comment\n\t\tp, program = test(\"obj = {x: 1, y: 2, z: 3,/*test2*/}\", nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.AssignExpression).Right.(*ast.ObjectLiteral)], []string{\"test2\"}, ast.FINAL), nil)\n\n\t\t// Line breaks\n\t\tp, program = test(`\nt1 = \"BLA DE VLA\"\n/*Test*/\nt2 = \"Nothing happens.\"\n\t\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[1]], []string{\"Test\"}, ast.LEADING), nil)\n\n\t\t// Line breaks pt 2\n\t\tp, program = test(`\nt1 = \"BLA DE VLA\" /*Test*/\nt2 = \"Nothing happens.\"\n\t\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.AssignExpression).Right.(*ast.StringLiteral)], []string{\"Test\"}, ast.TRAILING), nil)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[1].(*ast.ExpressionStatement)], []string{}, ast.LEADING), nil)\n\n\t\t// Line breaks pt 3\n\t\tp, program = test(`\nt1 = \"BLA DE VLA\" /*Test*/ /*Test2*/\nt2 = \"Nothing happens.\"\n\t\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 2)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.AssignExpression).Right.(*ast.StringLiteral)], []string{\"Test\", \"Test2\"}, ast.TRAILING), nil)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[1].(*ast.ExpressionStatement)], []string{}, ast.LEADING), nil)\n\n\t\t// Line breaks pt 4\n\t\tp, program = test(`\nt1 = \"BLA DE VLA\" /*Test*/\n/*Test2*/\nt2 = \"Nothing happens.\"\n\t\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 2)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.AssignExpression).Right.(*ast.StringLiteral)], []string{\"Test\"}, ast.TRAILING), nil)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[1]], []string{\"Test2\"}, ast.LEADING), nil)\n\n\t\t// Line breaks pt 5\n\t\tp, program = test(`\nt1 = \"BLA DE VLA\";\n/*Test*/\nt2 = \"Nothing happens.\"\n\t\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[1]], []string{\"Test\"}, ast.LEADING), nil)\n\n\t\t// Line breaks pt 6\n\t\tp, program = test(`\nt1 = \"BLA DE VLA\"; /*Test*/\n/*Test2*/\nt2 = \"Nothing happens.\"\n\t\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 2)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[1]], []string{\"Test\", \"Test2\"}, ast.LEADING), nil)\n\n\t\t// Misc\n\t\tp, _ = test(`\nvar x = Object.create({y: {\n},\n// a\n});\n\t\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// Misc 2\n\t\tp, _ = test(`\nvar x = Object.create({y: {\n},\n// a\n// b\na: 2});\n\t\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 2)\n\n\t\t// Statement blocks\n\t\tp, program = test(`\n(function() {\n  // Baseline setup\n})\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral).Body], []string{\" Baseline setup\"}, ast.FINAL), nil)\n\n\t\t// Switches\n\t\tp, program = test(`\nswitch (switcha) {\n  // switch comment\n  case \"switchb\":\n  \ta\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.SwitchStatement).Body[0]], []string{\" switch comment\"}, ast.LEADING), nil)\n\n\t\t// Switches pt 2\n\t\tp, program = test(`\nswitch (switcha) {\n  case /*switch comment*/ \"switchb\":\n  \ta\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.SwitchStatement).Body[0].Test], []string{\"switch comment\"}, ast.LEADING), nil)\n\n\t\t// Switches pt 3\n\t\tp, program = test(`\nswitch (switcha) {\n  case \"switchb\" /*switch comment*/:\n  \ta\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.SwitchStatement).Body[0].Test], []string{\"switch comment\"}, ast.TRAILING), nil)\n\n\t\t// Switches pt 4\n\t\tp, program = test(`\nswitch (switcha) {\n  case \"switchb\": /*switch comment*/\n  \ta\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.SwitchStatement).Body[0].Consequent[0]], []string{\"switch comment\"}, ast.LEADING), nil)\n\n\t\t// Switches pt 5 - default\n\t\tp, program = test(`\nswitch (switcha) {\n  default: /*switch comment*/\n  \ta\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.SwitchStatement).Body[0].Consequent[0]], []string{\"switch comment\"}, ast.LEADING), nil)\n\n\t\t// Switches pt 6\n\t\tp, program = test(`\nswitch (switcha) {\n  case \"switchb\":\n  \t/*switch comment*/a\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.SwitchStatement).Body[0].Consequent[0]], []string{\"switch comment\"}, ast.LEADING), nil)\n\n\t\t// Switches pt 7\n\t\tp, program = test(`\nswitch (switcha) {\n  case \"switchb\": /*switch comment*/ {\n  \ta\n  \t}\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.SwitchStatement).Body[0].Consequent[0]], []string{\"switch comment\"}, ast.LEADING), nil)\n\n\t\t// Switches pt 8\n\t\tp, program = test(`\nswitch (switcha) {\n  case \"switchb\":  {\n  \ta\n  \t}/*switch comment*/\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.SwitchStatement).Body[0].Consequent[0]], []string{\"switch comment\"}, ast.TRAILING), nil)\n\n\t\t// Switches pt 9\n\t\tp, program = test(`\nswitch (switcha) {\n  case \"switchb\": /*switch comment*/ {\n  \ta\n  \t}\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.SwitchStatement).Body[0].Consequent[0]], []string{\"switch comment\"}, ast.LEADING), nil)\n\n\t\t// Switches pt 10\n\t\tp, program = test(`\nswitch (switcha) {\n  case \"switchb\": {\n  \t/*switch comment*/a\n  \t}\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.SwitchStatement).Body[0].Consequent[0].(*ast.BlockStatement).List[0]], []string{\"switch comment\"}, ast.LEADING), nil)\n\n\t\t// For loops\n\t\tp, program = test(`\nfor(/*comment*/i = 0 ; i < 1 ; i++) {\n\ta\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ForStatement).Initializer.(*ast.SequenceExpression).Sequence[0].(*ast.AssignExpression).Left], []string{\"comment\"}, ast.LEADING), nil)\n\n\t\t// For loops pt 2\n\t\tp, program = test(`\nfor(i/*comment*/ = 0 ; i < 1 ; i++) {\n\ta\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ForStatement).Initializer.(*ast.SequenceExpression).Sequence[0].(*ast.AssignExpression).Left], []string{\"comment\"}, ast.TRAILING), nil)\n\n\t\t// For loops pt 3\n\t\tp, program = test(`\nfor(i = 0 ; /*comment*/i < 1 ; i++) {\n\ta\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ForStatement).Test.(*ast.BinaryExpression).Left], []string{\"comment\"}, ast.LEADING), nil)\n\n\t\t// For loops pt 4\n\t\tp, program = test(`\nfor(i = 0 ;i /*comment*/ < 1 ; i++) {\n\ta\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ForStatement).Test.(*ast.BinaryExpression).Left], []string{\"comment\"}, ast.TRAILING), nil)\n\n\t\t// For loops pt 5\n\t\tp, program = test(`\nfor(i = 0 ;i < 1 /*comment*/ ; i++) {\n\ta\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ForStatement).Test.(*ast.BinaryExpression).Right], []string{\"comment\"}, ast.TRAILING), nil)\n\n\t\t// For loops pt 6\n\t\tp, program = test(`\nfor(i = 0 ;i < 1 ; /*comment*/ i++) {\n\ta\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ForStatement).Update.(*ast.UnaryExpression).Operand], []string{\"comment\"}, ast.LEADING), nil)\n\n\t\t// For loops pt 7\n\t\tp, program = test(`\nfor(i = 0 ;i < 1 ; i++) /*comment*/ {\n\ta\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ForStatement).Body], []string{\"comment\"}, ast.LEADING), nil)\n\n\t\t// For loops pt 8\n\t\tp, program = test(`\nfor(i = 0 ;i < 1 ; i++)  {\n\ta\n}/*comment*/\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ForStatement).Body], []string{\"comment\"}, ast.TRAILING), nil)\n\n\t\t// For loops pt 9\n\t\tp, program = test(`\nfor(i = 0 ;i < 1 ; /*comment*/i++)  {\n\ta\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ForStatement).Update.(*ast.UnaryExpression).Operand], []string{\"comment\"}, ast.LEADING), nil)\n\n\t\t// For loops pt 10\n\t\tp, program = test(`\nfor(i = 0 ;i < 1 ; i/*comment*/++)  {\n\ta\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ForStatement).Update.(*ast.UnaryExpression).Operand.(*ast.Identifier)], []string{\"comment\"}, ast.TRAILING), nil)\n\n\t\t// For loops pt 11\n\t\tp, program = test(`\nfor(i = 0 ;i < 1 ; i++/*comment*/)  {\n\ta\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ForStatement).Update.(*ast.UnaryExpression)], []string{\"comment\"}, ast.TRAILING), nil)\n\n\t\t// ForIn\n\t\tp, program = test(`\nfor(/*comment*/var i = 0 in obj)  {\n\ta\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ForInStatement).Into], []string{\"comment\"}, ast.LEADING), nil)\n\n\t\t// ForIn pt 2\n\t\tp, program = test(`\nfor(var i = 0 /*comment*/in obj)  {\n\ta\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ForInStatement).Into.(*ast.VariableExpression).Initializer], []string{\"comment\"}, ast.TRAILING), nil)\n\n\t\t// ForIn pt 3\n\t\tp, program = test(`\nfor(var i = 0 in /*comment*/ obj)  {\n\ta\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ForInStatement).Source], []string{\"comment\"}, ast.LEADING), nil)\n\n\t\t// ForIn pt 4\n\t\tp, program = test(`\nfor(var i = 0 in  obj/*comment*/)  {\n\ta\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ForInStatement).Source], []string{\"comment\"}, ast.TRAILING), nil)\n\n\t\t// ForIn pt 5\n\t\tp, program = test(`\nfor(var i = 0 in  obj) /*comment*/ {\n\ta\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ForInStatement).Body], []string{\"comment\"}, ast.LEADING), nil)\n\n\t\t// ForIn pt 6\n\t\tp, program = test(`\nfor(var i = 0 in  obj) {\n\ta\n}/*comment*/\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ForInStatement).Body], []string{\"comment\"}, ast.TRAILING), nil)\n\n\t\t// ForIn pt 7\n\t\tp, program = test(`\nfor(var i = 0 in  obj) {\n\ta\n}\n// comment\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program], []string{\" comment\"}, ast.TRAILING), nil)\n\n\t\t// ForIn pt 8\n\t\tp, program = test(`\nfor(var i = 0 in  obj) {\n\ta\n}\n// comment\nc\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[1]], []string{\" comment\"}, ast.LEADING), nil)\n\n\t\t// Block\n\t\tp, program = test(`\n\t\t/*comment*/{\n\t\t\ta\n\t\t}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.BlockStatement)], []string{\"comment\"}, ast.LEADING), nil)\n\n\t\t// Block pt 2\n\t\tp, program = test(`\n\t\t{\n\t\t\ta\n\t\t}/*comment*/\n\t\t\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.BlockStatement)], []string{\"comment\"}, ast.TRAILING), nil)\n\n\t\t// If then else\n\t\tp, program = test(`\n/*comment*/\nif(a) {\n\tb\n} else {\n\tc\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.IfStatement)], []string{\"comment\"}, ast.LEADING), nil)\n\n\t\t// If then else pt 2\n\t\tp, program = test(`\nif/*comment*/(a) {\n\tb\n} else {\n\tc\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.IfStatement)], []string{\"comment\"}, ast.IF), nil)\n\n\t\t// If then else pt 3\n\t\tp, program = test(`\nif(/*comment*/a) {\n\tb\n} else {\n\tc\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.IfStatement).Test], []string{\"comment\"}, ast.LEADING), nil)\n\n\t\t// If then else pt 4\n\t\tp, program = test(`\nif(a/*comment*/) {\n\tb\n} else {\n\tc\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.IfStatement).Test], []string{\"comment\"}, ast.TRAILING), nil)\n\n\t\t// If then else pt 4\n\t\tp, program = test(`\nif(a)/*comment*/ {\n\tb\n} else {\n\tc\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.IfStatement).Consequent], []string{\"comment\"}, ast.LEADING), nil)\n\n\t\t// If then else pt 5\n\t\tp, program = test(`\nif(a) {\n\tb\n} /*comment*/else {\n\tc\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.IfStatement).Consequent], []string{\"comment\"}, ast.TRAILING), nil)\n\n\t\t// If then else pt 6\n\t\tp, program = test(`\nif(a) {\n\tb\n} else/*comment*/ {\n\tc\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.IfStatement).Alternate], []string{\"comment\"}, ast.LEADING), nil)\n\n\t\t// If then else pt 7\n\t\tp, program = test(`\nif(a) {\n\tb\n} else {\n\tc\n}/*comment*/\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.IfStatement).Alternate], []string{\"comment\"}, ast.TRAILING), nil)\n\n\t\t// If then else pt 8\n\t\tp, _ = test(`\nif\n/*comment*/\n(a) {\n\tb\n} else {\n\tc\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// If then else pt 9\n\t\tp, _ = test(`\nif\n(a)\n /*comment*/{\n\tb\n} else {\n\tc\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// If then else pt 10\n\t\tp, _ = test(`\nif(a){\n\tb\n}\n/*comment*/\nelse {\n\tc\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// Do while\n\t\tp, program = test(`\n/*comment*/do {\n\ta\n} while(b)\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.DoWhileStatement)], []string{\"comment\"}, ast.LEADING), nil)\n\n\t\t// Do while pt 2\n\t\tp, program = test(`\ndo /*comment*/ {\n\ta\n} while(b)\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.DoWhileStatement)], []string{\"comment\"}, ast.DO), nil)\n\n\t\t// Do while pt 3\n\t\tp, program = test(`\ndo {\n\ta\n} /*comment*/ while(b)\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.DoWhileStatement).Body], []string{\"comment\"}, ast.TRAILING), nil)\n\n\t\t// Do while pt 4\n\t\tp, program = test(`\ndo {\n\ta\n} while/*comment*/(b)\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.DoWhileStatement)], []string{\"comment\"}, ast.WHILE), nil)\n\n\t\t// Do while pt 5\n\t\tp, program = test(`\ndo {\n\ta\n} while(b)/*comment*/\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.DoWhileStatement)], []string{\"comment\"}, ast.TRAILING), nil)\n\n\t\t// While\n\t\tp, program = test(`\n/*comment*/while(a) {\n\tb\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.WhileStatement)], []string{\"comment\"}, ast.LEADING), nil)\n\n\t\t// While pt 2\n\t\tp, program = test(`\nwhile/*comment*/(a) {\n\tb\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.WhileStatement)], []string{\"comment\"}, ast.WHILE), nil)\n\n\t\t// While pt 3\n\t\tp, program = test(`\nwhile(/*comment*/a) {\n\tb\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.WhileStatement).Test], []string{\"comment\"}, ast.LEADING), nil)\n\n\t\t// While pt 4\n\t\tp, program = test(`\nwhile(a/*comment*/) {\n\tb\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.WhileStatement).Test], []string{\"comment\"}, ast.TRAILING), nil)\n\n\t\t// While pt 5\n\t\tp, program = test(`\nwhile(a) /*comment*/ {\n\tc\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.WhileStatement).Body], []string{\"comment\"}, ast.LEADING), nil)\n\n\t\t// While pt 6\n\t\tp, program = test(`\nwhile(a) {\n\tc\n}/*comment*/\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.WhileStatement).Body], []string{\"comment\"}, ast.TRAILING), nil)\n\n\t\t// While pt 7\n\t\tp, program = test(`\nwhile(a) {\n\tc/*comment*/\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.WhileStatement).Body.(*ast.BlockStatement).List[0].(*ast.ExpressionStatement).Expression.(*ast.Identifier)], []string{\"comment\"}, ast.TRAILING), nil)\n\n\t\t// While pt 7\n\t\tp, program = test(`\nwhile(a) {\n\t/*comment*/\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.WhileStatement).Body.(*ast.BlockStatement)], []string{\"comment\"}, ast.FINAL), nil)\n\n\t\t// While pt 8\n\t\tp, _ = test(`\nwhile\n/*comment*/(a) {\n\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// While pt 9\n\t\tp, _ = test(`\nwhile\n(a)\n /*comment*/{\n\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// Break\n\t\tp, program = test(`\nwhile(a) {\n\tbreak/*comment*/;\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.WhileStatement).Body.(*ast.BlockStatement).List[0].(*ast.BranchStatement)], []string{\"comment\"}, ast.TRAILING), nil)\n\n\t\t// Break pt 2\n\t\tp, program = test(`\nwhile(a) {\n\tnext/*comment*/:\n\tbreak next;\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.WhileStatement).Body.(*ast.BlockStatement).List[0].(*ast.LabelledStatement).Label], []string{\"comment\"}, ast.TRAILING), nil)\n\n\t\t// Break pt 3\n\t\tp, program = test(`\nwhile(a) {\n\tnext:/*comment*/\n\tbreak next;\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.WhileStatement).Body.(*ast.BlockStatement).List[0].(*ast.LabelledStatement)], []string{\"comment\"}, ast.LEADING), nil)\n\n\t\t// Break pt 4\n\t\tp, program = test(`\nwhile(a) {\n\tnext:\n\tbreak /*comment*/next;\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.WhileStatement).Body.(*ast.BlockStatement).List[0].(*ast.LabelledStatement).Statement.(*ast.BranchStatement).Label], []string{\"comment\"}, ast.LEADING), nil)\n\n\t\t// Break pt 5\n\t\tp, program = test(`\nwhile(a) {\n\tnext:\n\tbreak next/*comment*/;\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.WhileStatement).Body.(*ast.BlockStatement).List[0].(*ast.LabelledStatement).Statement.(*ast.BranchStatement).Label], []string{\"comment\"}, ast.TRAILING), nil)\n\n\t\t// Debugger\n\t\tp, program = test(`\ndebugger // comment\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.DebuggerStatement)], []string{\" comment\"}, ast.TRAILING), nil)\n\n\t\t// Debugger pt 2\n\t\tp, program = test(`\ndebugger; // comment\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program], []string{\" comment\"}, ast.TRAILING), nil)\n\n\t\t// Debugger pt 3\n\t\tp, program = test(`\ndebugger;\n// comment\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program], []string{\" comment\"}, ast.TRAILING), nil)\n\n\t\t// With\n\t\tp, program = test(`\n/*comment*/with(a) {\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.WithStatement)], []string{\"comment\"}, ast.LEADING), nil)\n\n\t\t// With pt 2\n\t\tp, program = test(`\nwith/*comment*/(a) {\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.WithStatement)], []string{\"comment\"}, ast.WITH), nil)\n\n\t\t// With pt 3\n\t\tp, program = test(`\nwith(/*comment*/a) {\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.WithStatement).Object], []string{\"comment\"}, ast.LEADING), nil)\n\n\t\t// With pt 4\n\t\tp, program = test(`\nwith(a/*comment*/) {\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.WithStatement).Object], []string{\"comment\"}, ast.TRAILING), nil)\n\n\t\t// With pt 5\n\t\tp, program = test(`\nwith(a) /*comment*/ {\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.WithStatement).Body], []string{\"comment\"}, ast.LEADING), nil)\n\n\t\t// With pt 6\n\t\tp, program = test(`\nwith(a)  {\n}/*comment*/\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.WithStatement).Body], []string{\"comment\"}, ast.TRAILING), nil)\n\n\t\t// With pt 7\n\t\tp, _ = test(`\nwith\n/*comment*/(a)  {\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// With pt 8\n\t\tp, _ = test(`\nwith\n(a)\n  /*comment*/{\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// Var\n\t\tp, program = test(`\n/*comment*/var a\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.VariableStatement)], []string{\"comment\"}, ast.LEADING), nil)\n\n\t\t// Var pt 2\n\t\tp, program = test(`\nvar/*comment*/ a\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.VariableStatement).List[0]], []string{\"comment\"}, ast.LEADING), nil)\n\n\t\t// Var pt 3\n\t\tp, program = test(`\nvar a/*comment*/\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.VariableStatement).List[0]], []string{\"comment\"}, ast.TRAILING), nil)\n\n\t\t// Var pt 4\n\t\tp, program = test(`\nvar a/*comment*/, b\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.VariableStatement).List[0].(*ast.VariableExpression)], []string{\"comment\"}, ast.TRAILING), nil)\n\n\t\t// Var pt 5\n\t\tp, program = test(`\nvar a, /*comment*/b\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.VariableStatement).List[1].(*ast.VariableExpression)], []string{\"comment\"}, ast.LEADING), nil)\n\n\t\t// Var pt 6\n\t\tp, program = test(`\nvar a, b/*comment*/\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.VariableStatement).List[1]], []string{\"comment\"}, ast.TRAILING), nil)\n\n\t\t// Var pt 7\n\t\tp, program = test(`\nvar a, b;\n/*comment*/\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program], []string{\"comment\"}, ast.TRAILING), nil)\n\n\t\t// Return\n\t\tp, _ = test(`\n\t\tfunction f() {\n/*comment*/return o\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// Try catch\n\t\tp, program = test(`\n/*comment*/try {\n\ta\n} catch(b) {\n\tc\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.TryStatement)], []string{\"comment\"}, ast.LEADING), nil)\n\n\t\t// Try catch pt 2\n\t\tp, program = test(`\ntry/*comment*/ {\n\ta\n} catch(b) {\n\tc\n} finally {\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.TryStatement).Body], []string{\"comment\"}, ast.LEADING), nil)\n\n\t\t// Try catch pt 3\n\t\tp, program = test(`\ntry {\n\ta\n}/*comment*/ catch(b) {\n\tc\n} finally {\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.TryStatement).Body], []string{\"comment\"}, ast.TRAILING), nil)\n\n\t\t// Try catch pt 4\n\t\tp, program = test(`\ntry {\n\ta\n} catch(/*comment*/b) {\n\tc\n} finally {\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.TryStatement).Catch.Parameter], []string{\"comment\"}, ast.LEADING), nil)\n\n\t\t// Try catch pt 5\n\t\tp, program = test(`\ntry {\n\ta\n} catch(b/*comment*/) {\n\tc\n} finally {\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.TryStatement).Catch.Parameter], []string{\"comment\"}, ast.TRAILING), nil)\n\n\t\t// Try catch pt 6\n\t\tp, program = test(`\ntry {\n\ta\n} catch(b) /*comment*/{\n\tc\n} finally {\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.TryStatement).Catch.Body], []string{\"comment\"}, ast.LEADING), nil)\n\n\t\t// Try catch pt 7\n\t\tp, program = test(`\ntry {\n\ta\n} catch(b){\n\tc\n} /*comment*/ finally {\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.TryStatement).Catch.Body], []string{\"comment\"}, ast.TRAILING), nil)\n\n\t\t// Try catch pt 8\n\t\tp, program = test(`\ntry {\n\ta\n} catch(b){\n\tc\n} finally /*comment*/ {\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.TryStatement).Finally], []string{\"comment\"}, ast.LEADING), nil)\n\n\t\t// Try catch pt 9\n\t\tp, program = test(`\ntry {\n\ta\n} catch(b){\n\tc\n} finally  {\n}/*comment*/\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.TryStatement).Finally], []string{\"comment\"}, ast.TRAILING), nil)\n\n\t\t// Try catch pt 11\n\t\tp, program = test(`\ntry {\n\ta\n}\n/*comment*/\n catch(b){\n\tc\n} finally {\n d\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.TryStatement).Body], []string{\"comment\"}, ast.TRAILING), nil)\n\n\t\t// Throw\n\t\tp, program = test(`\nthrow a/*comment*/\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ThrowStatement).Argument], []string{\"comment\"}, ast.TRAILING), nil)\n\n\t\t// Throw pt 2\n\t\tp, program = test(`\n/*comment*/throw a\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ThrowStatement)], []string{\"comment\"}, ast.LEADING), nil)\n\n\t\t// Throw pt 3\n\t\tp, program = test(`\nthrow /*comment*/a\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ThrowStatement).Argument], []string{\"comment\"}, ast.LEADING), nil)\n\n\t\t// Try catch pt 10\n\t\tp, program = test(`\ntry {\n\ta\n} catch(b){\n\tc\n}\n /*comment*/finally  {\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.TryStatement).Catch.Body], []string{\"comment\"}, ast.TRAILING), nil)\n\n\t\t// Try catch pt 11\n\t\tp, program = test(`\ntry {\n\ta\n} catch(b){\n\tc\n}\n finally\n /*comment*/\n {\n d\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.TryStatement).Finally], []string{\"comment\"}, ast.LEADING), nil)\n\n\t\t// Switch / comment\n\t\tp, _ = test(`\nvar volvo = 1\n//comment\nswitch(abra) {\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// Switch / comment\n\t\tp, _ = test(`\nf(\"string\",{\n   key: \"val\"\n   //comment\n});\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\n\t\t// Switch / comment\n\t\tp, program = test(`\nfunction f() {\n   /*comment*/if(true){a++}\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tn := program.Body[0].(*ast.FunctionStatement).Function.Body.(*ast.BlockStatement).List[0]\n\t\tis(checkComments((p.comments.CommentMap)[n], []string{\"comment\"}, ast.LEADING), nil)\n\n\t\t// Function in function\n\t\tp, program = test(`\nfunction f() {\n   /*comment*/function f2() {\n   }\n}\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 1)\n\t\tn = program.Body[0].(*ast.FunctionStatement).Function.Body.(*ast.BlockStatement).List[0]\n\t\tis(checkComments((p.comments.CommentMap)[n], []string{\"comment\"}, ast.LEADING), nil)\n\n\t\tp, program = test(`\na + /*comment1*/\n/*comment2*/\nb/*comment3*/;\n/*comment4*/c\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 4)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.BinaryExpression).Right], []string{\"comment1\", \"comment2\"}, ast.LEADING), nil)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.BinaryExpression).Right], []string{\"comment3\"}, ast.TRAILING), nil)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[1]], []string{\"comment4\"}, ast.LEADING), nil)\n\n\t\tp, program = test(`\na + /*comment1*/\n/*comment2*/\nb/*comment3*/\n/*comment4*/c\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 4)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.BinaryExpression).Right], []string{\"comment1\", \"comment2\"}, ast.LEADING), nil)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.BinaryExpression).Right], []string{\"comment3\"}, ast.TRAILING), nil)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[1]], []string{\"comment4\"}, ast.LEADING), nil)\n\n\t\t// New\n\t\tp, program = test(`\na = /*comment1*/new /*comment2*/ obj/*comment3*/()\n\t`, nil)\n\t\tis(p.comments.CommentMap.Size(), 3)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.AssignExpression).Right], []string{\"comment1\"}, ast.LEADING), nil)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.AssignExpression).Right.(*ast.NewExpression).Callee], []string{\"comment2\"}, ast.LEADING), nil)\n\t\tis(checkComments((p.comments.CommentMap)[program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.AssignExpression).Right.(*ast.NewExpression).Callee], []string{\"comment3\"}, ast.TRAILING), nil)\n\t})\n}\n\nfunc TestParser_comments2(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := func(source string, chk interface{}) (*parser, *ast.Program) {\n\t\t\tparser, program, err := testParseWithMode(source, StoreComments)\n\t\t\tis(firstErr(err), chk)\n\n\t\t\t// Check unresolved comments\n\t\t\tis(len(parser.comments.Comments), 0)\n\t\t\treturn parser, program\n\t\t}\n\n\t\tparser, program := test(`\na = /*comment1*/new /*comment2*/ obj/*comment3*/()\n`, nil)\n\t\tn := program.Body[0]\n\t\tfmt.Printf(\"FOUND NODE: %v, number of comments: %v\\n\", reflect.TypeOf(n), len(parser.comments.CommentMap[n])) //nolint:forbidigo\n\t\tdisplayComments(parser.comments.CommentMap)\n\t})\n}\n"
  },
  {
    "path": "parser/error.go",
    "content": "package parser\n\nimport (\n\t\"fmt\"\n\t\"sort\"\n\n\t\"github.com/robertkrimen/otto/file\"\n\t\"github.com/robertkrimen/otto/token\"\n)\n\nconst (\n\terrUnexpectedToken      = \"Unexpected token %v\"\n\terrUnexpectedEndOfInput = \"Unexpected end of input\"\n)\n\n//    UnexpectedNumber:  'Unexpected number',\n//    UnexpectedString:  'Unexpected string',\n//    UnexpectedIdentifier:  'Unexpected identifier',\n//    UnexpectedReserved:  'Unexpected reserved word',\n//    NewlineAfterThrow:  'Illegal newline after throw',\n//    InvalidRegExp: 'Invalid regular expression',\n//    UnterminatedRegExp:  'Invalid regular expression: missing /',\n//    InvalidLHSInAssignment:  'invalid left-hand side in assignment',\n//    InvalidLHSInForIn:  'Invalid left-hand side in for-in',\n//    MultipleDefaultsInSwitch: 'More than one default clause in switch statement',\n//    NoCatchOrFinally:  'Missing catch or finally after try',\n//    UnknownLabel: 'Undefined label \\'%0\\'',\n//    Redeclaration: '%0 \\'%1\\' has already been declared',\n//    IllegalContinue: 'Illegal continue statement',\n//    IllegalBreak: 'Illegal break statement',\n//    IllegalReturn: 'Illegal return statement',\n//    StrictModeWith:  'Strict mode code may not include a with statement',\n//    StrictCatchVariable:  'Catch variable may not be eval or arguments in strict mode',\n//    StrictVarName:  'Variable name may not be eval or arguments in strict mode',\n//    StrictParamName:  'Parameter name eval or arguments is not allowed in strict mode',\n//    StrictParamDupe: 'Strict mode function may not have duplicate parameter names',\n//    StrictFunctionName:  'Function name may not be eval or arguments in strict mode',\n//    StrictOctalLiteral:  'Octal literals are not allowed in strict mode.',\n//    StrictDelete:  'Delete of an unqualified identifier in strict mode.',\n//    StrictDuplicateProperty:  'Duplicate data property in object literal not allowed in strict mode',\n//    AccessorDataProperty:  'Object literal may not have data and accessor property with the same name',\n//    AccessorGetSet:  'Object literal may not have multiple get/set accessors with the same name',\n//    StrictLHSAssignment:  'Assignment to eval or arguments is not allowed in strict mode',\n//    StrictLHSPostfix:  'Postfix increment/decrement may not have eval or arguments operand in strict mode',\n//    StrictLHSPrefix:  'Prefix increment/decrement may not have eval or arguments operand in strict mode',\n//    StrictReservedWord:  'Use of future reserved word in strict mode'\n\n// A SyntaxError is a description of an ECMAScript syntax error.\n\n// An Error represents a parsing error. It includes the position where the error occurred and a message/description.\ntype Error struct {\n\tMessage  string\n\tPosition file.Position\n}\n\n// FIXME Should this be \"SyntaxError\"?\n\nfunc (e Error) Error() string {\n\tfilename := e.Position.Filename\n\tif filename == \"\" {\n\t\tfilename = \"(anonymous)\"\n\t}\n\treturn fmt.Sprintf(\"%s: Line %d:%d %s\",\n\t\tfilename,\n\t\te.Position.Line,\n\t\te.Position.Column,\n\t\te.Message,\n\t)\n}\n\nfunc (p *parser) error(place interface{}, msg string, msgValues ...interface{}) {\n\tvar idx file.Idx\n\tswitch place := place.(type) {\n\tcase int:\n\t\tidx = p.idxOf(place)\n\tcase file.Idx:\n\t\tif place == 0 {\n\t\t\tidx = p.idxOf(p.chrOffset)\n\t\t} else {\n\t\t\tidx = place\n\t\t}\n\tdefault:\n\t\tpanic(fmt.Errorf(\"error(%T, ...)\", place))\n\t}\n\n\tposition := p.position(idx)\n\tmsg = fmt.Sprintf(msg, msgValues...)\n\tp.errors.Add(position, msg)\n}\n\nfunc (p *parser) errorUnexpected(idx file.Idx, chr rune) {\n\tif chr == -1 {\n\t\tp.error(idx, errUnexpectedEndOfInput)\n\t\treturn\n\t}\n\tp.error(idx, errUnexpectedToken, token.ILLEGAL)\n}\n\nfunc (p *parser) errorUnexpectedToken(tkn token.Token) {\n\tif tkn == token.EOF {\n\t\tp.error(file.Idx(0), errUnexpectedEndOfInput)\n\t\treturn\n\t}\n\tvalue := tkn.String()\n\tswitch tkn {\n\tcase token.BOOLEAN, token.NULL:\n\t\tp.error(p.idx, errUnexpectedToken, p.literal)\n\tcase token.IDENTIFIER:\n\t\tp.error(p.idx, \"Unexpected identifier\")\n\tcase token.KEYWORD:\n\t\t// TODO Might be a future reserved word\n\t\tp.error(p.idx, \"Unexpected reserved word\")\n\tcase token.NUMBER:\n\t\tp.error(p.idx, \"Unexpected number\")\n\tcase token.STRING:\n\t\tp.error(p.idx, \"Unexpected string\")\n\tdefault:\n\t\tp.error(p.idx, errUnexpectedToken, value)\n\t}\n}\n\n// ErrorList is a list of *Errors.\ntype ErrorList []*Error //nolint:errname\n\n// Add adds an Error with given position and message to an ErrorList.\nfunc (el *ErrorList) Add(position file.Position, msg string) {\n\t*el = append(*el, &Error{Position: position, Message: msg})\n}\n\n// Reset resets an ErrorList to no errors.\nfunc (el *ErrorList) Reset() {\n\t*el = (*el)[0:0]\n}\n\n// Len implement sort.Interface.\nfunc (el *ErrorList) Len() int {\n\treturn len(*el)\n}\n\n// Swap implement sort.Interface.\nfunc (el *ErrorList) Swap(i, j int) {\n\t(*el)[i], (*el)[j] = (*el)[j], (*el)[i]\n}\n\n// Less implement sort.Interface.\nfunc (el *ErrorList) Less(i, j int) bool {\n\tx := (*el)[i].Position\n\ty := (*el)[j].Position\n\tif x.Filename < y.Filename {\n\t\treturn true\n\t}\n\tif x.Filename == y.Filename {\n\t\tif x.Line < y.Line {\n\t\t\treturn true\n\t\t}\n\t\tif x.Line == y.Line {\n\t\t\treturn x.Column < y.Column\n\t\t}\n\t}\n\treturn false\n}\n\n// Sort sorts el.\nfunc (el *ErrorList) Sort() {\n\tsort.Sort(el)\n}\n\n// Error implements the Error interface.\nfunc (el *ErrorList) Error() string {\n\tswitch len(*el) {\n\tcase 0:\n\t\treturn \"no errors\"\n\tcase 1:\n\t\treturn (*el)[0].Error()\n\tdefault:\n\t\treturn fmt.Sprintf(\"%s (and %d more errors)\", (*el)[0].Error(), len(*el)-1)\n\t}\n}\n\n// Err returns an error equivalent to this ErrorList.\n// If the list is empty, Err returns nil.\nfunc (el *ErrorList) Err() error {\n\tif len(*el) == 0 {\n\t\treturn nil\n\t}\n\treturn el\n}\n"
  },
  {
    "path": "parser/expression.go",
    "content": "package parser\n\nimport (\n\t\"regexp\"\n\n\t\"github.com/robertkrimen/otto/ast\"\n\t\"github.com/robertkrimen/otto/file\"\n\t\"github.com/robertkrimen/otto/token\"\n)\n\nfunc (p *parser) parseIdentifier() *ast.Identifier {\n\tliteral := p.literal\n\tidx := p.idx\n\tif p.mode&StoreComments != 0 {\n\t\tp.comments.MarkComments(ast.LEADING)\n\t}\n\tp.next()\n\texp := &ast.Identifier{\n\t\tName: literal,\n\t\tIdx:  idx,\n\t}\n\n\tif p.mode&StoreComments != 0 {\n\t\tp.comments.SetExpression(exp)\n\t}\n\n\treturn exp\n}\n\nfunc (p *parser) parsePrimaryExpression() ast.Expression {\n\tliteral := p.literal\n\tidx := p.idx\n\tswitch p.token {\n\tcase token.IDENTIFIER:\n\t\tp.next()\n\t\tif len(literal) > 1 {\n\t\t\ttkn, strict := token.IsKeyword(literal)\n\t\t\tif tkn == token.KEYWORD {\n\t\t\t\tif !strict {\n\t\t\t\t\tp.error(idx, \"Unexpected reserved word\")\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn &ast.Identifier{\n\t\t\tName: literal,\n\t\t\tIdx:  idx,\n\t\t}\n\tcase token.NULL:\n\t\tp.next()\n\t\treturn &ast.NullLiteral{\n\t\t\tIdx:     idx,\n\t\t\tLiteral: literal,\n\t\t}\n\tcase token.BOOLEAN:\n\t\tp.next()\n\t\tvalue := false\n\t\tswitch literal {\n\t\tcase \"true\":\n\t\t\tvalue = true\n\t\tcase \"false\":\n\t\t\tvalue = false\n\t\tdefault:\n\t\t\tp.error(idx, \"Illegal boolean literal\")\n\t\t}\n\t\treturn &ast.BooleanLiteral{\n\t\t\tIdx:     idx,\n\t\t\tLiteral: literal,\n\t\t\tValue:   value,\n\t\t}\n\tcase token.STRING:\n\t\tp.next()\n\t\tvalue, err := parseStringLiteral(literal[1 : len(literal)-1])\n\t\tif err != nil {\n\t\t\tp.error(idx, err.Error())\n\t\t}\n\t\treturn &ast.StringLiteral{\n\t\t\tIdx:     idx,\n\t\t\tLiteral: literal,\n\t\t\tValue:   value,\n\t\t}\n\tcase token.NUMBER:\n\t\tp.next()\n\t\tvalue, err := parseNumberLiteral(literal)\n\t\tif err != nil {\n\t\t\tp.error(idx, err.Error())\n\t\t\tvalue = 0\n\t\t}\n\t\treturn &ast.NumberLiteral{\n\t\t\tIdx:     idx,\n\t\t\tLiteral: literal,\n\t\t\tValue:   value,\n\t\t}\n\tcase token.SLASH, token.QUOTIENT_ASSIGN:\n\t\treturn p.parseRegExpLiteral()\n\tcase token.LEFT_BRACE:\n\t\treturn p.parseObjectLiteral()\n\tcase token.LEFT_BRACKET:\n\t\treturn p.parseArrayLiteral()\n\tcase token.LEFT_PARENTHESIS:\n\t\tp.expect(token.LEFT_PARENTHESIS)\n\t\texpression := p.parseExpression()\n\t\tif p.mode&StoreComments != 0 {\n\t\t\tp.comments.Unset()\n\t\t}\n\t\tp.expect(token.RIGHT_PARENTHESIS)\n\t\treturn expression\n\tcase token.THIS:\n\t\tp.next()\n\t\treturn &ast.ThisExpression{\n\t\t\tIdx: idx,\n\t\t}\n\tcase token.FUNCTION:\n\t\treturn p.parseFunction(false)\n\t}\n\n\tp.errorUnexpectedToken(p.token)\n\tp.nextStatement()\n\treturn &ast.BadExpression{From: idx, To: p.idx}\n}\n\nfunc (p *parser) parseRegExpLiteral() *ast.RegExpLiteral {\n\toffset := p.chrOffset - 1 // Opening slash already gotten\n\tif p.token == token.QUOTIENT_ASSIGN {\n\t\toffset-- // =\n\t}\n\tidx := p.idxOf(offset)\n\n\tpattern, err := p.scanString(offset)\n\tendOffset := p.chrOffset\n\n\tp.next()\n\tif err == nil {\n\t\tpattern = pattern[1 : len(pattern)-1]\n\t}\n\n\tflags := \"\"\n\tif p.token == token.IDENTIFIER { // gim\n\t\tflags = p.literal\n\t\tendOffset = p.chrOffset\n\t\tp.next()\n\t}\n\n\tvar value string\n\t// TODO 15.10\n\t// Test during parsing that this is a valid regular expression\n\t// Sorry, (?=) and (?!) are invalid (for now)\n\tpat, err := TransformRegExp(pattern)\n\tif err != nil {\n\t\tif pat == \"\" || p.mode&IgnoreRegExpErrors == 0 {\n\t\t\tp.error(idx, \"Invalid regular expression: %s\", err.Error())\n\t\t}\n\t} else {\n\t\t_, err = regexp.Compile(pat)\n\t\tif err != nil {\n\t\t\t// We should not get here, ParseRegExp should catch any errors\n\t\t\tp.error(idx, \"Invalid regular expression: %s\", err.Error()[22:]) // Skip redundant \"parse regexp error\"\n\t\t} else {\n\t\t\tvalue = pat\n\t\t}\n\t}\n\n\tliteral := p.str[offset:endOffset]\n\n\treturn &ast.RegExpLiteral{\n\t\tIdx:     idx,\n\t\tLiteral: literal,\n\t\tPattern: pattern,\n\t\tFlags:   flags,\n\t\tValue:   value,\n\t}\n}\n\nfunc (p *parser) parseVariableDeclaration(declarationList *[]*ast.VariableExpression) ast.Expression {\n\tif p.token != token.IDENTIFIER {\n\t\tidx := p.expect(token.IDENTIFIER)\n\t\tp.nextStatement()\n\t\treturn &ast.BadExpression{From: idx, To: p.idx}\n\t}\n\n\tliteral := p.literal\n\tidx := p.idx\n\tp.next()\n\tnode := &ast.VariableExpression{\n\t\tName: literal,\n\t\tIdx:  idx,\n\t}\n\tif p.mode&StoreComments != 0 {\n\t\tp.comments.SetExpression(node)\n\t}\n\n\tif declarationList != nil {\n\t\t*declarationList = append(*declarationList, node)\n\t}\n\n\tif p.token == token.ASSIGN {\n\t\tif p.mode&StoreComments != 0 {\n\t\t\tp.comments.Unset()\n\t\t}\n\t\tp.next()\n\t\tnode.Initializer = p.parseAssignmentExpression()\n\t}\n\n\treturn node\n}\n\nfunc (p *parser) parseVariableDeclarationList(idx file.Idx) []ast.Expression {\n\tvar declarationList []*ast.VariableExpression // Avoid bad expressions\n\tvar list []ast.Expression\n\n\tfor {\n\t\tif p.mode&StoreComments != 0 {\n\t\t\tp.comments.MarkComments(ast.LEADING)\n\t\t}\n\t\tdecl := p.parseVariableDeclaration(&declarationList)\n\t\tlist = append(list, decl)\n\t\tif p.token != token.COMMA {\n\t\t\tbreak\n\t\t}\n\t\tif p.mode&StoreComments != 0 {\n\t\t\tp.comments.Unset()\n\t\t}\n\t\tp.next()\n\t}\n\n\tp.scope.declare(&ast.VariableDeclaration{\n\t\tVar:  idx,\n\t\tList: declarationList,\n\t})\n\n\treturn list\n}\n\nfunc (p *parser) parseObjectPropertyKey() (string, string) {\n\tidx, tkn, literal := p.idx, p.token, p.literal\n\tvalue := \"\"\n\tif p.mode&StoreComments != 0 {\n\t\tp.comments.MarkComments(ast.KEY)\n\t}\n\tp.next()\n\n\tswitch tkn {\n\tcase token.IDENTIFIER:\n\t\tvalue = literal\n\tcase token.NUMBER:\n\t\tvar err error\n\t\t_, err = parseNumberLiteral(literal)\n\t\tif err != nil {\n\t\t\tp.error(idx, err.Error())\n\t\t} else {\n\t\t\tvalue = literal\n\t\t}\n\tcase token.STRING:\n\t\tvar err error\n\t\tvalue, err = parseStringLiteral(literal[1 : len(literal)-1])\n\t\tif err != nil {\n\t\t\tp.error(idx, err.Error())\n\t\t}\n\tdefault:\n\t\t// null, false, class, etc.\n\t\tif matchIdentifier.MatchString(literal) {\n\t\t\tvalue = literal\n\t\t}\n\t}\n\treturn literal, value\n}\n\nfunc (p *parser) parseObjectProperty() ast.Property {\n\tliteral, value := p.parseObjectPropertyKey()\n\tif literal == \"get\" && p.token != token.COLON {\n\t\tidx := p.idx\n\t\t_, value = p.parseObjectPropertyKey()\n\t\tparameterList := p.parseFunctionParameterList()\n\n\t\tnode := &ast.FunctionLiteral{\n\t\t\tFunction:      idx,\n\t\t\tParameterList: parameterList,\n\t\t}\n\t\tp.parseFunctionBlock(node)\n\t\treturn ast.Property{\n\t\t\tKey:   value,\n\t\t\tKind:  \"get\",\n\t\t\tValue: node,\n\t\t}\n\t} else if literal == \"set\" && p.token != token.COLON {\n\t\tidx := p.idx\n\t\t_, value = p.parseObjectPropertyKey()\n\t\tparameterList := p.parseFunctionParameterList()\n\n\t\tnode := &ast.FunctionLiteral{\n\t\t\tFunction:      idx,\n\t\t\tParameterList: parameterList,\n\t\t}\n\t\tp.parseFunctionBlock(node)\n\t\treturn ast.Property{\n\t\t\tKey:   value,\n\t\t\tKind:  \"set\",\n\t\t\tValue: node,\n\t\t}\n\t}\n\n\tif p.mode&StoreComments != 0 {\n\t\tp.comments.MarkComments(ast.COLON)\n\t}\n\tp.expect(token.COLON)\n\n\texp := ast.Property{\n\t\tKey:   value,\n\t\tKind:  \"value\",\n\t\tValue: p.parseAssignmentExpression(),\n\t}\n\n\tif p.mode&StoreComments != 0 {\n\t\tp.comments.SetExpression(exp.Value)\n\t}\n\treturn exp\n}\n\nfunc (p *parser) parseObjectLiteral() ast.Expression {\n\tvar value []ast.Property\n\tidx0 := p.expect(token.LEFT_BRACE)\n\tfor p.token != token.RIGHT_BRACE && p.token != token.EOF {\n\t\tvalue = append(value, p.parseObjectProperty())\n\t\tif p.token == token.COMMA {\n\t\t\tif p.mode&StoreComments != 0 {\n\t\t\t\tp.comments.Unset()\n\t\t\t}\n\t\t\tp.next()\n\t\t\tcontinue\n\t\t}\n\t}\n\tif p.mode&StoreComments != 0 {\n\t\tp.comments.MarkComments(ast.FINAL)\n\t}\n\tidx1 := p.expect(token.RIGHT_BRACE)\n\n\treturn &ast.ObjectLiteral{\n\t\tLeftBrace:  idx0,\n\t\tRightBrace: idx1,\n\t\tValue:      value,\n\t}\n}\n\nfunc (p *parser) parseArrayLiteral() ast.Expression {\n\tidx0 := p.expect(token.LEFT_BRACKET)\n\tvar value []ast.Expression\n\tfor p.token != token.RIGHT_BRACKET && p.token != token.EOF {\n\t\tif p.token == token.COMMA {\n\t\t\t// This kind of comment requires a special empty expression node.\n\t\t\tempty := &ast.EmptyExpression{Begin: p.idx, End: p.idx}\n\n\t\t\tif p.mode&StoreComments != 0 {\n\t\t\t\tp.comments.SetExpression(empty)\n\t\t\t\tp.comments.Unset()\n\t\t\t}\n\t\t\tvalue = append(value, empty)\n\t\t\tp.next()\n\t\t\tcontinue\n\t\t}\n\n\t\texp := p.parseAssignmentExpression()\n\n\t\tvalue = append(value, exp)\n\t\tif p.token != token.RIGHT_BRACKET {\n\t\t\tif p.mode&StoreComments != 0 {\n\t\t\t\tp.comments.Unset()\n\t\t\t}\n\t\t\tp.expect(token.COMMA)\n\t\t}\n\t}\n\tif p.mode&StoreComments != 0 {\n\t\tp.comments.MarkComments(ast.FINAL)\n\t}\n\tidx1 := p.expect(token.RIGHT_BRACKET)\n\n\treturn &ast.ArrayLiteral{\n\t\tLeftBracket:  idx0,\n\t\tRightBracket: idx1,\n\t\tValue:        value,\n\t}\n}\n\nfunc (p *parser) parseArgumentList() (argumentList []ast.Expression, idx0, idx1 file.Idx) { //nolint:nonamedreturns\n\tif p.mode&StoreComments != 0 {\n\t\tp.comments.Unset()\n\t}\n\tidx0 = p.expect(token.LEFT_PARENTHESIS)\n\tfor p.token != token.RIGHT_PARENTHESIS {\n\t\texp := p.parseAssignmentExpression()\n\t\tif p.mode&StoreComments != 0 {\n\t\t\tp.comments.SetExpression(exp)\n\t\t}\n\t\targumentList = append(argumentList, exp)\n\t\tif p.token != token.COMMA {\n\t\t\tbreak\n\t\t}\n\t\tif p.mode&StoreComments != 0 {\n\t\t\tp.comments.Unset()\n\t\t}\n\t\tp.next()\n\t}\n\tif p.mode&StoreComments != 0 {\n\t\tp.comments.Unset()\n\t}\n\tidx1 = p.expect(token.RIGHT_PARENTHESIS)\n\treturn\n}\n\nfunc (p *parser) parseCallExpression(left ast.Expression) ast.Expression {\n\targumentList, idx0, idx1 := p.parseArgumentList()\n\texp := &ast.CallExpression{\n\t\tCallee:           left,\n\t\tLeftParenthesis:  idx0,\n\t\tArgumentList:     argumentList,\n\t\tRightParenthesis: idx1,\n\t}\n\n\tif p.mode&StoreComments != 0 {\n\t\tp.comments.SetExpression(exp)\n\t}\n\treturn exp\n}\n\nfunc (p *parser) parseDotMember(left ast.Expression) ast.Expression {\n\tperiod := p.expect(token.PERIOD)\n\n\tliteral := p.literal\n\tidx := p.idx\n\n\tif !matchIdentifier.MatchString(literal) {\n\t\tp.expect(token.IDENTIFIER)\n\t\tp.nextStatement()\n\t\treturn &ast.BadExpression{From: period, To: p.idx}\n\t}\n\n\tp.next()\n\n\treturn &ast.DotExpression{\n\t\tLeft: left,\n\t\tIdentifier: &ast.Identifier{\n\t\t\tIdx:  idx,\n\t\t\tName: literal,\n\t\t},\n\t}\n}\n\nfunc (p *parser) parseBracketMember(left ast.Expression) ast.Expression {\n\tidx0 := p.expect(token.LEFT_BRACKET)\n\tmember := p.parseExpression()\n\tidx1 := p.expect(token.RIGHT_BRACKET)\n\treturn &ast.BracketExpression{\n\t\tLeftBracket:  idx0,\n\t\tLeft:         left,\n\t\tMember:       member,\n\t\tRightBracket: idx1,\n\t}\n}\n\nfunc (p *parser) parseNewExpression() ast.Expression {\n\tidx := p.expect(token.NEW)\n\tcallee := p.parseLeftHandSideExpression()\n\tnode := &ast.NewExpression{\n\t\tNew:    idx,\n\t\tCallee: callee,\n\t}\n\tif p.token == token.LEFT_PARENTHESIS {\n\t\targumentList, idx0, idx1 := p.parseArgumentList()\n\t\tnode.ArgumentList = argumentList\n\t\tnode.LeftParenthesis = idx0\n\t\tnode.RightParenthesis = idx1\n\t}\n\n\tif p.mode&StoreComments != 0 {\n\t\tp.comments.SetExpression(node)\n\t}\n\n\treturn node\n}\n\nfunc (p *parser) parseLeftHandSideExpression() ast.Expression {\n\tvar left ast.Expression\n\tif p.token == token.NEW {\n\t\tleft = p.parseNewExpression()\n\t} else {\n\t\tif p.mode&StoreComments != 0 {\n\t\t\tp.comments.MarkComments(ast.LEADING)\n\t\t\tp.comments.MarkPrimary()\n\t\t}\n\t\tleft = p.parsePrimaryExpression()\n\t}\n\n\tif p.mode&StoreComments != 0 {\n\t\tp.comments.SetExpression(left)\n\t}\n\n\tfor {\n\t\tswitch p.token {\n\t\tcase token.PERIOD:\n\t\t\tleft = p.parseDotMember(left)\n\t\tcase token.LEFT_BRACKET:\n\t\t\tleft = p.parseBracketMember(left)\n\t\tdefault:\n\t\t\treturn left\n\t\t}\n\t}\n}\n\nfunc (p *parser) parseLeftHandSideExpressionAllowCall() ast.Expression {\n\tallowIn := p.scope.allowIn\n\tp.scope.allowIn = true\n\tdefer func() {\n\t\tp.scope.allowIn = allowIn\n\t}()\n\n\tvar left ast.Expression\n\tif p.token == token.NEW {\n\t\tvar newComments []*ast.Comment\n\t\tif p.mode&StoreComments != 0 {\n\t\t\tnewComments = p.comments.FetchAll()\n\t\t\tp.comments.MarkComments(ast.LEADING)\n\t\t\tp.comments.MarkPrimary()\n\t\t}\n\t\tleft = p.parseNewExpression()\n\t\tif p.mode&StoreComments != 0 {\n\t\t\tp.comments.CommentMap.AddComments(left, newComments, ast.LEADING)\n\t\t}\n\t} else {\n\t\tif p.mode&StoreComments != 0 {\n\t\t\tp.comments.MarkComments(ast.LEADING)\n\t\t\tp.comments.MarkPrimary()\n\t\t}\n\t\tleft = p.parsePrimaryExpression()\n\t}\n\n\tif p.mode&StoreComments != 0 {\n\t\tp.comments.SetExpression(left)\n\t}\n\n\tfor {\n\t\tswitch p.token {\n\t\tcase token.PERIOD:\n\t\t\tleft = p.parseDotMember(left)\n\t\tcase token.LEFT_BRACKET:\n\t\t\tleft = p.parseBracketMember(left)\n\t\tcase token.LEFT_PARENTHESIS:\n\t\t\tleft = p.parseCallExpression(left)\n\t\tdefault:\n\t\t\treturn left\n\t\t}\n\t}\n}\n\nfunc (p *parser) parsePostfixExpression() ast.Expression {\n\toperand := p.parseLeftHandSideExpressionAllowCall()\n\n\tswitch p.token {\n\tcase token.INCREMENT, token.DECREMENT:\n\t\t// Make sure there is no line terminator here\n\t\tif p.implicitSemicolon {\n\t\t\tbreak\n\t\t}\n\t\ttkn := p.token\n\t\tidx := p.idx\n\t\tif p.mode&StoreComments != 0 {\n\t\t\tp.comments.Unset()\n\t\t}\n\t\tp.next()\n\t\tswitch operand.(type) {\n\t\tcase *ast.Identifier, *ast.DotExpression, *ast.BracketExpression:\n\t\tdefault:\n\t\t\tp.error(idx, \"invalid left-hand side in assignment\")\n\t\t\tp.nextStatement()\n\t\t\treturn &ast.BadExpression{From: idx, To: p.idx}\n\t\t}\n\t\texp := &ast.UnaryExpression{\n\t\t\tOperator: tkn,\n\t\t\tIdx:      idx,\n\t\t\tOperand:  operand,\n\t\t\tPostfix:  true,\n\t\t}\n\n\t\tif p.mode&StoreComments != 0 {\n\t\t\tp.comments.SetExpression(exp)\n\t\t}\n\n\t\treturn exp\n\t}\n\n\treturn operand\n}\n\nfunc (p *parser) parseUnaryExpression() ast.Expression {\n\tswitch p.token {\n\tcase token.PLUS, token.MINUS, token.NOT, token.BITWISE_NOT:\n\t\tfallthrough\n\tcase token.DELETE, token.VOID, token.TYPEOF:\n\t\ttkn := p.token\n\t\tidx := p.idx\n\t\tif p.mode&StoreComments != 0 {\n\t\t\tp.comments.Unset()\n\t\t}\n\t\tp.next()\n\n\t\treturn &ast.UnaryExpression{\n\t\t\tOperator: tkn,\n\t\t\tIdx:      idx,\n\t\t\tOperand:  p.parseUnaryExpression(),\n\t\t}\n\tcase token.INCREMENT, token.DECREMENT:\n\t\ttkn := p.token\n\t\tidx := p.idx\n\t\tif p.mode&StoreComments != 0 {\n\t\t\tp.comments.Unset()\n\t\t}\n\t\tp.next()\n\t\toperand := p.parseUnaryExpression()\n\t\tswitch operand.(type) {\n\t\tcase *ast.Identifier, *ast.DotExpression, *ast.BracketExpression:\n\t\tdefault:\n\t\t\tp.error(idx, \"invalid left-hand side in assignment\")\n\t\t\tp.nextStatement()\n\t\t\treturn &ast.BadExpression{From: idx, To: p.idx}\n\t\t}\n\t\treturn &ast.UnaryExpression{\n\t\t\tOperator: tkn,\n\t\t\tIdx:      idx,\n\t\t\tOperand:  operand,\n\t\t}\n\t}\n\n\treturn p.parsePostfixExpression()\n}\n\nfunc (p *parser) parseMultiplicativeExpression() ast.Expression {\n\tnext := p.parseUnaryExpression\n\tleft := next()\n\n\tfor p.token == token.MULTIPLY || p.token == token.SLASH ||\n\t\tp.token == token.REMAINDER {\n\t\ttkn := p.token\n\t\tif p.mode&StoreComments != 0 {\n\t\t\tp.comments.Unset()\n\t\t}\n\t\tp.next()\n\n\t\tleft = &ast.BinaryExpression{\n\t\t\tOperator: tkn,\n\t\t\tLeft:     left,\n\t\t\tRight:    next(),\n\t\t}\n\t}\n\n\treturn left\n}\n\nfunc (p *parser) parseAdditiveExpression() ast.Expression {\n\tnext := p.parseMultiplicativeExpression\n\tleft := next()\n\n\tfor p.token == token.PLUS || p.token == token.MINUS {\n\t\ttkn := p.token\n\t\tif p.mode&StoreComments != 0 {\n\t\t\tp.comments.Unset()\n\t\t}\n\t\tp.next()\n\n\t\tleft = &ast.BinaryExpression{\n\t\t\tOperator: tkn,\n\t\t\tLeft:     left,\n\t\t\tRight:    next(),\n\t\t}\n\t}\n\n\treturn left\n}\n\nfunc (p *parser) parseShiftExpression() ast.Expression {\n\tnext := p.parseAdditiveExpression\n\tleft := next()\n\n\tfor p.token == token.SHIFT_LEFT || p.token == token.SHIFT_RIGHT ||\n\t\tp.token == token.UNSIGNED_SHIFT_RIGHT {\n\t\ttkn := p.token\n\t\tif p.mode&StoreComments != 0 {\n\t\t\tp.comments.Unset()\n\t\t}\n\t\tp.next()\n\n\t\tleft = &ast.BinaryExpression{\n\t\t\tOperator: tkn,\n\t\t\tLeft:     left,\n\t\t\tRight:    next(),\n\t\t}\n\t}\n\n\treturn left\n}\n\nfunc (p *parser) parseRelationalExpression() ast.Expression {\n\tnext := p.parseShiftExpression\n\tleft := next()\n\n\tallowIn := p.scope.allowIn\n\tp.scope.allowIn = true\n\tdefer func() {\n\t\tp.scope.allowIn = allowIn\n\t}()\n\n\tswitch p.token {\n\tcase token.LESS, token.LESS_OR_EQUAL, token.GREATER, token.GREATER_OR_EQUAL:\n\t\ttkn := p.token\n\t\tif p.mode&StoreComments != 0 {\n\t\t\tp.comments.Unset()\n\t\t}\n\t\tp.next()\n\n\t\texp := &ast.BinaryExpression{\n\t\t\tOperator:   tkn,\n\t\t\tLeft:       left,\n\t\t\tRight:      p.parseRelationalExpression(),\n\t\t\tComparison: true,\n\t\t}\n\t\treturn exp\n\tcase token.INSTANCEOF:\n\t\ttkn := p.token\n\t\tif p.mode&StoreComments != 0 {\n\t\t\tp.comments.Unset()\n\t\t}\n\t\tp.next()\n\n\t\texp := &ast.BinaryExpression{\n\t\t\tOperator: tkn,\n\t\t\tLeft:     left,\n\t\t\tRight:    p.parseRelationalExpression(),\n\t\t}\n\t\treturn exp\n\tcase token.IN:\n\t\tif !allowIn {\n\t\t\treturn left\n\t\t}\n\t\ttkn := p.token\n\t\tif p.mode&StoreComments != 0 {\n\t\t\tp.comments.Unset()\n\t\t}\n\t\tp.next()\n\n\t\texp := &ast.BinaryExpression{\n\t\t\tOperator: tkn,\n\t\t\tLeft:     left,\n\t\t\tRight:    p.parseRelationalExpression(),\n\t\t}\n\t\treturn exp\n\t}\n\n\treturn left\n}\n\nfunc (p *parser) parseEqualityExpression() ast.Expression {\n\tnext := p.parseRelationalExpression\n\tleft := next()\n\n\tfor p.token == token.EQUAL || p.token == token.NOT_EQUAL ||\n\t\tp.token == token.STRICT_EQUAL || p.token == token.STRICT_NOT_EQUAL {\n\t\ttkn := p.token\n\t\tif p.mode&StoreComments != 0 {\n\t\t\tp.comments.Unset()\n\t\t}\n\t\tp.next()\n\n\t\tleft = &ast.BinaryExpression{\n\t\t\tOperator:   tkn,\n\t\t\tLeft:       left,\n\t\t\tRight:      next(),\n\t\t\tComparison: true,\n\t\t}\n\t}\n\n\treturn left\n}\n\nfunc (p *parser) parseBitwiseAndExpression() ast.Expression {\n\tnext := p.parseEqualityExpression\n\tleft := next()\n\n\tfor p.token == token.AND {\n\t\tif p.mode&StoreComments != 0 {\n\t\t\tp.comments.Unset()\n\t\t}\n\t\ttkn := p.token\n\t\tp.next()\n\n\t\tleft = &ast.BinaryExpression{\n\t\t\tOperator: tkn,\n\t\t\tLeft:     left,\n\t\t\tRight:    next(),\n\t\t}\n\t}\n\n\treturn left\n}\n\nfunc (p *parser) parseBitwiseExclusiveOrExpression() ast.Expression {\n\tnext := p.parseBitwiseAndExpression\n\tleft := next()\n\n\tfor p.token == token.EXCLUSIVE_OR {\n\t\tif p.mode&StoreComments != 0 {\n\t\t\tp.comments.Unset()\n\t\t}\n\t\ttkn := p.token\n\t\tp.next()\n\n\t\tleft = &ast.BinaryExpression{\n\t\t\tOperator: tkn,\n\t\t\tLeft:     left,\n\t\t\tRight:    next(),\n\t\t}\n\t}\n\n\treturn left\n}\n\nfunc (p *parser) parseBitwiseOrExpression() ast.Expression {\n\tnext := p.parseBitwiseExclusiveOrExpression\n\tleft := next()\n\n\tfor p.token == token.OR {\n\t\tif p.mode&StoreComments != 0 {\n\t\t\tp.comments.Unset()\n\t\t}\n\t\ttkn := p.token\n\t\tp.next()\n\n\t\tleft = &ast.BinaryExpression{\n\t\t\tOperator: tkn,\n\t\t\tLeft:     left,\n\t\t\tRight:    next(),\n\t\t}\n\t}\n\n\treturn left\n}\n\nfunc (p *parser) parseLogicalAndExpression() ast.Expression {\n\tnext := p.parseBitwiseOrExpression\n\tleft := next()\n\n\tfor p.token == token.LOGICAL_AND {\n\t\tif p.mode&StoreComments != 0 {\n\t\t\tp.comments.Unset()\n\t\t}\n\t\ttkn := p.token\n\t\tp.next()\n\n\t\tleft = &ast.BinaryExpression{\n\t\t\tOperator: tkn,\n\t\t\tLeft:     left,\n\t\t\tRight:    next(),\n\t\t}\n\t}\n\n\treturn left\n}\n\nfunc (p *parser) parseLogicalOrExpression() ast.Expression {\n\tnext := p.parseLogicalAndExpression\n\tleft := next()\n\n\tfor p.token == token.LOGICAL_OR {\n\t\tif p.mode&StoreComments != 0 {\n\t\t\tp.comments.Unset()\n\t\t}\n\t\ttkn := p.token\n\t\tp.next()\n\n\t\tleft = &ast.BinaryExpression{\n\t\t\tOperator: tkn,\n\t\t\tLeft:     left,\n\t\t\tRight:    next(),\n\t\t}\n\t}\n\n\treturn left\n}\n\nfunc (p *parser) parseConditionalExpression() ast.Expression {\n\tleft := p.parseLogicalOrExpression()\n\n\tif p.token == token.QUESTION_MARK {\n\t\tif p.mode&StoreComments != 0 {\n\t\t\tp.comments.Unset()\n\t\t}\n\t\tp.next()\n\n\t\tconsequent := p.parseAssignmentExpression()\n\t\tif p.mode&StoreComments != 0 {\n\t\t\tp.comments.Unset()\n\t\t}\n\t\tp.expect(token.COLON)\n\t\texp := &ast.ConditionalExpression{\n\t\t\tTest:       left,\n\t\t\tConsequent: consequent,\n\t\t\tAlternate:  p.parseAssignmentExpression(),\n\t\t}\n\n\t\treturn exp\n\t}\n\n\treturn left\n}\n\nfunc (p *parser) parseAssignmentExpression() ast.Expression {\n\tleft := p.parseConditionalExpression()\n\tvar operator token.Token\n\tswitch p.token {\n\tcase token.ASSIGN:\n\t\toperator = p.token\n\tcase token.ADD_ASSIGN:\n\t\toperator = token.PLUS\n\tcase token.SUBTRACT_ASSIGN:\n\t\toperator = token.MINUS\n\tcase token.MULTIPLY_ASSIGN:\n\t\toperator = token.MULTIPLY\n\tcase token.QUOTIENT_ASSIGN:\n\t\toperator = token.SLASH\n\tcase token.REMAINDER_ASSIGN:\n\t\toperator = token.REMAINDER\n\tcase token.AND_ASSIGN:\n\t\toperator = token.AND\n\tcase token.AND_NOT_ASSIGN:\n\t\toperator = token.AND_NOT\n\tcase token.OR_ASSIGN:\n\t\toperator = token.OR\n\tcase token.EXCLUSIVE_OR_ASSIGN:\n\t\toperator = token.EXCLUSIVE_OR\n\tcase token.SHIFT_LEFT_ASSIGN:\n\t\toperator = token.SHIFT_LEFT\n\tcase token.SHIFT_RIGHT_ASSIGN:\n\t\toperator = token.SHIFT_RIGHT\n\tcase token.UNSIGNED_SHIFT_RIGHT_ASSIGN:\n\t\toperator = token.UNSIGNED_SHIFT_RIGHT\n\t}\n\n\tif operator != 0 {\n\t\tidx := p.idx\n\t\tif p.mode&StoreComments != 0 {\n\t\t\tp.comments.Unset()\n\t\t}\n\t\tp.next()\n\t\tswitch left.(type) {\n\t\tcase *ast.Identifier, *ast.DotExpression, *ast.BracketExpression:\n\t\tdefault:\n\t\t\tp.error(left.Idx0(), \"invalid left-hand side in assignment\")\n\t\t\tp.nextStatement()\n\t\t\treturn &ast.BadExpression{From: idx, To: p.idx}\n\t\t}\n\n\t\texp := &ast.AssignExpression{\n\t\t\tLeft:     left,\n\t\t\tOperator: operator,\n\t\t\tRight:    p.parseAssignmentExpression(),\n\t\t}\n\n\t\tif p.mode&StoreComments != 0 {\n\t\t\tp.comments.SetExpression(exp)\n\t\t}\n\n\t\treturn exp\n\t}\n\n\treturn left\n}\n\nfunc (p *parser) parseExpression() ast.Expression {\n\tnext := p.parseAssignmentExpression\n\tleft := next()\n\n\tif p.token == token.COMMA {\n\t\tsequence := []ast.Expression{left}\n\t\tfor {\n\t\t\tif p.token != token.COMMA {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tp.next()\n\t\t\tsequence = append(sequence, next())\n\t\t}\n\t\treturn &ast.SequenceExpression{\n\t\t\tSequence: sequence,\n\t\t}\n\t}\n\n\treturn left\n}\n"
  },
  {
    "path": "parser/lexer.go",
    "content": "package parser\n\nimport (\n\t\"bytes\"\n\t\"errors\"\n\t\"fmt\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n\t\"unicode\"\n\t\"unicode/utf8\"\n\n\t\"github.com/robertkrimen/otto/ast\"\n\t\"github.com/robertkrimen/otto/file\"\n\t\"github.com/robertkrimen/otto/token\"\n)\n\ntype chr struct { //nolint:unused\n\tvalue rune\n\twidth int\n}\n\nvar matchIdentifier = regexp.MustCompile(`^[$_\\p{L}][$_\\p{L}\\d}]*$`)\n\nfunc isDecimalDigit(chr rune) bool {\n\treturn '0' <= chr && chr <= '9'\n}\n\nfunc digitValue(chr rune) int {\n\tswitch {\n\tcase '0' <= chr && chr <= '9':\n\t\treturn int(chr - '0')\n\tcase 'a' <= chr && chr <= 'f':\n\t\treturn int(chr - 'a' + 10)\n\tcase 'A' <= chr && chr <= 'F':\n\t\treturn int(chr - 'A' + 10)\n\t}\n\treturn 16 // Larger than any legal digit value\n}\n\n// See https://www.unicode.org/reports/tr31/ for reference on ID_Start and ID_Continue.\nvar includeIDStart = []*unicode.RangeTable{\n\tunicode.Lu,\n\tunicode.Ll,\n\tunicode.Lt,\n\tunicode.Lm,\n\tunicode.Lo,\n\tunicode.Nl,\n\tunicode.Other_ID_Start,\n}\n\nvar includeIDContinue = []*unicode.RangeTable{\n\tunicode.Lu,\n\tunicode.Ll,\n\tunicode.Lt,\n\tunicode.Lm,\n\tunicode.Lo,\n\tunicode.Nl,\n\tunicode.Other_ID_Start,\n\tunicode.Mn,\n\tunicode.Mc,\n\tunicode.Nd,\n\tunicode.Pc,\n\tunicode.Other_ID_Continue,\n}\n\nvar exclude = []*unicode.RangeTable{\n\tunicode.Pattern_Syntax,\n\tunicode.Pattern_White_Space,\n}\n\nfunc unicodeIDStart(r rune) bool {\n\tif unicode.In(r, exclude...) {\n\t\treturn false\n\t}\n\n\treturn unicode.In(r, includeIDStart...)\n}\n\nfunc unicodeIDContinue(r rune) bool {\n\tif unicode.In(r, exclude...) {\n\t\treturn false\n\t}\n\n\treturn unicode.In(r, includeIDContinue...)\n}\n\nfunc isDigit(chr rune, base int) bool {\n\treturn digitValue(chr) < base\n}\n\nfunc isIdentifierStart(chr rune) bool {\n\treturn chr == '$' || chr == '_' || chr == '\\\\' ||\n\t\t'a' <= chr && chr <= 'z' || 'A' <= chr && chr <= 'Z' ||\n\t\tchr >= utf8.RuneSelf && unicodeIDStart(chr)\n}\n\nfunc isIdentifierPart(chr rune) bool {\n\treturn chr == '$' || chr == '_' || chr == '\\\\' ||\n\t\t'a' <= chr && chr <= 'z' || 'A' <= chr && chr <= 'Z' ||\n\t\t'0' <= chr && chr <= '9' ||\n\t\tchr >= utf8.RuneSelf && unicodeIDContinue(chr)\n}\n\nfunc (p *parser) scanIdentifier() (string, error) {\n\toffset := p.chrOffset\n\tparse := false\n\tfor isIdentifierPart(p.chr) {\n\t\tif p.chr == '\\\\' {\n\t\t\tdistance := p.chrOffset - offset\n\t\t\tp.read()\n\t\t\tif p.chr != 'u' {\n\t\t\t\treturn \"\", fmt.Errorf(\"invalid identifier escape character: %c (%s)\", p.chr, string(p.chr))\n\t\t\t}\n\t\t\tparse = true\n\t\t\tvar value rune\n\t\t\tfor range 4 {\n\t\t\t\tp.read()\n\t\t\t\tdecimal, ok := hex2decimal(byte(p.chr))\n\t\t\t\tif !ok {\n\t\t\t\t\treturn \"\", fmt.Errorf(\"invalid identifier escape character: %c (%s)\", p.chr, string(p.chr))\n\t\t\t\t}\n\t\t\t\tvalue = value<<4 | decimal\n\t\t\t}\n\t\t\tswitch {\n\t\t\tcase value == '\\\\':\n\t\t\t\treturn \"\", fmt.Errorf(\"invalid identifier escape value: %c (%s)\", value, string(value))\n\t\t\tcase distance == 0:\n\t\t\t\tif !isIdentifierStart(value) {\n\t\t\t\t\treturn \"\", fmt.Errorf(\"invalid identifier escape value: %c (%s)\", value, string(value))\n\t\t\t\t}\n\t\t\tcase distance > 0:\n\t\t\t\tif !isIdentifierPart(value) {\n\t\t\t\t\treturn \"\", fmt.Errorf(\"invalid identifier escape value: %c (%s)\", value, string(value))\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tp.read()\n\t}\n\tliteral := p.str[offset:p.chrOffset]\n\tif parse {\n\t\treturn parseStringLiteral(literal)\n\t}\n\treturn literal, nil\n}\n\n// 7.2.\nfunc isLineWhiteSpace(chr rune) bool { //nolint:unused, deadcode\n\tswitch chr {\n\tcase '\\u0009', '\\u000b', '\\u000c', '\\u0020', '\\u00a0', '\\ufeff':\n\t\treturn true\n\tcase '\\u000a', '\\u000d', '\\u2028', '\\u2029':\n\t\treturn false\n\tcase '\\u0085':\n\t\treturn false\n\t}\n\treturn unicode.IsSpace(chr)\n}\n\n// 7.3.\nfunc isLineTerminator(chr rune) bool {\n\tswitch chr {\n\tcase '\\u000a', '\\u000d', '\\u2028', '\\u2029':\n\t\treturn true\n\t}\n\treturn false\n}\n\nfunc (p *parser) scan() (tkn token.Token, literal string, idx file.Idx) { //nolint:nonamedreturns\n\tp.implicitSemicolon = false\n\n\tfor {\n\t\tp.skipWhiteSpace()\n\n\t\tidx = p.idxOf(p.chrOffset)\n\t\tinsertSemicolon := false\n\n\t\tswitch chr := p.chr; {\n\t\tcase isIdentifierStart(chr):\n\t\t\tvar err error\n\t\t\tliteral, err = p.scanIdentifier()\n\t\t\tif err != nil {\n\t\t\t\ttkn = token.ILLEGAL\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tif len(literal) > 1 {\n\t\t\t\t// Keywords are longer than 1 character, avoid lookup otherwise\n\t\t\t\tvar strict bool\n\t\t\t\ttkn, strict = token.IsKeyword(literal)\n\n\t\t\t\tswitch tkn {\n\t\t\t\tcase 0: // Not a keyword\n\t\t\t\t\tswitch literal {\n\t\t\t\t\tcase \"true\", \"false\":\n\t\t\t\t\t\tp.insertSemicolon = true\n\t\t\t\t\t\treturn token.BOOLEAN, literal, idx\n\t\t\t\t\tcase \"null\":\n\t\t\t\t\t\tp.insertSemicolon = true\n\t\t\t\t\t\treturn token.NULL, literal, idx\n\t\t\t\t\t}\n\t\t\t\tcase token.KEYWORD:\n\t\t\t\t\tif strict {\n\t\t\t\t\t\t// TODO If strict and in strict mode, then this is not a break\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\treturn token.KEYWORD, literal, idx\n\n\t\t\t\tcase\n\t\t\t\t\ttoken.THIS,\n\t\t\t\t\ttoken.BREAK,\n\t\t\t\t\ttoken.THROW, // A newline after a throw is not allowed, but we need to detect it\n\t\t\t\t\ttoken.RETURN,\n\t\t\t\t\ttoken.CONTINUE,\n\t\t\t\t\ttoken.DEBUGGER:\n\t\t\t\t\tp.insertSemicolon = true\n\t\t\t\t\treturn tkn, literal, idx\n\n\t\t\t\tdefault:\n\t\t\t\t\treturn tkn, literal, idx\n\t\t\t\t}\n\t\t\t}\n\t\t\tp.insertSemicolon = true\n\t\t\treturn token.IDENTIFIER, literal, idx\n\t\tcase '0' <= chr && chr <= '9':\n\t\t\tp.insertSemicolon = true\n\t\t\ttkn, literal = p.scanNumericLiteral(false)\n\t\t\treturn tkn, literal, idx\n\t\tdefault:\n\t\t\tp.read()\n\t\t\tswitch chr {\n\t\t\tcase -1:\n\t\t\t\tif p.insertSemicolon {\n\t\t\t\t\tp.insertSemicolon = false\n\t\t\t\t\tp.implicitSemicolon = true\n\t\t\t\t}\n\t\t\t\ttkn = token.EOF\n\t\t\tcase '\\r', '\\n', '\\u2028', '\\u2029':\n\t\t\t\tp.insertSemicolon = false\n\t\t\t\tp.implicitSemicolon = true\n\t\t\t\tp.comments.AtLineBreak()\n\t\t\t\tcontinue\n\t\t\tcase ':':\n\t\t\t\ttkn = token.COLON\n\t\t\tcase '.':\n\t\t\t\tif digitValue(p.chr) < 10 {\n\t\t\t\t\tinsertSemicolon = true\n\t\t\t\t\ttkn, literal = p.scanNumericLiteral(true)\n\t\t\t\t} else {\n\t\t\t\t\ttkn = token.PERIOD\n\t\t\t\t}\n\t\t\tcase ',':\n\t\t\t\ttkn = token.COMMA\n\t\t\tcase ';':\n\t\t\t\ttkn = token.SEMICOLON\n\t\t\tcase '(':\n\t\t\t\ttkn = token.LEFT_PARENTHESIS\n\t\t\tcase ')':\n\t\t\t\ttkn = token.RIGHT_PARENTHESIS\n\t\t\t\tinsertSemicolon = true\n\t\t\tcase '[':\n\t\t\t\ttkn = token.LEFT_BRACKET\n\t\t\tcase ']':\n\t\t\t\ttkn = token.RIGHT_BRACKET\n\t\t\t\tinsertSemicolon = true\n\t\t\tcase '{':\n\t\t\t\ttkn = token.LEFT_BRACE\n\t\t\tcase '}':\n\t\t\t\ttkn = token.RIGHT_BRACE\n\t\t\t\tinsertSemicolon = true\n\t\t\tcase '+':\n\t\t\t\ttkn = p.switch3(token.PLUS, token.ADD_ASSIGN, '+', token.INCREMENT)\n\t\t\t\tif tkn == token.INCREMENT {\n\t\t\t\t\tinsertSemicolon = true\n\t\t\t\t}\n\t\t\tcase '-':\n\t\t\t\ttkn = p.switch3(token.MINUS, token.SUBTRACT_ASSIGN, '-', token.DECREMENT)\n\t\t\t\tif tkn == token.DECREMENT {\n\t\t\t\t\tinsertSemicolon = true\n\t\t\t\t}\n\t\t\tcase '*':\n\t\t\t\ttkn = p.switch2(token.MULTIPLY, token.MULTIPLY_ASSIGN)\n\t\t\tcase '/':\n\t\t\t\tswitch p.chr {\n\t\t\t\tcase '/':\n\t\t\t\t\tif p.mode&StoreComments != 0 {\n\t\t\t\t\t\tcomment := string(p.readSingleLineComment())\n\t\t\t\t\t\tp.comments.AddComment(ast.NewComment(comment, idx))\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tp.skipSingleLineComment()\n\t\t\t\t\tcontinue\n\t\t\t\tcase '*':\n\t\t\t\t\tif p.mode&StoreComments != 0 {\n\t\t\t\t\t\tcomment := string(p.readMultiLineComment())\n\t\t\t\t\t\tp.comments.AddComment(ast.NewComment(comment, idx))\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tp.skipMultiLineComment()\n\t\t\t\t\tcontinue\n\t\t\t\tdefault:\n\t\t\t\t\t// Could be division, could be RegExp literal\n\t\t\t\t\ttkn = p.switch2(token.SLASH, token.QUOTIENT_ASSIGN)\n\t\t\t\t\tinsertSemicolon = true\n\t\t\t\t}\n\t\t\tcase '%':\n\t\t\t\ttkn = p.switch2(token.REMAINDER, token.REMAINDER_ASSIGN)\n\t\t\tcase '^':\n\t\t\t\ttkn = p.switch2(token.EXCLUSIVE_OR, token.EXCLUSIVE_OR_ASSIGN)\n\t\t\tcase '<':\n\t\t\t\ttkn = p.switch4(token.LESS, token.LESS_OR_EQUAL, '<', token.SHIFT_LEFT, token.SHIFT_LEFT_ASSIGN)\n\t\t\tcase '>':\n\t\t\t\ttkn = p.switch6(token.GREATER, token.GREATER_OR_EQUAL, '>', token.SHIFT_RIGHT, token.SHIFT_RIGHT_ASSIGN, '>', token.UNSIGNED_SHIFT_RIGHT, token.UNSIGNED_SHIFT_RIGHT_ASSIGN)\n\t\t\tcase '=':\n\t\t\t\ttkn = p.switch2(token.ASSIGN, token.EQUAL)\n\t\t\t\tif tkn == token.EQUAL && p.chr == '=' {\n\t\t\t\t\tp.read()\n\t\t\t\t\ttkn = token.STRICT_EQUAL\n\t\t\t\t}\n\t\t\tcase '!':\n\t\t\t\ttkn = p.switch2(token.NOT, token.NOT_EQUAL)\n\t\t\t\tif tkn == token.NOT_EQUAL && p.chr == '=' {\n\t\t\t\t\tp.read()\n\t\t\t\t\ttkn = token.STRICT_NOT_EQUAL\n\t\t\t\t}\n\t\t\tcase '&':\n\t\t\t\tif p.chr == '^' {\n\t\t\t\t\tp.read()\n\t\t\t\t\ttkn = p.switch2(token.AND_NOT, token.AND_NOT_ASSIGN)\n\t\t\t\t} else {\n\t\t\t\t\ttkn = p.switch3(token.AND, token.AND_ASSIGN, '&', token.LOGICAL_AND)\n\t\t\t\t}\n\t\t\tcase '|':\n\t\t\t\ttkn = p.switch3(token.OR, token.OR_ASSIGN, '|', token.LOGICAL_OR)\n\t\t\tcase '~':\n\t\t\t\ttkn = token.BITWISE_NOT\n\t\t\tcase '?':\n\t\t\t\ttkn = token.QUESTION_MARK\n\t\t\tcase '\"', '\\'':\n\t\t\t\tinsertSemicolon = true\n\t\t\t\ttkn = token.STRING\n\t\t\t\tvar err error\n\t\t\t\tliteral, err = p.scanString(p.chrOffset - 1)\n\t\t\t\tif err != nil {\n\t\t\t\t\ttkn = token.ILLEGAL\n\t\t\t\t}\n\t\t\tdefault:\n\t\t\t\tp.errorUnexpected(idx, chr)\n\t\t\t\ttkn = token.ILLEGAL\n\t\t\t}\n\t\t}\n\t\tp.insertSemicolon = insertSemicolon\n\t\treturn tkn, literal, idx\n\t}\n}\n\nfunc (p *parser) switch2(tkn0, tkn1 token.Token) token.Token {\n\tif p.chr == '=' {\n\t\tp.read()\n\t\treturn tkn1\n\t}\n\treturn tkn0\n}\n\nfunc (p *parser) switch3(tkn0, tkn1 token.Token, chr2 rune, tkn2 token.Token) token.Token {\n\tif p.chr == '=' {\n\t\tp.read()\n\t\treturn tkn1\n\t}\n\tif p.chr == chr2 {\n\t\tp.read()\n\t\treturn tkn2\n\t}\n\treturn tkn0\n}\n\nfunc (p *parser) switch4(tkn0, tkn1 token.Token, chr2 rune, tkn2, tkn3 token.Token) token.Token {\n\tif p.chr == '=' {\n\t\tp.read()\n\t\treturn tkn1\n\t}\n\tif p.chr == chr2 {\n\t\tp.read()\n\t\tif p.chr == '=' {\n\t\t\tp.read()\n\t\t\treturn tkn3\n\t\t}\n\t\treturn tkn2\n\t}\n\treturn tkn0\n}\n\nfunc (p *parser) switch6(tkn0, tkn1 token.Token, chr2 rune, tkn2, tkn3 token.Token, chr3 rune, tkn4, tkn5 token.Token) token.Token {\n\tif p.chr == '=' {\n\t\tp.read()\n\t\treturn tkn1\n\t}\n\tif p.chr == chr2 {\n\t\tp.read()\n\t\tif p.chr == '=' {\n\t\t\tp.read()\n\t\t\treturn tkn3\n\t\t}\n\t\tif p.chr == chr3 {\n\t\t\tp.read()\n\t\t\tif p.chr == '=' {\n\t\t\t\tp.read()\n\t\t\t\treturn tkn5\n\t\t\t}\n\t\t\treturn tkn4\n\t\t}\n\t\treturn tkn2\n\t}\n\treturn tkn0\n}\n\nfunc (p *parser) chrAt(index int) chr { //nolint:unused\n\tvalue, width := utf8.DecodeRuneInString(p.str[index:])\n\treturn chr{\n\t\tvalue: value,\n\t\twidth: width,\n\t}\n}\n\nfunc (p *parser) peek() rune {\n\tif p.offset+1 < p.length {\n\t\treturn rune(p.str[p.offset+1])\n\t}\n\treturn -1\n}\n\nfunc (p *parser) read() {\n\tif p.offset < p.length {\n\t\tp.chrOffset = p.offset\n\t\tchr, width := rune(p.str[p.offset]), 1\n\t\tif chr >= utf8.RuneSelf { // !ASCII\n\t\t\tchr, width = utf8.DecodeRuneInString(p.str[p.offset:])\n\t\t\tif chr == utf8.RuneError && width == 1 {\n\t\t\t\tp.error(p.chrOffset, \"Invalid UTF-8 character\")\n\t\t\t}\n\t\t}\n\t\tp.offset += width\n\t\tp.chr = chr\n\t} else {\n\t\tp.chrOffset = p.length\n\t\tp.chr = -1 // EOF\n\t}\n}\n\n// This is here since the functions are so similar.\nfunc (p *regExpParser) read() {\n\tif p.offset < p.length {\n\t\tp.chrOffset = p.offset\n\t\tchr, width := rune(p.str[p.offset]), 1\n\t\tif chr >= utf8.RuneSelf { // !ASCII\n\t\t\tchr, width = utf8.DecodeRuneInString(p.str[p.offset:])\n\t\t\tif chr == utf8.RuneError && width == 1 {\n\t\t\t\tp.error(p.chrOffset, \"Invalid UTF-8 character\")\n\t\t\t}\n\t\t}\n\t\tp.offset += width\n\t\tp.chr = chr\n\t} else {\n\t\tp.chrOffset = p.length\n\t\tp.chr = -1 // EOF\n\t}\n}\n\nfunc (p *parser) readSingleLineComment() []rune {\n\tvar result []rune\n\tfor p.chr != -1 {\n\t\tp.read()\n\t\tif isLineTerminator(p.chr) {\n\t\t\treturn result\n\t\t}\n\t\tresult = append(result, p.chr)\n\t}\n\n\t// Get rid of the trailing -1\n\treturn result[:len(result)-1]\n}\n\nfunc (p *parser) readMultiLineComment() []rune {\n\tvar result []rune\n\tp.read()\n\tfor p.chr >= 0 {\n\t\tchr := p.chr\n\t\tp.read()\n\t\tif chr == '*' && p.chr == '/' {\n\t\t\tp.read()\n\t\t\treturn result\n\t\t}\n\n\t\tresult = append(result, chr)\n\t}\n\n\tp.errorUnexpected(0, p.chr)\n\n\treturn result\n}\n\nfunc (p *parser) skipSingleLineComment() {\n\tfor p.chr != -1 {\n\t\tp.read()\n\t\tif isLineTerminator(p.chr) {\n\t\t\treturn\n\t\t}\n\t}\n}\n\nfunc (p *parser) skipMultiLineComment() {\n\tp.read()\n\tfor p.chr >= 0 {\n\t\tchr := p.chr\n\t\tp.read()\n\t\tif chr == '*' && p.chr == '/' {\n\t\t\tp.read()\n\t\t\treturn\n\t\t}\n\t}\n\n\tp.errorUnexpected(0, p.chr)\n}\n\nfunc (p *parser) skipWhiteSpace() {\n\tfor {\n\t\tswitch p.chr {\n\t\tcase ' ', '\\t', '\\f', '\\v', '\\u00a0', '\\ufeff':\n\t\t\tp.read()\n\t\t\tcontinue\n\t\tcase '\\r':\n\t\t\tif p.peek() == '\\n' {\n\t\t\t\tp.comments.AtLineBreak()\n\t\t\t\tp.read()\n\t\t\t}\n\t\t\tfallthrough\n\t\tcase '\\u2028', '\\u2029', '\\n':\n\t\t\tif p.insertSemicolon {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tp.comments.AtLineBreak()\n\t\t\tp.read()\n\t\t\tcontinue\n\t\t}\n\t\tif p.chr >= utf8.RuneSelf {\n\t\t\tif unicode.IsSpace(p.chr) {\n\t\t\t\tp.read()\n\t\t\t\tcontinue\n\t\t\t}\n\t\t}\n\t\tbreak\n\t}\n}\n\nfunc (p *parser) scanMantissa(base int) {\n\tfor digitValue(p.chr) < base {\n\t\tp.read()\n\t}\n}\n\nfunc (p *parser) scanEscape(quote rune) {\n\tvar length, base uint32\n\tswitch p.chr {\n\t//    Octal:\n\t//    length, base, limit = 3, 8, 255\n\tcase 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\\\', '\"', '\\'', '0':\n\t\tp.read()\n\t\treturn\n\tcase '\\r', '\\n', '\\u2028', '\\u2029':\n\t\tp.scanNewline()\n\t\treturn\n\tcase 'x':\n\t\tp.read()\n\t\tlength, base = 2, 16\n\tcase 'u':\n\t\tp.read()\n\t\tlength, base = 4, 16\n\tdefault:\n\t\tp.read() // Always make progress\n\t\treturn\n\t}\n\n\tvar value uint32\n\tfor ; length > 0 && p.chr != quote && p.chr >= 0; length-- {\n\t\tdigit := uint32(digitValue(p.chr))\n\t\tif digit >= base {\n\t\t\tbreak\n\t\t}\n\t\tvalue = value*base + digit\n\t\tp.read()\n\t}\n}\n\nfunc (p *parser) scanString(offset int) (string, error) {\n\t// \" ' /\n\tquote := rune(p.str[offset])\n\n\tfor p.chr != quote {\n\t\tchr := p.chr\n\t\tif chr == '\\n' || chr == '\\r' || chr == '\\u2028' || chr == '\\u2029' || chr < 0 {\n\t\t\tgoto newline\n\t\t}\n\t\tp.read()\n\t\tswitch {\n\t\tcase chr == '\\\\':\n\t\t\tif quote == '/' {\n\t\t\t\tif p.chr == '\\n' || p.chr == '\\r' || p.chr == '\\u2028' || p.chr == '\\u2029' || p.chr < 0 {\n\t\t\t\t\tgoto newline\n\t\t\t\t}\n\t\t\t\tp.read()\n\t\t\t} else {\n\t\t\t\tp.scanEscape(quote)\n\t\t\t}\n\t\tcase chr == '[' && quote == '/':\n\t\t\t// Allow a slash (/) in a bracket character class ([...])\n\t\t\t// TODO Fix this, this is hacky...\n\t\t\tquote = -1\n\t\tcase chr == ']' && quote == -1:\n\t\t\tquote = '/'\n\t\t}\n\t}\n\n\t// \" ' /\n\tp.read()\n\n\treturn p.str[offset:p.chrOffset], nil\n\nnewline:\n\tp.scanNewline()\n\terr := \"String not terminated\"\n\tif quote == '/' {\n\t\terr = \"Invalid regular expression: missing /\"\n\t\tp.error(p.idxOf(offset), err)\n\t}\n\treturn \"\", errors.New(err)\n}\n\nfunc (p *parser) scanNewline() {\n\tif p.chr == '\\r' {\n\t\tp.read()\n\t\tif p.chr != '\\n' {\n\t\t\treturn\n\t\t}\n\t}\n\tp.read()\n}\n\nfunc hex2decimal(chr byte) (rune, bool) {\n\tr := rune(chr)\n\tswitch {\n\tcase '0' <= r && r <= '9':\n\t\treturn r - '0', true\n\tcase 'a' <= r && r <= 'f':\n\t\treturn r - 'a' + 10, true\n\tcase 'A' <= r && r <= 'F':\n\t\treturn r - 'A' + 10, true\n\tdefault:\n\t\treturn 0, false\n\t}\n}\n\nfunc parseNumberLiteral(literal string) (value interface{}, err error) { //nolint:nonamedreturns\n\t// TODO Is Uint okay? What about -MAX_UINT\n\tvalue, err = strconv.ParseInt(literal, 0, 64)\n\tif err == nil {\n\t\treturn value, nil\n\t}\n\n\tparseIntErr := err // Save this first error, just in case\n\n\tvalue, err = strconv.ParseFloat(literal, 64)\n\tif err == nil {\n\t\treturn value, nil\n\t} else if errors.Is(err, strconv.ErrRange) {\n\t\t// Infinity, etc.\n\t\treturn value, nil\n\t}\n\n\t// TODO(steve): Fix as this is assigning to err so we know the type.\n\t// Need to understand what this was trying to do?\n\terr = parseIntErr\n\n\tif errors.Is(err, strconv.ErrRange) {\n\t\tif len(literal) > 2 && literal[0] == '0' && (literal[1] == 'X' || literal[1] == 'x') {\n\t\t\t// Could just be a very large number (e.g. 0x8000000000000000)\n\t\t\tvar value float64\n\t\t\tliteral = literal[2:]\n\t\t\tfor _, chr := range literal {\n\t\t\t\tdigit := digitValue(chr)\n\t\t\t\tif digit >= 16 {\n\t\t\t\t\treturn nil, fmt.Errorf(\"illegal numeric literal: %v (>= 16)\", digit)\n\t\t\t\t}\n\t\t\t\tvalue = value*16 + float64(digit)\n\t\t\t}\n\t\t\treturn value, nil\n\t\t}\n\t}\n\n\treturn nil, errors.New(\"illegal numeric literal\")\n}\n\nfunc parseStringLiteral(literal string) (string, error) {\n\t// Best case scenario...\n\tif literal == \"\" {\n\t\treturn \"\", nil\n\t}\n\n\t// Slightly less-best case scenario...\n\tif !strings.ContainsRune(literal, '\\\\') {\n\t\treturn literal, nil\n\t}\n\n\tstr := literal\n\tbuffer := bytes.NewBuffer(make([]byte, 0, 3*len(literal)/2))\n\n\tfor len(str) > 0 {\n\t\tswitch chr := str[0]; {\n\t\t// We do not explicitly handle the case of the quote\n\t\t// value, which can be: \" ' /\n\t\t// This assumes we're already passed a partially well-formed literal\n\t\tcase chr >= utf8.RuneSelf:\n\t\t\tchr, size := utf8.DecodeRuneInString(str)\n\t\t\tbuffer.WriteRune(chr)\n\t\t\tstr = str[size:]\n\t\t\tcontinue\n\t\tcase chr != '\\\\':\n\t\t\tbuffer.WriteByte(chr)\n\t\t\tstr = str[1:]\n\t\t\tcontinue\n\t\t}\n\n\t\tif len(str) <= 1 {\n\t\t\tpanic(\"len(str) <= 1\")\n\t\t}\n\t\tchr := str[1]\n\t\tvar value rune\n\t\tif chr >= utf8.RuneSelf {\n\t\t\tstr = str[1:]\n\t\t\tvar size int\n\t\t\tvalue, size = utf8.DecodeRuneInString(str)\n\t\t\tstr = str[size:] // \\ + <character>\n\t\t} else {\n\t\t\tstr = str[2:] // \\<character>\n\t\t\tswitch chr {\n\t\t\tcase 'b':\n\t\t\t\tvalue = '\\b'\n\t\t\tcase 'f':\n\t\t\t\tvalue = '\\f'\n\t\t\tcase 'n':\n\t\t\t\tvalue = '\\n'\n\t\t\tcase 'r':\n\t\t\t\tvalue = '\\r'\n\t\t\tcase 't':\n\t\t\t\tvalue = '\\t'\n\t\t\tcase 'v':\n\t\t\t\tvalue = '\\v'\n\t\t\tcase 'x', 'u':\n\t\t\t\tsize := 0\n\t\t\t\tswitch chr {\n\t\t\t\tcase 'x':\n\t\t\t\t\tsize = 2\n\t\t\t\tcase 'u':\n\t\t\t\t\tsize = 4\n\t\t\t\t}\n\t\t\t\tif len(str) < size {\n\t\t\t\t\treturn \"\", fmt.Errorf(\"invalid escape: \\\\%s: len(%q) != %d\", string(chr), str, size)\n\t\t\t\t}\n\t\t\t\tfor j := range size {\n\t\t\t\t\tdecimal, ok := hex2decimal(str[j])\n\t\t\t\t\tif !ok {\n\t\t\t\t\t\treturn \"\", fmt.Errorf(\"invalid escape: \\\\%s: %q\", string(chr), str[:size])\n\t\t\t\t\t}\n\t\t\t\t\tvalue = value<<4 | decimal\n\t\t\t\t}\n\t\t\t\tstr = str[size:]\n\t\t\t\tif chr == 'x' {\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tif value > utf8.MaxRune {\n\t\t\t\t\tpanic(\"value > utf8.MaxRune\")\n\t\t\t\t}\n\t\t\tcase '0':\n\t\t\t\tif len(str) == 0 || '0' > str[0] || str[0] > '7' {\n\t\t\t\t\tvalue = 0\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t\tfallthrough\n\t\t\tcase '1', '2', '3', '4', '5', '6', '7':\n\t\t\t\t// TODO strict\n\t\t\t\tvalue = rune(chr) - '0'\n\t\t\t\tj := 0\n\t\t\t\tfor ; j < 2; j++ {\n\t\t\t\t\tif len(str) < j+1 {\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\n\t\t\t\t\tif ch := str[j]; '0' > ch || ch > '7' {\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tdecimal := rune(str[j]) - '0'\n\t\t\t\t\tvalue = (value << 3) | decimal\n\t\t\t\t}\n\t\t\t\tstr = str[j:]\n\t\t\tcase '\\\\':\n\t\t\t\tvalue = '\\\\'\n\t\t\tcase '\\'', '\"':\n\t\t\t\tvalue = rune(chr)\n\t\t\tcase '\\r':\n\t\t\t\tif len(str) > 0 {\n\t\t\t\t\tif str[0] == '\\n' {\n\t\t\t\t\t\tstr = str[1:]\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfallthrough\n\t\t\tcase '\\n':\n\t\t\t\tcontinue\n\t\t\tdefault:\n\t\t\t\tvalue = rune(chr)\n\t\t\t}\n\t\t}\n\t\tbuffer.WriteRune(value)\n\t}\n\n\treturn buffer.String(), nil\n}\n\nfunc (p *parser) scanNumericLiteral(decimalPoint bool) (token.Token, string) {\n\toffset := p.chrOffset\n\ttkn := token.NUMBER\n\n\tif decimalPoint {\n\t\toffset--\n\t\tp.scanMantissa(10)\n\t\tgoto exponent\n\t}\n\n\tif p.chr == '0' {\n\t\tchrOffset := p.chrOffset\n\t\tp.read()\n\t\tswitch p.chr {\n\t\tcase 'x', 'X':\n\t\t\t// Hexadecimal\n\t\t\tp.read()\n\t\t\tif isDigit(p.chr, 16) {\n\t\t\t\tp.read()\n\t\t\t} else {\n\t\t\t\treturn token.ILLEGAL, p.str[chrOffset:p.chrOffset]\n\t\t\t}\n\t\t\tp.scanMantissa(16)\n\n\t\t\tif p.chrOffset-chrOffset <= 2 {\n\t\t\t\t// Only \"0x\" or \"0X\"\n\t\t\t\tp.error(0, \"Illegal hexadecimal number\")\n\t\t\t}\n\n\t\t\tgoto hexadecimal\n\t\tcase '.':\n\t\t\t// Float\n\t\t\tgoto float\n\t\tdefault:\n\t\t\t// Octal, Float\n\t\t\tif p.chr == 'e' || p.chr == 'E' {\n\t\t\t\tgoto exponent\n\t\t\t}\n\t\t\tp.scanMantissa(8)\n\t\t\tif p.chr == '8' || p.chr == '9' {\n\t\t\t\treturn token.ILLEGAL, p.str[chrOffset:p.chrOffset]\n\t\t\t}\n\t\t\tgoto octal\n\t\t}\n\t}\n\n\tp.scanMantissa(10)\n\nfloat:\n\tif p.chr == '.' {\n\t\tp.read()\n\t\tp.scanMantissa(10)\n\t}\n\nexponent:\n\tif p.chr == 'e' || p.chr == 'E' {\n\t\tp.read()\n\t\tif p.chr == '-' || p.chr == '+' {\n\t\t\tp.read()\n\t\t}\n\t\tif isDecimalDigit(p.chr) {\n\t\t\tp.read()\n\t\t\tp.scanMantissa(10)\n\t\t} else {\n\t\t\treturn token.ILLEGAL, p.str[offset:p.chrOffset]\n\t\t}\n\t}\n\nhexadecimal:\noctal:\n\tif isIdentifierStart(p.chr) || isDecimalDigit(p.chr) {\n\t\treturn token.ILLEGAL, p.str[offset:p.chrOffset]\n\t}\n\n\treturn tkn, p.str[offset:p.chrOffset]\n}\n"
  },
  {
    "path": "parser/lexer_test.go",
    "content": "package parser\n\nimport (\n\t\"testing\"\n\n\t\"github.com/robertkrimen/otto/file\"\n\t\"github.com/robertkrimen/otto/terst\"\n\t\"github.com/robertkrimen/otto/token\"\n)\n\nvar (\n\ttt = terst.Terst\n\tis = terst.Is\n)\n\nfunc TestLexer(t *testing.T) {\n\ttt(t, func() {\n\t\tsetup := func(src string) *parser {\n\t\t\tparser := newParser(\"\", src, 1, nil)\n\t\t\treturn parser\n\t\t}\n\n\t\ttest := func(src string, test ...interface{}) {\n\t\t\tparser := setup(src)\n\t\t\tfor len(test) > 0 {\n\t\t\t\ttkn, literal, idx := parser.scan()\n\t\t\t\tif len(test) > 0 {\n\t\t\t\t\tis(tkn, test[0].(token.Token))\n\t\t\t\t\ttest = test[1:]\n\t\t\t\t}\n\t\t\t\tif len(test) > 0 {\n\t\t\t\t\tis(literal, test[0].(string))\n\t\t\t\t\ttest = test[1:]\n\t\t\t\t}\n\t\t\t\tif len(test) > 0 {\n\t\t\t\t\t// FIXME terst, Fix this so that cast to file.Idx is not necessary?\n\t\t\t\t\tis(idx, file.Idx(test[0].(int)))\n\t\t\t\t\ttest = test[1:]\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\ttest(\"\",\n\t\t\ttoken.EOF, \"\", 1,\n\t\t)\n\n\t\ttest(\"1\",\n\t\t\ttoken.NUMBER, \"1\", 1,\n\t\t\ttoken.EOF, \"\", 2,\n\t\t)\n\n\t\ttest(\".0\",\n\t\t\ttoken.NUMBER, \".0\", 1,\n\t\t\ttoken.EOF, \"\", 3,\n\t\t)\n\n\t\ttest(\"abc\",\n\t\t\ttoken.IDENTIFIER, \"abc\", 1,\n\t\t\ttoken.EOF, \"\", 4,\n\t\t)\n\n\t\ttest(\"abc(1)\",\n\t\t\ttoken.IDENTIFIER, \"abc\", 1,\n\t\t\ttoken.LEFT_PARENTHESIS, \"\", 4,\n\t\t\ttoken.NUMBER, \"1\", 5,\n\t\t\ttoken.RIGHT_PARENTHESIS, \"\", 6,\n\t\t\ttoken.EOF, \"\", 7,\n\t\t)\n\n\t\ttest(\".\",\n\t\t\ttoken.PERIOD, \"\", 1,\n\t\t\ttoken.EOF, \"\", 2,\n\t\t)\n\n\t\ttest(\"===.\",\n\t\t\ttoken.STRICT_EQUAL, \"\", 1,\n\t\t\ttoken.PERIOD, \"\", 4,\n\t\t\ttoken.EOF, \"\", 5,\n\t\t)\n\n\t\ttest(\">>>=.0\",\n\t\t\ttoken.UNSIGNED_SHIFT_RIGHT_ASSIGN, \"\", 1,\n\t\t\ttoken.NUMBER, \".0\", 5,\n\t\t\ttoken.EOF, \"\", 7,\n\t\t)\n\n\t\ttest(\">>>=0.0.\",\n\t\t\ttoken.UNSIGNED_SHIFT_RIGHT_ASSIGN, \"\", 1,\n\t\t\ttoken.NUMBER, \"0.0\", 5,\n\t\t\ttoken.PERIOD, \"\", 8,\n\t\t\ttoken.EOF, \"\", 9,\n\t\t)\n\n\t\ttest(\"\\\"abc\\\"\",\n\t\t\ttoken.STRING, \"\\\"abc\\\"\", 1,\n\t\t\ttoken.EOF, \"\", 6,\n\t\t)\n\n\t\ttest(\"abc = //\",\n\t\t\ttoken.IDENTIFIER, \"abc\", 1,\n\t\t\ttoken.ASSIGN, \"\", 5,\n\t\t\ttoken.EOF, \"\", 9,\n\t\t)\n\n\t\ttest(\"abc = /*test*/\",\n\t\t\ttoken.IDENTIFIER, \"abc\", 1,\n\t\t\ttoken.ASSIGN, \"\", 5,\n\t\t\ttoken.EOF, \"\", 15,\n\t\t)\n\n\t\ttest(\"abc = 1 / 2\",\n\t\t\ttoken.IDENTIFIER, \"abc\", 1,\n\t\t\ttoken.ASSIGN, \"\", 5,\n\t\t\ttoken.NUMBER, \"1\", 7,\n\t\t\ttoken.SLASH, \"\", 9,\n\t\t\ttoken.NUMBER, \"2\", 11,\n\t\t\ttoken.EOF, \"\", 12,\n\t\t)\n\n\t\ttest(\"xyzzy = 'Nothing happens.'\",\n\t\t\ttoken.IDENTIFIER, \"xyzzy\", 1,\n\t\t\ttoken.ASSIGN, \"\", 7,\n\t\t\ttoken.STRING, \"'Nothing happens.'\", 9,\n\t\t\ttoken.EOF, \"\", 27,\n\t\t)\n\n\t\ttest(\"abc = !false\",\n\t\t\ttoken.IDENTIFIER, \"abc\", 1,\n\t\t\ttoken.ASSIGN, \"\", 5,\n\t\t\ttoken.NOT, \"\", 7,\n\t\t\ttoken.BOOLEAN, \"false\", 8,\n\t\t\ttoken.EOF, \"\", 13,\n\t\t)\n\n\t\ttest(\"abc = !!true\",\n\t\t\ttoken.IDENTIFIER, \"abc\", 1,\n\t\t\ttoken.ASSIGN, \"\", 5,\n\t\t\ttoken.NOT, \"\", 7,\n\t\t\ttoken.NOT, \"\", 8,\n\t\t\ttoken.BOOLEAN, \"true\", 9,\n\t\t\ttoken.EOF, \"\", 13,\n\t\t)\n\n\t\ttest(\"abc *= 1\",\n\t\t\ttoken.IDENTIFIER, \"abc\", 1,\n\t\t\ttoken.MULTIPLY_ASSIGN, \"\", 5,\n\t\t\ttoken.NUMBER, \"1\", 8,\n\t\t\ttoken.EOF, \"\", 9,\n\t\t)\n\n\t\ttest(\"if 1 else\",\n\t\t\ttoken.IF, \"if\", 1,\n\t\t\ttoken.NUMBER, \"1\", 4,\n\t\t\ttoken.ELSE, \"else\", 6,\n\t\t\ttoken.EOF, \"\", 10,\n\t\t)\n\n\t\ttest(\"null\",\n\t\t\ttoken.NULL, \"null\", 1,\n\t\t\ttoken.EOF, \"\", 5,\n\t\t)\n\n\t\ttest(`\"\\u007a\\x79\\u000a\\x78\"`,\n\t\t\ttoken.STRING, \"\\\"\\\\u007a\\\\x79\\\\u000a\\\\x78\\\"\", 1,\n\t\t\ttoken.EOF, \"\", 23,\n\t\t)\n\n\t\ttest(`\"[First line \\\nSecond line \\\n Third line\\\n.     ]\"\n\t`,\n\t\t\ttoken.STRING, \"\\\"[First line \\\\\\nSecond line \\\\\\n Third line\\\\\\n.     ]\\\"\", 1,\n\t\t\ttoken.EOF, \"\", 53,\n\t\t)\n\n\t\ttest(\"/\",\n\t\t\ttoken.SLASH, \"\", 1,\n\t\t\ttoken.EOF, \"\", 2,\n\t\t)\n\n\t\ttest(\"var abc = \\\"abc\\uFFFFabc\\\"\",\n\t\t\ttoken.VAR, \"var\", 1,\n\t\t\ttoken.IDENTIFIER, \"abc\", 5,\n\t\t\ttoken.ASSIGN, \"\", 9,\n\t\t\ttoken.STRING, \"\\\"abc\\uFFFFabc\\\"\", 11,\n\t\t\ttoken.EOF, \"\", 22,\n\t\t)\n\n\t\ttest(`'\\t' === '\\r'`,\n\t\t\ttoken.STRING, \"'\\\\t'\", 1,\n\t\t\ttoken.STRICT_EQUAL, \"\", 6,\n\t\t\ttoken.STRING, \"'\\\\r'\", 10,\n\t\t\ttoken.EOF, \"\", 14,\n\t\t)\n\n\t\ttest(`var \\u0024 = 1`,\n\t\t\ttoken.VAR, \"var\", 1,\n\t\t\ttoken.IDENTIFIER, \"$\", 5,\n\t\t\ttoken.ASSIGN, \"\", 12,\n\t\t\ttoken.NUMBER, \"1\", 14,\n\t\t\ttoken.EOF, \"\", 15,\n\t\t)\n\n\t\ttest(\"10e10000\",\n\t\t\ttoken.NUMBER, \"10e10000\", 1,\n\t\t\ttoken.EOF, \"\", 9,\n\t\t)\n\n\t\ttest(`var if var class`,\n\t\t\ttoken.VAR, \"var\", 1,\n\t\t\ttoken.IF, \"if\", 5,\n\t\t\ttoken.VAR, \"var\", 8,\n\t\t\ttoken.KEYWORD, \"class\", 12,\n\t\t\ttoken.EOF, \"\", 17,\n\t\t)\n\n\t\ttest(`-0`,\n\t\t\ttoken.MINUS, \"\", 1,\n\t\t\ttoken.NUMBER, \"0\", 2,\n\t\t\ttoken.EOF, \"\", 3,\n\t\t)\n\n\t\ttest(`.01`,\n\t\t\ttoken.NUMBER, \".01\", 1,\n\t\t\ttoken.EOF, \"\", 4,\n\t\t)\n\n\t\ttest(`.01e+2`,\n\t\t\ttoken.NUMBER, \".01e+2\", 1,\n\t\t\ttoken.EOF, \"\", 7,\n\t\t)\n\n\t\ttest(\";\",\n\t\t\ttoken.SEMICOLON, \"\", 1,\n\t\t\ttoken.EOF, \"\", 2,\n\t\t)\n\n\t\ttest(\";;\",\n\t\t\ttoken.SEMICOLON, \"\", 1,\n\t\t\ttoken.SEMICOLON, \"\", 2,\n\t\t\ttoken.EOF, \"\", 3,\n\t\t)\n\n\t\ttest(\"//\",\n\t\t\ttoken.EOF, \"\", 3,\n\t\t)\n\n\t\ttest(\";;//test\",\n\t\t\ttoken.SEMICOLON, \"\", 1,\n\t\t\ttoken.SEMICOLON, \"\", 2,\n\t\t\ttoken.EOF, \"\", 9,\n\t\t)\n\n\t\ttest(\"1\",\n\t\t\ttoken.NUMBER, \"1\", 1,\n\t\t)\n\n\t\ttest(\"12 123\",\n\t\t\ttoken.NUMBER, \"12\", 1,\n\t\t\ttoken.NUMBER, \"123\", 4,\n\t\t)\n\n\t\ttest(\"1.2 12.3\",\n\t\t\ttoken.NUMBER, \"1.2\", 1,\n\t\t\ttoken.NUMBER, \"12.3\", 5,\n\t\t)\n\n\t\ttest(\"/ /=\",\n\t\t\ttoken.SLASH, \"\", 1,\n\t\t\ttoken.QUOTIENT_ASSIGN, \"\", 3,\n\t\t)\n\n\t\ttest(`\"abc\"`,\n\t\t\ttoken.STRING, `\"abc\"`, 1,\n\t\t)\n\n\t\ttest(`'abc'`,\n\t\t\ttoken.STRING, `'abc'`, 1,\n\t\t)\n\n\t\ttest(\"++\",\n\t\t\ttoken.INCREMENT, \"\", 1,\n\t\t)\n\n\t\ttest(\">\",\n\t\t\ttoken.GREATER, \"\", 1,\n\t\t)\n\n\t\ttest(\">=\",\n\t\t\ttoken.GREATER_OR_EQUAL, \"\", 1,\n\t\t)\n\n\t\ttest(\">>\",\n\t\t\ttoken.SHIFT_RIGHT, \"\", 1,\n\t\t)\n\n\t\ttest(\">>=\",\n\t\t\ttoken.SHIFT_RIGHT_ASSIGN, \"\", 1,\n\t\t)\n\n\t\ttest(\">>>\",\n\t\t\ttoken.UNSIGNED_SHIFT_RIGHT, \"\", 1,\n\t\t)\n\n\t\ttest(\">>>=\",\n\t\t\ttoken.UNSIGNED_SHIFT_RIGHT_ASSIGN, \"\", 1,\n\t\t)\n\n\t\ttest(\"1 \\\"abc\\\"\",\n\t\t\ttoken.NUMBER, \"1\", 1,\n\t\t\ttoken.STRING, \"\\\"abc\\\"\", 3,\n\t\t)\n\n\t\ttest(\",\",\n\t\t\ttoken.COMMA, \"\", 1,\n\t\t)\n\n\t\ttest(\"1, \\\"abc\\\"\",\n\t\t\ttoken.NUMBER, \"1\", 1,\n\t\t\ttoken.COMMA, \"\", 2,\n\t\t\ttoken.STRING, \"\\\"abc\\\"\", 4,\n\t\t)\n\n\t\ttest(\"new abc(1, 3.14159);\",\n\t\t\ttoken.NEW, \"new\", 1,\n\t\t\ttoken.IDENTIFIER, \"abc\", 5,\n\t\t\ttoken.LEFT_PARENTHESIS, \"\", 8,\n\t\t\ttoken.NUMBER, \"1\", 9,\n\t\t\ttoken.COMMA, \"\", 10,\n\t\t\ttoken.NUMBER, \"3.14159\", 12,\n\t\t\ttoken.RIGHT_PARENTHESIS, \"\", 19,\n\t\t\ttoken.SEMICOLON, \"\", 20,\n\t\t)\n\n\t\ttest(\"1 == \\\"1\\\"\",\n\t\t\ttoken.NUMBER, \"1\", 1,\n\t\t\ttoken.EQUAL, \"\", 3,\n\t\t\ttoken.STRING, \"\\\"1\\\"\", 6,\n\t\t)\n\n\t\ttest(\"1\\n[]\\n\",\n\t\t\ttoken.NUMBER, \"1\", 1,\n\t\t\ttoken.LEFT_BRACKET, \"\", 3,\n\t\t\ttoken.RIGHT_BRACKET, \"\", 4,\n\t\t)\n\n\t\ttest(\"1\\ufeff[]\\ufeff\",\n\t\t\ttoken.NUMBER, \"1\", 1,\n\t\t\ttoken.LEFT_BRACKET, \"\", 5,\n\t\t\ttoken.RIGHT_BRACKET, \"\", 6,\n\t\t)\n\n\t\t// Identifier from Unicode Nl\n\t\ttest(\"\\u16ee\",\n\t\t\ttoken.IDENTIFIER, \"ᛮ\", 1,\n\t\t)\n\n\t\t// Identifier from Unicode Other_ID_Start\n\t\ttest(\"\\u212e\",\n\t\t\ttoken.IDENTIFIER, \"℮\", 1,\n\t\t)\n\n\t\t// Using char from ID_Continue after valid start char\n\t\ttest(\"a\\u0300\",\n\t\t\ttoken.IDENTIFIER, \"à\", 1,\n\t\t)\n\n\t\t// ILLEGAL\n\n\t\ttest(`3ea`,\n\t\t\ttoken.ILLEGAL, \"3e\", 1,\n\t\t\ttoken.IDENTIFIER, \"a\", 3,\n\t\t\ttoken.EOF, \"\", 4,\n\t\t)\n\n\t\ttest(`3in`,\n\t\t\ttoken.ILLEGAL, \"3\", 1,\n\t\t\ttoken.IN, \"in\", 2,\n\t\t\ttoken.EOF, \"\", 4,\n\t\t)\n\n\t\ttest(\"\\\"Hello\\nWorld\\\"\",\n\t\t\ttoken.ILLEGAL, \"\", 1,\n\t\t\ttoken.IDENTIFIER, \"World\", 8,\n\t\t\ttoken.ILLEGAL, \"\", 13,\n\t\t\ttoken.EOF, \"\", 14,\n\t\t)\n\n\t\ttest(\"\\u203f = 10\",\n\t\t\ttoken.ILLEGAL, \"\", 1,\n\t\t\ttoken.ASSIGN, \"\", 5,\n\t\t\ttoken.NUMBER, \"10\", 7,\n\t\t\ttoken.EOF, \"\", 9,\n\t\t)\n\n\t\ttest(`\"\\x0G\"`,\n\t\t\ttoken.STRING, \"\\\"\\\\x0G\\\"\", 1,\n\t\t\ttoken.EOF, \"\", 7,\n\t\t)\n\n\t\t// Starting identifier with ID_Continue char from Nm\n\t\ttest(\"\\u0300\",\n\t\t\ttoken.ILLEGAL,\n\t\t)\n\n\t\t// Starting identifier with Pattern_Syntax\n\t\ttest(\"'\",\n\t\t\ttoken.ILLEGAL,\n\t\t)\n\t})\n}\n"
  },
  {
    "path": "parser/marshal_test.go",
    "content": "package parser\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"os\"\n\t\"reflect\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/robertkrimen/otto/ast\"\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc marshal(name string, children ...interface{}) interface{} {\n\tif len(children) == 1 {\n\t\tif name == \"\" {\n\t\t\treturn testMarshalNode(children[0])\n\t\t}\n\t\treturn map[string]interface{}{\n\t\t\tname: children[0],\n\t\t}\n\t}\n\tret := map[string]interface{}{}\n\tlength := len(children) / 2\n\tfor i := range length {\n\t\tname := children[i*2].(string)\n\t\tvalue := children[i*2+1]\n\t\tret[name] = value\n\t}\n\tif name == \"\" {\n\t\treturn ret\n\t}\n\treturn map[string]interface{}{\n\t\tname: ret,\n\t}\n}\n\nfunc testMarshalNode(node interface{}) interface{} {\n\tswitch node := node.(type) {\n\t// Expression\n\n\tcase *ast.ArrayLiteral:\n\t\treturn marshal(\"Array\", testMarshalNode(node.Value))\n\n\tcase *ast.AssignExpression:\n\t\treturn marshal(\"Assign\",\n\t\t\t\"Left\", testMarshalNode(node.Left),\n\t\t\t\"Right\", testMarshalNode(node.Right),\n\t\t)\n\n\tcase *ast.BinaryExpression:\n\t\treturn marshal(\"BinaryExpression\",\n\t\t\t\"Operator\", node.Operator.String(),\n\t\t\t\"Left\", testMarshalNode(node.Left),\n\t\t\t\"Right\", testMarshalNode(node.Right),\n\t\t)\n\n\tcase *ast.BooleanLiteral:\n\t\treturn marshal(\"Literal\", node.Value)\n\n\tcase *ast.CallExpression:\n\t\treturn marshal(\"Call\",\n\t\t\t\"Callee\", testMarshalNode(node.Callee),\n\t\t\t\"ArgumentList\", testMarshalNode(node.ArgumentList),\n\t\t)\n\n\tcase *ast.ConditionalExpression:\n\t\treturn marshal(\"Conditional\",\n\t\t\t\"Test\", testMarshalNode(node.Test),\n\t\t\t\"Consequent\", testMarshalNode(node.Consequent),\n\t\t\t\"Alternate\", testMarshalNode(node.Alternate),\n\t\t)\n\n\tcase *ast.DotExpression:\n\t\treturn marshal(\"Dot\",\n\t\t\t\"Left\", testMarshalNode(node.Left),\n\t\t\t\"Member\", node.Identifier.Name,\n\t\t)\n\n\tcase *ast.NewExpression:\n\t\treturn marshal(\"New\",\n\t\t\t\"Callee\", testMarshalNode(node.Callee),\n\t\t\t\"ArgumentList\", testMarshalNode(node.ArgumentList),\n\t\t)\n\n\tcase *ast.NullLiteral:\n\t\treturn marshal(\"Literal\", nil)\n\n\tcase *ast.NumberLiteral:\n\t\treturn marshal(\"Literal\", node.Value)\n\n\tcase *ast.ObjectLiteral:\n\t\treturn marshal(\"Object\", testMarshalNode(node.Value))\n\n\tcase *ast.RegExpLiteral:\n\t\treturn marshal(\"Literal\", node.Literal)\n\n\tcase *ast.StringLiteral:\n\t\treturn marshal(\"Literal\", node.Literal)\n\n\tcase *ast.VariableExpression:\n\t\treturn []interface{}{node.Name, testMarshalNode(node.Initializer)}\n\n\t// Statement\n\n\tcase *ast.Program:\n\t\treturn testMarshalNode(node.Body)\n\n\tcase *ast.BlockStatement:\n\t\treturn marshal(\"BlockStatement\", testMarshalNode(node.List))\n\n\tcase *ast.EmptyStatement:\n\t\treturn \"EmptyStatement\"\n\n\tcase *ast.ExpressionStatement:\n\t\treturn testMarshalNode(node.Expression)\n\n\tcase *ast.ForInStatement:\n\t\treturn marshal(\"ForIn\",\n\t\t\t\"Into\", marshal(\"\", node.Into),\n\t\t\t\"Source\", marshal(\"\", node.Source),\n\t\t\t\"Body\", marshal(\"\", node.Body),\n\t\t)\n\n\tcase *ast.FunctionLiteral:\n\t\treturn marshal(\"Function\", testMarshalNode(node.Body))\n\n\tcase *ast.Identifier:\n\t\treturn marshal(\"Identifier\", node.Name)\n\n\tcase *ast.IfStatement:\n\t\tret := marshal(\"\",\n\t\t\t\"Test\", testMarshalNode(node.Test),\n\t\t\t\"Consequent\", testMarshalNode(node.Consequent),\n\t\t).(map[string]interface{})\n\t\tif node.Alternate != nil {\n\t\t\tret[\"Alternate\"] = testMarshalNode(node.Alternate)\n\t\t}\n\t\treturn marshal(\"If\", ret)\n\n\tcase *ast.LabelledStatement:\n\t\treturn marshal(\"Label\",\n\t\t\t\"Name\", node.Label.Name,\n\t\t\t\"Statement\", testMarshalNode(node.Statement),\n\t\t)\n\tcase ast.Property:\n\t\treturn marshal(\"\",\n\t\t\t\"Key\", node.Key,\n\t\t\t\"Value\", testMarshalNode(node.Value),\n\t\t)\n\n\tcase *ast.ReturnStatement:\n\t\treturn marshal(\"Return\", testMarshalNode(node.Argument))\n\n\tcase *ast.SequenceExpression:\n\t\treturn marshal(\"Sequence\", testMarshalNode(node.Sequence))\n\n\tcase *ast.ThrowStatement:\n\t\treturn marshal(\"Throw\", testMarshalNode(node.Argument))\n\n\tcase *ast.VariableStatement:\n\t\treturn marshal(\"Var\", testMarshalNode(node.List))\n\t}\n\n\t{\n\t\tvalue := reflect.ValueOf(node)\n\t\tif value.Kind() == reflect.Slice {\n\t\t\ttmp0 := []interface{}{}\n\t\t\tfor index := range value.Len() {\n\t\t\t\ttmp0 = append(tmp0, testMarshalNode(value.Index(index).Interface()))\n\t\t\t}\n\t\t\treturn tmp0\n\t\t}\n\t}\n\n\tif node != nil {\n\t\tfmt.Fprintf(os.Stderr, \"testMarshalNode(%T)\\n\", node)\n\t}\n\n\treturn nil\n}\n\nfunc testMarshal(node interface{}) string {\n\tvalue, err := json.Marshal(testMarshalNode(node))\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treturn string(value)\n}\n\nfunc TestParserAST(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := func(inputOutput string) {\n\t\t\tmatch := matchBeforeAfterSeparator.FindStringIndex(inputOutput)\n\t\t\tinput := strings.TrimSpace(inputOutput[0:match[0]])\n\t\t\twantOutput := strings.TrimSpace(inputOutput[match[1]:])\n\t\t\t_, program, err := testParse(input)\n\t\t\tis(err, nil)\n\t\t\thaveOutput := testMarshal(program)\n\t\t\ttmp0, tmp1 := bytes.Buffer{}, bytes.Buffer{}\n\t\t\terr = json.Indent(&tmp0, []byte(haveOutput), \"\\t\\t\", \"   \")\n\t\t\trequire.NoError(t, err)\n\t\t\terr = json.Indent(&tmp1, []byte(wantOutput), \"\\t\\t\", \"   \")\n\t\t\trequire.NoError(t, err)\n\t\t\tis(\"\\n\\t\\t\"+tmp0.String(), \"\\n\\t\\t\"+tmp1.String())\n\t\t}\n\n\t\ttest(`\n        ---\n[]\n        `)\n\n\t\ttest(`\n        ;\n        ---\n[\n  \"EmptyStatement\"\n]\n        `)\n\n\t\ttest(`\n        ;;;\n        ---\n[\n  \"EmptyStatement\",\n  \"EmptyStatement\",\n  \"EmptyStatement\"\n]\n        `)\n\n\t\ttest(`\n        1; true; abc; \"abc\"; null;\n        ---\n[\n  {\n    \"Literal\": 1\n  },\n  {\n    \"Literal\": true\n  },\n  {\n    \"Identifier\": \"abc\"\n  },\n  {\n    \"Literal\": \"\\\"abc\\\"\"\n  },\n  {\n    \"Literal\": null\n  }\n]\n        `)\n\n\t\ttest(`\n        { 1; null; 3.14159; ; }\n        ---\n[\n  {\n    \"BlockStatement\": [\n      {\n        \"Literal\": 1\n      },\n      {\n        \"Literal\": null\n      },\n      {\n        \"Literal\": 3.14159\n      },\n      \"EmptyStatement\"\n    ]\n  }\n]\n        `)\n\n\t\ttest(`\n        new abc();\n        ---\n[\n  {\n    \"New\": {\n      \"ArgumentList\": [],\n      \"Callee\": {\n        \"Identifier\": \"abc\"\n      }\n    }\n  }\n]\n        `)\n\n\t\ttest(`\n        new abc(1, 3.14159)\n        ---\n[\n  {\n    \"New\": {\n      \"ArgumentList\": [\n        {\n          \"Literal\": 1\n        },\n        {\n          \"Literal\": 3.14159\n        }\n      ],\n      \"Callee\": {\n        \"Identifier\": \"abc\"\n      }\n    }\n  }\n]\n        `)\n\n\t\ttest(`\n        true ? false : true\n        ---\n[\n  {\n    \"Conditional\": {\n      \"Alternate\": {\n        \"Literal\": true\n      },\n      \"Consequent\": {\n        \"Literal\": false\n      },\n      \"Test\": {\n        \"Literal\": true\n      }\n    }\n  }\n]\n        `)\n\n\t\ttest(`\n        true || false\n        ---\n[\n  {\n    \"BinaryExpression\": {\n      \"Left\": {\n        \"Literal\": true\n      },\n      \"Operator\": \"||\",\n      \"Right\": {\n        \"Literal\": false\n      }\n    }\n  }\n]\n        `)\n\n\t\ttest(`\n        0 + { abc: true }\n        ---\n[\n  {\n    \"BinaryExpression\": {\n      \"Left\": {\n        \"Literal\": 0\n      },\n      \"Operator\": \"+\",\n      \"Right\": {\n        \"Object\": [\n          {\n            \"Key\": \"abc\",\n            \"Value\": {\n              \"Literal\": true\n            }\n          }\n        ]\n      }\n    }\n  }\n]\n        `)\n\n\t\ttest(`\n        1 == \"1\"\n        ---\n[\n  {\n    \"BinaryExpression\": {\n      \"Left\": {\n        \"Literal\": 1\n      },\n      \"Operator\": \"==\",\n      \"Right\": {\n        \"Literal\": \"\\\"1\\\"\"\n      }\n    }\n  }\n]\n        `)\n\n\t\ttest(`\n        abc(1)\n        ---\n[\n  {\n    \"Call\": {\n      \"ArgumentList\": [\n        {\n          \"Literal\": 1\n        }\n      ],\n      \"Callee\": {\n        \"Identifier\": \"abc\"\n      }\n    }\n  }\n]\n        `)\n\n\t\ttest(`\n        Math.pow(3, 2)\n        ---\n[\n  {\n    \"Call\": {\n      \"ArgumentList\": [\n        {\n          \"Literal\": 3\n        },\n        {\n          \"Literal\": 2\n        }\n      ],\n      \"Callee\": {\n        \"Dot\": {\n          \"Left\": {\n            \"Identifier\": \"Math\"\n          },\n          \"Member\": \"pow\"\n        }\n      }\n    }\n  }\n]\n        `)\n\n\t\ttest(`\n        1, 2, 3\n        ---\n[\n  {\n    \"Sequence\": [\n      {\n        \"Literal\": 1\n      },\n      {\n        \"Literal\": 2\n      },\n      {\n        \"Literal\": 3\n      }\n    ]\n  }\n]\n        `)\n\n\t\ttest(`\n        / abc /   gim;\n        ---\n[\n  {\n    \"Literal\": \"/ abc /   gim\"\n  }\n]\n        `)\n\n\t\ttest(`\n        if (0)\n            1;\n        ---\n[\n  {\n    \"If\": {\n      \"Consequent\": {\n        \"Literal\": 1\n      },\n      \"Test\": {\n        \"Literal\": 0\n      }\n    }\n  }\n]\n        `)\n\n\t\ttest(`\n        0+function(){\n            return;\n        }\n        ---\n[\n  {\n    \"BinaryExpression\": {\n      \"Left\": {\n        \"Literal\": 0\n      },\n      \"Operator\": \"+\",\n      \"Right\": {\n        \"Function\": {\n          \"BlockStatement\": [\n            {\n              \"Return\": null\n            }\n          ]\n        }\n      }\n    }\n  }\n]\n        `)\n\n\t\ttest(`\n        xyzzy // Ignore it\n        // Ignore this\n        // And this\n        /* And all..\n\n\n\n        ... of this!\n        */\n        \"Nothing happens.\"\n        // And finally this\n        ---\n[\n  {\n    \"Identifier\": \"xyzzy\"\n  },\n  {\n    \"Literal\": \"\\\"Nothing happens.\\\"\"\n  }\n]\n        `)\n\n\t\ttest(`\n        ((x & (x = 1)) !== 0)\n        ---\n[\n  {\n    \"BinaryExpression\": {\n      \"Left\": {\n        \"BinaryExpression\": {\n          \"Left\": {\n            \"Identifier\": \"x\"\n          },\n          \"Operator\": \"\\u0026\",\n          \"Right\": {\n            \"Assign\": {\n              \"Left\": {\n                \"Identifier\": \"x\"\n              },\n              \"Right\": {\n                \"Literal\": 1\n              }\n            }\n          }\n        }\n      },\n      \"Operator\": \"!==\",\n      \"Right\": {\n        \"Literal\": 0\n      }\n    }\n  }\n]\n        `)\n\n\t\ttest(`\n        { abc: 'def' }\n        ---\n[\n  {\n    \"BlockStatement\": [\n      {\n        \"Label\": {\n          \"Name\": \"abc\",\n          \"Statement\": {\n            \"Literal\": \"'def'\"\n          }\n        }\n      }\n    ]\n  }\n]\n        `)\n\n\t\ttest(`\n        // This is not an object, this is a string literal with a label!\n        ({ abc: 'def' })\n        ---\n[\n  {\n    \"Object\": [\n      {\n        \"Key\": \"abc\",\n        \"Value\": {\n          \"Literal\": \"'def'\"\n        }\n      }\n    ]\n  }\n]\n        `)\n\n\t\ttest(`\n        [,]\n        ---\n[\n  {\n    \"Array\": [\n      null\n    ]\n  }\n]\n        `)\n\n\t\ttest(`\n        [,,]\n        ---\n[\n  {\n    \"Array\": [\n      null,\n      null\n    ]\n  }\n]\n        `)\n\n\t\ttest(`\n        ({ get abc() {} })\n        ---\n[\n  {\n    \"Object\": [\n      {\n        \"Key\": \"abc\",\n        \"Value\": {\n          \"Function\": {\n            \"BlockStatement\": []\n          }\n        }\n      }\n    ]\n  }\n]\n        `)\n\n\t\ttest(`\n        /abc/.source\n        ---\n[\n  {\n    \"Dot\": {\n      \"Left\": {\n        \"Literal\": \"/abc/\"\n      },\n      \"Member\": \"source\"\n    }\n  }\n]\n        `)\n\n\t\ttest(`\n                xyzzy\n\n        throw new TypeError(\"Nothing happens.\")\n        ---\n[\n  {\n    \"Identifier\": \"xyzzy\"\n  },\n  {\n    \"Throw\": {\n      \"New\": {\n        \"ArgumentList\": [\n          {\n            \"Literal\": \"\\\"Nothing happens.\\\"\"\n          }\n        ],\n        \"Callee\": {\n          \"Identifier\": \"TypeError\"\n        }\n      }\n    }\n  }\n]\n\t`)\n\n\t\t// When run, this will call a type error to be thrown\n\t\t// This is essentially the same as:\n\t\t//\n\t\t// var abc = 1(function(){})()\n\t\t//\n\t\ttest(`\n        var abc = 1\n        (function(){\n        })()\n        ---\n[\n  {\n    \"Var\": [\n      [\n        \"abc\",\n        {\n          \"Call\": {\n            \"ArgumentList\": [],\n            \"Callee\": {\n              \"Call\": {\n                \"ArgumentList\": [\n                  {\n                    \"Function\": {\n                      \"BlockStatement\": []\n                    }\n                  }\n                ],\n                \"Callee\": {\n                  \"Literal\": 1\n                }\n              }\n            }\n          }\n        }\n      ]\n    ]\n  }\n]\n        `)\n\n\t\ttest(`\n        \"use strict\"\n        ---\n[\n  {\n    \"Literal\": \"\\\"use strict\\\"\"\n  }\n]\n        `)\n\n\t\ttest(`\n        \"use strict\"\n        abc = 1 + 2 + 11\n        ---\n[\n  {\n    \"Literal\": \"\\\"use strict\\\"\"\n  },\n  {\n    \"Assign\": {\n      \"Left\": {\n        \"Identifier\": \"abc\"\n      },\n      \"Right\": {\n        \"BinaryExpression\": {\n          \"Left\": {\n            \"BinaryExpression\": {\n              \"Left\": {\n                \"Literal\": 1\n              },\n              \"Operator\": \"+\",\n              \"Right\": {\n                \"Literal\": 2\n              }\n            }\n          },\n          \"Operator\": \"+\",\n          \"Right\": {\n            \"Literal\": 11\n          }\n        }\n      }\n    }\n  }\n]\n        `)\n\n\t\ttest(`\n        abc = function() { 'use strict' }\n        ---\n[\n  {\n    \"Assign\": {\n      \"Left\": {\n        \"Identifier\": \"abc\"\n      },\n      \"Right\": {\n        \"Function\": {\n          \"BlockStatement\": [\n            {\n              \"Literal\": \"'use strict'\"\n            }\n          ]\n        }\n      }\n    }\n  }\n]\n        `)\n\n\t\ttest(`\n        for (var abc in def) {\n        }\n        ---\n[\n  {\n    \"ForIn\": {\n      \"Body\": {\n        \"BlockStatement\": []\n      },\n      \"Into\": [\n        \"abc\",\n        null\n      ],\n      \"Source\": {\n        \"Identifier\": \"def\"\n      }\n    }\n  }\n]\n        `)\n\n\t\ttest(`\n        abc = {\n            '\"': \"'\",\n            \"'\": '\"',\n        }\n        ---\n[\n  {\n    \"Assign\": {\n      \"Left\": {\n        \"Identifier\": \"abc\"\n      },\n      \"Right\": {\n        \"Object\": [\n          {\n            \"Key\": \"\\\"\",\n            \"Value\": {\n              \"Literal\": \"\\\"'\\\"\"\n            }\n          },\n          {\n            \"Key\": \"'\",\n            \"Value\": {\n              \"Literal\": \"'\\\"'\"\n            }\n          }\n        ]\n      }\n    }\n  }\n]\n            `)\n\n\t\ttest(`\n        if (!abc && abc.jkl(def) && abc[0] === +abc[0] && abc.length < ghi) {\n        }\n        ---\n[\n  {\n    \"If\": {\n      \"Consequent\": {\n        \"BlockStatement\": []\n      },\n      \"Test\": {\n        \"BinaryExpression\": {\n          \"Left\": {\n            \"BinaryExpression\": {\n              \"Left\": {\n                \"BinaryExpression\": {\n                  \"Left\": null,\n                  \"Operator\": \"\\u0026\\u0026\",\n                  \"Right\": {\n                    \"Call\": {\n                      \"ArgumentList\": [\n                        {\n                          \"Identifier\": \"def\"\n                        }\n                      ],\n                      \"Callee\": {\n                        \"Dot\": {\n                          \"Left\": {\n                            \"Identifier\": \"abc\"\n                          },\n                          \"Member\": \"jkl\"\n                        }\n                      }\n                    }\n                  }\n                }\n              },\n              \"Operator\": \"\\u0026\\u0026\",\n              \"Right\": {\n                \"BinaryExpression\": {\n                  \"Left\": null,\n                  \"Operator\": \"===\",\n                  \"Right\": null\n                }\n              }\n            }\n          },\n          \"Operator\": \"\\u0026\\u0026\",\n          \"Right\": {\n            \"BinaryExpression\": {\n              \"Left\": {\n                \"Dot\": {\n                  \"Left\": {\n                    \"Identifier\": \"abc\"\n                  },\n                  \"Member\": \"length\"\n                }\n              },\n              \"Operator\": \"\\u003c\",\n              \"Right\": {\n                \"Identifier\": \"ghi\"\n              }\n            }\n          }\n        }\n      }\n    }\n  }\n]\n        `)\n\t})\n}\n"
  },
  {
    "path": "parser/parser.go",
    "content": "/*\nPackage parser implements a parser for JavaScript.\n\n\timport (\n\t    \"github.com/robertkrimen/otto/parser\"\n\t)\n\nParse and return an AST\n\n\tfilename := \"\" // A filename is optional\n\tsrc := `\n\t    // Sample xyzzy example\n\t    (function(){\n\t        if (3.14159 > 0) {\n\t            console.log(\"Hello, World.\");\n\t            return;\n\t        }\n\n\t        var xyzzy = NaN;\n\t        console.log(\"Nothing happens.\");\n\t        return xyzzy;\n\t    })();\n\t`\n\n\t// Parse some JavaScript, yielding a *ast.Program and/or an ErrorList\n\tprogram, err := parser.ParseFile(nil, filename, src, 0)\n\n# Warning\n\nThe parser and AST interfaces are still works-in-progress (particularly where\nnode types are concerned) and may change in the future.\n*/\npackage parser\n\nimport (\n\t\"bytes\"\n\t\"encoding/base64\"\n\t\"fmt\"\n\t\"io\"\n\t\"os\"\n\n\t\"github.com/robertkrimen/otto/ast\"\n\t\"github.com/robertkrimen/otto/file\"\n\t\"github.com/robertkrimen/otto/token\"\n\t\"gopkg.in/sourcemap.v1\"\n)\n\n// A Mode value is a set of flags (or 0). They control optional parser functionality.\ntype Mode uint\n\nconst (\n\t// IgnoreRegExpErrors ignores RegExp compatibility errors (allow backtracking).\n\tIgnoreRegExpErrors Mode = 1 << iota\n\n\t// StoreComments stores the comments from source to the comments map.\n\tStoreComments\n)\n\ntype parser struct {\n\tcomments *ast.Comments\n\tfile     *file.File\n\tscope    *scope\n\tliteral  string\n\tstr      string\n\terrors   ErrorList\n\trecover  struct {\n\t\tidx   file.Idx\n\t\tcount int\n\t}\n\tidx               file.Idx\n\ttoken             token.Token\n\toffset            int\n\tchrOffset         int\n\tmode              Mode\n\tbase              int\n\tlength            int\n\tchr               rune\n\tinsertSemicolon   bool\n\timplicitSemicolon bool // Scratch when trying to seek to the next statement, etc.\n}\n\n// Parser is implemented by types which can parse JavaScript Code.\ntype Parser interface {\n\tScan() (tkn token.Token, literal string, idx file.Idx)\n}\n\nfunc newParser(filename, src string, base int, sm *sourcemap.Consumer) *parser {\n\treturn &parser{\n\t\tchr:      ' ', // This is set so we can start scanning by skipping whitespace\n\t\tstr:      src,\n\t\tlength:   len(src),\n\t\tbase:     base,\n\t\tfile:     file.NewFile(filename, src, base).WithSourceMap(sm),\n\t\tcomments: ast.NewComments(),\n\t}\n}\n\n// NewParser returns a new Parser.\nfunc NewParser(filename, src string) Parser {\n\treturn newParser(filename, src, 1, nil)\n}\n\n// ReadSource reads code from src if not nil, otherwise reads from filename.\nfunc ReadSource(filename string, src interface{}) ([]byte, error) {\n\tif src != nil {\n\t\tswitch src := src.(type) {\n\t\tcase string:\n\t\t\treturn []byte(src), nil\n\t\tcase []byte:\n\t\t\treturn src, nil\n\t\tcase *bytes.Buffer:\n\t\t\tif src != nil {\n\t\t\t\treturn src.Bytes(), nil\n\t\t\t}\n\t\tcase io.Reader:\n\t\t\tvar bfr bytes.Buffer\n\t\t\tif _, err := io.Copy(&bfr, src); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\treturn bfr.Bytes(), nil\n\t\tdefault:\n\t\t\treturn nil, fmt.Errorf(\"invalid src type %T\", src)\n\t\t}\n\t}\n\treturn os.ReadFile(filename) //nolint:gosec\n}\n\n// ReadSourceMap reads the source map from src if not nil, otherwise is a noop.\nfunc ReadSourceMap(filename string, src interface{}) (*sourcemap.Consumer, error) {\n\tif src == nil {\n\t\treturn nil, nil //nolint:nilnil\n\t}\n\n\tswitch src := src.(type) {\n\tcase string:\n\t\treturn sourcemap.Parse(filename, []byte(src))\n\tcase []byte:\n\t\treturn sourcemap.Parse(filename, src)\n\tcase *bytes.Buffer:\n\t\treturn sourcemap.Parse(filename, src.Bytes())\n\tcase io.Reader:\n\t\tvar bfr bytes.Buffer\n\t\tif _, err := io.Copy(&bfr, src); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn sourcemap.Parse(filename, bfr.Bytes())\n\tcase *sourcemap.Consumer:\n\t\treturn src, nil\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"invalid sourcemap type %T\", src)\n\t}\n}\n\n// ParseFileWithSourceMap parses the sourcemap returning the resulting Program.\nfunc ParseFileWithSourceMap(fileSet *file.FileSet, filename string, javascriptSource, sourcemapSource interface{}, mode Mode) (*ast.Program, error) {\n\tsrc, err := ReadSource(filename, javascriptSource)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif sourcemapSource == nil {\n\t\tlines := bytes.Split(src, []byte(\"\\n\"))\n\t\tlastLine := lines[len(lines)-1]\n\t\tif bytes.HasPrefix(lastLine, []byte(\"//# sourceMappingURL=data:application/json\")) {\n\t\t\tbits := bytes.SplitN(lastLine, []byte(\",\"), 2)\n\t\t\tif len(bits) == 2 {\n\t\t\t\tif d, errDecode := base64.StdEncoding.DecodeString(string(bits[1])); errDecode == nil {\n\t\t\t\t\tsourcemapSource = d\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tsm, err := ReadSourceMap(filename, sourcemapSource)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tbase := 1\n\tif fileSet != nil {\n\t\tbase = fileSet.AddFile(filename, string(src))\n\t}\n\n\tp := newParser(filename, string(src), base, sm)\n\tp.mode = mode\n\tprogram, err := p.parse()\n\tprogram.Comments = p.comments.CommentMap\n\n\treturn program, err\n}\n\n// ParseFile parses the source code of a single JavaScript/ECMAScript source file and returns\n// the corresponding ast.Program node.\n//\n// If fileSet == nil, ParseFile parses source without a FileSet.\n// If fileSet != nil, ParseFile first adds filename and src to fileSet.\n//\n// The filename argument is optional and is used for labelling errors, etc.\n//\n// src may be a string, a byte slice, a bytes.Buffer, or an io.Reader, but it MUST always be in UTF-8.\n//\n//\t// Parse some JavaScript, yielding a *ast.Program and/or an ErrorList\n//\tprogram, err := parser.ParseFile(nil, \"\", `if (abc > 1) {}`, 0)\nfunc ParseFile(fileSet *file.FileSet, filename string, src interface{}, mode Mode) (*ast.Program, error) {\n\treturn ParseFileWithSourceMap(fileSet, filename, src, nil, mode)\n}\n\n// ParseFunction parses a given parameter list and body as a function and returns the\n// corresponding ast.FunctionLiteral node.\n//\n// The parameter list, if any, should be a comma-separated list of identifiers.\nfunc ParseFunction(parameterList, body string) (*ast.FunctionLiteral, error) {\n\tsrc := \"(function(\" + parameterList + \") {\\n\" + body + \"\\n})\"\n\n\tp := newParser(\"\", src, 1, nil)\n\tprogram, err := p.parse()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral), nil\n}\n\n// Scan reads a single token from the source at the current offset, increments the offset and\n// returns the token.Token token, a string literal representing the value of the token (if applicable)\n// and it's current file.Idx index.\nfunc (p *parser) Scan() (token.Token, string, file.Idx) {\n\treturn p.scan()\n}\n\nfunc (p *parser) slice(idx0, idx1 file.Idx) string {\n\tfrom := int(idx0) - p.base\n\tto := int(idx1) - p.base\n\tif from >= 0 && to <= len(p.str) {\n\t\treturn p.str[from:to]\n\t}\n\n\treturn \"\"\n}\n\nfunc (p *parser) parse() (*ast.Program, error) {\n\tp.next()\n\tprogram := p.parseProgram()\n\tif false {\n\t\tp.errors.Sort()\n\t}\n\n\tif p.mode&StoreComments != 0 {\n\t\tp.comments.CommentMap.AddComments(program, p.comments.FetchAll(), ast.TRAILING)\n\t}\n\n\treturn program, p.errors.Err()\n}\n\nfunc (p *parser) next() {\n\tp.token, p.literal, p.idx = p.scan()\n}\n\nfunc (p *parser) optionalSemicolon() {\n\tif p.token == token.SEMICOLON {\n\t\tp.next()\n\t\treturn\n\t}\n\n\tif p.implicitSemicolon {\n\t\tp.implicitSemicolon = false\n\t\treturn\n\t}\n\n\tif p.token != token.EOF && p.token != token.RIGHT_BRACE {\n\t\tp.expect(token.SEMICOLON)\n\t}\n}\n\nfunc (p *parser) semicolon() {\n\tif p.token != token.RIGHT_PARENTHESIS && p.token != token.RIGHT_BRACE {\n\t\tif p.implicitSemicolon {\n\t\t\tp.implicitSemicolon = false\n\t\t\treturn\n\t\t}\n\n\t\tp.expect(token.SEMICOLON)\n\t}\n}\n\nfunc (p *parser) idxOf(offset int) file.Idx {\n\treturn file.Idx(p.base + offset)\n}\n\nfunc (p *parser) expect(value token.Token) file.Idx {\n\tidx := p.idx\n\tif p.token != value {\n\t\tp.errorUnexpectedToken(p.token)\n\t}\n\tp.next()\n\treturn idx\n}\n\nfunc lineCount(str string) (int, int) {\n\tline, last := 0, -1\n\tpair := false\n\tfor index, chr := range str {\n\t\tswitch chr {\n\t\tcase '\\r':\n\t\t\tline++\n\t\t\tlast = index\n\t\t\tpair = true\n\t\t\tcontinue\n\t\tcase '\\n':\n\t\t\tif !pair {\n\t\t\t\tline++\n\t\t\t}\n\t\t\tlast = index\n\t\tcase '\\u2028', '\\u2029':\n\t\t\tline++\n\t\t\tlast = index + 2\n\t\t}\n\t\tpair = false\n\t}\n\treturn line, last\n}\n\nfunc (p *parser) position(idx file.Idx) file.Position {\n\tposition := file.Position{}\n\toffset := int(idx) - p.base\n\tstr := p.str[:offset]\n\tposition.Filename = p.file.Name()\n\tline, last := lineCount(str)\n\tposition.Line = 1 + line\n\tif last >= 0 {\n\t\tposition.Column = offset - last\n\t} else {\n\t\tposition.Column = 1 + len(str)\n\t}\n\n\treturn position\n}\n"
  },
  {
    "path": "parser/parser_test.go",
    "content": "package parser\n\nimport (\n\t\"errors\"\n\t\"regexp\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/robertkrimen/otto/ast\"\n\t\"github.com/robertkrimen/otto/file\"\n\t\"github.com/robertkrimen/otto/underscore\"\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc firstErr(err error) error {\n\tvar lerr *ErrorList\n\tif errors.As(err, &lerr) {\n\t\treturn (*lerr)[0]\n\t}\n\treturn err\n}\n\nvar matchBeforeAfterSeparator = regexp.MustCompile(`(?m)^[ \\t]*---$`)\n\nfunc testParse(src string) (*parser, *ast.Program, error) {\n\treturn testParseWithMode(src, 0)\n}\n\nfunc testParseWithMode(src string, mode Mode) (parser *parser, program *ast.Program, err error) { //nolint:nonamedreturns\n\tdefer func() {\n\t\tif tmp := recover(); tmp != nil {\n\t\t\tif tmp, ok := tmp.(string); ok {\n\t\t\t\tif strings.HasPrefix(tmp, \"SyntaxError:\") {\n\t\t\t\t\tparser = nil\n\t\t\t\t\tprogram = nil\n\t\t\t\t\terr = errors.New(tmp)\n\t\t\t\t\treturn\n\t\t\t\t}\n\t\t\t}\n\t\t\tpanic(tmp)\n\t\t}\n\t}()\n\tparser = newParser(\"\", src, 1, nil)\n\tparser.mode = mode\n\tprogram, err = parser.parse()\n\treturn parser, program, err\n}\n\nfunc TestParseFile(t *testing.T) {\n\ttt(t, func() {\n\t\t_, err := ParseFile(nil, \"\", `/abc/`, 0)\n\t\tis(err, nil)\n\n\t\t_, err = ParseFile(nil, \"\", `/(?!def)abc/`, IgnoreRegExpErrors)\n\t\tis(err, nil)\n\n\t\t_, err = ParseFile(nil, \"\", `/(?!def)abc/`, 0)\n\t\tis(err, \"(anonymous): Line 1:1 Invalid regular expression: re2: Invalid (?!) <lookahead>\")\n\n\t\t_, err = ParseFile(nil, \"\", `/(?!def)abc/; return`, IgnoreRegExpErrors)\n\t\tis(err, \"(anonymous): Line 1:15 Illegal return statement\")\n\n\t\t_, err = ParseFile(nil, \"/make-sure-file-path-is-returned-not-anonymous\", `a..`, 0)\n\t\tis(err, \"/make-sure-file-path-is-returned-not-anonymous: Line 1:3 Unexpected token .\")\n\t})\n}\n\nfunc TestParseFunction(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := func(prm, bdy string, expect interface{}) *ast.FunctionLiteral {\n\t\t\tfunction, err := ParseFunction(prm, bdy)\n\t\t\tis(firstErr(err), expect)\n\t\t\treturn function\n\t\t}\n\n\t\ttest(\"a, b,c,d\", \"\", nil)\n\n\t\ttest(\"a, b;,c,d\", \"\", \"(anonymous): Line 1:15 Unexpected token ;\")\n\n\t\ttest(\"this\", \"\", \"(anonymous): Line 1:11 Unexpected token this\")\n\n\t\ttest(\"a, b, c, null\", \"\", \"(anonymous): Line 1:20 Unexpected token null\")\n\n\t\ttest(\"a, b,c,d\", \"return;\", nil)\n\n\t\ttest(\"a, b,c,d\", \"break;\", \"(anonymous): Line 2:1 Illegal break statement\")\n\n\t\ttest(\"a, b,c,d\", \"{}\", nil)\n\t})\n}\n\nfunc TestParserErr(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := func(input string, expect interface{}) (*ast.Program, *parser) {\n\t\t\tparser := newParser(\"\", input, 1, nil)\n\t\t\tprogram, err := parser.parse()\n\t\t\tis(firstErr(err), expect)\n\t\t\treturn program, parser\n\t\t}\n\n\t\ttest(\"\", nil)\n\n\t\tprogram, parser := test(`\n        var abc;\n        break; do {\n        } while(true);\n    `, \"(anonymous): Line 3:9 Illegal break statement\")\n\t\t{\n\t\t\tstmt := program.Body[1].(*ast.BadStatement)\n\t\t\tis(parser.position(stmt.From).Column, 9)\n\t\t\tis(parser.position(stmt.To).Column, 16)\n\t\t\tis(parser.slice(stmt.From, stmt.To), \"break; \")\n\t\t}\n\n\t\ttest(\"{\", \"(anonymous): Line 1:2 Unexpected end of input\")\n\n\t\ttest(\"}\", \"(anonymous): Line 1:1 Unexpected token }\")\n\n\t\ttest(\"3ea\", \"(anonymous): Line 1:1 Unexpected token ILLEGAL\")\n\n\t\ttest(\"3in\", \"(anonymous): Line 1:1 Unexpected token ILLEGAL\")\n\n\t\ttest(\"3in []\", \"(anonymous): Line 1:1 Unexpected token ILLEGAL\")\n\n\t\ttest(\"3e\", \"(anonymous): Line 1:1 Unexpected token ILLEGAL\")\n\n\t\ttest(\"3e+\", \"(anonymous): Line 1:1 Unexpected token ILLEGAL\")\n\n\t\ttest(\"3e-\", \"(anonymous): Line 1:1 Unexpected token ILLEGAL\")\n\n\t\ttest(\"3x\", \"(anonymous): Line 1:1 Unexpected token ILLEGAL\")\n\n\t\ttest(\"3x0\", \"(anonymous): Line 1:1 Unexpected token ILLEGAL\")\n\n\t\ttest(\"0x\", \"(anonymous): Line 1:1 Unexpected token ILLEGAL\")\n\n\t\ttest(\"09\", \"(anonymous): Line 1:1 Unexpected token ILLEGAL\")\n\n\t\ttest(\"018\", \"(anonymous): Line 1:1 Unexpected token ILLEGAL\")\n\n\t\ttest(\"01.0\", \"(anonymous): Line 1:3 Unexpected number\")\n\n\t\ttest(\"01a\", \"(anonymous): Line 1:1 Unexpected token ILLEGAL\")\n\n\t\ttest(\"0x3in[]\", \"(anonymous): Line 1:1 Unexpected token ILLEGAL\")\n\n\t\ttest(\"\\\"Hello\\nWorld\\\"\", \"(anonymous): Line 1:1 Unexpected token ILLEGAL\")\n\n\t\ttest(\"\\u203f = 10\", \"(anonymous): Line 1:1 Unexpected token ILLEGAL\")\n\n\t\ttest(\"x\\\\\", \"(anonymous): Line 1:1 Unexpected token ILLEGAL\")\n\n\t\ttest(\"x\\\\\\\\\", \"(anonymous): Line 1:1 Unexpected token ILLEGAL\")\n\n\t\ttest(\"x\\\\u005c\", \"(anonymous): Line 1:1 Unexpected token ILLEGAL\")\n\n\t\ttest(\"x\\\\u002a\", \"(anonymous): Line 1:1 Unexpected token ILLEGAL\")\n\n\t\ttest(\"x\\\\\\\\u002a\", \"(anonymous): Line 1:1 Unexpected token ILLEGAL\")\n\n\t\ttest(\"/\\n\", \"(anonymous): Line 1:1 Invalid regular expression: missing /\")\n\n\t\ttest(\"var x = /(s/g\", \"(anonymous): Line 1:9 Invalid regular expression: Unterminated group\")\n\n\t\ttest(\"0 = 1\", \"(anonymous): Line 1:1 invalid left-hand side in assignment\")\n\n\t\ttest(\"func() = 1\", \"(anonymous): Line 1:1 invalid left-hand side in assignment\")\n\n\t\ttest(\"(1 + 1) = 2\", \"(anonymous): Line 1:2 invalid left-hand side in assignment\")\n\n\t\ttest(\"1++\", \"(anonymous): Line 1:2 invalid left-hand side in assignment\")\n\n\t\ttest(\"1--\", \"(anonymous): Line 1:2 invalid left-hand side in assignment\")\n\n\t\ttest(\"--1\", \"(anonymous): Line 1:1 invalid left-hand side in assignment\")\n\n\t\ttest(\"for((1 + 1) in abc) def();\", \"(anonymous): Line 1:1 Invalid left-hand side in for-in\")\n\n\t\ttest(\"[\", \"(anonymous): Line 1:2 Unexpected end of input\")\n\n\t\ttest(\"[,\", \"(anonymous): Line 1:3 Unexpected end of input\")\n\n\t\ttest(\"1 + {\", \"(anonymous): Line 1:6 Unexpected end of input\")\n\n\t\ttest(\"1 + { abc:abc\", \"(anonymous): Line 1:14 Unexpected end of input\")\n\n\t\ttest(\"1 + { abc:abc,\", \"(anonymous): Line 1:15 Unexpected end of input\")\n\n\t\ttest(\"var abc = /\\n/\", \"(anonymous): Line 1:11 Invalid regular expression: missing /\")\n\n\t\ttest(\"var abc = \\\"\\n\", \"(anonymous): Line 1:11 Unexpected token ILLEGAL\")\n\n\t\ttest(\"var if = 0\", \"(anonymous): Line 1:5 Unexpected token if\")\n\n\t\ttest(\"abc + 0 = 1\", \"(anonymous): Line 1:1 invalid left-hand side in assignment\")\n\n\t\ttest(\"+abc = 1\", \"(anonymous): Line 1:1 invalid left-hand side in assignment\")\n\n\t\ttest(\"1 + (\", \"(anonymous): Line 1:6 Unexpected end of input\")\n\n\t\ttest(\"\\n\\n\\n{\", \"(anonymous): Line 4:2 Unexpected end of input\")\n\n\t\ttest(\"\\n/* Some multiline\\ncomment */\\n)\", \"(anonymous): Line 4:1 Unexpected token )\")\n\n\t\t// TODO\n\t\t// { set 1 }\n\t\t// { get 2 }\n\t\t// ({ set: s(if) { } })\n\t\t// ({ set s(.) { } })\n\t\t// ({ set: s() { } })\n\t\t// ({ set: s(a, b) { } })\n\t\t// ({ get: g(d) { } })\n\t\t// ({ get i() { }, i: 42 })\n\t\t// ({ i: 42, get i() { } })\n\t\t// ({ set i(x) { }, i: 42 })\n\t\t// ({ i: 42, set i(x) { } })\n\t\t// ({ get i() { }, get i() { } })\n\t\t// ({ set i(x) { }, set i(x) { } })\n\n\t\ttest(\"function abc(if) {}\", \"(anonymous): Line 1:14 Unexpected token if\")\n\n\t\ttest(\"function abc(true) {}\", \"(anonymous): Line 1:14 Unexpected token true\")\n\n\t\ttest(\"function abc(false) {}\", \"(anonymous): Line 1:14 Unexpected token false\")\n\n\t\ttest(\"function abc(null) {}\", \"(anonymous): Line 1:14 Unexpected token null\")\n\n\t\ttest(\"function null() {}\", \"(anonymous): Line 1:10 Unexpected token null\")\n\n\t\ttest(\"function true() {}\", \"(anonymous): Line 1:10 Unexpected token true\")\n\n\t\ttest(\"function false() {}\", \"(anonymous): Line 1:10 Unexpected token false\")\n\n\t\ttest(\"function if() {}\", \"(anonymous): Line 1:10 Unexpected token if\")\n\n\t\ttest(\"a b;\", \"(anonymous): Line 1:3 Unexpected identifier\")\n\n\t\ttest(\"if.a\", \"(anonymous): Line 1:3 Unexpected token .\")\n\n\t\ttest(\"a if\", \"(anonymous): Line 1:3 Unexpected token if\")\n\n\t\ttest(\"a class\", \"(anonymous): Line 1:3 Unexpected reserved word\")\n\n\t\ttest(\"break\\n\", \"(anonymous): Line 1:1 Illegal break statement\")\n\n\t\ttest(\"break 1;\", \"(anonymous): Line 1:7 Unexpected number\")\n\n\t\ttest(\"for (;;) { break 1; }\", \"(anonymous): Line 1:18 Unexpected number\")\n\n\t\ttest(\"continue\\n\", \"(anonymous): Line 1:1 Illegal continue statement\")\n\n\t\ttest(\"continue 1;\", \"(anonymous): Line 1:10 Unexpected number\")\n\n\t\ttest(\"for (;;) { continue 1; }\", \"(anonymous): Line 1:21 Unexpected number\")\n\n\t\ttest(\"throw\", \"(anonymous): Line 1:1 Unexpected end of input\")\n\n\t\ttest(\"throw;\", \"(anonymous): Line 1:6 Unexpected token ;\")\n\n\t\ttest(\"throw \\n\", \"(anonymous): Line 1:1 Unexpected end of input\")\n\n\t\ttest(\"for (var abc, def in {});\", \"(anonymous): Line 1:19 Unexpected token in\")\n\n\t\ttest(\"for ((abc in {});;);\", nil)\n\n\t\ttest(\"for ((abc in {}));\", \"(anonymous): Line 1:17 Unexpected token )\")\n\n\t\ttest(\"for (+abc in {});\", \"(anonymous): Line 1:1 Invalid left-hand side in for-in\")\n\n\t\ttest(\"if (false)\", \"(anonymous): Line 1:11 Unexpected end of input\")\n\n\t\ttest(\"if (false) abc(); else\", \"(anonymous): Line 1:23 Unexpected end of input\")\n\n\t\ttest(\"do\", \"(anonymous): Line 1:3 Unexpected end of input\")\n\n\t\ttest(\"while (false)\", \"(anonymous): Line 1:14 Unexpected end of input\")\n\n\t\ttest(\"for (;;)\", \"(anonymous): Line 1:9 Unexpected end of input\")\n\n\t\ttest(\"with (abc)\", \"(anonymous): Line 1:11 Unexpected end of input\")\n\n\t\ttest(\"try {}\", \"(anonymous): Line 1:1 Missing catch or finally after try\")\n\n\t\ttest(\"try {} catch {}\", \"(anonymous): Line 1:14 Unexpected token {\")\n\n\t\ttest(\"try {} catch () {}\", \"(anonymous): Line 1:15 Unexpected token )\")\n\n\t\ttest(\"\\u203f = 1\", \"(anonymous): Line 1:1 Unexpected token ILLEGAL\")\n\n\t\t// TODO\n\t\t// const x = 12, y;\n\t\t// const x, y = 12;\n\t\t// const x;\n\t\t// if(true) let a = 1;\n\t\t// if(true) const  a = 1;\n\n\t\ttest(`new abc().\"def\"`, \"(anonymous): Line 1:11 Unexpected string\")\n\n\t\ttest(\"/*\", \"(anonymous): Line 1:3 Unexpected end of input\")\n\n\t\ttest(\"/**\", \"(anonymous): Line 1:4 Unexpected end of input\")\n\n\t\ttest(\"/*\\n\\n\\n\", \"(anonymous): Line 4:1 Unexpected end of input\")\n\n\t\ttest(\"/*\\n\\n\\n*\", \"(anonymous): Line 4:2 Unexpected end of input\")\n\n\t\ttest(\"/*abc\", \"(anonymous): Line 1:6 Unexpected end of input\")\n\n\t\ttest(\"/*abc  *\", \"(anonymous): Line 1:9 Unexpected end of input\")\n\n\t\ttest(\"\\n]\", \"(anonymous): Line 2:1 Unexpected token ]\")\n\n\t\ttest(\"\\r\\n]\", \"(anonymous): Line 2:1 Unexpected token ]\")\n\n\t\ttest(\"\\n\\r]\", \"(anonymous): Line 3:1 Unexpected token ]\")\n\n\t\ttest(\"//\\r\\n]\", \"(anonymous): Line 2:1 Unexpected token ]\")\n\n\t\ttest(\"//\\n\\r]\", \"(anonymous): Line 3:1 Unexpected token ]\")\n\n\t\ttest(\"/abc\\\\\\n/\", \"(anonymous): Line 1:1 Invalid regular expression: missing /\")\n\n\t\ttest(\"//\\r \\n]\", \"(anonymous): Line 3:1 Unexpected token ]\")\n\n\t\ttest(\"/*\\r\\n*/]\", \"(anonymous): Line 2:3 Unexpected token ]\")\n\n\t\ttest(\"/*\\r \\n*/]\", \"(anonymous): Line 3:3 Unexpected token ]\")\n\n\t\ttest(\"\\\\\\\\\", \"(anonymous): Line 1:1 Unexpected token ILLEGAL\")\n\n\t\ttest(\"\\\\u005c\", \"(anonymous): Line 1:1 Unexpected token ILLEGAL\")\n\n\t\ttest(\"\\\\abc\", \"(anonymous): Line 1:1 Unexpected token ILLEGAL\")\n\n\t\ttest(\"\\\\u0000\", \"(anonymous): Line 1:1 Unexpected token ILLEGAL\")\n\n\t\ttest(\"\\\\u200c = []\", \"(anonymous): Line 1:1 Unexpected token ILLEGAL\")\n\n\t\ttest(\"\\\\u200D = []\", \"(anonymous): Line 1:1 Unexpected token ILLEGAL\")\n\n\t\ttest(`\"\\`, \"(anonymous): Line 1:1 Unexpected token ILLEGAL\")\n\n\t\ttest(`\"\\u`, \"(anonymous): Line 1:1 Unexpected token ILLEGAL\")\n\n\t\ttest(\"return\", \"(anonymous): Line 1:1 Illegal return statement\")\n\n\t\ttest(\"continue\", \"(anonymous): Line 1:1 Illegal continue statement\")\n\n\t\ttest(\"break\", \"(anonymous): Line 1:1 Illegal break statement\")\n\n\t\ttest(\"switch (abc) { default: continue; }\", \"(anonymous): Line 1:25 Illegal continue statement\")\n\n\t\ttest(\"do { abc } *\", \"(anonymous): Line 1:12 Unexpected token *\")\n\n\t\ttest(\"while (true) { break abc; }\", \"(anonymous): Line 1:16 Undefined label 'abc'\")\n\n\t\ttest(\"while (true) { continue abc; }\", \"(anonymous): Line 1:16 Undefined label 'abc'\")\n\n\t\ttest(\"abc: while (true) { (function(){ break abc; }); }\", \"(anonymous): Line 1:34 Undefined label 'abc'\")\n\n\t\ttest(\"abc: while (true) { (function(){ abc: break abc; }); }\", nil)\n\n\t\ttest(\"abc: while (true) { (function(){ continue abc; }); }\", \"(anonymous): Line 1:34 Undefined label 'abc'\")\n\n\t\ttest(`abc: if (0) break abc; else {}`, nil)\n\n\t\ttest(`abc: if (0) { break abc; } else {}`, nil)\n\n\t\ttest(`abc: if (0) { break abc } else {}`, nil)\n\n\t\ttest(\"abc: while (true) { abc: while (true) {} }\", \"(anonymous): Line 1:21 Label 'abc' already exists\")\n\n\t\tif false {\n\t\t\t// TODO When strict mode is implemented\n\t\t\ttest(\"(function () { 'use strict'; delete abc; }())\", \"\")\n\t\t}\n\n\t\ttest(\"_: _: while (true) {]\", \"(anonymous): Line 1:4 Label '_' already exists\")\n\n\t\ttest(\"_:\\n_:\\nwhile (true) {]\", \"(anonymous): Line 2:1 Label '_' already exists\")\n\n\t\ttest(\"_:\\n   _:\\nwhile (true) {]\", \"(anonymous): Line 2:4 Label '_' already exists\")\n\n\t\ttest(\"/Xyzzy(?!Nothing happens)/\",\n\t\t\t\"(anonymous): Line 1:1 Invalid regular expression: re2: Invalid (?!) <lookahead>\")\n\n\t\ttest(\"function(){}\", \"(anonymous): Line 1:9 Unexpected token (\")\n\n\t\ttest(\"\\n/*/\", \"(anonymous): Line 2:4 Unexpected end of input\")\n\n\t\ttest(\"/*/.source\", \"(anonymous): Line 1:11 Unexpected end of input\")\n\n\t\ttest(\"/\\\\1/.source\", \"(anonymous): Line 1:1 Invalid regular expression: re2: Invalid \\\\1 <backreference>\")\n\n\t\ttest(\"var class\", \"(anonymous): Line 1:5 Unexpected reserved word\")\n\n\t\ttest(\"var if\", \"(anonymous): Line 1:5 Unexpected token if\")\n\n\t\ttest(\"object Object\", \"(anonymous): Line 1:8 Unexpected identifier\")\n\n\t\ttest(\"[object Object]\", \"(anonymous): Line 1:9 Unexpected identifier\")\n\n\t\ttest(\"\\\\u0xyz\", \"(anonymous): Line 1:1 Unexpected token ILLEGAL\")\n\n\t\ttest(`for (var abc, def in {}) {}`, \"(anonymous): Line 1:19 Unexpected token in\")\n\n\t\ttest(`for (abc, def in {}) {}`, \"(anonymous): Line 1:1 Invalid left-hand side in for-in\")\n\n\t\ttest(`for (var abc=def, ghi=(\"abc\" in {}); true;) {}`, nil)\n\n\t\t{\n\t\t\t// Semicolon insertion\n\n\t\t\ttest(\"this\\nif (1);\", nil)\n\n\t\t\ttest(\"while (1) { break\\nif (1); }\", nil)\n\n\t\t\ttest(\"throw\\nif (1);\", \"(anonymous): Line 1:1 Illegal newline after throw\")\n\n\t\t\ttest(\"(function(){ return\\nif (1); })\", nil)\n\n\t\t\ttest(\"while (1) { continue\\nif (1); }\", nil)\n\n\t\t\ttest(\"debugger\\nif (1);\", nil)\n\t\t}\n\n\t\t{ // Reserved words\n\t\t\ttest(\"class\", \"(anonymous): Line 1:1 Unexpected reserved word\")\n\t\t\ttest(\"abc.class = 1\", nil)\n\t\t\ttest(\"var class;\", \"(anonymous): Line 1:5 Unexpected reserved word\")\n\n\t\t\ttest(\"const\", \"(anonymous): Line 1:1 Unexpected reserved word\")\n\t\t\ttest(\"abc.const = 1\", nil)\n\t\t\ttest(\"var const;\", \"(anonymous): Line 1:5 Unexpected reserved word\")\n\n\t\t\ttest(\"enum\", \"(anonymous): Line 1:1 Unexpected reserved word\")\n\t\t\ttest(\"abc.enum = 1\", nil)\n\t\t\ttest(\"var enum;\", \"(anonymous): Line 1:5 Unexpected reserved word\")\n\n\t\t\ttest(\"export\", \"(anonymous): Line 1:1 Unexpected reserved word\")\n\t\t\ttest(\"abc.export = 1\", nil)\n\t\t\ttest(\"var export;\", \"(anonymous): Line 1:5 Unexpected reserved word\")\n\n\t\t\ttest(\"extends\", \"(anonymous): Line 1:1 Unexpected reserved word\")\n\t\t\ttest(\"abc.extends = 1\", nil)\n\t\t\ttest(\"var extends;\", \"(anonymous): Line 1:5 Unexpected reserved word\")\n\n\t\t\ttest(\"import\", \"(anonymous): Line 1:1 Unexpected reserved word\")\n\t\t\ttest(\"abc.import = 1\", nil)\n\t\t\ttest(\"var import;\", \"(anonymous): Line 1:5 Unexpected reserved word\")\n\n\t\t\ttest(\"super\", \"(anonymous): Line 1:1 Unexpected reserved word\")\n\t\t\ttest(\"abc.super = 1\", nil)\n\t\t\ttest(\"var super;\", \"(anonymous): Line 1:5 Unexpected reserved word\")\n\t\t}\n\n\t\t{ // Reserved words (strict)\n\t\t\ttest(`implements`, nil)\n\t\t\ttest(`abc.implements = 1`, nil)\n\t\t\ttest(`var implements;`, nil)\n\n\t\t\ttest(`interface`, nil)\n\t\t\ttest(`abc.interface = 1`, nil)\n\t\t\ttest(`var interface;`, nil)\n\n\t\t\ttest(`let`, nil)\n\t\t\ttest(`abc.let = 1`, nil)\n\t\t\ttest(`var let;`, nil)\n\n\t\t\ttest(`package`, nil)\n\t\t\ttest(`abc.package = 1`, nil)\n\t\t\ttest(`var package;`, nil)\n\n\t\t\ttest(`private`, nil)\n\t\t\ttest(`abc.private = 1`, nil)\n\t\t\ttest(`var private;`, nil)\n\n\t\t\ttest(`protected`, nil)\n\t\t\ttest(`abc.protected = 1`, nil)\n\t\t\ttest(`var protected;`, nil)\n\n\t\t\ttest(`public`, nil)\n\t\t\ttest(`abc.public = 1`, nil)\n\t\t\ttest(`var public;`, nil)\n\n\t\t\ttest(`static`, nil)\n\t\t\ttest(`abc.static = 1`, nil)\n\t\t\ttest(`var static;`, nil)\n\n\t\t\ttest(`yield`, nil)\n\t\t\ttest(`abc.yield = 1`, nil)\n\t\t\ttest(`var yield;`, nil)\n\t\t}\n\t})\n}\n\nfunc TestParser(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := func(source string, chk interface{}) *ast.Program {\n\t\t\t_, program, err := testParse(source)\n\t\t\tis(firstErr(err), chk)\n\t\t\treturn program\n\t\t}\n\n\t\ttest(`\n            abc\n            --\n            []\n        `, \"(anonymous): Line 3:13 invalid left-hand side in assignment\")\n\n\t\ttest(`\n            abc--\n            []\n        `, nil)\n\n\t\ttest(\"1\\n[]\\n\", \"(anonymous): Line 2:2 Unexpected token ]\")\n\n\t\ttest(`\n            function abc() {\n            }\n            abc()\n        `, nil)\n\n\t\ttest(\"\", nil)\n\n\t\ttest(\"//\", nil)\n\n\t\ttest(\"/* */\", nil)\n\n\t\ttest(\"/** **/\", nil)\n\n\t\ttest(\"/*****/\", nil)\n\n\t\ttest(\"/*\", \"(anonymous): Line 1:3 Unexpected end of input\")\n\n\t\ttest(\"#\", \"(anonymous): Line 1:1 Unexpected token ILLEGAL\")\n\n\t\ttest(\"/**/#\", \"(anonymous): Line 1:5 Unexpected token ILLEGAL\")\n\n\t\ttest(\"new +\", \"(anonymous): Line 1:5 Unexpected token +\")\n\n\t\tprogram := test(\";\", nil)\n\t\tis(len(program.Body), 1)\n\t\tis(program.Body[0].(*ast.EmptyStatement).Semicolon, file.Idx(1))\n\n\t\tprogram = test(\";;\", nil)\n\t\tis(len(program.Body), 2)\n\t\tis(program.Body[0].(*ast.EmptyStatement).Semicolon, file.Idx(1))\n\t\tis(program.Body[1].(*ast.EmptyStatement).Semicolon, file.Idx(2))\n\n\t\tprogram = test(\"1.2\", nil)\n\t\tis(len(program.Body), 1)\n\t\tis(program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.NumberLiteral).Literal, \"1.2\")\n\n\t\tprogram = test(\"/* */1.2\", nil)\n\t\tis(len(program.Body), 1)\n\t\tis(program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.NumberLiteral).Literal, \"1.2\")\n\n\t\tprogram = test(\"\\n\", nil)\n\t\tis(len(program.Body), 0)\n\n\t\ttest(`\n            if (0) {\n                abc = 0\n            }\n            else abc = 0\n        `, nil)\n\n\t\ttest(\"if (0) abc = 0 else abc = 0\", \"(anonymous): Line 1:16 Unexpected token else\")\n\n\t\ttest(`\n            if (0) {\n                abc = 0\n            } else abc = 0\n        `, nil)\n\n\t\ttest(`\n            if (0) {\n                abc = 1\n            } else {\n            }\n        `, nil)\n\n\t\ttest(`\n            do {\n            } while (true)\n        `, nil)\n\n\t\ttest(`\n            try {\n            } finally {\n            }\n        `, nil)\n\n\t\ttest(`\n            try {\n            } catch (abc) {\n            } finally {\n            }\n        `, nil)\n\n\t\ttest(`\n            try {\n            }\n            catch (abc) {\n            }\n            finally {\n            }\n        `, nil)\n\n\t\ttest(`try {} catch (abc) {} finally {}`, nil)\n\n\t\ttest(`\n            do {\n                do {\n                } while (0)\n            } while (0)\n        `, nil)\n\n\t\ttest(`do do; while(0); while(0);`, nil)\n\n\t\ttest(`\n            (function(){\n                try {\n                    if (\n                        1\n                    ) {\n                        return 1\n                    }\n                    return 0\n                } finally {\n                }\n            })()\n        `, nil)\n\n\t\ttest(\"abc = ''\\ndef\", nil)\n\n\t\ttest(\"abc = 1\\ndef\", nil)\n\n\t\ttest(\"abc = Math\\ndef\", nil)\n\n\t\ttest(`\"\\'\"`, nil)\n\n\t\ttest(`\n            abc = function(){\n            }\n            abc = 0\n        `, nil)\n\n\t\ttest(\"abc.null = 0\", nil)\n\n\t\ttest(\"0x41\", nil)\n\n\t\ttest(`\"\\d\"`, nil)\n\n\t\ttest(`(function(){return this})`, nil)\n\n\t\ttest(`\n            Object.defineProperty(Array.prototype, \"0\", {\n                value: 100,\n                writable: false,\n                configurable: true\n            });\n            abc = [101];\n            abc.hasOwnProperty(\"0\") && abc[0] === 101;\n        `, nil)\n\n\t\ttest(`new abc()`, nil)\n\t\ttest(`new {}`, nil)\n\n\t\ttest(`\n            limit = 4\n            result = 0\n            while (limit) {\n                limit = limit - 1\n                if (limit) {\n                }\n                else {\n                    break\n                }\n                result = result + 1\n            }\n        `, nil)\n\n\t\ttest(`\n            while (0) {\n                if (0) {\n                    continue\n                }\n            }\n        `, nil)\n\n\t\ttest(\"var \\u0061\\u0062\\u0063 = 0\", nil)\n\n\t\t// 7_3_1\n\t\ttest(\"var test7_3_1\\nabc = 66;\", nil)\n\t\ttest(\"var test7_3_1\\u2028abc = 66;\", nil)\n\n\t\t// 7_3_3\n\t\ttest(\"//\\u2028 =;\", \"(anonymous): Line 2:2 Unexpected token =\")\n\n\t\t// 7_3_10\n\t\ttest(\"var abc = \\u2029;\", \"(anonymous): Line 2:1 Unexpected token ;\")\n\t\ttest(\"var abc = \\\\u2029;\", \"(anonymous): Line 1:11 Unexpected token ILLEGAL\")\n\t\ttest(\"var \\\\u0061\\\\u0062\\\\u0063 = 0;\", nil)\n\n\t\ttest(\"'\", \"(anonymous): Line 1:1 Unexpected token ILLEGAL\")\n\n\t\ttest(\"'\\nstr\\ning\\n'\", \"(anonymous): Line 1:1 Unexpected token ILLEGAL\")\n\n\t\t// S7.6_A4.3_T1\n\t\ttest(`var $\\u0030 = 0;`, nil)\n\n\t\t// S7.6.1.1_A1.1\n\t\ttest(`switch = 1`, \"(anonymous): Line 1:8 Unexpected token =\")\n\n\t\t// S7.8.3_A2.1_T1\n\t\ttest(`.0 === 0.0`, nil)\n\n\t\t// 7.8.5-1\n\t\ttest(\"var regExp = /\\\\\\rn/;\", \"(anonymous): Line 1:14 Invalid regular expression: missing /\")\n\n\t\t// S7.8.5_A1.1_T2\n\t\ttest(\"var regExp = /=/;\", nil)\n\n\t\t// S7.8.5_A1.2_T1\n\t\ttest(\"/*/\", \"(anonymous): Line 1:4 Unexpected end of input\")\n\n\t\t// Sbp_7.9_A9_T3\n\t\ttest(`\n            do {\n            ;\n            } while (false) true\n        `, nil)\n\n\t\t// S7.9_A10_T10\n\t\ttest(`\n            {a:1\n            } 3\n        `, nil)\n\n\t\ttest(`\n            abc\n            ++def\n        `, nil)\n\n\t\t// S7.9_A5.2_T1\n\t\ttest(`\n            for(false;false\n            ) {\n            break;\n            }\n        `, \"(anonymous): Line 3:13 Unexpected token )\")\n\n\t\t// S7.9_A9_T8\n\t\ttest(`\n            do {};\n            while (false)\n        `, \"(anonymous): Line 2:18 Unexpected token ;\")\n\n\t\t// S8.4_A5\n\t\ttest(`\n            \"x\\0y\"\n        `, nil)\n\n\t\t// S9.3.1_A6_T1\n\t\ttest(`\n            10e10000\n        `, nil)\n\n\t\t// 10.4.2-1-5\n\t\ttest(`\n            \"abc\\\n            def\"\n        `, nil)\n\n\t\ttest(\"'\\\\\\n'\", nil)\n\n\t\ttest(\"'\\\\\\r\\n'\", nil)\n\n\t\t//// 11.13.1-1-1\n\t\ttest(\"42 = 42;\", \"(anonymous): Line 1:1 invalid left-hand side in assignment\")\n\n\t\t// S11.13.2_A4.2_T1.3\n\t\ttest(`\n            abc /= \"1\"\n        `, nil)\n\n\t\t// 12.1-1\n\t\ttest(`\n            try{};catch(){}\n        `, \"(anonymous): Line 2:13 Missing catch or finally after try\")\n\n\t\t// 12.1-3\n\t\ttest(`\n            try{};finally{}\n        `, \"(anonymous): Line 2:13 Missing catch or finally after try\")\n\n\t\t// S12.6.3_A11.1_T3\n\t\ttest(`\n            while (true) {\n                break abc;\n            }\n        `, \"(anonymous): Line 3:17 Undefined label 'abc'\")\n\n\t\t// S15.3_A2_T1\n\t\ttest(`var x / = 1;`, \"(anonymous): Line 1:7 Unexpected token /\")\n\n\t\ttest(`\n            function abc() {\n                if (0)\n                    return;\n                else {\n                }\n            }\n        `, nil)\n\n\t\ttest(\"//\\u2028 var =;\", \"(anonymous): Line 2:6 Unexpected token =\")\n\n\t\ttest(`\n            throw\n            {}\n        `, \"(anonymous): Line 2:13 Illegal newline after throw\")\n\n\t\t// S7.6.1.1_A1.11\n\t\ttest(`\n            function = 1\n        `, \"(anonymous): Line 2:22 Unexpected token =\")\n\n\t\t// S7.8.3_A1.2_T1\n\t\ttest(`0e1`, nil)\n\n\t\ttest(\"abc = 1; abc\\n++\", \"(anonymous): Line 2:3 Unexpected end of input\")\n\n\t\t// ---\n\n\t\ttest(\"({ get abc() {} })\", nil)\n\n\t\ttest(`for (abc.def in {}) {}`, nil)\n\n\t\ttest(`while (true) { break }`, nil)\n\n\t\ttest(`while (true) { continue }`, nil)\n\n\t\ttest(`abc=/^(?:(\\w+:)\\/{2}(\\w+(?:\\.\\w+)*\\/?)|(.{0,2}\\/{1}))?([/.]*?(?:[^?]+)?\\/)?((?:[^/?]+)\\.(\\w+))(?:\\?(\\S+)?)?$/,def=/^(?:(\\w+:)\\/{2})|(.{0,2}\\/{1})?([/.]*?(?:[^?]+)?\\/?)?$/`, nil)\n\n\t\ttest(`(function() { try {} catch (err) {} finally {} return })`, nil)\n\n\t\ttest(`0xde0b6b3a7640080.toFixed(0)`, nil)\n\n\t\ttest(`/[^-._0-9A-Za-z\\xb7\\xc0-\\xd6\\xd8-\\xf6\\xf8-\\u037d\\u37f-\\u1fff\\u200c-\\u200d\\u203f\\u2040\\u2070-\\u218f]/`, nil)\n\n\t\ttest(`/[\\u0000-\\u0008\\u000B-\\u000C\\u000E-\\u001F\\uD800-\\uDFFF\\uFFFE-\\uFFFF]/`, nil)\n\n\t\ttest(\"var abc = 1;\\ufeff\", nil)\n\n\t\ttest(\"\\ufeff/* var abc = 1; */\", nil)\n\n\t\ttest(`if (-0x8000000000000000<=abc&&abc<=0x8000000000000000) {}`, nil)\n\n\t\ttest(`(function(){debugger;return this;})`, nil)\n\n\t\ttest(`\n\n        `, nil)\n\n\t\ttest(`\n            var abc = \"\"\n            debugger\n        `, nil)\n\n\t\ttest(`\n            var abc = /\\[\\]$/\n            debugger\n        `, nil)\n\n\t\ttest(`\n            var abc = 1 /\n                2\n            debugger\n        `, nil)\n\n\t\ttest(`\n            function mergeObjects(x, y) { /* dummy body */}\n\n            mergeObjects(\n                { \"duck\": \"quack\" },\n                { \"dog\": \"bark\" }, // Allow trailing comma after the last argument.\n            );\n        `, nil)\n\t})\n}\n\nfunc Test_parseStringLiteral(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := func(have, want string) {\n\t\t\thave, err := parseStringLiteral(have)\n\t\t\tis(err, nil)\n\t\t\tis(have, want)\n\t\t}\n\n\t\ttest(\"\", \"\")\n\n\t\ttest(\"1(\\\\\\\\d+)\", \"1(\\\\d+)\")\n\n\t\ttest(\"\\\\u2029\", \"\\u2029\")\n\n\t\ttest(\"abc\\\\uFFFFabc\", \"abc\\uFFFFabc\")\n\n\t\ttest(\"[First line \\\\\\nSecond line \\\\\\n Third line\\\\\\n.     ]\",\n\t\t\t\"[First line Second line  Third line.     ]\")\n\n\t\ttest(\"\\\\u007a\\\\x79\\\\u000a\\\\x78\", \"zy\\nx\")\n\n\t\t// S7.8.4_A4.2_T3\n\t\ttest(\"\\\\a\", \"a\")\n\t\ttest(\"\\u0410\", \"\\u0410\")\n\n\t\t// S7.8.4_A5.1_T1\n\t\ttest(\"\\\\0\", \"\\u0000\")\n\n\t\t// S8.4_A5\n\t\ttest(\"\\u0000\", \"\\u0000\")\n\n\t\t// 15.5.4.20\n\t\ttest(\"'abc'\\\\\\n'def'\", \"'abc''def'\")\n\n\t\t// 15.5.4.20-4-1\n\t\ttest(\"'abc'\\\\\\r\\n'def'\", \"'abc''def'\")\n\n\t\t// Octal\n\t\ttest(\"\\\\0\", \"\\000\")\n\t\ttest(\"\\\\00\", \"\\000\")\n\t\ttest(\"\\\\000\", \"\\000\")\n\t\ttest(\"\\\\09\", \"\\0009\")\n\t\ttest(\"\\\\009\", \"\\0009\")\n\t\ttest(\"\\\\0009\", \"\\0009\")\n\t\ttest(\"\\\\1\", \"\\001\")\n\t\ttest(\"\\\\01\", \"\\001\")\n\t\ttest(\"\\\\001\", \"\\001\")\n\t\ttest(\"\\\\0011\", \"\\0011\")\n\t\ttest(\"\\\\1abc\", \"\\001abc\")\n\n\t\ttest(\"\\\\\\u4e16\", \"\\u4e16\")\n\n\t\t// err\n\t\ttest = func(have, want string) {\n\t\t\thave, err := parseStringLiteral(have)\n\t\t\tis(err.Error(), want)\n\t\t\tis(have, \"\")\n\t\t}\n\n\t\ttest(`\\u`, `invalid escape: \\u: len(\"\") != 4`)\n\t\ttest(`\\u0`, `invalid escape: \\u: len(\"0\") != 4`)\n\t\ttest(`\\u00`, `invalid escape: \\u: len(\"00\") != 4`)\n\t\ttest(`\\u000`, `invalid escape: \\u: len(\"000\") != 4`)\n\n\t\ttest(`\\x`, `invalid escape: \\x: len(\"\") != 2`)\n\t\ttest(`\\x0`, `invalid escape: \\x: len(\"0\") != 2`)\n\t\ttest(`\\x0`, `invalid escape: \\x: len(\"0\") != 2`)\n\t})\n}\n\nfunc Test_parseNumberLiteral(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := func(input string, expect interface{}) {\n\t\t\tresult, err := parseNumberLiteral(input)\n\t\t\tis(err, nil)\n\t\t\tis(result, expect)\n\t\t}\n\n\t\ttest(\"0\", 0)\n\n\t\ttest(\"0x8000000000000000\", float64(9.223372036854776e+18))\n\t})\n}\n\nfunc Test_praseRegExpLiteral(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := func(input, literal, pattern, flags string) {\n\t\t\tparser := newParser(\"\", input, 1, nil)\n\t\t\tprogram, err := parser.parse()\n\t\t\tis(err, nil)\n\n\t\t\tregex := program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.RegExpLiteral)\n\t\t\tis(regex.Literal, literal)\n\t\t\tis(regex.Pattern, pattern)\n\t\t\tis(regex.Flags, flags)\n\t\t}\n\n\t\ttest(\"/abc/\", \"/abc/\", \"abc\", \"\")\n\t\ttest(\"/abc/gim\", \"/abc/gim\", \"abc\", \"gim\")\n\t\ttest(\"/abc/ \", \"/abc/\", \"abc\", \"\")\n\t\ttest(\"/abc/gim \", \"/abc/gim\", \"abc\", \"gim\")\n\t\ttest(\"/abc/;\", \"/abc/\", \"abc\", \"\")\n\t\ttest(\"/abc/gim;\", \"/abc/gim\", \"abc\", \"gim\")\n\t\ttest(\"/abc/\\n\", \"/abc/\", \"abc\", \"\")\n\t\ttest(\"/abc/gim\\n\", \"/abc/gim\", \"abc\", \"gim\")\n\t\ttest(\"/abc/;\\n\", \"/abc/\", \"abc\", \"\")\n\t\ttest(\"/abc/gim;\\n\", \"/abc/gim\", \"abc\", \"gim\")\n\t})\n}\n\nfunc TestPosition(t *testing.T) {\n\ttt(t, func() {\n\t\tparser := newParser(\"\", \"// Lorem ipsum\", 1, nil)\n\n\t\t// Out of range, idx0 (error condition)\n\t\tis(parser.slice(0, 1), \"\")\n\t\tis(parser.slice(0, 10), \"\")\n\n\t\t// Out of range, idx1 (error condition)\n\t\tis(parser.slice(1, 128), \"\")\n\n\t\tis(parser.str[0:0], \"\")\n\t\tis(parser.slice(1, 1), \"\")\n\n\t\tis(parser.str[0:1], \"/\")\n\t\tis(parser.slice(1, 2), \"/\")\n\n\t\tis(parser.str[0:14], \"// Lorem ipsum\")\n\t\tis(parser.slice(1, 15), \"// Lorem ipsum\")\n\n\t\tparser = newParser(\"\", \"(function(){ return 0; })\", 1, nil)\n\t\tprogram, err := parser.parse()\n\t\tis(err, nil)\n\n\t\tvar node ast.Node\n\t\tnode = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral)\n\t\tis(node.Idx0(), file.Idx(2))\n\t\tis(node.Idx1(), file.Idx(25))\n\t\tis(parser.slice(node.Idx0(), node.Idx1()), \"function(){ return 0; }\")\n\t\tis(parser.slice(node.Idx0(), node.Idx1()+1), \"function(){ return 0; })\")\n\t\tis(parser.slice(node.Idx0(), node.Idx1()+2), \"\")\n\t\tis(node.(*ast.FunctionLiteral).Source, \"function(){ return 0; }\")\n\n\t\tnode = program\n\t\tis(node.Idx0(), file.Idx(2))\n\t\tis(node.Idx1(), file.Idx(25))\n\t\tis(parser.slice(node.Idx0(), node.Idx1()), \"function(){ return 0; }\")\n\n\t\tparser = newParser(\"\", \"(function(){ return abc; })\", 1, nil)\n\t\tprogram, err = parser.parse()\n\t\tis(err, nil)\n\t\tnode = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral)\n\t\tis(node.(*ast.FunctionLiteral).Source, \"function(){ return abc; }\")\n\n\t\tparser = newParser(\"\", \"this.style\", 1, nil)\n\t\tprogram, err = parser.parse()\n\t\tis(err, nil)\n\t\tnode = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.DotExpression).Left.(*ast.ThisExpression)\n\t\tis(node.Idx0(), file.Idx(1))\n\t\tis(node.Idx1(), file.Idx(5))\n\n\t\tparser = newParser(\"\", \"(function(){ if (abc) { throw 'failed'; } })\", 1, nil)\n\t\tprogram, err = parser.parse()\n\t\tis(err, nil)\n\t\tblock := program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral).Body.(*ast.BlockStatement)\n\t\tnode = block.List[0].(*ast.IfStatement)\n\t\tis(node.Idx0(), 14)\n\t\tis(parser.slice(node.Idx0(), node.Idx1()), \"if (abc) { throw 'failed'; }\")\n\t\tnode = node.(*ast.IfStatement).Consequent.(*ast.BlockStatement).List[0].(*ast.ThrowStatement)\n\t\tis(node.Idx0(), 25)\n\t\tis(parser.slice(node.Idx0(), node.Idx1()), \"throw 'failed'\")\n\n\t\tparser = newParser(\"\", \"(function(){ for (x=1; x<=4; x++) { console.log(x); } })\", 1, nil)\n\t\tprogram, err = parser.parse()\n\t\tis(err, nil)\n\t\tblock = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral).Body.(*ast.BlockStatement)\n\t\tnode = block.List[0].(*ast.ForStatement)\n\t\tis(node.Idx0(), 14)\n\t\tis(parser.slice(node.Idx0(), node.Idx1()), \"for (x=1; x<=4; x++) { console.log(x); }\")\n\n\t\tparser = newParser(\"\", \"(function(){ for (p in o) { console.log(p); } })\", 1, nil)\n\t\tprogram, err = parser.parse()\n\t\tis(err, nil)\n\t\tblock = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral).Body.(*ast.BlockStatement)\n\t\tnode = block.List[0].(*ast.ForInStatement)\n\t\tis(node.Idx0(), 14)\n\t\tis(parser.slice(node.Idx0(), node.Idx1()), \"for (p in o) { console.log(p); }\")\n\n\t\tparser = newParser(\"\", \"x = {x: 1}\", 1, nil)\n\t\tprogram, err = parser.parse()\n\t\tis(err, nil)\n\t\tnode = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.AssignExpression).Right.(*ast.ObjectLiteral)\n\t\tis(node.Idx0(), 5)\n\t\tis(parser.slice(node.Idx0(), node.Idx1()), \"{x: 1}\")\n\n\t\tparser = newParser(\"\", \"x = [1, 2]\", 1, nil)\n\t\tprogram, err = parser.parse()\n\t\tis(err, nil)\n\t\tnode = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.AssignExpression).Right.(*ast.ArrayLiteral)\n\t\tis(node.Idx0(), 5)\n\t\tis(parser.slice(node.Idx0(), node.Idx1()), \"[1, 2]\")\n\n\t\tparser = newParser(\"\", \"x = true ? 1 : 2\", 1, nil)\n\t\tprogram, err = parser.parse()\n\t\tis(err, nil)\n\t\tnode = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.AssignExpression).Right.(*ast.ConditionalExpression)\n\t\tis(node.Idx0(), 5)\n\t\tis(parser.slice(node.Idx0(), node.Idx1()), \"true ? 1 : 2\")\n\n\t\tparser = newParser(\"\", \"(function(){ x = 1, y = 2; })\", 1, nil)\n\t\tprogram, err = parser.parse()\n\t\tis(err, nil)\n\t\tblock = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral).Body.(*ast.BlockStatement)\n\t\tnode = block.List[0].(*ast.ExpressionStatement).Expression.(*ast.SequenceExpression)\n\t\tis(node.Idx0(), 14)\n\t\tis(parser.slice(node.Idx0(), node.Idx1()), \"x = 1, y = 2\")\n\n\t\tparser = newParser(\"\", \"x = ~x\", 1, nil)\n\t\tprogram, err = parser.parse()\n\t\tis(err, nil)\n\t\tnode = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.AssignExpression).Right.(*ast.UnaryExpression)\n\t\tis(node.Idx0(), 5)\n\t\tis(parser.slice(node.Idx0(), node.Idx1()), \"~x\")\n\n\t\tparser = newParser(\"\", \"(function(){ xyz++; })\", 1, nil)\n\t\tprogram, err = parser.parse()\n\t\tis(err, nil)\n\t\tblock = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral).Body.(*ast.BlockStatement)\n\t\tnode = block.List[0].(*ast.ExpressionStatement).Expression.(*ast.UnaryExpression)\n\t\tis(node.Idx0(), 14)\n\t\tis(parser.slice(node.Idx0(), node.Idx1()), \"xyz++\")\n\n\t\tparser = newParser(\"\", \"(function(){ var abc, xyz = 1; })\", 1, nil)\n\t\tprogram, err = parser.parse()\n\t\tis(err, nil)\n\t\tblock = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral).Body.(*ast.BlockStatement)\n\t\tnode = block.List[0].(*ast.VariableStatement)\n\t\tis(node.Idx0(), 14)\n\t\tis(parser.slice(node.Idx0(), node.Idx1()), \"var abc, xyz = 1\")\n\t\tnode = block.List[0].(*ast.VariableStatement).List[0].(*ast.VariableExpression)\n\t\tis(node.Idx0(), 18)\n\t\tis(parser.slice(node.Idx0(), node.Idx1()), \"abc\")\n\t\tnode = block.List[0].(*ast.VariableStatement).List[1].(*ast.VariableExpression)\n\t\tis(node.Idx0(), 23)\n\t\tis(parser.slice(node.Idx0(), node.Idx1()), \"xyz = 1\")\n\n\t\tparser = newParser(\"\", \"for (i = 0; i < 10; i++) { if (i == 5) break; }\", 1, nil)\n\t\tprogram, err = parser.parse()\n\t\tis(err, nil)\n\t\tblock = program.Body[0].(*ast.ForStatement).Body.(*ast.BlockStatement)\n\t\tnode = block.List[0].(*ast.IfStatement).Consequent.(*ast.BranchStatement)\n\t\tis(node.Idx0(), 40)\n\t\tis(parser.slice(node.Idx0(), node.Idx1()), \"break\")\n\n\t\tparser = newParser(\"\", \"(function(){ xyz: for (i = 0; i < 10; i++) { if (i == 5) continue xyz; } })\", 1, nil)\n\t\tprogram, err = parser.parse()\n\t\tis(err, nil)\n\t\tblock = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral).Body.(*ast.BlockStatement)\n\t\tnode = block.List[0].(*ast.LabelledStatement)\n\t\tis(node.Idx0(), 14)\n\t\tis(parser.slice(node.Idx0(), node.Idx1()), \"xyz: for (i = 0; i < 10; i++) { if (i == 5) continue xyz; }\")\n\t\tblock = node.(*ast.LabelledStatement).Statement.(*ast.ForStatement).Body.(*ast.BlockStatement)\n\t\tnode = block.List[0].(*ast.IfStatement).Consequent.(*ast.BranchStatement)\n\t\tis(node.Idx0(), 58)\n\t\tis(parser.slice(node.Idx0(), node.Idx1()), \"continue xyz\")\n\n\t\tparser = newParser(\"\", \"(function(){ return; })\", 1, nil)\n\t\tprogram, err = parser.parse()\n\t\tis(err, nil)\n\t\tblock = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral).Body.(*ast.BlockStatement)\n\t\tnode = block.List[0].(*ast.ReturnStatement)\n\t\tis(node.Idx0(), 14)\n\t\tis(parser.slice(node.Idx0(), node.Idx1()), \"return\")\n\n\t\tparser = newParser(\"\", \"(function(){ return 10; })\", 1, nil)\n\t\tprogram, err = parser.parse()\n\t\tis(err, nil)\n\t\tblock = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral).Body.(*ast.BlockStatement)\n\t\tnode = block.List[0].(*ast.ReturnStatement)\n\t\tis(node.Idx0(), 14)\n\t\tis(parser.slice(node.Idx0(), node.Idx1()), \"return 10\")\n\n\t\tparser = newParser(\"\", \"(function(){ switch (a) { default: return; }})\", 1, nil)\n\t\tprogram, err = parser.parse()\n\t\tis(err, nil)\n\t\tblock = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral).Body.(*ast.BlockStatement)\n\t\tnode = block.List[0].(*ast.SwitchStatement)\n\t\tis(node.Idx0(), 14)\n\t\tis(parser.slice(node.Idx0(), node.Idx1()), \"switch (a) { default: return; }\")\n\n\t\tparser = newParser(\"\", \"(function(){ try { a(); } catch (error) { b(); } })\", 1, nil)\n\t\tprogram, err = parser.parse()\n\t\tis(err, nil)\n\t\tblock = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral).Body.(*ast.BlockStatement)\n\t\tnode = block.List[0].(*ast.TryStatement)\n\t\tis(node.Idx0(), 14)\n\t\tis(parser.slice(node.Idx0(), node.Idx1()), \"try { a(); } catch (error) { b(); }\")\n\t\tnode = block.List[0].(*ast.TryStatement).Catch\n\t\tis(node.Idx0(), 27)\n\t\tis(parser.slice(node.Idx0(), node.Idx1()), \"catch (error) { b(); }\")\n\n\t\tparser = newParser(\"\", \"(function(){ try { a(); } catch (error) { b(); } finally { c(); } })\", 1, nil)\n\t\tprogram, err = parser.parse()\n\t\tis(err, nil)\n\t\tblock = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral).Body.(*ast.BlockStatement)\n\t\tnode = block.List[0].(*ast.TryStatement)\n\t\tis(node.Idx0(), 14)\n\t\tis(parser.slice(node.Idx0(), node.Idx1()), \"try { a(); } catch (error) { b(); } finally { c(); }\")\n\n\t\tparser = newParser(\"\", \"(function(){ with (1) {} })\", 1, nil)\n\t\tprogram, err = parser.parse()\n\t\tis(err, nil)\n\t\tblock = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral).Body.(*ast.BlockStatement)\n\t\tnode = block.List[0].(*ast.WithStatement)\n\t\tis(node.Idx0(), 14)\n\t\tis(parser.slice(node.Idx0(), node.Idx1()), \"with (1) {}\")\n\n\t\tparser = newParser(\"\", \"while (i < 10) { i++; }\", 1, nil)\n\t\tprogram, err = parser.parse()\n\t\tis(err, nil)\n\t\tnode = program.Body[0].(*ast.WhileStatement)\n\t\tis(node.Idx0(), 1)\n\t\tis(parser.slice(node.Idx0(), node.Idx1()), \"while (i < 10) { i++; }\")\n\n\t\tparser = newParser(\"\", \"do { i++; } while (i < 10 )\", 1, nil)\n\t\tprogram, err = parser.parse()\n\t\tis(err, nil)\n\t\tnode = program.Body[0].(*ast.DoWhileStatement)\n\t\tis(node.Idx0(), 1)\n\t\tis(parser.slice(node.Idx0(), node.Idx1()), \"do { i++; } while (i < 10 )\")\n\n\t\tparser = newParser(\"\", \"(function() { // single-line comment\\n })\", 1, nil)\n\t\tparser.mode |= StoreComments\n\t\tprogram, err = parser.parse()\n\t\tis(err, nil)\n\t\tblock = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral).Body.(*ast.BlockStatement)\n\t\tcomment := parser.comments.CommentMap[block][0]\n\t\tis(comment.Begin, 15)\n\t\tis(parser.slice(comment.Begin, file.Idx(int(comment.Begin)+len(comment.Text)+2)), \"// single-line comment\")\n\n\t\tparser = newParser(\"\", \"(function() { /* multi-line comment */ })\", 1, nil)\n\t\tparser.mode |= StoreComments\n\t\tprogram, err = parser.parse()\n\t\tis(err, nil)\n\t\tblock = program.Body[0].(*ast.ExpressionStatement).Expression.(*ast.FunctionLiteral).Body.(*ast.BlockStatement)\n\t\tcomment = parser.comments.CommentMap[block][0]\n\t\tis(comment.Begin, 15)\n\t\tis(parser.slice(comment.Begin, file.Idx(int(comment.Begin)+len(comment.Text)+4)), \"/* multi-line comment */\")\n\t})\n}\n\nfunc BenchmarkParser(b *testing.B) {\n\tsrc := underscore.Source()\n\tb.ResetTimer()\n\n\tfor i := 0; i < b.N; i++ {\n\t\tparser := newParser(\"\", src, 1, nil)\n\t\t_, err := parser.parse()\n\t\trequire.NoError(b, err)\n\t}\n}\n"
  },
  {
    "path": "parser/regexp.go",
    "content": "package parser\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"strconv\"\n)\n\ntype regExpParser struct {\n\tgoRegexp  *bytes.Buffer\n\tstr       string\n\terrors    []error\n\tlength    int\n\tchrOffset int\n\toffset    int\n\tchr       rune\n\tinvalid   bool\n}\n\n// TransformRegExp transforms a JavaScript pattern into  a Go \"regexp\" pattern.\n//\n// re2 (Go) cannot do backtracking, so the presence of a lookahead (?=) (?!) or\n// backreference (\\1, \\2, ...) will cause an error.\n//\n// re2 (Go) has a different definition for \\s: [\\t\\n\\f\\r ].\n// The JavaScript definition, on the other hand, also includes \\v, Unicode \"Separator, Space\", etc.\n//\n// If the pattern is invalid (not valid even in JavaScript), then this function\n// returns the empty string and an error.\n//\n// If the pattern is valid, but incompatible (contains a lookahead or backreference),\n// then this function returns the transformation (a non-empty string) AND an error.\nfunc TransformRegExp(pattern string) (string, error) {\n\tif pattern == \"\" {\n\t\treturn \"\", nil\n\t}\n\n\t// TODO If without \\, if without (?=, (?!, then another shortcut\n\n\tp := regExpParser{\n\t\tstr:      pattern,\n\t\tlength:   len(pattern),\n\t\tgoRegexp: bytes.NewBuffer(make([]byte, 0, 3*len(pattern)/2)),\n\t}\n\tp.read() // Pull in the first character\n\tp.scan()\n\tvar err error\n\tif len(p.errors) > 0 {\n\t\terr = p.errors[0]\n\t}\n\tif p.invalid {\n\t\treturn \"\", err\n\t}\n\n\t// Might not be re2 compatible, but is still a valid JavaScript RegExp\n\treturn p.goRegexp.String(), err\n}\n\nfunc (p *regExpParser) scan() {\n\tfor p.chr != -1 {\n\t\tswitch p.chr {\n\t\tcase '\\\\':\n\t\t\tp.read()\n\t\t\tp.scanEscape(false)\n\t\tcase '(':\n\t\t\tp.pass()\n\t\t\tp.scanGroup()\n\t\tcase '[':\n\t\t\tp.pass()\n\t\t\tp.scanBracket()\n\t\tcase ')':\n\t\t\tp.error(-1, \"Unmatched ')'\")\n\t\t\tp.invalid = true\n\t\t\tp.pass()\n\t\tdefault:\n\t\t\tp.pass()\n\t\t}\n\t}\n}\n\n// (...)\nfunc (p *regExpParser) scanGroup() {\n\tstr := p.str[p.chrOffset:]\n\tif len(str) > 1 { // A possibility of (?= or (?!\n\t\tif str[0] == '?' {\n\t\t\tif str[1] == '=' || str[1] == '!' {\n\t\t\t\tp.error(-1, \"re2: Invalid (%s) <lookahead>\", p.str[p.chrOffset:p.chrOffset+2])\n\t\t\t}\n\t\t}\n\t}\n\tfor p.chr != -1 && p.chr != ')' {\n\t\tswitch p.chr {\n\t\tcase '\\\\':\n\t\t\tp.read()\n\t\t\tp.scanEscape(false)\n\t\tcase '(':\n\t\t\tp.pass()\n\t\t\tp.scanGroup()\n\t\tcase '[':\n\t\t\tp.pass()\n\t\t\tp.scanBracket()\n\t\tdefault:\n\t\t\tp.pass()\n\t\t\tcontinue\n\t\t}\n\t}\n\tif p.chr != ')' {\n\t\tp.error(-1, \"Unterminated group\")\n\t\tp.invalid = true\n\t\treturn\n\t}\n\tp.pass()\n}\n\n// [...].\nfunc (p *regExpParser) scanBracket() {\n\tfor p.chr != -1 {\n\t\tif p.chr == ']' {\n\t\t\tbreak\n\t\t} else if p.chr == '\\\\' {\n\t\t\tp.read()\n\t\t\tp.scanEscape(true)\n\t\t\tcontinue\n\t\t}\n\t\tp.pass()\n\t}\n\tif p.chr != ']' {\n\t\tp.error(-1, \"Unterminated character class\")\n\t\tp.invalid = true\n\t\treturn\n\t}\n\tp.pass()\n}\n\n// \\...\nfunc (p *regExpParser) scanEscape(inClass bool) {\n\toffset := p.chrOffset\n\n\tvar length, base uint32\n\tswitch p.chr {\n\tcase '0', '1', '2', '3', '4', '5', '6', '7':\n\t\tvar value int64\n\t\tsize := 0\n\t\tfor {\n\t\t\tdigit := int64(digitValue(p.chr))\n\t\t\tif digit >= 8 {\n\t\t\t\t// Not a valid digit\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tvalue = value*8 + digit\n\t\t\tp.read()\n\t\t\tsize++\n\t\t}\n\t\tif size == 1 { // The number of characters read\n\t\t\t_, err := p.goRegexp.Write([]byte{'\\\\', byte(value) + '0'})\n\t\t\tif err != nil {\n\t\t\t\tp.errors = append(p.errors, err)\n\t\t\t}\n\t\t\tif value != 0 {\n\t\t\t\t// An invalid backreference\n\t\t\t\tp.error(-1, \"re2: Invalid \\\\%d <backreference>\", value)\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t\ttmp := []byte{'\\\\', 'x', '0', 0}\n\t\tif value >= 16 {\n\t\t\ttmp = tmp[0:2]\n\t\t} else {\n\t\t\ttmp = tmp[0:3]\n\t\t}\n\t\ttmp = strconv.AppendInt(tmp, value, 16)\n\t\t_, err := p.goRegexp.Write(tmp)\n\t\tif err != nil {\n\t\t\tp.errors = append(p.errors, err)\n\t\t}\n\t\treturn\n\n\tcase '8', '9':\n\t\tsize := 0\n\t\tfor {\n\t\t\tdigit := digitValue(p.chr)\n\t\t\tif digit >= 10 {\n\t\t\t\t// Not a valid digit\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tp.read()\n\t\t\tsize++\n\t\t}\n\t\terr := p.goRegexp.WriteByte('\\\\')\n\t\tif err != nil {\n\t\t\tp.errors = append(p.errors, err)\n\t\t}\n\t\t_, err = p.goRegexp.WriteString(p.str[offset:p.chrOffset])\n\t\tif err != nil {\n\t\t\tp.errors = append(p.errors, err)\n\t\t}\n\t\tp.error(-1, \"re2: Invalid \\\\%s <backreference>\", p.str[offset:p.chrOffset])\n\t\treturn\n\n\tcase 'x':\n\t\tp.read()\n\t\tlength, base = 2, 16\n\n\tcase 'u':\n\t\tp.read()\n\t\tlength, base = 4, 16\n\n\tcase 'b':\n\t\tif inClass {\n\t\t\t_, err := p.goRegexp.Write([]byte{'\\\\', 'x', '0', '8'})\n\t\t\tif err != nil {\n\t\t\t\tp.errors = append(p.errors, err)\n\t\t\t}\n\t\t\tp.read()\n\t\t\treturn\n\t\t}\n\t\tfallthrough\n\n\tcase 'B':\n\t\tfallthrough\n\n\tcase 'd', 'D', 's', 'S', 'w', 'W':\n\t\t// This is slightly broken, because ECMAScript\n\t\t// includes \\v in \\s, \\S, while re2 does not\n\t\tfallthrough\n\n\tcase '\\\\':\n\t\tfallthrough\n\n\tcase 'f', 'n', 'r', 't', 'v':\n\t\terr := p.goRegexp.WriteByte('\\\\')\n\t\tif err != nil {\n\t\t\tp.errors = append(p.errors, err)\n\t\t}\n\t\tp.pass()\n\t\treturn\n\n\tcase 'c':\n\t\tp.read()\n\t\tvar value int64\n\t\tswitch {\n\t\tcase 'a' <= p.chr && p.chr <= 'z':\n\t\t\tvalue = int64(p.chr) - 'a' + 1\n\t\tcase 'A' <= p.chr && p.chr <= 'Z':\n\t\t\tvalue = int64(p.chr) - 'A' + 1\n\t\tdefault:\n\t\t\terr := p.goRegexp.WriteByte('c')\n\t\t\tif err != nil {\n\t\t\t\tp.errors = append(p.errors, err)\n\t\t\t}\n\t\t\treturn\n\t\t}\n\t\ttmp := []byte{'\\\\', 'x', '0', 0}\n\t\tif value >= 16 {\n\t\t\ttmp = tmp[0:2]\n\t\t} else {\n\t\t\ttmp = tmp[0:3]\n\t\t}\n\t\ttmp = strconv.AppendInt(tmp, value, 16)\n\t\t_, err := p.goRegexp.Write(tmp)\n\t\tif err != nil {\n\t\t\tp.errors = append(p.errors, err)\n\t\t}\n\t\tp.read()\n\t\treturn\n\n\tdefault:\n\t\t// $ is an identifier character, so we have to have\n\t\t// a special case for it here\n\t\tif p.chr == '$' || !isIdentifierPart(p.chr) {\n\t\t\t// A non-identifier character needs escaping\n\t\t\terr := p.goRegexp.WriteByte('\\\\')\n\t\t\tif err != nil {\n\t\t\t\tp.errors = append(p.errors, err)\n\t\t\t}\n\t\t} else { //nolint:staticcheck\n\t\t\t// Unescape the character for re2\n\t\t}\n\t\tp.pass()\n\t\treturn\n\t}\n\n\t// Otherwise, we're a \\u.... or \\x...\n\tvalueOffset := p.chrOffset\n\n\tvar value uint32\n\tfor length := length; length > 0; length-- {\n\t\tdigit := uint32(digitValue(p.chr))\n\t\tif digit >= base {\n\t\t\t// Not a valid digit\n\t\t\tgoto skip\n\t\t}\n\t\tvalue = value*base + digit\n\t\tp.read()\n\t}\n\n\tswitch length {\n\tcase 4:\n\t\tif _, err := p.goRegexp.Write([]byte{\n\t\t\t'\\\\',\n\t\t\t'x',\n\t\t\t'{',\n\t\t\tp.str[valueOffset+0],\n\t\t\tp.str[valueOffset+1],\n\t\t\tp.str[valueOffset+2],\n\t\t\tp.str[valueOffset+3],\n\t\t\t'}',\n\t\t}); err != nil {\n\t\t\tp.errors = append(p.errors, err)\n\t\t}\n\tcase 2:\n\t\tif _, err := p.goRegexp.Write([]byte{\n\t\t\t'\\\\',\n\t\t\t'x',\n\t\t\tp.str[valueOffset+0],\n\t\t\tp.str[valueOffset+1],\n\t\t}); err != nil {\n\t\t\tp.errors = append(p.errors, err)\n\t\t}\n\tdefault:\n\t\t// Should never, ever get here...\n\t\tp.error(-1, \"re2: Illegal branch in scanEscape\")\n\t\tgoto skip\n\t}\n\n\treturn\n\nskip:\n\t_, err := p.goRegexp.WriteString(p.str[offset:p.chrOffset])\n\tif err != nil {\n\t\tp.errors = append(p.errors, err)\n\t}\n}\n\nfunc (p *regExpParser) pass() {\n\tif p.chr != -1 {\n\t\t_, err := p.goRegexp.WriteRune(p.chr)\n\t\tif err != nil {\n\t\t\tp.errors = append(p.errors, err)\n\t\t}\n\t}\n\tp.read()\n}\n\n// TODO Better error reporting, use the offset, etc.\nfunc (p *regExpParser) error(offset int, msg string, msgValues ...interface{}) { //nolint:unparam\n\terr := fmt.Errorf(msg, msgValues...)\n\tp.errors = append(p.errors, err)\n}\n"
  },
  {
    "path": "parser/regexp_test.go",
    "content": "package parser\n\nimport (\n\t\"regexp\"\n\t\"testing\"\n)\n\nfunc TestRegExp(t *testing.T) {\n\ttt(t, func() {\n\t\t{\n\t\t\t// err\n\t\t\ttest := func(input string, expect interface{}) {\n\t\t\t\t_, err := TransformRegExp(input)\n\t\t\t\tis(err, expect)\n\t\t\t}\n\n\t\t\ttest(\"[\", \"Unterminated character class\")\n\n\t\t\ttest(\"(\", \"Unterminated group\")\n\n\t\t\ttest(\"(?=)\", \"re2: Invalid (?=) <lookahead>\")\n\n\t\t\ttest(\"(?=)\", \"re2: Invalid (?=) <lookahead>\")\n\n\t\t\ttest(\"(?!)\", \"re2: Invalid (?!) <lookahead>\")\n\n\t\t\t// An error anyway\n\t\t\ttest(\"(?=\", \"re2: Invalid (?=) <lookahead>\")\n\n\t\t\ttest(\"\\\\1\", \"re2: Invalid \\\\1 <backreference>\")\n\n\t\t\ttest(\"\\\\90\", \"re2: Invalid \\\\90 <backreference>\")\n\n\t\t\ttest(\"\\\\9123456789\", \"re2: Invalid \\\\9123456789 <backreference>\")\n\n\t\t\ttest(\"\\\\(?=)\", \"Unmatched ')'\")\n\n\t\t\ttest(\")\", \"Unmatched ')'\")\n\t\t}\n\n\t\t{\n\t\t\t// err\n\t\t\ttest := func(input, expect string, expectErr interface{}) {\n\t\t\t\toutput, err := TransformRegExp(input)\n\t\t\t\tis(output, expect)\n\t\t\t\tis(err, expectErr)\n\t\t\t}\n\n\t\t\ttest(\"(?!)\", \"(?!)\", \"re2: Invalid (?!) <lookahead>\")\n\n\t\t\ttest(\")\", \"\", \"Unmatched ')'\")\n\n\t\t\ttest(\"(?!))\", \"\", \"re2: Invalid (?!) <lookahead>\")\n\n\t\t\ttest(\"\\\\0\", \"\\\\0\", nil)\n\n\t\t\ttest(\"\\\\1\", \"\\\\1\", \"re2: Invalid \\\\1 <backreference>\")\n\n\t\t\ttest(\"\\\\9123456789\", \"\\\\9123456789\", \"re2: Invalid \\\\9123456789 <backreference>\")\n\t\t}\n\n\t\t{\n\t\t\t// err\n\t\t\ttest := func(input string, expect string) {\n\t\t\t\tresult, err := TransformRegExp(input)\n\t\t\t\tis(err, nil)\n\t\t\t\tif is(result, expect) {\n\t\t\t\t\t_, err = regexp.Compile(result)\n\t\t\t\t\tif !is(err, nil) {\n\t\t\t\t\t\tt.Log(result)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttest(\"\", \"\")\n\n\t\t\ttest(\"abc\", \"abc\")\n\n\t\t\ttest(`\\abc`, `abc`)\n\n\t\t\ttest(`\\a\\b\\c`, `a\\bc`)\n\n\t\t\ttest(`\\x`, `x`)\n\n\t\t\ttest(`\\c`, `c`)\n\n\t\t\ttest(`\\cA`, `\\x01`)\n\n\t\t\ttest(`\\cz`, `\\x1a`)\n\n\t\t\ttest(`\\ca`, `\\x01`)\n\n\t\t\ttest(`\\cj`, `\\x0a`)\n\n\t\t\ttest(`\\ck`, `\\x0b`)\n\n\t\t\ttest(`\\+`, `\\+`)\n\n\t\t\ttest(`[\\b]`, `[\\x08]`)\n\n\t\t\ttest(`\\u0z01\\x\\undefined`, `u0z01xundefined`)\n\n\t\t\ttest(`\\\\|'|\\r|\\n|\\t|\\u2028|\\u2029`, `\\\\|'|\\r|\\n|\\t|\\x{2028}|\\x{2029}`)\n\n\t\t\ttest(\"]\", \"]\")\n\n\t\t\ttest(\"}\", \"}\")\n\n\t\t\ttest(\"%\", \"%\")\n\n\t\t\ttest(\"(%)\", \"(%)\")\n\n\t\t\ttest(\"(?:[%\\\\s])\", \"(?:[%\\\\s])\")\n\n\t\t\ttest(\"[[]\", \"[[]\")\n\n\t\t\ttest(\"\\\\101\", \"\\\\x41\")\n\n\t\t\ttest(\"\\\\51\", \"\\\\x29\")\n\n\t\t\ttest(\"\\\\051\", \"\\\\x29\")\n\n\t\t\ttest(\"\\\\175\", \"\\\\x7d\")\n\n\t\t\ttest(\"\\\\04\", \"\\\\x04\")\n\n\t\t\ttest(`<%([\\s\\S]+?)%>`, `<%([\\s\\S]+?)%>`)\n\n\t\t\ttest(`(.)^`, \"(.)^\")\n\n\t\t\ttest(`<%-([\\s\\S]+?)%>|<%=([\\s\\S]+?)%>|<%([\\s\\S]+?)%>|$`, `<%-([\\s\\S]+?)%>|<%=([\\s\\S]+?)%>|<%([\\s\\S]+?)%>|$`)\n\n\t\t\ttest(`\\$`, `\\$`)\n\n\t\t\ttest(`[G-b]`, `[G-b]`)\n\n\t\t\ttest(`[G-b\\0]`, `[G-b\\0]`)\n\t\t}\n\t})\n}\n\nfunc TestTransformRegExp(t *testing.T) {\n\ttt(t, func() {\n\t\tpattern, err := TransformRegExp(`\\s+abc\\s+`)\n\t\tis(err, nil)\n\t\tis(pattern, `\\s+abc\\s+`)\n\t\tis(regexp.MustCompile(pattern).MatchString(\"\\t abc def\"), true)\n\t})\n}\n"
  },
  {
    "path": "parser/scope.go",
    "content": "package parser\n\nimport (\n\t\"github.com/robertkrimen/otto/ast\"\n)\n\ntype scope struct {\n\touter           *scope\n\tdeclarationList []ast.Declaration\n\tlabels          []string\n\tallowIn         bool\n\tinIteration     bool\n\tinSwitch        bool\n\tinFunction      bool\n}\n\nfunc (p *parser) openScope() {\n\tp.scope = &scope{\n\t\touter:   p.scope,\n\t\tallowIn: true,\n\t}\n}\n\nfunc (p *parser) closeScope() {\n\tp.scope = p.scope.outer\n}\n\nfunc (p *scope) declare(declaration ast.Declaration) {\n\tp.declarationList = append(p.declarationList, declaration)\n}\n\nfunc (p *scope) hasLabel(name string) bool {\n\tfor _, label := range p.labels {\n\t\tif label == name {\n\t\t\treturn true\n\t\t}\n\t}\n\tif p.outer != nil && !p.inFunction {\n\t\t// Crossing a function boundary to look for a label is verboten\n\t\treturn p.outer.hasLabel(name)\n\t}\n\treturn false\n}\n"
  },
  {
    "path": "parser/statement.go",
    "content": "package parser\n\nimport (\n\t\"github.com/robertkrimen/otto/ast\"\n\t\"github.com/robertkrimen/otto/token\"\n)\n\nfunc (p *parser) parseBlockStatement() *ast.BlockStatement {\n\tnode := &ast.BlockStatement{}\n\n\t// Find comments before the leading brace\n\tif p.mode&StoreComments != 0 {\n\t\tp.comments.CommentMap.AddComments(node, p.comments.FetchAll(), ast.LEADING)\n\t\tp.comments.Unset()\n\t}\n\n\tnode.LeftBrace = p.expect(token.LEFT_BRACE)\n\tnode.List = p.parseStatementList()\n\n\tif p.mode&StoreComments != 0 {\n\t\tp.comments.Unset()\n\t\tp.comments.CommentMap.AddComments(node, p.comments.FetchAll(), ast.FINAL)\n\t\tp.comments.AfterBlock()\n\t}\n\n\tnode.RightBrace = p.expect(token.RIGHT_BRACE)\n\n\t// Find comments after the trailing brace\n\tif p.mode&StoreComments != 0 {\n\t\tp.comments.ResetLineBreak()\n\t\tp.comments.CommentMap.AddComments(node, p.comments.Fetch(), ast.TRAILING)\n\t}\n\n\treturn node\n}\n\nfunc (p *parser) parseEmptyStatement() ast.Statement {\n\tidx := p.expect(token.SEMICOLON)\n\treturn &ast.EmptyStatement{Semicolon: idx}\n}\n\nfunc (p *parser) parseStatementList() (list []ast.Statement) { //nolint:nonamedreturns\n\tfor p.token != token.RIGHT_BRACE && p.token != token.EOF {\n\t\tstatement := p.parseStatement()\n\t\tlist = append(list, statement)\n\t}\n\n\treturn list\n}\n\nfunc (p *parser) parseStatement() ast.Statement {\n\tif p.token == token.EOF {\n\t\tp.errorUnexpectedToken(p.token)\n\t\treturn &ast.BadStatement{From: p.idx, To: p.idx + 1}\n\t}\n\n\tif p.mode&StoreComments != 0 {\n\t\tp.comments.ResetLineBreak()\n\t}\n\n\tswitch p.token {\n\tcase token.SEMICOLON:\n\t\treturn p.parseEmptyStatement()\n\tcase token.LEFT_BRACE:\n\t\treturn p.parseBlockStatement()\n\tcase token.IF:\n\t\treturn p.parseIfStatement()\n\tcase token.DO:\n\t\tstatement := p.parseDoWhileStatement()\n\t\tp.comments.PostProcessNode(statement)\n\t\treturn statement\n\tcase token.WHILE:\n\t\treturn p.parseWhileStatement()\n\tcase token.FOR:\n\t\treturn p.parseForOrForInStatement()\n\tcase token.BREAK:\n\t\treturn p.parseBreakStatement()\n\tcase token.CONTINUE:\n\t\treturn p.parseContinueStatement()\n\tcase token.DEBUGGER:\n\t\treturn p.parseDebuggerStatement()\n\tcase token.WITH:\n\t\treturn p.parseWithStatement()\n\tcase token.VAR:\n\t\treturn p.parseVariableStatement()\n\tcase token.FUNCTION:\n\t\treturn p.parseFunctionStatement()\n\tcase token.SWITCH:\n\t\treturn p.parseSwitchStatement()\n\tcase token.RETURN:\n\t\treturn p.parseReturnStatement()\n\tcase token.THROW:\n\t\treturn p.parseThrowStatement()\n\tcase token.TRY:\n\t\treturn p.parseTryStatement()\n\t}\n\n\tvar comments []*ast.Comment\n\tif p.mode&StoreComments != 0 {\n\t\tcomments = p.comments.FetchAll()\n\t}\n\n\texpression := p.parseExpression()\n\n\tif identifier, isIdentifier := expression.(*ast.Identifier); isIdentifier && p.token == token.COLON {\n\t\t// LabelledStatement\n\t\tcolon := p.idx\n\t\tif p.mode&StoreComments != 0 {\n\t\t\tp.comments.Unset()\n\t\t}\n\t\tp.next() // :\n\n\t\tlabel := identifier.Name\n\t\tfor _, value := range p.scope.labels {\n\t\t\tif label == value {\n\t\t\t\tp.error(identifier.Idx0(), \"Label '%s' already exists\", label)\n\t\t\t}\n\t\t}\n\t\tvar labelComments []*ast.Comment\n\t\tif p.mode&StoreComments != 0 {\n\t\t\tlabelComments = p.comments.FetchAll()\n\t\t}\n\t\tp.scope.labels = append(p.scope.labels, label) // Push the label\n\t\tstatement := p.parseStatement()\n\t\tp.scope.labels = p.scope.labels[:len(p.scope.labels)-1] // Pop the label\n\t\texp := &ast.LabelledStatement{\n\t\t\tLabel:     identifier,\n\t\t\tColon:     colon,\n\t\t\tStatement: statement,\n\t\t}\n\t\tif p.mode&StoreComments != 0 {\n\t\t\tp.comments.CommentMap.AddComments(exp, labelComments, ast.LEADING)\n\t\t}\n\n\t\treturn exp\n\t}\n\n\tp.optionalSemicolon()\n\n\tstatement := &ast.ExpressionStatement{\n\t\tExpression: expression,\n\t}\n\n\tif p.mode&StoreComments != 0 {\n\t\tp.comments.CommentMap.AddComments(statement, comments, ast.LEADING)\n\t}\n\treturn statement\n}\n\nfunc (p *parser) parseTryStatement() ast.Statement {\n\tvar tryComments []*ast.Comment\n\tif p.mode&StoreComments != 0 {\n\t\ttryComments = p.comments.FetchAll()\n\t}\n\tnode := &ast.TryStatement{\n\t\tTry:  p.expect(token.TRY),\n\t\tBody: p.parseBlockStatement(),\n\t}\n\tif p.mode&StoreComments != 0 {\n\t\tp.comments.CommentMap.AddComments(node, tryComments, ast.LEADING)\n\t\tp.comments.CommentMap.AddComments(node.Body, p.comments.FetchAll(), ast.TRAILING)\n\t}\n\n\tif p.token == token.CATCH {\n\t\tcatch := p.idx\n\t\tif p.mode&StoreComments != 0 {\n\t\t\tp.comments.Unset()\n\t\t}\n\t\tp.next()\n\t\tp.expect(token.LEFT_PARENTHESIS)\n\t\tif p.token != token.IDENTIFIER {\n\t\t\tp.expect(token.IDENTIFIER)\n\t\t\tp.nextStatement()\n\t\t\treturn &ast.BadStatement{From: catch, To: p.idx}\n\t\t}\n\n\t\tidentifier := p.parseIdentifier()\n\t\tp.expect(token.RIGHT_PARENTHESIS)\n\t\tnode.Catch = &ast.CatchStatement{\n\t\t\tCatch:     catch,\n\t\t\tParameter: identifier,\n\t\t\tBody:      p.parseBlockStatement(),\n\t\t}\n\n\t\tif p.mode&StoreComments != 0 {\n\t\t\tp.comments.CommentMap.AddComments(node.Catch.Body, p.comments.FetchAll(), ast.TRAILING)\n\t\t}\n\t}\n\n\tif p.token == token.FINALLY {\n\t\tif p.mode&StoreComments != 0 {\n\t\t\tp.comments.Unset()\n\t\t}\n\t\tp.next()\n\t\tif p.mode&StoreComments != 0 {\n\t\t\ttryComments = p.comments.FetchAll()\n\t\t}\n\n\t\tnode.Finally = p.parseBlockStatement()\n\n\t\tif p.mode&StoreComments != 0 {\n\t\t\tp.comments.CommentMap.AddComments(node.Finally, tryComments, ast.LEADING)\n\t\t}\n\t}\n\n\tif node.Catch == nil && node.Finally == nil {\n\t\tp.error(node.Try, \"Missing catch or finally after try\")\n\t\treturn &ast.BadStatement{From: node.Try, To: node.Body.Idx1()}\n\t}\n\n\treturn node\n}\n\nfunc (p *parser) parseFunctionParameterList() *ast.ParameterList {\n\topening := p.expect(token.LEFT_PARENTHESIS)\n\tif p.mode&StoreComments != 0 {\n\t\tp.comments.Unset()\n\t}\n\tvar list []*ast.Identifier\n\tfor p.token != token.RIGHT_PARENTHESIS && p.token != token.EOF {\n\t\tif p.token != token.IDENTIFIER {\n\t\t\tp.expect(token.IDENTIFIER)\n\t\t} else {\n\t\t\tidentifier := p.parseIdentifier()\n\t\t\tlist = append(list, identifier)\n\t\t}\n\t\tif p.token != token.RIGHT_PARENTHESIS {\n\t\t\tif p.mode&StoreComments != 0 {\n\t\t\t\tp.comments.Unset()\n\t\t\t}\n\t\t\tp.expect(token.COMMA)\n\t\t}\n\t}\n\tclosing := p.expect(token.RIGHT_PARENTHESIS)\n\n\treturn &ast.ParameterList{\n\t\tOpening: opening,\n\t\tList:    list,\n\t\tClosing: closing,\n\t}\n}\n\nfunc (p *parser) parseFunctionStatement() *ast.FunctionStatement {\n\tvar comments []*ast.Comment\n\tif p.mode&StoreComments != 0 {\n\t\tcomments = p.comments.FetchAll()\n\t}\n\tfunction := &ast.FunctionStatement{\n\t\tFunction: p.parseFunction(true),\n\t}\n\tif p.mode&StoreComments != 0 {\n\t\tp.comments.CommentMap.AddComments(function, comments, ast.LEADING)\n\t}\n\n\treturn function\n}\n\nfunc (p *parser) parseFunction(declaration bool) *ast.FunctionLiteral {\n\tnode := &ast.FunctionLiteral{\n\t\tFunction: p.expect(token.FUNCTION),\n\t}\n\n\tvar name *ast.Identifier\n\tif p.token == token.IDENTIFIER {\n\t\tname = p.parseIdentifier()\n\t\tif declaration {\n\t\t\tp.scope.declare(&ast.FunctionDeclaration{\n\t\t\t\tFunction: node,\n\t\t\t})\n\t\t}\n\t} else if declaration {\n\t\t// Use expect error handling\n\t\tp.expect(token.IDENTIFIER)\n\t}\n\tif p.mode&StoreComments != 0 {\n\t\tp.comments.Unset()\n\t}\n\tnode.Name = name\n\tnode.ParameterList = p.parseFunctionParameterList()\n\tp.parseFunctionBlock(node)\n\tnode.Source = p.slice(node.Idx0(), node.Idx1())\n\n\treturn node\n}\n\nfunc (p *parser) parseFunctionBlock(node *ast.FunctionLiteral) {\n\tp.openScope()\n\tinFunction := p.scope.inFunction\n\tp.scope.inFunction = true\n\tdefer func() {\n\t\tp.scope.inFunction = inFunction\n\t\tp.closeScope()\n\t}()\n\tnode.Body = p.parseBlockStatement()\n\tnode.DeclarationList = p.scope.declarationList\n}\n\nfunc (p *parser) parseDebuggerStatement() ast.Statement {\n\tidx := p.expect(token.DEBUGGER)\n\n\tnode := &ast.DebuggerStatement{\n\t\tDebugger: idx,\n\t}\n\tif p.mode&StoreComments != 0 {\n\t\tp.comments.CommentMap.AddComments(node, p.comments.FetchAll(), ast.TRAILING)\n\t}\n\n\tp.semicolon()\n\treturn node\n}\n\nfunc (p *parser) parseReturnStatement() ast.Statement {\n\tidx := p.expect(token.RETURN)\n\tvar comments []*ast.Comment\n\tif p.mode&StoreComments != 0 {\n\t\tcomments = p.comments.FetchAll()\n\t}\n\n\tif !p.scope.inFunction {\n\t\tp.error(idx, \"Illegal return statement\")\n\t\tp.nextStatement()\n\t\treturn &ast.BadStatement{From: idx, To: p.idx}\n\t}\n\n\tnode := &ast.ReturnStatement{\n\t\tReturn: idx,\n\t}\n\n\tif !p.implicitSemicolon && p.token != token.SEMICOLON && p.token != token.RIGHT_BRACE && p.token != token.EOF {\n\t\tnode.Argument = p.parseExpression()\n\t}\n\tif p.mode&StoreComments != 0 {\n\t\tp.comments.CommentMap.AddComments(node, comments, ast.LEADING)\n\t}\n\n\tp.semicolon()\n\n\treturn node\n}\n\nfunc (p *parser) parseThrowStatement() ast.Statement {\n\tvar comments []*ast.Comment\n\tif p.mode&StoreComments != 0 {\n\t\tcomments = p.comments.FetchAll()\n\t}\n\tidx := p.expect(token.THROW)\n\n\tif p.implicitSemicolon {\n\t\tif p.chr == -1 { // Hackish\n\t\t\tp.error(idx, \"Unexpected end of input\")\n\t\t} else {\n\t\t\tp.error(idx, \"Illegal newline after throw\")\n\t\t}\n\t\tp.nextStatement()\n\t\treturn &ast.BadStatement{From: idx, To: p.idx}\n\t}\n\n\tnode := &ast.ThrowStatement{\n\t\tThrow:    idx,\n\t\tArgument: p.parseExpression(),\n\t}\n\tif p.mode&StoreComments != 0 {\n\t\tp.comments.CommentMap.AddComments(node, comments, ast.LEADING)\n\t}\n\n\tp.semicolon()\n\n\treturn node\n}\n\nfunc (p *parser) parseSwitchStatement() ast.Statement {\n\tvar comments []*ast.Comment\n\tif p.mode&StoreComments != 0 {\n\t\tcomments = p.comments.FetchAll()\n\t}\n\tidx := p.expect(token.SWITCH)\n\tif p.mode&StoreComments != 0 {\n\t\tcomments = append(comments, p.comments.FetchAll()...)\n\t}\n\tp.expect(token.LEFT_PARENTHESIS)\n\tnode := &ast.SwitchStatement{\n\t\tSwitch:       idx,\n\t\tDiscriminant: p.parseExpression(),\n\t\tDefault:      -1,\n\t}\n\tp.expect(token.RIGHT_PARENTHESIS)\n\tif p.mode&StoreComments != 0 {\n\t\tcomments = append(comments, p.comments.FetchAll()...)\n\t}\n\n\tp.expect(token.LEFT_BRACE)\n\n\tinSwitch := p.scope.inSwitch\n\tp.scope.inSwitch = true\n\tdefer func() {\n\t\tp.scope.inSwitch = inSwitch\n\t}()\n\n\tfor index := 0; p.token != token.EOF; index++ {\n\t\tif p.token == token.RIGHT_BRACE {\n\t\t\tnode.RightBrace = p.idx\n\t\t\tp.next()\n\t\t\tbreak\n\t\t}\n\n\t\tclause := p.parseCaseStatement()\n\t\tif clause.Test == nil {\n\t\t\tif node.Default != -1 {\n\t\t\t\tp.error(clause.Case, \"Already saw a default in switch\")\n\t\t\t}\n\t\t\tnode.Default = index\n\t\t}\n\t\tnode.Body = append(node.Body, clause)\n\t}\n\n\tif p.mode&StoreComments != 0 {\n\t\tp.comments.CommentMap.AddComments(node, comments, ast.LEADING)\n\t}\n\n\treturn node\n}\n\nfunc (p *parser) parseWithStatement() ast.Statement {\n\tvar comments []*ast.Comment\n\tif p.mode&StoreComments != 0 {\n\t\tcomments = p.comments.FetchAll()\n\t}\n\tidx := p.expect(token.WITH)\n\tvar withComments []*ast.Comment\n\tif p.mode&StoreComments != 0 {\n\t\twithComments = p.comments.FetchAll()\n\t}\n\n\tp.expect(token.LEFT_PARENTHESIS)\n\n\tnode := &ast.WithStatement{\n\t\tWith:   idx,\n\t\tObject: p.parseExpression(),\n\t}\n\tp.expect(token.RIGHT_PARENTHESIS)\n\n\tif p.mode&StoreComments != 0 {\n\t\tp.comments.CommentMap.AddComments(node, comments, ast.LEADING)\n\t\tp.comments.CommentMap.AddComments(node, withComments, ast.WITH)\n\t}\n\n\tnode.Body = p.parseStatement()\n\n\treturn node\n}\n\nfunc (p *parser) parseCaseStatement() *ast.CaseStatement {\n\tnode := &ast.CaseStatement{\n\t\tCase: p.idx,\n\t}\n\n\tvar comments []*ast.Comment\n\tif p.mode&StoreComments != 0 {\n\t\tcomments = p.comments.FetchAll()\n\t\tp.comments.Unset()\n\t}\n\n\tif p.token == token.DEFAULT {\n\t\tp.next()\n\t} else {\n\t\tp.expect(token.CASE)\n\t\tnode.Test = p.parseExpression()\n\t}\n\n\tif p.mode&StoreComments != 0 {\n\t\tp.comments.Unset()\n\t}\n\tp.expect(token.COLON)\n\n\tfor {\n\t\tif p.token == token.EOF ||\n\t\t\tp.token == token.RIGHT_BRACE ||\n\t\t\tp.token == token.CASE ||\n\t\t\tp.token == token.DEFAULT {\n\t\t\tbreak\n\t\t}\n\t\tconsequent := p.parseStatement()\n\t\tnode.Consequent = append(node.Consequent, consequent)\n\t}\n\n\t// Link the comments to the case statement\n\tif p.mode&StoreComments != 0 {\n\t\tp.comments.CommentMap.AddComments(node, comments, ast.LEADING)\n\t}\n\n\treturn node\n}\n\nfunc (p *parser) parseIterationStatement() ast.Statement {\n\tinIteration := p.scope.inIteration\n\tp.scope.inIteration = true\n\tdefer func() {\n\t\tp.scope.inIteration = inIteration\n\t}()\n\treturn p.parseStatement()\n}\n\nfunc (p *parser) parseForIn(into ast.Expression) *ast.ForInStatement {\n\t// Already have consumed \"<into> in\"\n\n\tsource := p.parseExpression()\n\tp.expect(token.RIGHT_PARENTHESIS)\n\tbody := p.parseIterationStatement()\n\n\tforin := &ast.ForInStatement{\n\t\tInto:   into,\n\t\tSource: source,\n\t\tBody:   body,\n\t}\n\n\treturn forin\n}\n\nfunc (p *parser) parseFor(initializer ast.Expression) *ast.ForStatement {\n\t// Already have consumed \"<initializer> ;\"\n\n\tvar test, update ast.Expression\n\n\tif p.token != token.SEMICOLON {\n\t\ttest = p.parseExpression()\n\t}\n\tif p.mode&StoreComments != 0 {\n\t\tp.comments.Unset()\n\t}\n\tp.expect(token.SEMICOLON)\n\n\tif p.token != token.RIGHT_PARENTHESIS {\n\t\tupdate = p.parseExpression()\n\t}\n\tp.expect(token.RIGHT_PARENTHESIS)\n\tbody := p.parseIterationStatement()\n\n\tforstatement := &ast.ForStatement{\n\t\tInitializer: initializer,\n\t\tTest:        test,\n\t\tUpdate:      update,\n\t\tBody:        body,\n\t}\n\n\treturn forstatement\n}\n\nfunc (p *parser) parseForOrForInStatement() ast.Statement {\n\tvar comments []*ast.Comment\n\tif p.mode&StoreComments != 0 {\n\t\tcomments = p.comments.FetchAll()\n\t}\n\tidx := p.expect(token.FOR)\n\tvar forComments []*ast.Comment\n\tif p.mode&StoreComments != 0 {\n\t\tforComments = p.comments.FetchAll()\n\t}\n\tp.expect(token.LEFT_PARENTHESIS)\n\n\tvar left []ast.Expression\n\n\tforIn := false\n\tif p.token != token.SEMICOLON {\n\t\tallowIn := p.scope.allowIn\n\t\tp.scope.allowIn = false\n\t\tif p.token == token.VAR {\n\t\t\ttokenIdx := p.idx\n\t\t\tvar varComments []*ast.Comment\n\t\t\tif p.mode&StoreComments != 0 {\n\t\t\t\tvarComments = p.comments.FetchAll()\n\t\t\t\tp.comments.Unset()\n\t\t\t}\n\t\t\tp.next()\n\t\t\tlist := p.parseVariableDeclarationList(tokenIdx)\n\t\t\tif len(list) == 1 && p.token == token.IN {\n\t\t\t\tif p.mode&StoreComments != 0 {\n\t\t\t\t\tp.comments.Unset()\n\t\t\t\t}\n\t\t\t\tp.next() // in\n\t\t\t\tforIn = true\n\t\t\t\tleft = []ast.Expression{list[0]} // There is only one declaration\n\t\t\t} else {\n\t\t\t\tleft = list\n\t\t\t}\n\t\t\tif p.mode&StoreComments != 0 {\n\t\t\t\tp.comments.CommentMap.AddComments(left[0], varComments, ast.LEADING)\n\t\t\t}\n\t\t} else {\n\t\t\tleft = append(left, p.parseExpression())\n\t\t\tif p.token == token.IN {\n\t\t\t\tp.next()\n\t\t\t\tforIn = true\n\t\t\t}\n\t\t}\n\t\tp.scope.allowIn = allowIn\n\t}\n\n\tif forIn {\n\t\tswitch left[0].(type) {\n\t\tcase *ast.Identifier, *ast.DotExpression, *ast.BracketExpression, *ast.VariableExpression:\n\t\t\t// These are all acceptable\n\t\tdefault:\n\t\t\tp.error(idx, \"Invalid left-hand side in for-in\")\n\t\t\tp.nextStatement()\n\t\t\treturn &ast.BadStatement{From: idx, To: p.idx}\n\t\t}\n\n\t\tforin := p.parseForIn(left[0])\n\t\tforin.For = idx\n\t\tif p.mode&StoreComments != 0 {\n\t\t\tp.comments.CommentMap.AddComments(forin, comments, ast.LEADING)\n\t\t\tp.comments.CommentMap.AddComments(forin, forComments, ast.FOR)\n\t\t}\n\t\treturn forin\n\t}\n\n\tif p.mode&StoreComments != 0 {\n\t\tp.comments.Unset()\n\t}\n\tp.expect(token.SEMICOLON)\n\tinitializer := &ast.SequenceExpression{Sequence: left}\n\tforstatement := p.parseFor(initializer)\n\tforstatement.For = idx\n\tif p.mode&StoreComments != 0 {\n\t\tp.comments.CommentMap.AddComments(forstatement, comments, ast.LEADING)\n\t\tp.comments.CommentMap.AddComments(forstatement, forComments, ast.FOR)\n\t}\n\treturn forstatement\n}\n\nfunc (p *parser) parseVariableStatement() *ast.VariableStatement {\n\tvar comments []*ast.Comment\n\tif p.mode&StoreComments != 0 {\n\t\tcomments = p.comments.FetchAll()\n\t}\n\tidx := p.expect(token.VAR)\n\n\tlist := p.parseVariableDeclarationList(idx)\n\n\tstatement := &ast.VariableStatement{\n\t\tVar:  idx,\n\t\tList: list,\n\t}\n\tif p.mode&StoreComments != 0 {\n\t\tp.comments.CommentMap.AddComments(statement, comments, ast.LEADING)\n\t\tp.comments.Unset()\n\t}\n\tp.semicolon()\n\n\treturn statement\n}\n\nfunc (p *parser) parseDoWhileStatement() ast.Statement {\n\tinIteration := p.scope.inIteration\n\tp.scope.inIteration = true\n\tdefer func() {\n\t\tp.scope.inIteration = inIteration\n\t}()\n\n\tvar comments []*ast.Comment\n\tif p.mode&StoreComments != 0 {\n\t\tcomments = p.comments.FetchAll()\n\t}\n\tidx := p.expect(token.DO)\n\tvar doComments []*ast.Comment\n\tif p.mode&StoreComments != 0 {\n\t\tdoComments = p.comments.FetchAll()\n\t}\n\n\tnode := &ast.DoWhileStatement{Do: idx}\n\tif p.token == token.LEFT_BRACE {\n\t\tnode.Body = p.parseBlockStatement()\n\t} else {\n\t\tnode.Body = p.parseStatement()\n\t}\n\n\tp.expect(token.WHILE)\n\tvar whileComments []*ast.Comment\n\tif p.mode&StoreComments != 0 {\n\t\twhileComments = p.comments.FetchAll()\n\t}\n\tp.expect(token.LEFT_PARENTHESIS)\n\tnode.Test = p.parseExpression()\n\tnode.RightParenthesis = p.expect(token.RIGHT_PARENTHESIS)\n\n\tp.implicitSemicolon = true\n\tp.optionalSemicolon()\n\n\tif p.mode&StoreComments != 0 {\n\t\tp.comments.CommentMap.AddComments(node, comments, ast.LEADING)\n\t\tp.comments.CommentMap.AddComments(node, doComments, ast.DO)\n\t\tp.comments.CommentMap.AddComments(node, whileComments, ast.WHILE)\n\t}\n\n\treturn node\n}\n\nfunc (p *parser) parseWhileStatement() ast.Statement {\n\tvar comments []*ast.Comment\n\tif p.mode&StoreComments != 0 {\n\t\tcomments = p.comments.FetchAll()\n\t}\n\tidx := p.expect(token.WHILE)\n\n\tvar whileComments []*ast.Comment\n\tif p.mode&StoreComments != 0 {\n\t\twhileComments = p.comments.FetchAll()\n\t}\n\n\tp.expect(token.LEFT_PARENTHESIS)\n\tnode := &ast.WhileStatement{\n\t\tWhile: idx,\n\t\tTest:  p.parseExpression(),\n\t}\n\tp.expect(token.RIGHT_PARENTHESIS)\n\tnode.Body = p.parseIterationStatement()\n\n\tif p.mode&StoreComments != 0 {\n\t\tp.comments.CommentMap.AddComments(node, comments, ast.LEADING)\n\t\tp.comments.CommentMap.AddComments(node, whileComments, ast.WHILE)\n\t}\n\n\treturn node\n}\n\nfunc (p *parser) parseIfStatement() ast.Statement {\n\tvar comments []*ast.Comment\n\tif p.mode&StoreComments != 0 {\n\t\tcomments = p.comments.FetchAll()\n\t}\n\tpos := p.expect(token.IF)\n\tvar ifComments []*ast.Comment\n\tif p.mode&StoreComments != 0 {\n\t\tifComments = p.comments.FetchAll()\n\t}\n\n\tp.expect(token.LEFT_PARENTHESIS)\n\tnode := &ast.IfStatement{\n\t\tIf:   pos,\n\t\tTest: p.parseExpression(),\n\t}\n\tp.expect(token.RIGHT_PARENTHESIS)\n\tif p.token == token.LEFT_BRACE {\n\t\tnode.Consequent = p.parseBlockStatement()\n\t} else {\n\t\tnode.Consequent = p.parseStatement()\n\t}\n\n\tif p.token == token.ELSE {\n\t\tp.next()\n\t\tnode.Alternate = p.parseStatement()\n\t}\n\n\tif p.mode&StoreComments != 0 {\n\t\tp.comments.CommentMap.AddComments(node, comments, ast.LEADING)\n\t\tp.comments.CommentMap.AddComments(node, ifComments, ast.IF)\n\t}\n\n\treturn node\n}\n\nfunc (p *parser) parseSourceElement() ast.Statement {\n\tstatement := p.parseStatement()\n\treturn statement\n}\n\nfunc (p *parser) parseSourceElements() []ast.Statement {\n\tbody := []ast.Statement(nil)\n\n\tfor {\n\t\tif p.token != token.STRING {\n\t\t\tbreak\n\t\t}\n\t\tbody = append(body, p.parseSourceElement())\n\t}\n\n\tfor p.token != token.EOF {\n\t\tbody = append(body, p.parseSourceElement())\n\t}\n\n\treturn body\n}\n\nfunc (p *parser) parseProgram() *ast.Program {\n\tp.openScope()\n\tdefer p.closeScope()\n\treturn &ast.Program{\n\t\tBody:            p.parseSourceElements(),\n\t\tDeclarationList: p.scope.declarationList,\n\t\tFile:            p.file,\n\t}\n}\n\nfunc (p *parser) parseBreakStatement() ast.Statement {\n\tvar comments []*ast.Comment\n\tif p.mode&StoreComments != 0 {\n\t\tcomments = p.comments.FetchAll()\n\t}\n\tidx := p.expect(token.BREAK)\n\tsemicolon := p.implicitSemicolon\n\tif p.token == token.SEMICOLON {\n\t\tsemicolon = true\n\t\tp.next()\n\t}\n\n\tif semicolon || p.token == token.RIGHT_BRACE {\n\t\tp.implicitSemicolon = false\n\t\tif !p.scope.inIteration && !p.scope.inSwitch {\n\t\t\tgoto illegal\n\t\t}\n\t\tbreakStatement := &ast.BranchStatement{\n\t\t\tIdx:   idx,\n\t\t\tToken: token.BREAK,\n\t\t}\n\n\t\tif p.mode&StoreComments != 0 {\n\t\t\tp.comments.CommentMap.AddComments(breakStatement, comments, ast.LEADING)\n\t\t\tp.comments.CommentMap.AddComments(breakStatement, p.comments.FetchAll(), ast.TRAILING)\n\t\t}\n\n\t\treturn breakStatement\n\t}\n\n\tif p.token == token.IDENTIFIER {\n\t\tidentifier := p.parseIdentifier()\n\t\tif !p.scope.hasLabel(identifier.Name) {\n\t\t\tp.error(idx, \"Undefined label '%s'\", identifier.Name)\n\t\t\treturn &ast.BadStatement{From: idx, To: identifier.Idx1()}\n\t\t}\n\t\tp.semicolon()\n\t\tbreakStatement := &ast.BranchStatement{\n\t\t\tIdx:   idx,\n\t\t\tToken: token.BREAK,\n\t\t\tLabel: identifier,\n\t\t}\n\t\tif p.mode&StoreComments != 0 {\n\t\t\tp.comments.CommentMap.AddComments(breakStatement, comments, ast.LEADING)\n\t\t}\n\n\t\treturn breakStatement\n\t}\n\n\tp.expect(token.IDENTIFIER)\n\nillegal:\n\tp.error(idx, \"Illegal break statement\")\n\tp.nextStatement()\n\treturn &ast.BadStatement{From: idx, To: p.idx}\n}\n\nfunc (p *parser) parseContinueStatement() ast.Statement {\n\tidx := p.expect(token.CONTINUE)\n\tsemicolon := p.implicitSemicolon\n\tif p.token == token.SEMICOLON {\n\t\tsemicolon = true\n\t\tp.next()\n\t}\n\n\tif semicolon || p.token == token.RIGHT_BRACE {\n\t\tp.implicitSemicolon = false\n\t\tif !p.scope.inIteration {\n\t\t\tgoto illegal\n\t\t}\n\t\treturn &ast.BranchStatement{\n\t\t\tIdx:   idx,\n\t\t\tToken: token.CONTINUE,\n\t\t}\n\t}\n\n\tif p.token == token.IDENTIFIER {\n\t\tidentifier := p.parseIdentifier()\n\t\tif !p.scope.hasLabel(identifier.Name) {\n\t\t\tp.error(idx, \"Undefined label '%s'\", identifier.Name)\n\t\t\treturn &ast.BadStatement{From: idx, To: identifier.Idx1()}\n\t\t}\n\t\tif !p.scope.inIteration {\n\t\t\tgoto illegal\n\t\t}\n\t\tp.semicolon()\n\t\treturn &ast.BranchStatement{\n\t\t\tIdx:   idx,\n\t\t\tToken: token.CONTINUE,\n\t\t\tLabel: identifier,\n\t\t}\n\t}\n\n\tp.expect(token.IDENTIFIER)\n\nillegal:\n\tp.error(idx, \"Illegal continue statement\")\n\tp.nextStatement()\n\treturn &ast.BadStatement{From: idx, To: p.idx}\n}\n\n// Find the next statement after an error (recover).\nfunc (p *parser) nextStatement() {\n\tfor {\n\t\tswitch p.token {\n\t\tcase token.BREAK, token.CONTINUE,\n\t\t\ttoken.FOR, token.IF, token.RETURN, token.SWITCH,\n\t\t\ttoken.VAR, token.DO, token.TRY, token.WITH,\n\t\t\ttoken.WHILE, token.THROW, token.CATCH, token.FINALLY:\n\t\t\t// Return only if parser made some progress since last\n\t\t\t// sync or if it has not reached 10 next calls without\n\t\t\t// progress. Otherwise consume at least one token to\n\t\t\t// avoid an endless parser loop\n\t\t\tif p.idx == p.recover.idx && p.recover.count < 10 {\n\t\t\t\tp.recover.count++\n\t\t\t\treturn\n\t\t\t}\n\t\t\tif p.idx > p.recover.idx {\n\t\t\t\tp.recover.idx = p.idx\n\t\t\t\tp.recover.count = 0\n\t\t\t\treturn\n\t\t\t}\n\t\t\t// Reaching here indicates a parser bug, likely an\n\t\t\t// incorrect token list in this function, but it only\n\t\t\t// leads to skipping of possibly correct code if a\n\t\t\t// previous error is present, and thus is preferred\n\t\t\t// over a non-terminating parse.\n\t\tcase token.EOF:\n\t\t\treturn\n\t\t}\n\t\tp.next()\n\t}\n}\n"
  },
  {
    "path": "parser_test.go",
    "content": "package otto\n\nimport (\n\t\"testing\"\n)\n\nfunc TestPersistence(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n        function abc() { return 1; }\n        abc.toString();\n    `, \"function abc() { return 1; }\")\n\n\t\ttest(`\n        function def() { return 3.14159; }\n        [ abc.toString(), def.toString() ];\n    `, \"function abc() { return 1; },function def() { return 3.14159; }\")\n\n\t\ttest(`\n        eval(\"function ghi() { return 'ghi' }\");\n        [ abc.toString(), def.toString(), ghi.toString() ];\n    `, \"function abc() { return 1; },function def() { return 3.14159; },function ghi() { return 'ghi' }\")\n\n\t\ttest(`\n        [ abc.toString(), def.toString(), ghi.toString() ];\n    `, \"function abc() { return 1; },function def() { return 3.14159; },function ghi() { return 'ghi' }\")\n\n\t\ttest(`/*\n\n\n\n\n\n\n\n\n\n    */`, UndefinedValue())\n\t})\n}\n"
  },
  {
    "path": "property.go",
    "content": "package otto\n\n// property\n\ntype propertyMode int\n\nconst (\n\tmodeWriteMask     propertyMode = 0o700\n\tmodeEnumerateMask propertyMode = 0o070\n\tmodeConfigureMask propertyMode = 0o007\n\tmodeOnMask        propertyMode = 0o111\n\tmodeSetMask       propertyMode = 0o222 // If value is 2, then mode is neither \"On\" nor \"Off\"\n)\n\ntype propertyGetSet [2]*object\n\nvar nilGetSetObject = object{}\n\ntype property struct {\n\tvalue interface{}\n\tmode  propertyMode\n}\n\nfunc (p property) writable() bool {\n\treturn p.mode&modeWriteMask == modeWriteMask&modeOnMask\n}\n\nfunc (p *property) writeOn() {\n\tp.mode = (p.mode & ^modeWriteMask) | (modeWriteMask & modeOnMask)\n}\n\nfunc (p *property) writeOff() {\n\tp.mode &= ^modeWriteMask\n}\n\nfunc (p *property) writeClear() {\n\tp.mode = (p.mode & ^modeWriteMask) | (modeWriteMask & modeSetMask)\n}\n\nfunc (p property) writeSet() bool {\n\treturn p.mode&modeWriteMask&modeSetMask == 0\n}\n\nfunc (p property) enumerable() bool {\n\treturn p.mode&modeEnumerateMask == modeEnumerateMask&modeOnMask\n}\n\nfunc (p *property) enumerateOn() {\n\tp.mode = (p.mode & ^modeEnumerateMask) | (modeEnumerateMask & modeOnMask)\n}\n\nfunc (p *property) enumerateOff() {\n\tp.mode &= ^modeEnumerateMask\n}\n\nfunc (p property) enumerateSet() bool {\n\treturn p.mode&modeEnumerateMask&modeSetMask == 0\n}\n\nfunc (p property) configurable() bool {\n\treturn p.mode&modeConfigureMask == modeConfigureMask&modeOnMask\n}\n\nfunc (p *property) configureOn() {\n\tp.mode = (p.mode & ^modeConfigureMask) | (modeConfigureMask & modeOnMask)\n}\n\nfunc (p *property) configureOff() {\n\tp.mode &= ^modeConfigureMask\n}\n\nfunc (p property) configureSet() bool { //nolint:unused\n\treturn p.mode&modeConfigureMask&modeSetMask == 0\n}\n\nfunc (p property) copy() *property { //nolint:unused\n\tcpy := p\n\treturn &cpy\n}\n\nfunc (p property) get(this *object) Value {\n\tswitch value := p.value.(type) {\n\tcase Value:\n\t\treturn value\n\tcase propertyGetSet:\n\t\tif value[0] != nil {\n\t\t\treturn value[0].call(toValue(this), nil, false, nativeFrame)\n\t\t}\n\t}\n\treturn Value{}\n}\n\nfunc (p property) isAccessorDescriptor() bool {\n\tsetGet, test := p.value.(propertyGetSet)\n\treturn test && (setGet[0] != nil || setGet[1] != nil)\n}\n\nfunc (p property) isDataDescriptor() bool {\n\tif p.writeSet() { // Either \"On\" or \"Off\"\n\t\treturn true\n\t}\n\tvalue, valid := p.value.(Value)\n\treturn valid && !value.isEmpty()\n}\n\nfunc (p property) isGenericDescriptor() bool {\n\treturn !(p.isDataDescriptor() || p.isAccessorDescriptor())\n}\n\nfunc (p property) isEmpty() bool {\n\treturn p.mode == 0o222 && p.isGenericDescriptor()\n}\n\n// _enumerableValue, _enumerableTrue, _enumerableFalse?\n// .enumerableValue() .enumerableExists()\n\nfunc toPropertyDescriptor(rt *runtime, value Value) property {\n\tobjectDescriptor := value.object()\n\tif objectDescriptor == nil {\n\t\tpanic(rt.panicTypeError(\"toPropertyDescriptor on nil\"))\n\t}\n\n\tvar descriptor property\n\tdescriptor.mode = modeSetMask // Initially nothing is set\n\tif objectDescriptor.hasProperty(\"enumerable\") {\n\t\tif objectDescriptor.get(\"enumerable\").bool() {\n\t\t\tdescriptor.enumerateOn()\n\t\t} else {\n\t\t\tdescriptor.enumerateOff()\n\t\t}\n\t}\n\n\tif objectDescriptor.hasProperty(\"configurable\") {\n\t\tif objectDescriptor.get(\"configurable\").bool() {\n\t\t\tdescriptor.configureOn()\n\t\t} else {\n\t\t\tdescriptor.configureOff()\n\t\t}\n\t}\n\n\tif objectDescriptor.hasProperty(\"writable\") {\n\t\tif objectDescriptor.get(\"writable\").bool() {\n\t\t\tdescriptor.writeOn()\n\t\t} else {\n\t\t\tdescriptor.writeOff()\n\t\t}\n\t}\n\n\tvar getter, setter *object\n\tgetterSetter := false\n\n\tif objectDescriptor.hasProperty(\"get\") {\n\t\tval := objectDescriptor.get(\"get\")\n\t\tif val.IsDefined() {\n\t\t\tif !val.isCallable() {\n\t\t\t\tpanic(rt.panicTypeError(\"toPropertyDescriptor get not callable\"))\n\t\t\t}\n\t\t\tgetter = val.object()\n\t\t\tgetterSetter = true\n\t\t} else {\n\t\t\tgetter = &nilGetSetObject\n\t\t\tgetterSetter = true\n\t\t}\n\t}\n\n\tif objectDescriptor.hasProperty(\"set\") {\n\t\tval := objectDescriptor.get(\"set\")\n\t\tif val.IsDefined() {\n\t\t\tif !val.isCallable() {\n\t\t\t\tpanic(rt.panicTypeError(\"toPropertyDescriptor set not callable\"))\n\t\t\t}\n\t\t\tsetter = val.object()\n\t\t\tgetterSetter = true\n\t\t} else {\n\t\t\tsetter = &nilGetSetObject\n\t\t\tgetterSetter = true\n\t\t}\n\t}\n\n\tif getterSetter {\n\t\tif descriptor.writeSet() {\n\t\t\tpanic(rt.panicTypeError(\"toPropertyDescriptor descriptor writeSet\"))\n\t\t}\n\t\tdescriptor.value = propertyGetSet{getter, setter}\n\t}\n\n\tif objectDescriptor.hasProperty(\"value\") {\n\t\tif getterSetter {\n\t\t\tpanic(rt.panicTypeError(\"toPropertyDescriptor value getterSetter\"))\n\t\t}\n\t\tdescriptor.value = objectDescriptor.get(\"value\")\n\t}\n\n\treturn descriptor\n}\n\nfunc (rt *runtime) fromPropertyDescriptor(descriptor property) *object {\n\tobj := rt.newObject()\n\tif descriptor.isDataDescriptor() {\n\t\tobj.defineProperty(\"value\", descriptor.value.(Value), 0o111, false)\n\t\tobj.defineProperty(\"writable\", boolValue(descriptor.writable()), 0o111, false)\n\t} else if descriptor.isAccessorDescriptor() {\n\t\tgetSet := descriptor.value.(propertyGetSet)\n\t\tget := Value{}\n\t\tif getSet[0] != nil {\n\t\t\tget = objectValue(getSet[0])\n\t\t}\n\t\tset := Value{}\n\t\tif getSet[1] != nil {\n\t\t\tset = objectValue(getSet[1])\n\t\t}\n\t\tobj.defineProperty(\"get\", get, 0o111, false)\n\t\tobj.defineProperty(\"set\", set, 0o111, false)\n\t}\n\tobj.defineProperty(\"enumerable\", boolValue(descriptor.enumerable()), 0o111, false)\n\tobj.defineProperty(\"configurable\", boolValue(descriptor.configurable()), 0o111, false)\n\treturn obj\n}\n"
  },
  {
    "path": "reflect_test.go",
    "content": "package otto\n\nimport (\n\t\"bytes\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"math\"\n\t\"reflect\"\n\t\"strings\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\ntype abcStruct struct {\n\tJkl interface{}\n\tPqr map[string]int8\n\tGhi string\n\tMno _mnoStruct\n\tDef int\n\tAbc bool\n}\n\nfunc (abc abcStruct) String() string {\n\treturn abc.Ghi\n}\n\nfunc (abc *abcStruct) FuncPointer() string {\n\treturn \"abc\"\n}\n\nfunc (abc abcStruct) Func() {\n}\n\nfunc (abc abcStruct) FuncReturn1() string {\n\treturn \"abc\"\n}\n\nfunc (abc abcStruct) FuncReturn2() (string, error) {\n\treturn \"def\", nil\n}\n\nfunc (abc abcStruct) Func1Return1(a string) string {\n\treturn a\n}\n\nfunc (abc abcStruct) Func2Return1(x, y string) string {\n\treturn x + y\n}\n\nfunc (abc abcStruct) FuncEllipsis(xyz ...string) int {\n\treturn len(xyz)\n}\n\nfunc (abc abcStruct) FuncReturnStruct() _mnoStruct {\n\treturn _mnoStruct{}\n}\n\nfunc (abc abcStruct) Func1Int(i int) int {\n\treturn i + 1\n}\n\nfunc (abc abcStruct) Func1Int8(i int8) int8 {\n\treturn i + 1\n}\n\nfunc (abc abcStruct) Func1Int16(i int16) int16 {\n\treturn i + 1\n}\n\nfunc (abc abcStruct) Func1Int32(i int32) int32 {\n\treturn i + 1\n}\n\nfunc (abc abcStruct) Func1Int64(i int64) int64 {\n\treturn i + 1\n}\n\nfunc (abc abcStruct) Func1Uint(i uint) uint {\n\treturn i + 1\n}\n\nfunc (abc abcStruct) Func1Uint8(i uint8) uint8 {\n\treturn i + 1\n}\n\nfunc (abc abcStruct) Func1Uint16(i uint16) uint16 {\n\treturn i + 1\n}\n\nfunc (abc abcStruct) Func1Uint32(i uint32) uint32 {\n\treturn i + 1\n}\n\nfunc (abc abcStruct) Func1Uint64(i uint64) uint64 {\n\treturn i + 1\n}\n\nfunc (abc abcStruct) Func2Int(i, j int) int {\n\treturn i + j\n}\n\nfunc (abc abcStruct) Func2StringInt(s string, i int) string {\n\treturn fmt.Sprintf(\"%v:%v\", s, i)\n}\n\nfunc (abc abcStruct) Func1IntVariadic(a ...int) int {\n\tt := 0\n\tfor _, i := range a {\n\t\tt += i\n\t}\n\treturn t\n}\n\nfunc (abc abcStruct) Func2IntVariadic(s string, a ...int) string {\n\tt := 0\n\tfor _, i := range a {\n\t\tt += i\n\t}\n\treturn fmt.Sprintf(\"%v:%v\", s, t)\n}\n\nfunc (abc abcStruct) Func2IntArrayVariadic(s string, a ...[]int) string {\n\tt := 0\n\tfor _, i := range a {\n\t\tfor _, j := range i {\n\t\t\tt += j\n\t\t}\n\t}\n\treturn fmt.Sprintf(\"%v:%v\", s, t)\n}\n\ntype _mnoStruct struct {\n\tGhi string\n}\n\nfunc (mno _mnoStruct) Func() string {\n\treturn \"mno\"\n}\n\nfunc TestReflect(t *testing.T) {\n\ttt(t, func() {\n\t\t// Testing dbgf\n\t\t// These should panic\n\t\tstr := \"test\"\n\t\trequire.Panics(t, func() {\n\t\t\t_, err := toValue(\"Xyzzy\").toReflectValue(reflect.ValueOf(&str).Type())\n\t\t\trequire.NoError(t, err)\n\t\t})\n\t\trequire.Panics(t, func() {\n\t\t\t_, err := stringToReflectValue(\"Xyzzy\", reflect.Ptr)\n\t\t\trequire.NoError(t, err)\n\t\t})\n\t})\n}\n\nfunc Test_reflectStruct(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, vm := test()\n\n\t\t// _abcStruct\n\t\t{\n\t\t\tabc := &abcStruct{}\n\t\t\tvm.Set(\"abc\", abc)\n\n\t\t\ttest(`\n                [ abc.Abc, abc.Ghi ];\n            `, \"false,\")\n\n\t\t\tabc.Abc = true\n\t\t\tabc.Ghi = \"Nothing happens.\"\n\n\t\t\ttest(`\n                [ abc.Abc, abc.Ghi ];\n            `, \"true,Nothing happens.\")\n\n\t\t\t*abc = abcStruct{}\n\n\t\t\ttest(`\n                [ abc.Abc, abc.Ghi ];\n            `, \"false,\")\n\n\t\t\tabc.Abc = true\n\t\t\tabc.Ghi = \"Xyzzy\"\n\t\t\tvm.Set(\"abc\", abc)\n\n\t\t\ttest(`\n                [ abc.Abc, abc.Ghi ];\n            `, \"true,Xyzzy\")\n\n\t\t\tis(abc.Abc, true)\n\t\t\ttest(`\n                abc.Abc = false;\n                abc.Def = 451;\n                abc.Ghi = \"Nothing happens.\";\n                abc.abc = \"Something happens.\";\n                [ abc.Def, abc.abc ];\n            `, \"451,Something happens.\")\n\t\t\tis(abc.Abc, false)\n\t\t\tis(abc.Def, 451)\n\t\t\tis(abc.Ghi, \"Nothing happens.\")\n\n\t\t\ttest(`\n                delete abc.Def;\n                delete abc.abc;\n                [ abc.Def, abc.abc ];\n            `, \"451,\")\n\t\t\tis(abc.Def, 451)\n\n\t\t\ttest(`\n                abc.FuncPointer();\n            `, \"abc\")\n\n\t\t\ttest(`\n                abc.Func();\n            `, \"undefined\")\n\n\t\t\ttest(`\n                abc.FuncReturn1();\n            `, \"abc\")\n\n\t\t\ttest(`\n                abc.Func1Return1(\"abc\");\n            `, \"abc\")\n\n\t\t\ttest(`\n                abc.Func2Return1(\"abc\", \"def\");\n            `, \"abcdef\")\n\n\t\t\ttest(`\n                abc.FuncEllipsis(\"abc\", \"def\", \"ghi\");\n            `, 3)\n\n\t\t\ttest(`\n                ret = abc.FuncReturn2();\n                if (ret && ret.length && ret.length == 2 && ret[0] == \"def\" && ret[1] === undefined) {\n                        true;\n                } else {\n                       false;\n                }\n            `, true)\n\n\t\t\ttest(`\n                abc.FuncReturnStruct();\n            `, \"[object Object]\")\n\n\t\t\ttest(`\n                abc.FuncReturnStruct().Func();\n            `, \"mno\")\n\n\t\t\ttest(`\n                abc.Func1Int(1);\n            `, 2)\n\n\t\t\ttest(`\n                abc.Func1Int(0x01 & 0x01);\n            `, 2)\n\n\t\t\ttest(`raise:\n                abc.Func1Int(1.1);\n            `, \"RangeError: converting float64 to int would cause loss of precision\")\n\n\t\t\ttest(`\n\t\tvar v = 1;\n                abc.Func1Int(v + 1);\n            `, 3)\n\n\t\t\ttest(`\n                abc.Func2Int(1, 2);\n            `, 3)\n\n\t\t\ttest(`\n                abc.Func1Int8(1);\n            `, 2)\n\n\t\t\ttest(`\n                abc.Func1Int16(1);\n            `, 2)\n\n\t\t\ttest(`\n                abc.Func1Int32(1);\n            `, 2)\n\n\t\t\ttest(`\n                abc.Func1Int64(1);\n            `, 2)\n\n\t\t\ttest(`\n                abc.Func1Uint(1);\n            `, 2)\n\n\t\t\ttest(`\n                abc.Func1Uint8(1);\n            `, 2)\n\n\t\t\ttest(`\n                abc.Func1Uint16(1);\n            `, 2)\n\n\t\t\ttest(`\n                abc.Func1Uint32(1);\n            `, 2)\n\n\t\t\ttest(`\n                abc.Func1Uint64(1);\n            `, 2)\n\n\t\t\ttest(`\n                abc.Func2StringInt(\"test\", 1);\n            `, \"test:1\")\n\n\t\t\ttest(`\n                abc.Func1IntVariadic(1, 2);\n            `, 3)\n\n\t\t\ttest(`\n                abc.Func2IntVariadic(\"test\", 1, 2);\n            `, \"test:3\")\n\n\t\t\ttest(`\n                abc.Func2IntVariadic(\"test\", [1, 2]);\n            `, \"test:3\")\n\n\t\t\ttest(`\n                abc.Func2IntArrayVariadic(\"test\", [1, 2]);\n            `, \"test:3\")\n\n\t\t\ttest(`\n                abc.Func2IntArrayVariadic(\"test\", [1, 2], [3, 4]);\n            `, \"test:10\")\n\n\t\t\ttest(`\n                abc.Func2IntArrayVariadic(\"test\", [[1, 2], [3, 4]]);\n            `, \"test:10\")\n\t\t}\n\t})\n}\n\nfunc Test_reflectMap(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, vm := test()\n\n\t\t// map[string]string\n\t\t{\n\t\t\tabc := map[string]string{\n\t\t\t\t\"Xyzzy\": \"Nothing happens.\",\n\t\t\t\t\"def\":   \"1\",\n\t\t\t}\n\t\t\tvm.Set(\"abc\", abc)\n\n\t\t\ttest(`\n                abc.xyz = \"pqr\";\n                [ abc.Xyzzy, abc.def, abc.ghi ];\n            `, \"Nothing happens.,1,\")\n\n\t\t\tis(abc[\"xyz\"], \"pqr\")\n\t\t}\n\n\t\t// map[string]float64\n\t\t{\n\t\t\tabc := map[string]float64{\n\t\t\t\t\"Xyzzy\": math.Pi,\n\t\t\t\t\"def\":   1,\n\t\t\t}\n\t\t\tvm.Set(\"abc\", abc)\n\n\t\t\ttest(`\n                abc.xyz = \"pqr\";\n                abc.jkl = 10;\n                [ abc.Xyzzy, abc.def, abc.ghi ];\n            `, \"3.141592653589793,1,\")\n\n\t\t\tis(abc[\"xyz\"], math.NaN())\n\t\t\tis(abc[\"jkl\"], float64(10))\n\t\t}\n\n\t\t// map[string]int32\n\t\t{\n\t\t\tabc := map[string]int32{\n\t\t\t\t\"Xyzzy\": 3,\n\t\t\t\t\"def\":   1,\n\t\t\t}\n\t\t\tvm.Set(\"abc\", abc)\n\n\t\t\ttest(`\n                abc.xyz = \"pqr\";\n                abc.jkl = 10;\n                [ abc.Xyzzy, abc.def, abc.ghi ];\n            `, \"3,1,\")\n\n\t\t\tis(abc[\"xyz\"], 0)\n\t\t\tis(abc[\"jkl\"], int32(10))\n\n\t\t\ttest(`\n                delete abc[\"Xyzzy\"];\n            `)\n\n\t\t\t_, exists := abc[\"Xyzzy\"]\n\t\t\tis(exists, false)\n\t\t\tis(abc[\"Xyzzy\"], 0)\n\t\t}\n\n\t\t// map[int32]string\n\t\t{\n\t\t\tabc := map[int32]string{\n\t\t\t\t0: \"abc\",\n\t\t\t\t1: \"def\",\n\t\t\t}\n\t\t\tvm.Set(\"abc\", abc)\n\n\t\t\ttest(`\n                abc[2] = \"pqr\";\n                //abc.jkl = 10;\n                abc[3] = 10;\n                [ abc[0], abc[1], abc[2], abc[3] ]\n            `, \"abc,def,pqr,10\")\n\n\t\t\tis(abc[2], \"pqr\")\n\t\t\tis(abc[3], \"10\")\n\n\t\t\ttest(`\n                delete abc[2];\n            `)\n\n\t\t\t_, exists := abc[2]\n\t\t\tis(exists, false)\n\t\t}\n\t})\n}\n\nfunc Test_reflectMapIterateKeys(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, vm := test()\n\n\t\t// map[string]interface{}\n\t\t{\n\t\t\tabc := map[string]interface{}{\n\t\t\t\t\"Xyzzy\": \"Nothing happens.\",\n\t\t\t\t\"def\":   1,\n\t\t\t}\n\t\t\tvm.Set(\"abc\", abc)\n\t\t\ttest(`\n                var keys = [];\n                for (var key in abc) {\n                  keys.push(key);\n                }\n                keys.sort();\n                keys;\n            `, \"Xyzzy,def\")\n\t\t}\n\n\t\t// map[uint]interface{}\n\t\t{\n\t\t\tabc := map[uint]interface{}{\n\t\t\t\t456: \"Nothing happens.\",\n\t\t\t\t123: 1,\n\t\t\t}\n\t\t\tvm.Set(\"abc\", abc)\n\t\t\ttest(`\n                var keys = [];\n                for (var key in abc) {\n                  keys.push(key);\n                }\n                keys.sort();\n                keys;\n            `, \"123,456\")\n\t\t}\n\n\t\t// map[byte]interface{}\n\t\t{\n\t\t\tabc := map[byte]interface{}{\n\t\t\t\t10: \"Nothing happens.\",\n\t\t\t\t20: 1,\n\t\t\t}\n\t\t\tvm.Set(\"abc\", abc)\n\t\t\ttest(`\n                for (var key in abc) {\n                  abc[key] = \"123\";\n                }\n            `)\n\t\t\tis(abc[10], \"123\")\n\t\t\tis(abc[20], \"123\")\n\t\t}\n\t})\n}\n\nfunc Test_reflectSlice(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, vm := test()\n\n\t\t// []bool\n\t\t{\n\t\t\tabc := []bool{\n\t\t\t\tfalse,\n\t\t\t\ttrue,\n\t\t\t\ttrue,\n\t\t\t\tfalse,\n\t\t\t}\n\t\t\tvm.Set(\"abc\", abc)\n\n\t\t\ttest(`\n                abc;\n            `, \"false,true,true,false\")\n\n\t\t\ttest(`\n                abc[0] = true;\n                abc[abc.length-1] = true;\n                delete abc[2];\n                abc;\n            `, \"true,true,false,true\")\n\n\t\t\tis(abc, []bool{true, true, false, true})\n\t\t\tis(abc[len(abc)-1], true)\n\t\t}\n\n\t\t// []int32\n\t\t{\n\t\t\tabc := make([]int32, 4)\n\t\t\tvm.Set(\"abc\", abc)\n\n\t\t\ttest(`\n                abc;\n            `, \"0,0,0,0\")\n\n\t\t\ttest(`raise:\n                abc[0] = \"42\";\n                abc[1] = 4.2;\n                abc[2] = 3.14;\n                abc;\n            `, \"RangeError: 4.2 to reflect.Kind: int32\")\n\n\t\t\tis(abc, []int32{42, 0, 0, 0})\n\n\t\t\ttest(`\n                delete abc[1];\n                delete abc[2];\n            `)\n\t\t\tis(abc[1], 0)\n\t\t\tis(abc[2], 0)\n\t\t}\n\t})\n}\n\nfunc Test_reflectArray(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, vm := test()\n\n\t\t// []bool\n\t\t{\n\t\t\tabc := [4]bool{\n\t\t\t\tfalse,\n\t\t\t\ttrue,\n\t\t\t\ttrue,\n\t\t\t\tfalse,\n\t\t\t}\n\t\t\tvm.Set(\"abc\", abc)\n\n\t\t\ttest(`\n                abc;\n            `, \"false,true,true,false\")\n\t\t\t// Unaddressable array\n\n\t\t\ttest(`\n                abc[0] = true;\n                abc[abc.length-1] = true;\n                abc;\n            `, \"false,true,true,false\")\n\t\t\t// Again, unaddressable array\n\n\t\t\tis(abc, [4]bool{false, true, true, false})\n\t\t\tis(abc[len(abc)-1], false)\n\t\t\t// ...\n\t\t}\n\t\t// []int32\n\t\t{\n\t\t\tabc := make([]int32, 4)\n\t\t\tvm.Set(\"abc\", abc)\n\n\t\t\ttest(`\n                abc;\n            `, \"0,0,0,0\")\n\n\t\t\ttest(`raise:\n                abc[0] = \"42\";\n                abc[1] = 4.2;\n                abc[2] = 3.14;\n                abc;\n            `, \"RangeError: 4.2 to reflect.Kind: int32\")\n\n\t\t\tis(abc, []int32{42, 0, 0, 0})\n\t\t}\n\n\t\t// []bool\n\t\t{\n\t\t\tabc := [4]bool{\n\t\t\t\tfalse,\n\t\t\t\ttrue,\n\t\t\t\ttrue,\n\t\t\t\tfalse,\n\t\t\t}\n\t\t\tvm.Set(\"abc\", &abc)\n\n\t\t\ttest(`\n                abc;\n            `, \"false,true,true,false\")\n\n\t\t\ttest(`\n                abc[0] = true;\n                abc[abc.length-1] = true;\n                delete abc[2];\n                abc;\n            `, \"true,true,false,true\")\n\n\t\t\tis(abc, [4]bool{true, true, false, true})\n\t\t\tis(abc[len(abc)-1], true)\n\t\t}\n\n\t\t// no common type\n\t\t{\n\t\t\ttest(`\n                 abc = [1, 2.2, \"str\"];\n                 abc;\n             `, \"1,2.2,str\")\n\t\t\tval, err := vm.Get(\"abc\")\n\t\t\tis(err, nil)\n\t\t\tabc, err := val.Export()\n\t\t\tis(err, nil)\n\t\t\tis(abc, []interface{}{int64(1), 2.2, \"str\"})\n\t\t}\n\n\t\t// common type int\n\t\t{\n\t\t\ttest(`\n                 abc = [1, 2, 3];\n                 abc;\n             `, \"1,2,3\")\n\t\t\tval, err := vm.Get(\"abc\")\n\t\t\tis(err, nil)\n\t\t\tabc, err := val.Export()\n\t\t\tis(err, nil)\n\t\t\tis(abc, []int64{1, 2, 3})\n\t\t}\n\n\t\t// common type string\n\t\t{\n\t\t\ttest(`\n                 abc = [\"str1\", \"str2\", \"str3\"];\n                 abc;\n             `, \"str1,str2,str3\")\n\n\t\t\tval, err := vm.Get(\"abc\")\n\t\t\tis(err, nil)\n\t\t\tabc, err := val.Export()\n\t\t\tis(err, nil)\n\t\t\tis(abc, []string{\"str1\", \"str2\", \"str3\"})\n\t\t}\n\n\t\t// issue #269\n\t\t{\n\t\t\tcalled := false\n\t\t\tvm.Set(\"blah\", func(c FunctionCall) Value {\n\t\t\t\tv, err := c.Argument(0).Export()\n\t\t\t\tis(err, nil)\n\t\t\t\tis(v, []int64{3})\n\t\t\t\tcalled = true\n\t\t\t\treturn UndefinedValue()\n\t\t\t})\n\t\t\tis(called, false)\n\t\t\ttest(`var x = 3; blah([x])`)\n\t\t\tis(called, true)\n\t\t}\n\t})\n}\n\nfunc Test_reflectArray_concat(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, vm := test()\n\n\t\tvm.Set(\"ghi\", []string{\"jkl\", \"mno\"})\n\t\tvm.Set(\"pqr\", []interface{}{\"jkl\", 42, 3.14159, true})\n\t\ttest(`\n            var def = {\n                \"abc\": [\"abc\"],\n                \"xyz\": [\"xyz\"]\n            };\n            xyz = pqr.concat(ghi, def.abc, def, def.xyz);\n            [ xyz, xyz.length ];\n        `, \"jkl,42,3.14159,true,jkl,mno,abc,[object Object],xyz,9\")\n\t})\n}\n\nfunc Test_reflectMapInterface(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, vm := test()\n\n\t\t{\n\t\t\tabc := map[string]interface{}{\n\t\t\t\t\"Xyzzy\": \"Nothing happens.\",\n\t\t\t\t\"def\":   \"1\",\n\t\t\t\t\"jkl\":   \"jkl\",\n\t\t\t}\n\t\t\tvm.Set(\"abc\", abc)\n\t\t\tvm.Set(\"mno\", &abcStruct{})\n\n\t\t\ttest(`\n                abc.xyz = \"pqr\";\n                abc.ghi = {};\n                abc.jkl = 3.14159;\n                abc.mno = mno;\n                mno.Abc = true;\n                mno.Ghi = \"Something happens.\";\n                [ abc.Xyzzy, abc.def, abc.ghi, abc.mno ];\n            `, \"Nothing happens.,1,[object Object],[object Object]\")\n\n\t\t\tis(abc[\"xyz\"], \"pqr\")\n\t\t\tis(abc[\"ghi\"], map[string]interface{}{})\n\t\t\tis(abc[\"jkl\"], float64(3.14159))\n\t\t\tmno, valid := abc[\"mno\"].(*abcStruct)\n\t\t\tis(valid, true)\n\t\t\tis(mno.Abc, true)\n\t\t\tis(mno.Ghi, \"Something happens.\")\n\t\t}\n\t})\n}\n\nfunc TestPassthrough(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, vm := test()\n\n\t\t{\n\t\t\tabc := &abcStruct{\n\t\t\t\tMno: _mnoStruct{\n\t\t\t\t\tGhi: \"<Mno.Ghi>\",\n\t\t\t\t},\n\t\t\t}\n\t\t\tvm.Set(\"abc\", abc)\n\n\t\t\ttest(`\n                abc.Mno.Ghi;\n            `, \"<Mno.Ghi>\")\n\n\t\t\tvm.Set(\"pqr\", map[string]int8{\n\t\t\t\t\"xyzzy\":            0,\n\t\t\t\t\"Nothing happens.\": 1,\n\t\t\t})\n\n\t\t\ttest(`\n                abc.Ghi = \"abc\";\n                abc.Pqr = pqr;\n                abc.Pqr[\"Nothing happens.\"];\n            `, 1)\n\n\t\t\tmno := _mnoStruct{\n\t\t\t\tGhi: \"<mno.Ghi>\",\n\t\t\t}\n\t\t\tvm.Set(\"mno\", mno)\n\n\t\t\ttest(`\n                abc.Mno = mno;\n                abc.Mno.Ghi;\n            `, \"<mno.Ghi>\")\n\t\t}\n\t})\n}\n\ntype TestDynamicFunctionReturningInterfaceMyStruct1 struct{} //nolint:errname\n\nfunc (m *TestDynamicFunctionReturningInterfaceMyStruct1) Error() string { return \"MyStruct1\" }\n\ntype TestDynamicFunctionReturningInterfaceMyStruct2 struct{} //nolint:errname\n\nfunc (m *TestDynamicFunctionReturningInterfaceMyStruct2) Error() string { return \"MyStruct2\" }\n\nfunc TestDynamicFunctionReturningInterface(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, vm := test()\n\n\t\tvar l []func() error\n\n\t\tvm.Set(\"r\", func(cb func() error) { l = append(l, cb) })\n\t\tvm.Set(\"e1\", func() error { return &TestDynamicFunctionReturningInterfaceMyStruct1{} })\n\t\tvm.Set(\"e2\", func() error { return &TestDynamicFunctionReturningInterfaceMyStruct2{} })\n\t\tvm.Set(\"e3\", func() error { return nil })\n\n\t\ttest(\"r(function() { return e1(); })\", UndefinedValue())\n\t\ttest(\"r(function() { return e2(); })\", UndefinedValue())\n\t\ttest(\"r(function() { return e3(); })\", UndefinedValue())\n\t\ttest(\"r(function() { return null; })\", UndefinedValue())\n\n\t\tif l[0]() == nil {\n\t\t\tt.Fail()\n\t\t}\n\t\tif l[1]() == nil {\n\t\t\tt.Fail()\n\t\t}\n\t\tif l[2]() != nil {\n\t\t\tt.Fail()\n\t\t}\n\t\tif l[3]() != nil {\n\t\t\tt.Fail()\n\t\t}\n\t})\n}\n\nfunc TestStructCallParameterConversion(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, vm := test()\n\n\t\ttype T struct {\n\t\t\tStringValue  string `json:\"s\"`\n\t\t\tBooleanValue bool   `json:\"b\"`\n\t\t\tIntegerValue int    `json:\"i\"`\n\t\t}\n\n\t\tvar x T\n\n\t\tvm.Set(\"f\", func(t T) bool { return t == x })\n\n\t\t// test set properties\n\n\t\tx = T{\"A\", true, 1}\n\t\ttest(\"f({s: 'A', b: true, i: 1})\", true)\n\n\t\t// test zero-value properties\n\n\t\tx = T{\"\", false, 0}\n\t\ttest(\"f({s: '', b: false, i: 0})\", true)\n\n\t\t// test missing properties\n\n\t\tx = T{\"\", true, 1}\n\t\ttest(\"f({b: true, i: 1})\", true)\n\n\t\tx = T{\"A\", false, 1}\n\t\ttest(\"f({s: 'A', i: 1})\", true)\n\n\t\tx = T{\"A\", true, 0}\n\t\ttest(\"f({s: 'A', b: true})\", true)\n\n\t\tx = T{\"\", false, 0}\n\t\ttest(\"f({})\", true)\n\n\t\t// make sure it fails with extra properties\n\n\t\tx = T{\"\", false, 0}\n\t\tif _, err := vm.Run(\"f({x: true})\"); err == nil {\n\t\t\tt.Fail()\n\t\t}\n\t})\n}\n\ntype TestTextUnmarshallerCallParameterConversionMyStruct struct{}\n\nfunc (m *TestTextUnmarshallerCallParameterConversionMyStruct) UnmarshalText(b []byte) error {\n\tif string(b) == \"good\" {\n\t\treturn nil\n\t}\n\n\treturn fmt.Errorf(\"NOT_GOOD: %s\", string(b))\n}\n\nfunc TestTextUnmarshallerCallParameterConversion(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, vm := test()\n\n\t\tvm.Set(\"f\", func(t TestTextUnmarshallerCallParameterConversionMyStruct) bool { return true })\n\n\t\t// success\n\t\ttest(\"f('good')\", true)\n\n\t\t// explicit failure, should pass error message up\n\t\tif _, err := vm.Run(\"f('bad')\"); err == nil || !strings.Contains(err.Error(), \"NOT_GOOD: bad\") {\n\t\t\tt.Fail()\n\t\t}\n\n\t\t// wrong input\n\t\tif _, err := vm.Run(\"f(null)\"); err == nil {\n\t\t\tt.Fail()\n\t\t}\n\n\t\t// no input\n\t\tif _, err := vm.Run(\"f()\"); err == nil {\n\t\t\tt.Fail()\n\t\t}\n\t})\n}\n\nfunc TestJSONRawMessageCallParameterConversion(t *testing.T) {\n\tfor _, e := range []struct {\n\t\tc string\n\t\tr string\n\t\te bool\n\t}{\n\t\t{\"f({a:1})\", `{\"a\":1}`, false},\n\t\t{\"f(null)\", `null`, false},\n\t\t{\"f(1)\", `1`, false},\n\t\t{\"f('x')\", `\"x\"`, false},\n\t\t{\"f([1,2,3])\", `[1,2,3]`, false},\n\t\t{\"f(function(){})\", `{}`, false},\n\t\t{\"f()\", `[1,2,3]`, true},\n\t} {\n\t\tt.Run(e.c, func(t *testing.T) {\n\t\t\tvm := New()\n\t\t\terr := vm.Set(\"f\", func(m json.RawMessage) json.RawMessage { return m })\n\t\t\trequire.NoError(t, err)\n\t\t\tr, err := vm.Run(e.c)\n\t\t\tif err != nil {\n\t\t\t\tif !e.e {\n\t\t\t\t\tt.Error(\"err should be nil\")\n\t\t\t\t\tt.Fail()\n\t\t\t\t}\n\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif e.e {\n\t\t\t\tt.Error(\"err should not be nil\")\n\t\t\t\tt.Fail()\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tv, err := r.Export()\n\t\t\tif err != nil {\n\t\t\t\tt.Error(err)\n\t\t\t\tt.Fail()\n\t\t\t}\n\n\t\t\tm, ok := v.(json.RawMessage)\n\t\t\tif !ok {\n\t\t\t\tt.Error(\"result should be json.RawMessage\")\n\t\t\t\tt.Fail()\n\t\t\t}\n\n\t\t\tif !bytes.Equal(m, json.RawMessage(e.r)) {\n\t\t\t\tt.Errorf(\"output is wrong\\nexpected: %s\\nactual:   %s\\n\", e.r, m)\n\t\t\t\tt.Fail()\n\t\t\t}\n\t\t})\n\t}\n}\n"
  },
  {
    "path": "regexp_test.go",
    "content": "package otto\n\nimport (\n\t\"fmt\"\n\t\"testing\"\n)\n\nfunc TestRegExp(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            [\n                /abc/.toString(),\n                /abc/gim.toString(),\n                \"\"+/abc/gi.toString(),\n                new RegExp(\"1(\\\\d+)\").toString(),\n            ];\n        `, \"/abc/,/abc/gim,/abc/gi,/1(\\\\d+)/\")\n\n\t\ttest(`\n            [\n                new RegExp(\"abc\").exec(\"123abc456\"),\n                null === new RegExp(\"xyzzy\").exec(\"123abc456\"),\n                new RegExp(\"1(\\\\d+)\").exec(\"123abc456\"),\n                new RegExp(\"xyzzy\").test(\"123abc456\"),\n                new RegExp(\"1(\\\\d+)\").test(\"123abc456\"),\n                new RegExp(\"abc\").exec(\"123abc456\"),\n            ];\n        `, \"abc,true,123,23,false,true,abc\")\n\n\t\ttest(`new RegExp(\"abc\").toString()`, \"/abc/\")\n\t\ttest(`new RegExp(\"abc\", \"g\").toString()`, \"/abc/g\")\n\t\ttest(`new RegExp(\"abc\", \"mig\").toString()`, \"/abc/gim\")\n\n\t\tresult := test(`/(a)?/.exec('b')`, \",\")\n\t\tis(result.object().get(\"0\"), \"\")\n\t\tis(result.object().get(\"1\"), \"undefined\")\n\t\tis(result.object().get(propertyLength), 2)\n\n\t\tresult = test(`/(a)?(b)?/.exec('b')`, \"b,,b\")\n\t\tis(result.object().get(\"0\"), \"b\")\n\t\tis(result.object().get(\"1\"), \"undefined\")\n\t\tis(result.object().get(\"2\"), \"b\")\n\t\tis(result.object().get(propertyLength), 3)\n\n\t\ttest(`/\\u0041/.source`, \"\\\\u0041\")\n\t\ttest(`/\\a/.source`, \"\\\\a\")\n\t\ttest(`/\\;/.source`, \"\\\\;\")\n\n\t\ttest(`/a\\a/.source`, \"a\\\\a\")\n\t\ttest(`/,\\;/.source`, \",\\\\;\")\n\t\ttest(`/ \\ /.source`, \" \\\\ \")\n\n\t\t// Start sanity check...\n\t\ttest(\"eval(\\\"/abc/\\\").source\", \"abc\")\n\t\ttest(\"eval(\\\"/\\u0023/\\\").source\", \"#\")\n\t\ttest(\"eval(\\\"/\\u0058/\\\").source\", \"X\")\n\t\ttest(\"eval(\\\"/\\\\\\u0023/\\\").source == \\\"\\\\\\u0023\\\"\", true)\n\t\ttest(\"'0x' + '0058'\", \"0x0058\")\n\t\ttest(\"'\\\\\\\\' + '0x' + '0058'\", \"\\\\0x0058\")\n\t\t// ...stop sanity check\n\n\t\ttest(`abc = '\\\\' + String.fromCharCode('0x' + '0058'); eval('/' + abc + '/').source`, \"\\\\X\")\n\t\ttest(`abc = '\\\\' + String.fromCharCode('0x0058'); eval('/' + abc + '/').source == \"\\\\\\u0058\"`, true)\n\t\ttest(`abc = '\\\\' + String.fromCharCode('0x0023'); eval('/' + abc + '/').source == \"\\\\\\u0023\"`, true)\n\t\ttest(`abc = '\\\\' + String.fromCharCode('0x0078'); eval('/' + abc + '/').source == \"\\\\\\u0078\"`, true)\n\n\t\ttest(`\n            var abc = Object.getOwnPropertyDescriptor(RegExp, \"prototype\");\n            [   [ typeof RegExp.prototype ],\n                [ abc.writable, abc.enumerable, abc.configurable ] ];\n        `, \"object,false,false,false\")\n\t})\n}\n\nfunc TestRegExp_global(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            var abc = /(?:ab|cd)\\d?/g;\n            var found = [];\n            do {\n                match = abc.exec(\"ab  cd2  ab34  cd\");\n                if (match !== null) {\n                    found.push(match[0]);\n                } else {\n                    break;\n                }\n            } while (true);\n            found;\n        `, \"ab,cd2,ab3,cd\")\n\t})\n}\n\nfunc TestRegExp_exec(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            abc = /./g;\n            def = '123456';\n            ghi = 0;\n            while (ghi < 100 && abc.exec(def) !== null) {\n                ghi += 1;\n            }\n            [ ghi, def.length, ghi == def.length ];\n        `, \"6,6,true\")\n\n\t\ttest(`\n            abc = /[abc](\\d)?/g;\n            def = 'a0 b c1 d3';\n            ghi = 0;\n            lastIndex = 0;\n            while (ghi < 100 && abc.exec(def) !== null) {\n                lastIndex = abc.lastIndex;\n                ghi += 1;\n\n            }\n            [ ghi, lastIndex ];\n        `, \"3,7\")\n\n\t\ttest(`\n            abc = /(\\d)?(s)/g;\n            def = 's';\n            ghi = abc.exec(def);\n            [ ghi[1] === undefined, ghi[2] === 's' ];\n        `, \"true,true\")\n\n\t\ttest(`\n            abc = /(\\d)?(s)/g;\n            def = '%s';\n            abc.lastIndex = 1;\n            ghi = abc.exec(def);\n            [ ghi[1] === undefined, ghi[2] === 's' ];\n        `, \"true,true\")\n\n\t\ttest(`\n            var abc = /[abc](\\d)?/.exec(\"a0 b c1 d3\");\n            [ abc.length, abc.input, abc.index, abc ];\n        `, \"2,a0 b c1 d3,0,a0,0\")\n\n\t\ttest(`raise:\n            var exec = RegExp.prototype.exec;\n            exec(\"Xyzzy\");\n        `, \"TypeError: Calling RegExp.exec on a non-RegExp object\")\n\n\t\ttest(`\n            var abc = /\\w{3}\\d?/.exec(\"CE\\uFFFFL\\uFFDDbox127\");\n            [ abc.input.length, abc.length, abc.input, abc.index, abc ];\n        `, \"11,1,CE\\uFFFFL\\uFFDDbox127,5,box1\")\n\n\t\ttest(`\n        var abc = /\\w{3}\\d?/.exec(\"CE😋box127\");\n        [ abc.input.length, abc.length, abc.input, abc.index, abc ];\n    `, \"10,1,CE😋box127,4,box1\")\n\n\t\ttest(`RegExp.prototype.exec.length`, 1)\n\t\ttest(`RegExp.prototype.exec.prototype`, \"undefined\")\n\t})\n}\n\nfunc TestRegExp_test(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`RegExp.prototype.test.length`, 1)\n\t\ttest(`RegExp.prototype.test.prototype`, \"undefined\")\n\t})\n}\n\nfunc TestRegExp_toString(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`RegExp.prototype.toString.length`, 0)\n\t\ttest(`RegExp.prototype.toString.prototype`, \"undefined\")\n\t})\n}\n\nfunc TestRegExp_zaacbbbcac(t *testing.T) {\n\tif true {\n\t\treturn\n\t}\n\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\t// FIXME? TODO /(z)((a+)?(b+)?(c))*/.exec(\"zaacbbbcac\")\n\t\ttest(`\n            var abc = /(z)((a+)?(b+)?(c))*/.exec(\"zaacbbbcac\");\n            [ abc.length, abc.index, abc ];\n        `, \"6,0,zaacbbbcac,z,ac,a,,c\")\n\t})\n}\n\nfunc TestRegExpCopying(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            abc = /xyzzy/i;\n            def = RegExp(abc);\n            abc.indicator = 1;\n            [ abc.indicator, def.indicator ];\n        `, \"1,1\")\n\n\t\ttest(`raise:\n            RegExp(new RegExp(\"\\\\d\"), \"1\");\n        `, \"TypeError: Cannot supply flags when constructing one RegExp from another\")\n\t})\n}\n\nfunc TestRegExp_multiline(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            var abc = /s$/m.exec(\"pairs\\nmakes\\tdouble\");\n            [ abc.length, abc.index, abc ];\n        `, \"1,4,s\")\n\t})\n}\n\nfunc TestRegExp_source(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            [ /xyzzy/i.source, /./i.source ];\n        `, \"xyzzy,.\")\n\n\t\ttest(`\n            var abc = /./i;\n            var def = new RegExp(abc);\n            [ abc.source, def.source, abc.source === def.source ];\n        `, \".,.,true\")\n\n\t\ttest(`\n            var abc = /./i;\n            var def = abc.hasOwnProperty(\"source\");\n            var ghi = abc.source;\n            abc.source = \"xyzzy\";\n            [ def, abc.source ];\n        `, \"true,.\")\n\t})\n}\n\nfunc TestRegExp_newRegExp(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            Math.toString();\n            var abc = new RegExp(Math,eval(\"\\\"g\\\"\"));\n            [ abc, abc.global ];\n        `, \"/[object Math]/g,true\")\n\t})\n}\n\nfunc TestRegExp_flags(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            var abc = /./i;\n            var def = new RegExp(abc);\n            [ abc.multiline == def.multiline, abc.global == def.global, abc.ignoreCase == def.ignoreCase ];\n        `, \"true,true,true\")\n\t})\n}\n\nfunc TestRegExp_controlCharacter(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\tfor code := 0x41; code < 0x5a; code++ {\n\t\t\tval := string(rune(code - 64))\n\t\t\ttest(fmt.Sprintf(`\n                var code = 0x%x;\n                var string = String.fromCharCode(code %% 32);\n                var result = (new RegExp(\"\\\\c\" + String.fromCharCode(code))).exec(string);\n                [ code, string, result ];\n            `, code), fmt.Sprintf(\"%d,%s,%s\", code, val, val))\n\t\t}\n\t})\n}\n\nfunc TestRegExp_notNotEmptyCharacterClass(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            var abc = /[\\s\\S]a/m.exec(\"a\\naba\");\n            [ abc.length, abc.input, abc ];\n        `, \"1,a\\naba,\\na\")\n\t})\n}\n\nfunc TestRegExp_compile(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            var abc = /[\\s\\S]a/;\n            abc.compile('^\\w+');\n        `, \"undefined\")\n\t})\n}\n"
  },
  {
    "path": "registry/registry.go",
    "content": "// Package registry is an experimental package to facilitate altering the otto runtime via import.\n//\n// This interface can change at any time.\npackage registry\n\nvar registry []*Entry = make([]*Entry, 0)\n\n// Entry represents a registry entry.\ntype Entry struct {\n\tsource func() string\n\tactive bool\n}\n\n// newEntry returns a new Entry for source.\nfunc newEntry(source func() string) *Entry {\n\treturn &Entry{\n\t\tactive: true,\n\t\tsource: source,\n\t}\n}\n\n// Enable enables the entry.\nfunc (e *Entry) Enable() {\n\te.active = true\n}\n\n// Disable disables the entry.\nfunc (e *Entry) Disable() {\n\te.active = false\n}\n\n// Source returns the source of the entry.\nfunc (e Entry) Source() string {\n\treturn e.source()\n}\n\n// Apply applies callback to all registry entries.\nfunc Apply(callback func(Entry)) {\n\tfor _, entry := range registry {\n\t\tif !entry.active {\n\t\t\tcontinue\n\t\t}\n\t\tcallback(*entry)\n\t}\n}\n\n// Register registers a new Entry for source.\nfunc Register(source func() string) *Entry {\n\tentry := newEntry(source)\n\tregistry = append(registry, entry)\n\treturn entry\n}\n"
  },
  {
    "path": "repl/autocompleter.go",
    "content": "package repl\n\nimport (\n\t\"regexp\"\n\t\"strings\"\n\n\t\"github.com/robertkrimen/otto\"\n)\n\ntype autoCompleter struct {\n\tvm *otto.Otto\n}\n\nvar lastExpressionRegex = regexp.MustCompile(`[a-zA-Z0-9]([a-zA-Z0-9\\.]*[a-zA-Z0-9])?\\.?$`)\n\nfunc (a *autoCompleter) Do(line []rune, pos int) ([][]rune, int) {\n\tlastExpression := lastExpressionRegex.FindString(string(line))\n\n\tbits := strings.Split(lastExpression, \".\")\n\n\tvar l []string\n\tif first := bits[:len(bits)-1]; len(first) == 0 {\n\t\tc := a.vm.Context()\n\n\t\tl = make([]string, len(c.Symbols))\n\n\t\ti := 0\n\t\tfor k := range c.Symbols {\n\t\t\tl[i] = k\n\t\t\ti++\n\t\t}\n\t} else {\n\t\tr, err := a.vm.Eval(strings.Join(bits[:len(bits)-1], \".\"))\n\t\tif err != nil {\n\t\t\treturn nil, 0\n\t\t}\n\n\t\tif o := r.Object(); o != nil {\n\t\t\tfor _, v := range o.KeysByParent() {\n\t\t\t\tl = append(l, v...) //nolint:makezero\n\t\t\t}\n\t\t}\n\t}\n\n\tlast := bits[len(bits)-1]\n\tvar r [][]rune\n\tfor _, s := range l {\n\t\tif strings.HasPrefix(s, last) {\n\t\t\tr = append(r, []rune(strings.TrimPrefix(s, last)))\n\t\t}\n\t}\n\n\treturn r, len(last)\n}\n"
  },
  {
    "path": "repl/repl.go",
    "content": "// Package repl implements a REPL (read-eval-print loop) for otto.\npackage repl\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"strings\"\n\t\"sync/atomic\"\n\n\t\"github.com/robertkrimen/otto\"\n\t\"gopkg.in/readline.v1\"\n)\n\nvar counter uint32\n\n// DebuggerHandler implements otto's debugger handler signature, providing a\n// simple drop-in debugger implementation.\nfunc DebuggerHandler(vm *otto.Otto) {\n\ti := atomic.AddUint32(&counter, 1)\n\n\t// purposefully ignoring the error here - we can't do anything useful with\n\t// it except panicking, and that'd be pretty rude. it'd be easy enough for a\n\t// consumer to define an equivalent function that _does_ panic if desired.\n\t_ = RunWithPrompt(vm, fmt.Sprintf(\"DEBUGGER[%d]> \", i))\n}\n\n// Run creates a REPL with the default prompt and no prelude.\nfunc Run(vm *otto.Otto) error {\n\treturn RunWithOptions(vm, Options{})\n}\n\n// RunWithPrompt runs a REPL with the given prompt and no prelude.\nfunc RunWithPrompt(vm *otto.Otto, prompt string) error {\n\treturn RunWithOptions(vm, Options{\n\t\tPrompt: prompt,\n\t})\n}\n\n// RunWithPrelude runs a REPL with the default prompt and the given prelude.\nfunc RunWithPrelude(vm *otto.Otto, prelude string) error {\n\treturn RunWithOptions(vm, Options{\n\t\tPrelude: prelude,\n\t})\n}\n\n// RunWithPromptAndPrelude runs a REPL with the given prompt and prelude.\nfunc RunWithPromptAndPrelude(vm *otto.Otto, prompt, prelude string) error {\n\treturn RunWithOptions(vm, Options{\n\t\tPrompt:  prompt,\n\t\tPrelude: prelude,\n\t})\n}\n\n// Options contains parameters for configuring a REPL session.\ntype Options struct {\n\t// Prompt controls what's shown at the beginning of the line. If not\n\t// specified, this defaults to \"> \"\n\tPrompt string\n\t// Prelude is some text that's printed before control is given to the user.\n\t// By default this is empty. If specified, this will be printed with a\n\t// newline following it.\n\tPrelude string\n\t// Autocomplete controls whether this REPL session has autocompletion\n\t// enabled. The way autocomplete is implemented can incur a performance\n\t// penalty, so it's turned off by default.\n\tAutocomplete bool\n}\n\n// RunWithOptions runs a REPL with the given options.\nfunc RunWithOptions(vm *otto.Otto, options Options) error {\n\tprompt := options.Prompt\n\tif prompt == \"\" {\n\t\tprompt = \"> \"\n\t}\n\n\tc := &readline.Config{\n\t\tPrompt: prompt,\n\t}\n\n\tif options.Autocomplete {\n\t\tc.AutoComplete = &autoCompleter{vm}\n\t}\n\n\trl, err := readline.NewEx(c)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tprelude := options.Prelude\n\tif prelude != \"\" {\n\t\tif _, err = io.Copy(rl.Stderr(), strings.NewReader(prelude+\"\\n\")); err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\trl.Refresh()\n\t}\n\n\tvar d []string\n\n\tfor {\n\t\tl, errRL := rl.Readline()\n\t\tif errRL != nil {\n\t\t\tif errors.Is(errRL, readline.ErrInterrupt) {\n\t\t\t\tif d != nil {\n\t\t\t\t\td = nil\n\n\t\t\t\t\trl.SetPrompt(prompt)\n\t\t\t\t\trl.Refresh()\n\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\treturn errRL\n\t\t}\n\n\t\tif l == \"\" {\n\t\t\tcontinue\n\t\t}\n\n\t\td = append(d, l)\n\n\t\ts, errRL := vm.Compile(\"repl\", strings.Join(d, \"\\n\"))\n\t\tif errRL != nil {\n\t\t\trl.SetPrompt(strings.Repeat(\" \", len(prompt)))\n\t\t} else {\n\t\t\trl.SetPrompt(prompt)\n\n\t\t\td = nil\n\n\t\t\tv, errEval := vm.Eval(s)\n\t\t\tif errEval != nil {\n\t\t\t\tvar oerr *otto.Error\n\t\t\t\tif errors.As(errEval, &oerr) {\n\t\t\t\t\tif _, err = io.Copy(rl.Stdout(), strings.NewReader(oerr.String())); err != nil {\n\t\t\t\t\t\treturn fmt.Errorf(\"write out: %w\", err)\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif _, err = io.Copy(rl.Stdout(), strings.NewReader(errEval.Error())); err != nil {\n\t\t\t\t\t\treturn fmt.Errorf(\"write out: %w\", err)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif _, err = rl.Stdout().Write([]byte(v.String() + \"\\n\")); err != nil {\n\t\t\t\t\treturn fmt.Errorf(\"write out: %w\", err)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\trl.Refresh()\n\t}\n\n\treturn rl.Close()\n}\n"
  },
  {
    "path": "result.go",
    "content": "package otto\n\ntype resultKind int\n\nconst (\n\t_ resultKind = iota\n\tresultReturn\n\tresultBreak\n\tresultContinue\n)\n\ntype result struct {\n\tvalue  Value\n\ttarget string\n\tkind   resultKind\n}\n\nfunc newReturnResult(value Value) result {\n\treturn result{kind: resultReturn, value: value, target: \"\"}\n}\n\nfunc newContinueResult(target string) result {\n\treturn result{kind: resultContinue, value: emptyValue, target: target}\n}\n\nfunc newBreakResult(target string) result {\n\treturn result{kind: resultBreak, value: emptyValue, target: target}\n}\n"
  },
  {
    "path": "runtime.go",
    "content": "package otto\n\nimport (\n\t\"encoding\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"fmt\"\n\t\"math\"\n\t\"path\"\n\t\"reflect\"\n\tgoruntime \"runtime\"\n\t\"strconv\"\n\t\"strings\"\n\t\"sync\"\n\n\t\"github.com/robertkrimen/otto/ast\"\n\t\"github.com/robertkrimen/otto/parser\"\n)\n\ntype global struct {\n\tObject         *object // Object( ... ), new Object( ... ) - 1 (length)\n\tFunction       *object // Function( ... ), new Function( ... ) - 1\n\tArray          *object // Array( ... ), new Array( ... ) - 1\n\tString         *object // String( ... ), new String( ... ) - 1\n\tBoolean        *object // Boolean( ... ), new Boolean( ... ) - 1\n\tNumber         *object // Number( ... ), new Number( ... ) - 1\n\tMath           *object\n\tDate           *object // Date( ... ), new Date( ... ) - 7\n\tRegExp         *object // RegExp( ... ), new RegExp( ... ) - 2\n\tError          *object // Error( ... ), new Error( ... ) - 1\n\tEvalError      *object\n\tTypeError      *object\n\tRangeError     *object\n\tReferenceError *object\n\tSyntaxError    *object\n\tURIError       *object\n\tJSON           *object\n\n\tObjectPrototype         *object // Object.prototype\n\tFunctionPrototype       *object // Function.prototype\n\tArrayPrototype          *object // Array.prototype\n\tStringPrototype         *object // String.prototype\n\tBooleanPrototype        *object // Boolean.prototype\n\tNumberPrototype         *object // Number.prototype\n\tDatePrototype           *object // Date.prototype\n\tRegExpPrototype         *object // RegExp.prototype\n\tErrorPrototype          *object // Error.prototype\n\tEvalErrorPrototype      *object\n\tTypeErrorPrototype      *object\n\tRangeErrorPrototype     *object\n\tReferenceErrorPrototype *object\n\tSyntaxErrorPrototype    *object\n\tURIErrorPrototype       *object\n}\n\ntype runtime struct {\n\tglobal       global\n\tglobalObject *object\n\tglobalStash  *objectStash\n\tscope        *scope\n\totto         *Otto\n\teval         *object\n\tdebugger     func(*Otto)\n\trandom       func() float64\n\tlabels       []string\n\tstackLimit   int\n\ttraceLimit   int\n\tlck          sync.Mutex\n}\n\nfunc (rt *runtime) enterScope(scop *scope) {\n\tscop.outer = rt.scope\n\tif rt.scope != nil {\n\t\tif rt.stackLimit != 0 && rt.scope.depth+1 >= rt.stackLimit {\n\t\t\tpanic(rt.panicRangeError(\"Maximum call stack size exceeded\"))\n\t\t}\n\n\t\tscop.depth = rt.scope.depth + 1\n\t}\n\n\trt.scope = scop\n}\n\nfunc (rt *runtime) leaveScope() {\n\trt.scope = rt.scope.outer\n}\n\n// FIXME This is used in two places (cloning).\nfunc (rt *runtime) enterGlobalScope() {\n\trt.enterScope(newScope(rt.globalStash, rt.globalStash, rt.globalObject))\n}\n\nfunc (rt *runtime) enterFunctionScope(outer stasher, this Value) *fnStash {\n\tif outer == nil {\n\t\touter = rt.globalStash\n\t}\n\tstash := rt.newFunctionStash(outer)\n\tvar thisObject *object\n\tswitch this.kind {\n\tcase valueUndefined, valueNull:\n\t\tthisObject = rt.globalObject\n\tdefault:\n\t\tthisObject = rt.toObject(this)\n\t}\n\trt.enterScope(newScope(stash, stash, thisObject))\n\treturn stash\n}\n\nfunc (rt *runtime) putValue(reference referencer, value Value) {\n\tname := reference.putValue(value)\n\tif name != \"\" {\n\t\t// Why? -- If reference.base == nil\n\t\t// strict = false\n\t\trt.globalObject.defineProperty(name, value, 0o111, false)\n\t}\n}\n\nfunc (rt *runtime) tryCatchEvaluate(inner func() Value) (tryValue Value, isException bool) { //nolint:nonamedreturns\n\t// resultValue = The value of the block (e.g. the last statement)\n\t// throw = Something was thrown\n\t// throwValue = The value of what was thrown\n\t// other = Something that changes flow (return, break, continue) that is not a throw\n\t// Otherwise, some sort of unknown panic happened, we'll just propagate it.\n\tdefer func() {\n\t\tif caught := recover(); caught != nil {\n\t\t\tif excep, ok := caught.(*exception); ok {\n\t\t\t\tcaught = excep.eject()\n\t\t\t}\n\t\t\tswitch caught := caught.(type) {\n\t\t\tcase ottoError:\n\t\t\t\tisException = true\n\t\t\t\ttryValue = objectValue(rt.newErrorObjectError(caught))\n\t\t\tcase Value:\n\t\t\t\tisException = true\n\t\t\t\ttryValue = caught\n\t\t\tdefault:\n\t\t\t\tisException = true\n\t\t\t\ttryValue = toValue(caught)\n\t\t\t}\n\t\t}\n\t}()\n\n\treturn inner(), false\n}\n\nfunc (rt *runtime) toObject(value Value) *object {\n\tswitch value.kind {\n\tcase valueEmpty, valueUndefined, valueNull:\n\t\tpanic(rt.panicTypeError(\"toObject unsupported kind %s\", value.kind))\n\tcase valueBoolean:\n\t\treturn rt.newBoolean(value)\n\tcase valueString:\n\t\treturn rt.newString(value)\n\tcase valueNumber:\n\t\treturn rt.newNumber(value)\n\tcase valueObject:\n\t\treturn value.object()\n\tdefault:\n\t\tpanic(rt.panicTypeError(\"toObject unknown kind %s\", value.kind))\n\t}\n}\n\nfunc (rt *runtime) objectCoerce(value Value) (*object, error) {\n\tswitch value.kind {\n\tcase valueUndefined:\n\t\treturn nil, errors.New(\"undefined\")\n\tcase valueNull:\n\t\treturn nil, errors.New(\"null\")\n\tcase valueBoolean:\n\t\treturn rt.newBoolean(value), nil\n\tcase valueString:\n\t\treturn rt.newString(value), nil\n\tcase valueNumber:\n\t\treturn rt.newNumber(value), nil\n\tcase valueObject:\n\t\treturn value.object(), nil\n\tdefault:\n\t\tpanic(rt.panicTypeError(\"objectCoerce unknown kind %s\", value.kind))\n\t}\n}\n\nfunc checkObjectCoercible(rt *runtime, value Value) {\n\tisObject, mustCoerce := testObjectCoercible(value)\n\tif !isObject && !mustCoerce {\n\t\tpanic(rt.panicTypeError(\"checkObjectCoercible not object or mustCoerce\"))\n\t}\n}\n\n// testObjectCoercible.\nfunc testObjectCoercible(value Value) (isObject, mustCoerce bool) { //nolint:nonamedreturns\n\tswitch value.kind {\n\tcase valueReference, valueEmpty, valueNull, valueUndefined:\n\t\treturn false, false\n\tcase valueNumber, valueString, valueBoolean:\n\t\treturn false, true\n\tcase valueObject:\n\t\treturn true, false\n\tdefault:\n\t\tpanic(fmt.Sprintf(\"testObjectCoercible unknown kind %s\", value.kind))\n\t}\n}\n\nfunc (rt *runtime) safeToValue(value interface{}) (Value, error) {\n\tresult := Value{}\n\terr := catchPanic(func() {\n\t\tresult = rt.toValue(value)\n\t})\n\treturn result, err\n}\n\n// convertNumeric converts numeric parameter val from js to that of type t if it is safe to do so, otherwise it panics.\n// This allows literals (int64), bitwise values (int32) and the general form (float64) of javascript numerics to be passed as parameters to go functions easily.\nfunc (rt *runtime) convertNumeric(v Value, t reflect.Type) reflect.Value {\n\tval := reflect.ValueOf(v.export())\n\n\tif val.Kind() == t.Kind() {\n\t\treturn val\n\t}\n\n\tif val.Kind() == reflect.Interface {\n\t\tval = reflect.ValueOf(val.Interface())\n\t}\n\n\tswitch val.Kind() {\n\tcase reflect.Float32, reflect.Float64:\n\t\tf64 := val.Float()\n\t\tswitch t.Kind() {\n\t\tcase reflect.Float64:\n\t\t\treturn reflect.ValueOf(f64)\n\t\tcase reflect.Float32:\n\t\t\tif reflect.Zero(t).OverflowFloat(f64) {\n\t\t\t\tpanic(rt.panicRangeError(\"converting float64 to float32 would overflow\"))\n\t\t\t}\n\n\t\t\treturn val.Convert(t)\n\t\tcase reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:\n\t\t\ti64 := int64(f64)\n\t\t\tif float64(i64) != f64 {\n\t\t\t\tpanic(rt.panicRangeError(fmt.Sprintf(\"converting %v to %v would cause loss of precision\", val.Type(), t)))\n\t\t\t}\n\n\t\t\t// The float represents an integer\n\t\t\tval = reflect.ValueOf(i64)\n\t\tdefault:\n\t\t\tpanic(rt.panicTypeError(fmt.Sprintf(\"cannot convert %v to %v\", val.Type(), t)))\n\t\t}\n\t}\n\n\tswitch val.Kind() {\n\tcase reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:\n\t\ti64 := val.Int()\n\t\tswitch t.Kind() {\n\t\tcase reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:\n\t\t\tif reflect.Zero(t).OverflowInt(i64) {\n\t\t\t\tpanic(rt.panicRangeError(fmt.Sprintf(\"converting %v to %v would overflow\", val.Type(), t)))\n\t\t\t}\n\t\t\treturn val.Convert(t)\n\t\tcase reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:\n\t\t\tif i64 < 0 {\n\t\t\t\tpanic(rt.panicRangeError(fmt.Sprintf(\"converting %v to %v would underflow\", val.Type(), t)))\n\t\t\t}\n\t\t\tif reflect.Zero(t).OverflowUint(uint64(i64)) {\n\t\t\t\tpanic(rt.panicRangeError(fmt.Sprintf(\"converting %v to %v would overflow\", val.Type(), t)))\n\t\t\t}\n\t\t\treturn val.Convert(t)\n\t\tcase reflect.Float32, reflect.Float64:\n\t\t\treturn val.Convert(t)\n\t\t}\n\n\tcase reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:\n\t\tu64 := val.Uint()\n\t\tswitch t.Kind() {\n\t\tcase reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:\n\t\t\tif u64 > math.MaxInt64 || reflect.Zero(t).OverflowInt(int64(u64)) {\n\t\t\t\tpanic(rt.panicRangeError(fmt.Sprintf(\"converting %v to %v would overflow\", val.Type(), t)))\n\t\t\t}\n\t\t\treturn val.Convert(t)\n\t\tcase reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:\n\t\t\tif reflect.Zero(t).OverflowUint(u64) {\n\t\t\t\tpanic(rt.panicRangeError(fmt.Sprintf(\"converting %v to %v would overflow\", val.Type(), t)))\n\t\t\t}\n\t\t\treturn val.Convert(t)\n\t\tcase reflect.Float32, reflect.Float64:\n\t\t\treturn val.Convert(t)\n\t\t}\n\t}\n\n\tpanic(rt.panicTypeError(fmt.Sprintf(\"unsupported type %v -> %v for numeric conversion\", val.Type(), t)))\n}\n\nfunc fieldIndexByName(t reflect.Type, name string) []int {\n\tfor t.Kind() == reflect.Ptr {\n\t\tt = t.Elem()\n\t}\n\n\tfor i := range t.NumField() {\n\t\tf := t.Field(i)\n\n\t\tif !validGoStructName(f.Name) {\n\t\t\tcontinue\n\t\t}\n\n\t\tif f.Anonymous {\n\t\t\tfor t.Kind() == reflect.Ptr {\n\t\t\t\tt = t.Elem()\n\t\t\t}\n\n\t\t\tif f.Type.Kind() == reflect.Struct {\n\t\t\t\tif a := fieldIndexByName(f.Type, name); a != nil {\n\t\t\t\t\treturn append([]int{i}, a...)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif a := strings.SplitN(f.Tag.Get(\"json\"), \",\", 2); a[0] != \"\" {\n\t\t\tif a[0] == \"-\" {\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif a[0] == name {\n\t\t\t\treturn []int{i}\n\t\t\t}\n\t\t}\n\n\t\tif f.Name == name {\n\t\t\treturn []int{i}\n\t\t}\n\t}\n\n\treturn nil\n}\n\nvar (\n\ttypeOfValue          = reflect.TypeOf(Value{})\n\ttypeOfJSONRawMessage = reflect.TypeOf(json.RawMessage{})\n)\n\n// convertCallParameter converts request val to type t if possible.\n// If the conversion fails due to overflow or type miss-match then it panics.\n// If no conversion is known then the original value is returned.\nfunc (rt *runtime) convertCallParameter(v Value, t reflect.Type) (reflect.Value, error) {\n\tif t == typeOfValue {\n\t\treturn reflect.ValueOf(v), nil\n\t}\n\n\tif t == typeOfJSONRawMessage {\n\t\tif d, err := json.Marshal(v.export()); err == nil {\n\t\t\treturn reflect.ValueOf(d), nil\n\t\t}\n\t}\n\n\tif v.kind == valueObject {\n\t\tif gso, ok := v.object().value.(*goStructObject); ok {\n\t\t\tif gso.value.Type().AssignableTo(t) {\n\t\t\t\t// please see TestDynamicFunctionReturningInterface for why this exists\n\t\t\t\tif t.Kind() == reflect.Interface && gso.value.Type().ConvertibleTo(t) {\n\t\t\t\t\treturn gso.value.Convert(t), nil\n\t\t\t\t}\n\t\t\t\treturn gso.value, nil\n\t\t\t}\n\t\t}\n\n\t\tif gao, ok := v.object().value.(*goArrayObject); ok {\n\t\t\tif gao.value.Type().AssignableTo(t) {\n\t\t\t\t// please see TestDynamicFunctionReturningInterface for why this exists\n\t\t\t\tif t.Kind() == reflect.Interface && gao.value.Type().ConvertibleTo(t) {\n\t\t\t\t\treturn gao.value.Convert(t), nil\n\t\t\t\t}\n\t\t\t\treturn gao.value, nil\n\t\t\t}\n\t\t}\n\t}\n\n\ttk := t.Kind()\n\n\tif tk == reflect.Interface {\n\t\te := v.export()\n\t\tif e == nil {\n\t\t\treturn reflect.Zero(t), nil\n\t\t}\n\t\tiv := reflect.ValueOf(e)\n\t\tif iv.Type().AssignableTo(t) {\n\t\t\treturn iv, nil\n\t\t}\n\t}\n\n\tif tk == reflect.Ptr {\n\t\tswitch v.kind {\n\t\tcase valueEmpty, valueNull, valueUndefined:\n\t\t\treturn reflect.Zero(t), nil\n\t\tdefault:\n\t\t\tvar vv reflect.Value\n\t\t\tvv, err := rt.convertCallParameter(v, t.Elem())\n\t\t\tif err != nil {\n\t\t\t\treturn reflect.Zero(t), fmt.Errorf(\"can't convert to %s: %w\", t, err)\n\t\t\t}\n\n\t\t\tif vv.CanAddr() {\n\t\t\t\treturn vv.Addr(), nil\n\t\t\t}\n\n\t\t\tpv := reflect.New(vv.Type())\n\t\t\tpv.Elem().Set(vv)\n\t\t\treturn pv, nil\n\t\t}\n\t}\n\n\tswitch tk {\n\tcase reflect.Bool:\n\t\treturn reflect.ValueOf(v.bool()), nil\n\tcase reflect.String:\n\t\tswitch v.kind {\n\t\tcase valueString:\n\t\t\treturn reflect.ValueOf(v.value), nil\n\t\tcase valueNumber:\n\t\t\treturn reflect.ValueOf(fmt.Sprintf(\"%v\", v.value)), nil\n\t\t}\n\tcase reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64:\n\t\tif v.kind == valueNumber {\n\t\t\treturn rt.convertNumeric(v, t), nil\n\t\t}\n\tcase reflect.Slice:\n\t\tif o := v.object(); o != nil {\n\t\t\tif lv := o.get(propertyLength); lv.IsNumber() {\n\t\t\t\tl := lv.number().int64\n\n\t\t\t\ts := reflect.MakeSlice(t, int(l), int(l))\n\n\t\t\t\ttt := t.Elem()\n\n\t\t\t\tswitch o.class {\n\t\t\t\tcase classArrayName:\n\t\t\t\t\tfor i := range l {\n\t\t\t\t\t\tp, ok := o.property[strconv.FormatInt(i, 10)]\n\t\t\t\t\t\tif !ok {\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\te, ok := p.value.(Value)\n\t\t\t\t\t\tif !ok {\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tev, err := rt.convertCallParameter(e, tt)\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\treturn reflect.Zero(t), fmt.Errorf(\"couldn't convert element %d of %s: %w\", i, t, err)\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ts.Index(int(i)).Set(ev)\n\t\t\t\t\t}\n\t\t\t\tcase classGoArrayName, classGoSliceName:\n\t\t\t\t\tvar gslice bool\n\t\t\t\t\tswitch o.value.(type) {\n\t\t\t\t\tcase *goSliceObject:\n\t\t\t\t\t\tgslice = true\n\t\t\t\t\tcase *goArrayObject:\n\t\t\t\t\t\tgslice = false\n\t\t\t\t\t}\n\n\t\t\t\t\tfor i := range l {\n\t\t\t\t\t\tvar p *property\n\t\t\t\t\t\tif gslice {\n\t\t\t\t\t\t\tp = goSliceGetOwnProperty(o, strconv.FormatInt(i, 10))\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tp = goArrayGetOwnProperty(o, strconv.FormatInt(i, 10))\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif p == nil {\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\te, ok := p.value.(Value)\n\t\t\t\t\t\tif !ok {\n\t\t\t\t\t\t\tcontinue\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tev, err := rt.convertCallParameter(e, tt)\n\t\t\t\t\t\tif err != nil {\n\t\t\t\t\t\t\treturn reflect.Zero(t), fmt.Errorf(\"couldn't convert element %d of %s: %w\", i, t, err)\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ts.Index(int(i)).Set(ev)\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn s, nil\n\t\t\t}\n\t\t}\n\tcase reflect.Map:\n\t\tif o := v.object(); o != nil && t.Key().Kind() == reflect.String {\n\t\t\tm := reflect.MakeMap(t)\n\n\t\t\tvar err error\n\n\t\t\to.enumerate(false, func(k string) bool {\n\t\t\t\tv, verr := rt.convertCallParameter(o.get(k), t.Elem())\n\t\t\t\tif verr != nil {\n\t\t\t\t\terr = fmt.Errorf(\"couldn't convert property %q of %s: %w\", k, t, verr)\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t\tm.SetMapIndex(reflect.ValueOf(k), v)\n\t\t\t\treturn true\n\t\t\t})\n\n\t\t\tif err != nil {\n\t\t\t\treturn reflect.Zero(t), err\n\t\t\t}\n\n\t\t\treturn m, nil\n\t\t}\n\tcase reflect.Func:\n\t\tif t.NumOut() > 1 {\n\t\t\treturn reflect.Zero(t), errors.New(\"converting JavaScript values to Go functions with more than one return value is currently not supported\")\n\t\t}\n\n\t\tif o := v.object(); o != nil && o.class == classFunctionName {\n\t\t\treturn reflect.MakeFunc(t, func(args []reflect.Value) []reflect.Value {\n\t\t\t\tl := make([]interface{}, len(args))\n\t\t\t\tfor i, a := range args {\n\t\t\t\t\tif a.CanInterface() {\n\t\t\t\t\t\tl[i] = a.Interface()\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\trv, err := v.Call(nullValue, l...)\n\t\t\t\tif err != nil {\n\t\t\t\t\tpanic(err)\n\t\t\t\t}\n\n\t\t\t\tif t.NumOut() == 0 {\n\t\t\t\t\treturn nil\n\t\t\t\t}\n\n\t\t\t\tr, err := rt.convertCallParameter(rv, t.Out(0))\n\t\t\t\tif err != nil {\n\t\t\t\t\tpanic(rt.panicTypeError(\"convertCallParameter Func: %s\", err))\n\t\t\t\t}\n\n\t\t\t\treturn []reflect.Value{r}\n\t\t\t}), nil\n\t\t}\n\tcase reflect.Struct:\n\t\tif o := v.object(); o != nil && o.class == classObjectName {\n\t\t\ts := reflect.New(t)\n\n\t\t\tfor _, k := range o.propertyOrder {\n\t\t\t\tidx := fieldIndexByName(t, k)\n\n\t\t\t\tif idx == nil {\n\t\t\t\t\treturn reflect.Zero(t), fmt.Errorf(\"can't convert property %q of %s: field does not exist\", k, t)\n\t\t\t\t}\n\n\t\t\t\tss := s\n\n\t\t\t\tfor _, i := range idx {\n\t\t\t\t\tif ss.Kind() == reflect.Ptr {\n\t\t\t\t\t\tif ss.IsNil() {\n\t\t\t\t\t\t\tif !ss.CanSet() {\n\t\t\t\t\t\t\t\treturn reflect.Zero(t), fmt.Errorf(\"can't convert property %q of %s: %s is unexported\", k, t, ss.Type().Elem())\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\tss.Set(reflect.New(ss.Type().Elem()))\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tss = ss.Elem()\n\t\t\t\t\t}\n\n\t\t\t\t\tss = ss.Field(i)\n\t\t\t\t}\n\n\t\t\t\tv, err := rt.convertCallParameter(o.get(k), ss.Type())\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn reflect.Zero(t), fmt.Errorf(\"couldn't convert property %q of %s: %w\", k, t, err)\n\t\t\t\t}\n\n\t\t\t\tss.Set(v)\n\t\t\t}\n\n\t\t\treturn s.Elem(), nil\n\t\t}\n\t}\n\n\tif tk == reflect.String {\n\t\tif o := v.object(); o != nil && o.hasProperty(\"toString\") {\n\t\t\tif fn := o.get(\"toString\"); fn.IsFunction() {\n\t\t\t\tsv, err := fn.Call(v)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn reflect.Zero(t), fmt.Errorf(\"couldn't call toString: %w\", err)\n\t\t\t\t}\n\n\t\t\t\tr, err := rt.convertCallParameter(sv, t)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn reflect.Zero(t), fmt.Errorf(\"couldn't convert toString result: %w\", err)\n\t\t\t\t}\n\t\t\t\treturn r, nil\n\t\t\t}\n\t\t}\n\n\t\treturn reflect.ValueOf(v.String()), nil\n\t}\n\n\tif v.kind == valueString {\n\t\tvar s encoding.TextUnmarshaler\n\n\t\tif reflect.PointerTo(t).Implements(reflect.TypeOf(&s).Elem()) {\n\t\t\tr := reflect.New(t)\n\n\t\t\tif err := r.Interface().(encoding.TextUnmarshaler).UnmarshalText([]byte(v.string())); err != nil {\n\t\t\t\treturn reflect.Zero(t), fmt.Errorf(\"can't convert to %s as TextUnmarshaller: %w\", t.String(), err)\n\t\t\t}\n\n\t\t\treturn r.Elem(), nil\n\t\t}\n\t}\n\n\ts := \"OTTO DOES NOT UNDERSTAND THIS TYPE\"\n\tswitch v.kind {\n\tcase valueBoolean:\n\t\ts = \"boolean\"\n\tcase valueNull:\n\t\ts = \"null\"\n\tcase valueNumber:\n\t\ts = \"number\"\n\tcase valueString:\n\t\ts = \"string\"\n\tcase valueUndefined:\n\t\ts = \"undefined\"\n\tcase valueObject:\n\t\ts = v.Class()\n\t}\n\n\treturn reflect.Zero(t), fmt.Errorf(\"can't convert from %q to %q\", s, t)\n}\n\nfunc (rt *runtime) toValue(value interface{}) Value {\n\trv, ok := value.(reflect.Value)\n\tif ok {\n\t\tvalue = rv.Interface()\n\t}\n\n\tswitch value := value.(type) {\n\tcase Value:\n\t\treturn value\n\tcase func(FunctionCall) Value:\n\t\tvar name, file string\n\t\tvar line int\n\t\tpc := reflect.ValueOf(value).Pointer()\n\t\tfn := goruntime.FuncForPC(pc)\n\t\tif fn != nil {\n\t\t\tname = fn.Name()\n\t\t\tfile, line = fn.FileLine(pc)\n\t\t\tfile = path.Base(file)\n\t\t}\n\t\treturn objectValue(rt.newNativeFunction(name, file, line, value))\n\tcase nativeFunction:\n\t\tvar name, file string\n\t\tvar line int\n\t\tpc := reflect.ValueOf(value).Pointer()\n\t\tfn := goruntime.FuncForPC(pc)\n\t\tif fn != nil {\n\t\t\tname = fn.Name()\n\t\t\tfile, line = fn.FileLine(pc)\n\t\t\tfile = path.Base(file)\n\t\t}\n\t\treturn objectValue(rt.newNativeFunction(name, file, line, value))\n\tcase Object, *Object, object, *object:\n\t\t// Nothing happens.\n\t\t// FIXME We should really figure out what can come here.\n\t\t// This catch-all is ugly.\n\tdefault:\n\t\tval := reflect.ValueOf(value)\n\t\tif ok && val.Kind() == rv.Kind() {\n\t\t\t// Use passed in rv which may be writable.\n\t\t\tval = rv\n\t\t}\n\n\t\tswitch val.Kind() {\n\t\tcase reflect.Ptr:\n\t\t\tswitch reflect.Indirect(val).Kind() {\n\t\t\tcase reflect.Struct:\n\t\t\t\treturn objectValue(rt.newGoStructObject(val))\n\t\t\tcase reflect.Array:\n\t\t\t\treturn objectValue(rt.newGoArray(val))\n\t\t\t}\n\t\tcase reflect.Struct:\n\t\t\treturn objectValue(rt.newGoStructObject(val))\n\t\tcase reflect.Map:\n\t\t\treturn objectValue(rt.newGoMapObject(val))\n\t\tcase reflect.Slice:\n\t\t\treturn objectValue(rt.newGoSlice(val))\n\t\tcase reflect.Array:\n\t\t\treturn objectValue(rt.newGoArray(val))\n\t\tcase reflect.Func:\n\t\t\tvar name, file string\n\t\t\tvar line int\n\t\t\tif v := reflect.ValueOf(val); v.Kind() == reflect.Ptr {\n\t\t\t\tpc := v.Pointer()\n\t\t\t\tfn := goruntime.FuncForPC(pc)\n\t\t\t\tif fn != nil {\n\t\t\t\t\tname = fn.Name()\n\t\t\t\t\tfile, line = fn.FileLine(pc)\n\t\t\t\t\tfile = path.Base(file)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\ttyp := val.Type()\n\n\t\t\treturn objectValue(rt.newNativeFunction(name, file, line, func(c FunctionCall) Value {\n\t\t\t\tnargs := typ.NumIn()\n\n\t\t\t\tif len(c.ArgumentList) != nargs {\n\t\t\t\t\tif typ.IsVariadic() {\n\t\t\t\t\t\tif len(c.ArgumentList) < nargs-1 {\n\t\t\t\t\t\t\tpanic(rt.panicRangeError(fmt.Sprintf(\"expected at least %d arguments; got %d\", nargs-1, len(c.ArgumentList))))\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tpanic(rt.panicRangeError(fmt.Sprintf(\"expected %d argument(s); got %d\", nargs, len(c.ArgumentList))))\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tin := make([]reflect.Value, len(c.ArgumentList))\n\n\t\t\t\tcallSlice := false\n\n\t\t\t\tfor i, a := range c.ArgumentList {\n\t\t\t\t\tvar t reflect.Type\n\n\t\t\t\t\tn := i\n\t\t\t\t\tif n >= nargs-1 && typ.IsVariadic() {\n\t\t\t\t\t\tif n > nargs-1 {\n\t\t\t\t\t\t\tn = nargs - 1\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tt = typ.In(n).Elem()\n\t\t\t\t\t} else {\n\t\t\t\t\t\tt = typ.In(n)\n\t\t\t\t\t}\n\n\t\t\t\t\t// if this is a variadic Go function, and the caller has supplied\n\t\t\t\t\t// exactly the number of JavaScript arguments required, and this\n\t\t\t\t\t// is the last JavaScript argument, try treating the it as the\n\t\t\t\t\t// actual set of variadic Go arguments. if that succeeds, break\n\t\t\t\t\t// out of the loop.\n\t\t\t\t\tif typ.IsVariadic() && len(c.ArgumentList) == nargs && i == nargs-1 {\n\t\t\t\t\t\tif v, err := rt.convertCallParameter(a, typ.In(n)); err == nil {\n\t\t\t\t\t\t\tin[i] = v\n\t\t\t\t\t\t\tcallSlice = true\n\t\t\t\t\t\t\tbreak\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tv, err := rt.convertCallParameter(a, t)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\tpanic(rt.panicTypeError(err.Error()))\n\t\t\t\t\t}\n\n\t\t\t\t\tin[i] = v\n\t\t\t\t}\n\n\t\t\t\tvar out []reflect.Value\n\t\t\t\tif callSlice {\n\t\t\t\t\tout = val.CallSlice(in)\n\t\t\t\t} else {\n\t\t\t\t\tout = val.Call(in)\n\t\t\t\t}\n\n\t\t\t\tswitch len(out) {\n\t\t\t\tcase 0:\n\t\t\t\t\treturn Value{}\n\t\t\t\tcase 1:\n\t\t\t\t\treturn rt.toValue(out[0].Interface())\n\t\t\t\tdefault:\n\t\t\t\t\ts := make([]interface{}, len(out))\n\t\t\t\t\tfor i, v := range out {\n\t\t\t\t\t\ts[i] = rt.toValue(v.Interface())\n\t\t\t\t\t}\n\n\t\t\t\t\treturn rt.toValue(s)\n\t\t\t\t}\n\t\t\t}))\n\t\t}\n\t}\n\n\treturn toValue(value)\n}\n\nfunc (rt *runtime) newGoSlice(value reflect.Value) *object {\n\tobj := rt.newGoSliceObject(value)\n\tobj.prototype = rt.global.ArrayPrototype\n\treturn obj\n}\n\nfunc (rt *runtime) newGoArray(value reflect.Value) *object {\n\tobj := rt.newGoArrayObject(value)\n\tobj.prototype = rt.global.ArrayPrototype\n\treturn obj\n}\n\nfunc (rt *runtime) parse(filename string, src, sm interface{}) (*ast.Program, error) {\n\treturn parser.ParseFileWithSourceMap(nil, filename, src, sm, 0)\n}\n\nfunc (rt *runtime) cmplParse(filename string, src, sm interface{}) (*nodeProgram, error) {\n\tprogram, err := parser.ParseFileWithSourceMap(nil, filename, src, sm, 0)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn cmplParse(program), nil\n}\n\nfunc (rt *runtime) parseSource(src, sm interface{}) (*nodeProgram, *ast.Program, error) {\n\tswitch src := src.(type) {\n\tcase *ast.Program:\n\t\treturn nil, src, nil\n\tcase *Script:\n\t\treturn src.program, nil, nil\n\t}\n\n\tprogram, err := rt.parse(\"\", src, sm)\n\n\treturn nil, program, err\n}\n\nfunc (rt *runtime) cmplRunOrEval(src, sm interface{}, eval bool) (Value, error) {\n\tresult := Value{}\n\tnode, program, err := rt.parseSource(src, sm)\n\tif err != nil {\n\t\treturn result, err\n\t}\n\tif node == nil {\n\t\tnode = cmplParse(program)\n\t}\n\terr = catchPanic(func() {\n\t\tresult = rt.cmplEvaluateNodeProgram(node, eval)\n\t})\n\tswitch result.kind {\n\tcase valueEmpty:\n\t\tresult = Value{}\n\tcase valueReference:\n\t\tresult = result.resolve()\n\t}\n\treturn result, err\n}\n\nfunc (rt *runtime) cmplRun(src, sm interface{}) (Value, error) {\n\treturn rt.cmplRunOrEval(src, sm, false)\n}\n\nfunc (rt *runtime) cmplEval(src, sm interface{}) (Value, error) {\n\treturn rt.cmplRunOrEval(src, sm, true)\n}\n\nfunc (rt *runtime) parseThrow(err error) {\n\tif err == nil {\n\t\treturn\n\t}\n\n\tvar errl parser.ErrorList\n\tif errors.Is(err, &errl) {\n\t\terr := errl[0]\n\t\tif err.Message == \"invalid left-hand side in assignment\" {\n\t\t\tpanic(rt.panicReferenceError(err.Message))\n\t\t}\n\t\tpanic(rt.panicSyntaxError(err.Message))\n\t}\n\tpanic(rt.panicSyntaxError(err.Error()))\n}\n\nfunc (rt *runtime) cmplParseOrThrow(src, sm interface{}) *nodeProgram {\n\tprogram, err := rt.cmplParse(\"\", src, sm)\n\trt.parseThrow(err) // Will panic/throw appropriately\n\treturn program\n}\n"
  },
  {
    "path": "runtime_test.go",
    "content": "package otto\n\nimport (\n\t\"math\"\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\n// FIXME terst, Review tests\n\nfunc TestOperator(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, vm := test()\n\n\t\ttest(\"xyzzy = 1\")\n\t\ttest(\"xyzzy\", 1)\n\n\t\tif true {\n\t\t\tvm.Set(\"twoPlusTwo\", func(FunctionCall) Value {\n\t\t\t\treturn toValue(5)\n\t\t\t})\n\t\t\ttest(\"twoPlusTwo( 1 )\", 5)\n\n\t\t\ttest(\"1 + twoPlusTwo( 1 )\", 6)\n\n\t\t\ttest(\"-1 + twoPlusTwo( 1 )\", 4)\n\t\t}\n\n\t\ttest(\"result = 4\")\n\t\ttest(\"result\", 4)\n\n\t\ttest(\"result += 1\")\n\t\ttest(\"result\", 5)\n\n\t\ttest(\"result *= 2\")\n\t\ttest(\"result\", 10)\n\n\t\ttest(\"result /= 2\")\n\t\ttest(\"result\", 5)\n\n\t\ttest(\"result = 112.51 % 3.1\")\n\t\ttest(\"result\", 0.9100000000000019)\n\n\t\ttest(\"result = 'Xyzzy'\")\n\t\ttest(\"result\", \"Xyzzy\")\n\n\t\ttest(\"result = 'Xyz' + 'zy'\")\n\t\ttest(\"result\", \"Xyzzy\")\n\n\t\ttest(\"result = \\\"Xyzzy\\\"\")\n\t\ttest(\"result\", \"Xyzzy\")\n\n\t\ttest(\"result = 1; result = result\")\n\t\ttest(\"result\", 1)\n\n\t\ttest(`\n            var result64\n            =\n            64\n            , result10 =\n            10\n        `)\n\t\ttest(\"result64\", 64)\n\t\ttest(\"result10\", 10)\n\n\t\ttest(`\n            result = 1;\n            result += 1;\n        `)\n\t\ttest(\"result\", 2)\n\t})\n}\n\nfunc TestFunction_(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            result = 2\n            xyzzy = function() {\n                result += 1\n            }\n            xyzzy()\n            result;\n        `, 3)\n\n\t\ttest(`\n            xyzzy = function() {\n                return 1\n            }\n            result = xyzzy()\n        `, 1)\n\n\t\ttest(`\n            xyzzy = function() {}\n            result = xyzzy()\n        `, \"undefined\")\n\n\t\ttest(`\n            xyzzy = function() {\n                return 64\n                return 1\n            }\n            result = xyzzy()\n        `, 64)\n\n\t\ttest(`\n            result = 4\n            xyzzy = function() {\n                result = 2\n            }\n            xyzzy();\n            result;\n        `, 2)\n\n\t\ttest(`\n            result = 4\n            xyzzy = function() {\n                var result\n                result = 2\n            }\n            xyzzy();\n            result;\n        `, 4)\n\n\t\ttest(`\n            xyzzy = function() {\n                var result = 4\n                return result\n            }\n            result = xyzzy()\n        `, 4)\n\n\t\ttest(`\n            xyzzy = function() {\n                    function test() {\n                        var result = 1\n                    return result\n                }\n                    return test() + 1\n                }\n            result = xyzzy() + 1\n        `, 3)\n\n\t\ttest(`\n            xyzzy = function() {\n                function test() {\n                    var result = 1\n                    return result\n                }\n                _xyzzy = 2\n                    var result = _xyzzy + test() + 1\n                    return result\n            }\n            result = xyzzy() + 1;\n            [ result, _xyzzy ];\n        `, \"5,2\")\n\n\t\ttest(`\n            xyzzy = function(apple) {\n                return 1\n            }\n            result = xyzzy(1)\n        `, 1)\n\n\t\ttest(`\n            xyzzy = function(apple) {\n                return apple + 1\n            }\n            result = xyzzy(2)\n        `, 3)\n\n\t\ttest(`\n            {\n                result = 1\n                result += 1;\n            }\n        `, 2)\n\n\t\ttest(`\n            var global = 1\n            outer = function() {\n                var global = 2\n                var inner = function(){\n                    return global\n                }\n                return inner()\n            }\n            result = outer()\n        `, 2)\n\n\t\ttest(`\n            var apple = 1\n            var banana = function() {\n                return apple\n            }\n            var cherry = function() {\n                var apple = 2\n                return banana()\n            }\n            result = cherry()\n        `, 1)\n\n\t\ttest(`\n            function xyz() {\n            };\n            delete xyz;\n        `, false)\n\n\t\ttest(`\n            var abc = function __factorial(def){\n                if (def === 1) {\n                    return def;\n                } else {\n                    return __factorial(def-1)*def;\n                }\n            };\n            abc(3);\n        `, 6)\n\t})\n}\n\nfunc TestDoWhile(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            limit = 4;\n            result = 0;\n            do { \n                result = result + 1;\n                limit = limit - 1;\n            } while (limit);\n            result;\n        `, 4)\n\n\t\ttest(`\n            result = eval(\"do {abc=1; break; abc=2;} while (0);\");\n            [ result, abc ];\n        `, \"1,1\")\n\t})\n}\n\nfunc TestContinueBreak(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            limit = 4\n            result = 0\n            while (limit) {\n                limit = limit - 1\n                if (limit) {\n                }\n                else {\n                    break\n                }\n                result = result + 1\n            }\n            [ result, limit ];\n        `, \"3,0\")\n\n\t\ttest(`\n            limit = 4\n            result = 0\n            while (limit) {\n                limit = limit - 1\n                if (limit) {\n                    continue\n                }\n                else {\n                    break\n                }\n                result = result + 1\n            }\n            result;\n        `, 0)\n\n\t\ttest(`\n            limit = 4\n            result = 0\n            do {\n                limit = limit - 1\n                if (limit) {\n                    continue\n                }\n                else {\n                    break\n                }\n                result = result + 1\n            } while (limit)\n            result;\n        `, 0)\n\t})\n}\n\nfunc TestTryCatchError(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            var abc\n            try {\n                1()\n            }\n            catch (def) {\n                abc = def\n            }\n            abc;\n        `, \"TypeError: 1 is not a function\")\n\t})\n}\n\nfunc TestPositiveNegativeZero(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`1/0`, infinity)\n\t\ttest(`1/-0`, -infinity)\n\t\ttest(`\n            abc = -0\n            1/abc\n        `, -infinity)\n\t})\n}\n\nfunc TestComparison(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            undefined = 1; undefined;\n        `, \"undefined\")\n\n\t\ttest(\"undefined == undefined\", true)\n\n\t\ttest(\"undefined != undefined\", false)\n\n\t\ttest(\"null == null\", true)\n\n\t\ttest(\"null != null\", false)\n\n\t\ttest(\"0 == 1\", false)\n\n\t\tis(negativeZero, -0)\n\t\tis(positiveZero, 0)\n\t\tis(math.Signbit(negativeZero), true)\n\t\tis(positiveZero == negativeZero, true)\n\n\t\ttest(\"1 == 1\", true)\n\n\t\ttest(\"'Hello, World.' == 'Goodbye, World.'\", false)\n\n\t\ttest(\"'Hello, World.' == true\", false)\n\n\t\ttest(\"'Hello, World.' == false\", false)\n\n\t\ttest(\"'Hello, World.' == 1\", false)\n\n\t\ttest(\"1 == 'Hello, World.'\", false)\n\n\t\tis(parseNumber(\"-1\"), -1)\n\n\t\ttest(\"0+Object\", \"0function Object() { [native code] }\")\n\t})\n}\n\nfunc TestComparisonRelational(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(\"0 < 0\", false)\n\n\t\ttest(\"0 > 0\", false)\n\n\t\ttest(\"0 <= 0\", true)\n\n\t\ttest(\"0 >= 0\", true)\n\n\t\ttest(\"'   0' >= 0\", true)\n\n\t\ttest(\"'_   0' >= 0\", false)\n\t})\n}\n\nfunc TestArguments(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            xyzzy = function() {\n                return arguments[0]\n            }\n            result = xyzzy(\"xyzzy\");\n        `, \"xyzzy\")\n\n\t\ttest(`\n            xyzzy = function() {\n                arguments[0] = \"abcdef\"\n                return arguments[0]\n            }\n            result = xyzzy(\"xyzzy\");\n        `, \"abcdef\")\n\n\t\ttest(`\n            xyzzy = function(apple) {\n                apple = \"abcdef\"\n                return arguments[0]\n            }\n            result = xyzzy(\"xyzzy\");\n        `, \"abcdef\")\n\n\t\ttest(`\n            (function(){\n                return arguments\n            })()\n        `, \"[object Arguments]\")\n\n\t\ttest(`\n            (function(){\n                return arguments.length\n            })()\n        `, 0)\n\n\t\ttest(`\n            (function(){\n                return arguments.length\n            })(1, 2, 4, 8, 10)\n        `, 5)\n\t})\n}\n\nfunc TestObjectLiteral(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            ({});\n        `, \"[object Object]\")\n\n\t\ttest(`\n            var abc = {\n                xyzzy: \"Nothing happens.\",\n                get 1e2() {\n                    return 3.14159;\n                },\n                get null() {\n                    return true;\n                },\n                get \"[\\n]\"() {\n                    return \"<>\";\n                }\n            };\n            [ abc[\"1e2\"], abc.null, abc[\"[\\n]\"] ]; \n        `, \"3.14159,true,<>\")\n\n\t\ttest(`\n            var abc = {\n                xyzzy: \"Nothing happens.\",\n                set 1e2() {\n                    this[3.14159] = 100;\n                    return Math.random();\n                },\n                set null(def) {\n                    this.def = def;\n                    return Math.random();\n                },\n            };\n            [ abc[\"1e2\"] = Infinity, abc[3.14159], abc.null = \"xyz\", abc.def ];\n        `, \"Infinity,100,xyz,xyz\")\n\t})\n}\n\nfunc TestUnaryPrefix(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            var result = 0;\n            [++result, result];\n        `, \"1,1\")\n\n\t\ttest(`\n            result = 0;\n            [--result, result];\n        `, \"-1,-1\")\n\n\t\ttest(`\n            var object = { valueOf: function() { return 1; } };\n            result = ++object;\n            [ result, typeof result ];\n        `, \"2,number\")\n\n\t\ttest(`\n            var object = { valueOf: function() { return 1; } };\n            result = --object;\n            [ result, typeof result ];\n        `, \"0,number\")\n\t})\n}\n\nfunc TestUnaryPostfix(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            var result = 0;\n            result++;\n            [ result++, result ];\n        `, \"1,2\")\n\n\t\ttest(`\n            result = 0;\n            result--;\n            [ result--, result ];\n        `, \"-1,-2\")\n\n\t\ttest(`\n            var object = { valueOf: function() { return 1; } };\n            result = object++;\n            [ result, typeof result ];\n        `, \"1,number\")\n\n\t\ttest(`\n            var object = { valueOf: function() { return 1; } };\n            result = object--\n            [ result, typeof result ];\n        `, \"1,number\")\n\t})\n}\n\nfunc TestBinaryLogicalOperation(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            abc = true\n            def = false\n            ghi = false\n            jkl = false\n            result = abc && def || ghi && jkl\n        `, false)\n\n\t\ttest(`\n            abc = true\n            def = true\n            ghi = false\n            jkl = false\n            result = abc && def || ghi && jkl\n        `, true)\n\t})\n}\n\nfunc TestBinaryBitwiseOperation(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            abc = 1 & 2;\n            def = 1 & 3;\n            ghi = 1 | 3;\n            jkl = 1 ^ 2;\n            mno = 1 ^ 3;\n            [ abc, def, ghi, jkl, mno ];\n        `, \"0,1,3,3,2\")\n\t})\n}\n\nfunc TestBinaryShiftOperation(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            high = (1 << 30) - 1 + (1 << 30)\n            low = -high - 1\n            abc = 23 << 1\n            def = -105 >> 1\n            ghi = 23 << 2\n            jkl = 1 >>> 31\n            mno = 1 << 64\n            pqr = 1 >> 2\n            stu = -2 >> 4\n            vwx = low >> 1\n            yz = low >>> 1\n        `)\n\t\ttest(\"abc\", 46)\n\t\ttest(\"def\", -53)\n\t\ttest(\"ghi\", 92)\n\t\ttest(\"jkl\", 0)\n\t\ttest(\"mno\", 1)\n\t\ttest(\"pqr\", 0)\n\t\ttest(\"stu\", -1)\n\t\ttest(\"vwx\", -1073741824)\n\t\ttest(\"yz\", 1073741824)\n\t})\n}\n\nfunc TestParenthesizing(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            abc = 1 + 2 * 3\n            def = (1 + 2) * 3\n            ghi = !(false || true)\n            jkl = !false || true\n        `)\n\t\ttest(\"abc\", 7)\n\t\ttest(\"def\", 9)\n\t\ttest(\"ghi\", false)\n\t\ttest(\"jkl\", true)\n\t})\n}\n\nfunc Test_instanceof(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            abc = {} instanceof Object;\n        `, true)\n\n\t\ttest(`\n            abc = \"abc\" instanceof Object;\n        `, false)\n\n\t\ttest(`raise:\n            abc = {} instanceof \"abc\";\n        `, \"TypeError: invalid kind String for instanceof (expected object)\")\n\n\t\ttest(`raise:\n            \"xyzzy\" instanceof Math;\n        `, \"TypeError: Object.hasInstance not callable\")\n\t})\n}\n\nfunc TestIn(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            abc = \"prototype\" in Object;\n            def = \"xyzzy\" in Object;\n            [ abc, def ];\n        `, \"true,false\")\n\t})\n}\n\nfunc Test_new(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            abc = new Boolean;\n            def = new Boolean(1);\n            [ abc, def ];\n        `, \"false,true\")\n\t})\n}\n\nfunc TestNewFunction(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            new Function(\"return 11\")()\n        `, 11)\n\n\t\ttest(`\n            abc = 10\n            new Function(\"abc += 1\")()\n            abc\n        `, 11)\n\n\t\ttest(`\n            new Function(\"a\", \"b\", \"c\", \"return b + 2\")(10, 11, 12)\n        `, 13)\n\n\t\ttest(`raise:\n            new 1\n        `, \"TypeError: 1 is not a function\")\n\n\t\t// TODO Better error reporting: new this\n\t\ttest(`raise:\n            new this\n        `, \"TypeError: [object environment] is not a function\")\n\n\t\ttest(`raise:\n            new {}\n        `, \"TypeError: [object Object] is not a function\")\n\t})\n}\n\nfunc TestNewPrototype(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            abc = { 'xyzzy': 'Nothing happens.' }\n            function Xyzzy(){}\n            Xyzzy.prototype = abc;\n            (new Xyzzy()).xyzzy\n        `, \"Nothing happens.\")\n\t})\n}\n\nfunc TestBlock(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            var abc=0;\n            var ghi;\n            def: {\n                do {\n                    abc++;\n                    if (!(abc < 10)) {\n                        break def;\n                        ghi = \"ghi\";\n                    }\n                } while (true);\n            }\n            [ abc,ghi ];\n        `, \"10,\")\n\t})\n}\n\nfunc Test_toString(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            [undefined+\"\"]\n        `, \"undefined\")\n\t})\n}\n\nfunc TestEvaluationOrder(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            var abc = 0;\n            abc < (abc = 1) === true;\n        `, true)\n\t})\n}\n\nfunc TestClone(t *testing.T) {\n\ttt(t, func() {\n\t\tvm1 := New()\n\t\t_, err := vm1.Run(`\n            var abc = 1;\n        `)\n\t\trequire.NoError(t, err)\n\n\t\tvm2 := vm1.clone()\n\t\t_, err = vm1.Run(`\n            abc += 2;\n        `)\n\t\trequire.NoError(t, err)\n\t\t_, err = vm2.Run(`\n            abc += 4;\n        `)\n\t\trequire.NoError(t, err)\n\n\t\tis(vm1.getValue(\"abc\"), 3)\n\t\tis(vm2.getValue(\"abc\"), 5)\n\t})\n}\n\nfunc Test_debugger(t *testing.T) {\n\ttt(t, func() {\n\t\tcalled := false\n\n\t\tvm := New()\n\t\tvm.SetDebuggerHandler(func(o *Otto) {\n\t\t\tis(o, vm)\n\t\t\tcalled = true\n\t\t})\n\n\t\t_, err := vm.Run(`debugger`)\n\t\trequire.NoError(t, err)\n\t\tis(called, true)\n\t})\n\n\ttt(t, func() {\n\t\tcalled := false\n\n\t\tvm := New()\n\t\tvm.SetDebuggerHandler(func(o *Otto) {\n\t\t\tis(o, vm)\n\t\t\tcalled = true\n\t\t})\n\n\t\t_, err := vm.Run(`null`)\n\t\trequire.NoError(t, err)\n\t\tis(called, false)\n\t})\n\n\ttt(t, func() {\n\t\tvm := New()\n\n\t\t_, err := vm.Run(`debugger`)\n\t\trequire.NoError(t, err)\n\t})\n}\n\nfunc Test_random(t *testing.T) {\n\ttt(t, func() {\n\t\tvm := New()\n\t\tvm.SetRandomSource(func() float64 { return 1 })\n\n\t\tr, err := vm.Run(`Math.random()`)\n\t\trequire.NoError(t, err)\n\t\tf, err := r.ToFloat()\n\t\trequire.NoError(t, err)\n\t\tis(f, 1)\n\t})\n\n\ttt(t, func() {\n\t\tvm := New()\n\n\t\tr1, err := vm.Run(`Math.random()`)\n\t\trequire.NoError(t, err)\n\t\tf1, err := r1.ToFloat()\n\t\trequire.NoError(t, err)\n\n\t\tr2, err := vm.Run(`Math.random()`)\n\t\trequire.NoError(t, err)\n\t\tf2, err := r2.ToFloat()\n\t\trequire.NoError(t, err)\n\n\t\tis(f1 == f2, false)\n\t})\n}\n\nfunc Test_stringArray(t *testing.T) {\n\tgetStrings := func() []string {\n\t\treturn []string{\"these\", \"are\", \"strings\"}\n\t}\n\tconcatStrings := func(a []string) string {\n\t\tif len(a) == 0 {\n\t\t\treturn \"\"\n\t\t}\n\t\tr := a[0]\n\t\tfor i := 1; i < len(a); i++ {\n\t\t\tr += \" \"\n\t\t\tr += a[i]\n\t\t}\n\t\treturn r\n\t}\n\ttt(t, func() {\n\t\tvm := New()\n\t\terr := vm.Set(\"getStrings\", getStrings)\n\t\trequire.NoError(t, err)\n\t\terr = vm.Set(\"concatStrings\", concatStrings)\n\t\trequire.NoError(t, err)\n\t\tr1, err := vm.Run(`var a = getStrings(); concatStrings(a)`)\n\t\trequire.NoError(t, err)\n\t\tis(r1, \"these are strings\")\n\t})\n}\n\ntype goByteArrayWithMethodsTest [8]byte\n\nfunc (g goByteArrayWithMethodsTest) S() string    { return string(g[:]) }\nfunc (g goByteArrayWithMethodsTest) F(i int) byte { return g[i] }\n\nfunc Test_goByteArrayWithMethods_typeof_S(t *testing.T) {\n\ta := goByteArrayWithMethodsTest{97, 98, 99, 100, 101, 102, 103, 104}\n\n\ttt(t, func() {\n\t\ttest, vm := test()\n\t\tvm.Set(\"a\", a)\n\t\tis(test(\"typeof a.S\").export(), \"function\")\n\t})\n}\n\nfunc Test_goByteArrayWithMethods_S(t *testing.T) {\n\ta := goByteArrayWithMethodsTest{97, 98, 99, 100, 101, 102, 103, 104}\n\n\ttt(t, func() {\n\t\ttest, vm := test()\n\t\tvm.Set(\"a\", a)\n\t\tis(test(\"a.S()\").export(), \"abcdefgh\")\n\t})\n}\n\nfunc Test_goByteArrayWithMethods_F0(t *testing.T) {\n\ta := goByteArrayWithMethodsTest{97, 98, 99, 100, 101, 102, 103, 104}\n\n\ttt(t, func() {\n\t\ttest, vm := test()\n\t\tvm.Set(\"a\", a)\n\t\tis(test(\"a.F(0)\").export(), 97)\n\t})\n}\n\nfunc Test_goByteArrayWithMethods_F1(t *testing.T) {\n\ta := goByteArrayWithMethodsTest{97, 98, 99, 100, 101, 102, 103, 104}\n\n\ttt(t, func() {\n\t\ttest, vm := test()\n\t\tvm.Set(\"a\", a)\n\t\tis(test(\"a.F(1)\").export(), 98)\n\t})\n}\n"
  },
  {
    "path": "scope.go",
    "content": "package otto\n\n// An ECMA-262 ExecutionContext.\ntype scope struct {\n\tlexical  stasher\n\tvariable stasher\n\tthis     *object\n\touter    *scope\n\tframe    frame\n\tdepth    int\n\teval     bool\n}\n\nfunc newScope(lexical stasher, variable stasher, this *object) *scope {\n\treturn &scope{\n\t\tlexical:  lexical,\n\t\tvariable: variable,\n\t\tthis:     this,\n\t}\n}\n"
  },
  {
    "path": "script.go",
    "content": "package otto\n\nimport (\n\t\"bytes\"\n\t\"encoding/gob\"\n\t\"errors\"\n)\n\n// ErrVersion is an error which represents a version mismatch.\nvar ErrVersion = errors.New(\"version mismatch\")\n\nvar scriptVersion = \"2014-04-13/1\"\n\n// Script is a handle for some (reusable) JavaScript.\n// Passing a Script value to a run method will evaluate the JavaScript.\ntype Script struct {\n\tversion  string\n\tprogram  *nodeProgram\n\tfilename string\n\tsrc      string\n}\n\n// Compile will parse the given source and return a Script value or nil and\n// an error if there was a problem during compilation.\n//\n//\tscript, err := vm.Compile(\"\", `var abc; if (!abc) abc = 0; abc += 2; abc;`)\n//\tvm.Run(script)\nfunc (o *Otto) Compile(filename string, src interface{}) (*Script, error) {\n\treturn o.CompileWithSourceMap(filename, src, nil)\n}\n\n// CompileWithSourceMap does the same thing as Compile, but with the obvious\n// difference of applying a source map.\nfunc (o *Otto) CompileWithSourceMap(filename string, src, sm interface{}) (*Script, error) {\n\tprogram, err := o.runtime.parse(filename, src, sm)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tnode := cmplParse(program)\n\tscript := &Script{\n\t\tversion:  scriptVersion,\n\t\tprogram:  node,\n\t\tfilename: filename,\n\t\tsrc:      program.File.Source(),\n\t}\n\n\treturn script, nil\n}\n\nfunc (s *Script) String() string {\n\treturn \"// \" + s.filename + \"\\n\" + s.src\n}\n\n// MarshalBinary will marshal a script into a binary form. A marshalled script\n// that is later unmarshalled can be executed on the same version of the otto runtime.\n//\n// The binary format can change at any time and should be considered unspecified and opaque.\nfunc (s *Script) marshalBinary() ([]byte, error) {\n\tvar bfr bytes.Buffer\n\tencoder := gob.NewEncoder(&bfr)\n\terr := encoder.Encode(s.version)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\terr = encoder.Encode(s.program)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\terr = encoder.Encode(s.filename)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\terr = encoder.Encode(s.src)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn bfr.Bytes(), nil\n}\n\n// UnmarshalBinary will vivify a marshalled script into something usable. If the script was\n// originally marshalled on a different version of the otto runtime, then this method\n// will return an error.\n//\n// The binary format can change at any time and should be considered unspecified and opaque.\nfunc (s *Script) unmarshalBinary(data []byte) (err error) { //nolint:nonamedreturns\n\tdecoder := gob.NewDecoder(bytes.NewReader(data))\n\tdefer func() {\n\t\tif err != nil {\n\t\t\ts.version = \"\"\n\t\t\ts.program = nil\n\t\t\ts.filename = \"\"\n\t\t\ts.src = \"\"\n\t\t}\n\t}()\n\tif err = decoder.Decode(&s.version); err != nil {\n\t\treturn err\n\t}\n\tif s.version != scriptVersion {\n\t\treturn ErrVersion\n\t}\n\tif err = decoder.Decode(&s.program); err != nil {\n\t\treturn err\n\t}\n\tif err = decoder.Decode(&s.filename); err != nil {\n\t\treturn err\n\t}\n\treturn decoder.Decode(&s.src)\n}\n"
  },
  {
    "path": "script_test.go",
    "content": "package otto\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestScript(t *testing.T) {\n\ttt(t, func() {\n\t\tvm := New()\n\n\t\tscript, err := vm.Compile(\"xyzzy\", `var abc; if (!abc) abc = 0; abc += 2; abc;`)\n\t\trequire.NoError(t, err)\n\n\t\tstr := script.String()\n\t\tis(str, \"// xyzzy\\nvar abc; if (!abc) abc = 0; abc += 2; abc;\")\n\n\t\tval, err := vm.Run(script)\n\t\trequire.NoError(t, err)\n\t\tis(val, 2)\n\n\t\t// TODO(steve): Fix the underlying issues as to why this returns early.\n\t\tif true {\n\t\t\treturn\n\t\t}\n\n\t\ttmp, err := script.marshalBinary()\n\t\trequire.NoError(t, err)\n\t\tis(len(tmp), 1228)\n\n\t\t{\n\t\t\tscript2 := &Script{}\n\t\t\terr = script2.unmarshalBinary(tmp)\n\t\t\trequire.NoError(t, err)\n\n\t\t\tis(script2.String(), str)\n\n\t\t\tval, err = vm.Run(script2)\n\t\t\trequire.NoError(t, err)\n\t\t\tis(val, 4)\n\n\t\t\ttmp, err = script2.marshalBinary()\n\t\t\trequire.NoError(t, err)\n\t\t\tis(len(tmp), 1228)\n\t\t}\n\n\t\t{\n\t\t\tscript2 := &Script{}\n\t\t\terr = script2.unmarshalBinary(tmp)\n\t\t\trequire.NoError(t, err)\n\n\t\t\tis(script2.String(), str)\n\n\t\t\tval2, err2 := vm.Run(script2)\n\t\t\trequire.NoError(t, err2)\n\t\t\tis(val2, 6)\n\n\t\t\ttmp, err2 = script2.marshalBinary()\n\t\t\trequire.NoError(t, err2)\n\t\t\tis(len(tmp), 1228)\n\t\t}\n\n\t\t{\n\t\t\tversion := scriptVersion\n\t\t\tscriptVersion = \"bogus\"\n\n\t\t\tscript2 := &Script{}\n\t\t\terr = script2.unmarshalBinary(tmp)\n\t\t\tis(err, \"version mismatch\")\n\n\t\t\tis(script2.String(), \"// \\n\")\n\t\t\tis(script2.version, \"\")\n\t\t\tis(script2.program == nil, true)\n\t\t\tis(script2.filename, \"\")\n\t\t\tis(script2.src, \"\")\n\n\t\t\tscriptVersion = version\n\t\t}\n\t})\n}\n\nfunc TestFunctionCall_CallerLocation(t *testing.T) {\n\ttt(t, func() {\n\t\tvm := New()\n\t\terr := vm.Set(\"loc\", func(call FunctionCall) Value {\n\t\t\treturn toValue(call.CallerLocation())\n\t\t})\n\t\trequire.NoError(t, err)\n\t\tscript, err := vm.Compile(\"somefile.js\", `var where = loc();`)\n\t\trequire.NoError(t, err)\n\t\t_, err = vm.Run(script)\n\t\trequire.NoError(t, err)\n\t\twhere, err := vm.Get(\"where\")\n\t\trequire.NoError(t, err)\n\t\tis(where, \"somefile.js:1:13\")\n\t})\n}\n"
  },
  {
    "path": "sourcemap_test.go",
    "content": "package otto\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nconst (\n\ttestSourcemapCodeOriginal  = \"function functionA(argA, argB) {\\n  functionB(argA, argB);\\n}\\n\\nfunction functionB(argA, argB) {\\n  functionExternal(argA, argB);\\n}\"\n\ttestSourcemapCodeMangled   = \"function functionA(argA,argB){functionB(argA,argB)}function functionB(argA,argB){functionExternal(argA,argB)}\"\n\ttestSourcemapContent       = `{\"version\":3,\"sources\":[\"hello.js\"],\"names\":[\"functionA\",\"argA\",\"argB\",\"functionB\",\"functionExternal\"],\"mappings\":\"AAAA,QAASA,WAAUC,KAAMC,MACvBC,UAAUF,KAAMC,MAGlB,QAASC,WAAUF,KAAMC,MACvBE,iBAAiBH,KAAMC\"}`\n\ttestSourcemapInline        = \"function functionA(argA,argB){functionB(argA,argB)}function functionB(argA,argB){functionExternal(argA,argB)}\\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImhlbGxvLmpzIl0sIm5hbWVzIjpbImZ1bmN0aW9uQSIsImFyZ0EiLCJhcmdCIiwiZnVuY3Rpb25CIiwiZnVuY3Rpb25FeHRlcm5hbCJdLCJtYXBwaW5ncyI6IkFBQUEsUUFBU0EsV0FBVUMsS0FBTUMsTUFDdkJDLFVBQVVGLEtBQU1DLE1BR2xCLFFBQVNDLFdBQVVGLEtBQU1DLE1BQ3ZCRSxpQkFBaUJILEtBQU1DIn0=\"\n\ttestSourcemapOriginalStack = \"ReferenceError: 'functionExternal' is not defined\\n    at functionB (hello.js:6:3)\\n    at functionA (hello.js:2:3)\\n    at <anonymous>:1:1\\n\"\n\ttestSourcemapMangledStack  = \"ReferenceError: 'functionExternal' is not defined\\n    at functionB (hello.js:1:82)\\n    at functionA (hello.js:1:31)\\n    at <anonymous>:1:1\\n\"\n\ttestSourcemapMappedStack   = \"ReferenceError: 'functionExternal' is not defined\\n    at functionB (hello.js:6:2)\\n    at functionA (hello.js:2:2)\\n    at <anonymous>:1:1\\n\"\n)\n\nfunc TestSourceMapOriginalWithNoSourcemap(t *testing.T) {\n\ttt(t, func() {\n\t\tvm := New()\n\n\t\ts, err := vm.Compile(\"hello.js\", testSourcemapCodeOriginal)\n\t\trequire.NoError(t, err)\n\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(t, err)\n\n\t\t_, err = vm.Run(`functionA()`)\n\t\trequire.Error(t, err)\n\t\tvar oerr *Error\n\t\trequire.ErrorAs(t, err, &oerr)\n\t\trequire.Equal(t, testSourcemapOriginalStack, oerr.String())\n\t})\n}\n\nfunc TestSourceMapMangledWithNoSourcemap(t *testing.T) {\n\ttt(t, func() {\n\t\tvm := New()\n\n\t\ts, err := vm.Compile(\"hello.js\", testSourcemapCodeMangled)\n\t\trequire.NoError(t, err)\n\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(t, err)\n\n\t\t_, err = vm.Run(`functionA()`)\n\t\trequire.Error(t, err)\n\t\tvar oerr *Error\n\t\trequire.ErrorAs(t, err, &oerr)\n\t\trequire.Equal(t, testSourcemapMangledStack, oerr.String())\n\t})\n}\n\nfunc TestSourceMapMangledWithSourcemap(t *testing.T) {\n\ttt(t, func() {\n\t\tvm := New()\n\n\t\ts, err := vm.CompileWithSourceMap(\"hello.js\", testSourcemapCodeMangled, testSourcemapContent)\n\t\trequire.NoError(t, err)\n\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(t, err)\n\n\t\t_, err = vm.Run(`functionA()`)\n\t\trequire.Error(t, err)\n\t\tvar oerr *Error\n\t\trequire.ErrorAs(t, err, &oerr)\n\t\trequire.Equal(t, testSourcemapMappedStack, oerr.String())\n\t})\n}\n\nfunc TestSourceMapMangledWithInlineSourcemap(t *testing.T) {\n\ttt(t, func() {\n\t\tvm := New()\n\n\t\ts, err := vm.CompileWithSourceMap(\"hello.js\", testSourcemapInline, nil)\n\t\trequire.NoError(t, err)\n\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(t, err)\n\n\t\t_, err = vm.Run(`functionA()`)\n\t\trequire.Error(t, err)\n\t\tvar oerr *Error\n\t\trequire.ErrorAs(t, err, &oerr)\n\t\trequire.Equal(t, testSourcemapMappedStack, oerr.String())\n\t})\n}\n\nfunc TestSourceMapContextPosition(t *testing.T) {\n\ttt(t, func() {\n\t\tvm := New()\n\n\t\ts, err := vm.CompileWithSourceMap(\"hello.js\", testSourcemapCodeMangled, testSourcemapContent)\n\t\trequire.NoError(t, err)\n\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(t, err)\n\n\t\terr = vm.Set(\"functionExternal\", func(c FunctionCall) Value {\n\t\t\tctx := c.Otto.Context()\n\n\t\t\tis(ctx.Filename, \"hello.js\")\n\t\t\tis(ctx.Line, 6)\n\t\t\tis(ctx.Column, 2)\n\n\t\t\treturn UndefinedValue()\n\t\t})\n\t\trequire.NoError(t, err)\n\n\t\t_, err = vm.Run(`functionA()`)\n\t\trequire.NoError(t, err)\n\t})\n}\n\nfunc TestSourceMapContextStacktrace(t *testing.T) {\n\ttt(t, func() {\n\t\tvm := New()\n\n\t\ts, err := vm.CompileWithSourceMap(\"hello.js\", testSourcemapCodeMangled, testSourcemapContent)\n\t\trequire.NoError(t, err)\n\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(t, err)\n\n\t\terr = vm.Set(\"functionExternal\", func(c FunctionCall) Value {\n\t\t\tctx := c.Otto.Context()\n\n\t\t\tis(ctx.Stacktrace, []string{\n\t\t\t\t\"functionB (hello.js:6:2)\",\n\t\t\t\t\"functionA (hello.js:2:2)\",\n\t\t\t\t\"<anonymous>:1:1\",\n\t\t\t})\n\n\t\t\treturn UndefinedValue()\n\t\t})\n\t\trequire.NoError(t, err)\n\n\t\t_, err = vm.Run(`functionA()`)\n\t\trequire.NoError(t, err)\n\t})\n}\n"
  },
  {
    "path": "stash.go",
    "content": "package otto\n\nimport (\n\t\"fmt\"\n)\n\n// stasher is implemented by types which can stash data.\ntype stasher interface {\n\thasBinding(name string) bool                            //\n\tcreateBinding(name string, deletable bool, value Value) // CreateMutableBinding\n\tsetBinding(name string, value Value, strict bool)       // SetMutableBinding\n\tgetBinding(name string, throw bool) Value               // GetBindingValue\n\tdeleteBinding(name string) bool                         //\n\tsetValue(name string, value Value, throw bool)          // createBinding + setBinding\n\n\touter() stasher\n\truntime() *runtime\n\n\tnewReference(name string, strict bool, atv at) referencer\n\n\tclone(cloner *cloner) stasher\n}\n\ntype objectStash struct {\n\trt     *runtime\n\toutr   stasher\n\tobject *object\n}\n\nfunc (s *objectStash) runtime() *runtime {\n\treturn s.rt\n}\n\nfunc (rt *runtime) newObjectStash(obj *object, outer stasher) *objectStash {\n\tif obj == nil {\n\t\tobj = rt.newBaseObject()\n\t\tobj.class = \"environment\"\n\t}\n\treturn &objectStash{\n\t\trt:     rt,\n\t\toutr:   outer,\n\t\tobject: obj,\n\t}\n}\n\nfunc (s *objectStash) clone(c *cloner) stasher {\n\tout, exists := c.objectStash(s)\n\tif exists {\n\t\treturn out\n\t}\n\t*out = objectStash{\n\t\tc.runtime,\n\t\tc.stash(s.outr),\n\t\tc.object(s.object),\n\t}\n\treturn out\n}\n\nfunc (s *objectStash) hasBinding(name string) bool {\n\treturn s.object.hasProperty(name)\n}\n\nfunc (s *objectStash) createBinding(name string, deletable bool, value Value) {\n\tif s.object.hasProperty(name) {\n\t\tpanic(hereBeDragons())\n\t}\n\tmode := propertyMode(0o111)\n\tif !deletable {\n\t\tmode = propertyMode(0o110)\n\t}\n\t// TODO False?\n\ts.object.defineProperty(name, value, mode, false)\n}\n\nfunc (s *objectStash) setBinding(name string, value Value, strict bool) {\n\ts.object.put(name, value, strict)\n}\n\nfunc (s *objectStash) setValue(name string, value Value, throw bool) {\n\tif !s.hasBinding(name) {\n\t\ts.createBinding(name, true, value) // Configurable by default\n\t} else {\n\t\ts.setBinding(name, value, throw)\n\t}\n}\n\nfunc (s *objectStash) getBinding(name string, throw bool) Value {\n\tif s.object.hasProperty(name) {\n\t\treturn s.object.get(name)\n\t}\n\tif throw { // strict?\n\t\tpanic(s.rt.panicReferenceError(\"Not Defined\", name))\n\t}\n\treturn Value{}\n}\n\nfunc (s *objectStash) deleteBinding(name string) bool {\n\treturn s.object.delete(name, false)\n}\n\nfunc (s *objectStash) outer() stasher {\n\treturn s.outr\n}\n\nfunc (s *objectStash) newReference(name string, strict bool, atv at) referencer {\n\treturn newPropertyReference(s.rt, s.object, name, strict, atv)\n}\n\ntype dclStash struct {\n\trt       *runtime\n\toutr     stasher\n\tproperty map[string]dclProperty\n}\n\ntype dclProperty struct {\n\tvalue     Value\n\tmutable   bool\n\tdeletable bool\n\treadable  bool\n}\n\nfunc (rt *runtime) newDeclarationStash(outer stasher) *dclStash {\n\treturn &dclStash{\n\t\trt:       rt,\n\t\toutr:     outer,\n\t\tproperty: map[string]dclProperty{},\n\t}\n}\n\nfunc (s *dclStash) clone(c *cloner) stasher {\n\tout, exists := c.dclStash(s)\n\tif exists {\n\t\treturn out\n\t}\n\tprop := make(map[string]dclProperty, len(s.property))\n\tfor index, value := range s.property {\n\t\tprop[index] = c.dclProperty(value)\n\t}\n\t*out = dclStash{\n\t\tc.runtime,\n\t\tc.stash(s.outr),\n\t\tprop,\n\t}\n\treturn out\n}\n\nfunc (s *dclStash) hasBinding(name string) bool {\n\t_, exists := s.property[name]\n\treturn exists\n}\n\nfunc (s *dclStash) runtime() *runtime {\n\treturn s.rt\n}\n\nfunc (s *dclStash) createBinding(name string, deletable bool, value Value) {\n\tif _, exists := s.property[name]; exists {\n\t\tpanic(fmt.Errorf(\"createBinding: %s: already exists\", name))\n\t}\n\ts.property[name] = dclProperty{\n\t\tvalue:     value,\n\t\tmutable:   true,\n\t\tdeletable: deletable,\n\t\treadable:  false,\n\t}\n}\n\nfunc (s *dclStash) setBinding(name string, value Value, strict bool) {\n\tprop, exists := s.property[name]\n\tif !exists {\n\t\tpanic(fmt.Errorf(\"setBinding: %s: missing\", name))\n\t}\n\tif prop.mutable {\n\t\tprop.value = value\n\t\ts.property[name] = prop\n\t} else {\n\t\ts.rt.typeErrorResult(strict)\n\t}\n}\n\nfunc (s *dclStash) setValue(name string, value Value, throw bool) {\n\tif !s.hasBinding(name) {\n\t\ts.createBinding(name, false, value) // NOT deletable by default\n\t} else {\n\t\ts.setBinding(name, value, throw)\n\t}\n}\n\n// FIXME This is called a __lot__.\nfunc (s *dclStash) getBinding(name string, throw bool) Value {\n\tprop, exists := s.property[name]\n\tif !exists {\n\t\tpanic(fmt.Errorf(\"getBinding: %s: missing\", name))\n\t}\n\tif !prop.mutable && !prop.readable {\n\t\tif throw { // strict?\n\t\t\tpanic(s.rt.panicTypeError(\"getBinding property %s not mutable and not readable\", name))\n\t\t}\n\t\treturn Value{}\n\t}\n\treturn prop.value\n}\n\nfunc (s *dclStash) deleteBinding(name string) bool {\n\tprop, exists := s.property[name]\n\tif !exists {\n\t\treturn true\n\t}\n\tif !prop.deletable {\n\t\treturn false\n\t}\n\tdelete(s.property, name)\n\treturn true\n}\n\nfunc (s *dclStash) outer() stasher {\n\treturn s.outr\n}\n\nfunc (s *dclStash) newReference(name string, strict bool, _ at) referencer {\n\treturn &stashReference{\n\t\tname: name,\n\t\tbase: s,\n\t}\n}\n\n// ========\n// _fnStash\n// ========\n\ntype fnStash struct {\n\tdclStash\n\targuments           *object\n\tindexOfArgumentName map[string]string\n}\n\nfunc (rt *runtime) newFunctionStash(outer stasher) *fnStash {\n\treturn &fnStash{\n\t\tdclStash: dclStash{\n\t\t\trt:       rt,\n\t\t\toutr:     outer,\n\t\t\tproperty: map[string]dclProperty{},\n\t\t},\n\t}\n}\n\nfunc (s *fnStash) clone(c *cloner) stasher {\n\tout, exists := c.fnStash(s)\n\tif exists {\n\t\treturn out\n\t}\n\tdclStash := s.dclStash.clone(c).(*dclStash)\n\tindex := make(map[string]string, len(s.indexOfArgumentName))\n\tfor name, value := range s.indexOfArgumentName {\n\t\tindex[name] = value\n\t}\n\t*out = fnStash{\n\t\tdclStash:            *dclStash,\n\t\targuments:           c.object(s.arguments),\n\t\tindexOfArgumentName: index,\n\t}\n\treturn out\n}\n\n// getStashProperties returns the properties from stash.\nfunc getStashProperties(stash stasher) []string {\n\tswitch vars := stash.(type) {\n\tcase *dclStash:\n\t\tkeys := make([]string, 0, len(vars.property))\n\t\tfor k := range vars.property {\n\t\t\tkeys = append(keys, k)\n\t\t}\n\t\treturn keys\n\tcase *fnStash:\n\t\tkeys := make([]string, 0, len(vars.property))\n\t\tfor k := range vars.property {\n\t\t\tkeys = append(keys, k)\n\t\t}\n\t\treturn keys\n\tcase *objectStash:\n\t\tkeys := make([]string, 0, len(vars.object.property))\n\t\tfor k := range vars.object.property {\n\t\t\tkeys = append(keys, k)\n\t\t}\n\t\treturn keys\n\tdefault:\n\t\tpanic(\"unknown stash type\")\n\t}\n}\n"
  },
  {
    "path": "string_test.go",
    "content": "package otto\n\nimport (\n\t\"testing\"\n\n\t\"github.com/stretchr/testify/require\"\n)\n\nfunc TestString(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            abc = (new String(\"xyzzy\")).length;\n            def = new String().length;\n            ghi = new String(\"Nothing happens.\").length;\n        `)\n\t\ttest(\"abc\", 5)\n\t\ttest(\"def\", 0)\n\t\ttest(\"ghi\", 16)\n\t\ttest(`\"\".length`, 0)\n\t\ttest(`\"a\\uFFFFbc\".length`, 4)\n\t\ttest(`String(+0)`, \"0\")\n\t\ttest(`String(-0)`, \"0\")\n\t\ttest(`\"\"+-0`, \"0\")\n\t\ttest(`\n            var abc = Object.getOwnPropertyDescriptor(String, \"prototype\");\n            [   [ typeof String.prototype ],\n                [ abc.writable, abc.enumerable, abc.configurable ] ];\n        `, \"object,false,false,false\")\n\t})\n}\n\nfunc TestString_charAt(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            abc = \"xyzzy\".charAt(0)\n            def = \"xyzzy\".charAt(11)\n        `)\n\t\ttest(\"abc\", \"x\")\n\t\ttest(\"def\", \"\")\n\t})\n}\n\nfunc TestString_charCodeAt(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\n            abc = \"xyzzy\".charCodeAt(0)\n            def = \"xyzzy\".charCodeAt(11)\n        `)\n\t\ttest(\"abc\", 120)\n\t\ttest(\"def\", naN)\n\t})\n}\n\nfunc TestString_fromCharCode(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`String.fromCharCode()`, []uint16{})\n\t\ttest(`String.fromCharCode(88, 121, 122, 122, 121)`, []uint16{88, 121, 122, 122, 121}) // FIXME terst, Double-check these...\n\t\ttest(`String.fromCharCode(\"88\", 121, 122, 122.05, 121)`, []uint16{88, 121, 122, 122, 121})\n\t\ttest(`String.fromCharCode(\"88\", 121, 122, NaN, 121)`, []uint16{88, 121, 122, 0, 121})\n\t\ttest(`String.fromCharCode(\"0x21\")`, []uint16{33})\n\t\ttest(`String.fromCharCode(-1).charCodeAt(0)`, 65535)\n\t\ttest(`String.fromCharCode(65535).charCodeAt(0)`, 65535)\n\t\ttest(`String.fromCharCode(65534).charCodeAt(0)`, 65534)\n\t\ttest(`String.fromCharCode(4294967295).charCodeAt(0)`, 65535)\n\t\ttest(`String.fromCharCode(4294967294).charCodeAt(0)`, 65534)\n\t\ttest(`String.fromCharCode(0x0024) === \"$\"`, true)\n\t})\n}\n\nfunc TestString_concat(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\"\".concat()`, \"\")\n\t\ttest(`\"\".concat(\"abc\", \"def\")`, \"abcdef\")\n\t\ttest(`\"\".concat(\"abc\", undefined, \"def\")`, \"abcundefineddef\")\n\t})\n}\n\nfunc TestString_indexOf(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\"\".indexOf(\"\")`, 0)\n\t\ttest(`\"\".indexOf(\"\", 11)`, 0)\n\t\ttest(`\"abc\".indexOf(\"\")`, 0)\n\t\ttest(`\"abc\".indexOf(\"\", 11)`, 3)\n\t\ttest(`\"abc\".indexOf(\"a\")`, 0)\n\t\ttest(`\"abc\".indexOf(\"bc\")`, 1)\n\t\ttest(`\"abc\".indexOf(\"bc\", 11)`, -1)\n\n\t\ttest(`\"uñiçode\".indexOf(\"ñ\")`, 1)\n\t\ttest(`\"uñiçode\".indexOf(\"ñ\", 11)`, -1)\n\t\ttest(`\"uññiçode\".indexOf(\"ç\")`, 4)\n\t\ttest(`\"uññiçode\".indexOf(\"ç\", 11)`, -1)\n\n\t\ttest(`\"$$abcdabcd\".indexOf(\"ab\", function(){return -Infinity;}())`, 2)\n\t\ttest(`\"$$abcdabcd\".indexOf(\"ab\", function(){return NaN;}())`, 2)\n\n\t\ttest(`\n            var abc = {toString:function(){return \"\\u0041B\";}}\n            var def = {valueOf:function(){return true;}}\n            var ghi = \"ABB\\u0041BABAB\";\n            var jkl;\n            with(ghi) {\n                jkl = indexOf(abc, def);\n            }\n            jkl;\n        `, 3)\n\t})\n}\n\nfunc TestString_lastIndexOf(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\"\".lastIndexOf(\"\")`, 0)\n\t\ttest(`\"\".lastIndexOf(\"\", 11)`, 0)\n\t\ttest(`\"abc\".lastIndexOf(\"\")`, 3)\n\t\ttest(`\"abc\".lastIndexOf(\"\", 11)`, 3)\n\t\ttest(`\"abc\".lastIndexOf(\"a\")`, 0)\n\t\ttest(`\"abc\".lastIndexOf(\"bc\")`, 1)\n\t\ttest(`\"abc\".lastIndexOf(\"bc\", 11)`, 1)\n\t\ttest(`\"abc\".lastIndexOf(\"bc\", 0)`, -1)\n\t\ttest(`\"abc\".lastIndexOf(\"abcabcabc\", 2)`, -1)\n\t\ttest(`\"abc\".lastIndexOf(\"abc\", 0)`, 0)\n\t\ttest(`\"abc\".lastIndexOf(\"abc\", 1)`, 0)\n\t\ttest(`\"abc\".lastIndexOf(\"abc\", 2)`, 0)\n\t\ttest(`\"abc\".lastIndexOf(\"abc\", 3)`, 0)\n\n\t\ttest(`\"uñiçodeñ\".lastIndexOf(\"ñ\")`, 7)\n\t\ttest(`\"uñiçode\".lastIndexOf(\"ñ\")`, 1)\n\t\ttest(`\"uñiçodeñ\".lastIndexOf(\"ç\")`, 3)\n\t\ttest(`\"uñiçodeñ\".lastIndexOf(\"aç\")`, -1)\n\n\t\ttest(`\n            abc = new Object(true);\n            abc.lastIndexOf = String.prototype.lastIndexOf;\n            abc.lastIndexOf(true, false);\n        `, 0)\n\t})\n}\n\nfunc TestString_match(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\"abc____abc_abc___\".match(/__abc/)`, \"__abc\")\n\t\ttest(`\"abc___abc_abc__abc__abc\".match(/abc/g)`, \"abc,abc,abc,abc,abc\")\n\t\ttest(`\"abc____abc_abc___\".match(/__abc/g)`, \"__abc\")\n\t\ttest(`\n            abc = /abc/g\n            \"abc___abc_abc__abc__abc\".match(abc)\n        `, \"abc,abc,abc,abc,abc\")\n\t\ttest(`abc.lastIndex`, 23)\n\t})\n}\n\nfunc BenchmarkString_match(b *testing.B) {\n\tvm := New()\n\ts, _ := vm.Compile(\"test.js\", `\"abc____abc_abc___\".match(/__abc/g)`)\n\tfor i := 0; i < b.N; i++ {\n\t\t_, e := vm.Run(s)\n\t\tif e != nil {\n\t\t\tb.Error(e.Error())\n\t\t}\n\t}\n}\n\nfunc TestString_replace(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\"abc_abc\".replace(/abc/, \"$&123\")`, \"abc123_abc\")\n\t\ttest(`\"abc_abc\".replace(/abc/g, \"$&123\")`, \"abc123_abc123\")\n\t\ttest(`\"abc_abc_\".replace(/abc/g, \"$&123\")`, \"abc123_abc123_\")\n\t\ttest(`\"_abc_abc_\".replace(/abc/g, \"$&123\")`, \"_abc123_abc123_\")\n\t\ttest(`\"abc\".replace(/abc/, \"$&123\")`, \"abc123\")\n\t\ttest(`\"abc_\".replace(/abc/, \"$&123\")`, \"abc123_\")\n\t\ttest(\"\\\"^abc$\\\".replace(/abc/, \\\"$`def\\\")\", \"^^def$\")\n\t\ttest(\"\\\"^abc$\\\".replace(/abc/, \\\"def$`\\\")\", \"^def^$\")\n\t\ttest(`\"_abc_abd_\".replace(/ab(c|d)/g, \"$1\")`, \"_c_d_\")\n\t\ttest(`\n            \"_abc_abd_\".replace(/ab(c|d)/g, function(){\n            })\n        `, \"_undefined_undefined_\")\n\n\t\ttest(`\"b\".replace(/(a)?(b)?/, \"_$1_\")`, \"__\")\n\t\ttest(`\n            \"b\".replace(/(a)?(b)?/, function(a, b, c, d, e, f){\n                return [a, b, c, d, e, f]\n            })\n        `, \"b,,b,0,b,\")\n\n\t\ttest(`\n            var abc = 'She sells seashells by the seashore.';\n            var def = /sh/;\n            [ abc.replace(def, \"$'\" + 'sch') ];\n        `, \"She sells seaells by the seashore.schells by the seashore.\")\n\t})\n}\n\nfunc BenchmarkString_replace(b *testing.B) {\n\tvm := New()\n\ts, _ := vm.Compile(\"test.js\", `\"_abc_abd_\".replace(/ab(c|d)/g, \"$1\")`)\n\tfor i := 0; i < b.N; i++ {\n\t\t_, e := vm.Run(s)\n\t\tif e != nil {\n\t\t\tb.Error(e.Error())\n\t\t}\n\t}\n}\n\nfunc TestString_search(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\"abc\".search(/abc/)`, 0)\n\t\ttest(`\"abc\".search(/def/)`, -1)\n\t\ttest(`\"abc\".search(/c$/)`, 2)\n\t\ttest(`\"abc\".search(/$/)`, 3)\n\t})\n}\n\nfunc BenchmarkString_search(b *testing.B) {\n\tvm := New()\n\ts, _ := vm.Compile(\"test.js\", `\"abc\".search(/c$/)`)\n\tfor i := 0; i < b.N; i++ {\n\t\t_, e := vm.Run(s)\n\t\tif e != nil {\n\t\t\tb.Error(e.Error())\n\t\t}\n\t}\n}\n\nfunc TestString_split(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\"abc\".split(\"\", 1)`, \"a\")\n\t\ttest(`\"abc\".split(\"\", 2)`, \"a,b\")\n\t\ttest(`\"abc\".split(\"\", 3)`, \"a,b,c\")\n\t\ttest(`\"abc\".split(\"\", 4)`, \"a,b,c\")\n\t\ttest(`\"abc\".split(\"\", 11)`, \"a,b,c\")\n\t\ttest(`\"abc\".split(\"\", 0)`, \"\")\n\t\ttest(`\"abc\".split(\"\")`, \"a,b,c\")\n\n\t\ttest(`\"abc\".split(undefined)`, \"abc\")\n\n\t\ttest(`\"__1__3_1__2__\".split(\"_\")`, \",,1,,3,1,,2,,\")\n\n\t\ttest(`\"__1__3_1__2__\".split(/_/)`, \",,1,,3,1,,2,,\")\n\n\t\ttest(`\"ab\".split(/a*/)`, \",b\")\n\n\t\ttest(`_ = \"A<B>bold</B>and<CODE>coded</CODE>\".split(/<(\\/)?([^<>]+)>/)`, \"A,,B,bold,/,B,and,,CODE,coded,/,CODE,\")\n\t\ttest(`_.length`, 13)\n\t\ttest(`_[1] === undefined`, true)\n\t\ttest(`_[12] === \"\"`, true)\n\n\t\ttest(`\n            var abc = new String(\"one-1 two-2 three-3\");\n            var def = abc.split(new RegExp);\n\n            [ def.constructor === Array, abc.length, def.length, def.join('') ];\n        `, \"true,19,19,one-1 two-2 three-3\")\n\t})\n}\n\nfunc BenchmarkString_splitWithString(b *testing.B) {\n\tvm := New()\n\terr := vm.Set(\"data\", \"Lorem ipsum dolor sit amet, blandit nec elit. Ridiculous tortor wisi fusce vivamus\")\n\trequire.NoError(b, err)\n\ts, err := vm.Compile(\"test.js\", `data.split(\" \")`)\n\trequire.NoError(b, err)\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc BenchmarkString_splitWithRegex(b *testing.B) {\n\tvm := New()\n\terr := vm.Set(\"data\", \"Lorem ipsum dolor sit amet, blandit nec elit. Ridiculous tortor wisi fusce vivamus\")\n\trequire.NoError(b, err)\n\ts, err := vm.Compile(\"test.js\", `data.split(/ /)`)\n\trequire.NoError(b, err)\n\tfor i := 0; i < b.N; i++ {\n\t\t_, err = vm.Run(s)\n\t\trequire.NoError(b, err)\n\t}\n}\n\nfunc TestString_slice(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\"abc\".slice()`, \"abc\")\n\t\ttest(`\"abc\".slice(0)`, \"abc\")\n\t\ttest(`\"abc\".slice(0,11)`, \"abc\")\n\t\ttest(`\"abc\".slice(0,-1)`, \"ab\")\n\t\ttest(`\"abc\".slice(-1,11)`, \"c\")\n\t\ttest(`abc = \"abc\"; abc.slice(abc.length+1, 0)`, \"\")\n\t})\n}\n\nfunc TestString_length(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\"abc\".length`, 3)\n\t\ttest(`\"uñiçode\".length`, 7)\n\t\ttest(`\"😋\".length`, 2)\n\t})\n}\n\nfunc TestString_slice_unicode(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\"uñiçode\".slice()`, \"uñiçode\")\n\t\ttest(`\"uñiçode\".slice(0)`, \"uñiçode\")\n\t\ttest(`\"uñiçode\".slice(0,11)`, \"uñiçode\")\n\t\ttest(`\"uñiçode\".slice(0,-1)`, \"uñiçod\")\n\t\ttest(`\"uñiçode\".slice(-1,11)`, \"e\")\n\t\ttest(`\"发送 213123\".slice(0,2)`, \"发送\")\n\t})\n}\n\nfunc TestString_substring_unicode(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\"uñiçode\".substring()`, \"uñiçode\")\n\t\ttest(`\"uñiçode\".substring(0)`, \"uñiçode\")\n\t\ttest(`\"uñiçode\".substring(0,11)`, \"uñiçode\")\n\t\ttest(`\"uñiçode\".substring(11,0)`, \"uñiçode\")\n\t\ttest(`\"uñiçode\".substring(0,-1)`, \"\")\n\t\ttest(`\"uñiçode\".substring(-1,11)`, \"uñiçode\")\n\t\ttest(`\"uñiçode\".substring(1)`, \"ñiçode\")\n\t\ttest(`\"uñiçode\".substring(Infinity, Infinity)`, \"\")\n\t})\n}\n\nfunc TestString_substring(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\"abc\".substring()`, \"abc\")\n\t\ttest(`\"abc\".substring(0)`, \"abc\")\n\t\ttest(`\"abc\".substring(0,11)`, \"abc\")\n\t\ttest(`\"abc\".substring(11,0)`, \"abc\")\n\t\ttest(`\"abc\".substring(0,-1)`, \"\")\n\t\ttest(`\"abc\".substring(-1,11)`, \"abc\")\n\t\ttest(`\"abc\".substring(11,1)`, \"bc\")\n\t\ttest(`\"abc\".substring(1)`, \"bc\")\n\t\ttest(`\"abc\".substring(Infinity, Infinity)`, \"\")\n\t})\n}\n\nfunc TestString_toCase(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\"abc\".toLowerCase()`, \"abc\")\n\t\ttest(`\"ABC\".toLowerCase()`, \"abc\")\n\t\ttest(`\"abc\".toLocaleLowerCase()`, \"abc\")\n\t\ttest(`\"ABC\".toLocaleLowerCase()`, \"abc\")\n\t\ttest(`\"abc\".toUpperCase()`, \"ABC\")\n\t\ttest(`\"ABC\".toUpperCase()`, \"ABC\")\n\t\ttest(`\"abc\".toLocaleUpperCase()`, \"ABC\")\n\t\ttest(`\"ABC\".toLocaleUpperCase()`, \"ABC\")\n\t})\n}\n\nfunc Test_floatToString(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`String(-1234567890)`, \"-1234567890\")\n\t\ttest(`-+String(-(-1234567890))`, -1234567890)\n\t\ttest(`String(-1e128)`, \"-1e+128\")\n\t\ttest(`String(0.12345)`, \"0.12345\")\n\t\ttest(`String(-0.00000012345)`, \"-1.2345e-7\")\n\t\ttest(`String(0.0000012345)`, \"0.0000012345\")\n\t\ttest(`String(1000000000000000000000)`, \"1e+21\")\n\t\ttest(`String(1e21)`, \"1e+21\")\n\t\ttest(`String(1E21)`, \"1e+21\")\n\t\ttest(`String(-1000000000000000000000)`, \"-1e+21\")\n\t\ttest(`String(-1e21)`, \"-1e+21\")\n\t\ttest(`String(-1E21)`, \"-1e+21\")\n\t\ttest(`String(0.0000001)`, \"1e-7\")\n\t\ttest(`String(1e-7)`, \"1e-7\")\n\t\ttest(`String(1E-7)`, \"1e-7\")\n\t\ttest(`String(-0.0000001)`, \"-1e-7\")\n\t\ttest(`String(-1e-7)`, \"-1e-7\")\n\t\ttest(`String(-1E-7)`, \"-1e-7\")\n\t})\n}\n\nfunc TestString_indexing(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\t// Actually a test of stringToArrayIndex, under the hood.\n\t\ttest(`\n            abc = new String(\"abc\");\n            index = Math.pow(2, 32);\n            [ abc.length, abc[index], abc[index+1], abc[index+2], abc[index+3] ];\n        `, \"3,,,,\")\n\t})\n}\n\nfunc TestString_trim(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`'    \\n abc   \\t \\n'.trim();`, \"abc\")\n\t\ttest(`\"\t\tabc\\u000B\".trim()`, \"abc\")\n\t\ttest(`\"abc \".trim()`, \"abc\")\n\t\ttest(`\n            var a = \"\\u180Eabc \\u000B \"\n            var b = a.trim()\n            a.length + b.length\n        `, 10)\n\t})\n}\n\nfunc TestString_trimLeft(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\"\t\tabc\\u000B\".trimLeft()`, \"abc\\u000B\")\n\t\ttest(`\"abc \".trimLeft()`, \"abc \")\n\t\ttest(`\n            var a = \"\\u180Eabc \\u000B \"\n            var b = a.trimLeft()\n            a.length + b.length\n        `, 13)\n\t})\n}\n\nfunc TestString_trimRight(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\"\t\tabc\\u000B\".trimRight()`, \"\t\tabc\")\n\t\ttest(`\" abc \".trimRight()`, \" abc\")\n\t\ttest(`\n            var a = \"\\u180Eabc \\u000B \"\n            var b = a.trimRight()\n            a.length + b.length\n        `, 11)\n\t})\n}\n\nfunc TestString_localeCompare(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`'a'.localeCompare('c');`, -1)\n\t\ttest(`'c'.localeCompare('a');`, 1)\n\t\ttest(`'a'.localeCompare('a');`, 0)\n\t})\n}\n\nfunc TestString_startsWith(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`'a'.startsWith('c');`, false)\n\t\ttest(`'aa'.startsWith('a');`, true)\n\t})\n}\n\nfunc TestString_trimStart(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\"\t\tabc\\u000B\".trimStart()`, \"abc\\u000B\")\n\t\ttest(`\"abc \".trimStart()`, \"abc \")\n\t\ttest(`\n\t\t\tvar a = \"\\u180Eabc \\u000B \"\n\t\t\tvar b = a.trimStart()\n\t\t\ta.length + b.length\n\t\t`, 13)\n\t})\n}\n\nfunc TestString_trimEnd(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, _ := test()\n\n\t\ttest(`\"\t\tabc\\u000B\".trimEnd()`, \"\t\tabc\")\n\t\ttest(`\" abc \".trimEnd()`, \" abc\")\n\t\ttest(`\n\t\t\tvar a = \"\\u180Eabc \\u000B \"\n\t\t\tvar b = a.trimEnd()\n\t\t\ta.length + b.length\n\t\t`, 11)\n\t})\n}\n"
  },
  {
    "path": "terst/terst.go",
    "content": "// This file was AUTOMATICALLY GENERATED by terst-import (smuggol) from github.com/robertkrimen/terst\n\n/*\nPackage terst is a terse (terst = test + terse), easy-to-use testing library for Go.\n\nterst is compatible with (and works via) the standard testing package: http://golang.org/pkg/testing\n\n\tvar is = terst.Is\n\n\tfunc Test(t *testing.T) {\n\t    terst.Terst(t, func() {\n\t        is(\"abc\", \"abc\")\n\n\t        is(1, \">\", 0)\n\n\t        var abc []int\n\t        is(abc, nil)\n\t    }\n\t}\n\nDo not import terst directly, instead use `terst-import` to copy it into your testing environment:\n\nhttps://github.com/robertkrimen/terst/tree/master/terst-import\n\n\t$ go get github.com/robertkrimen/terst/terst-import\n\n\t$ terst-import\n*/\npackage terst\n\nimport (\n\t\"bytes\"\n\t\"errors\"\n\t\"fmt\"\n\t\"math/big\"\n\t\"reflect\"\n\t\"regexp\"\n\tgoruntime \"runtime\"\n\t\"strings\"\n\t\"sync\"\n\t\"testing\"\n\t\"time\"\n)\n\n// Is compares two values (got & expect) and returns true if the comparison is true,\n// false otherwise. In addition, if the comparison is false, Is will report the error\n// in a manner similar to testing.T.Error(...). Is also takes an optional argument,\n// a comparator, that changes how the comparison is made.  The following\n// comparators are available:\n//\n//\t==      # got == expect (default)\n//\t!=      # got != expect\n//\n//\t>       # got > expect (float32, uint, uint16, int, int64, ...)\n//\t>=      # got >= expect\n//\t<       # got < expect\n//\t<=      # got <= expect\n//\n//\t=~      # regexp.MustCompile(expect).Match{String}(got)\n//\t!~      # !regexp.MustCompile(expect).Match{String}(got)\n//\n// Basic usage with the default comparator (==):\n//\n//\tIs(<got>, <expect>)\n//\n// Specifying a different comparator:\n//\n//\tIs(<got>, <comparator>, <expect>)\n//\n// A simple comparison:\n//\n//\tIs(2 + 2, 4)\n//\n// A bit trickier:\n//\n//\tIs(1, \">\", 0)\n//\tIs(2 + 2, \"!=\", 5)\n//\tIs(\"Nothing happens.\", \"=~\", `ing(\\s+)happens\\.$`)\n//\n// Is should only be called under a Terst(t, ...) call. For a standalone version,\n// use IsErr. If no scope is found and the comparison is false, then Is will panic the error.\nfunc Is(arguments ...interface{}) bool {\n\terr := IsErr(arguments...)\n\tif err != nil {\n\t\tcall := Caller()\n\t\tif call == nil {\n\t\t\tpanic(err)\n\t\t}\n\t\tcall.Error(err)\n\t\treturn false\n\t}\n\treturn true\n}\n\ntype (\n\t// ErrFail indicates a comparison failure (e.g. 0 > 1).\n\tErrFail error\n\n\t// ErrInvalid indicates an invalid comparison (e.g. bool == string).\n\tErrInvalid error\n)\n\nvar errInvalid = errors.New(\"invalid\")\n\nvar registry = struct {\n\ttable map[uintptr]*_scope\n\tlock  sync.RWMutex\n}{\n\ttable: map[uintptr]*_scope{},\n}\n\nfunc registerScope(pc uintptr, scope *_scope) {\n\tregistry.lock.Lock()\n\tdefer registry.lock.Unlock()\n\tregistry.table[pc] = scope\n}\n\nfunc getScope() *_scope {\n\ts, _ := findScope()\n\treturn s\n}\n\nfunc floatCompare(a float64, b float64) int {\n\tif a > b {\n\t\treturn 1\n\t} else if a < b {\n\t\treturn -1\n\t}\n\t// NaN == NaN\n\treturn 0\n}\n\nfunc bigIntCompare(a *big.Int, b *big.Int) int {\n\treturn a.Cmp(b)\n}\n\nfunc bigInt(value int64) *big.Int {\n\treturn big.NewInt(value)\n}\n\nfunc bigUint(value uint64) *big.Int {\n\treturn big.NewInt(0).SetUint64(value)\n}\n\nfunc toString(value interface{}) (string, error) {\n\tswitch value := value.(type) {\n\tcase string:\n\t\treturn value, nil\n\tcase fmt.Stringer:\n\t\treturn value.String(), nil\n\tcase error:\n\t\treturn value.Error(), nil\n\t}\n\treturn \"\", errInvalid\n}\n\nfunc matchString(got string, expect *regexp.Regexp) (int, error) {\n\tif expect.MatchString(got) {\n\t\treturn 0, nil\n\t}\n\treturn -1, nil\n}\n\nfunc match(got []byte, expect *regexp.Regexp) (int, error) {\n\tif expect.Match(got) {\n\t\treturn 0, nil\n\t}\n\treturn -1, nil\n}\n\nfunc compareMatch(got, expect interface{}) (int, error) {\n\tswitch got := got.(type) {\n\tcase []byte:\n\t\tswitch expect := expect.(type) {\n\t\tcase string:\n\t\t\tmatcher, err := regexp.Compile(expect)\n\t\t\tif err != nil {\n\t\t\t\treturn 0, err\n\t\t\t}\n\t\t\treturn match(got, matcher)\n\t\tcase *regexp.Regexp:\n\t\t\treturn match(got, expect)\n\t\t}\n\tdefault:\n\t\tif got, err := toString(got); err == nil {\n\t\t\tswitch expect := expect.(type) {\n\t\t\tcase string:\n\t\t\t\tmatcher, err := regexp.Compile(expect)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn 0, err\n\t\t\t\t}\n\t\t\t\treturn matchString(got, matcher)\n\t\t\tcase *regexp.Regexp:\n\t\t\t\treturn matchString(got, expect)\n\t\t\t}\n\t\t} else {\n\t\t\treturn 0, err\n\t\t}\n\t}\n\treturn 0, errInvalid\n}\n\nfunc floatPromote(value reflect.Value) (float64, error) {\n\tkind := value.Kind()\n\tif reflect.Int <= kind && kind <= reflect.Int64 {\n\t\treturn float64(value.Int()), nil\n\t}\n\tif reflect.Uint <= kind && kind <= reflect.Uint64 {\n\t\treturn float64(value.Uint()), nil\n\t}\n\tif reflect.Float32 <= kind && kind <= reflect.Float64 {\n\t\treturn value.Float(), nil\n\t}\n\treturn 0, errInvalid\n}\n\nfunc bigIntPromote(value reflect.Value) (*big.Int, error) {\n\tkind := value.Kind()\n\tif reflect.Int <= kind && kind <= reflect.Int64 {\n\t\treturn bigInt(value.Int()), nil\n\t}\n\tif reflect.Uint <= kind && kind <= reflect.Uint64 {\n\t\treturn bigUint(value.Uint()), nil\n\t}\n\treturn nil, errInvalid\n}\n\nfunc compareOther(got, expect interface{}) (int, error) {\n\tswitch expect.(type) {\n\tcase float32, float64:\n\t\treturn compareNumber(got, expect)\n\tcase uint, uint8, uint16, uint32, uint64:\n\t\treturn compareNumber(got, expect)\n\tcase int, int8, int16, int32, int64:\n\t\treturn compareNumber(got, expect)\n\tcase string:\n\t\tvar err error\n\t\tgot, err = toString(got)\n\t\tif err != nil {\n\t\t\treturn 0, err\n\t\t}\n\tcase nil:\n\t\tgot := reflect.ValueOf(got)\n\t\tswitch got.Kind() {\n\t\tcase reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Slice, reflect.Interface:\n\t\t\tif got.IsNil() {\n\t\t\t\treturn 0, nil\n\t\t\t}\n\t\t\treturn -1, nil\n\t\tcase reflect.Invalid: // reflect.Invalid: var abc interface{} = nil\n\t\t\treturn 0, nil\n\t\t}\n\t\treturn 0, errInvalid\n\t}\n\n\tif reflect.ValueOf(got).Type() != reflect.ValueOf(expect).Type() {\n\t\treturn 0, errInvalid\n\t}\n\n\tif reflect.DeepEqual(got, expect) {\n\t\treturn 0, nil\n\t}\n\treturn -1, nil\n}\n\nfunc compareNumber(got, expect interface{}) (int, error) {\n\tgotRv := reflect.ValueOf(got)\n\tgotKind := gotRv.Kind()\n\texpectRv := reflect.ValueOf(expect)\n\texpectKind := expectRv.Kind()\n\tif reflect.Float32 <= gotKind && gotKind <= reflect.Float64 ||\n\t\treflect.Float32 <= expectKind && expectKind <= reflect.Float64 {\n\t\tgot, err := floatPromote(gotRv)\n\t\tif err != nil {\n\t\t\treturn 0, err\n\t\t}\n\t\texpect, err := floatPromote(expectRv)\n\t\tif err != nil {\n\t\t\treturn 0, err\n\t\t}\n\t\treturn floatCompare(got, expect), nil\n\t}\n\n\tgoBigInt, err := bigIntPromote(gotRv)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\texpectBigInt, err := bigIntPromote(expectRv)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn goBigInt.Cmp(expectBigInt), nil\n}\n\n// IsErr compares two values (got & expect) and returns nil if the comparison is true, an ErrFail if\n// the comparison is false, or an ErrInvalid if the comparison is invalid. IsErr also\n// takes an optional argument, a comparator, that changes how the comparison is made.\n//\n// Is & IsErr are similar but different:\n//\n//\tIs(...)     // Should only be called within a Terst(...) call\n//\tIsErr(...)  // A standalone comparator, the same as Is, just without the automatic reporting\nfunc IsErr(arguments ...interface{}) error {\n\tvar got, expect interface{}\n\tcomparator := \"==\"\n\tswitch len(arguments) {\n\tcase 0, 1:\n\t\treturn fmt.Errorf(\"invalid number of arguments to IsErr: %d\", len(arguments))\n\tcase 2:\n\t\tgot, expect = arguments[0], arguments[1]\n\tdefault:\n\t\tif value, ok := arguments[1].(string); ok {\n\t\t\tcomparator = value\n\t\t} else {\n\t\t\treturn fmt.Errorf(\"invalid comparator: %v\", arguments[1])\n\t\t}\n\t\tgot, expect = arguments[0], arguments[2]\n\t}\n\n\tvar result int\n\tvar err error\n\n\tswitch comparator {\n\tcase \"<\", \"<=\", \">\", \">=\":\n\t\tresult, err = compareNumber(got, expect)\n\tcase \"=~\", \"!~\":\n\t\tresult, err = compareMatch(got, expect)\n\tcase \"==\", \"!=\":\n\t\tresult, err = compareOther(got, expect)\n\tdefault:\n\t\treturn fmt.Errorf(\"invalid comparator: %s\", comparator)\n\t}\n\n\tif err == errInvalid {\n\t\treturn ErrInvalid(fmt.Errorf(\n\t\t\t\"\\nINVALID (%s):\\n        got: %v (%T)\\n   expected: %v (%T)\",\n\t\t\tcomparator,\n\t\t\tgot, got,\n\t\t\texpect, expect,\n\t\t))\n\t} else if err != nil {\n\t\treturn err\n\t}\n\n\tequality, pass := false, false\n\n\tswitch comparator {\n\tcase \"==\", \"=~\":\n\t\tequality = true\n\t\tpass = result == 0\n\tcase \"!=\", \"!~\":\n\t\tequality = true\n\t\tpass = result != 0\n\tcase \"<\":\n\t\tpass = result < 0\n\tcase \"<=\":\n\t\tpass = result <= 0\n\tcase \">\":\n\t\tpass = result > 0\n\tcase \">=\":\n\t\tpass = result >= 0\n\t}\n\n\tif !pass {\n\t\tif equality {\n\t\t\tif comparator[1] == '~' {\n\t\t\t\tif value, ok := got.([]byte); ok {\n\t\t\t\t\treturn ErrFail(fmt.Errorf(\n\t\t\t\t\t\t\"\\nFAIL (%s)\\n     got: %s %v%s\\nexpected: %v%s\",\n\t\t\t\t\t\tcomparator,\n\t\t\t\t\t\tvalue, got, typeKindString(got),\n\t\t\t\t\t\texpect, typeKindString(expect),\n\t\t\t\t\t))\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn ErrFail(fmt.Errorf(\n\t\t\t\t\"\\nFAIL (%s)\\n     got: %v%s\\nexpected: %v%s\",\n\t\t\t\tcomparator,\n\t\t\t\tgot, typeKindString(got),\n\t\t\t\texpect, typeKindString(expect),\n\t\t\t))\n\t\t}\n\t\treturn ErrFail(fmt.Errorf(\n\t\t\t\"\\nFAIL (%s)\\n     got: %v%s\\nexpected: %s %v%s\",\n\t\t\tcomparator,\n\t\t\tgot, typeKindString(got),\n\t\t\tcomparator, expect, typeKindString(expect),\n\t\t))\n\t}\n\n\treturn nil\n}\n\nfunc typeKindString(value interface{}) string {\n\treflectValue := reflect.ValueOf(value)\n\tkind := reflectValue.Kind().String()\n\tresult := fmt.Sprintf(\"%T\", value)\n\tif kind == result {\n\t\tif kind == \"string\" {\n\t\t\treturn \"\"\n\t\t}\n\t\treturn fmt.Sprintf(\" (%T)\", value)\n\t}\n\treturn fmt.Sprintf(\" (%T=%s)\", value, kind)\n}\n\nfunc (s *_scope) reset() {\n\ts.name = \"\"\n\ts.output = s.output[:0]\n\ts.start = time.Time{}\n\ts.duration = 0\n}\n\n// Terst creates a testing scope, where Is can be called and errors will be reported\n// according to the top-level location of the comparison, and not where the Is call\n// actually takes place. For example:\n//\n//\tfunc test(value int) {\n//\t    Is(value, 5) // <--- This failure is reported below.\n//\t}\n//\n//\tTerst(t, func(){\n//\n//\t    Is(2, \">\", 3) // <--- An error is reported here.\n//\n//\t    test(5) // <--- An error is reported here.\n//\n//\t})\nfunc Terst(t *testing.T, arguments ...func()) {\n\tcurScope := &_scope{\n\t\tt: t,\n\t}\n\n\tpc, _, _, ok := goruntime.Caller(1) // TODO Associate with the Test... func\n\tif !ok {\n\t\tpanic(\"Here be dragons.\")\n\t}\n\n\t_, curScope.testFunc = findTestFunc()\n\n\tregisterScope(pc, curScope)\n\n\tfor _, fn := range arguments {\n\t\tfunc() {\n\t\t\tcurScope.reset()\n\t\t\tname := curScope.testFunc.Name()\n\t\t\tindex := strings.LastIndex(curScope.testFunc.Name(), \".\")\n\t\t\tif index >= 0 {\n\t\t\t\tname = name[index+1:] + \"(Terst)\"\n\t\t\t} else {\n\t\t\t\tname = \"(Terst)\"\n\t\t\t}\n\t\t\tname = \"(Terst)\"\n\t\t\tcurScope.name = name\n\t\t\tcurScope.start = time.Now()\n\t\t\tdefer func() {\n\t\t\t\tcurScope.duration = time.Now().Sub(curScope.start)\n\t\t\t\tif err := recover(); err != nil {\n\t\t\t\t\tcurScope.t.Fail()\n\t\t\t\t\tcurScope.report()\n\t\t\t\t\tpanic(err)\n\t\t\t\t}\n\t\t\t\tcurScope.report()\n\t\t\t}()\n\t\t\tfn()\n\t\t}()\n\t}\n}\n\n// From \"testing\"\nfunc (s *_scope) report() {\n\tformat := \"~~~ %s: (Terst)\\n%s\"\n\tif s.t.Failed() {\n\t\tfmt.Printf(format, \"FAIL\", s.output)\n\t} else if testing.Verbose() && len(s.output) > 0 {\n\t\tfmt.Printf(format, \"PASS\", s.output)\n\t}\n}\n\nfunc (s *_scope) log(call entry, str string) {\n\ts.mu.Lock()\n\tdefer s.mu.Unlock()\n\ts.output = append(s.output, decorate(call, str)...)\n}\n\n// decorate prefixes the string with the file and line of the call site\n// and inserts the final newline if needed and indentation tabs for formascing.\nfunc decorate(call entry, s string) string {\n\n\tfile, line := call.File, call.Line\n\tif call.PC > 0 {\n\t\t// Truncate file name at last file name separator.\n\t\tif index := strings.LastIndex(file, \"/\"); index >= 0 {\n\t\t\tfile = file[index+1:]\n\t\t} else if index = strings.LastIndex(file, \"\\\\\"); index >= 0 {\n\t\t\tfile = file[index+1:]\n\t\t}\n\t} else {\n\t\tfile = \"???\"\n\t\tline = 1\n\t}\n\tbuf := new(bytes.Buffer)\n\t// Every line is indented at least one tab.\n\tbuf.WriteByte('\\t')\n\tfmt.Fprintf(buf, \"%s:%d: \", file, line)\n\tlines := strings.Split(s, \"\\n\")\n\tif l := len(lines); l > 1 && lines[l-1] == \"\" {\n\t\tlines = lines[:l-1]\n\t}\n\tfor i, line := range lines {\n\t\tif i > 0 {\n\t\t\t// Second and subsequent lines are indented an extra tab.\n\t\t\tbuf.WriteString(\"\\n\\t\\t\")\n\t\t}\n\t\tbuf.WriteString(line)\n\t}\n\tbuf.WriteByte('\\n')\n\treturn buf.String()\n}\n\nfunc findScope() (*_scope, entry) {\n\tregistry.lock.RLock()\n\tdefer registry.lock.RUnlock()\n\ttable := registry.table\n\tdepth := 2 // Starting depth\n\tcall := entry{}\n\tfor {\n\t\tpc, _, _, ok := goruntime.Caller(depth)\n\t\tif !ok {\n\t\t\tbreak\n\t\t}\n\t\tif s, exists := table[pc]; exists {\n\t\t\tpc, file, line, _ := goruntime.Caller(depth - 3) // Terst(...) + func(){}() + fn() => ???()\n\t\t\tcall.PC = pc\n\t\t\tcall.File = file\n\t\t\tcall.Line = line\n\t\t\treturn s, call\n\t\t}\n\t\tdepth++\n\t}\n\treturn nil, entry{}\n}\n\n// Call is a reference to a line immediately under a Terst testing scope.\ntype Call struct {\n\tscope *_scope\n\tentry entry\n}\n\n// Caller will search the stack, looking for a Terst testing scope. If a scope\n// is found, then Caller returns a Call for logging errors, accessing testing.T, etc.\n// If no scope is found, Caller returns nil.\nfunc Caller() *Call {\n\tcurScope, entry := findScope()\n\tif curScope == nil {\n\t\treturn nil\n\t}\n\treturn &Call{\n\t\tscope: curScope,\n\t\tentry: entry,\n\t}\n}\n\n// TestFunc returns the *runtime.Func entry for the top-level Test...(t testing.T)\n// function.\nfunc (cl *Call) TestFunc() *goruntime.Func {\n\treturn cl.scope.testFunc\n}\n\n// T returns the original testing.T passed to Terst(...)\nfunc (cl *Call) T() *testing.T {\n\treturn cl.scope.t\n}\n\n// Log is the terst version of `testing.T.Log`\nfunc (cl *Call) Log(arguments ...interface{}) {\n\tcl.scope.log(cl.entry, fmt.Sprintln(arguments...))\n}\n\n// Logf is the terst version of `testing.T.Logf`\nfunc (cl *Call) Logf(format string, arguments ...interface{}) {\n\tcl.scope.log(cl.entry, fmt.Sprintf(format, arguments...))\n}\n\n// Error is the terst version of `testing.T.Error`\nfunc (cl *Call) Error(arguments ...interface{}) {\n\tcl.scope.log(cl.entry, fmt.Sprintln(arguments...))\n\tcl.scope.t.Fail()\n}\n\n// Errorf is the terst version of `testing.T.Errorf`\nfunc (cl *Call) Errorf(format string, arguments ...interface{}) {\n\tcl.scope.log(cl.entry, fmt.Sprintf(format, arguments...))\n\tcl.scope.t.Fail()\n}\n\n// Skip is the terst version of `testing.T.Skip`\nfunc (cl *Call) Skip(arguments ...interface{}) {\n\tcl.scope.log(cl.entry, fmt.Sprintln(arguments...))\n\tcl.scope.t.SkipNow()\n}\n\n// Skipf is the terst version of `testing.T.Skipf`\nfunc (cl *Call) Skipf(format string, arguments ...interface{}) {\n\tcl.scope.log(cl.entry, fmt.Sprintf(format, arguments...))\n\tcl.scope.t.SkipNow()\n}\n\ntype _scope struct {\n\tt        *testing.T\n\ttestFunc *goruntime.Func\n\tname     string\n\tmu       sync.RWMutex\n\toutput   []byte\n\tstart    time.Time\n\tduration time.Duration\n}\n\ntype entry struct {\n\tPC   uintptr\n\tFile string\n\tLine int\n\tFunc *goruntime.Func\n}\n\nfunc findFunc(match string) (entry, *goruntime.Func) {\n\tdepth := 2 // Starting depth\n\tfor {\n\t\tpc, file, line, ok := goruntime.Caller(depth)\n\t\tif !ok {\n\t\t\tbreak\n\t\t}\n\t\tfn := goruntime.FuncForPC(pc)\n\t\tname := fn.Name()\n\t\tif index := strings.LastIndex(name, match); index >= 0 {\n\t\t\t// Assume we have an instance of TestXyzzy in a _test file\n\t\t\treturn entry{\n\t\t\t\tPC:   pc,\n\t\t\t\tFile: file,\n\t\t\t\tLine: line,\n\t\t\t\tFunc: fn,\n\t\t\t}, fn\n\t\t}\n\t\tdepth++\n\t}\n\treturn entry{}, nil\n}\n\nfunc findTestFunc() (entry, *goruntime.Func) {\n\treturn findFunc(\".Test\")\n}\n\nfunc findTerstFunc() (entry, *goruntime.Func) {\n\treturn findFunc(\".Terst\")\n}\n"
  },
  {
    "path": "testing_test.go",
    "content": "package otto\n\nimport (\n\t\"errors\"\n\t\"strings\"\n\t\"testing\"\n\t\"time\"\n\n\t\"github.com/robertkrimen/otto/terst\"\n)\n\nfunc tt(t *testing.T, arguments ...func()) {\n\tt.Helper()\n\thalt := errors.New(\"A test was taking too long\")\n\ttimer := time.AfterFunc(20*time.Second, func() {\n\t\tpanic(halt)\n\t})\n\tdefer func() {\n\t\ttimer.Stop()\n\t}()\n\tterst.Terst(t, arguments...)\n}\n\nfunc is(arguments ...interface{}) bool {\n\tvar got, expect interface{}\n\n\tswitch len(arguments) {\n\tcase 0, 1:\n\t\treturn terst.Is(arguments...)\n\tcase 2:\n\t\tgot, expect = arguments[0], arguments[1]\n\tdefault:\n\t\tgot, expect = arguments[0], arguments[2]\n\t}\n\n\tswitch value := got.(type) {\n\tcase Value:\n\t\tif value.value != nil {\n\t\t\tgot = value.value\n\t\t}\n\tcase *Error:\n\t\tif value != nil {\n\t\t\tgot = value.Error()\n\t\t}\n\t\tif expect == nil {\n\t\t\t// FIXME This is weird\n\t\t\texpect = \"\"\n\t\t}\n\t}\n\n\tif len(arguments) == 2 {\n\t\targuments[0] = got\n\t\targuments[1] = expect\n\t} else {\n\t\targuments[0] = got\n\t\targuments[2] = expect\n\t}\n\n\treturn terst.Is(arguments...)\n}\n\nfunc test(arguments ...interface{}) (func(string, ...interface{}) Value, *_tester) {\n\ttester := newTester()\n\tif len(arguments) > 0 {\n\t\ttester.test(arguments[0].(string))\n\t}\n\treturn tester.test, tester\n}\n\ntype _tester struct {\n\tvm *Otto\n}\n\nfunc newTester() *_tester {\n\treturn &_tester{\n\t\tvm: New(),\n\t}\n}\n\nfunc (te *_tester) Get(name string) (Value, error) {\n\treturn te.vm.Get(name)\n}\n\nfunc (te *_tester) Set(name string, value interface{}) Value {\n\terr := te.vm.Set(name, value)\n\tis(err, nil)\n\tif err != nil {\n\t\tterst.Caller().T().FailNow()\n\t}\n\treturn te.vm.getValue(name)\n}\n\nfunc (te *_tester) Run(src interface{}) (Value, error) {\n\treturn te.vm.Run(src)\n}\n\nfunc (te *_tester) test(name string, expect ...interface{}) Value {\n\tvm := te.vm\n\traise := false\n\tdefer func() {\n\t\tif caught := recover(); caught != nil {\n\t\t\tif exception, ok := caught.(*exception); ok {\n\t\t\t\tcaught = exception.eject()\n\t\t\t}\n\t\t\tif raise {\n\t\t\t\tif len(expect) > 0 {\n\t\t\t\t\tis(caught, expect[0])\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tdbg(\"Panic, caught:\", caught)\n\t\t\t\tpanic(caught)\n\t\t\t}\n\t\t}\n\t}()\n\tvar value Value\n\tvar err error\n\tif isIdentifier(name) {\n\t\tvalue = vm.getValue(name)\n\t} else {\n\t\tsource := name\n\t\tindex := strings.Index(source, \"raise:\")\n\t\tif index == 0 {\n\t\t\traise = true\n\t\t\tsource = source[6:]\n\t\t\tsource = strings.TrimLeft(source, \" \")\n\t\t}\n\t\tvalue, err = vm.runtime.cmplRun(source, nil)\n\t\tif err != nil {\n\t\t\tpanic(err)\n\t\t}\n\t}\n\tvalue = value.resolve()\n\tif len(expect) > 0 {\n\t\tis(value, expect[0])\n\t}\n\treturn value\n}\n"
  },
  {
    "path": "token/generate.go",
    "content": "package token\n\n//go:generate go run ../tools/gen-tokens -output token_const.go\n"
  },
  {
    "path": "token/token.go",
    "content": "// Package token defines constants representing the lexical tokens of JavaScript (ECMA5).\npackage token\n\nimport (\n\t\"strconv\"\n)\n\n// Token is the set of lexical tokens in JavaScript (ECMA5).\ntype Token int\n\n// String returns the string corresponding to the token.\n// For operators, delimiters, and keywords the string is the actual\n// token string (e.g., for the token PLUS, the String() is\n// \"+\"). For all other tokens the string corresponds to the token\n// name (e.g. for the token IDENTIFIER, the string is \"IDENTIFIER\").\nfunc (tkn Token) String() string {\n\tswitch {\n\tcase tkn == 0:\n\t\treturn \"UNKNOWN\"\n\tcase tkn < Token(len(token2string)):\n\t\treturn token2string[tkn]\n\tdefault:\n\t\treturn \"token(\" + strconv.Itoa(int(tkn)) + \")\"\n\t}\n}\n\ntype keyword struct {\n\ttoken         Token\n\tfutureKeyword bool\n\tstrict        bool\n}\n\n// IsKeyword returns the keyword token if literal is a keyword, a KEYWORD token\n// if the literal is a future keyword (const, let, class, super, ...), or 0 if the literal is not a keyword.\n//\n// If the literal is a keyword, IsKeyword returns a second value indicating if the literal\n// is considered a future keyword in strict-mode only.\n//\n// 7.6.1.2 Future Reserved Words:\n//\n//\tconst\n//\tclass\n//\tenum\n//\texport\n//\textends\n//\timport\n//\tsuper\n//\n// 7.6.1.2 Future Reserved Words (strict):\n//\n//\timplements\n//\tinterface\n//\tlet\n//\tpackage\n//\tprivate\n//\tprotected\n//\tpublic\n//\tstatic\nfunc IsKeyword(literal string) (Token, bool) {\n\tif kw, exists := keywordTable[literal]; exists {\n\t\tif kw.futureKeyword {\n\t\t\treturn KEYWORD, kw.strict\n\t\t}\n\t\treturn kw.token, false\n\t}\n\treturn 0, false\n}\n"
  },
  {
    "path": "token/token_const.go",
    "content": "// Code generated by tools/gen-tokens. DO NOT EDIT.\n\npackage token\n\nconst (\n\t_ Token = iota\n\n\t// Control.\n\tILLEGAL\n\tEOF\n\tCOMMENT\n\tKEYWORD\n\t// Types.\n\tSTRING\n\tBOOLEAN\n\tNULL\n\tNUMBER\n\tIDENTIFIER\n\t// Maths.\n\tPLUS      // +\n\tMINUS     // -\n\tMULTIPLY  // *\n\tSLASH     // /\n\tREMAINDER // %\n\t// Logical and bitwise operators.\n\tAND                  // &\n\tOR                   // |\n\tEXCLUSIVE_OR         // ^\n\tSHIFT_LEFT           // <<\n\tSHIFT_RIGHT          // >>\n\tUNSIGNED_SHIFT_RIGHT // >>>\n\tAND_NOT              // &^\n\t// Math assignments.\n\tADD_ASSIGN       // +=\n\tSUBTRACT_ASSIGN  // -=\n\tMULTIPLY_ASSIGN  // *=\n\tQUOTIENT_ASSIGN  // /=\n\tREMAINDER_ASSIGN // %=\n\t// Math and bitwise assignments.\n\tAND_ASSIGN                  // &=\n\tOR_ASSIGN                   // |=\n\tEXCLUSIVE_OR_ASSIGN         // ^=\n\tSHIFT_LEFT_ASSIGN           // <<=\n\tSHIFT_RIGHT_ASSIGN          // >>=\n\tUNSIGNED_SHIFT_RIGHT_ASSIGN // >>>=\n\tAND_NOT_ASSIGN              // &^=\n\t// Logical operators and decrement / increment.\n\tLOGICAL_AND // &&\n\tLOGICAL_OR  // ||\n\tINCREMENT   // ++\n\tDECREMENT   // --\n\t// Comparison operators.\n\tEQUAL        // ==\n\tSTRICT_EQUAL // ===\n\tLESS         // <\n\tGREATER      // >\n\tASSIGN       // =\n\tNOT          // !\n\t// Bitwise not.\n\tBITWISE_NOT // ~\n\t// Comparison operators.\n\tNOT_EQUAL        // !=\n\tSTRICT_NOT_EQUAL // !==\n\tLESS_OR_EQUAL    // <=\n\tGREATER_OR_EQUAL // >=\n\t// Left operators.\n\tLEFT_PARENTHESIS // (\n\tLEFT_BRACKET     // [\n\tLEFT_BRACE       // {\n\tCOMMA            // ,\n\tPERIOD           // .\n\t// Right operators.\n\tRIGHT_PARENTHESIS // )\n\tRIGHT_BRACKET     // ]\n\tRIGHT_BRACE       // }\n\tSEMICOLON         // ;\n\tCOLON             // :\n\tQUESTION_MARK     // ?\n\t// Basic flow - keywords below here.\n\t_\n\tIF\n\tIN\n\tDO\n\t// Declarations.\n\tVAR\n\tFOR\n\tNEW\n\tTRY\n\t// Advanced flow.\n\tTHIS\n\tELSE\n\tCASE\n\tVOID\n\tWITH\n\t// Loops.\n\tWHILE\n\tBREAK\n\tCATCH\n\tTHROW\n\t// Functions.\n\tRETURN\n\tTYPEOF\n\tDELETE\n\tSWITCH\n\t// Fallback identifiers.\n\tDEFAULT\n\tFINALLY\n\t// Miscellaneous.\n\tFUNCTION\n\tCONTINUE\n\tDEBUGGER\n\t// Instance of.\n\tINSTANCEOF\n)\n\nvar token2string = [...]string{\n\tILLEGAL:                     \"ILLEGAL\",\n\tEOF:                         \"EOF\",\n\tCOMMENT:                     \"COMMENT\",\n\tKEYWORD:                     \"KEYWORD\",\n\tSTRING:                      \"STRING\",\n\tBOOLEAN:                     \"BOOLEAN\",\n\tNULL:                        \"NULL\",\n\tNUMBER:                      \"NUMBER\",\n\tIDENTIFIER:                  \"IDENTIFIER\",\n\tPLUS:                        \"+\",\n\tMINUS:                       \"-\",\n\tMULTIPLY:                    \"*\",\n\tSLASH:                       \"/\",\n\tREMAINDER:                   \"%\",\n\tAND:                         \"&\",\n\tOR:                          \"|\",\n\tEXCLUSIVE_OR:                \"^\",\n\tSHIFT_LEFT:                  \"<<\",\n\tSHIFT_RIGHT:                 \">>\",\n\tUNSIGNED_SHIFT_RIGHT:        \">>>\",\n\tAND_NOT:                     \"&^\",\n\tADD_ASSIGN:                  \"+=\",\n\tSUBTRACT_ASSIGN:             \"-=\",\n\tMULTIPLY_ASSIGN:             \"*=\",\n\tQUOTIENT_ASSIGN:             \"/=\",\n\tREMAINDER_ASSIGN:            \"%=\",\n\tAND_ASSIGN:                  \"&=\",\n\tOR_ASSIGN:                   \"|=\",\n\tEXCLUSIVE_OR_ASSIGN:         \"^=\",\n\tSHIFT_LEFT_ASSIGN:           \"<<=\",\n\tSHIFT_RIGHT_ASSIGN:          \">>=\",\n\tUNSIGNED_SHIFT_RIGHT_ASSIGN: \">>>=\",\n\tAND_NOT_ASSIGN:              \"&^=\",\n\tLOGICAL_AND:                 \"&&\",\n\tLOGICAL_OR:                  \"||\",\n\tINCREMENT:                   \"++\",\n\tDECREMENT:                   \"--\",\n\tEQUAL:                       \"==\",\n\tSTRICT_EQUAL:                \"===\",\n\tLESS:                        \"<\",\n\tGREATER:                     \">\",\n\tASSIGN:                      \"=\",\n\tNOT:                         \"!\",\n\tBITWISE_NOT:                 \"~\",\n\tNOT_EQUAL:                   \"!=\",\n\tSTRICT_NOT_EQUAL:            \"!==\",\n\tLESS_OR_EQUAL:               \"<=\",\n\tGREATER_OR_EQUAL:            \">=\",\n\tLEFT_PARENTHESIS:            \"(\",\n\tLEFT_BRACKET:                \"[\",\n\tLEFT_BRACE:                  \"{\",\n\tCOMMA:                       \",\",\n\tPERIOD:                      \".\",\n\tRIGHT_PARENTHESIS:           \")\",\n\tRIGHT_BRACKET:               \"]\",\n\tRIGHT_BRACE:                 \"}\",\n\tSEMICOLON:                   \";\",\n\tCOLON:                       \":\",\n\tQUESTION_MARK:               \"?\",\n\tIF:                          \"if\",\n\tIN:                          \"in\",\n\tDO:                          \"do\",\n\tVAR:                         \"var\",\n\tFOR:                         \"for\",\n\tNEW:                         \"new\",\n\tTRY:                         \"try\",\n\tTHIS:                        \"this\",\n\tELSE:                        \"else\",\n\tCASE:                        \"case\",\n\tVOID:                        \"void\",\n\tWITH:                        \"with\",\n\tWHILE:                       \"while\",\n\tBREAK:                       \"break\",\n\tCATCH:                       \"catch\",\n\tTHROW:                       \"throw\",\n\tRETURN:                      \"return\",\n\tTYPEOF:                      \"typeof\",\n\tDELETE:                      \"delete\",\n\tSWITCH:                      \"switch\",\n\tDEFAULT:                     \"default\",\n\tFINALLY:                     \"finally\",\n\tFUNCTION:                    \"function\",\n\tCONTINUE:                    \"continue\",\n\tDEBUGGER:                    \"debugger\",\n\tINSTANCEOF:                  \"instanceof\",\n}\n\nvar keywordTable = map[string]keyword{\n\t\"if\": {\n\t\ttoken: IF,\n\t},\n\t\"in\": {\n\t\ttoken: IN,\n\t},\n\t\"do\": {\n\t\ttoken: DO,\n\t},\n\t\"var\": {\n\t\ttoken: VAR,\n\t},\n\t\"for\": {\n\t\ttoken: FOR,\n\t},\n\t\"new\": {\n\t\ttoken: NEW,\n\t},\n\t\"try\": {\n\t\ttoken: TRY,\n\t},\n\t\"this\": {\n\t\ttoken: THIS,\n\t},\n\t\"else\": {\n\t\ttoken: ELSE,\n\t},\n\t\"case\": {\n\t\ttoken: CASE,\n\t},\n\t\"void\": {\n\t\ttoken: VOID,\n\t},\n\t\"with\": {\n\t\ttoken: WITH,\n\t},\n\t\"while\": {\n\t\ttoken: WHILE,\n\t},\n\t\"break\": {\n\t\ttoken: BREAK,\n\t},\n\t\"catch\": {\n\t\ttoken: CATCH,\n\t},\n\t\"throw\": {\n\t\ttoken: THROW,\n\t},\n\t\"return\": {\n\t\ttoken: RETURN,\n\t},\n\t\"typeof\": {\n\t\ttoken: TYPEOF,\n\t},\n\t\"delete\": {\n\t\ttoken: DELETE,\n\t},\n\t\"switch\": {\n\t\ttoken: SWITCH,\n\t},\n\t\"default\": {\n\t\ttoken: DEFAULT,\n\t},\n\t\"finally\": {\n\t\ttoken: FINALLY,\n\t},\n\t\"function\": {\n\t\ttoken: FUNCTION,\n\t},\n\t\"continue\": {\n\t\ttoken: CONTINUE,\n\t},\n\t\"debugger\": {\n\t\ttoken: DEBUGGER,\n\t},\n\t\"instanceof\": {\n\t\ttoken: INSTANCEOF,\n\t},\n\t\"const\": {\n\t\ttoken:         KEYWORD,\n\t\tfutureKeyword: true,\n\t},\n\t\"class\": {\n\t\ttoken:         KEYWORD,\n\t\tfutureKeyword: true,\n\t},\n\t\"enum\": {\n\t\ttoken:         KEYWORD,\n\t\tfutureKeyword: true,\n\t},\n\t\"export\": {\n\t\ttoken:         KEYWORD,\n\t\tfutureKeyword: true,\n\t},\n\t\"extends\": {\n\t\ttoken:         KEYWORD,\n\t\tfutureKeyword: true,\n\t},\n\t\"import\": {\n\t\ttoken:         KEYWORD,\n\t\tfutureKeyword: true,\n\t},\n\t\"super\": {\n\t\ttoken:         KEYWORD,\n\t\tfutureKeyword: true,\n\t},\n\t\"implements\": {\n\t\ttoken:         KEYWORD,\n\t\tfutureKeyword: true,\n\t\tstrict:        true,\n\t},\n\t\"interface\": {\n\t\ttoken:         KEYWORD,\n\t\tfutureKeyword: true,\n\t\tstrict:        true,\n\t},\n\t\"let\": {\n\t\ttoken:         KEYWORD,\n\t\tfutureKeyword: true,\n\t\tstrict:        true,\n\t},\n\t\"package\": {\n\t\ttoken:         KEYWORD,\n\t\tfutureKeyword: true,\n\t\tstrict:        true,\n\t},\n\t\"private\": {\n\t\ttoken:         KEYWORD,\n\t\tfutureKeyword: true,\n\t\tstrict:        true,\n\t},\n\t\"protected\": {\n\t\ttoken:         KEYWORD,\n\t\tfutureKeyword: true,\n\t\tstrict:        true,\n\t},\n\t\"public\": {\n\t\ttoken:         KEYWORD,\n\t\tfutureKeyword: true,\n\t\tstrict:        true,\n\t},\n\t\"static\": {\n\t\ttoken:         KEYWORD,\n\t\tfutureKeyword: true,\n\t\tstrict:        true,\n\t},\n}\n"
  },
  {
    "path": "tools/gen-jscore/.gen-jscore.yaml",
    "content": "types:\n  - name: Object\n    core: true\n    properties:\n      - name: length\n        mode: 0\n        value: 1\n      - name: prototype\n        mode: 0\n        value: rt.global.ObjectPrototype\n      - name: getPrototypeOf\n        function: 1\n      - name: assign\n        function: 1\n      - name: getOwnPropertyDescriptor\n        function: 2\n      - name: defineProperty\n        function: 3\n      - name: defineProperties\n        function: 2\n      - name: create\n        function: 2\n      - name: isExtensible\n        function: 1\n      - name: preventExtensions\n        function: 1\n      - name: isSealed\n        function: 1\n      - name: seal\n        function: 1\n      - name: isFrozen\n        function: 1\n      - name: freeze\n        function: 1\n      - name: keys\n        function: 1\n      - name: values\n        function: 1\n      - name: getOwnPropertyNames\n        function: 1\n    prototype:\n      value: prototypeValueObject\n      properties:\n        - name: constructor\n          value: rt.global.Object\n        - name: hasOwnProperty\n          function: 1\n        - name: isPrototypeOf\n          function: 1\n        - name: propertyIsEnumerable\n          function: 1\n        - name: toString\n          function: -1\n        - name: valueOf\n          function: -1\n        - name: toLocaleString\n          function: -1\n\n  - name: Function\n    core: true\n    properties:\n      - name: length\n        value: 1\n      - name: prototype\n        value: rt.global.FunctionPrototype\n    prototype:\n      prototype: Object\n      value: prototypeValueFunction\n      properties:\n        - name: toString\n          function: -1\n        - name: apply\n          function: 2\n        - name: call\n          function: 1\n        - name: bind\n          function: 1\n        - name: constructor\n          value: rt.global.Function\n        - name: length\n          kind: valueNumber\n          value: 0\n\n  - name: Array\n    objectClass: Object\n    properties:\n      - name: length\n        value: 1\n      - name: prototype\n        value: rt.global.ArrayPrototype\n      - name: isArray\n        function: 1\n    prototype:\n      prototype: Object\n      objectClass: Array\n      value: nil\n      properties:\n        - name: length\n          mode: 0o100\n          kind: valueNumber\n          value: uint32(0)\n        - name: constructor\n          value: rt.global.Array\n        - name: concat\n          function: 1\n        - name: lastIndexOf\n          function: 1\n        - name: pop\n          function: -1\n        - name: push\n          function: 1\n        - name: reverse\n          function: -1\n        - name: shift\n          function: -1\n        - name: unshift\n          function: 1\n        - name: slice\n          function: 2\n        - name: sort\n          function: 1\n        - name: splice\n          function: 2\n        - name: indexOf\n          function: 1\n        - name: join\n          function: 1\n        - name: forEach\n          function: 1\n        - name: filter\n          function: 1\n        - name: map\n          function: 1\n        - name: every\n          function: 1\n        - name: some\n          function: 1\n        - name: reduce\n          function: 1\n        - name: reduceRight\n          function: 1\n        - name: toLocaleString\n          function: -1\n        - name: toString\n          function: -1\n\n  - name: String\n    properties:\n      - name: length\n        value: 1\n      - name: prototype\n        value: rt.global.StringPrototype\n      - name: fromCharCode\n        function: 1\n    prototype:\n      objectClass: String\n      prototype: Object\n      value: prototypeValueString\n      properties:\n        - name: length\n          kind: valueNumber\n          value: int(0)\n        - name: constructor\n          value: rt.global.String\n        - name: charAt\n          function: 1\n        - name: charCodeAt\n          function: 1\n        - name: concat\n          function: 1\n        - name: indexOf\n          function: 1\n        - name: lastIndexOf\n          function: 1\n        - name: localeCompare\n          function: 1\n        - name: match\n          function: 1\n        - name: replace\n          function: 2\n        - name: search\n          function: 1\n        - name: slice\n          function: 2\n        - name: split\n          function: 2\n        - name: substr\n          function: 2\n        - name: substring\n          function: 2\n        - name: startsWith\n          function: 1\n        - name: toString\n          function: -1\n        - name: trim\n          function: -1\n        - name: trimLeft\n          function: -1\n        - name: trimRight\n          function: -1\n        - name: trimStart\n          function: -1\n        - name: trimEnd\n          function: -1\n        - name: toLocaleLowerCase\n          function: -1\n        - name: toLocaleUpperCase\n          function: -1\n        - name: toLowerCase\n          function: -1\n        - name: toUpperCase\n          function: -1\n        - name: valueOf\n          function: -1\n\n  - name: Boolean\n    properties:\n      - name: length\n        value: 1\n      - name: prototype\n        value: rt.global.BooleanPrototype\n    prototype:\n      prototype: Object\n      value: prototypeValueBoolean\n      properties:\n        - name: constructor\n          value: rt.global.Boolean\n        - name: toString\n          function: -1\n        - name: valueOf\n          function: -1\n    globals:\n      length: 1\n\n  - name: Number\n    properties:\n      - name: length\n        value: 1\n      - name: prototype\n        value: rt.global.NumberPrototype\n      - name: isNaN\n        function: 1\n      - name: MAX_VALUE\n        value: math.MaxFloat64\n        kind: valueNumber\n      - name: MIN_VALUE\n        kind: valueNumber\n        value: math.SmallestNonzeroFloat64\n      - name: NaN\n        kind: valueNumber\n        value: math.NaN()\n      - name: NEGATIVE_INFINITY\n        kind: valueNumber\n        value: math.Inf(-1)\n      - name: POSITIVE_INFINITY\n        kind: valueNumber\n        value: math.Inf(+1)\n    prototype:\n      prototype: Object\n      value: prototypeValueNumber\n      properties:\n        - name: constructor\n          value: rt.global.Number\n        - name: toExponential\n          function: 1\n        - name: toFixed\n          function: 1\n        - name: toPrecision\n          function: 1\n        - name: toString\n          function: -1\n        - name: valueOf\n          function: -1\n        - name: toLocaleString\n          function: 1\n\n  - name: Math\n    class: Math\n    objectPrototype: Object\n    properties:\n      - name: abs\n        function: 1\n      - name: acos\n        function: 1\n      - name: acosh\n        function: 1\n      - name: asin\n        function: 1\n      - name: asinh\n        function: 1\n      - name: atan\n        function: 1\n      - name: atanh\n        function: 1\n      - name: atan2\n        function: 1\n      - name: cbrt\n        function: 1\n      - name: ceil\n        function: 1\n      - name: cos\n        function: 1\n      - name: cosh\n        function: 1\n      - name: exp\n        function: 1\n      - name: expm1\n        function: 1\n      - name: floor\n        function: 1\n      - name: log\n        function: 1\n      - name: log10\n        function: 1\n      - name: log1p\n        function: 1\n      - name: log2\n        function: 1\n      - name: max\n        function: 2\n      - name: min\n        function: 2\n      - name: pow\n        function: 2\n      - name: random\n        function: -1\n      - name: round\n        function: 1\n      - name: sin\n        function: 1\n      - name: sinh\n        function: 1\n      - name: sqrt\n        function: 1\n      - name: tan\n        function: 1\n      - name: tanh\n        function: 1\n      - name: trunc\n        function: 1\n      - name: E\n        kind: valueNumber\n        value: math.E\n      - name: LN10\n        kind: valueNumber\n        value: math.Ln10\n      - name: LN2\n        kind: valueNumber\n        value: math.Ln2\n      - name: LOG10E\n        kind: valueNumber\n        value: math.Log10E\n      - name: LOG2E\n        kind: valueNumber\n        value: math.Log2E\n      - name: PI\n        kind: valueNumber\n        value: math.Pi\n      - name: SQRT1_2\n        kind: valueNumber\n        value: sqrt1_2\n      - name: SQRT2\n        kind: valueNumber\n        value: math.Sqrt2\n\n  - name: Date\n    properties:\n      - name: length\n        value: 7\n      - name: prototype\n        value: rt.global.DatePrototype\n      - name: parse\n        function: 1\n      - name: UTC\n        function: 7\n      - name: now\n        function: -1\n    prototype:\n      prototype: Object\n      value: prototypeValueDate\n      properties:\n        - name: constructor\n          value: rt.global.Date\n        - name: toString\n          function: -1\n        - name: toDateString\n          function: -1\n        - name: toTimeString\n          function: -1\n        - name: toISOString\n          function: -1\n        - name: toUTCString\n          function: -1\n        - name: toGMTString\n          function: -1\n        - name: getDate\n          function: -1\n        - name: setDate\n          function: 1\n        - name: getDay\n          function: -1\n        - name: getFullYear\n          function: -1\n        - name: setFullYear\n          function: 3\n        - name: getHours\n          function: -1\n        - name: setHours\n          function: 4\n        - name: getMilliseconds\n          function: -1\n        - name: setMilliseconds\n          function: 1\n        - name: getMinutes\n          function: -1\n        - name: setMinutes\n          function: 3\n        - name: getMonth\n          function: -1\n        - name: setMonth\n          function: 2\n        - name: getSeconds\n          function: -1\n        - name: setSeconds\n          function: 2\n        - name: getTime\n          function: -1\n        - name: setTime\n          function: 1\n        - name: getTimezoneOffset\n          function: -1\n        - name: getUTCDate\n          function: -1\n        - name: setUTCDate\n          function: 1\n        - name: getUTCDay\n          function: -1\n        - name: getUTCFullYear\n          function: -1\n        - name: setUTCFullYear\n          function: 3\n        - name: getUTCHours\n          function: -1\n        - name: setUTCHours\n          function: 4\n        - name: getUTCMilliseconds\n          function: -1\n        - name: setUTCMilliseconds\n          function: 1\n        - name: getUTCMinutes\n          function: -1\n        - name: setUTCMinutes\n          function: 3\n        - name: getUTCMonth\n          function: -1\n        - name: setUTCMonth\n          function: 2\n        - name: getUTCSeconds\n          function: -1\n        - name: setUTCSeconds\n          function: 2\n        - name: valueOf\n          function: -1\n        - name: getYear\n          function: -1\n        - name: setYear\n          function: 1\n        - name: toJSON\n          function: 1\n        - name: toLocaleString\n          function: -1\n        - name: toLocaleDateString\n          function: -1\n        - name: toLocaleTimeString\n          function: -1\n\n  - name: RegExp\n    properties:\n      - name: length\n        value: 2\n      - name: prototype\n        value: rt.global.RegExpPrototype\n    prototype:\n      prototype: Object\n      value: prototypeValueRegExp\n      properties:\n        - name: constructor\n          value: rt.global.RegExp\n        - name: exec\n          function: 1\n        - name: compile\n          function: 1\n        - name: toString\n          function: -1\n        - name: test\n          function: 1\n\n  - name: Error\n    objectPrototype: Function\n    properties:\n      - name: length\n        value: 1\n      - name: prototype\n        value: rt.global.ErrorPrototype\n    prototype:\n      prototype: Object\n      value: nil\n      properties:\n        - name: constructor\n          value: rt.global.Error\n        - name: name\n          kind: valueString\n          value: classErrorName\n          mode: 0o101\n        - name: message\n          kind: valueString\n          value: '\"\"'\n          mode: 0o101\n        - name: toString\n          function: -1\n\n  - name: EvalError\n    objectPrototype: Function\n    properties:\n      - name: length\n        value: 1\n      - name: prototype\n        value: rt.global.EvalErrorPrototype\n    prototype:\n      prototype: Error\n      value: nil\n      properties:\n        - name: constructor\n          value: rt.global.EvalError\n        - name: name\n          kind: valueString\n          value: classEvalErrorName\n          mode: 0o101\n        - name: message\n          kind: valueString\n          value: '\"\"'\n          mode: 0o101\n        - name: toString\n          function: -1\n          call: ErrorToString\n\n  - name: TypeError\n    objectPrototype: Function\n    properties:\n      - name: length\n        value: 1\n      - name: prototype\n        value: rt.global.TypeErrorPrototype\n    prototype:\n      prototype: Error\n      value: nil\n      properties:\n        - name: constructor\n          value: rt.global.TypeError\n        - name: name\n          kind: valueString\n          value: classTypeErrorName\n          mode: 0o101\n        - name: message\n          kind: valueString\n          value: '\"\"'\n          mode: 0o101\n        - name: toString\n          function: -1\n          call: ErrorToString\n\n  - name: RangeError\n    objectPrototype: Function\n    properties:\n      - name: length\n        value: 1\n      - name: prototype\n        value: rt.global.RangeErrorPrototype\n    prototype:\n      prototype: Error\n      value: nil\n      properties:\n        - name: constructor\n          value: rt.global.RangeError\n        - name: name\n          kind: valueString\n          value: classRangeErrorName\n          mode: 0o101\n        - name: message\n          kind: valueString\n          value: '\"\"'\n          mode: 0o101\n        - name: toString\n          function: -1\n          call: ErrorToString\n\n  - name: ReferenceError\n    objectPrototype: Function\n    properties:\n      - name: length\n        value: 1\n      - name: prototype\n        value: rt.global.ReferenceErrorPrototype\n    prototype:\n      prototype: Error\n      value: nil\n      properties:\n        - name: constructor\n          value: rt.global.ReferenceError\n        - name: name\n          kind: valueString\n          value: classReferenceErrorName\n          mode: 0o101\n        - name: message\n          kind: valueString\n          value: '\"\"'\n          mode: 0o101\n        - name: toString\n          function: -1\n          call: ErrorToString\n\n  - name: SyntaxError\n    objectPrototype: Function\n    properties:\n      - name: length\n        value: 1\n      - name: prototype\n        value: rt.global.SyntaxErrorPrototype\n    prototype:\n      prototype: Error\n      value: nil\n      properties:\n        - name: constructor\n          value: rt.global.SyntaxError\n        - name: name\n          kind: valueString\n          value: classSyntaxErrorName\n          mode: 0o101\n        - name: message\n          kind: valueString\n          value: '\"\"'\n          mode: 0o101\n        - name: toString\n          function: -1\n          call: ErrorToString\n\n  - name: URIError\n    objectPrototype: Function\n    properties:\n      - name: length\n        value: 1\n      - name: prototype\n        value: rt.global.URIErrorPrototype\n    prototype:\n      prototype: Error\n      value: nil\n      properties:\n        - name: constructor\n          value: rt.global.URIError\n        - name: name\n          kind: valueString\n          value: classURIErrorName\n          mode: 0o101\n        - name: message\n          kind: valueString\n          value: '\"\"'\n          mode: 0o101\n        - name: toString\n          function: -1\n          call: ErrorToString\n\n  - name: JSON\n    class: JSON\n    objectPrototype: Object\n    properties:\n      - name: parse\n        function: 2\n      - name: stringify\n        function: 3\n\n  - name: Global\n    properties:\n      - name: eval\n        function: 1\n      - name: parseInt\n        function: 2\n      - name: parseFloat\n        function: 1\n      - name: isNaN\n        function: 1\n      - name: isFinite\n        function: 1\n      - name: decodeURI\n        function: 1\n      - name: decodeURIComponent\n        function: 1\n      - name: encodeURI\n        function: 1\n      - name: encodeURIComponent\n        function: 1\n      - name: escape\n        function: 1\n      - name: unescape\n        function: 1\n      - name: Object\n        mode: 0o101\n        value: rt.global.Object\n      - name: Function\n        mode: 0o101\n        value: rt.global.Function\n      - name: Array\n        mode: 0o101\n        value: rt.global.Array\n      - name: String\n        mode: 0o101\n        value: rt.global.String\n      - name: Boolean\n        mode: 0o101\n        value: rt.global.Boolean\n      - name: Number\n        mode: 0o101\n        value: rt.global.Number\n      - name: Math\n        mode: 0o101\n        value: rt.global.Math\n      - name: Date\n        mode: 0o101\n        value: rt.global.Date\n      - name: RegExp\n        mode: 0o101\n        value: rt.global.RegExp\n      - name: Error\n        mode: 0o101\n        value: rt.global.Error\n      - name: EvalError\n        mode: 0o101\n        value: rt.global.EvalError\n      - name: TypeError\n        mode: 0o101\n        value: rt.global.TypeError\n      - name: RangeError\n        mode: 0o101\n        value: rt.global.RangeError\n      - name: ReferenceError\n        mode: 0o101\n        value: rt.global.ReferenceError\n      - name: SyntaxError\n        mode: 0o101\n        value: rt.global.SyntaxError\n      - name: URIError\n        mode: 0o101\n        value: rt.global.URIError\n      - name: JSON\n        mode: 0o101\n        value: rt.global.JSON\n      - name: undefined\n        kind: valueUndefined\n      - name: NaN\n        kind: valueNumber\n        value: math.NaN()\n      - name: Infinity\n        kind: valueNumber\n        value: math.Inf(+1)\n\nlog:\n  name: Console\n  class: Object\n  objectPrototype: Object\n  properties:\n    - name: log\n      function: -1\n    - name: debug\n      call: ConsoleLog\n      function: -1\n    - name: info\n      call: ConsoleLog\n      function: -1\n    - name: error\n      function: -1\n    - name: warn\n      function: -1\n      call: ConsoleError\n    - name: dir\n      function: -1\n    - name: time\n      function: -1\n    - name: timeEnd\n      function: -1\n    - name: trace\n      function: -1\n    - name: assert\n      function: -1\n\nvalues:\n  - name: int\n  - name: int32\n  - name: int64\n  - name: uint16\n  - name: uint32\n  - name: float64\n  - name: string\n  - name: string16\n    type: \"[]uint16\"\n  - name: bool\n  - name: object\n    type: \"*object\"\n"
  },
  {
    "path": "tools/gen-jscore/helpers.go",
    "content": "package main\n\nimport (\n\t\"fmt\"\n\t\"unicode\"\n)\n\n// ucfirst converts the first rune of val to uppercase an returns the result.\nfunc ucfirst(val string) string {\n\tr := []rune(val)\n\tr[0] = unicode.ToUpper(r[0])\n\n\treturn string(r)\n}\n\n// dict is a template helper returns a map created from alternating values.\n// Values must be passed as key, value pairs with key being a string.\n// It can be used to pass the combination of multiple values to a template.\nfunc dict(values ...interface{}) (map[string]interface{}, error) {\n\tif len(values)%2 != 0 {\n\t\treturn nil, fmt.Errorf(\"map requires parameters which are multiple of 2 got %d\", len(values))\n\t}\n\n\tm := make(map[string]interface{}, len(values)/2)\n\tfor i := 0; i < len(values); i += 2 {\n\t\tkey, ok := values[i].(string)\n\t\tif !ok {\n\t\t\treturn nil, fmt.Errorf(\"map keys must be strings got %T\", values[i])\n\t\t}\n\t\tm[key] = values[i+1]\n\t}\n\n\treturn m, nil\n}\n"
  },
  {
    "path": "tools/gen-jscore/main.go",
    "content": "// Command gen-jscore generates go representations of JavaScript core types file.\npackage main\n\nimport (\n\t\"embed\"\n\t\"flag\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"os/exec\"\n\t\"strings\"\n\t\"text/template\"\n\n\t\"gopkg.in/yaml.v3\"\n)\n\n//go:embed .gen-jscore.yaml\nvar configData []byte\n\n//go:embed templates/*\nvar templates embed.FS\n\n// jsType represents JavaScript type to generate.\ntype jsType struct {\n\tPrototype       *prototype `yaml:\"prototype\"`\n\tName            string     `yaml:\"name\"`\n\tObjectClass     string     `yaml:\"objectClass\"`\n\tObjectPrototype string     `yaml:\"objectPrototype\"`\n\tClass           string     `yaml:\"class\"`\n\tValue           string     `yaml:\"value\"`\n\tProperties      []property `yaml:\"properties\"`\n\tCore            bool       `yaml:\"core\"`\n}\n\n// BlankConstructor is a default fallback returning false for templates.\nfunc (t jsType) BlankConstructor() bool {\n\treturn false\n}\n\n// prototype represents a JavaScript prototype to generate.\ntype prototype struct {\n\tValue       string     `yaml:\"value\"`\n\tObjectClass string     `yaml:\"objectClass\"`\n\tPrototype   string     `yaml:\"prototype\"`\n\tProperties  []property `yaml:\"properties\"`\n}\n\n// Property returns the property with the given name.\nfunc (p prototype) Property(name string) (*property, error) {\n\tfor _, prop := range p.Properties {\n\t\tif prop.Name == name {\n\t\t\treturn &prop, nil\n\t\t}\n\t}\n\n\treturn nil, fmt.Errorf(\"missing property %q\", name)\n}\n\n// property represents a JavaScript property to generate.\ntype property struct {\n\tName     string `yaml:\"name\"`\n\tCall     string `yaml:\"call\"`\n\tMode     string `yaml:\"mode\"`\n\tValue    string `yaml:\"value\"`\n\tKind     string `yaml:\"kind\"`\n\tFunction int    `yaml:\"function\"`\n}\n\n// value represents a JavaScript value to generate a Value creator for.\ntype value struct {\n\tName string `yaml:\"name\"`\n\tType string `yaml:\"type\"`\n}\n\n// config represents our configuration.\ntype config struct {\n\tTypes  []jsType `yaml:\"types\"`\n\tValues []value  `yaml:\"values\"`\n\tLog    jsType   `yaml:\"log\"`\n}\n\n// Type returns the type for name.\nfunc (c config) Type(name string) (*jsType, error) {\n\tfor _, t := range c.Types {\n\t\tif t.Name == name {\n\t\t\treturn &t, nil\n\t\t}\n\t}\n\n\treturn nil, fmt.Errorf(\"missing type %q\", name)\n}\n\n// generate generates the context file writing the output to filename.\nfunc generate(filename string) (err error) {\n\tvar cfg config\n\tif err = yaml.Unmarshal(configData, &cfg); err != nil {\n\t\treturn fmt.Errorf(\"decode config: %w\", err)\n\t}\n\n\ttmpl := template.New(\"base\").Funcs(template.FuncMap{\n\t\t\"ucfirst\":  ucfirst,\n\t\t\"dict\":     dict,\n\t\t\"contains\": strings.Contains,\n\t})\n\n\ttmpl, err = tmpl.ParseFS(templates, \"templates/*.tmpl\")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"parse templates: %w\", err)\n\t}\n\n\toutput, err := os.Create(filename) //nolint:gosec\n\tif err != nil {\n\t\treturn fmt.Errorf(\"open output: %w\", err)\n\t}\n\n\tdefer func() {\n\t\tif errc := output.Close(); err == nil && errc != nil {\n\t\t\terr = errc\n\t\t}\n\t}()\n\n\tif err = tmpl.ExecuteTemplate(output, \"root.tmpl\", cfg); err != nil {\n\t\treturn fmt.Errorf(\"execute template: %w\", err)\n\t}\n\n\tcmd := exec.Command(\"gofmt\", \"-w\", filename)\n\tbuf, err := cmd.CombinedOutput()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"format output %q: %w\", string(buf), err)\n\t}\n\n\treturn nil\n}\n\nfunc main() {\n\tvar filename string\n\tflag.StringVar(&filename, \"output\", \"inline.go\", \"the filename to write the generated code to\")\n\tif err := generate(filename); err != nil {\n\t\tlog.Fatal(err)\n\t}\n}\n"
  },
  {
    "path": "tools/gen-jscore/templates/constructor.tmpl",
    "content": "{{- with .Prototype.Property \"constructor\"}}\n    // {{$.Name}} constructor definition.\n    rt.global.{{$.Name}}Prototype.property[{{template \"name.tmpl\" .Name}}] = property{{template \"property-value.tmpl\" dict \"Name\" $.Name \"Core\" true \"Property\" .}}\n{{- end}}\n"
  },
  {
    "path": "tools/gen-jscore/templates/core-prototype-property.tmpl",
    "content": "{{/* Expects .(jsType) */}}\n\n// {{.Name}} prototype property definition.\nrt.global.{{.Name}}Prototype.property = {{template \"property.tmpl\" dict \"Name\" .Name \"BlankConstructor\" true \"Properties\" .Prototype.Properties}}\nrt.global.{{.Name}}Prototype.propertyOrder = {{template \"property-order.tmpl\" .Prototype}}{{/* No newline. */}}\n"
  },
  {
    "path": "tools/gen-jscore/templates/definition.tmpl",
    "content": "&object{\n    runtime:     rt,\n    class:       class{{or .Class \"Function\"}}Name,\n    objectClass: class{{or .ObjectClass \"Object\"}},\n    prototype:   rt.global.{{or .ObjectPrototype \"Function\"}}Prototype,\n    extensible:  true,\n    {{- if not .Class}}\n    value: nativeFunctionObject{\n            name:      class{{or .Value .Name}}Name,\n            call:      builtin{{or .Value .Name}},\n            construct: builtinNew{{or .Value .Name}},\n    },\n    {{- end}}\n    {{- template \"property-fields.tmpl\" .}}\n}{{/* No newline */ -}}\n"
  },
  {
    "path": "tools/gen-jscore/templates/function.tmpl",
    "content": "&object{\n    runtime:     rt,\n    class:       classFunctionName,\n    objectClass: classObject,\n    prototype:   rt.global.FunctionPrototype,\n    extensible:  true,\n    property: map[string]property{\n        propertyLength: {\n            mode: 0,\n            value: Value{\n                kind:  valueNumber,\n                value: {{if eq .Property.Function -1}}0{{else}}{{.Property.Function}}{{end}},\n            },\n        },\n        propertyName: {\n            mode: 0,\n            value: Value{\n                kind:  valueString,\n                value: \"{{.Property.Name}}\",\n            },\n        },\n    },\n    propertyOrder: []string{\n        propertyLength,\n        propertyName,\n    },\n    value: nativeFunctionObject{\n        name: {{template \"name.tmpl\" .Property.Name}},\n        call: builtin{{if .Property.Call}}{{.Property.Call}}{{else}}{{.Name}}{{.Property.Name | ucfirst}}{{end}},\n    },\n}{{/* No newline. */ -}}\n"
  },
  {
    "path": "tools/gen-jscore/templates/global.tmpl",
    "content": "// {{.Name}} properties.\nrt.globalObject.property = {{template \"property.tmpl\" .}}\n\n// {{.Name}} property order.\nrt.globalObject.propertyOrder = {{template \"property-order.tmpl\" . -}}\n"
  },
  {
    "path": "tools/gen-jscore/templates/name.tmpl",
    "content": "{{- if eq . \"length\" \"prototype\" \"constructor\" -}}\nproperty{{ucfirst .}}\n{{- else if eq . \"toString\" -}}\nmethodToString\n{{- else if eq . \"Object\" \"Function\" \"Array\" \"String\" \"Boolean\" \"Number\" \"Math\" \"Date\" \"RegExp\"\n    \"Error\" \"EvalError\" \"TypeError\" \"RangeError\" \"ReferenceError\" \"SyntaxError\" \"URIError\" \"JSON\" -}}\nclass{{.}}Name\n{{- else -}}\n\"{{.}}\"\n{{- end -}}\n"
  },
  {
    "path": "tools/gen-jscore/templates/property-entry.tmpl",
    "content": "{{- template \"name.tmpl\" .Property.Name}}: {{- template \"property-value.tmpl\" .}},{{/* No newline */ -}}\n"
  },
  {
    "path": "tools/gen-jscore/templates/property-fields.tmpl",
    "content": "{{- /* expects .Name and .Properties */ -}}\n{{if .Properties}}\nproperty: {{template \"property.tmpl\" .}},\npropertyOrder: {{template \"property-order.tmpl\" .}},\n{{end -}}\n"
  },
  {
    "path": "tools/gen-jscore/templates/property-order.tmpl",
    "content": "{{- /* expects .Properties */ -}}\n[]string{\n{{range .Properties -}}\n    {{template \"name.tmpl\" .Name}},\n{{end -}}\n}{{/* No newline */ -}}\n"
  },
  {
    "path": "tools/gen-jscore/templates/property-value.tmpl",
    "content": "{{with .Property}} {\n    mode: {{if .Mode}}{{.Mode}}{{else if or .Function (eq .Name \"constructor\")}}0o101{{else}}0{{end}},\n    {{- if eq .Name \"constructor\" | and $.BlankConstructor}}\n    value: Value{},\n    {{- else}}\n    value: Value{\n        kind:  {{if .Kind}}{{.Kind}}{{else if eq .Name \"length\"}}valueNumber{{else}}valueObject{{end}},\n        {{- if .Function}}\n        value: {{template \"function.tmpl\" $}},\n        {{- else if .Value}}\n        value: {{.Value}},\n        {{- end}}\n    },\n    {{- end}}\n}{{end -}}\n"
  },
  {
    "path": "tools/gen-jscore/templates/property.tmpl",
    "content": "{{- /* Expects .Name and .Properties */ -}}\nmap[string]property{\n{{range .Properties -}}\n    {{- /* Skip constructor which is output later. */}}\n    {{- if eq .Name \"constructor\" | not -}}\n        {{template \"property-entry.tmpl\" dict \"Name\" $.Name \"BlankConstructor\" $.BlankConstructor \"Property\" .}}\n    {{end -}}\n{{end -}}\n}{{/* No newline */ -}}\n"
  },
  {
    "path": "tools/gen-jscore/templates/prototype.tmpl",
    "content": "{{/* Expects .Name.(jsType.Name), .Prototype and optional .BlankConstructor */}}\n{{- with .Prototype}}\n// {{$.Name}} prototype.\nrt.global.{{$.Name}}Prototype = &object{\n    runtime:     rt,\n    class:       class{{$.Name}}Name,\n    objectClass: class{{or .ObjectClass \"Object\"}},\n    prototype:   {{if .Prototype}}rt.global.{{.Prototype}}Prototype{{else}}nil{{end}},\n    extensible:  true,\n    value:       {{or .Value (print \"prototypeValue\" $.Name)}},\n    {{- if not $.Core}}\n        {{- template \"property-fields.tmpl\" dict \"Name\" $.Name \"BlankConstructor\" $.BlankConstructor \"Properties\" .Properties}}\n    {{- end}}\n}\n{{- end -}}\n"
  },
  {
    "path": "tools/gen-jscore/templates/root.tmpl",
    "content": "// Code generated by tools/gen-jscore. DO NOT EDIT.\n\npackage otto\n\nimport (\n\t\"math\"\n)\n\nfunc (rt *runtime) newContext() {\n    // Order here is import as definitions depend on each other.\n    {{- $object := .Type \"Object\"}}\n    {{- $function := .Type \"Function\"}}\n    {{template \"prototype.tmpl\" $object}}\n    {{template \"prototype.tmpl\" $function}}\n\n    {{- template \"core-prototype-property.tmpl\" $object}}\n    {{- template \"core-prototype-property.tmpl\" $function}}\n\n    {{- template \"type.tmpl\" $object}}\n    {{- template \"type.tmpl\" $function}}\n\n    {{- range .Types}}\n        {{- if eq .Name \"Global\"}}\n            {{template \"global.tmpl\" . }}\n        {{- else if not .Core}}\n            {{template \"type.tmpl\" .}}\n        {{- end}}\n    {{- end}}\n}\n\nfunc (rt *runtime) newConsole() *object {\n    return {{template \"definition.tmpl\" .Log}}\n}\n\n{{range .Values}}\n    {{template \"value.tmpl\" .}}\n{{- end}}\n"
  },
  {
    "path": "tools/gen-jscore/templates/type.tmpl",
    "content": "{{if not .Core | and .Prototype}}\n{{template \"prototype.tmpl\" dict \"Name\" .Name \"Prototype\" .Prototype}}\n{{- end}}\n\n// {{.Name}} definition.\nrt.global.{{.Name}} = {{template \"definition.tmpl\" .}}\n\n{{- if .Prototype}}\n{{template \"constructor.tmpl\" .}}\n{{- end}}\n"
  },
  {
    "path": "tools/gen-jscore/templates/value.tmpl",
    "content": "func {{.Name}}Value(value {{or .Type .Name}}) Value {\n\treturn Value{\n\t\tkind:\n{{- if contains .Name \"string\"}}\nvalueString\n{{- else if contains .Name \"bool\"}}\nvalueBoolean\n{{- else if contains .Name \"object\"}}\nvalueObject\n{{- else}}\nvalueNumber\n{{- end}},\n\t\tvalue: value,\n\t}\n}\n"
  },
  {
    "path": "tools/gen-tokens/.gen-tokens.yaml",
    "content": "tokens:\n  - group: Control\n  - name: ILLEGAL\n  - name: EOF\n  - name: COMMENT\n  - name: KEYWORD\n\n  - group: Types\n  - name: STRING\n  - name: BOOLEAN\n  - name: \"NULL\"\n  - name: NUMBER\n  - name: IDENTIFIER\n\n  - group: Maths\n  - name: PLUS\n    symbol: \"+\"\n  - name: MINUS\n    symbol: \"-\"\n  - name: MULTIPLY\n    symbol: \"*\"\n  - name: SLASH\n    symbol: \"/\"\n  - name: REMAINDER\n    symbol: \"%\"\n\n  - group: Logical and bitwise operators\n  - name: AND\n    symbol: \"&\"\n  - name: OR\n    symbol: \"|\"\n  - name: EXCLUSIVE_OR\n    symbol: \"^\"\n  - name: SHIFT_LEFT\n    symbol: \"<<\"\n  - name: SHIFT_RIGHT\n    symbol: \">>\"\n  - name: UNSIGNED_SHIFT_RIGHT\n    symbol: \">>>\"\n  - name: AND_NOT\n    symbol: \"&^\"\n\n  - group: Math assignments\n  - name: ADD_ASSIGN\n    symbol: \"+=\"\n  - name: SUBTRACT_ASSIGN\n    symbol: \"-=\"\n  - name: MULTIPLY_ASSIGN\n    symbol: \"*=\"\n  - name: QUOTIENT_ASSIGN\n    symbol: \"/=\"\n  - name: REMAINDER_ASSIGN\n    symbol: \"%=\"\n\n  - group: Math and bitwise assignments\n  - name: AND_ASSIGN\n    symbol: \"&=\"\n  - name: OR_ASSIGN\n    symbol: \"|=\"\n  - name: EXCLUSIVE_OR_ASSIGN\n    symbol: \"^=\"\n  - name: SHIFT_LEFT_ASSIGN\n    symbol: \"<<=\"\n  - name: SHIFT_RIGHT_ASSIGN\n    symbol: \">>=\"\n  - name: UNSIGNED_SHIFT_RIGHT_ASSIGN\n    symbol: \">>>=\"\n  - name: AND_NOT_ASSIGN\n    symbol: \"&^=\"\n\n  - group: Logical operators and decrement / increment\n  - name: LOGICAL_AND\n    symbol: \"&&\"\n  - name: LOGICAL_OR\n    symbol: \"||\"\n  - name: INCREMENT\n    symbol: \"++\"\n  - name: DECREMENT\n    symbol: \"--\"\n\n  - group: Comparison operators\n  - name: EQUAL\n    symbol: \"==\"\n  - name: STRICT_EQUAL\n    symbol: \"===\"\n  - name: LESS\n    symbol: \"<\"\n  - name: GREATER\n    symbol: \">\"\n  - name: ASSIGN\n    symbol: \"=\"\n  - name: NOT\n    symbol: \"!\"\n\n  - group: Bitwise not\n  - name: BITWISE_NOT\n    symbol: \"~\"\n\n  - group: Comparison operators\n  - name: NOT_EQUAL\n    symbol: \"!=\"\n  - name: STRICT_NOT_EQUAL\n    symbol: \"!==\"\n  - name: LESS_OR_EQUAL\n    symbol: \"<=\"\n  - name: GREATER_OR_EQUAL\n    symbol: \">=\"\n\n  - group: Left operators\n  - name: LEFT_PARENTHESIS\n    symbol: \"(\"\n  - name: LEFT_BRACKET\n    symbol: \"[\"\n  - name: LEFT_BRACE\n    symbol: \"{\"\n  - name: COMMA\n    symbol: \",\"\n  - name: PERIOD\n    symbol: \".\"\n\n  - group: Right operators\n  - name: RIGHT_PARENTHESIS\n    symbol: \")\"\n  - name: RIGHT_BRACKET\n    symbol: \"]\"\n  - name: RIGHT_BRACE\n    symbol: \"}\"\n  - name: SEMICOLON\n    symbol: \";\"\n  - name: COLON\n    symbol: \":\"\n  - name: QUESTION_MARK\n    symbol: \"?\"\n\n  - group: Basic flow - keywords below here\n  - name: _\n  - name: IF\n  - name: IN\n  - name: DO\n\n  - group: Declarations\n  - name: VAR\n  - name: FOR\n  - name: NEW\n  - name: TRY\n\n  - group: Advanced flow\n  - name: THIS\n  - name: ELSE\n  - name: CASE\n  - name: VOID\n  - name: WITH\n\n  - group: Loops\n  - name: WHILE\n  - name: BREAK\n  - name: CATCH\n  - name: THROW\n\n  - group: Functions\n  - name: RETURN\n  - name: TYPEOF\n  - name: DELETE\n  - name: SWITCH\n\n  - group: Fallback identifiers\n  - name: DEFAULT\n  - name: FINALLY\n\n  - group: Miscellaneous\n  - name: FUNCTION\n  - name: CONTINUE\n  - name: DEBUGGER\n\n  - group: Instance of\n  - name: INSTANCEOF\n\n  # Future\n  - name: const\n    future: true\n  - name: class\n    future: true\n  - name: enum\n    future: true\n  - name: export\n    future: true\n  - name: extends\n    future: true\n  - name: import\n    future: true\n  - name: super\n    future: true\n\n  # Future Strict items\n  - name: implements\n    future: true\n    strict: true\n  - name: interface\n    future: true\n    strict: true\n  - name: let\n    future: true\n    strict: true\n  - name: package\n    future: true\n    strict: true\n  - name: private\n    future: true\n    strict: true\n  - name: protected\n    future: true\n    strict: true\n  - name: public\n    future: true\n    strict: true\n  - name: static\n    future: true\n    strict: true\n"
  },
  {
    "path": "tools/gen-tokens/main.go",
    "content": "// Command gen-tokens generates go representations of JavaScript tokens.\npackage main\n\nimport (\n\t\"embed\"\n\t\"flag\"\n\t\"fmt\"\n\t\"log\"\n\t\"os\"\n\t\"os/exec\"\n\t\"strings\"\n\t\"text/template\"\n\n\t\"gopkg.in/yaml.v3\"\n)\n\n//go:embed .gen-tokens.yaml\nvar configData []byte\n\n//go:embed templates/*\nvar templates embed.FS\n\n// token represents a JavaScript token.\ntype token struct {\n\tGroup  string `yaml:\"group\"`\n\tName   string `yaml:\"name\"`\n\tSymbol string `yaml:\"symbol\"`\n\tFuture bool   `yaml:\"future\"`\n\tStrict bool   `yaml:\"strict\"`\n}\n\n// config represents our configuration.\ntype config struct {\n\tTokens []token `yaml:\"tokens\"`\n}\n\n// generate generates the context file writing the output to filename.\nfunc generate(filename string) (err error) {\n\tvar cfg config\n\tif err = yaml.Unmarshal(configData, &cfg); err != nil {\n\t\treturn fmt.Errorf(\"decode config: %w\", err)\n\t}\n\n\ttmpl := template.New(\"base\").Funcs(template.FuncMap{\n\t\t\"toLower\": strings.ToLower,\n\t})\n\n\ttmpl, err = tmpl.ParseFS(templates, \"templates/*.tmpl\")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"parse templates: %w\", err)\n\t}\n\n\toutput, err := os.Create(filename) //nolint:gosec\n\tif err != nil {\n\t\treturn fmt.Errorf(\"open output: %w\", err)\n\t}\n\n\tdefer func() {\n\t\tif errc := output.Close(); err == nil && errc != nil {\n\t\t\terr = errc\n\t\t}\n\t}()\n\n\tif err = tmpl.ExecuteTemplate(output, \"root.tmpl\", cfg); err != nil {\n\t\treturn fmt.Errorf(\"execute template: %w\", err)\n\t}\n\n\tcmd := exec.Command(\"gofmt\", \"-w\", filename)\n\tbuf, err := cmd.CombinedOutput()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"format output %q: %w\", string(buf), err)\n\t}\n\n\treturn nil\n}\n\nfunc main() {\n\tvar filename string\n\tflag.StringVar(&filename, \"output\", \"token_const.go\", \"the filename to write the generated code to\")\n\tif err := generate(filename); err != nil {\n\t\tlog.Fatal(err)\n\t}\n}\n"
  },
  {
    "path": "tools/gen-tokens/templates/root.tmpl",
    "content": "// Code generated by tools/gen-tokens. DO NOT EDIT.\n\npackage token\n\nconst (\n\t_ Token = iota\n    {{range .Tokens}}\n        {{- if not .Future}}\n            {{- if .Group}}\n                // {{.Group}}.\n            {{- else}}\n                {{.Name}} {{- if .Symbol}}// {{.Symbol}}{{end}}\n            {{- end}}\n        {{- end}}\n    {{- end}}\n)\n\n\nvar token2string = [...]string{\n    {{- $lc := false -}}\n    {{- range .Tokens -}}\n        {{if or .Future .Group | not -}}\n            {{- if eq .Name \"_\" -}}\n                {{$lc = true}}\n            {{- else}}\n                {{- $symbol := or .Symbol .Name}}\n                {{.Name}}: \"{{if $lc}}{{toLower $symbol}}{{else}}{{$symbol}}{{end}}\",\n            {{- end}}\n        {{- end -}}\n    {{- end}}\n}\n\nvar keywordTable = map[string]keyword{\n    {{- $keyword := false -}}\n    {{range .Tokens}}\n        {{- /* First keyword follows _ */ -}}\n        {{- if eq .Name \"_\"}}{{$keyword = true}}{{continue}}{{end}}\n        {{- if $keyword}}\n            {{- if or .Symbol .Group | not}}\n                \"{{toLower .Name}}\": {\n                    {{- if .Future}}\n                    token: KEYWORD,\n                    futureKeyword: true,\n                    {{- else}}\n                    token: {{.Name}},\n                    {{- end}}\n                    {{- if .Strict}}\n                    strict:        true,\n                    {{- end}}\n                },\n            {{- end -}}\n        {{end -}}\n    {{- end}}\n}\n"
  },
  {
    "path": "tools/tester/main.go",
    "content": "// Command tester automates the ability to download a suite of JavaScript libraries from a CDN and check if otto can handle them.\n//\n// It provides two commands via flags:\n// * -fetch = Fetch all libraries from the CDN and store them in local testdata directory.\n// * -report [file1 file2 ... fileN] = Report the results of trying to run the given or if empty all libraries in the testdata directory.\npackage main\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"errors\"\n\t\"flag\"\n\t\"fmt\"\n\t\"io\"\n\t\"io/fs\"\n\t\"net/http\"\n\t\"os\"\n\t\"path/filepath\"\n\t\"regexp\"\n\t\"runtime\"\n\t\"strings\"\n\t\"sync\"\n\t\"text/tabwriter\"\n\t\"time\"\n\n\t\"github.com/robertkrimen/otto\"\n\t\"github.com/robertkrimen/otto/parser\"\n)\n\nconst (\n\t// dataDir is where the libraries are downloaded to.\n\tdataDir = \"testdata\"\n\n\t// downloadWorkers is the number of workers that process downloads.\n\tdownloadWorkers = 40\n\n\t// librariesURL is the source for JavaScript libraries for testing.\n\tlibrariesURL = \"http://api.cdnjs.com/libraries\"\n\n\t// requestTimeout is the maximum time we wait for a request to complete.\n\trequestTimeout = time.Second * 20\n)\n\nvar (\n\t// testWorkers is the number of workers that process report.\n\ttestWorkers = min(10, runtime.GOMAXPROCS(0))\n\n\t// noopConsole is a noopConsole which ignore log requests.\n\tnoopConsole = map[string]interface{}{\n\t\t\"log\": func(call otto.FunctionCall) otto.Value {\n\t\t\treturn otto.UndefinedValue()\n\t\t},\n\t}\n)\n\nvar (\n\tmatchReferenceErrorNotDefined = regexp.MustCompile(`^ReferenceError: \\S+ is not defined$`)\n\tmatchLookahead                = regexp.MustCompile(`Invalid regular expression: re2: Invalid \\(\\?[=!]\\) <lookahead>`)\n\tmatchBackReference            = regexp.MustCompile(`Invalid regular expression: re2: Invalid \\\\\\d <backreference>`)\n\tmatchTypeErrorUndefined       = regexp.MustCompile(`^TypeError: Cannot access member '[^']+' of undefined$`)\n)\n\n// broken identifies libraries which fail with a fatal error, so must be skipped.\nvar broken = map[string]string{\n\t\"lets-plot.js\":      \"stack overflow\",\n\t\"knockout-es5.js\":   \"stack overflow\",\n\t\"sendbird-calls.js\": \"runtime: out of memory\",\n}\n\n// libraries represents fetch all libraries response.\ntype libraries struct {\n\tResults []library `json:\"results\"`\n}\n\n// library represents a single library in a libraries response.\ntype library struct {\n\tName   string `json:\"name\"`\n\tLatest string `json:\"latest\"`\n}\n\n// fetch fetches itself and stores it in the dataDir.\nfunc (l library) fetch() error {\n\tif !strings.HasSuffix(l.Latest, \".js\") {\n\t\treturn nil\n\t}\n\n\tctx, cancel := context.WithTimeout(context.Background(), requestTimeout)\n\tdefer cancel()\n\n\treq, err := http.NewRequestWithContext(ctx, http.MethodGet, l.Latest, nil)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"request library %q: %w\", l.Name, err)\n\t}\n\n\tresp, err := http.DefaultClient.Do(req)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"get library %q: %w\", l.Name, err)\n\t}\n\tdefer resp.Body.Close() //nolint:errcheck\n\n\tname := l.Name\n\tif !strings.HasSuffix(name, \".js\") {\n\t\tname += \".js\"\n\t}\n\n\tf, err := os.Create(filepath.Join(dataDir, name)) //nolint:gosec\n\tif err != nil {\n\t\treturn fmt.Errorf(\"create library %q: %w\", l.Name, err)\n\t}\n\n\tif _, err = io.Copy(f, resp.Body); err != nil {\n\t\treturn fmt.Errorf(\"write library %q: %w\", l.Name, err)\n\t}\n\n\treturn nil\n}\n\n// test runs the code from filename returning the time it took and any error\n// encountered when running a full parse without IgnoreRegExpErrors in parseError.\nfunc test(filename string) (took time.Duration, parseError, err error) { //nolint:nonamedreturns\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\terr = fmt.Errorf(\"panic on %q: %v\", filename, r)\n\t\t}\n\t}()\n\tnow := time.Now()\n\tdefer func() {\n\t\t// Always set took.\n\t\ttook = time.Since(now)\n\t}()\n\n\tif val := broken[filepath.Base(filename)]; val != \"\" {\n\t\treturn 0, nil, fmt.Errorf(\"fatal %q\", val)\n\t}\n\n\tscript, err := os.ReadFile(filename) //nolint:gosec\n\tif err != nil {\n\t\treturn 0, nil, err\n\t}\n\n\tvm := otto.New()\n\tif err = vm.Set(\"console\", noopConsole); err != nil {\n\t\treturn 0, nil, fmt.Errorf(\"set console: %w\", err)\n\t}\n\n\tprog, err := parser.ParseFile(nil, filename, string(script), 0)\n\tif err != nil {\n\t\tval := err.Error()\n\t\tswitch {\n\t\tcase matchReferenceErrorNotDefined.MatchString(val),\n\t\t\tmatchTypeErrorUndefined.MatchString(val),\n\t\t\tmatchLookahead.MatchString(val),\n\t\t\tmatchBackReference.MatchString(val):\n\t\t\t// RegExp issues, retry with IgnoreRegExpErrors.\n\t\t\tparseError = err\n\t\t\tif _, err = parser.ParseFile(nil, filename, string(script), parser.IgnoreRegExpErrors); err != nil {\n\t\t\t\treturn 0, nil, err\n\t\t\t}\n\t\t\treturn 0, parseError, nil\n\t\tdefault:\n\t\t\treturn 0, nil, err\n\t\t}\n\t}\n\n\t_, err = vm.Run(prog)\n\treturn 0, nil, err\n}\n\n// fetchAll fetches all files from src.\nfunc fetchAll(src string) error {\n\tctx, cancel := context.WithTimeout(context.Background(), requestTimeout)\n\tdefer cancel()\n\n\treq, err := http.NewRequestWithContext(ctx, http.MethodGet, librariesURL, nil)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"request libraries %q: %w\", src, err)\n\t}\n\n\tresp, err := http.DefaultClient.Do(req)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"get libraries %q: %w\", src, err)\n\t}\n\tdefer resp.Body.Close() //nolint:errcheck\n\n\tvar libs libraries\n\tdec := json.NewDecoder(resp.Body)\n\tif err = dec.Decode(&libs); err != nil {\n\t\treturn fmt.Errorf(\"json decode: %w\", err)\n\t}\n\n\tif err = os.Mkdir(dataDir, 0o750); err != nil && !errors.Is(err, fs.ErrExist) {\n\t\treturn fmt.Errorf(\"mkdir: %w\", err)\n\t}\n\n\tvar wg sync.WaitGroup\n\twork := make(chan library, downloadWorkers)\n\terrs := make(chan error, len(libs.Results))\n\twg.Add(downloadWorkers)\n\tfor range downloadWorkers {\n\t\tgo func() {\n\t\t\tdefer wg.Done()\n\t\t\tfor lib := range work {\n\t\t\t\tfmt.Fprint(os.Stdout, \".\")\n\t\t\t\terrs <- lib.fetch()\n\t\t\t}\n\t\t}()\n\t}\n\n\tfmt.Fprintf(os.Stdout, \"Downloading %d libraries with %d workers ...\", len(libs.Results), downloadWorkers)\n\twg.Add(1)\n\tgo func() {\n\t\tdefer wg.Done()\n\t\tfor _, lib := range libs.Results {\n\t\t\twork <- lib\n\t\t}\n\t\tclose(work)\n\t}()\n\n\twg.Wait()\n\tclose(errs)\n\tfmt.Fprintln(os.Stdout, \" done\")\n\n\tfor e := range errs {\n\t\tif e != nil {\n\t\t\tfmt.Fprintln(os.Stderr, e)\n\t\t\terr = e\n\t\t}\n\t}\n\n\treturn err\n}\n\n// result represents the result from a test.\ntype result struct {\n\terr        error\n\tparseError error\n\tfilename   string\n\ttook       time.Duration\n}\n\n// report runs test for all specified files, if none a specified all\n// JavaScript files in our dataDir, outputting the results.\nfunc report(files []string) error {\n\tif len(files) == 0 {\n\t\tvar err error\n\t\tfiles, err = filepath.Glob(filepath.Join(dataDir, \"*.js\"))\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"read dir: %w\", err)\n\t\t}\n\t}\n\n\tvar wg sync.WaitGroup\n\tworkers := min(testWorkers, len(files))\n\twork := make(chan string, workers)\n\tresults := make(chan result, len(files))\n\twg.Add(workers)\n\tfor range workers {\n\t\tgo func() {\n\t\t\tdefer wg.Done()\n\t\t\tfor f := range work {\n\t\t\t\tfmt.Fprint(os.Stdout, \".\")\n\t\t\t\ttook, parseError, err := test(f)\n\t\t\t\tresults <- result{\n\t\t\t\t\tfilename:   f,\n\t\t\t\t\terr:        err,\n\t\t\t\t\tparseError: parseError,\n\t\t\t\t\ttook:       took,\n\t\t\t\t}\n\t\t\t}\n\t\t}()\n\t}\n\n\tfmt.Fprintf(os.Stdout, \"Reporting on %d libs with %d workers...\", len(files), workers)\n\twg.Add(1)\n\tgo func() {\n\t\tdefer wg.Done()\n\t\tfor _, f := range files {\n\t\t\twork <- f\n\t\t}\n\t\tclose(work)\n\t}()\n\n\twg.Wait()\n\tclose(results)\n\tfmt.Fprintln(os.Stdout, \" done\")\n\n\tvar fail, pass, parse int\n\twriter := tabwriter.NewWriter(os.Stdout, 0, 8, 0, '\\t', 0)\n\tfmt.Fprintln(writer, \"Library\", \"\\t| Took\", \"\\t| Status\")\n\tfmt.Fprintln(writer, \"-------\", \"\\t| ----\", \"\\t| ------\")\n\n\tfor res := range results {\n\t\tswitch {\n\t\tcase res.err != nil:\n\t\t\tfmt.Fprintf(writer, \"%s\\t| %v\\t| fail: %v\\n\", res.filename, res.took, res.err)\n\t\t\tfail++\n\t\tcase res.parseError != nil:\n\t\t\tfmt.Fprintf(writer, \"%s\\t| %v\\t| pass parse: %v\\n\", res.filename, res.took, res.parseError)\n\t\t\tparse++\n\t\tdefault:\n\t\t\tfmt.Fprintf(writer, \"%s\\t| %v\\t| pass\\n\", res.filename, res.took)\n\t\t\tpass++\n\t\t}\n\t}\n\n\tif err := writer.Flush(); err != nil {\n\t\treturn fmt.Errorf(\"flush: %w\", err)\n\t}\n\n\tfmt.Fprintf(os.Stdout, \"\\nSummary:\\n - %d passes\\n - %d parse passes\\n - %d fails\\n\", pass, parse, fail)\n\n\treturn nil\n}\n\nfunc main() {\n\tflagFetch := flag.Bool(\"fetch\", false, \"fetch all libraries for testing\")\n\tflagReport := flag.Bool(\"report\", false, \"test and report the named files or all libraries if non specified\")\n\tflag.Parse()\n\n\tvar err error\n\tswitch {\n\tcase *flagFetch:\n\t\terr = fetchAll(librariesURL)\n\tcase *flagReport:\n\t\terr = report(flag.Args())\n\tdefault:\n\t\tflag.PrintDefaults()\n\t\terr = errors.New(\"missing flag\")\n\t}\n\tif err != nil {\n\t\tfmt.Fprintln(os.Stderr, err)\n\t\tos.Exit(64)\n\t}\n}\n"
  },
  {
    "path": "type_arguments.go",
    "content": "package otto\n\nimport (\n\t\"strconv\"\n)\n\nfunc (rt *runtime) newArgumentsObject(indexOfParameterName []string, stash stasher, length int) *object {\n\tobj := rt.newClassObject(\"Arguments\")\n\n\tfor index := range indexOfParameterName {\n\t\tname := strconv.FormatInt(int64(index), 10)\n\t\tobjectDefineOwnProperty(obj, name, property{Value{}, 0o111}, false)\n\t}\n\n\tobj.objectClass = classArguments\n\tobj.value = argumentsObject{\n\t\tindexOfParameterName: indexOfParameterName,\n\t\tstash:                stash,\n\t}\n\n\tobj.prototype = rt.global.ObjectPrototype\n\n\tobj.defineProperty(propertyLength, intValue(length), 0o101, false)\n\n\treturn obj\n}\n\ntype argumentsObject struct {\n\tstash                stasher\n\tindexOfParameterName []string\n}\n\nfunc (o argumentsObject) clone(c *cloner) argumentsObject {\n\tindexOfParameterName := make([]string, len(o.indexOfParameterName))\n\tcopy(indexOfParameterName, o.indexOfParameterName)\n\treturn argumentsObject{\n\t\tindexOfParameterName: indexOfParameterName,\n\t\tstash:                c.stash(o.stash),\n\t}\n}\n\nfunc (o argumentsObject) get(name string) (Value, bool) {\n\tindex := stringToArrayIndex(name)\n\tif index >= 0 && index < int64(len(o.indexOfParameterName)) {\n\t\tif name = o.indexOfParameterName[index]; name == \"\" {\n\t\t\treturn Value{}, false\n\t\t}\n\t\treturn o.stash.getBinding(name, false), true\n\t}\n\treturn Value{}, false\n}\n\nfunc (o argumentsObject) put(name string, value Value) {\n\tindex := stringToArrayIndex(name)\n\tname = o.indexOfParameterName[index]\n\to.stash.setBinding(name, value, false)\n}\n\nfunc (o argumentsObject) delete(name string) {\n\tindex := stringToArrayIndex(name)\n\to.indexOfParameterName[index] = \"\"\n}\n\nfunc argumentsGet(obj *object, name string) Value {\n\tif value, exists := obj.value.(argumentsObject).get(name); exists {\n\t\treturn value\n\t}\n\treturn objectGet(obj, name)\n}\n\nfunc argumentsGetOwnProperty(obj *object, name string) *property {\n\tprop := objectGetOwnProperty(obj, name)\n\tif value, exists := obj.value.(argumentsObject).get(name); exists {\n\t\tprop.value = value\n\t}\n\treturn prop\n}\n\nfunc argumentsDefineOwnProperty(obj *object, name string, descriptor property, throw bool) bool {\n\tif _, exists := obj.value.(argumentsObject).get(name); exists {\n\t\tif !objectDefineOwnProperty(obj, name, descriptor, false) {\n\t\t\treturn obj.runtime.typeErrorResult(throw)\n\t\t}\n\t\tif value, valid := descriptor.value.(Value); valid {\n\t\t\tobj.value.(argumentsObject).put(name, value)\n\t\t}\n\t\treturn true\n\t}\n\treturn objectDefineOwnProperty(obj, name, descriptor, throw)\n}\n\nfunc argumentsDelete(obj *object, name string, throw bool) bool {\n\tif !objectDelete(obj, name, throw) {\n\t\treturn false\n\t}\n\tif _, exists := obj.value.(argumentsObject).get(name); exists {\n\t\tobj.value.(argumentsObject).delete(name)\n\t}\n\treturn true\n}\n"
  },
  {
    "path": "type_array.go",
    "content": "package otto\n\nimport (\n\t\"strconv\"\n)\n\nfunc (rt *runtime) newArrayObject(length uint32) *object {\n\tobj := rt.newObject()\n\tobj.class = classArrayName\n\tobj.defineProperty(propertyLength, uint32Value(length), 0o100, false)\n\tobj.objectClass = classArray\n\treturn obj\n}\n\nfunc isArray(obj *object) bool {\n\tif obj == nil {\n\t\treturn false\n\t}\n\n\tswitch obj.class {\n\tcase classArrayName, classGoArrayName, classGoSliceName:\n\t\treturn true\n\tdefault:\n\t\treturn false\n\t}\n}\n\nfunc objectLength(obj *object) uint32 {\n\tif obj == nil {\n\t\treturn 0\n\t}\n\tswitch obj.class {\n\tcase classArrayName:\n\t\treturn obj.get(propertyLength).value.(uint32)\n\tcase classStringName:\n\t\treturn uint32(obj.get(propertyLength).value.(int))\n\tcase classGoArrayName, classGoSliceName:\n\t\treturn uint32(obj.get(propertyLength).value.(int))\n\t}\n\treturn 0\n}\n\nfunc arrayUint32(rt *runtime, value Value) uint32 {\n\tnm := value.number()\n\tif nm.kind != numberInteger || !isUint32(nm.int64) {\n\t\t// FIXME\n\t\tpanic(rt.panicRangeError())\n\t}\n\treturn uint32(nm.int64)\n}\n\nfunc arrayDefineOwnProperty(obj *object, name string, descriptor property, throw bool) bool {\n\tlengthProperty := obj.getOwnProperty(propertyLength)\n\tlengthValue, valid := lengthProperty.value.(Value)\n\tif !valid {\n\t\tpanic(\"Array.length != Value{}\")\n\t}\n\n\treject := func(reason string) bool {\n\t\tif throw {\n\t\t\tpanic(obj.runtime.panicTypeError(\"Array.DefineOwnProperty %s\", reason))\n\t\t}\n\t\treturn false\n\t}\n\tlength := lengthValue.value.(uint32)\n\tif name == propertyLength {\n\t\tif descriptor.value == nil {\n\t\t\treturn objectDefineOwnProperty(obj, name, descriptor, throw)\n\t\t}\n\t\tnewLengthValue, isValue := descriptor.value.(Value)\n\t\tif !isValue {\n\t\t\tpanic(obj.runtime.panicTypeError(\"Array.DefineOwnProperty %q is not a value\", descriptor.value))\n\t\t}\n\t\tnewLength := arrayUint32(obj.runtime, newLengthValue)\n\t\tdescriptor.value = uint32Value(newLength)\n\t\tif newLength > length {\n\t\t\treturn objectDefineOwnProperty(obj, name, descriptor, throw)\n\t\t}\n\t\tif !lengthProperty.writable() {\n\t\t\treturn reject(\"property length for not writable\")\n\t\t}\n\t\tnewWritable := true\n\t\tif descriptor.mode&0o700 == 0 {\n\t\t\t// If writable is off\n\t\t\tnewWritable = false\n\t\t\tdescriptor.mode |= 0o100\n\t\t}\n\t\tif !objectDefineOwnProperty(obj, name, descriptor, throw) {\n\t\t\treturn false\n\t\t}\n\t\tfor newLength < length {\n\t\t\tlength--\n\t\t\tif !obj.delete(strconv.FormatInt(int64(length), 10), false) {\n\t\t\t\tdescriptor.value = uint32Value(length + 1)\n\t\t\t\tif !newWritable {\n\t\t\t\t\tdescriptor.mode &= 0o077\n\t\t\t\t}\n\t\t\t\tobjectDefineOwnProperty(obj, name, descriptor, false)\n\t\t\t\treturn reject(\"delete failed\")\n\t\t\t}\n\t\t}\n\t\tif !newWritable {\n\t\t\tdescriptor.mode &= 0o077\n\t\t\tobjectDefineOwnProperty(obj, name, descriptor, false)\n\t\t}\n\t} else if index := stringToArrayIndex(name); index >= 0 {\n\t\tif index >= int64(length) && !lengthProperty.writable() {\n\t\t\treturn reject(\"property length not writable\")\n\t\t}\n\t\tif !objectDefineOwnProperty(obj, strconv.FormatInt(index, 10), descriptor, false) {\n\t\t\treturn reject(\"Object.DefineOwnProperty failed\")\n\t\t}\n\t\tif index >= int64(length) {\n\t\t\tlengthProperty.value = uint32Value(uint32(index + 1))\n\t\t\tobjectDefineOwnProperty(obj, propertyLength, *lengthProperty, false)\n\t\t\treturn true\n\t\t}\n\t}\n\treturn objectDefineOwnProperty(obj, name, descriptor, throw)\n}\n"
  },
  {
    "path": "type_boolean.go",
    "content": "package otto\n\nfunc (rt *runtime) newBooleanObject(value Value) *object {\n\treturn rt.newPrimitiveObject(classBooleanName, boolValue(value.bool()))\n}\n"
  },
  {
    "path": "type_date.go",
    "content": "package otto\n\nimport (\n\t\"fmt\"\n\t\"math\"\n\t\"regexp\"\n\tTime \"time\"\n)\n\ntype dateObject struct {\n\ttime  Time.Time\n\tvalue Value\n\tepoch int64\n\tisNaN bool\n}\n\nvar invalidDateObject = dateObject{\n\ttime:  Time.Time{},\n\tepoch: -1,\n\tvalue: NaNValue(),\n\tisNaN: true,\n}\n\ntype ecmaTime struct {\n\tlocation    *Time.Location\n\tyear        int\n\tmonth       int\n\tday         int\n\thour        int\n\tminute      int\n\tsecond      int\n\tmillisecond int\n}\n\nfunc newEcmaTime(goTime Time.Time) ecmaTime {\n\treturn ecmaTime{\n\t\tyear:        goTime.Year(),\n\t\tmonth:       dateFromGoMonth(goTime.Month()),\n\t\tday:         goTime.Day(),\n\t\thour:        goTime.Hour(),\n\t\tminute:      goTime.Minute(),\n\t\tsecond:      goTime.Second(),\n\t\tmillisecond: goTime.Nanosecond() / (100 * 100 * 100),\n\t\tlocation:    goTime.Location(),\n\t}\n}\n\nfunc (t *ecmaTime) goTime() Time.Time {\n\treturn Time.Date(\n\t\tt.year,\n\t\tdateToGoMonth(t.month),\n\t\tt.day,\n\t\tt.hour,\n\t\tt.minute,\n\t\tt.second,\n\t\tt.millisecond*(100*100*100),\n\t\tt.location,\n\t)\n}\n\nfunc (d *dateObject) Time() Time.Time {\n\treturn d.time\n}\n\nfunc (d *dateObject) Epoch() int64 {\n\treturn d.epoch\n}\n\nfunc (d *dateObject) Value() Value {\n\treturn d.value\n}\n\n// FIXME A date should only be in the range of -100,000,000 to +100,000,000 (1970): 15.9.1.1.\nfunc (d *dateObject) SetNaN() {\n\td.time = Time.Time{}\n\td.epoch = -1\n\td.value = NaNValue()\n\td.isNaN = true\n}\n\nfunc (d *dateObject) SetTime(time Time.Time) {\n\td.Set(timeToEpoch(time))\n}\n\nfunc (d *dateObject) Set(epoch float64) {\n\t// epoch\n\td.epoch = epochToInteger(epoch)\n\n\t// time\n\ttime, err := epochToTime(epoch)\n\td.time = time // Is either a valid time, or the zero-value for time.Time\n\n\t// value & isNaN\n\tif err != nil {\n\t\td.isNaN = true\n\t\td.epoch = -1\n\t\td.value = NaNValue()\n\t} else {\n\t\td.value = int64Value(d.epoch)\n\t}\n}\n\nfunc epochToInteger(value float64) int64 {\n\tif value > 0 {\n\t\treturn int64(math.Floor(value))\n\t}\n\treturn int64(math.Ceil(value))\n}\n\nfunc epochToTime(value float64) (Time.Time, error) {\n\tepochWithMilli := value\n\tif math.IsNaN(epochWithMilli) || math.IsInf(epochWithMilli, 0) {\n\t\treturn Time.Time{}, fmt.Errorf(\"invalid time %v\", value)\n\t}\n\n\tepoch := int64(epochWithMilli / 1000)\n\tmilli := int64(epochWithMilli) % 1000\n\n\treturn Time.Unix(epoch, milli*1000000).In(utcTimeZone), nil\n}\n\nfunc timeToEpoch(time Time.Time) float64 {\n\treturn float64(time.UnixMilli())\n}\n\nfunc (rt *runtime) newDateObject(epoch float64) *object {\n\tobj := rt.newObject()\n\tobj.class = classDateName\n\n\t// FIXME This is ugly...\n\tdate := dateObject{}\n\tdate.Set(epoch)\n\tobj.value = date\n\treturn obj\n}\n\nfunc (o *object) dateValue() dateObject {\n\tvalue, _ := o.value.(dateObject)\n\treturn value\n}\n\nfunc dateObjectOf(rt *runtime, date *object) dateObject {\n\tif date == nil {\n\t\tpanic(rt.panicTypeError(\"Date.ObjectOf is nil\"))\n\t}\n\tif date.class != classDateName {\n\t\tpanic(rt.panicTypeError(\"Date.ObjectOf %q != %q\", date.class, classDateName))\n\t}\n\treturn date.dateValue()\n}\n\n// JavaScript is 0-based, Go is 1-based (15.9.1.4).\nfunc dateToGoMonth(month int) Time.Month {\n\treturn Time.Month(month + 1)\n}\n\nfunc dateFromGoMonth(month Time.Month) int {\n\treturn int(month) - 1\n}\n\nfunc dateFromGoDay(day Time.Weekday) int {\n\treturn int(day)\n}\n\n// newDateTime returns the epoch of date contained in argumentList for location.\nfunc newDateTime(argumentList []Value, location *Time.Location) float64 {\n\tpick := func(index int, default_ float64) (float64, bool) {\n\t\tif index >= len(argumentList) {\n\t\t\treturn default_, false\n\t\t}\n\t\tvalue := argumentList[index].float64()\n\t\tif math.IsNaN(value) || math.IsInf(value, 0) {\n\t\t\treturn 0, true\n\t\t}\n\t\treturn value, false\n\t}\n\n\tswitch len(argumentList) {\n\tcase 0: // 0-argument\n\t\ttime := Time.Now().In(utcTimeZone)\n\t\treturn timeToEpoch(time)\n\tcase 1: // 1-argument\n\t\tvalue := valueOfArrayIndex(argumentList, 0)\n\t\tvalue = toPrimitiveValue(value)\n\t\tif value.IsString() {\n\t\t\treturn dateParse(value.string())\n\t\t}\n\n\t\treturn value.float64()\n\tdefault: // 2-argument, 3-argument, ...\n\t\tvar year, month, day, hour, minute, second, millisecond float64\n\t\tvar invalid bool\n\t\tif year, invalid = pick(0, 1900.0); invalid {\n\t\t\treturn math.NaN()\n\t\t}\n\t\tif month, invalid = pick(1, 0.0); invalid {\n\t\t\treturn math.NaN()\n\t\t}\n\t\tif day, invalid = pick(2, 1.0); invalid {\n\t\t\treturn math.NaN()\n\t\t}\n\t\tif hour, invalid = pick(3, 0.0); invalid {\n\t\t\treturn math.NaN()\n\t\t}\n\t\tif minute, invalid = pick(4, 0.0); invalid {\n\t\t\treturn math.NaN()\n\t\t}\n\t\tif second, invalid = pick(5, 0.0); invalid {\n\t\t\treturn math.NaN()\n\t\t}\n\t\tif millisecond, invalid = pick(6, 0.0); invalid {\n\t\t\treturn math.NaN()\n\t\t}\n\n\t\tif year >= 0 && year <= 99 {\n\t\t\tyear += 1900\n\t\t}\n\n\t\ttime := Time.Date(int(year), dateToGoMonth(int(month)), int(day), int(hour), int(minute), int(second), int(millisecond)*1000*1000, location)\n\t\treturn timeToEpoch(time)\n\t}\n}\n\nvar (\n\tdateLayoutList = []string{\n\t\t\"2006\",\n\t\t\"2006-01\",\n\t\t\"2006-01-02\",\n\n\t\t\"2006T15:04\",\n\t\t\"2006-01T15:04\",\n\t\t\"2006-01-02T15:04\",\n\n\t\t\"2006T15:04:05\",\n\t\t\"2006-01T15:04:05\",\n\t\t\"2006-01-02T15:04:05\",\n\n\t\t\"2006/01\",\n\t\t\"2006/01/02\",\n\t\t\"2006/01/02 15:04:05\",\n\n\t\t\"2006T15:04:05.000\",\n\t\t\"2006-01T15:04:05.000\",\n\t\t\"2006-01-02T15:04:05.000\",\n\n\t\t\"2006T15:04-0700\",\n\t\t\"2006-01T15:04-0700\",\n\t\t\"2006-01-02T15:04-0700\",\n\n\t\t\"2006T15:04:05-0700\",\n\t\t\"2006-01T15:04:05-0700\",\n\t\t\"2006-01-02T15:04:05-0700\",\n\n\t\t\"2006T15:04:05.000-0700\",\n\t\t\"2006-01T15:04:05.000-0700\",\n\t\t\"2006-01-02T15:04:05.000-0700\",\n\n\t\tTime.RFC1123,\n\t}\n\tmatchDateTimeZone = regexp.MustCompile(`^(.*)(?:(Z)|([\\+\\-]\\d{2}):(\\d{2}))$`)\n)\n\n// dateParse returns the epoch of the parsed date.\nfunc dateParse(date string) float64 {\n\t// YYYY-MM-DDTHH:mm:ss.sssZ\n\tvar time Time.Time\n\tvar err error\n\n\tif match := matchDateTimeZone.FindStringSubmatch(date); match != nil {\n\t\tif match[2] == \"Z\" {\n\t\t\tdate = match[1] + \"+0000\"\n\t\t} else {\n\t\t\tdate = match[1] + match[3] + match[4]\n\t\t}\n\t}\n\n\tfor _, layout := range dateLayoutList {\n\t\ttime, err = Time.Parse(layout, date)\n\t\tif err == nil {\n\t\t\tbreak\n\t\t}\n\t}\n\n\tif err != nil {\n\t\treturn math.NaN()\n\t}\n\n\treturn float64(time.UnixMilli())\n}\n"
  },
  {
    "path": "type_error.go",
    "content": "package otto\n\nfunc (rt *runtime) newErrorObject(name string, message Value, stackFramesToPop int) *object {\n\tobj := rt.newClassObject(classErrorName)\n\tif message.IsDefined() {\n\t\terr := newError(rt, name, stackFramesToPop, \"%s\", message.string())\n\t\tobj.defineProperty(\"message\", err.messageValue(), 0o111, false)\n\t\tobj.value = err\n\t} else {\n\t\tobj.value = newError(rt, name, stackFramesToPop)\n\t}\n\n\tobj.defineOwnProperty(\"stack\", property{\n\t\tvalue: propertyGetSet{\n\t\t\trt.newNativeFunction(\"get\", \"internal\", 0, func(FunctionCall) Value {\n\t\t\t\treturn stringValue(obj.value.(ottoError).formatWithStack())\n\t\t\t}),\n\t\t\t&nilGetSetObject,\n\t\t},\n\t\tmode: modeConfigureMask & modeOnMask,\n\t}, false)\n\n\treturn obj\n}\n\nfunc (rt *runtime) newErrorObjectError(err ottoError) *object {\n\tobj := rt.newClassObject(classErrorName)\n\tobj.defineProperty(\"message\", err.messageValue(), 0o111, false)\n\tobj.value = err\n\tswitch err.name {\n\tcase \"EvalError\":\n\t\tobj.prototype = rt.global.EvalErrorPrototype\n\tcase \"TypeError\":\n\t\tobj.prototype = rt.global.TypeErrorPrototype\n\tcase \"RangeError\":\n\t\tobj.prototype = rt.global.RangeErrorPrototype\n\tcase \"ReferenceError\":\n\t\tobj.prototype = rt.global.ReferenceErrorPrototype\n\tcase \"SyntaxError\":\n\t\tobj.prototype = rt.global.SyntaxErrorPrototype\n\tcase \"URIError\":\n\t\tobj.prototype = rt.global.URIErrorPrototype\n\tdefault:\n\t\tobj.prototype = rt.global.ErrorPrototype\n\t}\n\n\tobj.defineOwnProperty(\"stack\", property{\n\t\tvalue: propertyGetSet{\n\t\t\trt.newNativeFunction(\"get\", \"internal\", 0, func(FunctionCall) Value {\n\t\t\t\treturn stringValue(obj.value.(ottoError).formatWithStack())\n\t\t\t}),\n\t\t\t&nilGetSetObject,\n\t\t},\n\t\tmode: modeConfigureMask & modeOnMask,\n\t}, false)\n\n\treturn obj\n}\n"
  },
  {
    "path": "type_function.go",
    "content": "package otto\n\n// constructFunction.\ntype constructFunction func(*object, []Value) Value\n\n// 13.2.2 [[Construct]].\nfunc defaultConstruct(fn *object, argumentList []Value) Value {\n\tobj := fn.runtime.newObject()\n\tobj.class = classObjectName\n\n\tprototype := fn.get(\"prototype\")\n\tif prototype.kind != valueObject {\n\t\tprototype = objectValue(fn.runtime.global.ObjectPrototype)\n\t}\n\tobj.prototype = prototype.object()\n\n\tthis := objectValue(obj)\n\tvalue := fn.call(this, argumentList, false, nativeFrame)\n\tif value.kind == valueObject {\n\t\treturn value\n\t}\n\treturn this\n}\n\n// nativeFunction.\ntype nativeFunction func(FunctionCall) Value\n\n// nativeFunctionObject.\ntype nativeFunctionObject struct {\n\tcall      nativeFunction\n\tconstruct constructFunction\n\tname      string\n\tfile      string\n\tline      int\n}\n\nfunc (rt *runtime) newNativeFunctionProperty(name, file string, line int, native nativeFunction, length int) *object {\n\to := rt.newClassObject(classFunctionName)\n\to.value = nativeFunctionObject{\n\t\tname:      name,\n\t\tfile:      file,\n\t\tline:      line,\n\t\tcall:      native,\n\t\tconstruct: defaultConstruct,\n\t}\n\to.defineProperty(\"name\", stringValue(name), 0o000, false)\n\to.defineProperty(propertyLength, intValue(length), 0o000, false)\n\treturn o\n}\n\nfunc (rt *runtime) newNativeFunctionObject(name, file string, line int, native nativeFunction, length int) *object {\n\to := rt.newNativeFunctionProperty(name, file, line, native, length)\n\to.defineOwnProperty(\"caller\", property{\n\t\tvalue: propertyGetSet{\n\t\t\trt.newNativeFunctionProperty(\"get\", \"internal\", 0, func(fc FunctionCall) Value {\n\t\t\t\tfor sc := rt.scope; sc != nil; sc = sc.outer {\n\t\t\t\t\tif sc.frame.fn == o {\n\t\t\t\t\t\tif sc.outer == nil || sc.outer.frame.fn == nil {\n\t\t\t\t\t\t\treturn nullValue\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn rt.toValue(sc.outer.frame.fn)\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn nullValue\n\t\t\t}, 0),\n\t\t\t&nilGetSetObject,\n\t\t},\n\t\tmode: 0o000,\n\t}, false)\n\treturn o\n}\n\n// bindFunctionObject.\ntype bindFunctionObject struct {\n\ttarget       *object\n\tthis         Value\n\targumentList []Value\n}\n\nfunc (rt *runtime) newBoundFunctionObject(target *object, this Value, argumentList []Value) *object {\n\to := rt.newClassObject(classFunctionName)\n\to.value = bindFunctionObject{\n\t\ttarget:       target,\n\t\tthis:         this,\n\t\targumentList: argumentList,\n\t}\n\tlength := int(toInt32(target.get(propertyLength)))\n\tlength -= len(argumentList)\n\tif length < 0 {\n\t\tlength = 0\n\t}\n\to.defineProperty(\"name\", stringValue(\"bound \"+target.get(\"name\").String()), 0o000, false)\n\to.defineProperty(propertyLength, intValue(length), 0o000, false)\n\to.defineProperty(\"caller\", Value{}, 0o000, false)    // TODO Should throw a TypeError\n\to.defineProperty(\"arguments\", Value{}, 0o000, false) // TODO Should throw a TypeError\n\treturn o\n}\n\n// [[Construct]].\nfunc (fn bindFunctionObject) construct(argumentList []Value) Value {\n\tobj := fn.target\n\tswitch value := obj.value.(type) {\n\tcase nativeFunctionObject:\n\t\treturn value.construct(obj, fn.argumentList)\n\tcase nodeFunctionObject:\n\t\targumentList = append(fn.argumentList, argumentList...)\n\t\treturn obj.construct(argumentList)\n\tdefault:\n\t\tpanic(fn.target.runtime.panicTypeError(\"construct unknown type %T\", obj.value))\n\t}\n}\n\n// nodeFunctionObject.\ntype nodeFunctionObject struct {\n\tnode  *nodeFunctionLiteral\n\tstash stasher\n}\n\nfunc (rt *runtime) newNodeFunctionObject(node *nodeFunctionLiteral, stash stasher) *object {\n\to := rt.newClassObject(classFunctionName)\n\to.value = nodeFunctionObject{\n\t\tnode:  node,\n\t\tstash: stash,\n\t}\n\to.defineProperty(\"name\", stringValue(node.name), 0o000, false)\n\to.defineProperty(propertyLength, intValue(len(node.parameterList)), 0o000, false)\n\to.defineOwnProperty(\"caller\", property{\n\t\tvalue: propertyGetSet{\n\t\t\trt.newNativeFunction(\"get\", \"internal\", 0, func(fc FunctionCall) Value {\n\t\t\t\tfor sc := rt.scope; sc != nil; sc = sc.outer {\n\t\t\t\t\tif sc.frame.fn == o {\n\t\t\t\t\t\tif sc.outer == nil || sc.outer.frame.fn == nil {\n\t\t\t\t\t\t\treturn nullValue\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn rt.toValue(sc.outer.frame.fn)\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn nullValue\n\t\t\t}),\n\t\t\t&nilGetSetObject,\n\t\t},\n\t\tmode: 0o000,\n\t}, false)\n\treturn o\n}\n\n// _object.\nfunc (o *object) isCall() bool {\n\tswitch fn := o.value.(type) {\n\tcase nativeFunctionObject:\n\t\treturn fn.call != nil\n\tcase bindFunctionObject:\n\t\treturn true\n\tcase nodeFunctionObject:\n\t\treturn true\n\tdefault:\n\t\treturn false\n\t}\n}\n\nfunc (o *object) call(this Value, argumentList []Value, eval bool, frm frame) Value { //nolint:unparam // Isn't currently used except in recursive self.\n\tswitch fn := o.value.(type) {\n\tcase nativeFunctionObject:\n\t\t// Since eval is a native function, we only have to check for it here\n\t\tif eval {\n\t\t\teval = o == o.runtime.eval // If eval is true, then it IS a direct eval\n\t\t}\n\n\t\t// Enter a scope, name from the native object...\n\t\trt := o.runtime\n\t\tif rt.scope != nil && !eval {\n\t\t\trt.enterFunctionScope(rt.scope.lexical, this)\n\t\t\trt.scope.frame = frame{\n\t\t\t\tnative:     true,\n\t\t\t\tnativeFile: fn.file,\n\t\t\t\tnativeLine: fn.line,\n\t\t\t\tcallee:     fn.name,\n\t\t\t\tfile:       nil,\n\t\t\t\tfn:         o,\n\t\t\t}\n\t\t\tdefer func() {\n\t\t\t\trt.leaveScope()\n\t\t\t}()\n\t\t}\n\n\t\treturn fn.call(FunctionCall{\n\t\t\truntime: o.runtime,\n\t\t\teval:    eval,\n\n\t\t\tThis:         this,\n\t\t\tArgumentList: argumentList,\n\t\t\tOtto:         o.runtime.otto,\n\t\t})\n\n\tcase bindFunctionObject:\n\t\t// TODO Passthrough site, do not enter a scope\n\t\targumentList = append(fn.argumentList, argumentList...)\n\t\treturn fn.target.call(fn.this, argumentList, false, frm)\n\n\tcase nodeFunctionObject:\n\t\trt := o.runtime\n\t\tstash := rt.enterFunctionScope(fn.stash, this)\n\t\trt.scope.frame = frame{\n\t\t\tcallee: fn.node.name,\n\t\t\tfile:   fn.node.file,\n\t\t\tfn:     o,\n\t\t}\n\t\tdefer func() {\n\t\t\trt.leaveScope()\n\t\t}()\n\t\tcallValue := rt.cmplCallNodeFunction(o, stash, fn.node, argumentList)\n\t\tif value, valid := callValue.value.(result); valid {\n\t\t\treturn value.value\n\t\t}\n\t\treturn callValue\n\t}\n\n\tpanic(o.runtime.panicTypeError(\"%v is not a function\", objectValue(o)))\n}\n\nfunc (o *object) construct(argumentList []Value) Value {\n\tswitch fn := o.value.(type) {\n\tcase nativeFunctionObject:\n\t\tif fn.call == nil {\n\t\t\tpanic(o.runtime.panicTypeError(\"%v is not a function\", objectValue(o)))\n\t\t}\n\t\tif fn.construct == nil {\n\t\t\tpanic(o.runtime.panicTypeError(\"%v is not a constructor\", objectValue(o)))\n\t\t}\n\t\treturn fn.construct(o, argumentList)\n\n\tcase bindFunctionObject:\n\t\treturn fn.construct(argumentList)\n\n\tcase nodeFunctionObject:\n\t\treturn defaultConstruct(o, argumentList)\n\t}\n\n\tpanic(o.runtime.panicTypeError(\"%v is not a function\", objectValue(o)))\n}\n\n// 15.3.5.3.\nfunc (o *object) hasInstance(of Value) bool {\n\tif !o.isCall() {\n\t\t// We should not have a hasInstance method\n\t\tpanic(o.runtime.panicTypeError(\"Object.hasInstance not callable\"))\n\t}\n\tif !of.IsObject() {\n\t\treturn false\n\t}\n\tprototype := o.get(\"prototype\")\n\tif !prototype.IsObject() {\n\t\tpanic(o.runtime.panicTypeError(\"Object.hasInstance prototype %q is not an object\", prototype))\n\t}\n\tprototypeObject := prototype.object()\n\n\tvalue := of.object().prototype\n\tfor value != nil {\n\t\tif value == prototypeObject {\n\t\t\treturn true\n\t\t}\n\t\tvalue = value.prototype\n\t}\n\treturn false\n}\n\n// FunctionCall is an encapsulation of a JavaScript function call.\ntype FunctionCall struct {\n\tThis         Value\n\truntime      *runtime\n\tthisObj      *object\n\tOtto         *Otto\n\tArgumentList []Value\n\teval         bool\n}\n\n// Argument will return the value of the argument at the given index.\n//\n// If no such argument exists, undefined is returned.\nfunc (f FunctionCall) Argument(index int) Value {\n\treturn valueOfArrayIndex(f.ArgumentList, index)\n}\n\nfunc (f FunctionCall) getArgument(index int) (Value, bool) {\n\treturn getValueOfArrayIndex(f.ArgumentList, index)\n}\n\nfunc (f FunctionCall) slice(index int) []Value {\n\tif index < len(f.ArgumentList) {\n\t\treturn f.ArgumentList[index:]\n\t}\n\treturn []Value{}\n}\n\nfunc (f *FunctionCall) thisObject() *object {\n\tif f.thisObj == nil {\n\t\tthis := f.This.resolve() // FIXME Is this right?\n\t\tf.thisObj = f.runtime.toObject(this)\n\t}\n\treturn f.thisObj\n}\n\nfunc (f *FunctionCall) thisClassObject(class string) *object {\n\tif o := f.thisObject(); o.class != class {\n\t\tpanic(f.runtime.panicTypeError(\"Function.Class %s != %s\", o.class, class))\n\t}\n\treturn f.thisObj\n}\n\nfunc (f FunctionCall) toObject(value Value) *object {\n\treturn f.runtime.toObject(value)\n}\n\n// CallerLocation will return file location information (file:line:pos) where this function is being called.\nfunc (f FunctionCall) CallerLocation() string {\n\t// see error.go for location()\n\treturn f.runtime.scope.outer.frame.location()\n}\n"
  },
  {
    "path": "type_go_array.go",
    "content": "package otto\n\nimport (\n\t\"reflect\"\n\t\"strconv\"\n)\n\nfunc (rt *runtime) newGoArrayObject(value reflect.Value) *object {\n\to := rt.newObject()\n\to.class = classGoArrayName\n\to.objectClass = classGoArray\n\to.value = newGoArrayObject(value)\n\treturn o\n}\n\ntype goArrayObject struct {\n\tvalue        reflect.Value\n\twritable     bool\n\tpropertyMode propertyMode\n}\n\nfunc newGoArrayObject(value reflect.Value) *goArrayObject {\n\twritable := value.Kind() == reflect.Ptr || value.CanSet() // The Array is addressable (like a Slice)\n\tmode := propertyMode(0o010)\n\tif writable {\n\t\tmode = 0o110\n\t}\n\n\treturn &goArrayObject{\n\t\tvalue:        value,\n\t\twritable:     writable,\n\t\tpropertyMode: mode,\n\t}\n}\n\nfunc (o goArrayObject) getValue(name string) (reflect.Value, bool) { //nolint:unused\n\tif index, err := strconv.ParseInt(name, 10, 64); err != nil {\n\t\tv, ok := o.getValueIndex(index)\n\t\tif ok {\n\t\t\treturn v, ok\n\t\t}\n\t}\n\n\tif m := o.value.MethodByName(name); m.IsValid() {\n\t\treturn m, true\n\t}\n\n\treturn reflect.Value{}, false\n}\n\nfunc (o goArrayObject) getValueIndex(index int64) (reflect.Value, bool) {\n\tvalue := reflect.Indirect(o.value)\n\tif index < int64(value.Len()) {\n\t\treturn value.Index(int(index)), true\n\t}\n\n\treturn reflect.Value{}, false\n}\n\nfunc (o goArrayObject) setValue(index int64, value Value) bool {\n\tindexValue, exists := o.getValueIndex(index)\n\tif !exists {\n\t\treturn false\n\t}\n\treflectValue, err := value.toReflectValue(reflect.Indirect(o.value).Type().Elem())\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tindexValue.Set(reflectValue)\n\treturn true\n}\n\nfunc goArrayGetOwnProperty(obj *object, name string) *property {\n\t// length\n\tif name == propertyLength {\n\t\treturn &property{\n\t\t\tvalue: toValue(reflect.Indirect(obj.value.(*goArrayObject).value).Len()),\n\t\t\tmode:  0,\n\t\t}\n\t}\n\n\t// .0, .1, .2, ...\n\tif index := stringToArrayIndex(name); index >= 0 {\n\t\tgoObj := obj.value.(*goArrayObject)\n\t\tvalue := Value{}\n\t\treflectValue, exists := goObj.getValueIndex(index)\n\t\tif exists {\n\t\t\tvalue = obj.runtime.toValue(reflectValue.Interface())\n\t\t}\n\t\treturn &property{\n\t\t\tvalue: value,\n\t\t\tmode:  goObj.propertyMode,\n\t\t}\n\t}\n\n\tif method := obj.value.(*goArrayObject).value.MethodByName(name); method.IsValid() {\n\t\treturn &property{\n\t\t\tobj.runtime.toValue(method.Interface()),\n\t\t\t0o110,\n\t\t}\n\t}\n\n\treturn objectGetOwnProperty(obj, name)\n}\n\nfunc goArrayEnumerate(obj *object, all bool, each func(string) bool) {\n\tgoObj := obj.value.(*goArrayObject)\n\t// .0, .1, .2, ...\n\n\tfor index, length := 0, goObj.value.Len(); index < length; index++ {\n\t\tname := strconv.FormatInt(int64(index), 10)\n\t\tif !each(name) {\n\t\t\treturn\n\t\t}\n\t}\n\n\tobjectEnumerate(obj, all, each)\n}\n\nfunc goArrayDefineOwnProperty(obj *object, name string, descriptor property, throw bool) bool {\n\tif name == propertyLength {\n\t\treturn obj.runtime.typeErrorResult(throw)\n\t} else if index := stringToArrayIndex(name); index >= 0 {\n\t\tgoObj := obj.value.(*goArrayObject)\n\t\tif goObj.writable {\n\t\t\tif obj.value.(*goArrayObject).setValue(index, descriptor.value.(Value)) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\t\treturn obj.runtime.typeErrorResult(throw)\n\t}\n\treturn objectDefineOwnProperty(obj, name, descriptor, throw)\n}\n\nfunc goArrayDelete(obj *object, name string, throw bool) bool {\n\t// length\n\tif name == propertyLength {\n\t\treturn obj.runtime.typeErrorResult(throw)\n\t}\n\n\t// .0, .1, .2, ...\n\tindex := stringToArrayIndex(name)\n\tif index >= 0 {\n\t\tgoObj := obj.value.(*goArrayObject)\n\t\tif goObj.writable {\n\t\t\tindexValue, exists := goObj.getValueIndex(index)\n\t\t\tif exists {\n\t\t\t\tindexValue.Set(reflect.Zero(reflect.Indirect(goObj.value).Type().Elem()))\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\t\treturn obj.runtime.typeErrorResult(throw)\n\t}\n\n\treturn obj.delete(name, throw)\n}\n"
  },
  {
    "path": "type_go_map.go",
    "content": "package otto\n\nimport (\n\t\"reflect\"\n)\n\nfunc (rt *runtime) newGoMapObject(value reflect.Value) *object {\n\tobj := rt.newObject()\n\tobj.class = classObjectName // TODO Should this be something else?\n\tobj.objectClass = classGoMap\n\tobj.value = newGoMapObject(value)\n\treturn obj\n}\n\ntype goMapObject struct {\n\tkeyType   reflect.Type\n\tvalueType reflect.Type\n\tvalue     reflect.Value\n}\n\nfunc newGoMapObject(value reflect.Value) *goMapObject {\n\tif value.Kind() != reflect.Map {\n\t\tdbgf(\"%/panic//%@: %v != reflect.Map\", value.Kind())\n\t}\n\treturn &goMapObject{\n\t\tvalue:     value,\n\t\tkeyType:   value.Type().Key(),\n\t\tvalueType: value.Type().Elem(),\n\t}\n}\n\nfunc (o goMapObject) toKey(name string) reflect.Value {\n\treflectValue, err := stringToReflectValue(name, o.keyType.Kind())\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treturn reflectValue\n}\n\nfunc (o goMapObject) toValue(value Value) reflect.Value {\n\treflectValue, err := value.toReflectValue(o.valueType)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\treturn reflectValue\n}\n\nfunc goMapGetOwnProperty(obj *object, name string) *property {\n\tgoObj := obj.value.(*goMapObject)\n\n\t// an error here means that the key referenced by `name` could not possibly\n\t// be a property of this object, so it should be safe to ignore this error\n\t//\n\t// TODO: figure out if any cases from\n\t// https://go.dev/ref/spec#Comparison_operators meet the criteria of 1)\n\t// being possible to represent as a string, 2) being possible to reconstruct\n\t// from a string, and 3) having a meaningful failure case in this context\n\t// other than \"key does not exist\"\n\tkey, err := stringToReflectValue(name, goObj.keyType.Kind())\n\tif err != nil {\n\t\treturn nil\n\t}\n\n\tvalue := goObj.value.MapIndex(key)\n\tif value.IsValid() {\n\t\treturn &property{obj.runtime.toValue(value.Interface()), 0o111}\n\t}\n\n\t// Other methods\n\tif method := obj.value.(*goMapObject).value.MethodByName(name); method.IsValid() {\n\t\treturn &property{\n\t\t\tvalue: obj.runtime.toValue(method.Interface()),\n\t\t\tmode:  0o110,\n\t\t}\n\t}\n\n\treturn nil\n}\n\nfunc goMapEnumerate(obj *object, all bool, each func(string) bool) {\n\tgoObj := obj.value.(*goMapObject)\n\tkeys := goObj.value.MapKeys()\n\tfor _, key := range keys {\n\t\tif !each(toValue(key).String()) {\n\t\t\treturn\n\t\t}\n\t}\n}\n\nfunc goMapDefineOwnProperty(obj *object, name string, descriptor property, throw bool) bool {\n\tgoObj := obj.value.(*goMapObject)\n\t// TODO ...or 0222\n\tif descriptor.mode != 0o111 {\n\t\treturn obj.runtime.typeErrorResult(throw)\n\t}\n\tif !descriptor.isDataDescriptor() {\n\t\treturn obj.runtime.typeErrorResult(throw)\n\t}\n\tgoObj.value.SetMapIndex(goObj.toKey(name), goObj.toValue(descriptor.value.(Value)))\n\treturn true\n}\n\nfunc goMapDelete(obj *object, name string, throw bool) bool {\n\tgoObj := obj.value.(*goMapObject)\n\tgoObj.value.SetMapIndex(goObj.toKey(name), reflect.Value{})\n\t// FIXME\n\treturn true\n}\n"
  },
  {
    "path": "type_go_map_test.go",
    "content": "package otto\n\nimport (\n\t\"sort\"\n\t\"strconv\"\n\t\"testing\"\n)\n\ntype GoMapTest map[string]int\n\nfunc (s GoMapTest) Join() string {\n\tjoinedStr := \"\"\n\n\t// Ordering the map takes some effort\n\t// because map iterators in golang are unordered by definition.\n\t// So we need to extract keys, sort them, and then generate K/V pairs\n\t// All of this is meant to ensure that the test is predictable.\n\tkeys := make([]string, len(s))\n\ti := 0\n\tfor key := range s {\n\t\tkeys[i] = key\n\t\ti++\n\t}\n\n\tsort.Strings(keys)\n\n\tfor _, key := range keys {\n\t\tjoinedStr += key + \": \" + strconv.Itoa(s[key]) + \" \"\n\t}\n\treturn joinedStr\n}\n\nfunc TestGoMap(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, vm := test()\n\t\tvm.Set(\"TestMap\", GoMapTest{\"one\": 1, \"two\": 2, \"three\": 3})\n\t\tis(test(`TestMap[\"one\"]`).export(), 1)\n\t\tis(test(`TestMap.Join()`).export(), \"one: 1 three: 3 two: 2 \")\n\t})\n}\n"
  },
  {
    "path": "type_go_slice.go",
    "content": "package otto\n\nimport (\n\t\"reflect\"\n\t\"strconv\"\n)\n\nfunc (rt *runtime) newGoSliceObject(value reflect.Value) *object {\n\to := rt.newObject()\n\to.class = classGoSliceName\n\to.objectClass = classGoSlice\n\to.value = newGoSliceObject(value)\n\treturn o\n}\n\ntype goSliceObject struct {\n\tvalue reflect.Value\n}\n\nfunc newGoSliceObject(value reflect.Value) *goSliceObject {\n\treturn &goSliceObject{\n\t\tvalue: value,\n\t}\n}\n\nfunc (o goSliceObject) getValue(index int64) (reflect.Value, bool) {\n\tif index < int64(o.value.Len()) {\n\t\treturn o.value.Index(int(index)), true\n\t}\n\treturn reflect.Value{}, false\n}\n\nfunc (o *goSliceObject) setLength(value Value) {\n\twant, err := value.ToInteger()\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\twantInt := int(want)\n\tswitch {\n\tcase wantInt == o.value.Len():\n\t\t// No change needed.\n\tcase wantInt < o.value.Cap():\n\t\t// Fits in current capacity.\n\t\to.value.SetLen(wantInt)\n\tdefault:\n\t\t// Needs expanding.\n\t\tnewSlice := reflect.MakeSlice(o.value.Type(), wantInt, wantInt)\n\t\treflect.Copy(newSlice, o.value)\n\t\to.value = newSlice\n\t}\n}\n\nfunc (o *goSliceObject) setValue(index int64, value Value) bool {\n\treflectValue, err := value.toReflectValue(o.value.Type().Elem())\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\tindexValue, exists := o.getValue(index)\n\tif !exists {\n\t\tif int64(o.value.Len()) == index {\n\t\t\t// Trying to append e.g. slice.push(...), allow it.\n\t\t\to.value = reflect.Append(o.value, reflectValue)\n\t\t\treturn true\n\t\t}\n\t\treturn false\n\t}\n\n\tindexValue.Set(reflectValue)\n\treturn true\n}\n\nfunc goSliceGetOwnProperty(obj *object, name string) *property {\n\t// length\n\tif name == propertyLength {\n\t\treturn &property{\n\t\t\tvalue: toValue(obj.value.(*goSliceObject).value.Len()),\n\t\t\tmode:  0o110,\n\t\t}\n\t}\n\n\t// .0, .1, .2, ...\n\tif index := stringToArrayIndex(name); index >= 0 {\n\t\tvalue := Value{}\n\t\treflectValue, exists := obj.value.(*goSliceObject).getValue(index)\n\t\tif exists {\n\t\t\tvalue = obj.runtime.toValue(reflectValue.Interface())\n\t\t}\n\t\treturn &property{\n\t\t\tvalue: value,\n\t\t\tmode:  0o110,\n\t\t}\n\t}\n\n\t// Other methods\n\tif method := obj.value.(*goSliceObject).value.MethodByName(name); method.IsValid() {\n\t\treturn &property{\n\t\t\tvalue: obj.runtime.toValue(method.Interface()),\n\t\t\tmode:  0o110,\n\t\t}\n\t}\n\n\treturn objectGetOwnProperty(obj, name)\n}\n\nfunc goSliceEnumerate(obj *object, all bool, each func(string) bool) {\n\tgoObj := obj.value.(*goSliceObject)\n\t// .0, .1, .2, ...\n\n\tfor index, length := 0, goObj.value.Len(); index < length; index++ {\n\t\tname := strconv.FormatInt(int64(index), 10)\n\t\tif !each(name) {\n\t\t\treturn\n\t\t}\n\t}\n\n\tobjectEnumerate(obj, all, each)\n}\n\nfunc goSliceDefineOwnProperty(obj *object, name string, descriptor property, throw bool) bool {\n\tif name == propertyLength {\n\t\tobj.value.(*goSliceObject).setLength(descriptor.value.(Value))\n\t\treturn true\n\t} else if index := stringToArrayIndex(name); index >= 0 {\n\t\tif obj.value.(*goSliceObject).setValue(index, descriptor.value.(Value)) {\n\t\t\treturn true\n\t\t}\n\t\treturn obj.runtime.typeErrorResult(throw)\n\t}\n\treturn objectDefineOwnProperty(obj, name, descriptor, throw)\n}\n\nfunc goSliceDelete(obj *object, name string, throw bool) bool {\n\t// length\n\tif name == propertyLength {\n\t\treturn obj.runtime.typeErrorResult(throw)\n\t}\n\n\t// .0, .1, .2, ...\n\tindex := stringToArrayIndex(name)\n\tif index >= 0 {\n\t\tgoObj := obj.value.(*goSliceObject)\n\t\tindexValue, exists := goObj.getValue(index)\n\t\tif exists {\n\t\t\tindexValue.Set(reflect.Zero(goObj.value.Type().Elem()))\n\t\t\treturn true\n\t\t}\n\t\treturn obj.runtime.typeErrorResult(throw)\n\t}\n\n\treturn obj.delete(name, throw)\n}\n"
  },
  {
    "path": "type_go_slice_test.go",
    "content": "package otto\n\nimport \"testing\"\n\ntype GoSliceTest []int\n\nfunc (s GoSliceTest) Sum() int {\n\tsum := 0\n\tfor _, v := range s {\n\t\tsum += v\n\t}\n\treturn sum\n}\n\nfunc TestGoSlice(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, vm := test()\n\t\tvm.Set(\"TestSlice\", GoSliceTest{1, 2, 3})\n\t\tis(test(`TestSlice.length`).export(), 3)\n\t\tis(test(`TestSlice[1]`).export(), 2)\n\t\tis(test(`TestSlice.Sum()`).export(), 6)\n\t})\n}\n"
  },
  {
    "path": "type_go_struct.go",
    "content": "package otto\n\nimport (\n\t\"encoding/json\"\n\t\"reflect\"\n)\n\n// FIXME Make a note about not being able to modify a struct unless it was\n// passed as a pointer-to: &struct{ ... }\n// This seems to be a limitation of the reflect package.\n// This goes for the other Go constructs too.\n// I guess we could get around it by either:\n// 1. Creating a new struct every time\n// 2. Creating an addressable? struct in the constructor\n\nfunc (rt *runtime) newGoStructObject(value reflect.Value) *object {\n\to := rt.newObject()\n\to.class = classObjectName // TODO Should this be something else?\n\to.objectClass = classGoStruct\n\to.value = newGoStructObject(value)\n\treturn o\n}\n\ntype goStructObject struct {\n\tvalue reflect.Value\n}\n\nfunc newGoStructObject(value reflect.Value) *goStructObject {\n\tif reflect.Indirect(value).Kind() != reflect.Struct {\n\t\tdbgf(\"%/panic//%@: %v != reflect.Struct\", value.Kind())\n\t}\n\treturn &goStructObject{\n\t\tvalue: value,\n\t}\n}\n\nfunc (o goStructObject) getValue(name string) reflect.Value {\n\tif idx := fieldIndexByName(reflect.Indirect(o.value).Type(), name); len(idx) > 0 {\n\t\treturn reflect.Indirect(o.value).FieldByIndex(idx)\n\t}\n\n\tif validGoStructName(name) {\n\t\t// Do not reveal hidden or unexported fields.\n\t\tif field := reflect.Indirect(o.value).FieldByName(name); field.IsValid() {\n\t\t\treturn field\n\t\t}\n\n\t\tif method := o.value.MethodByName(name); method.IsValid() {\n\t\t\treturn method\n\t\t}\n\t}\n\n\treturn reflect.Value{}\n}\n\nfunc (o goStructObject) fieldIndex(name string) []int { //nolint:unused\n\treturn fieldIndexByName(reflect.Indirect(o.value).Type(), name)\n}\n\nfunc (o goStructObject) method(name string) (reflect.Method, bool) { //nolint:unused\n\treturn reflect.Indirect(o.value).Type().MethodByName(name)\n}\n\nfunc (o goStructObject) setValue(rt *runtime, name string, value Value) bool {\n\tif idx := fieldIndexByName(reflect.Indirect(o.value).Type(), name); len(idx) == 0 {\n\t\treturn false\n\t}\n\n\tfieldValue := o.getValue(name)\n\tconverted, err := rt.convertCallParameter(value, fieldValue.Type())\n\tif err != nil {\n\t\tpanic(rt.panicTypeError(\"Object.setValue convertCallParameter: %s\", err))\n\t}\n\tfieldValue.Set(converted)\n\n\treturn true\n}\n\nfunc goStructGetOwnProperty(obj *object, name string) *property {\n\tgoObj := obj.value.(*goStructObject)\n\tvalue := goObj.getValue(name)\n\tif value.IsValid() {\n\t\treturn &property{obj.runtime.toValue(value), 0o110}\n\t}\n\n\treturn objectGetOwnProperty(obj, name)\n}\n\nfunc validGoStructName(name string) bool {\n\tif name == \"\" {\n\t\treturn false\n\t}\n\treturn 'A' <= name[0] && name[0] <= 'Z' // TODO What about Unicode?\n}\n\nfunc goStructEnumerate(obj *object, all bool, each func(string) bool) {\n\tgoObj := obj.value.(*goStructObject)\n\n\t// Enumerate fields\n\tfor index := range reflect.Indirect(goObj.value).NumField() {\n\t\tname := reflect.Indirect(goObj.value).Type().Field(index).Name\n\t\tif validGoStructName(name) {\n\t\t\tif !each(name) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n\n\t// Enumerate methods\n\tfor index := range goObj.value.NumMethod() {\n\t\tname := goObj.value.Type().Method(index).Name\n\t\tif validGoStructName(name) {\n\t\t\tif !each(name) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n\n\tobjectEnumerate(obj, all, each)\n}\n\nfunc goStructCanPut(obj *object, name string) bool {\n\tgoObj := obj.value.(*goStructObject)\n\tvalue := goObj.getValue(name)\n\tif value.IsValid() {\n\t\treturn true\n\t}\n\n\treturn objectCanPut(obj, name)\n}\n\nfunc goStructPut(obj *object, name string, value Value, throw bool) {\n\tgoObj := obj.value.(*goStructObject)\n\tif goObj.setValue(obj.runtime, name, value) {\n\t\treturn\n\t}\n\n\tobjectPut(obj, name, value, throw)\n}\n\nfunc goStructMarshalJSON(obj *object) json.Marshaler {\n\tgoObj := obj.value.(*goStructObject)\n\tgoValue := reflect.Indirect(goObj.value).Interface()\n\tmarshaler, _ := goValue.(json.Marshaler)\n\treturn marshaler\n}\n"
  },
  {
    "path": "type_go_struct_test.go",
    "content": "package otto\n\nimport (\n\t\"testing\"\n)\n\nfunc TestGoStructEmbeddedFields(t *testing.T) {\n\ttype A struct {\n\t\tA1 string `json:\"a1\"`\n\t\tA2 string `json:\"a2\"`\n\t\tA3 string `json:\"a3\"`\n\t}\n\n\ttype B struct {\n\t\tA\n\t\tB1 string `json:\"b1\"`\n\t}\n\n\ttt(t, func() {\n\t\ttest, vm := test()\n\n\t\tvm.Set(\"v\", B{A{\"a1\", \"a2\", \"a3\"}, \"b1\"})\n\n\t\ttest(`[v.a1,v.a2,v.a3,v.b1]`, \"a1,a2,a3,b1\")\n\t})\n}\n\nfunc TestGoStructNilBoolPointerField(t *testing.T) {\n\ttype S struct {\n\t\tC interface{} `json:\"c\"`\n\t\tB *bool       `json:\"b\"`\n\t\tA int         `json:\"a\"`\n\t}\n\n\ttt(t, func() {\n\t\ttest, vm := test()\n\t\tvm.Set(\"s\", S{A: 1, B: nil, C: nil})\n\t\ttest(`'a' in s`, true)\n\t\ttest(`typeof s.a`, \"number\")\n\t\ttest(`'b' in s`, true)\n\t\ttest(`typeof s.b`, \"undefined\")\n\t\ttest(`'c' in s`, true)\n\t\ttest(`typeof s.c`, \"undefined\")\n\t})\n}\n\nfunc TestGoStructError(t *testing.T) {\n\ttype S1 struct {\n\t\tA string `json:\"a\"`\n\t\tB string `json:\"b\"`\n\t}\n\n\ttype S2 struct {\n\t\tB S1   `json:\"b\"`\n\t\tA []S1 `json:\"a\"`\n\t}\n\n\ttype S3 struct {\n\t\tB S2   `json:\"b\"`\n\t\tA []S2 `json:\"a\"`\n\t}\n\n\ttt(t, func() {\n\t\ttest, vm := test()\n\t\tvm.Set(\"fn\", func(s *S3) string { return \"cool\" })\n\t\ttest(\n\t\t\t`(function() { try { fn({a:[{a:[{c:\"x\"}]}]}) } catch (ex) { return ex } })()`,\n\t\t\t`TypeError: can't convert to *otto.S3: couldn't convert property \"a\" of otto.S3: couldn't convert element 0 of []otto.S2: couldn't convert property \"a\" of otto.S2: couldn't convert element 0 of []otto.S1: can't convert property \"c\" of otto.S1: field does not exist`,\n\t\t)\n\t})\n}\n"
  },
  {
    "path": "type_number.go",
    "content": "package otto\n\nfunc (rt *runtime) newNumberObject(value Value) *object {\n\treturn rt.newPrimitiveObject(classNumberName, value.numberValue())\n}\n"
  },
  {
    "path": "type_reference.go",
    "content": "package otto\n\ntype referencer interface {\n\tinvalid() bool               // IsUnresolvableReference\n\tgetValue() Value             // getValue\n\tputValue(value Value) string // PutValue\n\tdelete() bool\n}\n\n// PropertyReference\n\ntype propertyReference struct {\n\tbase    *object\n\truntime *runtime\n\tname    string\n\tat      at\n\tstrict  bool\n}\n\nfunc newPropertyReference(rt *runtime, base *object, name string, strict bool, atv at) *propertyReference {\n\treturn &propertyReference{\n\t\truntime: rt,\n\t\tname:    name,\n\t\tstrict:  strict,\n\t\tbase:    base,\n\t\tat:      atv,\n\t}\n}\n\nfunc (pr *propertyReference) invalid() bool {\n\treturn pr.base == nil\n}\n\nfunc (pr *propertyReference) getValue() Value {\n\tif pr.base == nil {\n\t\tpanic(pr.runtime.panicReferenceError(\"'%s' is not defined\", pr.name, pr.at))\n\t}\n\treturn pr.base.get(pr.name)\n}\n\nfunc (pr *propertyReference) putValue(value Value) string {\n\tif pr.base == nil {\n\t\treturn pr.name\n\t}\n\tpr.base.put(pr.name, value, pr.strict)\n\treturn \"\"\n}\n\nfunc (pr *propertyReference) delete() bool {\n\tif pr.base == nil {\n\t\t// TODO Throw an error if strict\n\t\treturn true\n\t}\n\treturn pr.base.delete(pr.name, pr.strict)\n}\n\ntype stashReference struct {\n\tbase   stasher\n\tname   string\n\tstrict bool\n}\n\nfunc (sr *stashReference) invalid() bool {\n\treturn false // The base (an environment) will never be nil\n}\n\nfunc (sr *stashReference) getValue() Value {\n\treturn sr.base.getBinding(sr.name, sr.strict)\n}\n\nfunc (sr *stashReference) putValue(value Value) string {\n\tsr.base.setValue(sr.name, value, sr.strict)\n\treturn \"\"\n}\n\nfunc (sr *stashReference) delete() bool {\n\tif sr.base == nil {\n\t\t// This should never be reached, but just in case\n\t\treturn false\n\t}\n\treturn sr.base.deleteBinding(sr.name)\n}\n\n// getIdentifierReference.\nfunc getIdentifierReference(rt *runtime, stash stasher, name string, strict bool, atv at) referencer {\n\tif stash == nil {\n\t\treturn newPropertyReference(rt, nil, name, strict, atv)\n\t}\n\tif stash.hasBinding(name) {\n\t\treturn stash.newReference(name, strict, atv)\n\t}\n\treturn getIdentifierReference(rt, stash.outer(), name, strict, atv)\n}\n"
  },
  {
    "path": "type_regexp.go",
    "content": "package otto\n\nimport (\n\t\"fmt\"\n\t\"regexp\"\n\n\t\"github.com/robertkrimen/otto/parser\"\n)\n\ntype regExpObject struct {\n\tregularExpression *regexp.Regexp\n\tsource            string\n\tflags             string\n\tglobal            bool\n\tignoreCase        bool\n\tmultiline         bool\n}\n\nfunc (rt *runtime) newRegExpObject(pattern string, flags string) *object {\n\to := rt.newObject()\n\to.class = classRegExpName\n\n\tglobal := false\n\tignoreCase := false\n\tmultiline := false\n\tre2flags := \"\"\n\n\t// TODO Maybe clean up the panicking here... TypeError, SyntaxError, ?\n\n\tfor _, chr := range flags {\n\t\tswitch chr {\n\t\tcase 'g':\n\t\t\tif global {\n\t\t\t\tpanic(rt.panicSyntaxError(\"newRegExpObject: %s %s\", pattern, flags))\n\t\t\t}\n\t\t\tglobal = true\n\t\tcase 'm':\n\t\t\tif multiline {\n\t\t\t\tpanic(rt.panicSyntaxError(\"newRegExpObject: %s %s\", pattern, flags))\n\t\t\t}\n\t\t\tmultiline = true\n\t\t\tre2flags += \"m\"\n\t\tcase 'i':\n\t\t\tif ignoreCase {\n\t\t\t\tpanic(rt.panicSyntaxError(\"newRegExpObject: %s %s\", pattern, flags))\n\t\t\t}\n\t\t\tignoreCase = true\n\t\t\tre2flags += \"i\"\n\t\t}\n\t}\n\n\tre2pattern, err := parser.TransformRegExp(pattern)\n\tif err != nil {\n\t\tpanic(rt.panicTypeError(\"Invalid regular expression: %s\", err.Error()))\n\t}\n\tif len(re2flags) > 0 {\n\t\tre2pattern = fmt.Sprintf(\"(?%s:%s)\", re2flags, re2pattern)\n\t}\n\n\tregularExpression, err := regexp.Compile(re2pattern)\n\tif err != nil {\n\t\tpanic(rt.panicSyntaxError(\"Invalid regular expression: %s\", err.Error()[22:]))\n\t}\n\n\to.value = regExpObject{\n\t\tregularExpression: regularExpression,\n\t\tglobal:            global,\n\t\tignoreCase:        ignoreCase,\n\t\tmultiline:         multiline,\n\t\tsource:            pattern,\n\t\tflags:             flags,\n\t}\n\to.defineProperty(\"global\", boolValue(global), 0, false)\n\to.defineProperty(\"ignoreCase\", boolValue(ignoreCase), 0, false)\n\to.defineProperty(\"multiline\", boolValue(multiline), 0, false)\n\to.defineProperty(\"lastIndex\", intValue(0), 0o100, false)\n\to.defineProperty(\"source\", stringValue(pattern), 0, false)\n\treturn o\n}\n\nfunc (o *object) regExpValue() regExpObject {\n\tvalue, _ := o.value.(regExpObject)\n\treturn value\n}\n\nfunc execRegExp(this *object, target string) (bool, []int) {\n\tif this.class != classRegExpName {\n\t\tpanic(this.runtime.panicTypeError(\"Calling RegExp.exec on a non-RegExp object\"))\n\t}\n\tlastIndex := this.get(\"lastIndex\").number().int64\n\tindex := lastIndex\n\tglobal := this.get(\"global\").bool()\n\tif !global {\n\t\tindex = 0\n\t}\n\n\tvar result []int\n\tif 0 > index || index > int64(len(target)) {\n\t} else {\n\t\tresult = this.regExpValue().regularExpression.FindStringSubmatchIndex(target[index:])\n\t}\n\n\tif result == nil {\n\t\tthis.put(\"lastIndex\", intValue(0), true)\n\t\treturn false, nil\n\t}\n\n\tstartIndex := index\n\tendIndex := int(lastIndex) + result[1]\n\t// We do this shift here because the .FindStringSubmatchIndex above\n\t// was done on a local subordinate slice of the string, not the whole string\n\tfor index, offset := range result {\n\t\tif offset != -1 {\n\t\t\tresult[index] += int(startIndex)\n\t\t}\n\t}\n\tif global {\n\t\tthis.put(\"lastIndex\", intValue(endIndex), true)\n\t}\n\n\treturn true, result\n}\n\nfunc execResultToArray(rt *runtime, target string, result []int) *object {\n\tcaptureCount := len(result) / 2\n\tvalueArray := make([]Value, captureCount)\n\tfor index := range captureCount {\n\t\toffset := 2 * index\n\t\tif result[offset] != -1 {\n\t\t\tvalueArray[index] = stringValue(target[result[offset]:result[offset+1]])\n\t\t} else {\n\t\t\tvalueArray[index] = Value{}\n\t\t}\n\t}\n\tmatchIndex := result[0]\n\tif matchIndex != 0 {\n\t\t// Find the utf16 index in the string, not the byte index.\n\t\tmatchIndex = utf16Length(target[:matchIndex])\n\t}\n\tmatch := rt.newArrayOf(valueArray)\n\tmatch.defineProperty(\"input\", stringValue(target), 0o111, false)\n\tmatch.defineProperty(\"index\", intValue(matchIndex), 0o111, false)\n\treturn match\n}\n"
  },
  {
    "path": "type_string.go",
    "content": "package otto\n\nimport (\n\t\"strconv\"\n\t\"unicode/utf16\"\n\t\"unicode/utf8\"\n)\n\ntype stringObjecter interface {\n\tLength() int\n\tAt(at int) rune\n\tString() string\n}\n\ntype stringASCII string\n\nfunc (str stringASCII) Length() int {\n\treturn len(str)\n}\n\nfunc (str stringASCII) At(at int) rune {\n\treturn rune(str[at])\n}\n\nfunc (str stringASCII) String() string {\n\treturn string(str)\n}\n\ntype stringWide struct {\n\tstring  string\n\tvalue16 []uint16\n}\n\nfunc (str stringWide) Length() int {\n\tif str.value16 == nil {\n\t\tstr.value16 = utf16.Encode([]rune(str.string))\n\t}\n\treturn len(str.value16)\n}\n\nfunc (str stringWide) At(at int) rune {\n\tif str.value16 == nil {\n\t\tstr.value16 = utf16.Encode([]rune(str.string))\n\t}\n\treturn rune(str.value16[at])\n}\n\nfunc (str stringWide) String() string {\n\treturn str.string\n}\n\nfunc newStringObject(str string) stringObjecter {\n\tfor i := range len(str) {\n\t\tif str[i] >= utf8.RuneSelf {\n\t\t\tgoto wide\n\t\t}\n\t}\n\n\treturn stringASCII(str)\n\nwide:\n\treturn &stringWide{\n\t\tstring: str,\n\t}\n}\n\nfunc stringAt(str stringObjecter, index int) rune {\n\tif 0 <= index && index < str.Length() {\n\t\treturn str.At(index)\n\t}\n\treturn utf8.RuneError\n}\n\nfunc (rt *runtime) newStringObject(value Value) *object {\n\tstr := newStringObject(value.string())\n\n\tobj := rt.newClassObject(classStringName)\n\tobj.defineProperty(propertyLength, intValue(str.Length()), 0, false)\n\tobj.objectClass = classString\n\tobj.value = str\n\treturn obj\n}\n\nfunc (o *object) stringValue() stringObjecter {\n\tif str, ok := o.value.(stringObjecter); ok {\n\t\treturn str\n\t}\n\treturn nil\n}\n\nfunc stringEnumerate(obj *object, all bool, each func(string) bool) {\n\tif str := obj.stringValue(); str != nil {\n\t\tlength := str.Length()\n\t\tfor index := range length {\n\t\t\tif !each(strconv.FormatInt(int64(index), 10)) {\n\t\t\t\treturn\n\t\t\t}\n\t\t}\n\t}\n\tobjectEnumerate(obj, all, each)\n}\n\nfunc stringGetOwnProperty(obj *object, name string) *property {\n\tif prop := objectGetOwnProperty(obj, name); prop != nil {\n\t\treturn prop\n\t}\n\t// TODO Test a string of length >= +int32 + 1?\n\tif index := stringToArrayIndex(name); index >= 0 {\n\t\tif chr := stringAt(obj.stringValue(), int(index)); chr != utf8.RuneError {\n\t\t\treturn &property{stringValue(string(chr)), 0}\n\t\t}\n\t}\n\treturn nil\n}\n"
  },
  {
    "path": "underscore/LICENSE.underscorejs",
    "content": "Copyright (c) 2009-2022 Jeremy Ashkenas, Julian Gonggrijp, and DocumentCloud and Investigative Reporters & Editors\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the \"Software\"), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "underscore/README.md",
    "content": "# underscore\n\n[![Reference](https://pkg.go.dev/badge/github.com/robertkrimen/otto/underscore.svg)](https://pkg.go.dev/github.com/robertkrimen/otto/underscore) [![License](https://img.shields.io/badge/MIT-blue.svg)](https://opensource.org/licenses/MIT)\n\nTo update the version of underscore run:\n\n```shell\ngo generate\n```\n"
  },
  {
    "path": "underscore/download.go",
    "content": "//go:build generate\n\npackage main\n\nimport (\n\t\"context\"\n\t\"flag\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"net/http\"\n\t\"os\"\n\t\"time\"\n)\n\nvar (\n\turl    = flag.String(\"url\", \"\", \"url to read from\")\n\toutput = flag.String(\"output\", \"\", \"output file to write the result too\")\n)\n\nfunc download(url, output string) (err error) {\n\tctx, cancel := context.WithTimeout(context.Background(), time.Second*10)\n\tdefer cancel()\n\n\treq, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"new request failed: %w\", err)\n\t}\n\n\tresp, err := http.DefaultClient.Do(req)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"request failed: %w\", err)\n\t}\n\tdefer resp.Body.Close()\n\n\tvar f *os.File\n\tif output != \"\" {\n\t\tif f, err = os.Create(output); err != nil {\n\t\t\treturn fmt.Errorf(\"create file %q failed: %w\", output, err)\n\t\t}\n\n\t\tdefer f.Close()\n\t} else {\n\t\tf = os.Stdout\n\t}\n\n\tif _, err := io.Copy(f, resp.Body); err != nil {\n\t\treturn fmt.Errorf(\"body save: %w\", err)\n\t}\n\n\treturn nil\n}\n\nfunc main() {\n\tflag.Parse()\n\n\tswitch {\n\tcase len(*url) == 0:\n\t\tlog.Fatal(\"missing required --url parameter\")\n\t}\n\n\tif err := download(*url, *output); err != nil {\n\t\tlog.Fatal(err)\n\t}\n}\n"
  },
  {
    "path": "underscore/generate.go",
    "content": "package underscore\n\n//go:generate go run download.go --url https://underscorejs.org/underscore-min.js --output underscore-min.js\n//go:generate go run download.go --url https://raw.githubusercontent.com/jashkenas/underscore/master/LICENSE --output LICENSE.underscorejs\n"
  },
  {
    "path": "underscore/testify",
    "content": "#!/usr/bin/env perl\n\nuse strict;\nuse warnings;\n\nmy $underscore_test = shift @ARGV || \"\";\nif (!-d $underscore_test) {\n    print <<_END_;\nUsage:\n\n    testify ./underscore/test\n\n    # Should look something like:\n    arrays.js\n    chaining.js\n    collections.js\n    functions.js\n    index.html\n    objects.js\n    speed.js\n    utility.js\n    vendor\n\n_END_\n    if ($underscore_test) {\n        die \"!: Not a directory: $underscore_test\\n\"\n    }\n    exit;\n}\n\nchdir $underscore_test or die \"!: $!\";\n\nmy @js = <*.js>;\n\nfor my $file (@js) {\n    open my $fh, '<', $file or die \"!: $!\";\n    my $tests = join \"\", <$fh>;\n    my @tests = $tests =~ m/\n        ^(\\s{2}test\\(.*?\n        ^\\s{2}}\\);)$\n    /mgxs;\n    close $fh;\n    next unless @tests;\n    print \"$file: \", scalar(@tests), \"\\n\";\n    my $underscore_name = \"underscore_$file\";\n    $underscore_name =~ s/.js$//;\n    my $go_file = \"${underscore_name}_test.go\";\n    $go_file =~ s/.js$/.go/;\n    open $fh, '>', $go_file or die \"!: $!\";\n\n    $fh->print(<<_END_);\npackage otto\n\nimport (\n\t\"testing\"\n)\n\n_END_\n\n    my $count = 0;\n    for my $test (@tests) {\n        $test =~ s/`([^`]+)`/<$1>/g;\n        my ($name) = $test =~ m/^\\s*test\\(['\"]([^'\"]+)['\"]/;\n        $fh->print(<<_END_);\n// $name\nfunc Test_${underscore_name}_$count(t *testing.T) {\n    tt(t, func(){\n\t    test := underscoreTest()\n\n\t    test(`\n$test\n        `)\n    })\n}\n\n_END_\n        $count++;\n    }\n}\n\n#  test('#779 - delimeters are applied to unescaped text.', 1, function() {\n#    var template = _.template('<<\\nx\\n>>', null, {evaluate: /<<(.*?)>>/g});\n#    strictEqual(template(), '<<\\nx\\n>>');\n#  });\n"
  },
  {
    "path": "underscore/underscore-min.js",
    "content": "!function(n,r){\"object\"==typeof exports&&\"undefined\"!=typeof module?module.exports=r():\"function\"==typeof define&&define.amd?define(\"underscore\",r):(n=\"undefined\"!=typeof globalThis?globalThis:n||self,function(){var t=n._,e=n._=r();e.noConflict=function(){return n._=t,e}}())}(this,(function(){\n//     Underscore.js 1.13.7\n//     https://underscorejs.org\n//     (c) 2009-2024 Jeremy Ashkenas, Julian Gonggrijp, and DocumentCloud and Investigative Reporters & Editors\n//     Underscore may be freely distributed under the MIT license.\nvar n=\"1.13.7\",r=\"object\"==typeof self&&self.self===self&&self||\"object\"==typeof global&&global.global===global&&global||Function(\"return this\")()||{},t=Array.prototype,e=Object.prototype,u=\"undefined\"!=typeof Symbol?Symbol.prototype:null,i=t.push,o=t.slice,a=e.toString,f=e.hasOwnProperty,c=\"undefined\"!=typeof ArrayBuffer,l=\"undefined\"!=typeof DataView,s=Array.isArray,p=Object.keys,v=Object.create,h=c&&ArrayBuffer.isView,y=isNaN,d=isFinite,g=!{toString:null}.propertyIsEnumerable(\"toString\"),b=[\"valueOf\",\"isPrototypeOf\",\"toString\",\"propertyIsEnumerable\",\"hasOwnProperty\",\"toLocaleString\"],m=Math.pow(2,53)-1;function j(n,r){return r=null==r?n.length-1:+r,function(){for(var t=Math.max(arguments.length-r,0),e=Array(t),u=0;u<t;u++)e[u]=arguments[u+r];switch(r){case 0:return n.call(this,e);case 1:return n.call(this,arguments[0],e);case 2:return n.call(this,arguments[0],arguments[1],e)}var i=Array(r+1);for(u=0;u<r;u++)i[u]=arguments[u];return i[r]=e,n.apply(this,i)}}function w(n){var r=typeof n;return\"function\"===r||\"object\"===r&&!!n}function _(n){return void 0===n}function A(n){return!0===n||!1===n||\"[object Boolean]\"===a.call(n)}function x(n){var r=\"[object \"+n+\"]\";return function(n){return a.call(n)===r}}var S=x(\"String\"),O=x(\"Number\"),M=x(\"Date\"),E=x(\"RegExp\"),B=x(\"Error\"),N=x(\"Symbol\"),I=x(\"ArrayBuffer\"),T=x(\"Function\"),k=r.document&&r.document.childNodes;\"function\"!=typeof/./&&\"object\"!=typeof Int8Array&&\"function\"!=typeof k&&(T=function(n){return\"function\"==typeof n||!1});var D=T,R=x(\"Object\"),V=l&&(!/\\[native code\\]/.test(String(DataView))||R(new DataView(new ArrayBuffer(8)))),F=\"undefined\"!=typeof Map&&R(new Map),P=x(\"DataView\");var q=V?function(n){return null!=n&&D(n.getInt8)&&I(n.buffer)}:P,U=s||x(\"Array\");function W(n,r){return null!=n&&f.call(n,r)}var z=x(\"Arguments\");!function(){z(arguments)||(z=function(n){return W(n,\"callee\")})}();var L=z;function $(n){return O(n)&&y(n)}function C(n){return function(){return n}}function K(n){return function(r){var t=n(r);return\"number\"==typeof t&&t>=0&&t<=m}}function J(n){return function(r){return null==r?void 0:r[n]}}var G=J(\"byteLength\"),H=K(G),Q=/\\[object ((I|Ui)nt(8|16|32)|Float(32|64)|Uint8Clamped|Big(I|Ui)nt64)Array\\]/;var X=c?function(n){return h?h(n)&&!q(n):H(n)&&Q.test(a.call(n))}:C(!1),Y=J(\"length\");function Z(n,r){r=function(n){for(var r={},t=n.length,e=0;e<t;++e)r[n[e]]=!0;return{contains:function(n){return!0===r[n]},push:function(t){return r[t]=!0,n.push(t)}}}(r);var t=b.length,u=n.constructor,i=D(u)&&u.prototype||e,o=\"constructor\";for(W(n,o)&&!r.contains(o)&&r.push(o);t--;)(o=b[t])in n&&n[o]!==i[o]&&!r.contains(o)&&r.push(o)}function nn(n){if(!w(n))return[];if(p)return p(n);var r=[];for(var t in n)W(n,t)&&r.push(t);return g&&Z(n,r),r}function rn(n,r){var t=nn(r),e=t.length;if(null==n)return!e;for(var u=Object(n),i=0;i<e;i++){var o=t[i];if(r[o]!==u[o]||!(o in u))return!1}return!0}function tn(n){return n instanceof tn?n:this instanceof tn?void(this._wrapped=n):new tn(n)}function en(n){return new Uint8Array(n.buffer||n,n.byteOffset||0,G(n))}tn.VERSION=n,tn.prototype.value=function(){return this._wrapped},tn.prototype.valueOf=tn.prototype.toJSON=tn.prototype.value,tn.prototype.toString=function(){return String(this._wrapped)};var un=\"[object DataView]\";function on(n,r,t,e){if(n===r)return 0!==n||1/n==1/r;if(null==n||null==r)return!1;if(n!=n)return r!=r;var i=typeof n;return(\"function\"===i||\"object\"===i||\"object\"==typeof r)&&function n(r,t,e,i){r instanceof tn&&(r=r._wrapped);t instanceof tn&&(t=t._wrapped);var o=a.call(r);if(o!==a.call(t))return!1;if(V&&\"[object Object]\"==o&&q(r)){if(!q(t))return!1;o=un}switch(o){case\"[object RegExp]\":case\"[object String]\":return\"\"+r==\"\"+t;case\"[object Number]\":return+r!=+r?+t!=+t:0==+r?1/+r==1/t:+r==+t;case\"[object Date]\":case\"[object Boolean]\":return+r==+t;case\"[object Symbol]\":return u.valueOf.call(r)===u.valueOf.call(t);case\"[object ArrayBuffer]\":case un:return n(en(r),en(t),e,i)}var f=\"[object Array]\"===o;if(!f&&X(r)){if(G(r)!==G(t))return!1;if(r.buffer===t.buffer&&r.byteOffset===t.byteOffset)return!0;f=!0}if(!f){if(\"object\"!=typeof r||\"object\"!=typeof t)return!1;var c=r.constructor,l=t.constructor;if(c!==l&&!(D(c)&&c instanceof c&&D(l)&&l instanceof l)&&\"constructor\"in r&&\"constructor\"in t)return!1}i=i||[];var s=(e=e||[]).length;for(;s--;)if(e[s]===r)return i[s]===t;if(e.push(r),i.push(t),f){if((s=r.length)!==t.length)return!1;for(;s--;)if(!on(r[s],t[s],e,i))return!1}else{var p,v=nn(r);if(s=v.length,nn(t).length!==s)return!1;for(;s--;)if(p=v[s],!W(t,p)||!on(r[p],t[p],e,i))return!1}return e.pop(),i.pop(),!0}(n,r,t,e)}function an(n){if(!w(n))return[];var r=[];for(var t in n)r.push(t);return g&&Z(n,r),r}function fn(n){var r=Y(n);return function(t){if(null==t)return!1;var e=an(t);if(Y(e))return!1;for(var u=0;u<r;u++)if(!D(t[n[u]]))return!1;return n!==hn||!D(t[cn])}}var cn=\"forEach\",ln=\"has\",sn=[\"clear\",\"delete\"],pn=[\"get\",ln,\"set\"],vn=sn.concat(cn,pn),hn=sn.concat(pn),yn=[\"add\"].concat(sn,cn,ln),dn=F?fn(vn):x(\"Map\"),gn=F?fn(hn):x(\"WeakMap\"),bn=F?fn(yn):x(\"Set\"),mn=x(\"WeakSet\");function jn(n){for(var r=nn(n),t=r.length,e=Array(t),u=0;u<t;u++)e[u]=n[r[u]];return e}function wn(n){for(var r={},t=nn(n),e=0,u=t.length;e<u;e++)r[n[t[e]]]=t[e];return r}function _n(n){var r=[];for(var t in n)D(n[t])&&r.push(t);return r.sort()}function An(n,r){return function(t){var e=arguments.length;if(r&&(t=Object(t)),e<2||null==t)return t;for(var u=1;u<e;u++)for(var i=arguments[u],o=n(i),a=o.length,f=0;f<a;f++){var c=o[f];r&&void 0!==t[c]||(t[c]=i[c])}return t}}var xn=An(an),Sn=An(nn),On=An(an,!0);function Mn(n){if(!w(n))return{};if(v)return v(n);var r=function(){};r.prototype=n;var t=new r;return r.prototype=null,t}function En(n){return U(n)?n:[n]}function Bn(n){return tn.toPath(n)}function Nn(n,r){for(var t=r.length,e=0;e<t;e++){if(null==n)return;n=n[r[e]]}return t?n:void 0}function In(n,r,t){var e=Nn(n,Bn(r));return _(e)?t:e}function Tn(n){return n}function kn(n){return n=Sn({},n),function(r){return rn(r,n)}}function Dn(n){return n=Bn(n),function(r){return Nn(r,n)}}function Rn(n,r,t){if(void 0===r)return n;switch(null==t?3:t){case 1:return function(t){return n.call(r,t)};case 3:return function(t,e,u){return n.call(r,t,e,u)};case 4:return function(t,e,u,i){return n.call(r,t,e,u,i)}}return function(){return n.apply(r,arguments)}}function Vn(n,r,t){return null==n?Tn:D(n)?Rn(n,r,t):w(n)&&!U(n)?kn(n):Dn(n)}function Fn(n,r){return Vn(n,r,1/0)}function Pn(n,r,t){return tn.iteratee!==Fn?tn.iteratee(n,r):Vn(n,r,t)}function qn(){}function Un(n,r){return null==r&&(r=n,n=0),n+Math.floor(Math.random()*(r-n+1))}tn.toPath=En,tn.iteratee=Fn;var Wn=Date.now||function(){return(new Date).getTime()};function zn(n){var r=function(r){return n[r]},t=\"(?:\"+nn(n).join(\"|\")+\")\",e=RegExp(t),u=RegExp(t,\"g\");return function(n){return n=null==n?\"\":\"\"+n,e.test(n)?n.replace(u,r):n}}var Ln={\"&\":\"&amp;\",\"<\":\"&lt;\",\">\":\"&gt;\",'\"':\"&quot;\",\"'\":\"&#x27;\",\"`\":\"&#x60;\"},$n=zn(Ln),Cn=zn(wn(Ln)),Kn=tn.templateSettings={evaluate:/<%([\\s\\S]+?)%>/g,interpolate:/<%=([\\s\\S]+?)%>/g,escape:/<%-([\\s\\S]+?)%>/g},Jn=/(.)^/,Gn={\"'\":\"'\",\"\\\\\":\"\\\\\",\"\\r\":\"r\",\"\\n\":\"n\",\"\\u2028\":\"u2028\",\"\\u2029\":\"u2029\"},Hn=/\\\\|'|\\r|\\n|\\u2028|\\u2029/g;function Qn(n){return\"\\\\\"+Gn[n]}var Xn=/^\\s*(\\w|\\$)+\\s*$/;var Yn=0;function Zn(n,r,t,e,u){if(!(e instanceof r))return n.apply(t,u);var i=Mn(n.prototype),o=n.apply(i,u);return w(o)?o:i}var nr=j((function(n,r){var t=nr.placeholder,e=function(){for(var u=0,i=r.length,o=Array(i),a=0;a<i;a++)o[a]=r[a]===t?arguments[u++]:r[a];for(;u<arguments.length;)o.push(arguments[u++]);return Zn(n,e,this,this,o)};return e}));nr.placeholder=tn;var rr=j((function(n,r,t){if(!D(n))throw new TypeError(\"Bind must be called on a function\");var e=j((function(u){return Zn(n,e,r,this,t.concat(u))}));return e})),tr=K(Y);function er(n,r,t,e){if(e=e||[],r||0===r){if(r<=0)return e.concat(n)}else r=1/0;for(var u=e.length,i=0,o=Y(n);i<o;i++){var a=n[i];if(tr(a)&&(U(a)||L(a)))if(r>1)er(a,r-1,t,e),u=e.length;else for(var f=0,c=a.length;f<c;)e[u++]=a[f++];else t||(e[u++]=a)}return e}var ur=j((function(n,r){var t=(r=er(r,!1,!1)).length;if(t<1)throw new Error(\"bindAll must be passed function names\");for(;t--;){var e=r[t];n[e]=rr(n[e],n)}return n}));var ir=j((function(n,r,t){return setTimeout((function(){return n.apply(null,t)}),r)})),or=nr(ir,tn,1);function ar(n){return function(){return!n.apply(this,arguments)}}function fr(n,r){var t;return function(){return--n>0&&(t=r.apply(this,arguments)),n<=1&&(r=null),t}}var cr=nr(fr,2);function lr(n,r,t){r=Pn(r,t);for(var e,u=nn(n),i=0,o=u.length;i<o;i++)if(r(n[e=u[i]],e,n))return e}function sr(n){return function(r,t,e){t=Pn(t,e);for(var u=Y(r),i=n>0?0:u-1;i>=0&&i<u;i+=n)if(t(r[i],i,r))return i;return-1}}var pr=sr(1),vr=sr(-1);function hr(n,r,t,e){for(var u=(t=Pn(t,e,1))(r),i=0,o=Y(n);i<o;){var a=Math.floor((i+o)/2);t(n[a])<u?i=a+1:o=a}return i}function yr(n,r,t){return function(e,u,i){var a=0,f=Y(e);if(\"number\"==typeof i)n>0?a=i>=0?i:Math.max(i+f,a):f=i>=0?Math.min(i+1,f):i+f+1;else if(t&&i&&f)return e[i=t(e,u)]===u?i:-1;if(u!=u)return(i=r(o.call(e,a,f),$))>=0?i+a:-1;for(i=n>0?a:f-1;i>=0&&i<f;i+=n)if(e[i]===u)return i;return-1}}var dr=yr(1,pr,hr),gr=yr(-1,vr);function br(n,r,t){var e=(tr(n)?pr:lr)(n,r,t);if(void 0!==e&&-1!==e)return n[e]}function mr(n,r,t){var e,u;if(r=Rn(r,t),tr(n))for(e=0,u=n.length;e<u;e++)r(n[e],e,n);else{var i=nn(n);for(e=0,u=i.length;e<u;e++)r(n[i[e]],i[e],n)}return n}function jr(n,r,t){r=Pn(r,t);for(var e=!tr(n)&&nn(n),u=(e||n).length,i=Array(u),o=0;o<u;o++){var a=e?e[o]:o;i[o]=r(n[a],a,n)}return i}function wr(n){var r=function(r,t,e,u){var i=!tr(r)&&nn(r),o=(i||r).length,a=n>0?0:o-1;for(u||(e=r[i?i[a]:a],a+=n);a>=0&&a<o;a+=n){var f=i?i[a]:a;e=t(e,r[f],f,r)}return e};return function(n,t,e,u){var i=arguments.length>=3;return r(n,Rn(t,u,4),e,i)}}var _r=wr(1),Ar=wr(-1);function xr(n,r,t){var e=[];return r=Pn(r,t),mr(n,(function(n,t,u){r(n,t,u)&&e.push(n)})),e}function Sr(n,r,t){r=Pn(r,t);for(var e=!tr(n)&&nn(n),u=(e||n).length,i=0;i<u;i++){var o=e?e[i]:i;if(!r(n[o],o,n))return!1}return!0}function Or(n,r,t){r=Pn(r,t);for(var e=!tr(n)&&nn(n),u=(e||n).length,i=0;i<u;i++){var o=e?e[i]:i;if(r(n[o],o,n))return!0}return!1}function Mr(n,r,t,e){return tr(n)||(n=jn(n)),(\"number\"!=typeof t||e)&&(t=0),dr(n,r,t)>=0}var Er=j((function(n,r,t){var e,u;return D(r)?u=r:(r=Bn(r),e=r.slice(0,-1),r=r[r.length-1]),jr(n,(function(n){var i=u;if(!i){if(e&&e.length&&(n=Nn(n,e)),null==n)return;i=n[r]}return null==i?i:i.apply(n,t)}))}));function Br(n,r){return jr(n,Dn(r))}function Nr(n,r,t){var e,u,i=-1/0,o=-1/0;if(null==r||\"number\"==typeof r&&\"object\"!=typeof n[0]&&null!=n)for(var a=0,f=(n=tr(n)?n:jn(n)).length;a<f;a++)null!=(e=n[a])&&e>i&&(i=e);else r=Pn(r,t),mr(n,(function(n,t,e){((u=r(n,t,e))>o||u===-1/0&&i===-1/0)&&(i=n,o=u)}));return i}var Ir=/[^\\ud800-\\udfff]|[\\ud800-\\udbff][\\udc00-\\udfff]|[\\ud800-\\udfff]/g;function Tr(n){return n?U(n)?o.call(n):S(n)?n.match(Ir):tr(n)?jr(n,Tn):jn(n):[]}function kr(n,r,t){if(null==r||t)return tr(n)||(n=jn(n)),n[Un(n.length-1)];var e=Tr(n),u=Y(e);r=Math.max(Math.min(r,u),0);for(var i=u-1,o=0;o<r;o++){var a=Un(o,i),f=e[o];e[o]=e[a],e[a]=f}return e.slice(0,r)}function Dr(n,r){return function(t,e,u){var i=r?[[],[]]:{};return e=Pn(e,u),mr(t,(function(r,u){var o=e(r,u,t);n(i,r,o)})),i}}var Rr=Dr((function(n,r,t){W(n,t)?n[t].push(r):n[t]=[r]})),Vr=Dr((function(n,r,t){n[t]=r})),Fr=Dr((function(n,r,t){W(n,t)?n[t]++:n[t]=1})),Pr=Dr((function(n,r,t){n[t?0:1].push(r)}),!0);function qr(n,r,t){return r in t}var Ur=j((function(n,r){var t={},e=r[0];if(null==n)return t;D(e)?(r.length>1&&(e=Rn(e,r[1])),r=an(n)):(e=qr,r=er(r,!1,!1),n=Object(n));for(var u=0,i=r.length;u<i;u++){var o=r[u],a=n[o];e(a,o,n)&&(t[o]=a)}return t})),Wr=j((function(n,r){var t,e=r[0];return D(e)?(e=ar(e),r.length>1&&(t=r[1])):(r=jr(er(r,!1,!1),String),e=function(n,t){return!Mr(r,t)}),Ur(n,e,t)}));function zr(n,r,t){return o.call(n,0,Math.max(0,n.length-(null==r||t?1:r)))}function Lr(n,r,t){return null==n||n.length<1?null==r||t?void 0:[]:null==r||t?n[0]:zr(n,n.length-r)}function $r(n,r,t){return o.call(n,null==r||t?1:r)}var Cr=j((function(n,r){return r=er(r,!0,!0),xr(n,(function(n){return!Mr(r,n)}))})),Kr=j((function(n,r){return Cr(n,r)}));function Jr(n,r,t,e){A(r)||(e=t,t=r,r=!1),null!=t&&(t=Pn(t,e));for(var u=[],i=[],o=0,a=Y(n);o<a;o++){var f=n[o],c=t?t(f,o,n):f;r&&!t?(o&&i===c||u.push(f),i=c):t?Mr(i,c)||(i.push(c),u.push(f)):Mr(u,f)||u.push(f)}return u}var Gr=j((function(n){return Jr(er(n,!0,!0))}));function Hr(n){for(var r=n&&Nr(n,Y).length||0,t=Array(r),e=0;e<r;e++)t[e]=Br(n,e);return t}var Qr=j(Hr);function Xr(n,r){return n._chain?tn(r).chain():r}function Yr(n){return mr(_n(n),(function(r){var t=tn[r]=n[r];tn.prototype[r]=function(){var n=[this._wrapped];return i.apply(n,arguments),Xr(this,t.apply(tn,n))}})),tn}mr([\"pop\",\"push\",\"reverse\",\"shift\",\"sort\",\"splice\",\"unshift\"],(function(n){var r=t[n];tn.prototype[n]=function(){var t=this._wrapped;return null!=t&&(r.apply(t,arguments),\"shift\"!==n&&\"splice\"!==n||0!==t.length||delete t[0]),Xr(this,t)}})),mr([\"concat\",\"join\",\"slice\"],(function(n){var r=t[n];tn.prototype[n]=function(){var n=this._wrapped;return null!=n&&(n=r.apply(n,arguments)),Xr(this,n)}}));var Zr=Yr({__proto__:null,VERSION:n,restArguments:j,isObject:w,isNull:function(n){return null===n},isUndefined:_,isBoolean:A,isElement:function(n){return!(!n||1!==n.nodeType)},isString:S,isNumber:O,isDate:M,isRegExp:E,isError:B,isSymbol:N,isArrayBuffer:I,isDataView:q,isArray:U,isFunction:D,isArguments:L,isFinite:function(n){return!N(n)&&d(n)&&!isNaN(parseFloat(n))},isNaN:$,isTypedArray:X,isEmpty:function(n){if(null==n)return!0;var r=Y(n);return\"number\"==typeof r&&(U(n)||S(n)||L(n))?0===r:0===Y(nn(n))},isMatch:rn,isEqual:function(n,r){return on(n,r)},isMap:dn,isWeakMap:gn,isSet:bn,isWeakSet:mn,keys:nn,allKeys:an,values:jn,pairs:function(n){for(var r=nn(n),t=r.length,e=Array(t),u=0;u<t;u++)e[u]=[r[u],n[r[u]]];return e},invert:wn,functions:_n,methods:_n,extend:xn,extendOwn:Sn,assign:Sn,defaults:On,create:function(n,r){var t=Mn(n);return r&&Sn(t,r),t},clone:function(n){return w(n)?U(n)?n.slice():xn({},n):n},tap:function(n,r){return r(n),n},get:In,has:function(n,r){for(var t=(r=Bn(r)).length,e=0;e<t;e++){var u=r[e];if(!W(n,u))return!1;n=n[u]}return!!t},mapObject:function(n,r,t){r=Pn(r,t);for(var e=nn(n),u=e.length,i={},o=0;o<u;o++){var a=e[o];i[a]=r(n[a],a,n)}return i},identity:Tn,constant:C,noop:qn,toPath:En,property:Dn,propertyOf:function(n){return null==n?qn:function(r){return In(n,r)}},matcher:kn,matches:kn,times:function(n,r,t){var e=Array(Math.max(0,n));r=Rn(r,t,1);for(var u=0;u<n;u++)e[u]=r(u);return e},random:Un,now:Wn,escape:$n,unescape:Cn,templateSettings:Kn,template:function(n,r,t){!r&&t&&(r=t),r=On({},r,tn.templateSettings);var e=RegExp([(r.escape||Jn).source,(r.interpolate||Jn).source,(r.evaluate||Jn).source].join(\"|\")+\"|$\",\"g\"),u=0,i=\"__p+='\";n.replace(e,(function(r,t,e,o,a){return i+=n.slice(u,a).replace(Hn,Qn),u=a+r.length,t?i+=\"'+\\n((__t=(\"+t+\"))==null?'':_.escape(__t))+\\n'\":e?i+=\"'+\\n((__t=(\"+e+\"))==null?'':__t)+\\n'\":o&&(i+=\"';\\n\"+o+\"\\n__p+='\"),r})),i+=\"';\\n\";var o,a=r.variable;if(a){if(!Xn.test(a))throw new Error(\"variable is not a bare identifier: \"+a)}else i=\"with(obj||{}){\\n\"+i+\"}\\n\",a=\"obj\";i=\"var __t,__p='',__j=Array.prototype.join,\"+\"print=function(){__p+=__j.call(arguments,'');};\\n\"+i+\"return __p;\\n\";try{o=new Function(a,\"_\",i)}catch(n){throw n.source=i,n}var f=function(n){return o.call(this,n,tn)};return f.source=\"function(\"+a+\"){\\n\"+i+\"}\",f},result:function(n,r,t){var e=(r=Bn(r)).length;if(!e)return D(t)?t.call(n):t;for(var u=0;u<e;u++){var i=null==n?void 0:n[r[u]];void 0===i&&(i=t,u=e),n=D(i)?i.call(n):i}return n},uniqueId:function(n){var r=++Yn+\"\";return n?n+r:r},chain:function(n){var r=tn(n);return r._chain=!0,r},iteratee:Fn,partial:nr,bind:rr,bindAll:ur,memoize:function(n,r){var t=function(e){var u=t.cache,i=\"\"+(r?r.apply(this,arguments):e);return W(u,i)||(u[i]=n.apply(this,arguments)),u[i]};return t.cache={},t},delay:ir,defer:or,throttle:function(n,r,t){var e,u,i,o,a=0;t||(t={});var f=function(){a=!1===t.leading?0:Wn(),e=null,o=n.apply(u,i),e||(u=i=null)},c=function(){var c=Wn();a||!1!==t.leading||(a=c);var l=r-(c-a);return u=this,i=arguments,l<=0||l>r?(e&&(clearTimeout(e),e=null),a=c,o=n.apply(u,i),e||(u=i=null)):e||!1===t.trailing||(e=setTimeout(f,l)),o};return c.cancel=function(){clearTimeout(e),a=0,e=u=i=null},c},debounce:function(n,r,t){var e,u,i,o,a,f=function(){var c=Wn()-u;r>c?e=setTimeout(f,r-c):(e=null,t||(o=n.apply(a,i)),e||(i=a=null))},c=j((function(c){return a=this,i=c,u=Wn(),e||(e=setTimeout(f,r),t&&(o=n.apply(a,i))),o}));return c.cancel=function(){clearTimeout(e),e=i=a=null},c},wrap:function(n,r){return nr(r,n)},negate:ar,compose:function(){var n=arguments,r=n.length-1;return function(){for(var t=r,e=n[r].apply(this,arguments);t--;)e=n[t].call(this,e);return e}},after:function(n,r){return function(){if(--n<1)return r.apply(this,arguments)}},before:fr,once:cr,findKey:lr,findIndex:pr,findLastIndex:vr,sortedIndex:hr,indexOf:dr,lastIndexOf:gr,find:br,detect:br,findWhere:function(n,r){return br(n,kn(r))},each:mr,forEach:mr,map:jr,collect:jr,reduce:_r,foldl:_r,inject:_r,reduceRight:Ar,foldr:Ar,filter:xr,select:xr,reject:function(n,r,t){return xr(n,ar(Pn(r)),t)},every:Sr,all:Sr,some:Or,any:Or,contains:Mr,includes:Mr,include:Mr,invoke:Er,pluck:Br,where:function(n,r){return xr(n,kn(r))},max:Nr,min:function(n,r,t){var e,u,i=1/0,o=1/0;if(null==r||\"number\"==typeof r&&\"object\"!=typeof n[0]&&null!=n)for(var a=0,f=(n=tr(n)?n:jn(n)).length;a<f;a++)null!=(e=n[a])&&e<i&&(i=e);else r=Pn(r,t),mr(n,(function(n,t,e){((u=r(n,t,e))<o||u===1/0&&i===1/0)&&(i=n,o=u)}));return i},shuffle:function(n){return kr(n,1/0)},sample:kr,sortBy:function(n,r,t){var e=0;return r=Pn(r,t),Br(jr(n,(function(n,t,u){return{value:n,index:e++,criteria:r(n,t,u)}})).sort((function(n,r){var t=n.criteria,e=r.criteria;if(t!==e){if(t>e||void 0===t)return 1;if(t<e||void 0===e)return-1}return n.index-r.index})),\"value\")},groupBy:Rr,indexBy:Vr,countBy:Fr,partition:Pr,toArray:Tr,size:function(n){return null==n?0:tr(n)?n.length:nn(n).length},pick:Ur,omit:Wr,first:Lr,head:Lr,take:Lr,initial:zr,last:function(n,r,t){return null==n||n.length<1?null==r||t?void 0:[]:null==r||t?n[n.length-1]:$r(n,Math.max(0,n.length-r))},rest:$r,tail:$r,drop:$r,compact:function(n){return xr(n,Boolean)},flatten:function(n,r){return er(n,r,!1)},without:Kr,uniq:Jr,unique:Jr,union:Gr,intersection:function(n){for(var r=[],t=arguments.length,e=0,u=Y(n);e<u;e++){var i=n[e];if(!Mr(r,i)){var o;for(o=1;o<t&&Mr(arguments[o],i);o++);o===t&&r.push(i)}}return r},difference:Cr,unzip:Hr,transpose:Hr,zip:Qr,object:function(n,r){for(var t={},e=0,u=Y(n);e<u;e++)r?t[n[e]]=r[e]:t[n[e][0]]=n[e][1];return t},range:function(n,r,t){null==r&&(r=n||0,n=0),t||(t=r<n?-1:1);for(var e=Math.max(Math.ceil((r-n)/t),0),u=Array(e),i=0;i<e;i++,n+=t)u[i]=n;return u},chunk:function(n,r){if(null==r||r<1)return[];for(var t=[],e=0,u=n.length;e<u;)t.push(o.call(n,e,e+=r));return t},mixin:Yr,default:tn});return Zr._=Zr,Zr}));"
  },
  {
    "path": "underscore/underscore.go",
    "content": "// Package underscore contains the source for the JavaScript utility-belt library.\n//\n//\timport (\n//\t\t_ \"github.com/robertkrimen/otto/underscore\"\n//\t)\n//\n// Every Otto runtime will now include [underscore] for more information see the [underscore docs]\n//\n// By importing this package, you'll automatically load underscore every time you create a new Otto runtime.\n//\n// To prevent this behavior, you can do the following:\n//\n//\timport (\n//\t\t\"github.com/robertkrimen/otto/underscore\"\n//\t)\n//\n//\tfunc init() {\n//\t\tunderscore.Disable()\n//\t}\n//\n// [underscore]: http://underscorejs.org\n// [underscore docs]: https://github.com/documentcloud/underscore\npackage underscore\n\nimport (\n\t_ \"embed\" // Embed underscore.\n\n\t\"github.com/robertkrimen/otto/registry\"\n)\n\n//go:embed underscore-min.js\nvar underscore string\nvar entry *registry.Entry = registry.Register(Source)\n\n// Enable underscore runtime inclusion.\nfunc Enable() {\n\tentry.Enable()\n}\n\n// Disable underscore runtime inclusion.\nfunc Disable() {\n\tentry.Disable()\n}\n\n// Source returns the underscore source.\nfunc Source() string {\n\treturn underscore\n}\n"
  },
  {
    "path": "underscore_arrays_test.go",
    "content": "package otto\n\nimport (\n\t\"testing\"\n)\n\n// first.\nfunc Test_underscore_arrays_0(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"first\", function() {\n    equal(_.first([1,2,3]), 1, 'can pull out the first element of an array');\n    equal(_([1, 2, 3]).first(), 1, 'can perform OO-style \"first()\"');\n    equal(_.first([1,2,3], 0).join(', '), \"\", 'can pass an index to first');\n    equal(_.first([1,2,3], 2).join(', '), '1, 2', 'can pass an index to first');\n    equal(_.first([1,2,3], 5).join(', '), '1, 2, 3', 'can pass an index to first');\n    var result = (function(){ return _.first(arguments); })(4, 3, 2, 1);\n    equal(result, 4, 'works on an arguments object.');\n    result = _.map([[1,2,3],[1,2,3]], _.first);\n    equal(result.join(','), '1,1', 'works well with _.map');\n    result = (function() { return _.take([1,2,3], 2); })();\n    equal(result.join(','), '1,2', 'aliased as take');\n\n    equal(_.first(null), undefined, 'handles nulls');\n  });\n        `)\n\t})\n}\n\n// rest.\nfunc Test_underscore_arrays_1(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"rest\", function() {\n    var numbers = [1, 2, 3, 4];\n    equal(_.rest(numbers).join(\", \"), \"2, 3, 4\", 'working rest()');\n    equal(_.rest(numbers, 0).join(\", \"), \"1, 2, 3, 4\", 'working rest(0)');\n    equal(_.rest(numbers, 2).join(', '), '3, 4', 'rest can take an index');\n    var result = (function(){ return _(arguments).tail(); })(1, 2, 3, 4);\n    equal(result.join(', '), '2, 3, 4', 'aliased as tail and works on arguments object');\n    result = _.map([[1,2,3],[1,2,3]], _.rest);\n    equal(_.flatten(result).join(','), '2,3,2,3', 'works well with _.map');\n    result = (function(){ return _(arguments).drop(); })(1, 2, 3, 4);\n    equal(result.join(', '), '2, 3, 4', 'aliased as drop and works on arguments object');\n  });\n        `)\n\t})\n}\n\n// initial.\nfunc Test_underscore_arrays_2(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"initial\", function() {\n    equal(_.initial([1,2,3,4,5]).join(\", \"), \"1, 2, 3, 4\", 'working initial()');\n    equal(_.initial([1,2,3,4],2).join(\", \"), \"1, 2\", 'initial can take an index');\n    var result = (function(){ return _(arguments).initial(); })(1, 2, 3, 4);\n    equal(result.join(\", \"), \"1, 2, 3\", 'initial works on arguments object');\n    result = _.map([[1,2,3],[1,2,3]], _.initial);\n    equal(_.flatten(result).join(','), '1,2,1,2', 'initial works with _.map');\n  });\n        `)\n\t})\n}\n\n// last.\nfunc Test_underscore_arrays_3(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"last\", function() {\n    equal(_.last([1,2,3]), 3, 'can pull out the last element of an array');\n    equal(_.last([1,2,3], 0).join(', '), \"\", 'can pass an index to last');\n    equal(_.last([1,2,3], 2).join(', '), '2, 3', 'can pass an index to last');\n    equal(_.last([1,2,3], 5).join(', '), '1, 2, 3', 'can pass an index to last');\n    var result = (function(){ return _(arguments).last(); })(1, 2, 3, 4);\n    equal(result, 4, 'works on an arguments object');\n    result = _.map([[1,2,3],[1,2,3]], _.last);\n    equal(result.join(','), '3,3', 'works well with _.map');\n\n    equal(_.last(null), undefined, 'handles nulls');\n  });\n        `)\n\t})\n}\n\n// compact.\nfunc Test_underscore_arrays_4(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"compact\", function() {\n    equal(_.compact([0, 1, false, 2, false, 3]).length, 3, 'can trim out all falsy values');\n    var result = (function(){ return _.compact(arguments).length; })(0, 1, false, 2, false, 3);\n    equal(result, 3, 'works on an arguments object');\n  });\n        `)\n\t})\n}\n\n// flatten.\nfunc Test_underscore_arrays_5(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"flatten\", function() {\n    var list = [1, [2], [3, [[[4]]]]];\n    deepEqual(_.flatten(list), [1,2,3,4], 'can flatten nested arrays');\n    deepEqual(_.flatten(list, true), [1,2,3,[[[4]]]], 'can shallowly flatten nested arrays');\n    var result = (function(){ return _.flatten(arguments); })(1, [2], [3, [[[4]]]]);\n    deepEqual(result, [1,2,3,4], 'works on an arguments object');\n  });\n        `)\n\t})\n}\n\n// without.\nfunc Test_underscore_arrays_6(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"without\", function() {\n    var list = [1, 2, 1, 0, 3, 1, 4];\n    equal(_.without(list, 0, 1).join(', '), '2, 3, 4', 'can remove all instances of an object');\n    var result = (function(){ return _.without(arguments, 0, 1); })(1, 2, 1, 0, 3, 1, 4);\n    equal(result.join(', '), '2, 3, 4', 'works on an arguments object');\n\n    var list = [{one : 1}, {two : 2}];\n    ok(_.without(list, {one : 1}).length == 2, 'uses real object identity for comparisons.');\n    ok(_.without(list, list[0]).length == 1, 'ditto.');\n  });\n        `)\n\t})\n}\n\n// uniq.\nfunc Test_underscore_arrays_7(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"uniq\", function() {\n    var list = [1, 2, 1, 3, 1, 4];\n    equal(_.uniq(list).join(', '), '1, 2, 3, 4', 'can find the unique values of an unsorted array');\n\n    var list = [1, 1, 1, 2, 2, 3];\n    equal(_.uniq(list, true).join(', '), '1, 2, 3', 'can find the unique values of a sorted array faster');\n\n    var list = [{name:'moe'}, {name:'curly'}, {name:'larry'}, {name:'curly'}];\n    var iterator = function(value) { return value.name; };\n    equal(_.map(_.uniq(list, false, iterator), iterator).join(', '), 'moe, curly, larry', 'can find the unique values of an array using a custom iterator');\n\n    equal(_.map(_.uniq(list, iterator), iterator).join(', '), 'moe, curly, larry', 'can find the unique values of an array using a custom iterator without specifying whether array is sorted');\n\n    var iterator = function(value) { return value +1; };\n    var list = [1, 2, 2, 3, 4, 4];\n    equal(_.uniq(list, true, iterator).join(', '), '1, 2, 3, 4', 'iterator works with sorted array');\n\n    var result = (function(){ return _.uniq(arguments); })(1, 2, 1, 3, 1, 4);\n    equal(result.join(', '), '1, 2, 3, 4', 'works on an arguments object');\n  });\n        `)\n\t})\n}\n\n// intersection.\nfunc Test_underscore_arrays_8(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"intersection\", function() {\n    var stooges = ['moe', 'curly', 'larry'], leaders = ['moe', 'groucho'];\n    equal(_.intersection(stooges, leaders).join(''), 'moe', 'can take the set intersection of two arrays');\n    equal(_(stooges).intersection(leaders).join(''), 'moe', 'can perform an OO-style intersection');\n    var result = (function(){ return _.intersection(arguments, leaders); })('moe', 'curly', 'larry');\n    equal(result.join(''), 'moe', 'works on an arguments object');\n  });\n        `)\n\t})\n}\n\n// union.\nfunc Test_underscore_arrays_9(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"union\", function() {\n    var result = _.union([1, 2, 3], [2, 30, 1], [1, 40]);\n    equal(result.join(' '), '1 2 3 30 40', 'takes the union of a list of arrays');\n\n    var result = _.union([1, 2, 3], [2, 30, 1], [1, 40, [1]]);\n    equal(result.join(' '), '1 2 3 30 40 1', 'takes the union of a list of nested arrays');\n  });\n        `)\n\t})\n}\n\n// difference.\nfunc Test_underscore_arrays_10(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"difference\", function() {\n    var result = _.difference([1, 2, 3], [2, 30, 40]);\n    equal(result.join(' '), '1 3', 'takes the difference of two arrays');\n\n    var result = _.difference([1, 2, 3, 4], [2, 30, 40], [1, 11, 111]);\n    equal(result.join(' '), '3 4', 'takes the difference of three arrays');\n  });\n        `)\n\t})\n}\n\n// zip.\nfunc Test_underscore_arrays_11(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test('zip', function() {\n    var names = ['moe', 'larry', 'curly'], ages = [30, 40, 50], leaders = [true];\n    var stooges = _.zip(names, ages, leaders);\n    equal(String(stooges), 'moe,30,true,larry,40,,curly,50,', 'zipped together arrays of different lengths');\n  });\n        `)\n\t})\n}\n\n// object.\nfunc Test_underscore_arrays_12(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test('object', function() {\n    var result = _.object(['moe', 'larry', 'curly'], [30, 40, 50]);\n    var shouldBe = {moe: 30, larry: 40, curly: 50};\n    ok(_.isEqual(result, shouldBe), 'two arrays zipped together into an object');\n\n    result = _.object([['one', 1], ['two', 2], ['three', 3]]);\n    shouldBe = {one: 1, two: 2, three: 3};\n    ok(_.isEqual(result, shouldBe), 'an array of pairs zipped together into an object');\n\n    var stooges = {moe: 30, larry: 40, curly: 50};\n    ok(_.isEqual(_.object(_.pairs(stooges)), stooges), 'an object converted to pairs and back to an object');\n\n    ok(_.isEqual(_.object(null), {}), 'handles nulls');\n  });\n        `)\n\t})\n}\n\n// indexOf.\nfunc Test_underscore_arrays_13(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"indexOf\", function() {\n    var numbers = [1, 2, 3];\n    numbers.indexOf = null;\n    equal(_.indexOf(numbers, 2), 1, 'can compute indexOf, even without the native function');\n    var result = (function(){ return _.indexOf(arguments, 2); })(1, 2, 3);\n    equal(result, 1, 'works on an arguments object');\n    equal(_.indexOf(null, 2), -1, 'handles nulls properly');\n\n    var numbers = [10, 20, 30, 40, 50], num = 35;\n    var index = _.indexOf(numbers, num, true);\n    equal(index, -1, '35 is not in the list');\n\n    numbers = [10, 20, 30, 40, 50]; num = 40;\n    index = _.indexOf(numbers, num, true);\n    equal(index, 3, '40 is in the list');\n\n    numbers = [1, 40, 40, 40, 40, 40, 40, 40, 50, 60, 70]; num = 40;\n    index = _.indexOf(numbers, num, true);\n    equal(index, 1, '40 is in the list');\n\n    numbers = [1, 2, 3, 1, 2, 3, 1, 2, 3];\n    index = _.indexOf(numbers, 2, 5);\n    equal(index, 7, 'supports the fromIndex argument');\n  });\n        `)\n\t})\n}\n\n// lastIndexOf.\nfunc Test_underscore_arrays_14(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"lastIndexOf\", function() {\n    var numbers = [1, 0, 1];\n    equal(_.lastIndexOf(numbers, 1), 2);\n\n    numbers = [1, 0, 1, 0, 0, 1, 0, 0, 0];\n    numbers.lastIndexOf = null;\n    equal(_.lastIndexOf(numbers, 1), 5, 'can compute lastIndexOf, even without the native function');\n    equal(_.lastIndexOf(numbers, 0), 8, 'lastIndexOf the other element');\n    var result = (function(){ return _.lastIndexOf(arguments, 1); })(1, 0, 1, 0, 0, 1, 0, 0, 0);\n    equal(result, 5, 'works on an arguments object');\n    equal(_.indexOf(null, 2), -1, 'handles nulls properly');\n\n    numbers = [1, 2, 3, 1, 2, 3, 1, 2, 3];\n    var index = _.lastIndexOf(numbers, 2, 2);\n    equal(index, 1, 'supports the fromIndex argument');\n  });\n        `)\n\t})\n}\n\n// range.\nfunc Test_underscore_arrays_15(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"range\", function() {\n    equal(_.range(0).join(''), '', 'range with 0 as a first argument generates an empty array');\n    equal(_.range(4).join(' '), '0 1 2 3', 'range with a single positive argument generates an array of elements 0,1,2,...,n-1');\n    equal(_.range(5, 8).join(' '), '5 6 7', 'range with two arguments a &amp; b, a&lt;b generates an array of elements a,a+1,a+2,...,b-2,b-1');\n    equal(_.range(8, 5).join(' '), '8 7 6', 'range with two arguments a &amp; b, b&lt;a generates an array of elements 8,..6');\n    equal(_.range(3, 10, 3).join(' '), '3 6 9', 'range with three arguments a &amp; b &amp; c, c &lt; b-a, a &lt; b generates an array of elements a,a+c,a+2c,...,b - (multiplier of a) &lt; c');\n    equal(_.range(3, 10, 15).join(''), '3', 'range with three arguments a &amp; b &amp; c, c &gt; b-a, a &lt; b generates an array with a single element, equal to a');\n    equal(_.range(12, 7, -2).join(' '), '12 10 8', 'range with three arguments a &amp; b &amp; c, a &gt; b, c &lt; 0 generates an array of elements a,a-c,a-2c and ends with the number not less than b');\n    equal(_.range(0, -10, -1).join(' '), '0 -1 -2 -3 -4 -5 -6 -7 -8 -9', 'final example in the Python docs');\n  });\n        `)\n\t})\n}\n"
  },
  {
    "path": "underscore_chaining_test.go",
    "content": "package otto\n\nimport (\n\t\"testing\"\n)\n\n// map/flatten/reduce.\nfunc Test_underscore_chaining_0(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"map/flatten/reduce\", function() {\n    var lyrics = [\n      \"I'm a lumberjack and I'm okay\",\n      \"I sleep all night and I work all day\",\n      \"He's a lumberjack and he's okay\",\n      \"He sleeps all night and he works all day\"\n    ];\n    var counts = _(lyrics).chain()\n      .map(function(line) { return line.split(''); })\n      .flatten()\n      .reduce(function(hash, l) {\n        hash[l] = hash[l] || 0;\n        hash[l]++;\n        return hash;\n    }, {}).value();\n    ok(counts['a'] == 16 && counts['e'] == 10, 'counted all the letters in the song');\n  });\n        `)\n\t})\n}\n\n// select/reject/sortBy.\nfunc Test_underscore_chaining_1(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"select/reject/sortBy\", function() {\n    var numbers = [1,2,3,4,5,6,7,8,9,10];\n    numbers = _(numbers).chain().select(function(n) {\n      return n % 2 == 0;\n    }).reject(function(n) {\n      return n % 4 == 0;\n    }).sortBy(function(n) {\n      return -n;\n    }).value();\n    equal(numbers.join(', '), \"10, 6, 2\", \"filtered and reversed the numbers\");\n  });\n        `)\n\t})\n}\n\n// select/reject/sortBy in functional style.\nfunc Test_underscore_chaining_2(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"select/reject/sortBy in functional style\", function() {\n    var numbers = [1,2,3,4,5,6,7,8,9,10];\n    numbers = _.chain(numbers).select(function(n) {\n      return n % 2 == 0;\n    }).reject(function(n) {\n      return n % 4 == 0;\n    }).sortBy(function(n) {\n      return -n;\n    }).value();\n    equal(numbers.join(', '), \"10, 6, 2\", \"filtered and reversed the numbers\");\n  });\n        `)\n\t})\n}\n\n// reverse/concat/unshift/pop/map.\nfunc Test_underscore_chaining_3(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"reverse/concat/unshift/pop/map\", function() {\n    var numbers = [1,2,3,4,5];\n    numbers = _(numbers).chain()\n      .reverse()\n      .concat([5, 5, 5])\n      .unshift(17)\n      .pop()\n      .map(function(n){ return n * 2; })\n      .value();\n    equal(numbers.join(', '), \"34, 10, 8, 6, 4, 2, 10, 10\", 'can chain together array functions.');\n  });\n        `)\n\t})\n}\n"
  },
  {
    "path": "underscore_collections_test.go",
    "content": "package otto\n\nimport (\n\t\"testing\"\n)\n\n// each.\nfunc Test_underscore_collections_0(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"each\", function() {\n    _.each([1, 2, 3], function(num, i) {\n      equal(num, i + 1, 'each iterators provide value and iteration count');\n    });\n\n    var answers = [];\n    _.each([1, 2, 3], function(num){ answers.push(num * this.multiplier);}, {multiplier : 5});\n    equal(answers.join(', '), '5, 10, 15', 'context object property accessed');\n\n    answers = [];\n    _.forEach([1, 2, 3], function(num){ answers.push(num); });\n    equal(answers.join(', '), '1, 2, 3', 'aliased as \"forEach\"');\n\n    answers = [];\n    var obj = {one : 1, two : 2, three : 3};\n    obj.constructor.prototype.four = 4;\n    _.each(obj, function(value, key){ answers.push(key); });\n    equal(answers.join(\", \"), 'one, two, three', 'iterating over objects works, and ignores the object prototype.');\n    delete obj.constructor.prototype.four;\n\n    var answer = null;\n    _.each([1, 2, 3], function(num, index, arr){ if (_.include(arr, num)) answer = true; });\n    ok(answer, 'can reference the original collection from inside the iterator');\n\n    answers = 0;\n    _.each(null, function(){ ++answers; });\n    equal(answers, 0, 'handles a null properly');\n  });\n        `)\n\t})\n}\n\n// map.\nfunc Test_underscore_collections_1(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test('map', function() {\n    var doubled = _.map([1, 2, 3], function(num){ return num * 2; });\n    equal(doubled.join(', '), '2, 4, 6', 'doubled numbers');\n\n    doubled = _.collect([1, 2, 3], function(num){ return num * 2; });\n    equal(doubled.join(', '), '2, 4, 6', 'aliased as \"collect\"');\n\n    var tripled = _.map([1, 2, 3], function(num){ return num * this.multiplier; }, {multiplier : 3});\n    equal(tripled.join(', '), '3, 6, 9', 'tripled numbers with context');\n\n    var doubled = _([1, 2, 3]).map(function(num){ return num * 2; });\n    equal(doubled.join(', '), '2, 4, 6', 'OO-style doubled numbers');\n\n    // TEST: ReferenceError: document is not defined\n    return;\n\n    if (document.querySelectorAll) {\n      var ids = _.map(document.querySelectorAll('#map-test *'), function(n){ return n.id; });\n      deepEqual(ids, ['id1', 'id2'], 'Can use collection methods on NodeLists.');\n    }\n\n    var ids = _.map($('#map-test').children(), function(n){ return n.id; });\n    deepEqual(ids, ['id1', 'id2'], 'Can use collection methods on jQuery Array-likes.');\n\n    var ids = _.map(document.images, function(n){ return n.id; });\n    ok(ids[0] == 'chart_image', 'can use collection methods on HTMLCollections');\n\n    var ifnull = _.map(null, function(){});\n    ok(_.isArray(ifnull) && ifnull.length === 0, 'handles a null properly');\n  });\n        `)\n\t})\n}\n\n// reduce.\nfunc Test_underscore_collections_2(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test('reduce', function() {\n    var sum = _.reduce([1, 2, 3], function(sum, num){ return sum + num; }, 0);\n    equal(sum, 6, 'can sum up an array');\n\n    var context = {multiplier : 3};\n    sum = _.reduce([1, 2, 3], function(sum, num){ return sum + num * this.multiplier; }, 0, context);\n    equal(sum, 18, 'can reduce with a context object');\n\n    sum = _.inject([1, 2, 3], function(sum, num){ return sum + num; }, 0);\n    equal(sum, 6, 'aliased as \"inject\"');\n\n    sum = _([1, 2, 3]).reduce(function(sum, num){ return sum + num; }, 0);\n    equal(sum, 6, 'OO-style reduce');\n\n    var sum = _.reduce([1, 2, 3], function(sum, num){ return sum + num; });\n    equal(sum, 6, 'default initial value');\n\n    var ifnull;\n    try {\n      _.reduce(null, function(){});\n    } catch (ex) {\n      ifnull = ex;\n    }\n    ok(ifnull instanceof TypeError, 'handles a null (without initial value) properly');\n\n    ok(_.reduce(null, function(){}, 138) === 138, 'handles a null (with initial value) properly');\n    equal(_.reduce([], function(){}, undefined), undefined, 'undefined can be passed as a special case');\n    equal(_.reduce([], function(){}), undefined, 'undefined is the default case');\n  });\n        `)\n\t})\n}\n\n// reduceRight.\nfunc Test_underscore_collections_3(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test('reduceRight', function() {\n    var list = _.reduceRight([\"foo\", \"bar\", \"baz\"], function(memo, str){ return memo + str; }, '');\n    equal(list, 'bazbarfoo', 'can perform right folds');\n\n    var list = _.foldr([\"foo\", \"bar\", \"baz\"], function(memo, str){ return memo + str; }, '');\n    equal(list, 'bazbarfoo', 'aliased as \"foldr\"');\n\n    var list = _.foldr([\"foo\", \"bar\", \"baz\"], function(memo, str){ return memo + str; });\n    equal(list, 'bazbarfoo', 'default initial value');\n\n    var ifnull;\n    try {\n      _.reduceRight(null, function(){});\n    } catch (ex) {\n      ifnull = ex;\n    }\n    ok(ifnull instanceof TypeError, 'handles a null (without initial value) properly');\n\n    var sum = _.reduceRight({a: 1, b: 2, c: 3}, function(sum, num){ return sum + num; });\n    equal(sum, 6, 'default initial value on object');\n\n    ok(_.reduceRight(null, function(){}, 138) === 138, 'handles a null (with initial value) properly');\n\n    equal(_.reduceRight([], function(){}, undefined), undefined, 'undefined can be passed as a special case');\n    equal(_.reduceRight([], function(){}), undefined, 'undefined for empty array and no initial value');\n\n    // Assert that the correct arguments are being passed.\n\n    var args,\n        memo = {},\n        object = {a: 1, b: 2},\n        lastKey = _.keys(object).pop();\n\n    var expected = lastKey == 'a'\n      ? [memo, 1, 'a', object]\n      : [memo, 2, 'b', object];\n\n    _.reduceRight(object, function() {\n      args || (args = _.toArray(arguments));\n    }, memo);\n\n    deepEqual(args, expected);\n\n    // And again, with numeric keys.\n\n    object = {'2': 'a', '1': 'b'};\n    lastKey = _.keys(object).pop();\n    args = null;\n\n    expected = lastKey == '2'\n      ? [memo, 'a', '2', object]\n      : [memo, 'b', '1', object];\n\n    _.reduceRight(object, function() {\n      args || (args = _.toArray(arguments));\n    }, memo);\n\n    deepEqual(args, expected);\n  });\n        `)\n\t})\n}\n\n// find.\nfunc Test_underscore_collections_4(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test('find', function() {\n    var array = [1, 2, 3, 4];\n    strictEqual(_.find(array, function(n) { return n > 2; }), 3, 'should return first found <value>');\n    strictEqual(_.find(array, function() { return false; }), void 0, 'should return <undefined> if <value> is not found');\n  });\n        `)\n\t})\n}\n\n// detect.\nfunc Test_underscore_collections_5(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test('detect', function() {\n    var result = _.detect([1, 2, 3], function(num){ return num * 2 == 4; });\n    equal(result, 2, 'found the first \"2\" and broke the loop');\n  });\n        `)\n\t})\n}\n\n// select.\nfunc Test_underscore_collections_6(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test('select', function() {\n    var evens = _.select([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });\n    equal(evens.join(', '), '2, 4, 6', 'selected each even number');\n\n    evens = _.filter([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });\n    equal(evens.join(', '), '2, 4, 6', 'aliased as \"filter\"');\n  });\n        `)\n\t})\n}\n\n// reject.\nfunc Test_underscore_collections_7(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test('reject', function() {\n    var odds = _.reject([1, 2, 3, 4, 5, 6], function(num){ return num % 2 == 0; });\n    equal(odds.join(', '), '1, 3, 5', 'rejected each even number');\n\n    var context = \"obj\";\n\n    var evens = _.reject([1, 2, 3, 4, 5, 6], function(num){\n      equal(context, \"obj\");\n      return num % 2 != 0;\n    }, context);\n    equal(evens.join(', '), '2, 4, 6', 'rejected each odd number');\n  });\n        `)\n\t})\n}\n\n// all.\nfunc Test_underscore_collections_8(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test('all', function() {\n    ok(_.all([], _.identity), 'the empty set');\n    ok(_.all([true, true, true], _.identity), 'all true values');\n    ok(!_.all([true, false, true], _.identity), 'one false value');\n    ok(_.all([0, 10, 28], function(num){ return num % 2 == 0; }), 'even numbers');\n    ok(!_.all([0, 11, 28], function(num){ return num % 2 == 0; }), 'an odd number');\n    ok(_.all([1], _.identity) === true, 'cast to boolean - true');\n    ok(_.all([0], _.identity) === false, 'cast to boolean - false');\n    ok(_.every([true, true, true], _.identity), 'aliased as \"every\"');\n    ok(!_.all([undefined, undefined, undefined], _.identity), 'works with arrays of undefined');\n  });\n        `)\n\t})\n}\n\n// any.\nfunc Test_underscore_collections_9(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test('any', function() {\n    var nativeSome = Array.prototype.some;\n    Array.prototype.some = null;\n    ok(!_.any([]), 'the empty set');\n    ok(!_.any([false, false, false]), 'all false values');\n    ok(_.any([false, false, true]), 'one true value');\n    ok(_.any([null, 0, 'yes', false]), 'a string');\n    ok(!_.any([null, 0, '', false]), 'falsy values');\n    ok(!_.any([1, 11, 29], function(num){ return num % 2 == 0; }), 'all odd numbers');\n    ok(_.any([1, 10, 29], function(num){ return num % 2 == 0; }), 'an even number');\n    ok(_.any([1], _.identity) === true, 'cast to boolean - true');\n    ok(_.any([0], _.identity) === false, 'cast to boolean - false');\n    ok(_.some([false, false, true]), 'aliased as \"some\"');\n    Array.prototype.some = nativeSome;\n  });\n        `)\n\t})\n}\n\n// include.\nfunc Test_underscore_collections_10(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test('include', function() {\n    ok(_.include([1,2,3], 2), 'two is in the array');\n    ok(!_.include([1,3,9], 2), 'two is not in the array');\n    ok(_.contains({moe:1, larry:3, curly:9}, 3) === true, '_.include on objects checks their values');\n    ok(_([1,2,3]).include(2), 'OO-style include');\n  });\n        `)\n\t})\n}\n\n// invoke.\nfunc Test_underscore_collections_11(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test('invoke', function() {\n    var list = [[5, 1, 7], [3, 2, 1]];\n    var result = _.invoke(list, 'sort');\n    equal(result[0].join(', '), '1, 5, 7', 'first array sorted');\n    equal(result[1].join(', '), '1, 2, 3', 'second array sorted');\n  });\n        `)\n\t})\n}\n\n// invoke w/ function reference.\nfunc Test_underscore_collections_12(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test('invoke w/ function reference', function() {\n    var list = [[5, 1, 7], [3, 2, 1]];\n    var result = _.invoke(list, Array.prototype.sort);\n    equal(result[0].join(', '), '1, 5, 7', 'first array sorted');\n    equal(result[1].join(', '), '1, 2, 3', 'second array sorted');\n  });\n        `)\n\t})\n}\n\n// invoke when strings have a call method.\nfunc Test_underscore_collections_13(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test('invoke when strings have a call method', function() {\n    String.prototype.call = function() {\n      return 42;\n    };\n    var list = [[5, 1, 7], [3, 2, 1]];\n    var s = \"foo\";\n    equal(s.call(), 42, \"call function exists\");\n    var result = _.invoke(list, 'sort');\n    equal(result[0].join(', '), '1, 5, 7', 'first array sorted');\n    equal(result[1].join(', '), '1, 2, 3', 'second array sorted');\n    delete String.prototype.call;\n    equal(s.call, undefined, \"call function removed\");\n  });\n        `)\n\t})\n}\n\n// pluck.\nfunc Test_underscore_collections_14(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test('pluck', function() {\n    var people = [{name : 'moe', age : 30}, {name : 'curly', age : 50}];\n    equal(_.pluck(people, 'name').join(', '), 'moe, curly', 'pulls names out of objects');\n  });\n        `)\n\t})\n}\n\n// where.\nfunc Test_underscore_collections_15(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test('where', function() {\n    var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}];\n    var result = _.where(list, {a: 1});\n    equal(result.length, 3);\n    equal(result[result.length - 1].b, 4);\n    result = _.where(list, {b: 2});\n    equal(result.length, 2);\n    equal(result[0].a, 1);\n  });\n        `)\n\t})\n}\n\n// findWhere.\nfunc Test_underscore_collections_16(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test('findWhere', function() {\n    var list = [{a: 1, b: 2}, {a: 2, b: 2}, {a: 1, b: 3}, {a: 1, b: 4}, {a: 2, b: 4}];\n    var result = _.findWhere(list, {a: 1});\n    deepEqual(result, {a: 1, b: 2});\n    result = _.findWhere(list, {b: 4});\n    deepEqual(result, {a: 1, b: 4});\n  });\n        `)\n\t})\n}\n\n// max.\nfunc Test_underscore_collections_17(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test('max', function() {\n    equal(3, _.max([1, 2, 3]), 'can perform a regular Math.max');\n\n    var neg = _.max([1, 2, 3], function(num){ return -num; });\n    equal(neg, 1, 'can perform a computation-based max');\n\n    equal(-Infinity, _.max({}), 'Maximum value of an empty object');\n    equal(-Infinity, _.max([]), 'Maximum value of an empty array');\n    equal(_.max({'a': 'a'}), -Infinity, 'Maximum value of a non-numeric collection');\n\n    // TEST: Takes too long\n    return;\n\n    equal(299999, _.max(_.range(1,300000)), \"Maximum value of a too-big array\");\n  });\n        `)\n\t})\n}\n\n// min.\nfunc Test_underscore_collections_18(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test('min', function() {\n    equal(1, _.min([1, 2, 3]), 'can perform a regular Math.min');\n\n    var neg = _.min([1, 2, 3], function(num){ return -num; });\n    equal(neg, 3, 'can perform a computation-based min');\n\n    equal(Infinity, _.min({}), 'Minimum value of an empty object');\n    equal(Infinity, _.min([]), 'Minimum value of an empty array');\n    equal(_.min({'a': 'a'}), Infinity, 'Minimum value of a non-numeric collection');\n\n    var now = new Date(9999999999);\n    var then = new Date(0);\n    equal(_.min([now, then]), then);\n\n    // TEST: Takes too long\n    return;\n\n    equal(1, _.min(_.range(1,300000)), \"Minimum value of a too-big array\");\n  });\n        `)\n\t})\n}\n\n// sortBy.\nfunc Test_underscore_collections_19(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test('sortBy', function() {\n    var people = [{name : 'curly', age : 50}, {name : 'moe', age : 30}];\n    people = _.sortBy(people, function(person){ return person.age; });\n    equal(_.pluck(people, 'name').join(', '), 'moe, curly', 'stooges sorted by age');\n\n    var list = [undefined, 4, 1, undefined, 3, 2];\n    equal(_.sortBy(list, _.identity).join(','), '1,2,3,4,,', 'sortBy with undefined values');\n\n    var list = [\"one\", \"two\", \"three\", \"four\", \"five\"];\n    var sorted = _.sortBy(list, 'length');\n    equal(sorted.join(' '), 'one two four five three', 'sorted by length');\n\n    function Pair(x, y) {\n      this.x = x;\n      this.y = y;\n    }\n\n    var collection = [\n      new Pair(1, 1), new Pair(1, 2),\n      new Pair(1, 3), new Pair(1, 4),\n      new Pair(1, 5), new Pair(1, 6),\n      new Pair(2, 1), new Pair(2, 2),\n      new Pair(2, 3), new Pair(2, 4),\n      new Pair(2, 5), new Pair(2, 6),\n      new Pair(undefined, 1), new Pair(undefined, 2),\n      new Pair(undefined, 3), new Pair(undefined, 4),\n      new Pair(undefined, 5), new Pair(undefined, 6)\n    ];\n\n    var actual = _.sortBy(collection, function(pair) {\n      return pair.x;\n    });\n\n    deepEqual(actual, collection, 'sortBy should be stable');\n  });\n        `)\n\t})\n}\n\n// groupBy.\nfunc Test_underscore_collections_20(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test('groupBy', function() {\n    var parity = _.groupBy([1, 2, 3, 4, 5, 6], function(num){ return num % 2; });\n    ok('0' in parity && '1' in parity, 'created a group for each value');\n    equal(parity[0].join(', '), '2, 4, 6', 'put each even number in the right group');\n\n    var list = [\"one\", \"two\", \"three\", \"four\", \"five\", \"six\", \"seven\", \"eight\", \"nine\", \"ten\"];\n    var grouped = _.groupBy(list, 'length');\n    equal(grouped['3'].join(' '), 'one two six ten');\n    equal(grouped['4'].join(' '), 'four five nine');\n    equal(grouped['5'].join(' '), 'three seven eight');\n\n    var context = {};\n    _.groupBy([{}], function(){ ok(this === context); }, context);\n\n    grouped = _.groupBy([4.2, 6.1, 6.4], function(num) {\n      return Math.floor(num) > 4 ? 'hasOwnProperty' : 'constructor';\n    });\n    equal(grouped.constructor.length, 1);\n    equal(grouped.hasOwnProperty.length, 2);\n\n    var array = [{}];\n    _.groupBy(array, function(value, index, obj){ ok(obj === array); });\n\n    var array = [1, 2, 1, 2, 3];\n    var grouped = _.groupBy(array);\n    equal(grouped['1'].length, 2);\n    equal(grouped['3'].length, 1);\n  });\n        `)\n\t})\n}\n\n// countBy.\nfunc Test_underscore_collections_21(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test('countBy', function() {\n    var parity = _.countBy([1, 2, 3, 4, 5], function(num){ return num % 2 == 0; });\n    equal(parity['true'], 2);\n    equal(parity['false'], 3);\n\n    var list = [\"one\", \"two\", \"three\", \"four\", \"five\", \"six\", \"seven\", \"eight\", \"nine\", \"ten\"];\n    var grouped = _.countBy(list, 'length');\n    equal(grouped['3'], 4);\n    equal(grouped['4'], 3);\n    equal(grouped['5'], 3);\n\n    var context = {};\n    _.countBy([{}], function(){ ok(this === context); }, context);\n\n    grouped = _.countBy([4.2, 6.1, 6.4], function(num) {\n      return Math.floor(num) > 4 ? 'hasOwnProperty' : 'constructor';\n    });\n    equal(grouped.constructor, 1);\n    equal(grouped.hasOwnProperty, 2);\n\n    var array = [{}];\n    _.countBy(array, function(value, index, obj){ ok(obj === array); });\n\n    var array = [1, 2, 1, 2, 3];\n    var grouped = _.countBy(array);\n    equal(grouped['1'], 2);\n    equal(grouped['3'], 1);\n  });\n        `)\n\t})\n}\n\n// sortedIndex.\nfunc Test_underscore_collections_22(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test('sortedIndex', function() {\n    var numbers = [10, 20, 30, 40, 50], num = 35;\n    var indexForNum = _.sortedIndex(numbers, num);\n    equal(indexForNum, 3, '35 should be inserted at index 3');\n\n    var indexFor30 = _.sortedIndex(numbers, 30);\n    equal(indexFor30, 2, '30 should be inserted at index 2');\n\n    var objects = [{x: 10}, {x: 20}, {x: 30}, {x: 40}];\n    var iterator = function(obj){ return obj.x; };\n    strictEqual(_.sortedIndex(objects, {x: 25}, iterator), 2);\n    strictEqual(_.sortedIndex(objects, {x: 35}, 'x'), 3);\n\n    var context = {1: 2, 2: 3, 3: 4};\n    iterator = function(obj){ return this[obj]; };\n    strictEqual(_.sortedIndex([1, 3], 2, iterator, context), 1);\n  });\n        `)\n\t})\n}\n\n// shuffle.\nfunc Test_underscore_collections_23(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test('shuffle', function() {\n    var numbers = _.range(10);\n    var shuffled = _.shuffle(numbers).sort();\n    notStrictEqual(numbers, shuffled, 'original object is unmodified');\n    equal(shuffled.join(','), numbers.join(','), 'contains the same members before and after shuffle');\n  });\n        `)\n\t})\n}\n\n// toArray.\nfunc Test_underscore_collections_24(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test('toArray', function() {\n    ok(!_.isArray(arguments), 'arguments object is not an array');\n    ok(_.isArray(_.toArray(arguments)), 'arguments object converted into array');\n    var a = [1,2,3];\n    ok(_.toArray(a) !== a, 'array is cloned');\n    equal(_.toArray(a).join(', '), '1, 2, 3', 'cloned array contains same elements');\n\n    var numbers = _.toArray({one : 1, two : 2, three : 3});\n    equal(numbers.join(', '), '1, 2, 3', 'object flattened into array');\n\n    // TEST: ReferenceError: document is not defined\n    return;\n\n    // test in IE < 9\n    try {\n      var actual = _.toArray(document.childNodes);\n    } catch(ex) { }\n\n    ok(_.isArray(actual), 'should not throw converting a node list');\n  });\n        `)\n\t})\n}\n\n// size.\nfunc Test_underscore_collections_25(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test('size', function() {\n    equal(_.size({one : 1, two : 2, three : 3}), 3, 'can compute the size of an object');\n    equal(_.size([1, 2, 3]), 3, 'can compute the size of an array');\n\n    var func = function() {\n      return _.size(arguments);\n    };\n\n    equal(func(1, 2, 3, 4), 4, 'can test the size of the arguments object');\n\n    equal(_.size('hello'), 5, 'can compute the size of a string');\n\n    equal(_.size(null), 0, 'handles nulls');\n  });\n        `)\n\t})\n}\n"
  },
  {
    "path": "underscore_functions_test.go",
    "content": "package otto\n\nimport (\n\t\"testing\"\n)\n\n// bind.\nfunc Test_underscore_functions_0(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"bind\", function() {\n    var context = {name : 'moe'};\n    var func = function(arg) { return \"name: \" + (this.name || arg); };\n    var bound = _.bind(func, context);\n    equal(bound(), 'name: moe', 'can bind a function to a context');\n\n    bound = _(func).bind(context);\n    equal(bound(), 'name: moe', 'can do OO-style binding');\n\n    bound = _.bind(func, null, 'curly');\n    equal(bound(), 'name: curly', 'can bind without specifying a context');\n\n    func = function(salutation, name) { return salutation + ': ' + name; };\n    func = _.bind(func, this, 'hello');\n    equal(func('moe'), 'hello: moe', 'the function was partially applied in advance');\n\n    func = _.bind(func, this, 'curly');\n    equal(func(), 'hello: curly', 'the function was completely applied in advance');\n\n    func = function(salutation, firstname, lastname) { return salutation + ': ' + firstname + ' ' + lastname; };\n    func = _.bind(func, this, 'hello', 'moe', 'curly');\n    equal(func(), 'hello: moe curly', 'the function was partially applied in advance and can accept multiple arguments');\n\n    func = function(context, message) { equal(this, context, message); };\n    _.bind(func, 0, 0, 'can bind a function to <0>')();\n    _.bind(func, '', '', 'can bind a function to an empty string')();\n    _.bind(func, false, false, 'can bind a function to <false>')();\n\n    // These tests are only meaningful when using a browser without a native bind function\n    // To test this with a modern browser, set underscore's nativeBind to undefined\n    var F = function () { return this; };\n    var Boundf = _.bind(F, {hello: \"moe curly\"});\n    equal(Boundf().hello, \"moe curly\", \"When called without the new operator, it's OK to be bound to the context\");\n  });\n        `)\n\t})\n}\n\n// partial.\nfunc Test_underscore_functions_1(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"partial\", function() {\n    var obj = {name: 'moe'};\n    var func = function() { return this.name + ' ' + _.toArray(arguments).join(' '); };\n\n    obj.func = _.partial(func, 'a', 'b');\n    equal(obj.func('c', 'd'), 'moe a b c d', 'can partially apply');\n  });\n        `)\n\t})\n}\n\n// bindAll.\nfunc Test_underscore_functions_2(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"bindAll\", function() {\n    var curly = {name : 'curly'}, moe = {\n      name    : 'moe',\n      getName : function() { return 'name: ' + this.name; },\n      sayHi   : function() { return 'hi: ' + this.name; }\n    };\n    curly.getName = moe.getName;\n    _.bindAll(moe, 'getName', 'sayHi');\n    curly.sayHi = moe.sayHi;\n    equal(curly.getName(), 'name: curly', 'unbound function is bound to current object');\n    equal(curly.sayHi(), 'hi: moe', 'bound function is still bound to original object');\n  });\n        `)\n\t})\n}\n\n// memoize.\nfunc Test_underscore_functions_3(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"memoize\", function() {\n    var fib = function(n) {\n      return n < 2 ? n : fib(n - 1) + fib(n - 2);\n    };\n    var fastFib = _.memoize(fib);\n    equal(fib(10), 55, 'a memoized version of fibonacci produces identical results');\n    equal(fastFib(10), 55, 'a memoized version of fibonacci produces identical results');\n\n    var o = function(str) {\n      return str;\n    };\n    var fastO = _.memoize(o);\n    equal(o('toString'), 'toString', 'checks hasOwnProperty');\n    equal(fastO('toString'), 'toString', 'checks hasOwnProperty');\n  });\n        `)\n\t})\n}\n\n// once.\nfunc Test_underscore_functions_4(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"once\", function() {\n    var num = 0;\n    var increment = _.once(function(){ num++; });\n    increment();\n    increment();\n    equal(num, 1);\n  });\n        `)\n\t})\n}\n\n// wrap.\nfunc Test_underscore_functions_5(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"wrap\", function() {\n    var greet = function(name){ return \"hi: \" + name; };\n    var backwards = _.wrap(greet, function(func, name){ return func(name) + ' ' + name.split('').reverse().join(''); });\n    equal(backwards('moe'), 'hi: moe eom', 'wrapped the saluation function');\n\n    var inner = function(){ return \"Hello \"; };\n    var obj   = {name : \"Moe\"};\n    obj.hi    = _.wrap(inner, function(fn){ return fn() + this.name; });\n    equal(obj.hi(), \"Hello Moe\");\n\n    var noop    = function(){};\n    var wrapped = _.wrap(noop, function(fn){ return Array.prototype.slice.call(arguments, 0); });\n    var ret     = wrapped(['whats', 'your'], 'vector', 'victor');\n    deepEqual(ret, [noop, ['whats', 'your'], 'vector', 'victor']);\n  });\n        `)\n\t})\n}\n\n// compose.\nfunc Test_underscore_functions_6(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"compose\", function() {\n    var greet = function(name){ return \"hi: \" + name; };\n    var exclaim = function(sentence){ return sentence + '!'; };\n    var composed = _.compose(exclaim, greet);\n    equal(composed('moe'), 'hi: moe!', 'can compose a function that takes another');\n\n    composed = _.compose(greet, exclaim);\n    equal(composed('moe'), 'hi: moe!', 'in this case, the functions are also commutative');\n  });\n        `)\n\t})\n}\n\n// after.\nfunc Test_underscore_functions_7(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"after\", function() {\n    var testAfter = function(afterAmount, timesCalled) {\n      var afterCalled = 0;\n      var after = _.after(afterAmount, function() {\n        afterCalled++;\n      });\n      while (timesCalled--) after();\n      return afterCalled;\n    };\n\n    equal(testAfter(5, 5), 1, \"after(N) should fire after being called N times\");\n    equal(testAfter(5, 4), 0, \"after(N) should not fire unless called N times\");\n    equal(testAfter(0, 1), 1, \"after(0) should fire immediately\");\n  });\n        `)\n\t})\n}\n"
  },
  {
    "path": "underscore_objects_test.go",
    "content": "package otto\n\nimport (\n\t\"testing\"\n)\n\n// keys.\nfunc Test_underscore_objects_0(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"keys\", function() {\n    equal(_.keys({one : 1, two : 2}).join(', '), 'one, two', 'can extract the keys from an object');\n    // the test above is not safe because it relies on for-in enumeration order\n    var a = []; a[1] = 0;\n    equal(_.keys(a).join(', '), '1', 'is not fooled by sparse arrays; see issue #95');\n    equal(_.keys(null).join(''), '', 'empty array for <null> values');\n    equal(_.keys(void 0).join(''), '', 'empty array for <undefined> values');\n    equal(_.keys(1).join(''), '', 'empty array for number primitives');\n    equal(_.keys('a').join(''), '', 'empty array for string primitives');\n    equal(_.keys(true).join(''), '', 'empty array for boolean primitives');\n  });\n        `)\n\t})\n}\n\n// values.\nfunc Test_underscore_objects_1(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"values\", function() {\n    equal(_.values({one: 1, two: 2}).join(', '), '1, 2', 'can extract the values from an object');\n    equal(_.values({one: 1, two: 2, length: 3}).join(', '), '1, 2, 3', '... even when one of them is \"length\"');\n  });\n        `)\n\t})\n}\n\n// pairs.\nfunc Test_underscore_objects_2(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"pairs\", function() {\n    deepEqual(_.pairs({one: 1, two: 2}), [['one', 1], ['two', 2]], 'can convert an object into pairs');\n    deepEqual(_.pairs({one: 1, two: 2, length: 3}), [['one', 1], ['two', 2], ['length', 3]], '... even when one of them is \"length\"');\n  });\n        `)\n\t})\n}\n\n// invert.\nfunc Test_underscore_objects_3(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"invert\", function() {\n    var obj = {first: 'Moe', second: 'Larry', third: 'Curly'};\n    equal(_.keys(_.invert(obj)).join(' '), 'Moe Larry Curly', 'can invert an object');\n    ok(_.isEqual(_.invert(_.invert(obj)), obj), 'two inverts gets you back where you started');\n\n    var obj = {length: 3};\n    ok(_.invert(obj)['3'] == 'length', 'can invert an object with \"length\"')\n  });\n        `)\n\t})\n}\n\n// functions.\nfunc Test_underscore_objects_4(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"functions\", function() {\n    var obj = {a : 'dash', b : _.map, c : (/yo/), d : _.reduce};\n    ok(_.isEqual(['b', 'd'], _.functions(obj)), 'can grab the function names of any passed-in object');\n\n    var Animal = function(){};\n    Animal.prototype.run = function(){};\n    equal(_.functions(new Animal).join(''), 'run', 'also looks up functions on the prototype');\n  });\n        `)\n\t})\n}\n\n// extend.\nfunc Test_underscore_objects_5(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"extend\", function() {\n    var result;\n    equal(_.extend({}, {a:'b'}).a, 'b', 'can extend an object with the attributes of another');\n    equal(_.extend({a:'x'}, {a:'b'}).a, 'b', 'properties in source override destination');\n    equal(_.extend({x:'x'}, {a:'b'}).x, 'x', 'properties not in source dont get overriden');\n    result = _.extend({x:'x'}, {a:'a'}, {b:'b'});\n    ok(_.isEqual(result, {x:'x', a:'a', b:'b'}), 'can extend from multiple source objects');\n    result = _.extend({x:'x'}, {a:'a', x:2}, {a:'b'});\n    ok(_.isEqual(result, {x:2, a:'b'}), 'extending from multiple source objects last property trumps');\n    result = _.extend({}, {a: void 0, b: null});\n    equal(_.keys(result).join(''), 'ab', 'extend does not copy undefined values');\n\n    try {\n      result = {};\n      _.extend(result, null, undefined, {a:1});\n    } catch(ex) {}\n\n    equal(result.a, 1, 'should not error on <null> or <undefined> sources');\n  });\n        `)\n\t})\n}\n\n// pick.\nfunc Test_underscore_objects_6(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"pick\", function() {\n    var result;\n    result = _.pick({a:1, b:2, c:3}, 'a', 'c');\n    ok(_.isEqual(result, {a:1, c:3}), 'can restrict properties to those named');\n    result = _.pick({a:1, b:2, c:3}, ['b', 'c']);\n    ok(_.isEqual(result, {b:2, c:3}), 'can restrict properties to those named in an array');\n    result = _.pick({a:1, b:2, c:3}, ['a'], 'b');\n    ok(_.isEqual(result, {a:1, b:2}), 'can restrict properties to those named in mixed args');\n\n    var Obj = function(){};\n    Obj.prototype = {a: 1, b: 2, c: 3};\n    ok(_.isEqual(_.pick(new Obj, 'a', 'c'), {a:1, c: 3}), 'include prototype props');\n  });\n        `)\n\t})\n}\n\n// omit.\nfunc Test_underscore_objects_7(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"omit\", function() {\n    var result;\n    result = _.omit({a:1, b:2, c:3}, 'b');\n    ok(_.isEqual(result, {a:1, c:3}), 'can omit a single named property');\n    result = _.omit({a:1, b:2, c:3}, 'a', 'c');\n    ok(_.isEqual(result, {b:2}), 'can omit several named properties');\n    result = _.omit({a:1, b:2, c:3}, ['b', 'c']);\n    ok(_.isEqual(result, {a:1}), 'can omit properties named in an array');\n\n    var Obj = function(){};\n    Obj.prototype = {a: 1, b: 2, c: 3};\n    ok(_.isEqual(_.omit(new Obj, 'b'), {a:1, c: 3}), 'include prototype props');\n  });\n        `)\n\t})\n}\n\n// defaults.\nfunc Test_underscore_objects_8(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"defaults\", function() {\n    var result;\n    var options = {zero: 0, one: 1, empty: \"\", nan: NaN, string: \"string\"};\n\n    _.defaults(options, {zero: 1, one: 10, twenty: 20});\n    equal(options.zero, 0, 'value exists');\n    equal(options.one, 1, 'value exists');\n    equal(options.twenty, 20, 'default applied');\n\n    _.defaults(options, {empty: \"full\"}, {nan: \"nan\"}, {word: \"word\"}, {word: \"dog\"});\n    equal(options.empty, \"\", 'value exists');\n    ok(_.isNaN(options.nan), \"NaN isn't overridden\");\n    equal(options.word, \"word\", 'new value is added, first one wins');\n\n    try {\n      options = {};\n      _.defaults(options, null, undefined, {a:1});\n    } catch(ex) {}\n\n    equal(options.a, 1, 'should not error on <null> or <undefined> sources');\n  });\n        `)\n\t})\n}\n\n// clone.\nfunc Test_underscore_objects_9(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"clone\", function() {\n    var moe = {name : 'moe', lucky : [13, 27, 34]};\n    var clone = _.clone(moe);\n    equal(clone.name, 'moe', 'the clone as the attributes of the original');\n\n    clone.name = 'curly';\n    ok(clone.name == 'curly' && moe.name == 'moe', 'clones can change shallow attributes without affecting the original');\n\n    clone.lucky.push(101);\n    equal(_.last(moe.lucky), 101, 'changes to deep attributes are shared with the original');\n\n    equal(_.clone(undefined), void 0, 'non objects should not be changed by clone');\n    equal(_.clone(1), 1, 'non objects should not be changed by clone');\n    equal(_.clone(null), null, 'non objects should not be changed by clone');\n  });\n        `)\n\t})\n}\n\n// isEqual.\nfunc Test_underscore_objects_10(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"isEqual\", function() {\n    function First() {\n      this.value = 1;\n    }\n    First.prototype.value = 1;\n    function Second() {\n      this.value = 1;\n    }\n    Second.prototype.value = 2;\n\n    // Basic equality and identity comparisons.\n    ok(_.isEqual(null, null), \"<null> is equal to <null>\");\n    ok(_.isEqual(), \"<undefined> is equal to <undefined>\");\n\n    ok(!_.isEqual(0, -0), \"<0> is not equal to <-0>\");\n    ok(!_.isEqual(-0, 0), \"Commutative equality is implemented for <0> and <-0>\");\n    ok(!_.isEqual(null, undefined), \"<null> is not equal to <undefined>\");\n    ok(!_.isEqual(undefined, null), \"Commutative equality is implemented for <null> and <undefined>\");\n\n    // String object and primitive comparisons.\n    ok(_.isEqual(\"Curly\", \"Curly\"), \"Identical string primitives are equal\");\n    ok(_.isEqual(new String(\"Curly\"), new String(\"Curly\")), \"String objects with identical primitive values are equal\");\n    ok(_.isEqual(new String(\"Curly\"), \"Curly\"), \"String primitives and their corresponding object wrappers are equal\");\n    ok(_.isEqual(\"Curly\", new String(\"Curly\")), \"Commutative equality is implemented for string objects and primitives\");\n\n    ok(!_.isEqual(\"Curly\", \"Larry\"), \"String primitives with different values are not equal\");\n    ok(!_.isEqual(new String(\"Curly\"), new String(\"Larry\")), \"String objects with different primitive values are not equal\");\n    ok(!_.isEqual(new String(\"Curly\"), {toString: function(){ return \"Curly\"; }}), \"String objects and objects with a custom <toString> method are not equal\");\n\n    // Number object and primitive comparisons.\n    ok(_.isEqual(75, 75), \"Identical number primitives are equal\");\n    ok(_.isEqual(new Number(75), new Number(75)), \"Number objects with identical primitive values are equal\");\n    ok(_.isEqual(75, new Number(75)), \"Number primitives and their corresponding object wrappers are equal\");\n    ok(_.isEqual(new Number(75), 75), \"Commutative equality is implemented for number objects and primitives\");\n    ok(!_.isEqual(new Number(0), -0), \"<new Number(0)> and <-0> are not equal\");\n    ok(!_.isEqual(0, new Number(-0)), \"Commutative equality is implemented for <new Number(0)> and <-0>\");\n\n    ok(!_.isEqual(new Number(75), new Number(63)), \"Number objects with different primitive values are not equal\");\n    ok(!_.isEqual(new Number(63), {valueOf: function(){ return 63; }}), \"Number objects and objects with a <valueOf> method are not equal\");\n\n    // Comparisons involving <NaN>.\n    ok(_.isEqual(NaN, NaN), \"<NaN> is equal to <NaN>\");\n    ok(!_.isEqual(61, NaN), \"A number primitive is not equal to <NaN>\");\n    ok(!_.isEqual(new Number(79), NaN), \"A number object is not equal to <NaN>\");\n    ok(!_.isEqual(Infinity, NaN), \"<Infinity> is not equal to <NaN>\");\n\n    // Boolean object and primitive comparisons.\n    ok(_.isEqual(true, true), \"Identical boolean primitives are equal\");\n    ok(_.isEqual(new Boolean, new Boolean), \"Boolean objects with identical primitive values are equal\");\n    ok(_.isEqual(true, new Boolean(true)), \"Boolean primitives and their corresponding object wrappers are equal\");\n    ok(_.isEqual(new Boolean(true), true), \"Commutative equality is implemented for booleans\");\n    ok(!_.isEqual(new Boolean(true), new Boolean), \"Boolean objects with different primitive values are not equal\");\n\n    // Common type coercions.\n    ok(!_.isEqual(true, new Boolean(false)), \"Boolean objects are not equal to the boolean primitive <true>\");\n    ok(!_.isEqual(\"75\", 75), \"String and number primitives with like values are not equal\");\n    ok(!_.isEqual(new Number(63), new String(63)), \"String and number objects with like values are not equal\");\n    ok(!_.isEqual(75, \"75\"), \"Commutative equality is implemented for like string and number values\");\n    ok(!_.isEqual(0, \"\"), \"Number and string primitives with like values are not equal\");\n    ok(!_.isEqual(1, true), \"Number and boolean primitives with like values are not equal\");\n    ok(!_.isEqual(new Boolean(false), new Number(0)), \"Boolean and number objects with like values are not equal\");\n    ok(!_.isEqual(false, new String(\"\")), \"Boolean primitives and string objects with like values are not equal\");\n    ok(!_.isEqual(12564504e5, new Date(2009, 9, 25)), \"Dates and their corresponding numeric primitive values are not equal\");\n\n    // Dates.\n    ok(_.isEqual(new Date(2009, 9, 25), new Date(2009, 9, 25)), \"Date objects referencing identical times are equal\");\n    ok(!_.isEqual(new Date(2009, 9, 25), new Date(2009, 11, 13)), \"Date objects referencing different times are not equal\");\n    ok(!_.isEqual(new Date(2009, 11, 13), {\n      getTime: function(){\n        return 12606876e5;\n      }\n    }), \"Date objects and objects with a <getTime> method are not equal\");\n    ok(!_.isEqual(new Date(\"Curly\"), new Date(\"Curly\")), \"Invalid dates are not equal\");\n\n    // Functions.\n    ok(!_.isEqual(First, Second), \"Different functions with identical bodies and source code representations are not equal\");\n\n    // RegExps.\n    ok(_.isEqual(/(?:)/gim, /(?:)/gim), \"RegExps with equivalent patterns and flags are equal\");\n    ok(!_.isEqual(/(?:)/g, /(?:)/gi), \"RegExps with equivalent patterns and different flags are not equal\");\n    ok(!_.isEqual(/Moe/gim, /Curly/gim), \"RegExps with different patterns and equivalent flags are not equal\");\n    ok(!_.isEqual(/(?:)/gi, /(?:)/g), \"Commutative equality is implemented for RegExps\");\n    ok(!_.isEqual(/Curly/g, {source: \"Larry\", global: true, ignoreCase: false, multiline: false}), \"RegExps and RegExp-like objects are not equal\");\n\n    // Empty arrays, array-like objects, and object literals.\n    ok(_.isEqual({}, {}), \"Empty object literals are equal\");\n    ok(_.isEqual([], []), \"Empty array literals are equal\");\n    ok(_.isEqual([{}], [{}]), \"Empty nested arrays and objects are equal\");\n    ok(!_.isEqual({length: 0}, []), \"Array-like objects and arrays are not equal.\");\n    ok(!_.isEqual([], {length: 0}), \"Commutative equality is implemented for array-like objects\");\n\n    ok(!_.isEqual({}, []), \"Object literals and array literals are not equal\");\n    ok(!_.isEqual([], {}), \"Commutative equality is implemented for objects and arrays\");\n\n    // Arrays with primitive and object values.\n    ok(_.isEqual([1, \"Larry\", true], [1, \"Larry\", true]), \"Arrays containing identical primitives are equal\");\n    ok(_.isEqual([(/Moe/g), new Date(2009, 9, 25)], [(/Moe/g), new Date(2009, 9, 25)]), \"Arrays containing equivalent elements are equal\");\n\n    // Multi-dimensional arrays.\n    var a = [new Number(47), false, \"Larry\", /Moe/, new Date(2009, 11, 13), ['running', 'biking', new String('programming')], {a: 47}];\n    var b = [new Number(47), false, \"Larry\", /Moe/, new Date(2009, 11, 13), ['running', 'biking', new String('programming')], {a: 47}];\n    ok(_.isEqual(a, b), \"Arrays containing nested arrays and objects are recursively compared\");\n\n    // Overwrite the methods defined in ES 5.1 section 15.4.4.\n    a.forEach = a.map = a.filter = a.every = a.indexOf = a.lastIndexOf = a.some = a.reduce = a.reduceRight = null;\n    b.join = b.pop = b.reverse = b.shift = b.slice = b.splice = b.concat = b.sort = b.unshift = null;\n\n    // Array elements and properties.\n    ok(_.isEqual(a, b), \"Arrays containing equivalent elements and different non-numeric properties are equal\");\n    a.push(\"White Rocks\");\n    ok(!_.isEqual(a, b), \"Arrays of different lengths are not equal\");\n    a.push(\"East Boulder\");\n    b.push(\"Gunbarrel Ranch\", \"Teller Farm\");\n    ok(!_.isEqual(a, b), \"Arrays of identical lengths containing different elements are not equal\");\n\n    // Sparse arrays.\n    ok(_.isEqual(Array(3), Array(3)), \"Sparse arrays of identical lengths are equal\");\n    ok(!_.isEqual(Array(3), Array(6)), \"Sparse arrays of different lengths are not equal when both are empty\");\n\n    // Simple objects.\n    ok(_.isEqual({a: \"Curly\", b: 1, c: true}, {a: \"Curly\", b: 1, c: true}), \"Objects containing identical primitives are equal\");\n    ok(_.isEqual({a: /Curly/g, b: new Date(2009, 11, 13)}, {a: /Curly/g, b: new Date(2009, 11, 13)}), \"Objects containing equivalent members are equal\");\n    ok(!_.isEqual({a: 63, b: 75}, {a: 61, b: 55}), \"Objects of identical sizes with different values are not equal\");\n    ok(!_.isEqual({a: 63, b: 75}, {a: 61, c: 55}), \"Objects of identical sizes with different property names are not equal\");\n    ok(!_.isEqual({a: 1, b: 2}, {a: 1}), \"Objects of different sizes are not equal\");\n    ok(!_.isEqual({a: 1}, {a: 1, b: 2}), \"Commutative equality is implemented for objects\");\n    ok(!_.isEqual({x: 1, y: undefined}, {x: 1, z: 2}), \"Objects with identical keys and different values are not equivalent\");\n\n    // <A> contains nested objects and arrays.\n    a = {\n      name: new String(\"Moe Howard\"),\n      age: new Number(77),\n      stooge: true,\n      hobbies: [\"acting\"],\n      film: {\n        name: \"Sing a Song of Six Pants\",\n        release: new Date(1947, 9, 30),\n        stars: [new String(\"Larry Fine\"), \"Shemp Howard\"],\n        minutes: new Number(16),\n        seconds: 54\n      }\n    };\n\n    // <B> contains equivalent nested objects and arrays.\n    b = {\n      name: new String(\"Moe Howard\"),\n      age: new Number(77),\n      stooge: true,\n      hobbies: [\"acting\"],\n      film: {\n        name: \"Sing a Song of Six Pants\",\n        release: new Date(1947, 9, 30),\n        stars: [new String(\"Larry Fine\"), \"Shemp Howard\"],\n        minutes: new Number(16),\n        seconds: 54\n      }\n    };\n    ok(_.isEqual(a, b), \"Objects with nested equivalent members are recursively compared\");\n\n    // Instances.\n    ok(_.isEqual(new First, new First), \"Object instances are equal\");\n    ok(!_.isEqual(new First, new Second), \"Objects with different constructors and identical own properties are not equal\");\n    ok(!_.isEqual({value: 1}, new First), \"Object instances and objects sharing equivalent properties are not equal\");\n    ok(!_.isEqual({value: 2}, new Second), \"The prototype chain of objects should not be examined\");\n\n    // Circular Arrays.\n    (a = []).push(a);\n    (b = []).push(b);\n    ok(_.isEqual(a, b), \"Arrays containing circular references are equal\");\n    a.push(new String(\"Larry\"));\n    b.push(new String(\"Larry\"));\n    ok(_.isEqual(a, b), \"Arrays containing circular references and equivalent properties are equal\");\n    a.push(\"Shemp\");\n    b.push(\"Curly\");\n    ok(!_.isEqual(a, b), \"Arrays containing circular references and different properties are not equal\");\n\n    // More circular arrays #767.\n    a = [\"everything is checked but\", \"this\", \"is not\"];\n    a[1] = a;\n    b = [\"everything is checked but\", [\"this\", \"array\"], \"is not\"];\n    ok(!_.isEqual(a, b), \"Comparison of circular references with non-circular references are not equal\");\n\n    // Circular Objects.\n    a = {abc: null};\n    b = {abc: null};\n    a.abc = a;\n    b.abc = b;\n    ok(_.isEqual(a, b), \"Objects containing circular references are equal\");\n    a.def = 75;\n    b.def = 75;\n    ok(_.isEqual(a, b), \"Objects containing circular references and equivalent properties are equal\");\n    a.def = new Number(75);\n    b.def = new Number(63);\n    ok(!_.isEqual(a, b), \"Objects containing circular references and different properties are not equal\");\n\n    // More circular objects #767.\n    a = {everything: \"is checked\", but: \"this\", is: \"not\"};\n    a.but = a;\n    b = {everything: \"is checked\", but: {that:\"object\"}, is: \"not\"};\n    ok(!_.isEqual(a, b), \"Comparison of circular references with non-circular object references are not equal\");\n\n    // Cyclic Structures.\n    a = [{abc: null}];\n    b = [{abc: null}];\n    (a[0].abc = a).push(a);\n    (b[0].abc = b).push(b);\n    ok(_.isEqual(a, b), \"Cyclic structures are equal\");\n    a[0].def = \"Larry\";\n    b[0].def = \"Larry\";\n    ok(_.isEqual(a, b), \"Cyclic structures containing equivalent properties are equal\");\n    a[0].def = new String(\"Larry\");\n    b[0].def = new String(\"Curly\");\n    ok(!_.isEqual(a, b), \"Cyclic structures containing different properties are not equal\");\n\n    // Complex Circular References.\n    a = {foo: {b: {foo: {c: {foo: null}}}}};\n    b = {foo: {b: {foo: {c: {foo: null}}}}};\n    a.foo.b.foo.c.foo = a;\n    b.foo.b.foo.c.foo = b;\n    ok(_.isEqual(a, b), \"Cyclic structures with nested and identically-named properties are equal\");\n\n    // Chaining.\n    ok(!_.isEqual(_({x: 1, y: undefined}).chain(), _({x: 1, z: 2}).chain()), 'Chained objects containing different values are not equal');\n\n    a = _({x: 1, y: 2}).chain();\n    b = _({x: 1, y: 2}).chain();\n    equal(_.isEqual(a.isEqual(b), _(true)), true, '<isEqual> can be chained');\n\n    // TEST: ???\n    return;\n\n    // Objects from another frame.\n    ok(_.isEqual({}, iObject));\n  });\n        `)\n\t})\n}\n\n// isEmpty.\nfunc Test_underscore_objects_11(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"isEmpty\", function() {\n    ok(!_([1]).isEmpty(), '[1] is not empty');\n    ok(_.isEmpty([]), '[] is empty');\n    ok(!_.isEmpty({one : 1}), '{one : 1} is not empty');\n    ok(_.isEmpty({}), '{} is empty');\n    ok(_.isEmpty(new RegExp('')), 'objects with prototype properties are empty');\n    ok(_.isEmpty(null), 'null is empty');\n    ok(_.isEmpty(), 'undefined is empty');\n    ok(_.isEmpty(''), 'the empty string is empty');\n    ok(!_.isEmpty('moe'), 'but other strings are not');\n\n    var obj = {one : 1};\n    delete obj.one;\n    ok(_.isEmpty(obj), 'deleting all the keys from an object empties it');\n  });\n        `)\n\t})\n}\n\n// isElement.\nfunc Test_underscore_objects_12(t *testing.T) {\n\t// TEST: ReferenceError: $ is not defined\n\tif true {\n\t\treturn\n\t}\n\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"isElement\", function() {\n    ok(!_.isElement('div'), 'strings are not dom elements');\n    ok(_.isElement($('html')[0]), 'the html tag is a DOM element');\n    ok(_.isElement(iElement), 'even from another frame');\n  });\n        `)\n\t})\n}\n\n// isArguments.\nfunc Test_underscore_objects_13(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"isArguments\", function() {\n    var args = (function(){ return arguments; })(1, 2, 3);\n    ok(!_.isArguments('string'), 'a string is not an arguments object');\n    ok(!_.isArguments(_.isArguments), 'a function is not an arguments object');\n    ok(_.isArguments(args), 'but the arguments object is an arguments object');\n    ok(!_.isArguments(_.toArray(args)), 'but not when it\\'s converted into an array');\n    ok(!_.isArguments([1,2,3]), 'and not vanilla arrays.');\n\n    // TEST: ReferenceError: iArguments is not defined\n    return;\n    ok(_.isArguments(iArguments), 'even from another frame');\n  });\n        `)\n\t})\n}\n\n// isObject.\nfunc Test_underscore_objects_14(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"isObject\", function() {\n    ok(_.isObject(arguments), 'the arguments object is object');\n    ok(_.isObject([1, 2, 3]), 'and arrays');\n    // TEST: ReferenceError: $ is not defined\n    return;\n    ok(_.isObject($('html')[0]), 'and DOM element');\n    ok(_.isObject(iElement), 'even from another frame');\n    ok(_.isObject(function () {}), 'and functions');\n    ok(_.isObject(iFunction), 'even from another frame');\n    ok(!_.isObject(null), 'but not null');\n    ok(!_.isObject(undefined), 'and not undefined');\n    ok(!_.isObject('string'), 'and not string');\n    ok(!_.isObject(12), 'and not number');\n    ok(!_.isObject(true), 'and not boolean');\n    ok(_.isObject(new String('string')), 'but new String()');\n  });\n        `)\n\t})\n}\n\n// isArray.\nfunc Test_underscore_objects_15(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"isArray\", function() {\n    ok(!_.isArray(arguments), 'the arguments object is not an array');\n    ok(_.isArray([1, 2, 3]), 'but arrays are');\n    // TEST: ???\n    return;\n    ok(_.isArray(iArray), 'even from another frame');\n  });\n        `)\n\t})\n}\n\n// isString.\nfunc Test_underscore_objects_16(t *testing.T) {\n\t// TEST: ReferenceError: document is not defined\n\tif true {\n\t\treturn\n\t}\n\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"isString\", function() {\n    ok(!_.isString(document.body), 'the document body is not a string');\n    ok(_.isString([1, 2, 3].join(', ')), 'but strings are');\n    // TEST: ???\n    return;\n    ok(_.isString(iString), 'even from another frame');\n  });\n        `)\n\t})\n}\n\n// isNumber.\nfunc Test_underscore_objects_17(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"isNumber\", function() {\n    ok(!_.isNumber('string'), 'a string is not a number');\n    ok(!_.isNumber(arguments), 'the arguments object is not a number');\n    ok(!_.isNumber(undefined), 'undefined is not a number');\n    ok(_.isNumber(3 * 4 - 7 / 10), 'but numbers are');\n    ok(_.isNumber(NaN), 'NaN *is* a number');\n    ok(_.isNumber(Infinity), 'Infinity is a number');\n    // TEST: ???\n    return;\n    ok(_.isNumber(iNumber), 'even from another frame');\n    ok(!_.isNumber('1'), 'numeric strings are not numbers');\n  });\n        `)\n\t})\n}\n\n// isBoolean.\nfunc Test_underscore_objects_18(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"isBoolean\", function() {\n    ok(!_.isBoolean(2), 'a number is not a boolean');\n    ok(!_.isBoolean(\"string\"), 'a string is not a boolean');\n    ok(!_.isBoolean(\"false\"), 'the string \"false\" is not a boolean');\n    ok(!_.isBoolean(\"true\"), 'the string \"true\" is not a boolean');\n    ok(!_.isBoolean(arguments), 'the arguments object is not a boolean');\n    ok(!_.isBoolean(undefined), 'undefined is not a boolean');\n    ok(!_.isBoolean(NaN), 'NaN is not a boolean');\n    ok(!_.isBoolean(null), 'null is not a boolean');\n    ok(_.isBoolean(true), 'but true is');\n    ok(_.isBoolean(false), 'and so is false');\n    // TEST: ???\n    return;\n    ok(_.isBoolean(iBoolean), 'even from another frame');\n  });\n        `)\n\t})\n}\n\n// isFunction.\nfunc Test_underscore_objects_19(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"isFunction\", function() {\n    ok(!_.isFunction([1, 2, 3]), 'arrays are not functions');\n    ok(!_.isFunction('moe'), 'strings are not functions');\n    ok(_.isFunction(_.isFunction), 'but functions are');\n    // TEST: ???\n    return;\n    ok(_.isFunction(iFunction), 'even from another frame');\n  });\n        `)\n\t})\n}\n\n// isDate.\nfunc Test_underscore_objects_20(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"isDate\", function() {\n    ok(!_.isDate(100), 'numbers are not dates');\n    ok(!_.isDate({}), 'objects are not dates');\n    ok(_.isDate(new Date()), 'but dates are');\n    // TEST: ???\n    return;\n    ok(_.isDate(iDate), 'even from another frame');\n  });\n        `)\n\t})\n}\n\n// isRegExp.\nfunc Test_underscore_objects_21(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"isRegExp\", function() {\n    ok(!_.isRegExp(_.identity), 'functions are not RegExps');\n    ok(_.isRegExp(/identity/), 'but RegExps are');\n    // TEST: ???\n    return;\n    ok(_.isRegExp(iRegExp), 'even from another frame');\n  });\n        `)\n\t})\n}\n\n// isFinite.\nfunc Test_underscore_objects_22(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"isFinite\", function() {\n    ok(!_.isFinite(undefined), 'undefined is not Finite');\n    ok(!_.isFinite(null), 'null is not Finite');\n    ok(!_.isFinite(NaN), 'NaN is not Finite');\n    ok(!_.isFinite(Infinity), 'Infinity is not Finite');\n    ok(!_.isFinite(-Infinity), '-Infinity is not Finite');\n    ok(_.isFinite('12'), 'Numeric strings are numbers');\n    ok(!_.isFinite('1a'), 'Non numeric strings are not numbers');\n    ok(!_.isFinite(''), 'Empty strings are not numbers');\n    var obj = new Number(5);\n    ok(_.isFinite(obj), 'Number instances can be finite');\n    ok(_.isFinite(0), '0 is Finite');\n    ok(_.isFinite(123), 'Ints are Finite');\n    ok(_.isFinite(-12.44), 'Floats are Finite');\n  });\n        `)\n\t})\n}\n\n// isNaN.\nfunc Test_underscore_objects_23(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"isNaN\", function() {\n    ok(!_.isNaN(undefined), 'undefined is not NaN');\n    ok(!_.isNaN(null), 'null is not NaN');\n    ok(!_.isNaN(0), '0 is not NaN');\n    ok(_.isNaN(NaN), 'but NaN is');\n    // TEST: ???\n    return;\n    ok(_.isNaN(iNaN), 'even from another frame');\n    ok(_.isNaN(new Number(NaN)), 'wrapped NaN is still NaN');\n  });\n        `)\n\t})\n}\n\n// isNull.\nfunc Test_underscore_objects_24(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"isNull\", function() {\n    ok(!_.isNull(undefined), 'undefined is not null');\n    ok(!_.isNull(NaN), 'NaN is not null');\n    ok(_.isNull(null), 'but null is');\n    // TEST: ???\n    return;\n    ok(_.isNull(iNull), 'even from another frame');\n  });\n        `)\n\t})\n}\n\n// isUndefined.\nfunc Test_underscore_objects_25(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"isUndefined\", function() {\n    ok(!_.isUndefined(1), 'numbers are defined');\n    ok(!_.isUndefined(null), 'null is defined');\n    ok(!_.isUndefined(false), 'false is defined');\n    ok(!_.isUndefined(NaN), 'NaN is defined');\n    ok(_.isUndefined(), 'nothing is undefined');\n    ok(_.isUndefined(undefined), 'undefined is undefined');\n    // TEST: ???\n    return;\n    ok(_.isUndefined(iUndefined), 'even from another frame');\n  });\n        `)\n\t})\n}\n\n// tap.\nfunc Test_underscore_objects_26(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"tap\", function() {\n    var intercepted = null;\n    var interceptor = function(obj) { intercepted = obj; };\n    var returned = _.tap(1, interceptor);\n    equal(intercepted, 1, \"passes tapped object to interceptor\");\n    equal(returned, 1, \"returns tapped object\");\n\n    returned = _([1,2,3]).chain().\n      map(function(n){ return n * 2; }).\n      max().\n      tap(interceptor).\n      value();\n    ok(returned == 6 && intercepted == 6, 'can use tapped objects in a chain');\n  });\n        `)\n\t})\n}\n\n// has.\nfunc Test_underscore_objects_27(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"has\", function () {\n     var obj = {foo: \"bar\", func: function () {} };\n     ok (_.has(obj, \"foo\"), \"has() checks that the object has a property.\");\n     ok (_.has(obj, \"baz\") == false, \"has() returns false if the object doesn't have the property.\");\n     ok (_.has(obj, \"func\"), \"has() works for functions too.\");\n     obj.hasOwnProperty = null;\n     ok (_.has(obj, \"foo\"), \"has() works even when the hasOwnProperty method is deleted.\");\n     var child = {};\n     child.prototype = obj;\n     ok (_.has(child, \"foo\") == false, \"has() does not check the prototype chain for a property.\")\n  });\n        `)\n\t})\n}\n"
  },
  {
    "path": "underscore_test.go",
    "content": "package otto\n\nimport (\n\t\"sync\"\n\t\"testing\"\n\n\t\"github.com/robertkrimen/otto/terst\"\n\t\"github.com/robertkrimen/otto/underscore\"\n)\n\nfunc init() {\n\tunderscore.Disable()\n}\n\nvar (\n\t// A persistent handle for the underscore tester\n\t// We do not run underscore tests in parallel, so it is okay to stash globally.\n\ttester *_tester\n\tonce   sync.Once\n)\n\n// A tester for underscore: underscoreTest => test(underscore) :).\nfunc underscoreTest() func(string, ...interface{}) Value {\n\tsetTester := func() {\n\t\ttester = newTester()\n\t\ttester.underscore() // Load underscore and testing shim, etc.\n\t}\n\tonce.Do(setTester)\n\n\treturn tester.test\n}\n\nfunc (te *_tester) underscore() {\n\tvm := te.vm\n\t_, err := vm.Run(underscore.Source())\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\terr = vm.Set(\"assert\", func(call FunctionCall) Value {\n\t\tif !call.Argument(0).bool() {\n\t\t\tmessage := \"Assertion failed\"\n\t\t\tif len(call.ArgumentList) > 1 {\n\t\t\t\tmessage = call.ArgumentList[1].string()\n\t\t\t}\n\t\t\tt := terst.Caller().T()\n\t\t\tis(message, nil)\n\t\t\tt.Fail()\n\t\t\treturn falseValue\n\t\t}\n\t\treturn trueValue\n\t})\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\t_, err = vm.Run(`\n        var templateSettings;\n\n        function _setup() {\n            templateSettings = _.clone(_.templateSettings);\n        }\n\n        function _teardown() {\n            _.templateSettings = templateSettings;\n        }\n\n        function module() {\n            /* Nothing happens. */\n        }\n    \n        function equals(a, b, emit) {\n            assert(a == b, emit + \", <\" + a + \"> != <\" + b + \">\");\n        }\n        var equal = equals;\n\n        function notStrictEqual(a, b, emit) {\n            assert(a !== b, emit);\n        }\n\n        function strictEqual(a, b, emit) {\n            assert(a === b, emit);\n        }\n\n        function ok(a, emit) {\n            assert(a, emit);\n        }\n\n        function raises(fn, want, emit) {\n            var have, _ok = false;\n            if (typeof want === \"string\") {\n                emit = want;\n                want = null;\n            }\n            \n            try {\n                fn();\n            } catch(tmp) {\n                have = tmp;\n            }\n            \n            if (have) {\n                if (!want) {\n                    _ok = true;\n                }\n                else if (want instanceof RegExp) {\n                    _ok = want.test(have);\n                }\n                else if (have instanceof want) {\n                    _ok = true\n                }\n                else if (want.call({}, have) === true) {\n                    _ok = true;\n                }\n            }\n            \n            ok(_ok, emit);\n        }\n\n        function test(name){\n            _setup()\n            try {\n                templateSettings = _.clone(_.templateSettings);\n                if (arguments.length == 3) {\n                    count = 0\n                    for (count = 0; count < arguments[1]; count++) {\n                        arguments[2]()\n                    }\n                } else {\n                    // For now.\n                    arguments[1]()\n                }\n            }\n            finally {\n                _teardown()\n            }\n        }\n\n        function deepEqual(a, b, emit) {\n            // Also, for now.\n            assert(_.isEqual(a, b), emit)\n        }\n    `)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n}\n\nfunc Test_underscore(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n            _.map([1, 2, 3], function(value){\n                return value + 1\n            })\n        `, \"2,3,4\")\n\n\t\ttest(`\n            abc = _.find([1, 2, 3, -1], function(value) { return value == -1 })\n        `, -1)\n\n\t\ttest(`_.isEqual(1, 1)`, true)\n\t\ttest(`_.isEqual([], [])`, true)\n\t\ttest(`_.isEqual(['b', 'd'], ['b', 'd'])`, true)\n\t\ttest(`_.isEqual(['b', 'd', 'c'], ['b', 'd', 'e'])`, false)\n\t\ttest(`_.isFunction(function(){})`, true)\n\t\ttest(`_.template('<p>\\u2028<%= \"\\\\u2028\\\\u2029\" %>\\u2029</p>')()`, \"<p>\\u2028\\u2028\\u2029\\u2029</p>\")\n\t})\n}\n\n// TODO Test: typeof An argument reference\n// TODO Test: abc = {}; abc == Object(abc)\n"
  },
  {
    "path": "underscore_utility_test.go",
    "content": "package otto\n\nimport (\n\t\"testing\"\n)\n\n// #750 - Return _ instance.\nfunc Test_underscore_utility_0(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"#750 - Return _ instance.\", 2, function() {\n    var instance = _([]);\n    ok(_(instance) === instance);\n    ok(new _(instance) === instance);\n  });\n        `)\n\t})\n}\n\n// identity.\nfunc Test_underscore_utility_1(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"identity\", function() {\n    var moe = {name : 'moe'};\n    equal(_.identity(moe), moe, 'moe is the same as his identity');\n  });\n        `)\n\t})\n}\n\n// random.\nfunc Test_underscore_utility_2(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"random\", function() {\n    var array = _.range(1000);\n    var min = Math.pow(2, 31);\n    var max = Math.pow(2, 62);\n\n    ok(_.every(array, function() {\n      return _.random(min, max) >= min;\n    }), \"should produce a random number greater than or equal to the minimum number\");\n\n    ok(_.some(array, function() {\n      return _.random(Number.MAX_VALUE) > 0;\n    }), \"should produce a random number when passed <Number.MAX_VALUE>\");\n  });\n        `)\n\t})\n}\n\n// uniqueId.\nfunc Test_underscore_utility_3(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"uniqueId\", function() {\n    var ids = [], i = 0;\n    while(i++ < 100) ids.push(_.uniqueId());\n    equal(_.uniq(ids).length, ids.length, 'can generate a globally-unique stream of ids');\n  });\n        `)\n\t})\n}\n\n// times.\nfunc Test_underscore_utility_4(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"times\", function() {\n    var vals = [];\n    _.times(3, function (i) { vals.push(i); });\n    ok(_.isEqual(vals, [0,1,2]), \"is 0 indexed\");\n    //\n    vals = [];\n    _(3).times(function(i) { vals.push(i); });\n    ok(_.isEqual(vals, [0,1,2]), \"works as a wrapper\");\n    // collects return values\n    ok(_.isEqual([0, 1, 2], _.times(3, function(i) { return i; })), \"collects return values\");\n  });\n        `)\n\t})\n}\n\n// mixin.\nfunc Test_underscore_utility_5(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"mixin\", function() {\n    _.mixin({\n      myReverse: function(string) {\n        return string.split('').reverse().join('');\n      }\n    });\n    equal(_.myReverse('panacea'), 'aecanap', 'mixed in a function to _');\n    equal(_('champ').myReverse(), 'pmahc', 'mixed in a function to the OOP wrapper');\n  });\n        `)\n\t})\n}\n\n// _.escape.\nfunc Test_underscore_utility_6(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"_.escape\", function() {\n    equal(_.escape(\"Curly & Moe\"), \"Curly &amp; Moe\");\n    equal(_.escape(\"Curly &amp; Moe\"), \"Curly &amp;amp; Moe\");\n    equal(_.escape(null), '');\n  });\n        `)\n\t})\n}\n\n// _.unescape.\nfunc Test_underscore_utility_7(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"_.unescape\", function() {\n    var string = \"Curly & Moe\";\n    equal(_.unescape(\"Curly &amp; Moe\"), string);\n    equal(_.unescape(\"Curly &amp;amp; Moe\"), \"Curly &amp; Moe\");\n    equal(_.unescape(null), '');\n    equal(_.unescape(_.escape(string)), string);\n  });\n        `)\n\t})\n}\n\n// template.\nfunc Test_underscore_utility_8(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test(\"template\", function() {\n    var basicTemplate = _.template(\"<%= thing %> is gettin' on my noives!\");\n    var result = basicTemplate({thing : 'This'});\n    equal(result, \"This is gettin' on my noives!\", 'can do basic attribute interpolation');\n\n    var sansSemicolonTemplate = _.template(\"A <% this %> B\");\n    equal(sansSemicolonTemplate(), \"A  B\");\n\n    var backslashTemplate = _.template(\"<%= thing %> is \\\\ridanculous\");\n    equal(backslashTemplate({thing: 'This'}), \"This is \\\\ridanculous\");\n\n    var escapeTemplate = _.template('<%= a ? \"checked=\\\\\"checked\\\\\"\" : \"\" %>');\n    equal(escapeTemplate({a: true}), 'checked=\"checked\"', 'can handle slash escapes in interpolations.');\n\n    var fancyTemplate = _.template(\"<ul><% \\\n      for (var key in people) { \\\n    %><li><%= people[key] %></li><% } %></ul>\");\n    result = fancyTemplate({people : {moe : \"Moe\", larry : \"Larry\", curly : \"Curly\"}});\n    equal(result, \"<ul><li>Moe</li><li>Larry</li><li>Curly</li></ul>\", 'can run arbitrary javascript in templates');\n\n    var escapedCharsInJavascriptTemplate = _.template(\"<ul><% _.each(numbers.split('\\\\n'), function(item) { %><li><%= item %></li><% }) %></ul>\");\n    result = escapedCharsInJavascriptTemplate({numbers: \"one\\ntwo\\nthree\\nfour\"});\n    equal(result, \"<ul><li>one</li><li>two</li><li>three</li><li>four</li></ul>\", 'Can use escaped characters (e.g. \\\\n) in Javascript');\n\n    var namespaceCollisionTemplate = _.template(\"<%= pageCount %> <%= thumbnails[pageCount] %> <% _.each(thumbnails, function(p) { %><div class=\\\"thumbnail\\\" rel=\\\"<%= p %>\\\"></div><% }); %>\");\n    result = namespaceCollisionTemplate({\n      pageCount: 3,\n      thumbnails: {\n        1: \"p1-thumbnail.gif\",\n        2: \"p2-thumbnail.gif\",\n        3: \"p3-thumbnail.gif\"\n      }\n    });\n    equal(result, \"3 p3-thumbnail.gif <div class=\\\"thumbnail\\\" rel=\\\"p1-thumbnail.gif\\\"></div><div class=\\\"thumbnail\\\" rel=\\\"p2-thumbnail.gif\\\"></div><div class=\\\"thumbnail\\\" rel=\\\"p3-thumbnail.gif\\\"></div>\");\n\n    var noInterpolateTemplate = _.template(\"<div><p>Just some text. Hey, I know this is silly but it aids consistency.</p></div>\");\n    result = noInterpolateTemplate();\n    equal(result, \"<div><p>Just some text. Hey, I know this is silly but it aids consistency.</p></div>\");\n\n    var quoteTemplate = _.template(\"It's its, not it's\");\n    equal(quoteTemplate({}), \"It's its, not it's\");\n\n    var quoteInStatementAndBody = _.template(\"<%\\\n      if(foo == 'bar'){ \\\n    %>Statement quotes and 'quotes'.<% } %>\");\n    equal(quoteInStatementAndBody({foo: \"bar\"}), \"Statement quotes and 'quotes'.\");\n\n    var withNewlinesAndTabs = _.template('This\\n\\t\\tis: <%= x %>.\\n\\tok.\\nend.');\n    equal(withNewlinesAndTabs({x: 'that'}), 'This\\n\\t\\tis: that.\\n\\tok.\\nend.');\n\n    var template = _.template(\"<i><%- value %></i>\");\n    var result = template({value: \"<script>\"});\n    equal(result, '<i>&lt;script&gt;</i>');\n\n    var stooge = {\n      name: \"Moe\",\n      template: _.template(\"I'm <%= this.name %>\")\n    };\n    equal(stooge.template(), \"I'm Moe\");\n\n    // TEST: ReferenceError: $ is not defined\n    if (false) {\n        if (!$.browser.msie) {\n        var fromHTML = _.template($('#template').html());\n        equal(fromHTML({data : 12345}).replace(/\\s/g, ''), '<li>24690</li>');\n        }\n    }\n\n    _.templateSettings = {\n      evaluate    : /\\{\\{([\\s\\S]+?)\\}\\}/g,\n      interpolate : /\\{\\{=([\\s\\S]+?)\\}\\}/g\n    };\n\n    var custom = _.template(\"<ul>{{ for (var key in people) { }}<li>{{= people[key] }}</li>{{ } }}</ul>\");\n    result = custom({people : {moe : \"Moe\", larry : \"Larry\", curly : \"Curly\"}});\n    equal(result, \"<ul><li>Moe</li><li>Larry</li><li>Curly</li></ul>\", 'can run arbitrary javascript in templates');\n\n    var customQuote = _.template(\"It's its, not it's\");\n    equal(customQuote({}), \"It's its, not it's\");\n\n    var quoteInStatementAndBody = _.template(\"{{ if(foo == 'bar'){ }}Statement quotes and 'quotes'.{{ } }}\");\n    equal(quoteInStatementAndBody({foo: \"bar\"}), \"Statement quotes and 'quotes'.\");\n\n    _.templateSettings = {\n      evaluate    : /<\\?([\\s\\S]+?)\\?>/g,\n      interpolate : /<\\?=([\\s\\S]+?)\\?>/g\n    };\n\n    var customWithSpecialChars = _.template(\"<ul><? for (var key in people) { ?><li><?= people[key] ?></li><? } ?></ul>\");\n    result = customWithSpecialChars({people : {moe : \"Moe\", larry : \"Larry\", curly : \"Curly\"}});\n    equal(result, \"<ul><li>Moe</li><li>Larry</li><li>Curly</li></ul>\", 'can run arbitrary javascript in templates');\n\n    var customWithSpecialCharsQuote = _.template(\"It's its, not it's\");\n    equal(customWithSpecialCharsQuote({}), \"It's its, not it's\");\n\n    var quoteInStatementAndBody = _.template(\"<? if(foo == 'bar'){ ?>Statement quotes and 'quotes'.<? } ?>\");\n    equal(quoteInStatementAndBody({foo: \"bar\"}), \"Statement quotes and 'quotes'.\");\n\n    _.templateSettings = {\n      interpolate : /\\{\\{(.+?)\\}\\}/g\n    };\n\n    var mustache = _.template(\"Hello {{planet}}!\");\n    equal(mustache({planet : \"World\"}), \"Hello World!\", \"can mimic mustache.js\");\n\n    var templateWithNull = _.template(\"a null undefined {{planet}}\");\n    equal(templateWithNull({planet : \"world\"}), \"a null undefined world\", \"can handle missing escape and evaluate settings\");\n  });\n        `)\n\t})\n}\n\n// _.template provides the generated function source, when a SyntaxError occurs.\nfunc Test_underscore_utility_9(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test('_.template provides the generated function source, when a SyntaxError occurs', function() {\n    try {\n      _.template('<b><%= if x %></b>');\n    } catch (ex) {\n      var source = ex.source;\n    }\n    ok(/__p/.test(source));\n  });\n        `)\n\t})\n}\n\n// _.template handles \\\\u2028 & \\\\u2029.\nfunc Test_underscore_utility_10(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test('_.template handles \\\\u2028 & \\\\u2029', function() {\n    var tmpl = _.template('<p>\\u2028<%= \"\\\\u2028\\\\u2029\" %>\\u2029</p>');\n    strictEqual(tmpl(), '<p>\\u2028\\u2028\\u2029\\u2029</p>');\n  });\n        `)\n\t})\n}\n\n// result calls functions and returns primitives.\nfunc Test_underscore_utility_11(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test('result calls functions and returns primitives', function() {\n    var obj = {w: '', x: 'x', y: function(){ return this.x; }};\n    strictEqual(_.result(obj, 'w'), '');\n    strictEqual(_.result(obj, 'x'), 'x');\n    strictEqual(_.result(obj, 'y'), 'x');\n    strictEqual(_.result(obj, 'z'), undefined);\n    strictEqual(_.result(null, 'x'), undefined);\n  });\n        `)\n\t})\n}\n\n// _.templateSettings.variable.\nfunc Test_underscore_utility_12(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test('_.templateSettings.variable', function() {\n    var s = '<%=data.x%>';\n    var data = {x: 'x'};\n    strictEqual(_.template(s, {variable: 'data'})(data), 'x');\n    _.templateSettings.variable = 'data';\n    strictEqual(_.template(s)(data), 'x');\n  });\n        `)\n\t})\n}\n\n// #547 - _.templateSettings is unchanged by custom settings.\nfunc Test_underscore_utility_13(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test('#547 - _.templateSettings is unchanged by custom settings.', function() {\n    ok(!_.templateSettings.variable);\n    _.template('', {}, {variable: 'x'});\n    ok(!_.templateSettings.variable);\n  });\n        `)\n\t})\n}\n\n// #556 - undefined template variables.\nfunc Test_underscore_utility_14(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test('#556 - undefined template variables.', function() {\n    var template = _.template('<%=x%>');\n    strictEqual(template({x: null}), '');\n    strictEqual(template({x: undefined}), '');\n\n    var templateEscaped = _.template('<%-x%>');\n    strictEqual(templateEscaped({x: null}), '');\n    strictEqual(templateEscaped({x: undefined}), '');\n\n    var templateWithProperty = _.template('<%=x.foo%>');\n    strictEqual(templateWithProperty({x: {} }), '');\n    strictEqual(templateWithProperty({x: {} }), '');\n\n    var templateWithPropertyEscaped = _.template('<%-x.foo%>');\n    strictEqual(templateWithPropertyEscaped({x: {} }), '');\n    strictEqual(templateWithPropertyEscaped({x: {} }), '');\n  });\n        `)\n\t})\n}\n\n// interpolate evaluates code only once.\nfunc Test_underscore_utility_15(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test('interpolate evaluates code only once.', 2, function() {\n    var count = 0;\n    var template = _.template('<%= f() %>');\n    template({f: function(){ ok(!(count++)); }});\n\n    var countEscaped = 0;\n    var templateEscaped = _.template('<%- f() %>');\n    templateEscaped({f: function(){ ok(!(countEscaped++)); }});\n  });\n        `)\n\t})\n}\n\n// #746 - _.template settings are not modified.\nfunc Test_underscore_utility_16(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test('#746 - _.template settings are not modified.', 1, function() {\n    var settings = {};\n    _.template('', null, settings);\n    deepEqual(settings, {});\n  });\n        `)\n\t})\n}\n\n// #779 - delimeters are applied to unescaped text.\nfunc Test_underscore_utility_17(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := underscoreTest()\n\n\t\ttest(`\n  test('#779 - delimeters are applied to unescaped text.', 1, function() {\n    var template = _.template('<<\\nx\\n>>', null, {evaluate: /<<(.*?)>>/g});\n    strictEqual(template(), '<<\\nx\\n>>');\n  });\n        `)\n\t})\n}\n"
  },
  {
    "path": "value.go",
    "content": "package otto\n\nimport (\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"math\"\n\t\"reflect\"\n\t\"strconv\"\n\t\"unicode/utf16\"\n)\n\ntype valueKind int\n\nconst (\n\tvalueUndefined valueKind = iota\n\tvalueNull\n\tvalueNumber\n\tvalueString\n\tvalueBoolean\n\tvalueObject\n\n\t// These are invalid outside of the runtime.\n\tvalueEmpty\n\tvalueResult\n\tvalueReference\n)\n\n// Value is the representation of a JavaScript value.\ntype Value struct {\n\tvalue interface{}\n\tkind  valueKind\n}\n\nfunc (v Value) safe() bool {\n\treturn v.kind < valueEmpty\n}\n\nvar (\n\temptyValue = Value{kind: valueEmpty}\n\tnullValue  = Value{kind: valueNull}\n\tfalseValue = Value{kind: valueBoolean, value: false}\n\ttrueValue  = Value{kind: valueBoolean, value: true}\n)\n\n// ToValue will convert an interface{} value to a value digestible by otto/JavaScript\n//\n// This function will not work for advanced types (struct, map, slice/array, etc.) and\n// you should use Otto.ToValue instead.\nfunc ToValue(value interface{}) (Value, error) {\n\tresult := Value{}\n\terr := catchPanic(func() {\n\t\tresult = toValue(value)\n\t})\n\treturn result, err\n}\n\nfunc (v Value) isEmpty() bool {\n\treturn v.kind == valueEmpty\n}\n\n// Undefined\n\n// UndefinedValue will return a Value representing undefined.\nfunc UndefinedValue() Value {\n\treturn Value{}\n}\n\n// IsDefined will return false if the value is undefined, and true otherwise.\nfunc (v Value) IsDefined() bool {\n\treturn v.kind != valueUndefined\n}\n\n// IsUndefined will return true if the value is undefined, and false otherwise.\nfunc (v Value) IsUndefined() bool {\n\treturn v.kind == valueUndefined\n}\n\n// NullValue will return a Value representing null.\nfunc NullValue() Value {\n\treturn Value{kind: valueNull}\n}\n\n// IsNull will return true if the value is null, and false otherwise.\nfunc (v Value) IsNull() bool {\n\treturn v.kind == valueNull\n}\n\n// ---\n\nfunc (v Value) isCallable() bool {\n\to, ok := v.value.(*object)\n\treturn ok && o.isCall()\n}\n\n// Call the value as a function with the given this value and argument list and\n// return the result of invocation. It is essentially equivalent to:\n//\n//\tvalue.apply(thisValue, argumentList)\n//\n// An undefined value and an error will result if:\n//\n//  1. There is an error during conversion of the argument list\n//  2. The value is not actually a function\n//  3. An (uncaught) exception is thrown\nfunc (v Value) Call(this Value, argumentList ...interface{}) (Value, error) {\n\tresult := Value{}\n\terr := catchPanic(func() {\n\t\t// FIXME\n\t\tresult = v.call(nil, this, argumentList...)\n\t})\n\tif !v.safe() {\n\t\tv = Value{}\n\t}\n\treturn result, err\n}\n\nfunc (v Value) call(rt *runtime, this Value, argumentList ...interface{}) Value {\n\tif function, ok := v.value.(*object); ok {\n\t\treturn function.call(this, function.runtime.toValueArray(argumentList...), false, nativeFrame)\n\t}\n\tpanic(rt.panicTypeError(\"call %q is not an object\", v.value))\n}\n\nfunc (v Value) constructSafe(rt *runtime, this Value, argumentList ...interface{}) (Value, error) {\n\tresult := Value{}\n\terr := catchPanic(func() {\n\t\tresult = v.construct(rt, this, argumentList...)\n\t})\n\treturn result, err\n}\n\nfunc (v Value) construct(rt *runtime, this Value, argumentList ...interface{}) Value { //nolint:unparam\n\tif fn, ok := v.value.(*object); ok {\n\t\treturn fn.construct(fn.runtime.toValueArray(argumentList...))\n\t}\n\tpanic(rt.panicTypeError(\"construct %q is not an object\", v.value))\n}\n\n// IsPrimitive will return true if value is a primitive (any kind of primitive).\nfunc (v Value) IsPrimitive() bool {\n\treturn !v.IsObject()\n}\n\n// IsBoolean will return true if value is a boolean (primitive).\nfunc (v Value) IsBoolean() bool {\n\treturn v.kind == valueBoolean\n}\n\n// IsNumber will return true if value is a number (primitive).\nfunc (v Value) IsNumber() bool {\n\treturn v.kind == valueNumber\n}\n\n// IsNaN will return true if value is NaN (or would convert to NaN).\nfunc (v Value) IsNaN() bool {\n\tswitch value := v.value.(type) {\n\tcase float64:\n\t\treturn math.IsNaN(value)\n\tcase float32:\n\t\treturn math.IsNaN(float64(value))\n\tcase int, int8, int32, int64:\n\t\treturn false\n\tcase uint, uint8, uint32, uint64:\n\t\treturn false\n\t}\n\n\treturn math.IsNaN(v.float64())\n}\n\n// IsString will return true if value is a string (primitive).\nfunc (v Value) IsString() bool {\n\treturn v.kind == valueString\n}\n\n// IsObject will return true if value is an object.\nfunc (v Value) IsObject() bool {\n\treturn v.kind == valueObject\n}\n\n// IsFunction will return true if value is a function.\nfunc (v Value) IsFunction() bool {\n\tif v.kind != valueObject {\n\t\treturn false\n\t}\n\treturn v.value.(*object).class == classFunctionName\n}\n\n// Class will return the class string of the value or the empty string if value is not an object.\n//\n// The return value will (generally) be one of:\n//\n//\tObject\n//\tFunction\n//\tArray\n//\tString\n//\tNumber\n//\tBoolean\n//\tDate\n//\tRegExp\nfunc (v Value) Class() string {\n\tif v.kind != valueObject {\n\t\treturn \"\"\n\t}\n\treturn v.value.(*object).class\n}\n\nfunc (v Value) isArray() bool { //nolint:unused\n\tif v.kind != valueObject {\n\t\treturn false\n\t}\n\treturn isArray(v.value.(*object))\n}\n\nfunc (v Value) isStringObject() bool { //nolint:unused\n\tif v.kind != valueObject {\n\t\treturn false\n\t}\n\treturn v.value.(*object).class == classStringName\n}\n\nfunc (v Value) isBooleanObject() bool { //nolint:unused\n\tif v.kind != valueObject {\n\t\treturn false\n\t}\n\treturn v.value.(*object).class == classBooleanName\n}\n\nfunc (v Value) isNumberObject() bool { //nolint:unused\n\tif v.kind != valueObject {\n\t\treturn false\n\t}\n\treturn v.value.(*object).class == classNumberName\n}\n\nfunc (v Value) isDate() bool { //nolint:unused\n\tif v.kind != valueObject {\n\t\treturn false\n\t}\n\treturn v.value.(*object).class == classDateName\n}\n\nfunc (v Value) isRegExp() bool {\n\tif v.kind != valueObject {\n\t\treturn false\n\t}\n\treturn v.value.(*object).class == classRegExpName\n}\n\nfunc (v Value) isError() bool { //nolint:unused\n\tif v.kind != valueObject {\n\t\treturn false\n\t}\n\treturn v.value.(*object).class == classErrorName\n}\n\n// ---\n\nfunc reflectValuePanic(value interface{}, kind reflect.Kind) {\n\t// FIXME?\n\tswitch kind {\n\tcase reflect.Struct:\n\t\tpanic(newError(nil, \"TypeError\", 0, \"invalid value (struct): missing runtime: %v (%T)\", value, value))\n\tcase reflect.Map:\n\t\tpanic(newError(nil, \"TypeError\", 0, \"invalid value (map): missing runtime: %v (%T)\", value, value))\n\tcase reflect.Slice:\n\t\tpanic(newError(nil, \"TypeError\", 0, \"invalid value (slice): missing runtime: %v (%T)\", value, value))\n\t}\n}\n\nfunc toValue(value interface{}) Value {\n\tswitch value := value.(type) {\n\tcase Value:\n\t\treturn value\n\tcase bool:\n\t\treturn Value{kind: valueBoolean, value: value}\n\tcase int:\n\t\treturn Value{kind: valueNumber, value: value}\n\tcase int8:\n\t\treturn Value{kind: valueNumber, value: value}\n\tcase int16:\n\t\treturn Value{kind: valueNumber, value: value}\n\tcase int32:\n\t\treturn Value{kind: valueNumber, value: value}\n\tcase int64:\n\t\treturn Value{kind: valueNumber, value: value}\n\tcase uint:\n\t\treturn Value{kind: valueNumber, value: value}\n\tcase uint8:\n\t\treturn Value{kind: valueNumber, value: value}\n\tcase uint16:\n\t\treturn Value{kind: valueNumber, value: value}\n\tcase uint32:\n\t\treturn Value{kind: valueNumber, value: value}\n\tcase uint64:\n\t\treturn Value{kind: valueNumber, value: value}\n\tcase float32:\n\t\treturn Value{kind: valueNumber, value: float64(value)}\n\tcase float64:\n\t\treturn Value{kind: valueNumber, value: value}\n\tcase []uint16:\n\t\treturn Value{kind: valueString, value: value}\n\tcase string:\n\t\treturn Value{kind: valueString, value: value}\n\t// A rune is actually an int32, which is handled above\n\tcase *object:\n\t\treturn Value{kind: valueObject, value: value}\n\tcase *Object:\n\t\treturn Value{kind: valueObject, value: value.object}\n\tcase Object:\n\t\treturn Value{kind: valueObject, value: value.object}\n\tcase referencer: // reference is an interface (already a pointer)\n\t\treturn Value{kind: valueReference, value: value}\n\tcase result:\n\t\treturn Value{kind: valueResult, value: value}\n\tcase nil:\n\t\t// TODO Ugh.\n\t\treturn Value{}\n\tcase reflect.Value:\n\t\tfor value.Kind() == reflect.Ptr {\n\t\t\t// We were given a pointer, so we'll drill down until we get a non-pointer\n\t\t\t//\n\t\t\t// These semantics might change if we want to start supporting pointers to values transparently\n\t\t\t// (It would be best not to depend on this behavior)\n\t\t\t// FIXME: UNDEFINED\n\t\t\tif value.IsNil() {\n\t\t\t\treturn Value{}\n\t\t\t}\n\t\t\tvalue = value.Elem()\n\t\t}\n\t\tswitch value.Kind() {\n\t\tcase reflect.Bool:\n\t\t\treturn Value{kind: valueBoolean, value: value.Bool()}\n\t\tcase reflect.Int:\n\t\t\treturn Value{kind: valueNumber, value: int(value.Int())}\n\t\tcase reflect.Int8:\n\t\t\treturn Value{kind: valueNumber, value: int8(value.Int())}\n\t\tcase reflect.Int16:\n\t\t\treturn Value{kind: valueNumber, value: int16(value.Int())}\n\t\tcase reflect.Int32:\n\t\t\treturn Value{kind: valueNumber, value: int32(value.Int())}\n\t\tcase reflect.Int64:\n\t\t\treturn Value{kind: valueNumber, value: value.Int()}\n\t\tcase reflect.Uint:\n\t\t\treturn Value{kind: valueNumber, value: uint(value.Uint())}\n\t\tcase reflect.Uint8:\n\t\t\treturn Value{kind: valueNumber, value: uint8(value.Uint())}\n\t\tcase reflect.Uint16:\n\t\t\treturn Value{kind: valueNumber, value: uint16(value.Uint())}\n\t\tcase reflect.Uint32:\n\t\t\treturn Value{kind: valueNumber, value: uint32(value.Uint())}\n\t\tcase reflect.Uint64:\n\t\t\treturn Value{kind: valueNumber, value: value.Uint()}\n\t\tcase reflect.Float32:\n\t\t\treturn Value{kind: valueNumber, value: float32(value.Float())}\n\t\tcase reflect.Float64:\n\t\t\treturn Value{kind: valueNumber, value: value.Float()}\n\t\tcase reflect.String:\n\t\t\treturn Value{kind: valueString, value: value.String()}\n\t\tdefault:\n\t\t\treflectValuePanic(value.Interface(), value.Kind())\n\t\t}\n\tdefault:\n\t\treturn toValue(reflect.ValueOf(value))\n\t}\n\t// FIXME?\n\tpanic(newError(nil, \"TypeError\", 0, \"invalid value: %v (%T)\", value, value))\n}\n\n// String will return the value as a string.\n//\n// This method will make return the empty string if there is an error.\nfunc (v Value) String() string {\n\tvar result string\n\tcatchPanic(func() { //nolint:errcheck, gosec\n\t\tresult = v.string()\n\t})\n\treturn result\n}\n\n// ToBoolean will convert the value to a boolean (bool).\n//\n//\tToValue(0).ToBoolean() => false\n//\tToValue(\"\").ToBoolean() => false\n//\tToValue(true).ToBoolean() => true\n//\tToValue(1).ToBoolean() => true\n//\tToValue(\"Nothing happens\").ToBoolean() => true\n//\n// If there is an error during the conversion process (like an uncaught exception), then the result will be false and an error.\nfunc (v Value) ToBoolean() (bool, error) {\n\tresult := false\n\terr := catchPanic(func() {\n\t\tresult = v.bool()\n\t})\n\treturn result, err\n}\n\nfunc (v Value) numberValue() Value {\n\tif v.kind == valueNumber {\n\t\treturn v\n\t}\n\treturn Value{kind: valueNumber, value: v.float64()}\n}\n\n// ToFloat will convert the value to a number (float64).\n//\n//\tToValue(0).ToFloat() => 0.\n//\tToValue(1.1).ToFloat() => 1.1\n//\tToValue(\"11\").ToFloat() => 11.\n//\n// If there is an error during the conversion process (like an uncaught exception), then the result will be 0 and an error.\nfunc (v Value) ToFloat() (float64, error) {\n\tresult := float64(0)\n\terr := catchPanic(func() {\n\t\tresult = v.float64()\n\t})\n\treturn result, err\n}\n\n// ToInteger will convert the value to a number (int64).\n//\n//\tToValue(0).ToInteger() => 0\n//\tToValue(1.1).ToInteger() => 1\n//\tToValue(\"11\").ToInteger() => 11\n//\n// If there is an error during the conversion process (like an uncaught exception), then the result will be 0 and an error.\nfunc (v Value) ToInteger() (int64, error) {\n\tresult := int64(0)\n\terr := catchPanic(func() {\n\t\tresult = v.number().int64\n\t})\n\treturn result, err\n}\n\n// ToString will convert the value to a string (string).\n//\n//\tToValue(0).ToString() => \"0\"\n//\tToValue(false).ToString() => \"false\"\n//\tToValue(1.1).ToString() => \"1.1\"\n//\tToValue(\"11\").ToString() => \"11\"\n//\tToValue('Nothing happens.').ToString() => \"Nothing happens.\"\n//\n// If there is an error during the conversion process (like an uncaught exception), then the result will be the empty string (\"\") and an error.\nfunc (v Value) ToString() (string, error) {\n\tresult := \"\"\n\terr := catchPanic(func() {\n\t\tresult = v.string()\n\t})\n\treturn result, err\n}\n\nfunc (v Value) object() *object {\n\tif v, ok := v.value.(*object); ok {\n\t\treturn v\n\t}\n\treturn nil\n}\n\n// Object will return the object of the value, or nil if value is not an object.\n//\n// This method will not do any implicit conversion. For example, calling this method on a string primitive value will not return a String object.\nfunc (v Value) Object() *Object {\n\tif obj, ok := v.value.(*object); ok {\n\t\treturn &Object{\n\t\t\tobject: obj,\n\t\t\tvalue:  v,\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc (v Value) reference() referencer {\n\tvalue, _ := v.value.(referencer)\n\treturn value\n}\n\nfunc (v Value) resolve() Value {\n\tif value, ok := v.value.(referencer); ok {\n\t\treturn value.getValue()\n\t}\n\treturn v\n}\n\nvar (\n\tnan              float64 = math.NaN()\n\tpositiveInfinity float64 = math.Inf(+1)\n\tnegativeInfinity float64 = math.Inf(-1)\n\tpositiveZero     float64 = 0\n\tnegativeZero     float64 = math.Float64frombits(0 | (1 << 63))\n)\n\n// NaNValue will return a value representing NaN.\n//\n// It is equivalent to:\n//\n//\tToValue(math.NaN())\nfunc NaNValue() Value {\n\treturn Value{kind: valueNumber, value: nan}\n}\n\nfunc positiveInfinityValue() Value {\n\treturn Value{kind: valueNumber, value: positiveInfinity}\n}\n\nfunc negativeInfinityValue() Value {\n\treturn Value{kind: valueNumber, value: negativeInfinity}\n}\n\nfunc positiveZeroValue() Value {\n\treturn Value{kind: valueNumber, value: positiveZero}\n}\n\nfunc negativeZeroValue() Value {\n\treturn Value{kind: valueNumber, value: negativeZero}\n}\n\n// TrueValue will return a value representing true.\n//\n// It is equivalent to:\n//\n//\tToValue(true)\nfunc TrueValue() Value {\n\treturn Value{kind: valueBoolean, value: true}\n}\n\n// FalseValue will return a value representing false.\n//\n// It is equivalent to:\n//\n//\tToValue(false)\nfunc FalseValue() Value {\n\treturn Value{kind: valueBoolean, value: false}\n}\n\nfunc sameValue(x Value, y Value) bool {\n\tif x.kind != y.kind {\n\t\treturn false\n\t}\n\n\tswitch x.kind {\n\tcase valueUndefined, valueNull:\n\t\treturn true\n\tcase valueNumber:\n\t\tx := x.float64()\n\t\ty := y.float64()\n\t\tif math.IsNaN(x) && math.IsNaN(y) {\n\t\t\treturn true\n\t\t}\n\n\t\tif x == y {\n\t\t\tif x == 0 {\n\t\t\t\t// Since +0 != -0\n\t\t\t\treturn math.Signbit(x) == math.Signbit(y)\n\t\t\t}\n\t\t\treturn true\n\t\t}\n\t\treturn false\n\tcase valueString:\n\t\treturn x.string() == y.string()\n\tcase valueBoolean:\n\t\treturn x.bool() == y.bool()\n\tcase valueObject:\n\t\treturn x.object() == y.object()\n\tdefault:\n\t\tpanic(hereBeDragons())\n\t}\n}\n\nfunc strictEqualityComparison(x Value, y Value) bool {\n\tif x.kind != y.kind {\n\t\treturn false\n\t}\n\n\tswitch x.kind {\n\tcase valueUndefined, valueNull:\n\t\treturn true\n\tcase valueNumber:\n\t\tx := x.float64()\n\t\ty := y.float64()\n\t\tif math.IsNaN(x) && math.IsNaN(y) {\n\t\t\treturn false\n\t\t}\n\t\treturn x == y\n\tcase valueString:\n\t\treturn x.string() == y.string()\n\tcase valueBoolean:\n\t\treturn x.bool() == y.bool()\n\tcase valueObject:\n\t\treturn x.object() == y.object()\n\tdefault:\n\t\tpanic(hereBeDragons())\n\t}\n}\n\n// Export will attempt to convert the value to a Go representation\n// and return it via an interface{} kind.\n//\n// Export returns an error, but it will always be nil. It is present\n// for backwards compatibility.\n//\n// If a reasonable conversion is not possible, then the original\n// value is returned.\n//\n//\tundefined   -> nil (FIXME?: Should be Value{})\n//\tnull        -> nil\n//\tboolean     -> bool\n//\tnumber      -> A number type (int, float32, uint64, ...)\n//\tstring      -> string\n//\tArray       -> []interface{}\n//\tObject      -> map[string]interface{}\nfunc (v Value) Export() (interface{}, error) {\n\treturn v.export(), nil\n}\n\nfunc (v Value) export() interface{} {\n\tswitch v.kind {\n\tcase valueUndefined:\n\t\treturn nil\n\tcase valueNull:\n\t\treturn nil\n\tcase valueNumber, valueBoolean:\n\t\treturn v.value\n\tcase valueString:\n\t\tswitch value := v.value.(type) {\n\t\tcase string:\n\t\t\treturn value\n\t\tcase []uint16:\n\t\t\treturn string(utf16.Decode(value))\n\t\t}\n\tcase valueObject:\n\t\tobj := v.object()\n\t\tswitch value := obj.value.(type) {\n\t\tcase *goStructObject:\n\t\t\treturn value.value.Interface()\n\t\tcase *goMapObject:\n\t\t\treturn value.value.Interface()\n\t\tcase *goArrayObject:\n\t\t\treturn value.value.Interface()\n\t\tcase *goSliceObject:\n\t\t\treturn value.value.Interface()\n\t\t}\n\t\tif obj.class == classArrayName {\n\t\t\tresult := make([]interface{}, 0)\n\t\t\tlengthValue := obj.get(propertyLength)\n\t\t\tlength := lengthValue.value.(uint32)\n\t\t\tkind := reflect.Invalid\n\t\t\tkeyKind := reflect.Invalid\n\t\t\telemKind := reflect.Invalid\n\t\t\tstate := 0\n\t\t\tvar t reflect.Type\n\t\t\tfor index := range length {\n\t\t\t\tname := strconv.FormatInt(int64(index), 10)\n\t\t\t\tif !obj.hasProperty(name) {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tvalue := obj.get(name).export()\n\n\t\t\t\tt = reflect.TypeOf(value)\n\n\t\t\t\tvar k, kk, ek reflect.Kind\n\t\t\t\tif t != nil {\n\t\t\t\t\tk = t.Kind()\n\t\t\t\t\tswitch k {\n\t\t\t\t\tcase reflect.Map:\n\t\t\t\t\t\tkk = t.Key().Kind()\n\t\t\t\t\t\tfallthrough\n\t\t\t\t\tcase reflect.Array, reflect.Chan, reflect.Ptr, reflect.Slice:\n\t\t\t\t\t\tek = t.Elem().Kind()\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif state == 0 {\n\t\t\t\t\tkind = k\n\t\t\t\t\tkeyKind = kk\n\t\t\t\t\telemKind = ek\n\t\t\t\t\tstate = 1\n\t\t\t\t} else if state == 1 && (kind != k || keyKind != kk || elemKind != ek) {\n\t\t\t\t\tstate = 2\n\t\t\t\t}\n\n\t\t\t\tresult = append(result, value)\n\t\t\t}\n\n\t\t\tif state != 1 || kind == reflect.Interface || t == nil {\n\t\t\t\t// No common type\n\t\t\t\treturn result\n\t\t\t}\n\n\t\t\t// Convert to the common type\n\t\t\tval := reflect.MakeSlice(reflect.SliceOf(t), len(result), len(result))\n\t\t\tfor i, v := range result {\n\t\t\t\tval.Index(i).Set(reflect.ValueOf(v))\n\t\t\t}\n\t\t\treturn val.Interface()\n\t\t}\n\n\t\tresult := make(map[string]interface{})\n\t\t// TODO Should we export everything? Or just what is enumerable?\n\t\tobj.enumerate(false, func(name string) bool {\n\t\t\tvalue := obj.get(name)\n\t\t\tif value.IsDefined() {\n\t\t\t\tresult[name] = value.export()\n\t\t\t}\n\t\t\treturn true\n\t\t})\n\t\treturn result\n\t}\n\n\tif v.safe() {\n\t\treturn v\n\t}\n\n\treturn Value{}\n}\n\nfunc (v Value) evaluateBreakContinue(labels []string) resultKind {\n\tresult := v.value.(result)\n\tif result.kind == resultBreak || result.kind == resultContinue {\n\t\tfor _, label := range labels {\n\t\t\tif label == result.target {\n\t\t\t\treturn result.kind\n\t\t\t}\n\t\t}\n\t}\n\treturn resultReturn\n}\n\nfunc (v Value) evaluateBreak(labels []string) resultKind {\n\tresult := v.value.(result)\n\tif result.kind == resultBreak {\n\t\tfor _, label := range labels {\n\t\t\tif label == result.target {\n\t\t\t\treturn result.kind\n\t\t\t}\n\t\t}\n\t}\n\treturn resultReturn\n}\n\n// Make a best effort to return a reflect.Value corresponding to reflect.Kind, but\n// fallback to just returning the Go value we have handy.\nfunc (v Value) toReflectValue(typ reflect.Type) (reflect.Value, error) {\n\tkind := typ.Kind()\n\tswitch kind {\n\tcase reflect.Float32, reflect.Float64, reflect.Interface:\n\tdefault:\n\t\tswitch value := v.value.(type) {\n\t\tcase float32:\n\t\t\t_, frac := math.Modf(float64(value))\n\t\t\tif frac > 0 {\n\t\t\t\treturn reflect.Value{}, fmt.Errorf(\"RangeError: %v to reflect.Kind: %v\", value, kind)\n\t\t\t}\n\t\tcase float64:\n\t\t\t_, frac := math.Modf(value)\n\t\t\tif frac > 0 {\n\t\t\t\treturn reflect.Value{}, fmt.Errorf(\"RangeError: %v to reflect.Kind: %v\", value, kind)\n\t\t\t}\n\t\t}\n\t}\n\n\tswitch kind {\n\tcase reflect.Bool: // Bool\n\t\treturn reflect.ValueOf(v.bool()).Convert(typ), nil\n\tcase reflect.Int: // Int\n\t\t// We convert to float64 here because converting to int64 will not tell us\n\t\t// if a value is outside the range of int64\n\t\ttmp := toIntegerFloat(v)\n\t\tif tmp < floatMinInt || tmp > floatMaxInt {\n\t\t\treturn reflect.Value{}, fmt.Errorf(\"RangeError: %f (%v) to int\", tmp, v)\n\t\t}\n\t\treturn reflect.ValueOf(int(tmp)).Convert(typ), nil\n\tcase reflect.Int8: // Int8\n\t\ttmp := v.number().int64\n\t\tif tmp < int64MinInt8 || tmp > int64MaxInt8 {\n\t\t\treturn reflect.Value{}, fmt.Errorf(\"RangeError: %d (%v) to int8\", tmp, v)\n\t\t}\n\t\treturn reflect.ValueOf(int8(tmp)).Convert(typ), nil\n\tcase reflect.Int16: // Int16\n\t\ttmp := v.number().int64\n\t\tif tmp < int64MinInt16 || tmp > int64MaxInt16 {\n\t\t\treturn reflect.Value{}, fmt.Errorf(\"RangeError: %d (%v) to int16\", tmp, v)\n\t\t}\n\t\treturn reflect.ValueOf(int16(tmp)).Convert(typ), nil\n\tcase reflect.Int32: // Int32\n\t\ttmp := v.number().int64\n\t\tif tmp < int64MinInt32 || tmp > int64MaxInt32 {\n\t\t\treturn reflect.Value{}, fmt.Errorf(\"RangeError: %d (%v) to int32\", tmp, v)\n\t\t}\n\t\treturn reflect.ValueOf(int32(tmp)).Convert(typ), nil\n\tcase reflect.Int64: // Int64\n\t\t// We convert to float64 here because converting to int64 will not tell us\n\t\t// if a value is outside the range of int64\n\t\ttmp := toIntegerFloat(v)\n\t\tif tmp < floatMinInt64 || tmp > floatMaxInt64 {\n\t\t\treturn reflect.Value{}, fmt.Errorf(\"RangeError: %f (%v) to int\", tmp, v)\n\t\t}\n\t\treturn reflect.ValueOf(int64(tmp)).Convert(typ), nil\n\tcase reflect.Uint: // Uint\n\t\t// We convert to float64 here because converting to int64 will not tell us\n\t\t// if a value is outside the range of uint\n\t\ttmp := toIntegerFloat(v)\n\t\tif tmp < 0 || tmp > floatMaxUint {\n\t\t\treturn reflect.Value{}, fmt.Errorf(\"RangeError: %f (%v) to uint\", tmp, v)\n\t\t}\n\t\treturn reflect.ValueOf(uint(tmp)).Convert(typ), nil\n\tcase reflect.Uint8: // Uint8\n\t\ttmp := v.number().int64\n\t\tif tmp < 0 || tmp > int64MaxUint8 {\n\t\t\treturn reflect.Value{}, fmt.Errorf(\"RangeError: %d (%v) to uint8\", tmp, v)\n\t\t}\n\t\treturn reflect.ValueOf(uint8(tmp)).Convert(typ), nil\n\tcase reflect.Uint16: // Uint16\n\t\ttmp := v.number().int64\n\t\tif tmp < 0 || tmp > int64MaxUint16 {\n\t\t\treturn reflect.Value{}, fmt.Errorf(\"RangeError: %d (%v) to uint16\", tmp, v)\n\t\t}\n\t\treturn reflect.ValueOf(uint16(tmp)).Convert(typ), nil\n\tcase reflect.Uint32: // Uint32\n\t\ttmp := v.number().int64\n\t\tif tmp < 0 || tmp > int64MaxUint32 {\n\t\t\treturn reflect.Value{}, fmt.Errorf(\"RangeError: %d (%v) to uint32\", tmp, v)\n\t\t}\n\t\treturn reflect.ValueOf(uint32(tmp)).Convert(typ), nil\n\tcase reflect.Uint64: // Uint64\n\t\t// We convert to float64 here because converting to int64 will not tell us\n\t\t// if a value is outside the range of uint64\n\t\ttmp := toIntegerFloat(v)\n\t\tif tmp < 0 || tmp > floatMaxUint64 {\n\t\t\treturn reflect.Value{}, fmt.Errorf(\"RangeError: %f (%v) to uint64\", tmp, v)\n\t\t}\n\t\treturn reflect.ValueOf(uint64(tmp)).Convert(typ), nil\n\tcase reflect.Float32: // Float32\n\t\ttmp := v.float64()\n\t\ttmp1 := tmp\n\t\tif 0 > tmp1 {\n\t\t\ttmp1 = -tmp1\n\t\t}\n\t\tif tmp1 > 0 && (tmp1 < math.SmallestNonzeroFloat32 || tmp1 > math.MaxFloat32) {\n\t\t\treturn reflect.Value{}, fmt.Errorf(\"RangeError: %f (%v) to float32\", tmp, v)\n\t\t}\n\t\treturn reflect.ValueOf(float32(tmp)).Convert(typ), nil\n\tcase reflect.Float64: // Float64\n\t\tvalue := v.float64()\n\t\treturn reflect.ValueOf(value).Convert(typ), nil\n\tcase reflect.String: // String\n\t\treturn reflect.ValueOf(v.string()).Convert(typ), nil\n\tcase reflect.Invalid: // Invalid\n\tcase reflect.Complex64: // FIXME? Complex64\n\tcase reflect.Complex128: // FIXME? Complex128\n\tcase reflect.Chan: // FIXME? Chan\n\tcase reflect.Func: // FIXME? Func\n\tcase reflect.Ptr: // FIXME? Ptr\n\tcase reflect.UnsafePointer: // FIXME? UnsafePointer\n\tdefault:\n\t\tswitch v.kind {\n\t\tcase valueObject:\n\t\t\tobj := v.object()\n\t\t\tswitch vl := obj.value.(type) {\n\t\t\tcase *goStructObject: // Struct\n\t\t\t\treturn reflect.ValueOf(vl.value.Interface()), nil\n\t\t\tcase *goMapObject: // Map\n\t\t\t\treturn reflect.ValueOf(vl.value.Interface()), nil\n\t\t\tcase *goArrayObject: // Array\n\t\t\t\treturn reflect.ValueOf(vl.value.Interface()), nil\n\t\t\tcase *goSliceObject: // Slice\n\t\t\t\treturn reflect.ValueOf(vl.value.Interface()), nil\n\t\t\t}\n\t\t\texported := reflect.ValueOf(v.export())\n\t\t\tif exported.Type().ConvertibleTo(typ) {\n\t\t\t\treturn exported.Convert(typ), nil\n\t\t\t}\n\t\t\treturn reflect.Value{}, fmt.Errorf(\"TypeError: could not convert %v to reflect.Type: %v\", exported, typ)\n\t\tcase valueEmpty, valueResult, valueReference:\n\t\t\t// These are invalid, and should panic\n\t\tdefault:\n\t\t\treturn reflect.ValueOf(v.value), nil\n\t\t}\n\t}\n\n\t// FIXME Should this end up as a TypeError?\n\tpanic(fmt.Errorf(\"invalid conversion of %v (%v) to reflect.Type: %v\", v.kind, v, typ))\n}\n\nfunc stringToReflectValue(value string, kind reflect.Kind) (reflect.Value, error) {\n\tswitch kind {\n\tcase reflect.Bool:\n\t\tvalue, err := strconv.ParseBool(value)\n\t\tif err != nil {\n\t\t\treturn reflect.Value{}, err\n\t\t}\n\t\treturn reflect.ValueOf(value), nil\n\tcase reflect.Int:\n\t\tvalue, err := strconv.ParseInt(value, 0, 0)\n\t\tif err != nil {\n\t\t\treturn reflect.Value{}, err\n\t\t}\n\t\treturn reflect.ValueOf(int(value)), nil\n\tcase reflect.Int8:\n\t\tvalue, err := strconv.ParseInt(value, 0, 8)\n\t\tif err != nil {\n\t\t\treturn reflect.Value{}, err\n\t\t}\n\t\treturn reflect.ValueOf(int8(value)), nil\n\tcase reflect.Int16:\n\t\tvalue, err := strconv.ParseInt(value, 0, 16)\n\t\tif err != nil {\n\t\t\treturn reflect.Value{}, err\n\t\t}\n\t\treturn reflect.ValueOf(int16(value)), nil\n\tcase reflect.Int32:\n\t\tvalue, err := strconv.ParseInt(value, 0, 32)\n\t\tif err != nil {\n\t\t\treturn reflect.Value{}, err\n\t\t}\n\t\treturn reflect.ValueOf(int32(value)), nil\n\tcase reflect.Int64:\n\t\tvalue, err := strconv.ParseInt(value, 0, 64)\n\t\tif err != nil {\n\t\t\treturn reflect.Value{}, err\n\t\t}\n\t\treturn reflect.ValueOf(value), nil\n\tcase reflect.Uint:\n\t\tvalue, err := strconv.ParseUint(value, 0, 0)\n\t\tif err != nil {\n\t\t\treturn reflect.Value{}, err\n\t\t}\n\t\treturn reflect.ValueOf(uint(value)), nil\n\tcase reflect.Uint8:\n\t\tvalue, err := strconv.ParseUint(value, 0, 8)\n\t\tif err != nil {\n\t\t\treturn reflect.Value{}, err\n\t\t}\n\t\treturn reflect.ValueOf(uint8(value)), nil\n\tcase reflect.Uint16:\n\t\tvalue, err := strconv.ParseUint(value, 0, 16)\n\t\tif err != nil {\n\t\t\treturn reflect.Value{}, err\n\t\t}\n\t\treturn reflect.ValueOf(uint16(value)), nil\n\tcase reflect.Uint32:\n\t\tvalue, err := strconv.ParseUint(value, 0, 32)\n\t\tif err != nil {\n\t\t\treturn reflect.Value{}, err\n\t\t}\n\t\treturn reflect.ValueOf(uint32(value)), nil\n\tcase reflect.Uint64:\n\t\tvalue, err := strconv.ParseUint(value, 0, 64)\n\t\tif err != nil {\n\t\t\treturn reflect.Value{}, err\n\t\t}\n\t\treturn reflect.ValueOf(value), nil\n\tcase reflect.Float32:\n\t\tvalue, err := strconv.ParseFloat(value, 32)\n\t\tif err != nil {\n\t\t\treturn reflect.Value{}, err\n\t\t}\n\t\treturn reflect.ValueOf(float32(value)), nil\n\tcase reflect.Float64:\n\t\tvalue, err := strconv.ParseFloat(value, 64)\n\t\tif err != nil {\n\t\t\treturn reflect.Value{}, err\n\t\t}\n\t\treturn reflect.ValueOf(value), nil\n\tcase reflect.String:\n\t\treturn reflect.ValueOf(value), nil\n\t}\n\n\t// FIXME This should end up as a TypeError?\n\tpanic(fmt.Errorf(\"invalid conversion of %q to reflect.Kind: %v\", value, kind))\n}\n\n// MarshalJSON implements json.Marshaller.\nfunc (v Value) MarshalJSON() ([]byte, error) {\n\tswitch v.kind {\n\tcase valueUndefined, valueNull:\n\t\treturn []byte(\"null\"), nil\n\tcase valueBoolean, valueNumber:\n\t\treturn json.Marshal(v.value)\n\tcase valueString:\n\t\treturn json.Marshal(v.string())\n\tcase valueObject:\n\t\treturn v.Object().MarshalJSON()\n\t}\n\treturn nil, fmt.Errorf(\"invalid type %v\", v.kind)\n}\n"
  },
  {
    "path": "value_boolean.go",
    "content": "package otto\n\nimport (\n\t\"fmt\"\n\t\"math\"\n\t\"reflect\"\n\t\"unicode/utf16\"\n)\n\nfunc (v Value) bool() bool {\n\tif v.kind == valueBoolean {\n\t\treturn v.value.(bool)\n\t}\n\tif v.IsUndefined() || v.IsNull() {\n\t\treturn false\n\t}\n\tswitch value := v.value.(type) {\n\tcase bool:\n\t\treturn value\n\tcase int, int8, int16, int32, int64:\n\t\treturn reflect.ValueOf(value).Int() != 0\n\tcase uint, uint8, uint16, uint32, uint64:\n\t\treturn reflect.ValueOf(value).Uint() != 0\n\tcase float32:\n\t\treturn value != 0\n\tcase float64:\n\t\tif math.IsNaN(value) || value == 0 {\n\t\t\treturn false\n\t\t}\n\t\treturn true\n\tcase string:\n\t\treturn len(value) != 0\n\tcase []uint16:\n\t\treturn len(utf16.Decode(value)) != 0\n\t}\n\tif v.IsObject() {\n\t\treturn true\n\t}\n\tpanic(fmt.Sprintf(\"unexpected boolean type %T\", v.value))\n}\n"
  },
  {
    "path": "value_kind.gen.go",
    "content": "// Code generated by \"stringer -type=valueKind -trimprefix=value -output=value_kind.gen.go\"; DO NOT EDIT.\n\npackage otto\n\nimport \"strconv\"\n\nfunc _() {\n\t// An \"invalid array index\" compiler error signifies that the constant values have changed.\n\t// Re-run the stringer command to generate them again.\n\tvar x [1]struct{}\n\t_ = x[valueUndefined-0]\n\t_ = x[valueNull-1]\n\t_ = x[valueNumber-2]\n\t_ = x[valueString-3]\n\t_ = x[valueBoolean-4]\n\t_ = x[valueObject-5]\n\t_ = x[valueEmpty-6]\n\t_ = x[valueResult-7]\n\t_ = x[valueReference-8]\n}\n\nconst _valueKind_name = \"UndefinedNullNumberStringBooleanObjectEmptyResultReference\"\n\nvar _valueKind_index = [...]uint8{0, 9, 13, 19, 25, 32, 38, 43, 49, 58}\n\nfunc (i valueKind) String() string {\n\tif i < 0 || i >= valueKind(len(_valueKind_index)-1) {\n\t\treturn \"valueKind(\" + strconv.FormatInt(int64(i), 10) + \")\"\n\t}\n\treturn _valueKind_name[_valueKind_index[i]:_valueKind_index[i+1]]\n}\n"
  },
  {
    "path": "value_number.go",
    "content": "package otto\n\nimport (\n\t\"errors\"\n\t\"fmt\"\n\t\"math\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"strings\"\n)\n\nvar stringToNumberParseInteger = regexp.MustCompile(`^(?:0[xX])`)\n\nfunc parseNumber(value string) float64 {\n\tvalue = strings.Trim(value, builtinStringTrimWhitespace)\n\n\tif value == \"\" {\n\t\treturn 0\n\t}\n\n\tvar parseFloat bool\n\tswitch {\n\tcase strings.ContainsRune(value, '.'):\n\t\tparseFloat = true\n\tcase stringToNumberParseInteger.MatchString(value):\n\t\tparseFloat = false\n\tdefault:\n\t\tparseFloat = true\n\t}\n\n\tif parseFloat {\n\t\tnumber, err := strconv.ParseFloat(value, 64)\n\t\tif err != nil && !errors.Is(err, strconv.ErrRange) {\n\t\t\treturn math.NaN()\n\t\t}\n\t\treturn number\n\t}\n\n\tnumber, err := strconv.ParseInt(value, 0, 64)\n\tif err != nil {\n\t\treturn math.NaN()\n\t}\n\treturn float64(number)\n}\n\nfunc (v Value) float64() float64 {\n\tswitch v.kind {\n\tcase valueUndefined:\n\t\treturn math.NaN()\n\tcase valueNull:\n\t\treturn 0\n\t}\n\tswitch value := v.value.(type) {\n\tcase bool:\n\t\tif value {\n\t\t\treturn 1\n\t\t}\n\t\treturn 0\n\tcase int:\n\t\treturn float64(value)\n\tcase int8:\n\t\treturn float64(value)\n\tcase int16:\n\t\treturn float64(value)\n\tcase int32:\n\t\treturn float64(value)\n\tcase int64:\n\t\treturn float64(value)\n\tcase uint:\n\t\treturn float64(value)\n\tcase uint8:\n\t\treturn float64(value)\n\tcase uint16:\n\t\treturn float64(value)\n\tcase uint32:\n\t\treturn float64(value)\n\tcase uint64:\n\t\treturn float64(value)\n\tcase float64:\n\t\treturn value\n\tcase string:\n\t\treturn parseNumber(value)\n\tcase *object:\n\t\treturn value.DefaultValue(defaultValueHintNumber).float64()\n\t}\n\tpanic(fmt.Errorf(\"toFloat(%T)\", v.value))\n}\n\nconst (\n\tsqrt1_2 float64 = math.Sqrt2 / 2\n)\n\nconst (\n\tmaxUint32 = math.MaxUint32\n\tmaxInt    = int(^uint(0) >> 1)\n\n\t// int64.\n\tint64MaxInt8   int64 = math.MaxInt8\n\tint64MinInt8   int64 = math.MinInt8\n\tint64MaxInt16  int64 = math.MaxInt16\n\tint64MinInt16  int64 = math.MinInt16\n\tint64MaxInt32  int64 = math.MaxInt32\n\tint64MinInt32  int64 = math.MinInt32\n\tint64MaxUint8  int64 = math.MaxUint8\n\tint64MaxUint16 int64 = math.MaxUint16\n\tint64MaxUint32 int64 = math.MaxUint32\n\n\t// float64.\n\tfloatMaxInt    float64 = float64(int(^uint(0) >> 1))\n\tfloatMinInt    float64 = float64(-maxInt - 1)\n\tfloatMaxUint   float64 = float64(^uint(0))\n\tfloatMaxUint64 float64 = math.MaxUint64\n\tfloatMaxInt64  float64 = math.MaxInt64\n\tfloatMinInt64  float64 = math.MinInt64\n)\n\nfunc toIntegerFloat(value Value) float64 {\n\tfloat := value.float64()\n\tswitch {\n\tcase math.IsInf(float, 0):\n\t\treturn float\n\tcase math.IsNaN(float):\n\t\treturn 0\n\tcase float > 0:\n\t\treturn math.Floor(float)\n\tdefault:\n\t\treturn math.Ceil(float)\n\t}\n}\n\ntype numberKind int\n\nconst (\n\tnumberInteger  numberKind = iota // 3.0 => 3.0\n\tnumberFloat                      // 3.14159 => 3.0, 1+2**63 > 2**63-1\n\tnumberInfinity                   // Infinity => 2**63-1\n\tnumberNaN                        // NaN => 0\n)\n\ntype _number struct {\n\tkind    numberKind\n\tint64   int64\n\tfloat64 float64\n}\n\n// FIXME\n// http://www.goinggo.net/2013/08/gustavos-ieee-754-brain-teaser.html\n// http://bazaar.launchpad.net/~niemeyer/strepr/trunk/view/6/strepr.go#L160\nfunc (v Value) number() _number {\n\tvar num _number\n\tswitch value := v.value.(type) {\n\tcase int8:\n\t\tnum.int64 = int64(value)\n\t\treturn num\n\tcase int16:\n\t\tnum.int64 = int64(value)\n\t\treturn num\n\tcase uint8:\n\t\tnum.int64 = int64(value)\n\t\treturn num\n\tcase uint16:\n\t\tnum.int64 = int64(value)\n\t\treturn num\n\tcase uint32:\n\t\tnum.int64 = int64(value)\n\t\treturn num\n\tcase int:\n\t\tnum.int64 = int64(value)\n\t\treturn num\n\tcase int64:\n\t\tnum.int64 = value\n\t\treturn num\n\t}\n\n\tfloat := v.float64()\n\tif float == 0 {\n\t\treturn num\n\t}\n\n\tnum.kind = numberFloat\n\tnum.float64 = float\n\n\tif math.IsNaN(float) {\n\t\tnum.kind = numberNaN\n\t\treturn num\n\t}\n\n\tif math.IsInf(float, 0) {\n\t\tnum.kind = numberInfinity\n\t}\n\n\tif float >= floatMaxInt64 {\n\t\tnum.int64 = math.MaxInt64\n\t\treturn num\n\t}\n\n\tif float <= floatMinInt64 {\n\t\tnum.int64 = math.MinInt64\n\t\treturn num\n\t}\n\n\tvar integer float64\n\tif float > 0 {\n\t\tinteger = math.Floor(float)\n\t} else {\n\t\tinteger = math.Ceil(float)\n\t}\n\n\tif float == integer {\n\t\tnum.kind = numberInteger\n\t}\n\tnum.int64 = int64(float)\n\treturn num\n}\n\n// ECMA 262: 9.5.\nfunc toInt32(value Value) int32 {\n\tswitch value := value.value.(type) {\n\tcase int8:\n\t\treturn int32(value)\n\tcase int16:\n\t\treturn int32(value)\n\tcase int32:\n\t\treturn value\n\t}\n\n\tfloatValue := value.float64()\n\tif math.IsNaN(floatValue) || math.IsInf(floatValue, 0) || floatValue == 0 {\n\t\treturn 0\n\t}\n\n\t// Convert to int64 before int32 to force correct wrapping.\n\treturn int32(int64(floatValue))\n}\n\nfunc toUint32(value Value) uint32 {\n\tswitch value := value.value.(type) {\n\tcase int8:\n\t\treturn uint32(value)\n\tcase int16:\n\t\treturn uint32(value)\n\tcase uint8:\n\t\treturn uint32(value)\n\tcase uint16:\n\t\treturn uint32(value)\n\tcase uint32:\n\t\treturn value\n\t}\n\n\tfloatValue := value.float64()\n\tif math.IsNaN(floatValue) || math.IsInf(floatValue, 0) || floatValue == 0 {\n\t\treturn 0\n\t}\n\n\t// Convert to int64 before uint32 to force correct wrapping.\n\treturn uint32(int64(floatValue))\n}\n\n// ECMA 262 - 6.0 - 7.1.8.\nfunc toUint16(value Value) uint16 {\n\tswitch value := value.value.(type) {\n\tcase int8:\n\t\treturn uint16(value)\n\tcase uint8:\n\t\treturn uint16(value)\n\tcase uint16:\n\t\treturn value\n\t}\n\n\tfloatValue := value.float64()\n\tif math.IsNaN(floatValue) || math.IsInf(floatValue, 0) || floatValue == 0 {\n\t\treturn 0\n\t}\n\n\t// Convert to int64 before uint16 to force correct wrapping.\n\treturn uint16(int64(floatValue))\n}\n\n// toIntSign returns sign of a number converted to -1, 0 ,1.\nfunc toIntSign(value Value) int {\n\tswitch value := value.value.(type) {\n\tcase int8:\n\t\tif value > 0 {\n\t\t\treturn 1\n\t\t} else if value < 0 {\n\t\t\treturn -1\n\t\t}\n\n\t\treturn 0\n\tcase int16:\n\t\tif value > 0 {\n\t\t\treturn 1\n\t\t} else if value < 0 {\n\t\t\treturn -1\n\t\t}\n\n\t\treturn 0\n\tcase int32:\n\t\tif value > 0 {\n\t\t\treturn 1\n\t\t} else if value < 0 {\n\t\t\treturn -1\n\t\t}\n\n\t\treturn 0\n\tcase uint8:\n\t\tif value > 0 {\n\t\t\treturn 1\n\t\t}\n\n\t\treturn 0\n\tcase uint16:\n\t\tif value > 0 {\n\t\t\treturn 1\n\t\t}\n\n\t\treturn 0\n\tcase uint32:\n\t\tif value > 0 {\n\t\t\treturn 1\n\t\t}\n\n\t\treturn 0\n\t}\n\tfloatValue := value.float64()\n\tswitch {\n\tcase math.IsNaN(floatValue), math.IsInf(floatValue, 0):\n\t\treturn 0\n\tcase floatValue == 0:\n\t\treturn 0\n\tcase floatValue > 0:\n\t\treturn 1\n\tdefault:\n\t\treturn -1\n\t}\n}\n"
  },
  {
    "path": "value_primitive.go",
    "content": "package otto\n\nfunc toNumberPrimitive(value Value) Value {\n\treturn toPrimitive(value, defaultValueHintNumber)\n}\n\nfunc toPrimitiveValue(value Value) Value {\n\treturn toPrimitive(value, defaultValueNoHint)\n}\n\nfunc toPrimitive(value Value, hint defaultValueHint) Value {\n\tswitch value.kind {\n\tcase valueNull, valueUndefined, valueNumber, valueString, valueBoolean:\n\t\treturn value\n\tcase valueObject:\n\t\treturn value.object().DefaultValue(hint)\n\tdefault:\n\t\tpanic(hereBeDragons(value.kind, value))\n\t}\n}\n"
  },
  {
    "path": "value_string.go",
    "content": "package otto\n\nimport (\n\t\"fmt\"\n\t\"math\"\n\t\"regexp\"\n\t\"strconv\"\n\t\"unicode/utf16\"\n)\n\nvar matchLeading0Exponent = regexp.MustCompile(`([eE][\\+\\-])0+([1-9])`) // 1e-07 => 1e-7\n\n// FIXME\n// https://code.google.com/p/v8/source/browse/branches/bleeding_edge/src/conversions.cc?spec=svn18082&r=18082\nfunc floatToString(value float64, bitsize int) string {\n\t// TODO Fit to ECMA-262 9.8.1 specification\n\tif math.IsNaN(value) {\n\t\treturn \"NaN\"\n\t} else if math.IsInf(value, 0) {\n\t\tif math.Signbit(value) {\n\t\t\treturn \"-Infinity\"\n\t\t}\n\t\treturn \"Infinity\"\n\t}\n\texponent := math.Log10(math.Abs(value))\n\tif exponent >= 21 || exponent < -6 {\n\t\treturn matchLeading0Exponent.ReplaceAllString(strconv.FormatFloat(value, 'g', -1, bitsize), \"$1$2\")\n\t}\n\treturn strconv.FormatFloat(value, 'f', -1, bitsize)\n}\n\nfunc numberToStringRadix(value Value, radix int) string {\n\tfloat := value.float64()\n\tswitch {\n\tcase math.IsNaN(float):\n\t\treturn \"NaN\"\n\tcase math.IsInf(float, 1):\n\t\treturn \"Infinity\"\n\tcase math.IsInf(float, -1):\n\t\treturn \"-Infinity\"\n\tcase float == 0:\n\t\treturn \"0\"\n\t}\n\t// FIXME This is very broken\n\t// Need to do proper radix conversion for floats, ...\n\t// This truncates large floats (so bad).\n\treturn strconv.FormatInt(int64(float), radix)\n}\n\nfunc (v Value) string() string {\n\tif v.kind == valueString {\n\t\tswitch value := v.value.(type) {\n\t\tcase string:\n\t\t\treturn value\n\t\tcase []uint16:\n\t\t\treturn string(utf16.Decode(value))\n\t\t}\n\t}\n\tif v.IsUndefined() {\n\t\treturn \"undefined\"\n\t}\n\tif v.IsNull() {\n\t\treturn \"null\"\n\t}\n\tswitch value := v.value.(type) {\n\tcase bool:\n\t\treturn strconv.FormatBool(value)\n\tcase int:\n\t\treturn strconv.FormatInt(int64(value), 10)\n\tcase int8:\n\t\treturn strconv.FormatInt(int64(value), 10)\n\tcase int16:\n\t\treturn strconv.FormatInt(int64(value), 10)\n\tcase int32:\n\t\treturn strconv.FormatInt(int64(value), 10)\n\tcase int64:\n\t\treturn strconv.FormatInt(value, 10)\n\tcase uint:\n\t\treturn strconv.FormatUint(uint64(value), 10)\n\tcase uint8:\n\t\treturn strconv.FormatUint(uint64(value), 10)\n\tcase uint16:\n\t\treturn strconv.FormatUint(uint64(value), 10)\n\tcase uint32:\n\t\treturn strconv.FormatUint(uint64(value), 10)\n\tcase uint64:\n\t\treturn strconv.FormatUint(value, 10)\n\tcase float32:\n\t\tif value == 0 {\n\t\t\treturn \"0\" // Take care not to return -0\n\t\t}\n\t\treturn floatToString(float64(value), 32)\n\tcase float64:\n\t\tif value == 0 {\n\t\t\treturn \"0\" // Take care not to return -0\n\t\t}\n\t\treturn floatToString(value, 64)\n\tcase []uint16:\n\t\treturn string(utf16.Decode(value))\n\tcase string:\n\t\treturn value\n\tcase *object:\n\t\treturn value.DefaultValue(defaultValueHintString).string()\n\t}\n\tpanic(fmt.Errorf(\"%v.string( %T)\", v.value, v.value))\n}\n"
  },
  {
    "path": "value_test.go",
    "content": "package otto\n\nimport (\n\t\"encoding/json\"\n\t\"math\"\n\t\"reflect\"\n\t\"testing\"\n)\n\nfunc TestValue(t *testing.T) {\n\ttt(t, func() {\n\t\tvalue := UndefinedValue()\n\t\tis(value.IsUndefined(), true)\n\t\tis(value, UndefinedValue())\n\t\tis(value, \"undefined\")\n\n\t\tis(toValue(false), false)\n\t\tis(toValue(1), 1)\n\t\tis(toValue(1).float64(), float64(1))\n\t})\n}\n\nfunc TestObject(t *testing.T) {\n\ttt(t, func() {\n\t\tis(emptyValue.isEmpty(), true)\n\t})\n}\n\ntype intAlias int\n\nfunc TestToValue(t *testing.T) {\n\ttt(t, func() {\n\t\t_, tester2 := test()\n\t\tvm := tester2.vm\n\n\t\tvalue, _ := vm.ToValue(nil)\n\t\tis(value, \"undefined\")\n\n\t\tvalue, _ = vm.ToValue((*byte)(nil))\n\t\tis(value, \"undefined\")\n\n\t\tvalue, _ = vm.ToValue(intAlias(5))\n\t\tis(value, 5)\n\n\t\t{\n\t\t\ttmp := new(int)\n\n\t\t\tvalue, _ = vm.ToValue(&tmp)\n\t\t\tis(value, 0)\n\n\t\t\t*tmp = 1\n\n\t\t\tvalue, _ = vm.ToValue(&tmp)\n\t\t\tis(value, 1)\n\n\t\t\ttmp = nil\n\n\t\t\tvalue, _ = vm.ToValue(&tmp)\n\t\t\tis(value, \"undefined\")\n\t\t}\n\n\t\t{\n\t\t\ttmp0 := new(int)\n\t\t\ttmp1 := &tmp0\n\t\t\ttmp2 := &tmp1\n\n\t\t\tvalue, _ = vm.ToValue(&tmp2)\n\t\t\tis(value, 0)\n\n\t\t\t*tmp0 = 1\n\n\t\t\tvalue, _ = vm.ToValue(&tmp2)\n\t\t\tis(value, 1)\n\n\t\t\ttmp0 = nil\n\n\t\t\tvalue, _ = vm.ToValue(&tmp2)\n\t\t\tis(value, \"undefined\")\n\t\t}\n\n\t\t{\n\t\t\tm := map[int64]string{0: \"foo\", 1: \"bar\"}\n\t\t\tval, err := vm.ToValue(m)\n\t\t\tis(err, nil)\n\t\t\tv0, err := val.Object().Get(\"0\")\n\t\t\tis(err, nil)\n\t\t\tis(v0, m[0])\n\t\t\tv1, err := val.Object().Get(\"1\")\n\t\t\tis(err, nil)\n\t\t\tis(v1, m[1])\n\t\t\tmissing, err := val.Object().Get(\"2\")\n\t\t\tis(err, nil)\n\t\t\tis(missing, UndefinedValue())\n\t\t\tinvalid, err := val.Object().Get(\"xxx\")\n\t\t\tis(err, nil)\n\t\t\tis(invalid, UndefinedValue())\n\t\t}\n\n\t\t{\n\t\t\tm := map[uint64]string{0: \"foo\", 1: \"bar\"}\n\t\t\tval, err := vm.ToValue(m)\n\t\t\tis(err, nil)\n\t\t\tv0, err := val.Object().Get(\"0\")\n\t\t\tis(err, nil)\n\t\t\tis(v0, m[0])\n\t\t\tv1, err := val.Object().Get(\"1\")\n\t\t\tis(err, nil)\n\t\t\tis(v1, m[1])\n\t\t\tmissing, err := val.Object().Get(\"2\")\n\t\t\tis(err, nil)\n\t\t\tis(missing, UndefinedValue())\n\t\t\tinvalid, err := val.Object().Get(\"xxx\")\n\t\t\tis(err, nil)\n\t\t\tis(invalid, UndefinedValue())\n\t\t}\n\t})\n}\n\nfunc TestToBoolean(t *testing.T) {\n\ttt(t, func() {\n\t\tis := func(left interface{}, right bool) {\n\t\t\tis(toValue(left).bool(), right)\n\t\t}\n\n\t\tis(\"\", false)\n\t\tis(\"xyzzy\", true)\n\t\tis(1, true)\n\t\tis(0, false)\n\n\t\tis(UndefinedValue(), false)\n\t\tis(NullValue(), false)\n\t\tis([]uint16{}, false)\n\t\tis([]uint16{0x68, 0x65, 0x6c, 0x6c, 0x6f}, true)\n\t})\n}\n\nfunc TestToFloat(t *testing.T) {\n\ttt(t, func() {\n\t\t{\n\t\t\tis := func(left interface{}, right float64) {\n\t\t\t\tis(toValue(left).float64(), right)\n\t\t\t}\n\t\t\tis(\"\", 0)\n\t\t\tis(\"xyzzy\", math.NaN())\n\t\t\tis(\"2\", 2)\n\t\t\tis(1, 1)\n\t\t\tis(0, 0)\n\t\t\tis(NullValue(), 0)\n\t\t}\n\t\tis(math.IsNaN(UndefinedValue().float64()), true)\n\t})\n}\n\nfunc TestToString(t *testing.T) {\n\ttt(t, func() {\n\t\tis(\"undefined\", UndefinedValue().string())\n\t\tis(\"null\", NullValue().string())\n\t\tis(\"true\", toValue(true).string())\n\t\tis(\"false\", toValue(false).string())\n\n\t\tis(UndefinedValue(), \"undefined\")\n\t\tis(NullValue(), \"null\")\n\t\tis(toValue(true), true)\n\t\tis(toValue(false), false)\n\t})\n}\n\nfunc Test_toInt32(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := []interface{}{\n\t\t\t0, int32(0),\n\t\t\t1, int32(1),\n\t\t\t-2147483649.0, int32(2147483647),\n\t\t\t-4294967297.0, int32(-1),\n\t\t\t-4294967296.0, int32(0),\n\t\t\t-4294967295.0, int32(1),\n\t\t\tmath.Inf(+1), int32(0),\n\t\t\tmath.Inf(-1), int32(0),\n\t\t}\n\t\tfor index := range len(test) / 2 {\n\t\t\t// FIXME terst, Make strict again?\n\t\t\tis(\n\t\t\t\ttoInt32(toValue(test[index*2])),\n\t\t\t\ttest[index*2+1].(int32),\n\t\t\t)\n\t\t}\n\t})\n}\n\nfunc Test_toUint32(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := []interface{}{\n\t\t\t0, uint32(0),\n\t\t\t1, uint32(1),\n\t\t\t-2147483649.0, uint32(2147483647),\n\t\t\t-4294967297.0, uint32(4294967295),\n\t\t\t-4294967296.0, uint32(0),\n\t\t\t-4294967295.0, uint32(1),\n\t\t\tmath.Inf(+1), uint32(0),\n\t\t\tmath.Inf(-1), uint32(0),\n\t\t}\n\t\tfor index := range len(test) / 2 {\n\t\t\t// FIXME terst, Make strict again?\n\t\t\tis(\n\t\t\t\ttoUint32(toValue(test[index*2])),\n\t\t\t\ttest[index*2+1].(uint32),\n\t\t\t)\n\t\t}\n\t})\n}\n\nfunc Test_toUint16(t *testing.T) {\n\ttt(t, func() {\n\t\ttest := []interface{}{\n\t\t\t0, uint16(0),\n\t\t\t1, uint16(1),\n\t\t\t-2147483649.0, uint16(65535),\n\t\t\t-4294967297.0, uint16(65535),\n\t\t\t-4294967296.0, uint16(0),\n\t\t\t-4294967295.0, uint16(1),\n\t\t\tmath.Inf(+1), uint16(0),\n\t\t\tmath.Inf(-1), uint16(0),\n\t\t}\n\t\tfor index := range len(test) / 2 {\n\t\t\t// FIXME terst, Make strict again?\n\t\t\tis(\n\t\t\t\ttoUint16(toValue(test[index*2])),\n\t\t\t\ttest[index*2+1].(uint16),\n\t\t\t)\n\t\t}\n\t})\n}\n\nfunc Test_sameValue(t *testing.T) {\n\ttt(t, func() {\n\t\tis(sameValue(positiveZeroValue(), negativeZeroValue()), false)\n\t\tis(sameValue(positiveZeroValue(), toValue(0)), true)\n\t\tis(sameValue(NaNValue(), NaNValue()), true)\n\t\tis(sameValue(NaNValue(), toValue(\"Nothing happens.\")), false)\n\t})\n}\n\nfunc TestExport(t *testing.T) {\n\ttt(t, func() {\n\t\ttest, vm := test()\n\n\t\tis(test(`null;`).export(), nil)\n\t\tis(test(`undefined;`).export(), nil)\n\t\tis(test(`true;`).export(), true)\n\t\tis(test(`false;`).export(), false)\n\t\tis(test(`0;`).export(), 0)\n\t\tis(test(`3.1459`).export(), 3.1459)\n\t\tis(test(`\"Nothing happens\";`).export(), \"Nothing happens\")\n\t\tis(test(`String.fromCharCode(97,98,99,100,101,102)`).export(), \"abcdef\")\n\t\t{\n\t\t\tvalue := test(`({ abc: 1, def: true, ghi: undefined });`).export().(map[string]interface{})\n\t\t\tis(value[\"abc\"], 1)\n\t\t\tis(value[\"def\"], true)\n\t\t\t_, exists := value[\"ghi\"]\n\t\t\tis(exists, false)\n\t\t}\n\t\t{\n\t\t\tvalue := test(`[ \"abc\", 1, \"def\", true, undefined, null ];`).export().([]interface{})\n\t\t\tis(value[0], \"abc\")\n\t\t\tis(value[1], 1)\n\t\t\tis(value[2], \"def\")\n\t\t\tis(value[3], true)\n\t\t\tis(value[4], nil)\n\t\t\tis(value[5], nil)\n\t\t\tis(value[5], interface{}(nil))\n\t\t}\n\t\t{\n\t\t\tvalue := test(`[ undefined, null ];`).export().([]interface{})\n\t\t\tis(value[0], nil)\n\t\t\tis(value[1], nil)\n\t\t\tis(value[1], interface{}(nil))\n\t\t}\n\t\t{\n\t\t\tvalue := test(`[[1, 2.1], [3, 4], [\"a\", \"b\"], [{c: 5, d: 6}]];`).export().([]interface{})\n\t\t\tvalue0 := value[0].([]interface{})\n\t\t\tis(value0[0], 1)\n\t\t\tis(value0[1], 2.1)\n\t\t\tvalue1 := value[1].([]int64)\n\t\t\tis(value1[0], 3)\n\t\t\tis(value1[1], 4)\n\t\t\tvalue2 := value[2].([]string)\n\t\t\tis(value2[0], \"a\")\n\t\t\tis(value2[1], \"b\")\n\t\t\tvalue3 := value[3].([]map[string]interface{})\n\t\t\tis(value3[0][\"c\"], 5)\n\t\t\tis(value3[0][\"d\"], 6)\n\t\t}\n\n\t\troundtrip := []interface{}{\n\t\t\ttrue,\n\t\t\tfalse,\n\t\t\t0,\n\t\t\t3.1459,\n\t\t\t[]interface{}{true, false, 0, 3.1459, \"abc\"},\n\t\t\tmap[string]interface{}{\n\t\t\t\tclassBooleanName: true,\n\t\t\t\tclassNumberName:  3.1459,\n\t\t\t\tclassStringName:  \"abc\",\n\t\t\t\tclassArrayName:   []interface{}{false, 0, \"\", nil},\n\t\t\t\tclassObjectName: map[string]interface{}{\n\t\t\t\t\tclassBooleanName: false,\n\t\t\t\t\tclassNumberName:  0,\n\t\t\t\t\tclassStringName:  \"def\",\n\t\t\t\t},\n\t\t\t},\n\t\t}\n\n\t\tfor _, value := range roundtrip {\n\t\t\tinput, err := json.Marshal(value)\n\t\t\tis(err, nil)\n\n\t\t\toutput, err := json.Marshal(test(\"(\" + string(input) + \");\").export())\n\t\t\tis(err, nil)\n\n\t\t\tis(string(input), string(output))\n\t\t}\n\n\t\t{\n\t\t\tabc := struct {\n\t\t\t\tghi interface{}\n\t\t\t\tdef int\n\t\t\t\txyz float32\n\t\t\t}{}\n\t\t\tabc.def = 3\n\t\t\tabc.xyz = 3.1459\n\t\t\tvm.Set(\"abc\", abc)\n\t\t\tis(test(`abc;`).export(), abc)\n\t\t}\n\n\t\t{\n\t\t\tabc := map[int64]string{0: \"foo\", 1: \"bar\"}\n\t\t\tvm.Set(\"abc\", abc)\n\t\t\tis(test(`abc;`).export(), abc)\n\t\t}\n\n\t\t{\n\t\t\tabc := map[uint64]string{0: \"foo\", 1: \"bar\"}\n\t\t\tvm.Set(\"abc\", abc)\n\t\t\tis(test(`abc;`).export(), abc)\n\t\t}\n\t})\n}\n\nfunc Test_toReflectValue(t *testing.T) {\n\ttt(t, func() {\n\t\tvalue := toValue(0.0)\n\t\ttmp, err := value.toReflectValue(reflect.TypeOf(0.0))\n\t\tis(tmp.Float(), 0.0)\n\t\tis(err, nil)\n\t})\n}\n\nfunc TestJSONMarshaling(t *testing.T) {\n\ttt(t, func() {\n\t\teval, tester2 := test()\n\t\ttoJSON := func(val interface{}) string {\n\t\t\tj, err := json.Marshal(val)\n\t\t\tis(err, nil)\n\t\t\treturn string(j)\n\t\t}\n\n\t\tis(toJSON(UndefinedValue()), `null`)\n\t\tis(toJSON(NullValue()), `null`)\n\t\tis(toJSON(FalseValue()), `false`)\n\t\tis(toJSON(TrueValue()), `true`)\n\n\t\tis(toJSON(toValue(0)), `0`)\n\t\tis(toJSON(toValue(1234)), `1234`)\n\t\tis(toJSON(toValue(1234.125)), `1234.125`)\n\t\tis(toJSON(toValue(-1234)), `-1234`)\n\t\tis(toJSON(toValue(-1234.125)), `-1234.125`)\n\n\t\tis(toJSON(toValue(\"\")), `\"\"`)\n\t\tis(toJSON(toValue(\"Otto\")), `\"Otto\"`)\n\t\tis(toJSON(eval(`String.fromCharCode(97,98,99,100,101,102)`)), `\"abcdef\"`)\n\n\t\tis(toJSON(eval(\"[]\")), `[]`)\n\t\tis(toJSON(eval(\"[1, 2, 3]\")), `[1,2,3]`)\n\t\tis(toJSON(eval(\"new Array(1,2,3)\")), `[1,2,3]`)\n\n\t\tis(toJSON(eval(`({a:1, b:\"hi\", c:[true,false]})`)), `{\"a\":1,\"b\":\"hi\",\"c\":[true,false]}`)\n\n\t\tgoArray := []string{\"foo\", \"bar\"}\n\t\tval, _ := tester2.vm.ToValue(goArray)\n\t\tis(toJSON(val), `[\"foo\",\"bar\"]`)\n\n\t\tgoMap := map[string]interface{}{\n\t\t\t\"bar\": []int{1, 2, 3},\n\t\t\t\"foo\": 17,\n\t\t}\n\t\tval, _ = tester2.vm.ToValue(goMap)\n\t\tis(toJSON(val), `{\"bar\":[1,2,3],\"foo\":17}`)\n\t})\n}\n\nfunc TestNestedJSONMarshaling(t *testing.T) {\n\ttt(t, func() {\n\t\teval, _ := test()\n\t\ttoJSON := func(val interface{}) string {\n\t\t\tj, err := json.Marshal(val)\n\t\t\tis(err, nil)\n\t\t\treturn string(j)\n\t\t}\n\n\t\tgoMap := map[string]interface{}{\n\t\t\t\"foo\": 17,\n\t\t}\n\n\t\tfn := eval(`(function(obj) {obj.jsVal = \"hi\"; obj.jsArray = [17,true]; return obj;})`)\n\t\tresult, err := fn.Call(fn, goMap)\n\t\tis(err, nil)\n\t\texported, err := result.Export()\n\t\tis(err, nil)\n\n\t\tis(toJSON(exported), `{\"foo\":17,\"jsArray\":[17,true],\"jsVal\":\"hi\"}`)\n\n\t\t// Before MarshalJSON was implemented, this last assertion would fail:\n\t\t// FAIL (==)\n\t\t//      got: {\"foo\":17,\"jsArray\":{},\"jsVal\":\"hi\"}\n\t\t// expected: {\"foo\":17,\"jsArray\":[17,true],\"jsVal\":\"hi\"}\n\t})\n}\n"
  }
]