mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Bug 1621127 - Assert opcode list is in sync between jsparagus and SpiderMonkey, and update jsparagus. r=jorendorff
Differential Revision: https://phabricator.services.mozilla.com/D74254
This commit is contained in:
parent
230d8f88ed
commit
2ed7096f1c
@ -30,7 +30,7 @@ rev = "e1daa2a7e9add66c5a36a7c967495510c2e117e8"
|
||||
[source."https://github.com/mozilla-spidermonkey/jsparagus"]
|
||||
git = "https://github.com/mozilla-spidermonkey/jsparagus"
|
||||
replace-with = "vendored-sources"
|
||||
rev = "606760537b437c6d6cb571b1813bc7d159fe245f"
|
||||
rev = "9871d65530f5fc0e3d953efbf40b51e9c56c6d2a"
|
||||
|
||||
[source."https://github.com/kvark/spirv_cross"]
|
||||
branch = "wgpu2"
|
||||
|
14
Cargo.lock
generated
14
Cargo.lock
generated
@ -2266,7 +2266,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "jsparagus"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla-spidermonkey/jsparagus?rev=606760537b437c6d6cb571b1813bc7d159fe245f#606760537b437c6d6cb571b1813bc7d159fe245f"
|
||||
source = "git+https://github.com/mozilla-spidermonkey/jsparagus?rev=9871d65530f5fc0e3d953efbf40b51e9c56c6d2a#9871d65530f5fc0e3d953efbf40b51e9c56c6d2a"
|
||||
dependencies = [
|
||||
"jsparagus-ast",
|
||||
"jsparagus-emitter",
|
||||
@ -2279,7 +2279,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "jsparagus-ast"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla-spidermonkey/jsparagus?rev=606760537b437c6d6cb571b1813bc7d159fe245f#606760537b437c6d6cb571b1813bc7d159fe245f"
|
||||
source = "git+https://github.com/mozilla-spidermonkey/jsparagus?rev=9871d65530f5fc0e3d953efbf40b51e9c56c6d2a#9871d65530f5fc0e3d953efbf40b51e9c56c6d2a"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"indexmap",
|
||||
@ -2290,7 +2290,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "jsparagus-emitter"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla-spidermonkey/jsparagus?rev=606760537b437c6d6cb571b1813bc7d159fe245f#606760537b437c6d6cb571b1813bc7d159fe245f"
|
||||
source = "git+https://github.com/mozilla-spidermonkey/jsparagus?rev=9871d65530f5fc0e3d953efbf40b51e9c56c6d2a#9871d65530f5fc0e3d953efbf40b51e9c56c6d2a"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"byteorder",
|
||||
@ -2302,7 +2302,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "jsparagus-generated-parser"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla-spidermonkey/jsparagus?rev=606760537b437c6d6cb571b1813bc7d159fe245f#606760537b437c6d6cb571b1813bc7d159fe245f"
|
||||
source = "git+https://github.com/mozilla-spidermonkey/jsparagus?rev=9871d65530f5fc0e3d953efbf40b51e9c56c6d2a#9871d65530f5fc0e3d953efbf40b51e9c56c6d2a"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"jsparagus-ast",
|
||||
@ -2312,12 +2312,12 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "jsparagus-json-log"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla-spidermonkey/jsparagus?rev=606760537b437c6d6cb571b1813bc7d159fe245f#606760537b437c6d6cb571b1813bc7d159fe245f"
|
||||
source = "git+https://github.com/mozilla-spidermonkey/jsparagus?rev=9871d65530f5fc0e3d953efbf40b51e9c56c6d2a#9871d65530f5fc0e3d953efbf40b51e9c56c6d2a"
|
||||
|
||||
[[package]]
|
||||
name = "jsparagus-parser"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla-spidermonkey/jsparagus?rev=606760537b437c6d6cb571b1813bc7d159fe245f#606760537b437c6d6cb571b1813bc7d159fe245f"
|
||||
source = "git+https://github.com/mozilla-spidermonkey/jsparagus?rev=9871d65530f5fc0e3d953efbf40b51e9c56c6d2a#9871d65530f5fc0e3d953efbf40b51e9c56c6d2a"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"jsparagus-ast",
|
||||
@ -2329,7 +2329,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "jsparagus-scope"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla-spidermonkey/jsparagus?rev=606760537b437c6d6cb571b1813bc7d159fe245f#606760537b437c6d6cb571b1813bc7d159fe245f"
|
||||
source = "git+https://github.com/mozilla-spidermonkey/jsparagus?rev=9871d65530f5fc0e3d953efbf40b51e9c56c6d2a#9871d65530f5fc0e3d953efbf40b51e9c56c6d2a"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"jsparagus-ast",
|
||||
|
@ -12,6 +12,12 @@ log = "0.4"
|
||||
# Disable regex feature for code size.
|
||||
env_logger = {version = "0.6", default-features = false}
|
||||
# For non-jsparagus developers.
|
||||
jsparagus = { git = "https://github.com/mozilla-spidermonkey/jsparagus", rev = "606760537b437c6d6cb571b1813bc7d159fe245f" }
|
||||
jsparagus = { git = "https://github.com/mozilla-spidermonkey/jsparagus", rev = "9871d65530f5fc0e3d953efbf40b51e9c56c6d2a" }
|
||||
# For local development, replace above with
|
||||
# jsparagus = { path = "{path to jsparagus}" }
|
||||
|
||||
[build-dependencies]
|
||||
# For non-jsparagus developers.
|
||||
jsparagus = { git = "https://github.com/mozilla-spidermonkey/jsparagus", rev = "9871d65530f5fc0e3d953efbf40b51e9c56c6d2a" }
|
||||
# For local development, replace above with
|
||||
# jsparagus = { path = "{path to jsparagus}" }
|
||||
|
21
js/src/frontend/smoosh/build.rs
Normal file
21
js/src/frontend/smoosh/build.rs
Normal file
@ -0,0 +1,21 @@
|
||||
use jsparagus::emitter::opcode_info;
|
||||
|
||||
fn compare(name: &str, orig: &str, copied: &str) {
|
||||
if copied != orig {
|
||||
panic!(
|
||||
"{} is out of sync. \
|
||||
It's possible that the bytecode generated by jsparagus is \
|
||||
based on older opcodes. Please run \
|
||||
crates/emitter/scripts/update_opcodes.py in jsparagus.",
|
||||
name
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
compare(
|
||||
"Opcodes.h",
|
||||
include_str!("../../vm/Opcodes.h"),
|
||||
opcode_info::get_opcodes_source(),
|
||||
);
|
||||
}
|
@ -1 +1 @@
|
||||
{"files":{"Cargo.toml":"44e966f17baf603f83e2c5ea05563744d1d564471a837ff025218c65c5de0b93","scripts/update_opcodes.py":"bc83b97904f52b4df8fcaa43d45d4948ba41a2a14aca2e18881bfbad44ef408c","src/array_emitter.rs":"bbc6528321f1d11d7c86c4f2bfdcfc9dced8f0b8b1c30c9f0a5355f300d196b6","src/ast_emitter.rs":"937c4609b452dde38f2b5b92aad1c7ee2ed7b1b54eff7b8ce408c52b3e5aa713","src/block_emitter.rs":"a95e553b667990fb585d4186588b0b976a5a477649ab7b9ddf01b26a3ddc5918","src/bytecode_offset.rs":"2aa7ba8c3cfbbd832092e65b599ab1c5a28d784ccc65d9e351bba656421b9a69","src/compilation_info.rs":"259d16ed7580c973cc0bb24a1ff4c9e8a3ca37aab328d946aa7deeb832d46b4f","src/control_structures.rs":"36a5f050b7a5d9c46d18a83f36b23ce0aca8224aff690fdd652e8fab2ef7eb34","src/copy/AsyncFunctionResolveKind.h":"3851ecbb4728257595dd6e900749d1d8e02558574c00424a7ff0e3ca007fa6ec","src/copy/BytecodeFormatFlags.h":"7dc2932321cf7cf874cd92b6d8076ebd4139492730f3ee5a3b6ed7fc57a0c685","src/copy/CheckIsCallableKind.h":"66556f922d403cb46d4ad03a97a6795bcf22505eb9733cbfacd3f2cdd5f39463","src/copy/CheckIsObjectKind.h":"8f0e112396d966c9221a743d353f62671e04cdace7dd49a59898d94ba0f621b7","src/copy/FunctionFlags.h":"d18e76ae92a2e727f5c38a6d87e8efcde53193975d903ce6980f6e10339ce67f","src/copy/FunctionPrefixKind.h":"f540a5c646a519b2d61aa27e4be865e08a31438def00ad5ba4ba2982ad1f2275","src/copy/GeneratorAndAsyncKind.h":"301668ce705970a51abfa94f89fd5db29ef5f129525110860e9e9bf7586ef187","src/copy/GeneratorResumeKind.h":"9e3cd9dc9c7f50937c6c45d73ec092dbfd92c4b56818ae6d1504bcd77078d0a6","src/copy/Opcodes.h":"6dbfd5f78b5ea608ac01072772a298bfdfe788a564e7f1a13a03fb105e4ad29a","src/copy/SourceNotes.h":"1e467f4e63d6f40a428e257fecd210bd14664516adf75a45cb17ab02ccd65fd8","src/copy/StencilEnums.h":"58e63ca17b0584831d748259f7f8a434bed221e6a180bd3e534f4c5bcca238cb","src/copy/Symbol.h":"f68b32e1b7add89931a1fa82a6888ebf6d875d03b05872469de426844532bf33","src/copy/ThrowMsgKind.h":"da805756961d81a2b50aeb391a02fd59a0aa39a9e3eb6aae21b423b15875ab30","src/dis.rs":"945acee8fce373f160bdd53f538bcc97037eaade0029996c9c9cbda980c65205","src/emitter.rs":"dbe67b9f3ac77a22573ce0a1be5455e16dc386eca6827044c0ea54e230da1bb8","src/emitter_scope.rs":"84adc9b7240d66d6d454404e8bd3a590f53cd3e009eeb3c3a1de58f2ff5b91ad","src/expression_emitter.rs":"f8e02785dffb179bbe9fe58e45bbfccc08adc3ad0a071a0073bed0feedc8ed9a","src/function.rs":"2fe396b0ad3e1b73854ba8feff37353fe5986732868490c8ba1dfc51a4074f06","src/gcthings.rs":"7441b4a04ed56204682e3d328b2f87c25a3dacaab7b76011b521a4fc792ab6e9","src/lib.rs":"361ca4f6eff158ab18f5d765ec09cd9428590e84e59f9a0c7d219f5eea763904","src/object_emitter.rs":"1d3acaca4ec595473c0d31060dbab22eaaca7a02d76aa2e0d9c550541cdccdf1","src/opcode.rs":"d00059cb9a3f04b3390b5f99f3a5eff6b399bd37200e0b6a1c19cde6276e6abf","src/opcode_info.rs":"3475f87581ce05c301b915aca584577d15df3e1d7d4096c31546462d4ee1ece5","src/reference_op_emitter.rs":"8b5b3974830bcf77e78c96112522404a2edae21c5961c8386e70dc841709a100","src/regexp.rs":"7436cf545b990bec7dcc51ff28d67deaca9d4ce894468fdad0dd44b25c571cf2","src/scope_notes.rs":"e0861d8db2fae3410c3711fe3beb42b67faf90a49cb5f06ed40025a6b5ed6db5","src/script_atom_set.rs":"8a567a786c6cc15192ca629deb3544546ec204efd1d05d16ff9ccdbf42a94e96","src/script_emitter.rs":"44a6be5ecdcde3c32d78d100a205d38be2591c7c2cc109967579af7393e09fe8","src/stencil.rs":"38043a6eeb3e6b02010e98c49f88001516a1b7340eb976d2d3c175794e1c5b84"},"package":null}
|
||||
{"files":{"Cargo.toml":"44e966f17baf603f83e2c5ea05563744d1d564471a837ff025218c65c5de0b93","scripts/update_opcodes.py":"4b22ead637282b644020ea45aa20d93ba86dec0d1231f8edcd9a0ed1e5fa01e5","src/array_emitter.rs":"bbc6528321f1d11d7c86c4f2bfdcfc9dced8f0b8b1c30c9f0a5355f300d196b6","src/ast_emitter.rs":"937c4609b452dde38f2b5b92aad1c7ee2ed7b1b54eff7b8ce408c52b3e5aa713","src/block_emitter.rs":"a95e553b667990fb585d4186588b0b976a5a477649ab7b9ddf01b26a3ddc5918","src/bytecode_offset.rs":"2aa7ba8c3cfbbd832092e65b599ab1c5a28d784ccc65d9e351bba656421b9a69","src/compilation_info.rs":"259d16ed7580c973cc0bb24a1ff4c9e8a3ca37aab328d946aa7deeb832d46b4f","src/control_structures.rs":"36a5f050b7a5d9c46d18a83f36b23ce0aca8224aff690fdd652e8fab2ef7eb34","src/copy/AsyncFunctionResolveKind.h":"3851ecbb4728257595dd6e900749d1d8e02558574c00424a7ff0e3ca007fa6ec","src/copy/BytecodeFormatFlags.h":"7dc2932321cf7cf874cd92b6d8076ebd4139492730f3ee5a3b6ed7fc57a0c685","src/copy/CheckIsCallableKind.h":"66556f922d403cb46d4ad03a97a6795bcf22505eb9733cbfacd3f2cdd5f39463","src/copy/CheckIsObjectKind.h":"8f0e112396d966c9221a743d353f62671e04cdace7dd49a59898d94ba0f621b7","src/copy/FunctionFlags.h":"4376653f70711d916bc36c2096165f0be9a50c487b9d471821da1cad80daa3a3","src/copy/FunctionPrefixKind.h":"f540a5c646a519b2d61aa27e4be865e08a31438def00ad5ba4ba2982ad1f2275","src/copy/GeneratorAndAsyncKind.h":"301668ce705970a51abfa94f89fd5db29ef5f129525110860e9e9bf7586ef187","src/copy/GeneratorResumeKind.h":"9e3cd9dc9c7f50937c6c45d73ec092dbfd92c4b56818ae6d1504bcd77078d0a6","src/copy/Opcodes.h":"72e0faa4eb0ed4e59ee2205d0ed6734fc4e7383552545d605eef2201e69d4c99","src/copy/SourceNotes.h":"1e467f4e63d6f40a428e257fecd210bd14664516adf75a45cb17ab02ccd65fd8","src/copy/StencilEnums.h":"1c4d1a2c8b365c5dd01bbf09e921a0ef73f5614e5bfb1551cd7147def92ecdf9","src/copy/Symbol.h":"f68b32e1b7add89931a1fa82a6888ebf6d875d03b05872469de426844532bf33","src/copy/ThrowMsgKind.h":"da805756961d81a2b50aeb391a02fd59a0aa39a9e3eb6aae21b423b15875ab30","src/dis.rs":"945acee8fce373f160bdd53f538bcc97037eaade0029996c9c9cbda980c65205","src/emitter.rs":"c81b0f109e4b6f14778cd6ee23ca32f78f7e5bec7d6898de7b5f70fdce944bd3","src/emitter_scope.rs":"71c0621d5e58987916b1854d24ca8b8f10296b37000122e28ecac71bf6badcb8","src/expression_emitter.rs":"f8e02785dffb179bbe9fe58e45bbfccc08adc3ad0a071a0073bed0feedc8ed9a","src/function.rs":"2fe396b0ad3e1b73854ba8feff37353fe5986732868490c8ba1dfc51a4074f06","src/gcthings.rs":"7441b4a04ed56204682e3d328b2f87c25a3dacaab7b76011b521a4fc792ab6e9","src/lib.rs":"361ca4f6eff158ab18f5d765ec09cd9428590e84e59f9a0c7d219f5eea763904","src/object_emitter.rs":"1d3acaca4ec595473c0d31060dbab22eaaca7a02d76aa2e0d9c550541cdccdf1","src/opcode.rs":"4434a36d70387c5897f3349361e0010be08cf9d9499b47b22c0b4dbdb2ad4522","src/opcode_info.rs":"3475f87581ce05c301b915aca584577d15df3e1d7d4096c31546462d4ee1ece5","src/reference_op_emitter.rs":"8b5b3974830bcf77e78c96112522404a2edae21c5961c8386e70dc841709a100","src/regexp.rs":"7436cf545b990bec7dcc51ff28d67deaca9d4ce894468fdad0dd44b25c571cf2","src/scope_notes.rs":"e0861d8db2fae3410c3711fe3beb42b67faf90a49cb5f06ed40025a6b5ed6db5","src/script_atom_set.rs":"8a567a786c6cc15192ca629deb3544546ec204efd1d05d16ff9ccdbf42a94e96","src/script_emitter.rs":"44a6be5ecdcde3c32d78d100a205d38be2591c7c2cc109967579af7393e09fe8","src/stencil.rs":"38043a6eeb3e6b02010e98c49f88001516a1b7340eb976d2d3c175794e1c5b84"},"package":null}
|
@ -48,7 +48,6 @@ input_paths = ensure_input_files([
|
||||
(public_dir, 'Symbol.h'),
|
||||
(vm_dir, 'AsyncFunctionResolveKind.h'),
|
||||
(vm_dir, 'BytecodeFormatFlags.h'),
|
||||
(vm_dir, 'CheckIsCallableKind.h'),
|
||||
(vm_dir, 'CheckIsObjectKind.h'),
|
||||
(vm_dir, 'FunctionFlags.h'),
|
||||
(vm_dir, 'FunctionPrefixKind.h'),
|
||||
@ -333,7 +332,6 @@ def extract_types(paths):
|
||||
}
|
||||
|
||||
extract_enum(types, paths, 'AsyncFunctionResolveKind')
|
||||
extract_enum(types, paths, 'CheckIsCallableKind')
|
||||
extract_enum(types, paths, 'CheckIsObjectKind')
|
||||
extract_enum(types, paths, 'FunctionPrefixKind')
|
||||
extract_enum(types, paths, 'GeneratorResumeKind')
|
||||
@ -417,7 +415,6 @@ def parse_operands(opcode):
|
||||
|
||||
copied_types = [
|
||||
'AsyncFunctionResolveKind',
|
||||
'CheckIsCallableKind',
|
||||
'CheckIsObjectKind',
|
||||
'FunctionPrefixKind',
|
||||
'GeneratorResumeKind',
|
||||
|
@ -12,7 +12,9 @@
|
||||
|
||||
#include <stdint.h> // uint8_t, uint16_t
|
||||
|
||||
class JSAtom;
|
||||
#include "jstypes.h" // JS_PUBLIC_API
|
||||
|
||||
class JS_PUBLIC_API JSAtom;
|
||||
|
||||
namespace js {
|
||||
|
||||
@ -211,8 +213,8 @@ class FunctionFlags {
|
||||
}
|
||||
bool isLambda() const { return hasFlags(LAMBDA); }
|
||||
|
||||
bool isNamedLambda(JSAtom* atom) const {
|
||||
return isLambda() && atom && !hasInferredName() && !hasGuessedAtom();
|
||||
bool isNamedLambda(bool hasName) const {
|
||||
return hasName && isLambda() && !hasInferredName() && !hasGuessedAtom();
|
||||
}
|
||||
|
||||
// These methods determine which of the u.scripted.s union arms are active.
|
||||
|
@ -715,7 +715,7 @@
|
||||
* not possible to get the right behavior using `JSOp::Add` and `JSOp::Sub`
|
||||
* alone. For one thing, `JSOp::Add` sometimes does string concatenation,
|
||||
* while `++` always does numeric addition. More fundamentally, the result
|
||||
* of evaluating `--x` is ToNumeric(old value of `x`), a value that the
|
||||
* of evaluating `x--` is ToNumeric(old value of `x`), a value that the
|
||||
* sequence `GetLocal "x"; One; Sub; SetLocal "x"` does not give us.
|
||||
*
|
||||
* [1]: https://tc39.es/ecma262/#sec-tonumeric
|
||||
@ -726,7 +726,7 @@
|
||||
* Operands:
|
||||
* Stack: val => ToNumeric(val)
|
||||
*/ \
|
||||
MACRO(ToNumeric, to_numeric, NULL, 1, 1, 1, JOF_BYTE) \
|
||||
MACRO(ToNumeric, to_numeric, NULL, 1, 1, 1, JOF_BYTE|JOF_IC) \
|
||||
/*
|
||||
* Convert a value to a string.
|
||||
*
|
||||
@ -1381,17 +1381,6 @@
|
||||
* Stack: result => result
|
||||
*/ \
|
||||
MACRO(CheckIsObj, check_is_obj, NULL, 2, 1, 1, JOF_UINT8) \
|
||||
/*
|
||||
* Check that the top value on the stack is callable, and throw a TypeError
|
||||
* if not. The operand `kind` is used only to generate an appropriate error
|
||||
* message.
|
||||
*
|
||||
* Category: Objects
|
||||
* Type: Iteration
|
||||
* Operands: CheckIsCallableKind kind
|
||||
* Stack: obj => obj
|
||||
*/ \
|
||||
MACRO(CheckIsCallable, check_is_callable, NULL, 2, 1, 1, JOF_UINT8) \
|
||||
/*
|
||||
* Throw a TypeError if `val` is `null` or `undefined`.
|
||||
*
|
||||
@ -3671,6 +3660,7 @@
|
||||
* a power of two. Use this macro to do so.
|
||||
*/
|
||||
#define FOR_EACH_TRAILING_UNUSED_OPCODE(MACRO) \
|
||||
MACRO(237) \
|
||||
MACRO(238) \
|
||||
MACRO(239) \
|
||||
MACRO(240) \
|
||||
|
@ -68,14 +68,36 @@ enum class TryNoteKind : uint8_t {
|
||||
enum class ImmutableScriptFlagsEnum : uint32_t {
|
||||
// Input Flags
|
||||
//
|
||||
// Flags that come from CompileOptions.
|
||||
// These flags are from CompileOptions or the Parser entry point. They
|
||||
// generally cannot be derived from the source text alone.
|
||||
// ----
|
||||
|
||||
// No need for result value of last expression statement.
|
||||
NoScriptRval = 1 << 0,
|
||||
// A script may have one of the following kinds: Global, Eval, Module,
|
||||
// Function. At most one flag can be set, with a default of Global.
|
||||
IsForEval = 1 << 0,
|
||||
IsModule = 1 << 1,
|
||||
IsFunction = 1 << 2,
|
||||
|
||||
// See Parser::selfHostingMode.
|
||||
SelfHosted = 1 << 1,
|
||||
// The script is compiled as engine-internal self-hosted JavaScript. This mode
|
||||
// is used to implement certain library functions and has special parse,
|
||||
// bytecode, and runtime behaviour that differs from normal script.
|
||||
SelfHosted = 1 << 3,
|
||||
|
||||
// The script was compiled with the default mode set to strict mode. Note that
|
||||
// this tracks the default value, while the actual mode used (after processing
|
||||
// source and its directives) is the `Strict` flag below.
|
||||
ForceStrict = 1 << 4,
|
||||
|
||||
// The script has a non-syntactic scope on its environment chain. That is,
|
||||
// there may be objects about which we know nothing between the outermost
|
||||
// syntactic scope and the global.
|
||||
HasNonSyntacticScope = 1 << 5,
|
||||
|
||||
// The script return value will not be used and simplified code will be
|
||||
// generated. This can only be applied to top-level scripts. The value this
|
||||
// script returns will be UndefinedValue instead of what the spec normally
|
||||
// prescribes.
|
||||
NoScriptRval = 1 << 6,
|
||||
|
||||
// TreatAsRunOnce roughly indicates that a script is expected to be run no
|
||||
// more than once. This affects optimizations and heuristics.
|
||||
@ -94,149 +116,145 @@ enum class ImmutableScriptFlagsEnum : uint32_t {
|
||||
// not yet compiled, this flag is undefined and should not be used. As the
|
||||
// enclosing script is compiled, this flag is updated to the same definition
|
||||
// the eventual non-lazy function will use.
|
||||
TreatAsRunOnce = 1 << 2,
|
||||
|
||||
// Code was forced into strict mode using CompileOptions.
|
||||
ForceStrict = 1 << 3,
|
||||
|
||||
// Script came from eval().
|
||||
IsForEval = 1 << 4,
|
||||
|
||||
// Script is parsed with a top-level goal of Module. This may be a top-level
|
||||
// or an inner-function script.
|
||||
IsModule = 1 << 5,
|
||||
|
||||
// Script is for function.
|
||||
IsFunction = 1 << 6,
|
||||
TreatAsRunOnce = 1 << 7,
|
||||
// ----
|
||||
|
||||
// Parser Flags
|
||||
//
|
||||
// Flags that come from the parser.
|
||||
// Flags computed by the Parser from the source text and input flags.
|
||||
// ----
|
||||
|
||||
// Code is in strict mode.
|
||||
Strict = 1 << 7,
|
||||
|
||||
// The (static) bindings of this script need to support dynamic name
|
||||
// read/write access. Here, 'dynamic' means dynamic dictionary lookup on
|
||||
// the scope chain for a dynamic set of keys. The primary examples are:
|
||||
// - direct eval
|
||||
// - function:
|
||||
// - with
|
||||
// since both effectively allow any name to be accessed. Non-examples are:
|
||||
// - upvars of nested functions
|
||||
// - function statement
|
||||
// since the set of assigned name is known dynamically.
|
||||
//
|
||||
// Note: access through the arguments object is not considered dynamic
|
||||
// binding access since it does not go through the normal name lookup
|
||||
// mechanism. This is debatable and could be changed (although care must be
|
||||
// taken not to turn off the whole 'arguments' optimization). To answer the
|
||||
// more general "is this argument aliased" question, script->needsArgsObj
|
||||
// should be tested (see JSScript::argIsAliased).
|
||||
BindingsAccessedDynamically = 1 << 8,
|
||||
|
||||
// This function does something that can extend the set of bindings in its
|
||||
// call objects --- it does a direct eval in non-strict code, or includes a
|
||||
// function statement (as opposed to a function definition).
|
||||
//
|
||||
// This flag is *not* inherited by enclosed or enclosing functions; it
|
||||
// applies only to the function in whose flags it appears.
|
||||
//
|
||||
FunHasExtensibleScope = 1 << 9,
|
||||
|
||||
// True if a tagged template exists in the body => Bytecode contains
|
||||
// JSOp::CallSiteObj
|
||||
// (We don't relazify functions with template strings, due to observability)
|
||||
HasCallSiteObj = 1 << 10,
|
||||
// Generated code will execute in strict mode. This is due to either the
|
||||
// ForceStrict flag being specified above, or due to source text itself (such
|
||||
// as "use strict" directives).
|
||||
Strict = 1 << 8,
|
||||
|
||||
// Script is parsed with a top-level goal of Module. This may be a top-level
|
||||
// or an inner-function script.
|
||||
HasModuleGoal = 1 << 11,
|
||||
HasModuleGoal = 1 << 9,
|
||||
|
||||
// Whether this function has a .this binding. If true, we need to emit
|
||||
// JSOp::FunctionThis in the prologue to initialize it.
|
||||
FunctionHasThisBinding = 1 << 12,
|
||||
// Script contains inner functions.
|
||||
//
|
||||
// Note: This prevents relazification since inner function close-over the
|
||||
// current scripts scopes.
|
||||
HasInnerFunctions = 1 << 10,
|
||||
|
||||
// Whether the arguments object for this script, if it needs one, should be
|
||||
// mapped (alias formal parameters).
|
||||
HasMappedArgsObj = 1 << 13,
|
||||
// There is a direct eval statement in this script OR in any of its inner
|
||||
// functions.
|
||||
//
|
||||
// Note: This prevents relazification since it can introduce inner functions.
|
||||
HasDirectEval = 1 << 11,
|
||||
|
||||
// Script contains inner functions. Used to check if we can relazify the
|
||||
// script.
|
||||
HasInnerFunctions = 1 << 14,
|
||||
// The (static) bindings of this script must support dynamic name access for
|
||||
// read/write. The environment chain is used to do these dynamic lookups and
|
||||
// optimizations to avoid allocating environments are suppressed.
|
||||
//
|
||||
// This includes direct-eval, `with`, and `delete` in this script OR in any of
|
||||
// its inner functions.
|
||||
//
|
||||
// Note: Access through the arguments object is not considered dynamic binding
|
||||
// access since it does not go through the normal name lookup mechanism.
|
||||
BindingsAccessedDynamically = 1 << 12,
|
||||
|
||||
NeedsHomeObject = 1 << 15,
|
||||
IsDerivedClassConstructor = 1 << 16,
|
||||
// A tagged template exists in the body (which will use JSOp::CallSiteObj in
|
||||
// bytecode).
|
||||
//
|
||||
// Note: This prevents relazification since the template's object is
|
||||
// observable to the user and cannot be recreated.
|
||||
HasCallSiteObj = 1 << 13,
|
||||
|
||||
// 'this', 'arguments' and f.apply() are used. This is likely to be a
|
||||
// wrapper.
|
||||
IsLikelyConstructorWrapper = 1 << 17,
|
||||
// Parser Flags for Functions
|
||||
// ----
|
||||
|
||||
// Set if this function is a generator function or async generator.
|
||||
IsGenerator = 1 << 18,
|
||||
// This function's initial prototype is one of Function, GeneratorFunction,
|
||||
// AsyncFunction, or AsyncGeneratorFunction as indicated by these flags.
|
||||
//
|
||||
// If either of these flags is set, the script may suspend and resume as it
|
||||
// executes. Stack frames for this script also have a generator object.
|
||||
IsAsync = 1 << 14,
|
||||
IsGenerator = 1 << 15,
|
||||
|
||||
// Set if this function is an async function or async generator.
|
||||
IsAsync = 1 << 19,
|
||||
// This function's body serves as the `var` environment for a non-strict
|
||||
// direct eval. This matters because it's the only way bindings can be
|
||||
// dynamically added to a local environment, possibly shadowing other
|
||||
// variables.
|
||||
FunHasExtensibleScope = 1 << 16,
|
||||
|
||||
// Set if this function has a rest parameter.
|
||||
// This function has an internal .this binding and we need to emit
|
||||
// JSOp::FunctionThis in the prologue to initialize it. This binding may be
|
||||
// used directly for "this", or indirectly (such as class constructors).
|
||||
FunctionHasThisBinding = 1 << 17,
|
||||
|
||||
// This function is a class method that must uses an internal [[HomeObject]]
|
||||
// slot. This slot is initialized when the class definition is executed in the
|
||||
// enclosing function.
|
||||
NeedsHomeObject = 1 << 18,
|
||||
|
||||
// This function is a constructor for a derived class. This is a class that
|
||||
// uses the `extends` syntax.
|
||||
IsDerivedClassConstructor = 1 << 19,
|
||||
|
||||
// This function has a rest (`...`) parameter.
|
||||
HasRest = 1 << 20,
|
||||
|
||||
// Whether 'arguments' has a local binding.
|
||||
//
|
||||
// Technically, every function has a binding named 'arguments'. Internally,
|
||||
// this binding is only added when 'arguments' is mentioned by the function
|
||||
// body. This flag indicates whether 'arguments' has been bound either
|
||||
// through implicit use:
|
||||
// function f() { return arguments }
|
||||
// or explicit redeclaration:
|
||||
// function f() { var arguments; return arguments }
|
||||
//
|
||||
// Note 1: overwritten arguments (function() { arguments = 3 }) will cause
|
||||
// this flag to be set but otherwise require no special handling:
|
||||
// 'arguments' is just a local variable and uses of 'arguments' will just
|
||||
// read the local's current slot which may have been assigned. The only
|
||||
// special semantics is that the initial value of 'arguments' is the
|
||||
// arguments object (not undefined, like normal locals).
|
||||
//
|
||||
// Note 2: if 'arguments' is bound as a formal parameter, there will be an
|
||||
// 'arguments' in Bindings, but, as the "LOCAL" in the name indicates, this
|
||||
// flag will not be set. This is because, as a formal, 'arguments' will
|
||||
// have no special semantics: the initial value is unconditionally the
|
||||
// actual argument (or undefined if nactual < nformal).
|
||||
ArgumentsHasVarBinding = 1 << 21,
|
||||
|
||||
// Whether 'arguments' always must be the arguments object. If this is unset,
|
||||
// but ArgumentsHasVarBinding is set then an analysis pass is performed at
|
||||
// runtime to decide if we can optimize it away.
|
||||
AlwaysNeedsArgsObj = 1 << 22,
|
||||
|
||||
// Whether the Parser declared 'arguments'.
|
||||
ShouldDeclareArguments = 1 << 23,
|
||||
|
||||
// Whether this script contains a direct eval statement.
|
||||
HasDirectEval = 1 << 24,
|
||||
// This function needs a call object or named lambda environment to be created
|
||||
// in order to execute the function. This is done in the Stack or JIT frame
|
||||
// setup code _before_ the bytecode prologue starts.
|
||||
NeedsFunctionEnvironmentObjects = 1 << 21,
|
||||
|
||||
// An extra VarScope is used as the body scope instead of the normal
|
||||
// FunctionScope. This is needed when parameter expressions are used AND the
|
||||
// function has var bindings or a sloppy-direct-eval. For example,
|
||||
// `function(x = eval("")) { var y; }`
|
||||
FunctionHasExtraBodyVarScope = 1 << 25,
|
||||
FunctionHasExtraBodyVarScope = 1 << 22,
|
||||
|
||||
// Whether this function needs a call object or named lambda environment.
|
||||
NeedsFunctionEnvironmentObjects = 1 << 26,
|
||||
// ----
|
||||
|
||||
// Bytecode Emitter Flags
|
||||
// This function must define the implicit `arguments` binding on the function
|
||||
// scope. If there are no free uses or an appropriate explicit binding exists,
|
||||
// then this flag is unset.
|
||||
//
|
||||
// Flags that are initialized by the BCE.
|
||||
// ----
|
||||
// Note: Parameter expressions will not see an explicit `var arguments;`
|
||||
// binding in the body and an implicit binding on the function-scope must
|
||||
// still be used in that case.
|
||||
ShouldDeclareArguments = 1 << 23,
|
||||
|
||||
// True if the script has a non-syntactic scope on its dynamic scope chain.
|
||||
// That is, there are objects about which we know nothing between the
|
||||
// outermost syntactic scope and the global.
|
||||
HasNonSyntacticScope = 1 << 27,
|
||||
// This function has a local (implicit or explicit) `arguments` binding. This
|
||||
// binding is initialized by the JSOp::Arguments bytecode.
|
||||
//
|
||||
// Technically, every function has a binding named `arguments`. Internally,
|
||||
// this binding is only added when `arguments` is mentioned by the function
|
||||
// body.
|
||||
//
|
||||
// Examples:
|
||||
// ```
|
||||
// // Explicit definition
|
||||
// function f() { var arguments; return arguments; }
|
||||
//
|
||||
// // Implicit use
|
||||
// function f() { return arguments; }
|
||||
//
|
||||
// // Implicit use in arrow function
|
||||
// function f() { return () => arguments; }
|
||||
//
|
||||
// // Implicit use in parameter expression
|
||||
// function f(a = arguments) { return a; }
|
||||
// ```
|
||||
ArgumentsHasVarBinding = 1 << 24,
|
||||
|
||||
// This function requires the `arguments` binding to be initialized with the
|
||||
// real arguments object. If unset, but ArgumentsHasVarBinding is set then an
|
||||
// analysis pass will determine if an efficient placeholder value can be used
|
||||
// instead.
|
||||
// See the implementation of JSOp::Arguments opcode.
|
||||
AlwaysNeedsArgsObj = 1 << 25,
|
||||
|
||||
// This function must use the "mapped" form of an arguments object. This flag
|
||||
// is set independently of whether we actually use an `arguments` binding. The
|
||||
// conditions are specified in the ECMAScript spec.
|
||||
HasMappedArgsObj = 1 << 26,
|
||||
|
||||
// All of 'this', 'arguments' and f.apply() are used. This is likely to be a
|
||||
// wrapper. This is a heuristic that affects Type Inference.
|
||||
IsLikelyConstructorWrapper = 1 << 27,
|
||||
};
|
||||
|
||||
enum class MutableScriptFlagsEnum : uint32_t {
|
||||
@ -244,19 +262,21 @@ enum class MutableScriptFlagsEnum : uint32_t {
|
||||
// reset when a script is successfully jit-compiled.
|
||||
WarmupResets_MASK = 0xFF,
|
||||
|
||||
// (1 << 8) is unused
|
||||
|
||||
// If treatAsRunOnce, whether script has executed.
|
||||
HasRunOnce = 1 << 9,
|
||||
HasRunOnce = 1 << 8,
|
||||
|
||||
// Script has been reused for a clone.
|
||||
HasBeenCloned = 1 << 10,
|
||||
HasBeenCloned = 1 << 9,
|
||||
|
||||
// Script has an entry in Realm::scriptCountsMap.
|
||||
HasScriptCounts = 1 << 12,
|
||||
HasScriptCounts = 1 << 10,
|
||||
|
||||
// Script has an entry in Realm::debugScriptMap.
|
||||
HasDebugScript = 1 << 13,
|
||||
HasDebugScript = 1 << 11,
|
||||
|
||||
// See: JSScript::ensureHasAnalyzedArgsUsage.
|
||||
NeedsArgsAnalysis = 1 << 12,
|
||||
NeedsArgsObj = 1 << 13,
|
||||
|
||||
// Script supports relazification where it releases bytecode and gcthings to
|
||||
// save memory. This process is opt-in since various complexities may disallow
|
||||
@ -264,39 +284,42 @@ enum class MutableScriptFlagsEnum : uint32_t {
|
||||
// NOTE: Must check for isRelazifiable() before setting this flag.
|
||||
AllowRelazify = 1 << 14,
|
||||
|
||||
// Set if the script has opted into spew.
|
||||
SpewEnabled = 1 << 15,
|
||||
|
||||
//
|
||||
// IonMonkey compilation hints.
|
||||
|
||||
// Script has had hoisted bounds checks fail.
|
||||
FailedBoundsCheck = 1 << 15,
|
||||
|
||||
// Script has had hoisted shape guard fail.
|
||||
FailedShapeGuard = 1 << 16,
|
||||
|
||||
HadFrequentBailouts = 1 << 17,
|
||||
HadOverflowBailout = 1 << 18,
|
||||
//
|
||||
|
||||
// Whether Baseline or Ion compilation has been disabled for this script.
|
||||
// IonDisabled is equivalent to |jitScript->canIonCompile() == false| but
|
||||
// JitScript can be discarded on GC and we don't want this to affect
|
||||
// observable behavior (see ArgumentsGetterImpl comment).
|
||||
BaselineDisabled = 1 << 19,
|
||||
IonDisabled = 1 << 20,
|
||||
BaselineDisabled = 1 << 16,
|
||||
IonDisabled = 1 << 17,
|
||||
|
||||
// Explicitly marked as uninlineable.
|
||||
Uninlineable = 1 << 21,
|
||||
// Script has had hoisted bounds checks fail.
|
||||
FailedBoundsCheck = 1 << 18,
|
||||
|
||||
// Idempotent cache has triggered invalidation.
|
||||
InvalidatedIdempotentCache = 1 << 22,
|
||||
// Script has had hoisted shape guard fail.
|
||||
FailedShapeGuard = 1 << 19,
|
||||
|
||||
// Script experienced frequent bailouts.
|
||||
HadFrequentBailouts = 1 << 20,
|
||||
|
||||
// An overflow happened where Range Analysis hoped it would not. The next
|
||||
// compile should be more conservative.
|
||||
HadOverflowBailout = 1 << 21,
|
||||
|
||||
// This script should not be inlined into others. This happens after inlining
|
||||
// has failed.
|
||||
Uninlineable = 1 << 22,
|
||||
|
||||
// An idempotent IC has triggered invalidation and should be deoptimized.
|
||||
InvalidatedIdempotentCache = 1 << 23,
|
||||
|
||||
// Lexical check did fail and bail out.
|
||||
FailedLexicalCheck = 1 << 23,
|
||||
|
||||
// See comments below.
|
||||
NeedsArgsAnalysis = 1 << 24,
|
||||
NeedsArgsObj = 1 << 25,
|
||||
|
||||
// Set if the script has opted into spew
|
||||
SpewEnabled = 1 << 26,
|
||||
FailedLexicalCheck = 1 << 24,
|
||||
};
|
||||
|
||||
} // namespace js
|
||||
|
@ -34,11 +34,6 @@ pub enum AsyncFunctionResolveKind {
|
||||
Reject = 1,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum CheckIsCallableKind {
|
||||
IteratorReturn = 0,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum CheckIsObjectKind {
|
||||
IteratorNext = 0,
|
||||
@ -727,11 +722,6 @@ impl InstructionWriter {
|
||||
self.write_u8(kind as u8);
|
||||
}
|
||||
|
||||
pub fn check_is_callable(&mut self, kind: CheckIsCallableKind) {
|
||||
self.emit_op(Opcode::CheckIsCallable);
|
||||
self.write_u8(kind as u8);
|
||||
}
|
||||
|
||||
pub fn check_obj_coercible(&mut self) {
|
||||
self.emit_op(Opcode::CheckObjCoercible);
|
||||
}
|
||||
|
@ -26,7 +26,6 @@ pub enum NameLocation {
|
||||
//
|
||||
// These types are the variants of enum EmitterScope.
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
struct GlobalEmitterScope {
|
||||
cache: HashMap<SourceAtomSetIndex, NameLocation>,
|
||||
|
@ -56,7 +56,7 @@ macro_rules! using_opcode_database {
|
||||
(Mod, mod, "%", 1, 2, 1, JOF_BYTE|JOF_IC),
|
||||
(Pow, pow, "**", 1, 2, 1, JOF_BYTE|JOF_IC),
|
||||
(ToId, to_id, NULL, 1, 1, 1, JOF_BYTE),
|
||||
(ToNumeric, to_numeric, NULL, 1, 1, 1, JOF_BYTE),
|
||||
(ToNumeric, to_numeric, NULL, 1, 1, 1, JOF_BYTE|JOF_IC),
|
||||
(ToString, to_string, NULL, 1, 1, 1, JOF_BYTE),
|
||||
(GlobalThis, global_this, NULL, 1, 0, 1, JOF_BYTE),
|
||||
(NewTarget, new_target, NULL, 1, 0, 1, JOF_BYTE),
|
||||
@ -107,7 +107,6 @@ macro_rules! using_opcode_database {
|
||||
(IterNext, iter_next, NULL, 1, 1, 1, JOF_BYTE),
|
||||
(EndIter, end_iter, NULL, 1, 2, 0, JOF_BYTE),
|
||||
(CheckIsObj, check_is_obj, NULL, 2, 1, 1, JOF_UINT8),
|
||||
(CheckIsCallable, check_is_callable, NULL, 2, 1, 1, JOF_UINT8),
|
||||
(CheckObjCoercible, check_obj_coercible, NULL, 1, 1, 1, JOF_BYTE),
|
||||
(ToAsyncIter, to_async_iter, NULL, 1, 2, 1, JOF_BYTE),
|
||||
(MutateProto, mutate_proto, NULL, 1, 2, 1, JOF_BYTE),
|
||||
|
@ -1 +1 @@
|
||||
{"files":{"Cargo.toml":"8e424d01abd384e3d5f13bf921c8f4bc58306b3f41825dc821e60c5220efb7e0","src/ast_builder.rs":"9ee95229917116ec8c6c6ffb47ed534ac0041a29fbe38477496fc8f810f7c75c","src/context_stack.rs":"e3672850b0b28fc9a45dee17f25a1d52106c05af919c5354dc67b5cf0c4ff299","src/declaration_kind.rs":"fdfda2fe408cce1c637d17fee0813160619450472c6de9befc36ebeed892cc3c","src/early_errors.rs":"f6a8056fd23301fe60ca044932b6a228e9644694fb3d4239ffd6e28bc9f6fb13","src/error.rs":"507e4dd9c66720f3da2db135c3024392d8aaac5ccdb90c7f7463ccb2eff7efa8","src/lib.rs":"63e0a2bf67c30790e388f7d061a53098571599a06b0b218fa95c68b7d4f0ba11","src/parser_tables_generated.rs":"aadc235db975fc5082db20209f4e96b5ffe263fe8dbaf43d4dc0f934f5579a8a","src/stack_value_generated.rs":"d8696a671368e2565d589922e3a46d20667ed3e17e29953e69b970470e9639ee","src/token.rs":"479f4cb97d2e6bc654a70634f3809817cc73eaf749c845643beb3556b9ead383","src/traits/mod.rs":"bcc2fa63444ba4c763dc996f410a6871f2cdc3bde54e1924ca8cc25cba92674a"},"package":null}
|
||||
{"files":{"Cargo.toml":"8e424d01abd384e3d5f13bf921c8f4bc58306b3f41825dc821e60c5220efb7e0","src/ast_builder.rs":"1c7f5bd154d626ca560091764bf13c480e84295a2003ecd5d3157f242d03cfe3","src/context_stack.rs":"29331d03cd4c8ee9283cb426ebe893b7ba6ad6d8a69016399c4d92a81cb1363b","src/declaration_kind.rs":"fdfda2fe408cce1c637d17fee0813160619450472c6de9befc36ebeed892cc3c","src/early_error_checker.rs":"04b5e8dfc2db295c073cd97abd0e8a96ce641ab46ba9a06338f5154ff72377b0","src/early_errors.rs":"8674454af7ac5efe51eb6a8e2abe088aad5560e0a0bd88a3eae66c90f1527149","src/error.rs":"507e4dd9c66720f3da2db135c3024392d8aaac5ccdb90c7f7463ccb2eff7efa8","src/lib.rs":"a40b11e1dda1afcccef5fc86a2030c326d38feb31e24596e602930dcad28f1ec","src/parser_tables_generated.rs":"8a15ec6a66b92884f00a6d6616dd537d36e5135c6ba6f72f1b3def692bd6103d","src/stack_value_generated.rs":"d8696a671368e2565d589922e3a46d20667ed3e17e29953e69b970470e9639ee","src/token.rs":"479f4cb97d2e6bc654a70634f3809817cc73eaf749c845643beb3556b9ead383","src/traits/mod.rs":"bcc2fa63444ba4c763dc996f410a6871f2cdc3bde54e1924ca8cc25cba92674a"},"package":null}
|
@ -1,8 +1,5 @@
|
||||
use crate::context_stack::{
|
||||
BindingInfo, BindingKind, BindingsIndex, BreakOrContinueIndex, ContextMetadata, ControlInfo,
|
||||
};
|
||||
use crate::declaration_kind::DeclarationKind;
|
||||
use crate::early_errors::*;
|
||||
use crate::context_stack::{BindingKind, ContextMetadata, ControlInfo, LabelKind};
|
||||
use crate::early_error_checker::EarlyErrorChecker;
|
||||
use crate::error::{BoxedParseError, ParseError, Result};
|
||||
use crate::Token;
|
||||
use ast::{
|
||||
@ -2708,9 +2705,9 @@ impl<'alloc> AstBuilder<'alloc> {
|
||||
consequent: arena::Box<'alloc, Statement<'alloc>>,
|
||||
alternate: Option<arena::Box<'alloc, Statement<'alloc>>>,
|
||||
) -> Result<'alloc, arena::Box<'alloc, Statement<'alloc>>> {
|
||||
self.check_single_statement(&consequent)?;
|
||||
self.check_single_statement(consequent.get_loc().start)?;
|
||||
if let Some(ref stmt) = alternate {
|
||||
self.check_single_statement(&stmt)?;
|
||||
self.check_single_statement(stmt.get_loc().start)?;
|
||||
}
|
||||
|
||||
let if_loc = if_token.loc;
|
||||
@ -2777,7 +2774,7 @@ impl<'alloc> AstBuilder<'alloc> {
|
||||
test: arena::Box<'alloc, Expression<'alloc>>,
|
||||
close_token: arena::Box<'alloc, Token>,
|
||||
) -> Result<'alloc, arena::Box<'alloc, Statement<'alloc>>> {
|
||||
self.check_single_statement(&stmt)?;
|
||||
self.check_single_statement(stmt.get_loc().start)?;
|
||||
|
||||
self.context_metadata
|
||||
.pop_unlabelled_breaks_and_continues_from(do_token.loc.start);
|
||||
@ -2795,7 +2792,7 @@ impl<'alloc> AstBuilder<'alloc> {
|
||||
test: arena::Box<'alloc, Expression<'alloc>>,
|
||||
stmt: arena::Box<'alloc, Statement<'alloc>>,
|
||||
) -> Result<'alloc, arena::Box<'alloc, Statement<'alloc>>> {
|
||||
self.check_single_statement(&stmt)?;
|
||||
self.check_single_statement(stmt.get_loc().start)?;
|
||||
|
||||
let stmt_loc = stmt.get_loc();
|
||||
self.context_metadata
|
||||
@ -2817,7 +2814,7 @@ impl<'alloc> AstBuilder<'alloc> {
|
||||
update: Option<arena::Box<'alloc, Expression<'alloc>>>,
|
||||
stmt: arena::Box<'alloc, Statement<'alloc>>,
|
||||
) -> Result<'alloc, arena::Box<'alloc, Statement<'alloc>>> {
|
||||
self.check_single_statement(&stmt)?;
|
||||
self.check_single_statement(stmt.get_loc().start)?;
|
||||
self.for_statement_common(for_token, init, test, update, stmt)
|
||||
}
|
||||
|
||||
@ -2830,8 +2827,9 @@ impl<'alloc> AstBuilder<'alloc> {
|
||||
update: Option<arena::Box<'alloc, Expression<'alloc>>>,
|
||||
stmt: arena::Box<'alloc, Statement<'alloc>>,
|
||||
) -> Result<'alloc, arena::Box<'alloc, Statement<'alloc>>> {
|
||||
self.check_single_statement(&stmt)?;
|
||||
self.check_lexical_for_bindings(&init.get_loc())?;
|
||||
self.check_single_statement(stmt.get_loc().start)?;
|
||||
let init_loc = &init.get_loc();
|
||||
self.check_lexical_for_bindings(init_loc.start, init_loc.end)?;
|
||||
self.for_statement_common(for_token, Some(init), test, update, stmt)
|
||||
}
|
||||
|
||||
@ -2907,7 +2905,7 @@ impl<'alloc> AstBuilder<'alloc> {
|
||||
right: arena::Box<'alloc, Expression<'alloc>>,
|
||||
stmt: arena::Box<'alloc, Statement<'alloc>>,
|
||||
) -> Result<'alloc, arena::Box<'alloc, Statement<'alloc>>> {
|
||||
self.check_single_statement(&stmt)?;
|
||||
self.check_single_statement(stmt.get_loc().start)?;
|
||||
self.for_in_statement_common(for_token, left, right, stmt)
|
||||
}
|
||||
|
||||
@ -2919,8 +2917,9 @@ impl<'alloc> AstBuilder<'alloc> {
|
||||
right: arena::Box<'alloc, Expression<'alloc>>,
|
||||
stmt: arena::Box<'alloc, Statement<'alloc>>,
|
||||
) -> Result<'alloc, arena::Box<'alloc, Statement<'alloc>>> {
|
||||
self.check_single_statement(&stmt)?;
|
||||
self.check_lexical_for_bindings(&left.get_loc())?;
|
||||
self.check_single_statement(stmt.get_loc().start)?;
|
||||
let left_loc = &left.get_loc();
|
||||
self.check_lexical_for_bindings(left_loc.start, left_loc.end)?;
|
||||
self.for_in_statement_common(for_token, left, right, stmt)
|
||||
}
|
||||
|
||||
@ -2997,7 +2996,7 @@ impl<'alloc> AstBuilder<'alloc> {
|
||||
right: arena::Box<'alloc, Expression<'alloc>>,
|
||||
stmt: arena::Box<'alloc, Statement<'alloc>>,
|
||||
) -> Result<'alloc, arena::Box<'alloc, Statement<'alloc>>> {
|
||||
self.check_single_statement(&stmt)?;
|
||||
self.check_single_statement(stmt.get_loc().start)?;
|
||||
self.for_of_statement_common(for_token, left, right, stmt)
|
||||
}
|
||||
|
||||
@ -3009,8 +3008,9 @@ impl<'alloc> AstBuilder<'alloc> {
|
||||
right: arena::Box<'alloc, Expression<'alloc>>,
|
||||
stmt: arena::Box<'alloc, Statement<'alloc>>,
|
||||
) -> Result<'alloc, arena::Box<'alloc, Statement<'alloc>>> {
|
||||
self.check_single_statement(&stmt)?;
|
||||
self.check_lexical_for_bindings(&left.get_loc())?;
|
||||
self.check_single_statement(stmt.get_loc().start)?;
|
||||
let left_loc = &left.get_loc();
|
||||
self.check_lexical_for_bindings(left_loc.start, left_loc.end)?;
|
||||
self.for_of_statement_common(for_token, left, right, stmt)
|
||||
}
|
||||
|
||||
@ -3041,7 +3041,7 @@ impl<'alloc> AstBuilder<'alloc> {
|
||||
right: arena::Box<'alloc, Expression<'alloc>>,
|
||||
stmt: arena::Box<'alloc, Statement<'alloc>>,
|
||||
) -> Result<'alloc, arena::Box<'alloc, Statement<'alloc>>> {
|
||||
self.check_single_statement(&stmt)?;
|
||||
self.check_single_statement(stmt.get_loc().start)?;
|
||||
self.for_await_of_statement_common(for_token, left, right, stmt)
|
||||
}
|
||||
|
||||
@ -3053,8 +3053,9 @@ impl<'alloc> AstBuilder<'alloc> {
|
||||
right: arena::Box<'alloc, Expression<'alloc>>,
|
||||
stmt: arena::Box<'alloc, Statement<'alloc>>,
|
||||
) -> Result<'alloc, arena::Box<'alloc, Statement<'alloc>>> {
|
||||
self.check_single_statement(&stmt)?;
|
||||
self.check_lexical_for_bindings(&left.get_loc())?;
|
||||
self.check_single_statement(stmt.get_loc().start)?;
|
||||
let left_loc = &left.get_loc();
|
||||
self.check_lexical_for_bindings(left_loc.start, left_loc.end)?;
|
||||
self.for_await_of_statement_common(for_token, left, right, stmt)
|
||||
}
|
||||
|
||||
@ -3119,14 +3120,15 @@ impl<'alloc> AstBuilder<'alloc> {
|
||||
let info = match label {
|
||||
Some(ref label) => {
|
||||
// Label is used both for LabelledStatement and for labelled
|
||||
// ContinueStatements. A label will be noted in bindings whenever we hit
|
||||
// a label, as is the case for ContinueStatements. These bindings are
|
||||
// not necessary, and are at the end of the bindings stack. To keep things
|
||||
// clean, we will pop the last element (the label we just added) off the stack.
|
||||
// ContinueStatements. A label will be noted in the context metadata
|
||||
// whenever we hit a label, as is the case for BreakStatements. These
|
||||
// bindings are not necessary, and are at the end of the bindings stack.
|
||||
// To keep things clean, we will pop the last element (the label we just
|
||||
// added) off the stack.
|
||||
let index = self
|
||||
.context_metadata
|
||||
.find_first_binding(continue_token.loc.start);
|
||||
self.context_metadata.pop_bindings_from(index);
|
||||
.find_first_label(continue_token.loc.start);
|
||||
self.context_metadata.pop_labels_from(index);
|
||||
|
||||
ControlInfo::new_continue(continue_token.loc.start, Some(label.value))
|
||||
}
|
||||
@ -3156,12 +3158,13 @@ impl<'alloc> AstBuilder<'alloc> {
|
||||
let info = match label {
|
||||
Some(ref label) => {
|
||||
// Label is used both for LabelledStatement and for labelled
|
||||
// BreakStatements. A label will be noted in bindings whenever we hit
|
||||
// a label, as is the case for BreakStatements. These bindings are
|
||||
// not necessary, and are at the end of the bindings stack. To keep things
|
||||
// clean, we will pop the last element (the label we just added) off the stack.
|
||||
let index = self.context_metadata.find_first_binding(label.loc.start);
|
||||
self.context_metadata.pop_bindings_from(index);
|
||||
// BreakStatements. A label will be noted in the context metadata
|
||||
// whenever we hit a label, as is the case for BreakStatements. These
|
||||
// bindings are not necessary, and are at the end of the bindings stack.
|
||||
// To keep things clean, we will pop the last element (the label we just
|
||||
// added) off the stack.
|
||||
let index = self.context_metadata.find_first_label(label.loc.start);
|
||||
self.context_metadata.pop_labels_from(index);
|
||||
|
||||
ControlInfo::new_break(break_token.loc.start, Some(label.value))
|
||||
}
|
||||
@ -3377,7 +3380,8 @@ impl<'alloc> AstBuilder<'alloc> {
|
||||
) -> Result<'alloc, arena::Box<'alloc, Statement<'alloc>>> {
|
||||
let label_loc = label.loc;
|
||||
let body_loc = body.get_loc();
|
||||
self.check_labelled_statement(&label, &body)?;
|
||||
self.mark_labelled_statement(&label, &body);
|
||||
self.check_labelled_statement(label.value, label_loc.start, body_loc.start)?;
|
||||
Ok(self.alloc_with(|| Statement::LabelledStatement {
|
||||
label: label.unbox(),
|
||||
body,
|
||||
@ -3450,7 +3454,8 @@ impl<'alloc> AstBuilder<'alloc> {
|
||||
_ => false,
|
||||
};
|
||||
|
||||
self.check_catch_bindings(is_simple, &binding.get_loc())?;
|
||||
let bindings_loc = &binding.get_loc();
|
||||
self.check_catch_bindings(is_simple, bindings_loc.start, bindings_loc.end)?;
|
||||
|
||||
Ok(self.alloc_with(|| CatchClause {
|
||||
binding: Some(binding),
|
||||
@ -3506,6 +3511,9 @@ impl<'alloc> AstBuilder<'alloc> {
|
||||
let index = self.context_metadata.find_first_binding(f.loc.start);
|
||||
self.context_metadata.pop_bindings_from(index);
|
||||
|
||||
let label_index = self.context_metadata.find_first_label(f.loc.start);
|
||||
self.context_metadata.pop_labels_from(label_index);
|
||||
|
||||
self.alloc_with(|| Expression::FunctionExpression(f))
|
||||
}
|
||||
|
||||
@ -4019,9 +4027,8 @@ impl<'alloc> AstBuilder<'alloc> {
|
||||
name: Option<arena::Box<'alloc, BindingIdentifier>>,
|
||||
mut tail: arena::Box<'alloc, ClassExpression<'alloc>>,
|
||||
) -> arena::Box<'alloc, Expression<'alloc>> {
|
||||
let index = self
|
||||
.context_metadata
|
||||
.find_first_binding(class_token.loc.start);
|
||||
let offset = class_token.loc.start;
|
||||
let index = self.context_metadata.find_first_binding(offset);
|
||||
self.context_metadata.pop_bindings_from(index);
|
||||
|
||||
tail.name = name.map(|boxed| boxed.unbox());
|
||||
@ -4525,481 +4532,6 @@ impl<'alloc> AstBuilder<'alloc> {
|
||||
Err(ParseError::NotImplemented("export").into())
|
||||
}
|
||||
|
||||
// Check Early Error for BindingIdentifier and note binding info to the
|
||||
// stack.
|
||||
fn on_binding_identifier(&mut self, token: &arena::Box<'alloc, Token>) -> Result<'alloc, ()> {
|
||||
let context = IdentifierEarlyErrorsContext::new();
|
||||
context.check_binding_identifier(token, &self.atoms.borrow())?;
|
||||
|
||||
let name = token.value.as_atom();
|
||||
let offset = token.loc.start;
|
||||
|
||||
if let Some(info) = self.context_metadata.last_binding() {
|
||||
debug_assert!(info.offset < offset);
|
||||
}
|
||||
|
||||
self.context_metadata.push_binding(BindingInfo {
|
||||
name,
|
||||
offset,
|
||||
kind: BindingKind::Unknown,
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Check Early Error for IdentifierReference.
|
||||
fn on_identifier_reference(&self, token: &arena::Box<'alloc, Token>) -> Result<'alloc, ()> {
|
||||
let context = IdentifierEarlyErrorsContext::new();
|
||||
context.check_identifier_reference(token, &self.atoms.borrow())
|
||||
}
|
||||
|
||||
// Check Early Error for LabelIdentifier and note binding info to the
|
||||
// stack
|
||||
fn on_label_identifier(&mut self, token: &arena::Box<'alloc, Token>) -> Result<'alloc, ()> {
|
||||
let context = IdentifierEarlyErrorsContext::new();
|
||||
|
||||
let name = token.value.as_atom();
|
||||
let offset = token.loc.start;
|
||||
|
||||
if let Some(info) = self.context_metadata.last_binding() {
|
||||
debug_assert!(info.offset < offset);
|
||||
}
|
||||
|
||||
// Labels are not usually considered bindings, but we are using bindings
|
||||
// in order to track duplicate label information. See `check_labelled_statement` for
|
||||
// more information about how this is used.
|
||||
//
|
||||
// If the label is attached to a continue or break statement, its binding info
|
||||
// is popped from the stack. See `continue_statement` and `break_statement` for more
|
||||
// information.
|
||||
self.context_metadata.push_binding(BindingInfo {
|
||||
name,
|
||||
offset,
|
||||
kind: BindingKind::Label,
|
||||
});
|
||||
|
||||
context.check_label_identifier(token, &self.atoms.borrow())
|
||||
}
|
||||
|
||||
// Declare bindings to Block-like context, where function declarations
|
||||
// are lexical.
|
||||
fn declare_block<T>(&self, context: &mut T, index: BindingsIndex) -> Result<'alloc, ()>
|
||||
where
|
||||
T: LexicalEarlyErrorsContext + VarEarlyErrorsContext,
|
||||
{
|
||||
for info in self.context_metadata.bindings_from(index) {
|
||||
match info.kind {
|
||||
BindingKind::Var => {
|
||||
context.declare_var(
|
||||
info.name,
|
||||
DeclarationKind::Var,
|
||||
info.offset,
|
||||
&self.atoms.borrow(),
|
||||
)?;
|
||||
}
|
||||
BindingKind::Function => {
|
||||
context.declare_lex(
|
||||
info.name,
|
||||
DeclarationKind::LexicalFunction,
|
||||
info.offset,
|
||||
&self.atoms.borrow(),
|
||||
)?;
|
||||
}
|
||||
BindingKind::AsyncOrGenerator => {
|
||||
context.declare_lex(
|
||||
info.name,
|
||||
DeclarationKind::LexicalAsyncOrGenerator,
|
||||
info.offset,
|
||||
&self.atoms.borrow(),
|
||||
)?;
|
||||
}
|
||||
BindingKind::Let => {
|
||||
context.declare_lex(
|
||||
info.name,
|
||||
DeclarationKind::Let,
|
||||
info.offset,
|
||||
&self.atoms.borrow(),
|
||||
)?;
|
||||
}
|
||||
BindingKind::Const => {
|
||||
context.declare_lex(
|
||||
info.name,
|
||||
DeclarationKind::Const,
|
||||
info.offset,
|
||||
&self.atoms.borrow(),
|
||||
)?;
|
||||
}
|
||||
BindingKind::Class => {
|
||||
context.declare_lex(
|
||||
info.name,
|
||||
DeclarationKind::Class,
|
||||
info.offset,
|
||||
&self.atoms.borrow(),
|
||||
)?;
|
||||
}
|
||||
// Do nothing for Labels, as they have to be nested for
|
||||
// a syntax error to occur.
|
||||
//
|
||||
// We do not have the nesting information at the
|
||||
// script/block/function level so we cannot reuse the mechanism
|
||||
// used for checking duplicate bindings in those error contexts.
|
||||
// We only know that the label occurred somewhere in the block,
|
||||
// and that it might occur more than once, not how it occurs.
|
||||
// This is handled in check_labelled_statement.
|
||||
BindingKind::Label => {}
|
||||
_ => {
|
||||
panic!("Unexpected binding found {:?}", info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Check bindings in Block.
|
||||
fn check_block_bindings(&mut self, start_of_block_offset: usize) -> Result<'alloc, ()> {
|
||||
let mut context = BlockEarlyErrorsContext::new();
|
||||
let index = self
|
||||
.context_metadata
|
||||
.find_first_binding(start_of_block_offset);
|
||||
self.declare_block(&mut context, index)?;
|
||||
self.context_metadata.pop_lexical_bindings_from(index);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Declare bindings to the head of lexical for-statement.
|
||||
fn declare_lexical_for_head(
|
||||
&self,
|
||||
context: &mut LexicalForHeadEarlyErrorsContext,
|
||||
from: BindingsIndex,
|
||||
to: BindingsIndex,
|
||||
) -> Result<'alloc, ()> {
|
||||
for info in self.context_metadata.bindings_from_to(from, to) {
|
||||
match info.kind {
|
||||
BindingKind::Let => {
|
||||
context.declare_lex(
|
||||
info.name,
|
||||
DeclarationKind::Let,
|
||||
info.offset,
|
||||
&self.atoms.borrow(),
|
||||
)?;
|
||||
}
|
||||
BindingKind::Const => {
|
||||
context.declare_lex(
|
||||
info.name,
|
||||
DeclarationKind::Const,
|
||||
info.offset,
|
||||
&self.atoms.borrow(),
|
||||
)?;
|
||||
}
|
||||
_ => {
|
||||
panic!("Unexpected binding found {:?}", info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Declare bindings to the body of lexical for-statement.
|
||||
fn declare_lexical_for_body(
|
||||
&self,
|
||||
context: &mut LexicalForBodyEarlyErrorsContext,
|
||||
index: BindingsIndex,
|
||||
) -> Result<'alloc, ()> {
|
||||
for info in self.context_metadata.bindings_from(index) {
|
||||
match info.kind {
|
||||
BindingKind::Var => {
|
||||
context.declare_var(
|
||||
info.name,
|
||||
DeclarationKind::Var,
|
||||
info.offset,
|
||||
&self.atoms.borrow(),
|
||||
)?;
|
||||
}
|
||||
// Do nothing for Labels, as they have to be nested for
|
||||
// a syntax error to occur
|
||||
//
|
||||
// We do not have the nesting information at the
|
||||
// script/block/function level so we cannot reuse the mechanism
|
||||
// used for checking duplicate bindings in those error contexts.
|
||||
// We only know that the label occurred somewhere in the block,
|
||||
// and that it might occur more than once, not how it occurs.
|
||||
// This is handled in check_labelled_statement.
|
||||
BindingKind::Label => {}
|
||||
_ => {
|
||||
panic!("Unexpected binding found {:?}", info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Check bindings in lexical for-statement.
|
||||
fn check_lexical_for_bindings(&mut self, bindings_loc: &SourceLocation) -> Result<'alloc, ()> {
|
||||
let mut head_context = LexicalForHeadEarlyErrorsContext::new();
|
||||
|
||||
let head_index = self.context_metadata.find_first_binding(bindings_loc.start);
|
||||
let body_index = self.context_metadata.find_first_binding(bindings_loc.end);
|
||||
self.declare_lexical_for_head(&mut head_context, head_index, body_index)?;
|
||||
|
||||
let mut body_context = LexicalForBodyEarlyErrorsContext::new(head_context);
|
||||
self.declare_lexical_for_body(&mut body_context, body_index)?;
|
||||
self.context_metadata.pop_lexical_bindings_from(head_index);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Check bindings in CaseBlock of switch-statement.
|
||||
fn check_case_block_binding(&mut self, start_of_block_offset: usize) -> Result<'alloc, ()> {
|
||||
let mut context = CaseBlockEarlyErrorsContext::new();
|
||||
|
||||
let index = self
|
||||
.context_metadata
|
||||
.find_first_binding(start_of_block_offset);
|
||||
// Check bindings in CaseBlock of switch-statement.
|
||||
self.declare_block(&mut context, index)?;
|
||||
self.context_metadata.pop_lexical_bindings_from(index);
|
||||
|
||||
self.context_metadata
|
||||
.pop_unlabelled_breaks_from(start_of_block_offset);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Declare bindings to the parameter of function or catch.
|
||||
fn declare_param<T>(
|
||||
&self,
|
||||
context: &mut T,
|
||||
from: BindingsIndex,
|
||||
to: BindingsIndex,
|
||||
) -> Result<'alloc, ()>
|
||||
where
|
||||
T: ParameterEarlyErrorsContext,
|
||||
{
|
||||
for info in self.context_metadata.bindings_from_to(from, to) {
|
||||
context.declare(info.name, info.offset, &self.atoms.borrow())?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Check bindings in Catch and Block.
|
||||
fn check_catch_bindings(
|
||||
&mut self,
|
||||
is_simple: bool,
|
||||
bindings_loc: &SourceLocation,
|
||||
) -> Result<'alloc, ()> {
|
||||
let mut param_context = if is_simple {
|
||||
CatchParameterEarlyErrorsContext::new_with_binding_identifier()
|
||||
} else {
|
||||
CatchParameterEarlyErrorsContext::new_with_binding_pattern()
|
||||
};
|
||||
|
||||
let param_index = self.context_metadata.find_first_binding(bindings_loc.start);
|
||||
let body_index = self.context_metadata.find_first_binding(bindings_loc.end);
|
||||
self.declare_param(&mut param_context, param_index, body_index)?;
|
||||
|
||||
let mut block_context = CatchBlockEarlyErrorsContext::new(param_context);
|
||||
self.declare_block(&mut block_context, body_index)?;
|
||||
self.context_metadata.pop_lexical_bindings_from(param_index);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Check bindings in Catch with no parameter and Block.
|
||||
fn check_catch_no_param_bindings(&mut self, catch_offset: usize) -> Result<'alloc, ()> {
|
||||
let body_index = self.context_metadata.find_first_binding(catch_offset);
|
||||
|
||||
let param_context = CatchParameterEarlyErrorsContext::new_with_binding_identifier();
|
||||
let mut block_context = CatchBlockEarlyErrorsContext::new(param_context);
|
||||
self.declare_block(&mut block_context, body_index)?;
|
||||
self.context_metadata.pop_lexical_bindings_from(body_index);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn check_unhandled_break_or_continue<T>(
|
||||
&mut self,
|
||||
context: T,
|
||||
offset: usize,
|
||||
) -> Result<'alloc, ()>
|
||||
where
|
||||
T: ControlEarlyErrorsContext,
|
||||
{
|
||||
let index = self.context_metadata.find_first_break_or_continue(offset);
|
||||
if let Some(info) = self.context_metadata.find_break_or_continue_at(index) {
|
||||
context.on_unhandled_break_or_continue(info)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn check_unhandled_continue(
|
||||
&mut self,
|
||||
context: LabelledStatementEarlyErrorsContext,
|
||||
index: BreakOrContinueIndex,
|
||||
) -> Result<'alloc, ()> {
|
||||
for info in self.context_metadata.breaks_and_continues_from(index) {
|
||||
context.check_labelled_continue_to_non_loop(info)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Declare bindings to script-or-function-like context, where function
|
||||
// declarations are body-level.
|
||||
fn declare_script_or_function<T>(
|
||||
&self,
|
||||
context: &mut T,
|
||||
index: BindingsIndex,
|
||||
) -> Result<'alloc, ()>
|
||||
where
|
||||
T: LexicalEarlyErrorsContext + VarEarlyErrorsContext,
|
||||
{
|
||||
for info in self.context_metadata.bindings_from(index) {
|
||||
match info.kind {
|
||||
BindingKind::Var => {
|
||||
context.declare_var(
|
||||
info.name,
|
||||
DeclarationKind::Var,
|
||||
info.offset,
|
||||
&self.atoms.borrow(),
|
||||
)?;
|
||||
}
|
||||
BindingKind::Function | BindingKind::AsyncOrGenerator => {
|
||||
context.declare_var(
|
||||
info.name,
|
||||
DeclarationKind::BodyLevelFunction,
|
||||
info.offset,
|
||||
&self.atoms.borrow(),
|
||||
)?;
|
||||
}
|
||||
BindingKind::Let => {
|
||||
context.declare_lex(
|
||||
info.name,
|
||||
DeclarationKind::Let,
|
||||
info.offset,
|
||||
&self.atoms.borrow(),
|
||||
)?;
|
||||
}
|
||||
BindingKind::Const => {
|
||||
context.declare_lex(
|
||||
info.name,
|
||||
DeclarationKind::Const,
|
||||
info.offset,
|
||||
&self.atoms.borrow(),
|
||||
)?;
|
||||
}
|
||||
BindingKind::Class => {
|
||||
context.declare_lex(
|
||||
info.name,
|
||||
DeclarationKind::Class,
|
||||
info.offset,
|
||||
&self.atoms.borrow(),
|
||||
)?;
|
||||
}
|
||||
// Do nothing for Labels, as they have to be nested for
|
||||
// a syntax error to occur
|
||||
//
|
||||
// We do not have the nesting information at the
|
||||
// script/block/function level so we cannot reuse the mechanism
|
||||
// used for checking duplicate bindings in those error contexts.
|
||||
// We only know that the label occurred somewhere in the block,
|
||||
// and that it might occur more than once, not how it occurs.
|
||||
// This is handled in check_labelled_statement.
|
||||
BindingKind::Label => {}
|
||||
_ => {
|
||||
panic!("Unexpected binding found {:?}", info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Check bindings in function with FormalParameters.
|
||||
fn check_function_bindings(
|
||||
&mut self,
|
||||
is_simple: bool,
|
||||
start_of_param_offset: usize,
|
||||
end_of_param_offset: usize,
|
||||
) -> Result<'alloc, ()> {
|
||||
let mut param_context = if is_simple {
|
||||
FormalParametersEarlyErrorsContext::new_simple()
|
||||
} else {
|
||||
FormalParametersEarlyErrorsContext::new_non_simple()
|
||||
};
|
||||
|
||||
let param_index = self
|
||||
.context_metadata
|
||||
.find_first_binding(start_of_param_offset);
|
||||
let body_index = self
|
||||
.context_metadata
|
||||
.find_first_binding(end_of_param_offset);
|
||||
self.declare_param(&mut param_context, param_index, body_index)?;
|
||||
|
||||
let mut body_context = FunctionBodyEarlyErrorsContext::new(param_context);
|
||||
self.declare_script_or_function(&mut body_context, body_index)?;
|
||||
|
||||
self.check_unhandled_break_or_continue(body_context, end_of_param_offset)?;
|
||||
|
||||
self.context_metadata.pop_bindings_from(param_index);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Check bindings in function with UniqueFormalParameters.
|
||||
fn check_unique_function_bindings(
|
||||
&mut self,
|
||||
start_of_param_offset: usize,
|
||||
end_of_param_offset: usize,
|
||||
) -> Result<'alloc, ()> {
|
||||
let mut param_context = UniqueFormalParametersEarlyErrorsContext::new();
|
||||
|
||||
let param_index = self
|
||||
.context_metadata
|
||||
.find_first_binding(start_of_param_offset);
|
||||
let body_index = self
|
||||
.context_metadata
|
||||
.find_first_binding(end_of_param_offset);
|
||||
self.declare_param(&mut param_context, param_index, body_index)?;
|
||||
|
||||
let mut body_context = UniqueFunctionBodyEarlyErrorsContext::new(param_context);
|
||||
self.declare_script_or_function(&mut body_context, body_index)?;
|
||||
self.context_metadata.pop_bindings_from(param_index);
|
||||
|
||||
self.check_unhandled_break_or_continue(body_context, end_of_param_offset)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Check bindings in Script.
|
||||
fn check_script_bindings(&mut self) -> Result<'alloc, ()> {
|
||||
let mut context = ScriptEarlyErrorsContext::new();
|
||||
let index = BindingsIndex { index: 0 };
|
||||
self.declare_script_or_function(&mut context, index)?;
|
||||
self.context_metadata.pop_bindings_from(index);
|
||||
|
||||
self.check_unhandled_break_or_continue(context, 0)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Check bindings in Module.
|
||||
fn check_module_bindings(&mut self) -> Result<'alloc, ()> {
|
||||
let mut context = ModuleEarlyErrorsContext::new();
|
||||
let index = BindingsIndex { index: 0 };
|
||||
self.declare_script_or_function(&mut context, index)?;
|
||||
self.context_metadata.pop_bindings_from(index);
|
||||
|
||||
self.check_unhandled_break_or_continue(context, 0)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Returns IsSimpleParameterList of `params`.
|
||||
//
|
||||
// NOTE: For Syntax-only parsing (NYI), the stack value for FormalParameters
|
||||
@ -5021,81 +4553,36 @@ impl<'alloc> AstBuilder<'alloc> {
|
||||
true
|
||||
}
|
||||
|
||||
// Static Semantics: Early Errors
|
||||
// https://tc39.es/ecma262/#sec-if-statement-static-semantics-early-errors
|
||||
// https://tc39.es/ecma262/#sec-semantics-static-semantics-early-errors
|
||||
// https://tc39.es/ecma262/#sec-with-statement-static-semantics-early-errors
|
||||
fn check_single_statement(
|
||||
&self,
|
||||
stmt: &arena::Box<'alloc, Statement<'alloc>>,
|
||||
) -> Result<'alloc, ()> {
|
||||
// * It is a Syntax Error if IsLabelledFunction(Statement) is true.
|
||||
if self.is_labelled_function(stmt) {
|
||||
return Err(ParseError::LabelledFunctionDeclInSingleStatement.into());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// https://tc39.es/ecma262/#sec-islabelledfunction
|
||||
// Static Semantics: IsLabelledFunction ( stmt )
|
||||
//
|
||||
// Returns IsLabelledFunction of `stmt`.
|
||||
//
|
||||
// NOTE: For Syntax-only parsing (NYI), the stack value for Statement
|
||||
// should contain this information.
|
||||
fn is_labelled_function(&self, mut stmt: &Statement<'alloc>) -> bool {
|
||||
// Step 1. If stmt is not a LabelledStatement , return false.
|
||||
while let Statement::LabelledStatement { ref body, .. } = stmt {
|
||||
// Step 2. Let item be the LabelledItem of stmt.
|
||||
let item: &Statement<'alloc> = body;
|
||||
|
||||
// Step 3. If item is LabelledItem : FunctionDeclaration,
|
||||
// return true.
|
||||
if let Statement::FunctionDeclaration(_) = item {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Step 4. Let subStmt be the Statement of item.
|
||||
// Step 5. Return IsLabelledFunction(subStmt).
|
||||
stmt = item;
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
fn check_labelled_statement(
|
||||
fn mark_labelled_statement(
|
||||
&mut self,
|
||||
label: &arena::Box<'alloc, Label>,
|
||||
body: &Statement<'alloc>,
|
||||
) -> Result<'alloc, ()> {
|
||||
) {
|
||||
let start_label_offset = label.loc.start;
|
||||
let end_label_offset = label.loc.end;
|
||||
let name = label.value;
|
||||
let is_loop = match body {
|
||||
let kind = match body {
|
||||
Statement::ForStatement { .. }
|
||||
| Statement::ForOfStatement { .. }
|
||||
| Statement::ForInStatement { .. }
|
||||
| Statement::WhileStatement { .. }
|
||||
| Statement::DoWhileStatement { .. } => true,
|
||||
_ => false,
|
||||
| Statement::DoWhileStatement { .. } => LabelKind::Loop,
|
||||
Statement::LabelledStatement { .. } => LabelKind::LabelledLabel,
|
||||
Statement::FunctionDeclaration { .. } => LabelKind::Function,
|
||||
_ => LabelKind::Other,
|
||||
};
|
||||
|
||||
let context = LabelledStatementEarlyErrorsContext::new(name, is_loop);
|
||||
|
||||
let binding_index = self.context_metadata.find_first_binding(end_label_offset);
|
||||
for info in self.context_metadata.bindings_from(binding_index) {
|
||||
if info.kind == BindingKind::Label {
|
||||
context.check_duplicate_label(info.name)?;
|
||||
}
|
||||
}
|
||||
|
||||
let label_index = self
|
||||
.context_metadata
|
||||
.find_first_break_or_continue(start_label_offset);
|
||||
self.check_unhandled_continue(context, label_index)?;
|
||||
|
||||
self.context_metadata
|
||||
.pop_labelled_breaks_and_continues_from_index(label_index, name);
|
||||
Ok(())
|
||||
.mark_label_kind_at_offset(start_label_offset, kind);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'alloc> EarlyErrorChecker<'alloc> for AstBuilder<'alloc> {
|
||||
fn context_metadata_mut(&mut self) -> &mut ContextMetadata {
|
||||
&mut self.context_metadata
|
||||
}
|
||||
fn context_metadata(&self) -> &ContextMetadata {
|
||||
&self.context_metadata
|
||||
}
|
||||
fn atoms(&self) -> &Rc<RefCell<SourceAtomSet<'alloc>>> {
|
||||
&self.atoms
|
||||
}
|
||||
}
|
||||
|
@ -44,11 +44,6 @@ pub enum BindingKind {
|
||||
|
||||
// BindingIdentifier is the name of ClassDeclaration.
|
||||
Class,
|
||||
|
||||
// BindingIdentifier is the name of LabelIdentifier.
|
||||
// Only used to track which labels have been seen for duplicate labels. See
|
||||
// the AST Builder method 'on_label_identifier' for more information
|
||||
Label,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||
@ -107,6 +102,31 @@ impl BreakOrContinueIndex {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||
pub enum LabelKind {
|
||||
Other,
|
||||
|
||||
Function,
|
||||
|
||||
Loop,
|
||||
|
||||
LabelledLabel,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||
pub struct LabelInfo {
|
||||
pub name: SourceAtomSetIndex,
|
||||
// The offset of the BindingIdentifier in the source.
|
||||
pub offset: usize,
|
||||
pub kind: LabelKind,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||
pub struct LabelIndex {
|
||||
pub index: usize,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct ContextMetadata {
|
||||
// The stack of information about BindingIdentifier.
|
||||
//
|
||||
@ -121,9 +141,8 @@ pub struct ContextMetadata {
|
||||
// EarlyErrorsContext to detect Early Errors.
|
||||
//
|
||||
// When leaving a context that is not one of script/module/function,
|
||||
// lexical items (`kind != BindingKind::Var && kind != BindingKind::Label`)
|
||||
// in the corresponding range are removed, while non-lexical items
|
||||
// (`kind == BindingKind::Var || kind == BindingKind::Label`) are
|
||||
// lexical items (`kind != BindingKind::Var) in the corresponding range
|
||||
// are removed, while non-lexical items (`kind == BindingKind::Var) are
|
||||
// left there, so that VariableDeclarations and labels are propagated to the
|
||||
// enclosing context.
|
||||
//
|
||||
@ -138,6 +157,8 @@ pub struct ContextMetadata {
|
||||
// related metehods should be removed, and each break/continue should be
|
||||
// fed directly to EarlyErrorsContext.
|
||||
breaks_and_continues: Vec<ControlInfo>,
|
||||
|
||||
labels: Vec<LabelInfo>,
|
||||
}
|
||||
|
||||
impl ContextMetadata {
|
||||
@ -145,6 +166,7 @@ impl ContextMetadata {
|
||||
Self {
|
||||
bindings: Vec::new(),
|
||||
breaks_and_continues: Vec::new(),
|
||||
labels: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -160,6 +182,10 @@ impl ContextMetadata {
|
||||
self.breaks_and_continues.push(control);
|
||||
}
|
||||
|
||||
pub fn push_label(&mut self, label: LabelInfo) {
|
||||
self.labels.push(label);
|
||||
}
|
||||
|
||||
// Update the binding kind of all names declared in a specific range of the
|
||||
// source (and not in any nested scope). This is used e.g. when the parser
|
||||
// reaches the end of a VariableStatement to mark all the variables as Var
|
||||
@ -197,7 +223,7 @@ impl ContextMetadata {
|
||||
.take(to.index - from.index)
|
||||
}
|
||||
|
||||
// Returns the index of the first binding at/after `offset` source position.
|
||||
// Returns the index of the first label at/after `offset` source position.
|
||||
pub fn find_first_binding(&mut self, offset: usize) -> BindingsIndex {
|
||||
let mut i = self.bindings.len();
|
||||
for info in self.bindings.iter_mut().rev() {
|
||||
@ -216,6 +242,27 @@ impl ContextMetadata {
|
||||
self.bindings.truncate(index.index)
|
||||
}
|
||||
|
||||
pub fn labels_from(&self, index: LabelIndex) -> Skip<Iter<'_, LabelInfo>> {
|
||||
self.labels.iter().skip(index.index)
|
||||
}
|
||||
|
||||
// Update the label kind of a label declared in a specific range of the
|
||||
// source (and not in any nested scope). There should never be more than one.
|
||||
//
|
||||
// It's necessary because the current parser only calls AstBuilder methods
|
||||
// at the end of each production, not at the beginning.
|
||||
//
|
||||
// Labels inside `StatementList` must be marked using this method before
|
||||
// we reach the end of its scope.
|
||||
pub fn mark_label_kind_at_offset(&mut self, from: usize, kind: LabelKind) {
|
||||
let maybe_label = self.find_label_at_offset(from);
|
||||
if let Some(info) = maybe_label {
|
||||
info.kind = kind
|
||||
} else {
|
||||
panic!("Tried to mark a non-existant label");
|
||||
}
|
||||
}
|
||||
|
||||
// Remove lexical bindings after `index`-th item,
|
||||
// while keeping var bindings.
|
||||
//
|
||||
@ -230,9 +277,7 @@ impl ContextMetadata {
|
||||
|
||||
let mut j = i;
|
||||
while j < len {
|
||||
if self.bindings[j].kind == BindingKind::Var
|
||||
|| self.bindings[j].kind == BindingKind::Label
|
||||
{
|
||||
if self.bindings[j].kind == BindingKind::Var {
|
||||
self.bindings[i] = self.bindings[j];
|
||||
i += 1;
|
||||
}
|
||||
@ -242,6 +287,25 @@ impl ContextMetadata {
|
||||
self.bindings.truncate(i)
|
||||
}
|
||||
|
||||
// Returns the index of the first binding at/after `offset` source position.
|
||||
pub fn find_first_label(&mut self, offset: usize) -> LabelIndex {
|
||||
let mut i = self.labels.len();
|
||||
for info in self.labels.iter_mut().rev() {
|
||||
if info.offset < offset {
|
||||
break;
|
||||
}
|
||||
i -= 1;
|
||||
}
|
||||
LabelIndex { index: i }
|
||||
}
|
||||
|
||||
// Remove all bindings after `index`-th item.
|
||||
//
|
||||
// This should be called when leaving function/script/module.
|
||||
pub fn pop_labels_from(&mut self, index: LabelIndex) {
|
||||
self.labels.truncate(index.index)
|
||||
}
|
||||
|
||||
pub fn breaks_and_continues_from(
|
||||
&self,
|
||||
index: BreakOrContinueIndex,
|
||||
@ -329,4 +393,13 @@ impl ContextMetadata {
|
||||
pub fn find_break_or_continue_at(&self, index: BreakOrContinueIndex) -> Option<&ControlInfo> {
|
||||
self.breaks_and_continues.get(index.index)
|
||||
}
|
||||
|
||||
pub fn find_label_index_at_offset(&self, offset: usize) -> Option<LabelIndex> {
|
||||
let index = self.labels.iter().position(|info| info.offset == offset);
|
||||
index.map(|index| LabelIndex { index })
|
||||
}
|
||||
|
||||
pub fn find_label_at_offset(&mut self, offset: usize) -> Option<&mut LabelInfo> {
|
||||
self.labels.iter_mut().find(|info| info.offset == offset)
|
||||
}
|
||||
}
|
||||
|
639
third_party/rust/jsparagus-generated-parser/src/early_error_checker.rs
vendored
Normal file
639
third_party/rust/jsparagus-generated-parser/src/early_error_checker.rs
vendored
Normal file
@ -0,0 +1,639 @@
|
||||
use crate::context_stack::{
|
||||
BindingInfo, BindingKind, BindingsIndex, BreakOrContinueIndex, ContextMetadata, LabelIndex,
|
||||
LabelInfo, LabelKind,
|
||||
};
|
||||
use crate::declaration_kind::DeclarationKind;
|
||||
use crate::early_errors::*;
|
||||
use crate::error::{ParseError, Result};
|
||||
use crate::Token;
|
||||
use ast::arena;
|
||||
use ast::source_atom_set::{SourceAtomSet, SourceAtomSetIndex};
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
/// called From EarlyErrorChecker::check_labelled_statement, and not used by
|
||||
/// the struct implementing the trait. This means that
|
||||
/// LabelledStatementEarlyErrorsContext is allocated inside this trait.
|
||||
fn check_labelled_continue_to_non_loop<'alloc>(
|
||||
context_metadata_mut: &mut ContextMetadata,
|
||||
context: LabelledStatementEarlyErrorsContext,
|
||||
index: BreakOrContinueIndex,
|
||||
) -> Result<'alloc, ()> {
|
||||
for info in context_metadata_mut.breaks_and_continues_from(index) {
|
||||
context.check_labelled_continue_to_non_loop(info)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// called From EarlyErrorChecker::check_script_bindings
|
||||
/// EarlyErrorChecker::check_module_bindings,
|
||||
/// EarlyErrorChecker::check_function_bindings, and not used by
|
||||
/// the struct implementing the trait. This means that
|
||||
/// the contexts associated with those methods are allocated inside this trait.
|
||||
fn check_unhandled_break_or_continue<'alloc, T>(
|
||||
context_metadata_mut: &mut ContextMetadata,
|
||||
context: T,
|
||||
offset: usize,
|
||||
) -> Result<'alloc, ()>
|
||||
where
|
||||
T: ControlEarlyErrorsContext,
|
||||
{
|
||||
let index = context_metadata_mut.find_first_break_or_continue(offset);
|
||||
if let Some(info) = context_metadata_mut.find_break_or_continue_at(index) {
|
||||
context.on_unhandled_break_or_continue(info)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// https://tc39.es/ecma262/#sec-islabelledfunction
|
||||
/// Static Semantics: IsLabelledFunction ( stmt )
|
||||
fn is_labelled_function(context_metadata: &ContextMetadata, statement_start_offset: usize) -> bool {
|
||||
// Step 1. If stmt is not a LabelledStatement , return false.
|
||||
if let Some(index) = context_metadata.find_label_index_at_offset(statement_start_offset) {
|
||||
// Step 2. Let item be the LabelledItem of stmt.
|
||||
for label in context_metadata.labels_from(index) {
|
||||
match label.kind {
|
||||
// Step 3. If item is LabelledItem : FunctionDeclaration,
|
||||
// return true.
|
||||
LabelKind::Function => {
|
||||
return true;
|
||||
}
|
||||
// Step 4. Let subStmt be the Statement of item.
|
||||
// Step 5. Return IsLabelledFunction(subStmt).
|
||||
LabelKind::LabelledLabel => continue,
|
||||
_ => break,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
/// Declare bindings in context_metadata to script-or-function-like context,
|
||||
/// where function declarations are body-level. This method is an internal
|
||||
/// helper for EarlyErrorChecker
|
||||
fn declare_script_or_function<'alloc, T>(
|
||||
context_metadata: &ContextMetadata,
|
||||
atoms: &Rc<RefCell<SourceAtomSet<'alloc>>>,
|
||||
context: &mut T,
|
||||
index: BindingsIndex,
|
||||
) -> Result<'alloc, ()>
|
||||
where
|
||||
T: LexicalEarlyErrorsContext + VarEarlyErrorsContext,
|
||||
{
|
||||
for info in context_metadata.bindings_from(index) {
|
||||
match info.kind {
|
||||
BindingKind::Var => {
|
||||
context.declare_var(
|
||||
info.name,
|
||||
DeclarationKind::Var,
|
||||
info.offset,
|
||||
&atoms.borrow(),
|
||||
)?;
|
||||
}
|
||||
BindingKind::Function | BindingKind::AsyncOrGenerator => {
|
||||
context.declare_var(
|
||||
info.name,
|
||||
DeclarationKind::BodyLevelFunction,
|
||||
info.offset,
|
||||
&atoms.borrow(),
|
||||
)?;
|
||||
}
|
||||
BindingKind::Let => {
|
||||
context.declare_lex(
|
||||
info.name,
|
||||
DeclarationKind::Let,
|
||||
info.offset,
|
||||
&atoms.borrow(),
|
||||
)?;
|
||||
}
|
||||
BindingKind::Const => {
|
||||
context.declare_lex(
|
||||
info.name,
|
||||
DeclarationKind::Const,
|
||||
info.offset,
|
||||
&atoms.borrow(),
|
||||
)?;
|
||||
}
|
||||
BindingKind::Class => {
|
||||
context.declare_lex(
|
||||
info.name,
|
||||
DeclarationKind::Class,
|
||||
info.offset,
|
||||
&atoms.borrow(),
|
||||
)?;
|
||||
}
|
||||
_ => {
|
||||
panic!("Unexpected binding found {:?}", info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Declare bindings to Block-like context, where function declarations
|
||||
/// are lexical. This method is an internal helper for EarlyErrorChecker
|
||||
fn declare_block<'alloc, T>(
|
||||
context_metadata: &ContextMetadata,
|
||||
atoms: &Rc<RefCell<SourceAtomSet<'alloc>>>,
|
||||
context: &mut T,
|
||||
index: BindingsIndex,
|
||||
) -> Result<'alloc, ()>
|
||||
where
|
||||
T: LexicalEarlyErrorsContext + VarEarlyErrorsContext,
|
||||
{
|
||||
for info in context_metadata.bindings_from(index) {
|
||||
match info.kind {
|
||||
BindingKind::Var => {
|
||||
context.declare_var(
|
||||
info.name,
|
||||
DeclarationKind::Var,
|
||||
info.offset,
|
||||
&atoms.borrow(),
|
||||
)?;
|
||||
}
|
||||
BindingKind::Function => {
|
||||
context.declare_lex(
|
||||
info.name,
|
||||
DeclarationKind::LexicalFunction,
|
||||
info.offset,
|
||||
&atoms.borrow(),
|
||||
)?;
|
||||
}
|
||||
BindingKind::AsyncOrGenerator => {
|
||||
context.declare_lex(
|
||||
info.name,
|
||||
DeclarationKind::LexicalAsyncOrGenerator,
|
||||
info.offset,
|
||||
&atoms.borrow(),
|
||||
)?;
|
||||
}
|
||||
BindingKind::Let => {
|
||||
context.declare_lex(
|
||||
info.name,
|
||||
DeclarationKind::Let,
|
||||
info.offset,
|
||||
&atoms.borrow(),
|
||||
)?;
|
||||
}
|
||||
BindingKind::Const => {
|
||||
context.declare_lex(
|
||||
info.name,
|
||||
DeclarationKind::Const,
|
||||
info.offset,
|
||||
&atoms.borrow(),
|
||||
)?;
|
||||
}
|
||||
BindingKind::Class => {
|
||||
context.declare_lex(
|
||||
info.name,
|
||||
DeclarationKind::Class,
|
||||
info.offset,
|
||||
&atoms.borrow(),
|
||||
)?;
|
||||
}
|
||||
_ => {
|
||||
panic!("Unexpected binding found {:?}", info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Declare bindings to the parameter of function or catch.
|
||||
/// This method is an internal helper for EarlyErrorChecker
|
||||
fn declare_param<'alloc, T>(
|
||||
context_metadata: &ContextMetadata,
|
||||
atoms: &Rc<RefCell<SourceAtomSet<'alloc>>>,
|
||||
context: &mut T,
|
||||
from: BindingsIndex,
|
||||
to: BindingsIndex,
|
||||
) -> Result<'alloc, ()>
|
||||
where
|
||||
T: ParameterEarlyErrorsContext,
|
||||
{
|
||||
for info in context_metadata.bindings_from_to(from, to) {
|
||||
context.declare(info.name, info.offset, &atoms.borrow())?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Declare bindings to the body of lexical for-statement.
|
||||
/// This method is an internal helper for EarlyErrorChecker
|
||||
fn declare_lexical_for_body<'alloc>(
|
||||
context_metadata: &ContextMetadata,
|
||||
atoms: &Rc<RefCell<SourceAtomSet<'alloc>>>,
|
||||
context: &mut LexicalForBodyEarlyErrorsContext,
|
||||
index: BindingsIndex,
|
||||
) -> Result<'alloc, ()> {
|
||||
for info in context_metadata.bindings_from(index) {
|
||||
match info.kind {
|
||||
BindingKind::Var => {
|
||||
context.declare_var(
|
||||
info.name,
|
||||
DeclarationKind::Var,
|
||||
info.offset,
|
||||
&atoms.borrow(),
|
||||
)?;
|
||||
}
|
||||
_ => {
|
||||
panic!("Unexpected binding found {:?}", info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Declare bindings to the head of lexical for-statement.
|
||||
/// This method is an internal helper for EarlyErrorChecker
|
||||
fn declare_lexical_for_head<'alloc>(
|
||||
context_metadata: &ContextMetadata,
|
||||
atoms: &Rc<RefCell<SourceAtomSet<'alloc>>>,
|
||||
context: &mut LexicalForHeadEarlyErrorsContext,
|
||||
from: BindingsIndex,
|
||||
to: BindingsIndex,
|
||||
) -> Result<'alloc, ()> {
|
||||
for info in context_metadata.bindings_from_to(from, to) {
|
||||
match info.kind {
|
||||
BindingKind::Let => {
|
||||
context.declare_lex(
|
||||
info.name,
|
||||
DeclarationKind::Let,
|
||||
info.offset,
|
||||
&atoms.borrow(),
|
||||
)?;
|
||||
}
|
||||
BindingKind::Const => {
|
||||
context.declare_lex(
|
||||
info.name,
|
||||
DeclarationKind::Const,
|
||||
info.offset,
|
||||
&atoms.borrow(),
|
||||
)?;
|
||||
}
|
||||
_ => {
|
||||
panic!("Unexpected binding found {:?}", info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub trait EarlyErrorChecker<'alloc> {
|
||||
fn context_metadata_mut(&mut self) -> &mut ContextMetadata;
|
||||
fn context_metadata(&self) -> &ContextMetadata;
|
||||
fn atoms(&self) -> &Rc<RefCell<SourceAtomSet<'alloc>>>;
|
||||
|
||||
// Check Early Error for BindingIdentifier and note binding info to the
|
||||
// stack.
|
||||
fn on_binding_identifier(&mut self, token: &arena::Box<'alloc, Token>) -> Result<'alloc, ()> {
|
||||
let context = IdentifierEarlyErrorsContext::new();
|
||||
context.check_binding_identifier(token, &self.atoms().borrow())?;
|
||||
|
||||
let name = token.value.as_atom();
|
||||
let offset = token.loc.start;
|
||||
|
||||
if let Some(info) = self.context_metadata_mut().last_binding() {
|
||||
debug_assert!(info.offset < offset);
|
||||
}
|
||||
|
||||
self.context_metadata_mut().push_binding(BindingInfo {
|
||||
name,
|
||||
offset,
|
||||
kind: BindingKind::Unknown,
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Check Early Error for IdentifierReference.
|
||||
fn on_identifier_reference(&self, token: &arena::Box<'alloc, Token>) -> Result<'alloc, ()> {
|
||||
let context = IdentifierEarlyErrorsContext::new();
|
||||
context.check_identifier_reference(token, &self.atoms().borrow())
|
||||
}
|
||||
|
||||
// Check Early Error for LabelIdentifier and note binding info to the
|
||||
// stack
|
||||
fn on_label_identifier(&mut self, token: &arena::Box<'alloc, Token>) -> Result<'alloc, ()> {
|
||||
let context = IdentifierEarlyErrorsContext::new();
|
||||
|
||||
let name = token.value.as_atom();
|
||||
let offset = token.loc.start;
|
||||
|
||||
if let Some(info) = self.context_metadata_mut().last_binding() {
|
||||
debug_assert!(info.offset < offset);
|
||||
}
|
||||
|
||||
// If the label is attached to a continue or break statement, its label info
|
||||
// is popped from the stack. See `continue_statement` and `break_statement` for more
|
||||
// information.
|
||||
self.context_metadata_mut().push_label(LabelInfo {
|
||||
name,
|
||||
offset,
|
||||
kind: LabelKind::Other,
|
||||
});
|
||||
|
||||
context.check_label_identifier(token, &self.atoms().borrow())
|
||||
}
|
||||
|
||||
/// Check Early Error for LabelledStatement.
|
||||
/// This should be called after handling the labelled body.
|
||||
fn check_labelled_statement(
|
||||
&mut self,
|
||||
name: SourceAtomSetIndex,
|
||||
start_of_label_offset: usize,
|
||||
start_of_statement_offset: usize,
|
||||
) -> Result<'alloc, ()> {
|
||||
let label = self
|
||||
.context_metadata_mut()
|
||||
.find_label_at_offset(start_of_label_offset)
|
||||
.unwrap();
|
||||
|
||||
let context = LabelledStatementEarlyErrorsContext::new(name, label.kind);
|
||||
let next_label_index = self
|
||||
.context_metadata_mut()
|
||||
.find_first_label(start_of_statement_offset);
|
||||
for info in self.context_metadata_mut().labels_from(next_label_index) {
|
||||
context.check_duplicate_label(info.name)?;
|
||||
}
|
||||
|
||||
let break_or_continue_index = self
|
||||
.context_metadata_mut()
|
||||
.find_first_break_or_continue(start_of_label_offset);
|
||||
|
||||
check_labelled_continue_to_non_loop(
|
||||
self.context_metadata_mut(),
|
||||
context,
|
||||
break_or_continue_index,
|
||||
)?;
|
||||
|
||||
self.context_metadata_mut()
|
||||
.pop_labelled_breaks_and_continues_from_index(break_or_continue_index, name);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Static Semantics: Early Errors
|
||||
// https://tc39.es/ecma262/#sec-if-statement-static-semantics-early-errors
|
||||
// https://tc39.es/ecma262/#sec-semantics-static-semantics-early-errors
|
||||
// https://tc39.es/ecma262/#sec-with-statement-static-semantics-early-errors
|
||||
fn check_single_statement(&self, statement_start_offset: usize) -> Result<'alloc, ()> {
|
||||
// * It is a Syntax Error if IsLabelledFunction(Statement) is true.
|
||||
if is_labelled_function(self.context_metadata(), statement_start_offset) {
|
||||
return Err(ParseError::LabelledFunctionDeclInSingleStatement.into());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Check bindings in Script. This is called at the end of a script,
|
||||
// after we have noted all bindings and identified that we are in a script.
|
||||
// Any remaining bindings should be legal in this context. Any labels within this
|
||||
// context are only valid here, and can be popped.
|
||||
fn check_script_bindings(&mut self) -> Result<'alloc, ()> {
|
||||
let mut context = ScriptEarlyErrorsContext::new();
|
||||
let index = BindingsIndex { index: 0 };
|
||||
declare_script_or_function(self.context_metadata(), self.atoms(), &mut context, index)?;
|
||||
self.context_metadata_mut().pop_bindings_from(index);
|
||||
|
||||
let label_index = LabelIndex { index: 0 };
|
||||
self.context_metadata_mut().pop_labels_from(label_index);
|
||||
|
||||
check_unhandled_break_or_continue(self.context_metadata_mut(), context, 0)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Check bindings in Module. This is called at the end of a module,
|
||||
// after we have noted all bindings and identified that we are in a Module.
|
||||
// Any remaining bindings should be legal in this context. Any labels within this
|
||||
// context are only valid here, and can be popped.
|
||||
fn check_module_bindings(&mut self) -> Result<'alloc, ()> {
|
||||
let mut context = ModuleEarlyErrorsContext::new();
|
||||
let index = BindingsIndex { index: 0 };
|
||||
declare_script_or_function(self.context_metadata(), self.atoms(), &mut context, index)?;
|
||||
self.context_metadata_mut().pop_bindings_from(index);
|
||||
|
||||
let label_index = LabelIndex { index: 0 };
|
||||
self.context_metadata_mut().pop_labels_from(label_index);
|
||||
|
||||
check_unhandled_break_or_continue(self.context_metadata_mut(), context, 0)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Check bindings in function with FormalParameters.
|
||||
fn check_function_bindings(
|
||||
&mut self,
|
||||
is_simple: bool,
|
||||
start_of_param_offset: usize,
|
||||
end_of_param_offset: usize,
|
||||
) -> Result<'alloc, ()> {
|
||||
let mut param_context = if is_simple {
|
||||
FormalParametersEarlyErrorsContext::new_simple()
|
||||
} else {
|
||||
FormalParametersEarlyErrorsContext::new_non_simple()
|
||||
};
|
||||
|
||||
let param_index = self
|
||||
.context_metadata_mut()
|
||||
.find_first_binding(start_of_param_offset);
|
||||
let body_index = self
|
||||
.context_metadata_mut()
|
||||
.find_first_binding(end_of_param_offset);
|
||||
declare_param(
|
||||
self.context_metadata(),
|
||||
self.atoms(),
|
||||
&mut param_context,
|
||||
param_index,
|
||||
body_index,
|
||||
)?;
|
||||
|
||||
let mut body_context = FunctionBodyEarlyErrorsContext::new(param_context);
|
||||
declare_script_or_function(
|
||||
self.context_metadata(),
|
||||
self.atoms(),
|
||||
&mut body_context,
|
||||
body_index,
|
||||
)?;
|
||||
|
||||
check_unhandled_break_or_continue(
|
||||
self.context_metadata_mut(),
|
||||
body_context,
|
||||
end_of_param_offset,
|
||||
)?;
|
||||
|
||||
self.context_metadata_mut().pop_bindings_from(param_index);
|
||||
let label_index = self
|
||||
.context_metadata_mut()
|
||||
.find_first_label(start_of_param_offset);
|
||||
self.context_metadata_mut().pop_labels_from(label_index);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Check bindings in function with UniqueFormalParameters.
|
||||
fn check_unique_function_bindings(
|
||||
&mut self,
|
||||
start_of_param_offset: usize,
|
||||
end_of_param_offset: usize,
|
||||
) -> Result<'alloc, ()> {
|
||||
let mut param_context = UniqueFormalParametersEarlyErrorsContext::new();
|
||||
|
||||
let param_index = self
|
||||
.context_metadata_mut()
|
||||
.find_first_binding(start_of_param_offset);
|
||||
let body_index = self
|
||||
.context_metadata_mut()
|
||||
.find_first_binding(end_of_param_offset);
|
||||
declare_param(
|
||||
self.context_metadata(),
|
||||
self.atoms(),
|
||||
&mut param_context,
|
||||
param_index,
|
||||
body_index,
|
||||
)?;
|
||||
|
||||
let mut body_context = UniqueFunctionBodyEarlyErrorsContext::new(param_context);
|
||||
declare_script_or_function(
|
||||
self.context_metadata(),
|
||||
self.atoms(),
|
||||
&mut body_context,
|
||||
body_index,
|
||||
)?;
|
||||
|
||||
self.context_metadata_mut().pop_bindings_from(param_index);
|
||||
|
||||
let label_index = self
|
||||
.context_metadata_mut()
|
||||
.find_first_label(start_of_param_offset);
|
||||
self.context_metadata_mut().pop_labels_from(label_index);
|
||||
|
||||
check_unhandled_break_or_continue(
|
||||
self.context_metadata_mut(),
|
||||
body_context,
|
||||
end_of_param_offset,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Check bindings in Block.
|
||||
fn check_block_bindings(&mut self, start_of_block_offset: usize) -> Result<'alloc, ()> {
|
||||
let mut context = BlockEarlyErrorsContext::new();
|
||||
let index = self
|
||||
.context_metadata_mut()
|
||||
.find_first_binding(start_of_block_offset);
|
||||
declare_block(self.context_metadata(), self.atoms(), &mut context, index)?;
|
||||
self.context_metadata_mut().pop_lexical_bindings_from(index);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Check bindings in CaseBlock of switch-statement.
|
||||
fn check_case_block_binding(&mut self, start_of_block_offset: usize) -> Result<'alloc, ()> {
|
||||
let mut context = CaseBlockEarlyErrorsContext::new();
|
||||
|
||||
let index = self
|
||||
.context_metadata_mut()
|
||||
.find_first_binding(start_of_block_offset);
|
||||
// Check bindings in CaseBlock of switch-statement.
|
||||
declare_block(self.context_metadata(), self.atoms(), &mut context, index)?;
|
||||
self.context_metadata_mut().pop_lexical_bindings_from(index);
|
||||
|
||||
self.context_metadata_mut()
|
||||
.pop_unlabelled_breaks_from(start_of_block_offset);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Check bindings in Catch and Block.
|
||||
fn check_catch_bindings(
|
||||
&mut self,
|
||||
is_simple: bool,
|
||||
start_of_bindings_offset: usize,
|
||||
end_of_bindings_offset: usize,
|
||||
) -> Result<'alloc, ()> {
|
||||
let mut param_context = if is_simple {
|
||||
CatchParameterEarlyErrorsContext::new_with_binding_identifier()
|
||||
} else {
|
||||
CatchParameterEarlyErrorsContext::new_with_binding_pattern()
|
||||
};
|
||||
|
||||
let param_index = self.context_metadata_mut().find_first_binding(start_of_bindings_offset);
|
||||
let body_index = self.context_metadata_mut().find_first_binding(end_of_bindings_offset);
|
||||
declare_param(
|
||||
self.context_metadata(),
|
||||
self.atoms(),
|
||||
&mut param_context,
|
||||
param_index,
|
||||
body_index,
|
||||
)?;
|
||||
|
||||
let mut block_context = CatchBlockEarlyErrorsContext::new(param_context);
|
||||
declare_block(
|
||||
self.context_metadata(),
|
||||
self.atoms(),
|
||||
&mut block_context,
|
||||
body_index,
|
||||
)?;
|
||||
self.context_metadata_mut()
|
||||
.pop_lexical_bindings_from(param_index);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Check bindings in Catch with no parameter and Block.
|
||||
fn check_catch_no_param_bindings(&mut self, start_of_catch_offset: usize) -> Result<'alloc, ()> {
|
||||
let body_index = self.context_metadata_mut().find_first_binding(start_of_catch_offset);
|
||||
|
||||
let param_context = CatchParameterEarlyErrorsContext::new_with_binding_identifier();
|
||||
let mut block_context = CatchBlockEarlyErrorsContext::new(param_context);
|
||||
declare_block(
|
||||
self.context_metadata(),
|
||||
self.atoms(),
|
||||
&mut block_context,
|
||||
body_index,
|
||||
)?;
|
||||
self.context_metadata_mut()
|
||||
.pop_lexical_bindings_from(body_index);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// Check bindings in lexical for-statement.
|
||||
fn check_lexical_for_bindings(
|
||||
&mut self,
|
||||
start_of_bindings_offset: usize,
|
||||
end_of_bindings_offset: usize,
|
||||
) -> Result<'alloc, ()> {
|
||||
let mut head_context = LexicalForHeadEarlyErrorsContext::new();
|
||||
|
||||
let head_index = self.context_metadata_mut().find_first_binding(start_of_bindings_offset);
|
||||
let body_index = self.context_metadata_mut().find_first_binding(end_of_bindings_offset);
|
||||
declare_lexical_for_head(
|
||||
self.context_metadata(),
|
||||
self.atoms(),
|
||||
&mut head_context,
|
||||
head_index,
|
||||
body_index,
|
||||
)?;
|
||||
|
||||
let mut body_context = LexicalForBodyEarlyErrorsContext::new(head_context);
|
||||
declare_lexical_for_body(
|
||||
self.context_metadata(),
|
||||
self.atoms(),
|
||||
&mut body_context,
|
||||
body_index,
|
||||
)?;
|
||||
self.context_metadata_mut()
|
||||
.pop_lexical_bindings_from(head_index);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
use crate::context_stack::{ControlInfo, ControlKind};
|
||||
use crate::context_stack::{ControlInfo, ControlKind, LabelKind};
|
||||
use crate::parser_tables_generated::TerminalId;
|
||||
use crate::DeclarationKind;
|
||||
use crate::Token;
|
||||
@ -905,12 +905,12 @@ impl VarEarlyErrorsContext for LexicalForBodyEarlyErrorsContext {
|
||||
|
||||
pub struct LabelledStatementEarlyErrorsContext {
|
||||
name: SourceAtomSetIndex,
|
||||
is_loop: bool,
|
||||
kind: LabelKind,
|
||||
}
|
||||
|
||||
impl LabelledStatementEarlyErrorsContext {
|
||||
pub fn new(name: SourceAtomSetIndex, is_loop: bool) -> Self {
|
||||
Self { name, is_loop }
|
||||
pub fn new(name: SourceAtomSetIndex, kind: LabelKind) -> Self {
|
||||
Self { name, kind }
|
||||
}
|
||||
|
||||
pub fn check_duplicate_label<'alloc>(
|
||||
@ -966,7 +966,10 @@ impl LabelledStatementEarlyErrorsContext {
|
||||
// indirectly (but not crossing function boundaries), within an
|
||||
// IterationStatement.
|
||||
if let Some(name) = info.label {
|
||||
if !self.is_loop && info.kind == ControlKind::Continue && name == self.name {
|
||||
if self.kind != LabelKind::Loop
|
||||
&& info.kind == ControlKind::Continue
|
||||
&& name == self.name
|
||||
{
|
||||
return Err(ParseError::BadContinue.into());
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
mod ast_builder;
|
||||
mod context_stack;
|
||||
mod declaration_kind;
|
||||
mod early_error_checker;
|
||||
mod early_errors;
|
||||
mod error;
|
||||
mod parser_tables_generated;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1 +1 @@
|
||||
{"files":{"Cargo.toml":"2891ffd0f80fa04bddf4fd281ca7c80554bf04a65ae11ba2e729d1c4a074656b","src/builder.rs":"7ddde82d2ece70c269e4412ebb75e017fa390c75a195b64b24a38a2533a35d40","src/data.rs":"cfa80914be32e8ca3dd7b0ddc7e1f5263101353190974cc25f9a04c8645b5c78","src/frame_slot.rs":"b20c81d67c572f20d06d493b211cd3eaa0432a8294541583643b82df3af2f813","src/free_name_tracker.rs":"c29a7f7b53282233e54a28f49aa8ab90fa8f13553da39599f21ffb3a82a29867","src/lib.rs":"254ff9dd051937914225a6f96231db2c6e16fad7ff5c7a3016f82f4d3dc912c4","src/pass.rs":"fcf387ede9ed8ec496961bc68e0f9ce60a213a6553a252f0285671313336f904"},"package":null}
|
||||
{"files":{"Cargo.toml":"2891ffd0f80fa04bddf4fd281ca7c80554bf04a65ae11ba2e729d1c4a074656b","src/builder.rs":"f3a905712185d8d617ee574f5c57dc3af504a2ead1e976c072cbf66e031a5d36","src/data.rs":"71f5acf81a54a92d8ec9ec1531808a92a3a93c81e09af1a6cd27a1fd23f38a30","src/frame_slot.rs":"b20c81d67c572f20d06d493b211cd3eaa0432a8294541583643b82df3af2f813","src/free_name_tracker.rs":"c29a7f7b53282233e54a28f49aa8ab90fa8f13553da39599f21ffb3a82a29867","src/lib.rs":"254ff9dd051937914225a6f96231db2c6e16fad7ff5c7a3016f82f4d3dc912c4","src/pass.rs":"fcf387ede9ed8ec496961bc68e0f9ce60a213a6553a252f0285671313336f904"},"package":null}
|
10
third_party/rust/jsparagus-scope/src/builder.rs
vendored
10
third_party/rust/jsparagus-scope/src/builder.rs
vendored
@ -678,7 +678,7 @@ impl FunctionExpressionScopeBuilder {
|
||||
|
||||
ScopeData::Lexical(data)
|
||||
}
|
||||
None => ScopeData::AliasPrevious,
|
||||
None => ScopeData::Alias(enclosing),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -709,10 +709,10 @@ struct FunctionScopeDataSet {
|
||||
/// ScopeData::Function.
|
||||
function: ScopeData,
|
||||
|
||||
/// Either ScopeData::Var or ScopeData::AliasPrevious.
|
||||
/// Either ScopeData::Var or ScopeData::Alias.
|
||||
extra_body_var: ScopeData,
|
||||
|
||||
/// Either ScopeData::Lexical or ScopeData::AliasPrevious.
|
||||
/// Either ScopeData::Lexical or ScopeData::Alias.
|
||||
lexical: ScopeData,
|
||||
}
|
||||
|
||||
@ -1148,7 +1148,7 @@ impl FunctionParametersScopeBuilder {
|
||||
|
||||
// Step 27.d. Let varEnv be env.
|
||||
// Step 27.e. Let varEnvRec be envRec.
|
||||
ScopeData::AliasPrevious
|
||||
ScopeData::Alias(self.scope_index)
|
||||
}
|
||||
// Step 28. Else,
|
||||
else {
|
||||
@ -1253,7 +1253,7 @@ impl FunctionParametersScopeBuilder {
|
||||
|
||||
ScopeData::Lexical(data)
|
||||
} else {
|
||||
ScopeData::AliasPrevious
|
||||
ScopeData::Alias(body_scope_builder.var_scope_index)
|
||||
};
|
||||
|
||||
// Step 36. For each Parse Node f in functionsToInitialize, do
|
||||
|
11
third_party/rust/jsparagus-scope/src/data.rs
vendored
11
third_party/rust/jsparagus-scope/src/data.rs
vendored
@ -360,8 +360,9 @@ impl FunctionScopeData {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ScopeData {
|
||||
/// No scope should be generated. This is used, for example, when we see a
|
||||
/// function, and set aside a ScopeData for its lexical bindings, but upon
|
||||
/// No scope should be generated, but this scope becomes an alias to
|
||||
/// enclosing scope. This is used, for example, when we see a function,
|
||||
/// and set aside a ScopeData for its lexical bindings, but upon
|
||||
/// reaching the end of the function body, we find that there were no
|
||||
/// lexical bindings and the spec actually says not to generate a Lexical
|
||||
/// Environment when this function is called.
|
||||
@ -370,8 +371,8 @@ pub enum ScopeData {
|
||||
/// it turns out it doesn't have any bindings in it and we can optimize it
|
||||
/// away.
|
||||
///
|
||||
/// FIXME: "previous" doesn't work in some case. embed scope index instead.
|
||||
AliasPrevious,
|
||||
/// NOTE: Alias can be chained.
|
||||
Alias(ScopeIndex),
|
||||
|
||||
Global(GlobalScopeData),
|
||||
Var(VarScopeData),
|
||||
@ -515,7 +516,7 @@ impl ScopeDataMap {
|
||||
|
||||
pub fn is_alias(&mut self, index: ScopeIndex) -> bool {
|
||||
match self.scopes.get(index) {
|
||||
ScopeData::AliasPrevious => true,
|
||||
ScopeData::Alias(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
2
third_party/rust/nom/.cargo-checksum.json
vendored
2
third_party/rust/nom/.cargo-checksum.json
vendored
File diff suppressed because one or more lines are too long
101
third_party/rust/nom/.travis.yml
vendored
101
third_party/rust/nom/.travis.yml
vendored
@ -1,101 +0,0 @@
|
||||
language: rust
|
||||
# sudo is required to enable kcov to use the personality syscall
|
||||
sudo: required
|
||||
dist: trusty
|
||||
cache: cargo
|
||||
|
||||
rust:
|
||||
- nightly
|
||||
- beta
|
||||
- stable
|
||||
- 1.31.0
|
||||
|
||||
env:
|
||||
matrix:
|
||||
- FEATURES='--features "regexp regexp_macros"'
|
||||
|
||||
before_script:
|
||||
- eval git pull --rebase https://github.com/Geal/nom master
|
||||
- eval git log --pretty=oneline HEAD~5..HEAD
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- rust: nightly
|
||||
env: FEATURES='--no-default-features'
|
||||
- rust: nightly
|
||||
env: FEATURES='--no-default-features --features "alloc"'
|
||||
- rust: stable
|
||||
env: FEATURES=''
|
||||
- rust: nightly
|
||||
env: DOC_FEATURES='--features "std lexical regexp regexp_macros" --no-default-features'
|
||||
before_script:
|
||||
- export PATH=$HOME/.cargo/bin:$PATH
|
||||
script:
|
||||
- eval cargo doc --verbose $DOC_FEATURES
|
||||
- rust: nightly
|
||||
env: FEATURES=''
|
||||
before_script:
|
||||
- export PATH=$HOME/.cargo/bin:$PATH
|
||||
- cargo install cargo-update || echo "cargo-update already installed"
|
||||
- cargo install cargo-travis || echo "cargo-travis already installed"
|
||||
- cargo install-update -a
|
||||
- mkdir -p target/kcov-master
|
||||
script:
|
||||
cargo coveralls --verbose --all-features
|
||||
allow_failures:
|
||||
- rust: stable
|
||||
env: FEATURES=''
|
||||
before_script:
|
||||
- export PATH=$HOME/.cargo/bin:$PATH
|
||||
- rustup component add rustfmt-preview
|
||||
script:
|
||||
- eval cargo fmt -- --write-mode=diff
|
||||
|
||||
notifications:
|
||||
webhooks:
|
||||
urls:
|
||||
- https://webhooks.gitter.im/e/9c035a194ac4fd4cc061
|
||||
on_success: change
|
||||
on_failure: always
|
||||
on_start: false
|
||||
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- libcurl4-openssl-dev
|
||||
- libelf-dev
|
||||
- libdw-dev
|
||||
- binutils-dev
|
||||
- cmake
|
||||
sources:
|
||||
- kalakris-cmake
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- /home/travis/.cargo
|
||||
|
||||
before_cache:
|
||||
- rm -rf /home/travis/.cargo/registry
|
||||
|
||||
script:
|
||||
- eval cargo build --verbose $FEATURES
|
||||
- eval cargo test --verbose $FEATURES
|
||||
|
||||
after_success: |
|
||||
case "$TRAVIS_RUST_VERSION" in
|
||||
nightly)
|
||||
if [ "${TRAVIS_PULL_REQUEST_BRANCH:-$TRAVIS_BRANCH}" != "master" ]; then
|
||||
git fetch &&
|
||||
git checkout master &&
|
||||
cargo bench --verbose
|
||||
fi
|
||||
|
||||
if [ "$FEATURES" == '--features "regexp regexp_macros"' ]; then
|
||||
cargo bench --verbose
|
||||
fi
|
||||
;;
|
||||
|
||||
*)
|
||||
;;
|
||||
esac
|
Loading…
Reference in New Issue
Block a user