Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error handling in environment #659

Merged
merged 8 commits into from
Dec 27, 2020
Merged

Error handling in environment #659

merged 8 commits into from
Dec 27, 2020

Conversation

54k1
Copy link
Contributor

@54k1 54k1 commented Aug 23, 2020

This PR introduces error handling in environment.
This Pull Request fixes/closes #622.

  • Environment methods (which are prone to errors) now return a Result<X, ErrorKind>, where X is either () or Value.
  • ErrorKind enum gives a hint to the other modules about the Error. According to the spec, there only are ReferenceError and TypeError generated from environment. And so there only are two fields in the ErrorKind enum.
  • Since ErrorKind is returned, any code using environment must map data of type ErrorKind to type Error. This is achieved using to_error method. For instance, env.get_this_binding().map_err(|e| e.to_error(ctx))?;
  • panic!s and assert!s that are present in some environment methods correspond to assert statements in the spec. Some things have to be guaranteed (such as prior existence of a binding) and if they fail, they may lead to panic!.

@codecov
Copy link

codecov bot commented Aug 23, 2020

Codecov Report

Merging #659 (704f942) into master (015c11e) will decrease coverage by 0.16%.
The diff coverage is 50.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #659      +/-   ##
==========================================
- Coverage   59.97%   59.80%   -0.17%     
==========================================
  Files         166      167       +1     
  Lines       10851    10982     +131     
==========================================
+ Hits         6508     6568      +60     
- Misses       4343     4414      +71     
Impacted Files Coverage Δ
boa/src/environment/global_environment_record.rs 22.80% <14.70%> (-5.15%) ⬇️
boa/src/environment/object_environment_record.rs 21.05% <25.00%> (-2.03%) ⬇️
boa/src/syntax/ast/node/mod.rs 46.92% <25.00%> (-1.11%) ⬇️
boa/src/environment/function_environment_record.rs 33.33% <32.69%> (-1.78%) ⬇️
.../src/environment/declarative_environment_record.rs 39.32% <37.83%> (+0.65%) ⬆️
boa/src/environment/mod.rs 50.00% <50.00%> (ø)
boa/src/value/operations.rs 48.58% <50.00%> (ø)
...a/src/syntax/ast/node/iteration/for_of_loop/mod.rs 58.97% <63.15%> (+5.36%) ⬆️
boa/src/syntax/ast/node/operator/bin_op/mod.rs 72.41% <66.66%> (-1.28%) ⬇️
boa/src/environment/lexical_environment.rs 69.23% <68.18%> (-3.11%) ⬇️
... and 13 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 015c11e...704f942. Read the comment docs.

Copy link
Member

@HalidOdat HalidOdat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good! we should add some test cases where a panic was being caused.

@HalidOdat HalidOdat added bug Something isn't working enhancement New feature or request labels Aug 28, 2020
@54k1
Copy link
Contributor Author

54k1 commented Aug 29, 2020

@HalidOdat I think it would be better to add tests after there's support for strict mode added (After that, some implementation in exec(Assignment Operator) needs to be fixed).

  • The Assignment operator currently creates a new binding in the current scope if no binding was found in the environment stack.
    This is erroneous since in functions, any assignment without a prior declaration must result in addition of new entry to the global scope (in non-strict mode). In strict mode however, it must throw a ReferenceError.

Current behaviour: Assignments without prior declarations are added to the function scope.

>> function f () {
x = 12;
}
>> f()
>> x // Must be visible in global
Uncaught: "ReferenceError": "x is not defined"

Correct behaviour:

>> function f () {
    x = 12;
}
>> f()
undefined
>> x
12
// Ok
>> function f () {
    'use strict';
    x = 12;
}
>> f() // Can't do this in strict mode
Uncaught ReferenceError: assignment to undeclared variable x
  • There's also another issue which is that the following must throw a SyntaxError.
let x = 12;
const x = 12;

What do you think?

@HalidOdat HalidOdat self-requested a review September 1, 2020 14:08
@54k1
Copy link
Contributor Author

54k1 commented Oct 2, 2020

I'm taking a re-look at this.

@Razican
Copy link
Member

Razican commented Oct 14, 2020

Hi! It seems this requires a rebase :) what is the state of the PR?

Copy link
Member

@Razican Razican left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking very good. The CI error is unerlated, and seems to be related to the new Test262 conformance comments.

It should be writing this comment, but it's failing:

Test262 conformance changes:

Test result master count PR count difference
Total 78,493 78,493 0
Passed 19,596 19,600 +4
Ignored 15,585 15,585 0
Failed 43,312 43,308 -4
Panics 447 413 -34
Conformance 24.97 24.97 +0.01%

boa/src/builtins/function/mod.rs Outdated Show resolved Hide resolved
boa/src/environment/declarative_environment_record.rs Outdated Show resolved Hide resolved
boa/src/environment/function_environment_record.rs Outdated Show resolved Hide resolved
Comment on lines 12 to 13
ReferenceError(String),
TypeError(String),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we could use a Box<str> here to reduce a bit the memory footprint.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Error messages are however dynamic (depend on variable names, etc.) which is why we had used a String earlier. Could you please elaborate a bit more?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, a String contains a pointer, a length and a capacity. The capacity indicates how many bytes are allocated for the string, while the length indicates how many are in use. This is useful to grow the string without needing to allocate, but once we know that the String will not change anymore, it's better to drop the excess capacity and have just a pointer with length, a Box<str>.

This can be constructed using String::into_boxed_str() you can find more information on the standard library documentation :).

Copy link
Contributor Author

@54k1 54k1 Oct 21, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Razican Finally, when we are ready to construct the actual Error object, the API currently expects a template which can convert to a String as an argument (for the message).

pub fn construct_reference_error<M> (&mut self, msg: M) -> Value
where
    M: Into<String> {
...
}

Would a Box<str> be useful in this case?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most (if not all) of the things that can be converted to a String can be converted to a Box<str>, so changing it to Into<Box<str>> could make the trick.

boa/src/object/gcobject.rs Outdated Show resolved Hide resolved
boa/src/syntax/ast/node/identifier/mod.rs Outdated Show resolved Hide resolved
@Razican Razican added this to the v0.11.0 milestone Oct 20, 2020
@Razican Razican mentioned this pull request Oct 21, 2020
@54k1 54k1 marked this pull request as ready for review October 23, 2020 04:40
Copy link
Member

@HalidOdat HalidOdat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me! :)

@Razican
Copy link
Member

Razican commented Oct 26, 2020

I would spect this to be able to remove some of the panics listed in #817. Namely:

Identifier x has already been declared #659, count: 58 Example:
thread 'main' panicked at 'Identifier x has already been declared', boa/src/environment/function_environment_record.rs:94:13

and

Binding already exists! #659, count: 30 Example:
thread 'main' panicked at 'Binding already exists!', boa/src/environment/global_environment_record.rs:107:13

and

TypeError: Cannot mutate an immutable binding x #659, count: 2 Example:
thread 'main' panicked at 'TypeError: Cannot mutate an immutable binding x', boa/src/environment/declarative_environment_record.rs:117:13

and

thread 'main' panicked at 'TypeError: Cannot mutate an immutable binding i', boa/src/environment/declarative_environment_record.rs:117:13

But I think they still exist in this branch, right?

@Razican
Copy link
Member

Razican commented Dec 11, 2020

Hi @54k1, did you have the chance to review why are those environment panics still happening?

Copy link
Member

@Razican Razican left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me. Only needs a cargo fmt.

@Razican Razican merged commit 7b103a5 into boa-dev:master Dec 27, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Assignment to const results in panic
3 participants