This PR proposes changes to existing test262 tests to allow them to pass under Hardened JavaScript (see Secure ECMAScript proposal and Hardened JavaScript). Moddable uses Hardened JavaScript for JavaScript runtimes on resource constrained embedded devices, including those targeted by ECMA-419.
The changes fall into four groups:
1. Replace use of new Date() with new Date(1970). Scripts running inside a Compartment cannot retrieve the current time, so new Date() throws but new Date(1970) succeeds. Very few tests need the current time, but instead simply need a Date instance.
2. Use Object.defineProperty instead of setting existing built-in properties directly, such as toString and toValue. In Hardened JavaScript, prototypes of built-in objects are frozen. Consequently, setting properties of an instance that exist on the prototype throw (Hardened JavaScript is always in strict mode).
3. Eliminate use of Math.random(). Scripts running inside a Compartment cannot generate random numbers. One test identified so far uses Math.random() in a way that can easily be replaced with a counter.
4. Narrow the scope of exception tests. Consider the following
assert.throws(TypeError, () => {
var s1 = new Date();
s1.toString = Boolean.prototype.toString;
s1.toString();
});
This test passes, but only because new Date() fails by throwing a TypeError. If the invocation of the Date constructor is resolved by (1) above, then the assignment to toString fails as per (2) above. The script should be modified as below to ensure that assert.throws only tests the intended statement, s1.toString(). The modified script tests the intended functionality and passes under Hardened JavaScript
var s1 = new Date(1970);
Object.defineProperty(s1, "toString", {
value: Boolean.prototype.toString
});
assert.throws(TypeError, () => {
s1.toString();
});
This is an initial PR to begin the process of adapting test262 for use with Hardened JavaScript. Further changes are expected, with the vast majority likely to fall into the four groups described above.
Thank you to gibson042, kriskowal, and erights for their advice on this work.
Two issues:
1. There was a typo, the first `gen` should have been `genFn`.
2. And the last `toString` result should be `'[object Generator]'`,
because `Object.getPrototypeOf(gen) == genFn.prototype`. And the
`@@toStringTag` property of `genFn.prototype` is inherited from
`Generator.prototype[@@toStringTag]`.
That also means the "iterator-helpers" flag isn't needed for this test.
drop:
property descriptor
name
length
[[Prototype]]
is a function
is not constructible
result instanceof Iterator
limit is given a non-primitive that needs to be converted to a number
through valueOf
through toString (array)
limit coercion to number throws
limit converts to NaN
same as limit not supplied
limit behaves properly
limit < number of values
limit = number of values
limit > number of values
gets the next method from the underlying iterator only once
underlying iterator has throwing next getter
underlying iterator next throws when advancing past dropped items
underlying iterator is advanced after calling drop
underlying iterator is closed after calling drop
underlying iterator is already closed
underlying iterator next returns non-object
underlying iterator next returns object with throwing done/value getters
underlying iterator return is never called when result iterator is closed
every:
property descriptor
name
length
[[Prototype]]
is a function
is callable
is not constructible
result is a Boolean
predicate is non-callable
iterator already exhausted
called on non-object
called on object with "next" method
called on object with non-callable "next" method
predicate returns non-Boolean
predicate returns truthy for all iterated values
returns true
predicate returns truthy for some iterated values but then falsey for at least one iterated value
returns false
iteration stops
iterator is closed
predicate returns falsey immediately
returns false
iteration stops
iterator is closed
predicate throws
every throws
iterator is closed
predicate throws then iterator close also throws
predicate this value is undefined
predicate is passed the yielded value as the first parameter and a counter as second parameter
gets the next method from the iterator only once
iterator has throwing next getter
iterator has throwing return getter
iterator next throws
iterator return throws
iterator next returns non-object
iterator next returns object with throwing done/value getters
Co-authored-by: Michael Ficarra <mficarra@shapesecurity.com>
Co-authored-by: Jordan Harband <ljharb@gmail.com>
While we're at it, use assert() instead of assert.sameValue() for brevity,
if we are not specifically testing that the return value of hasOwnProperty
is the value true or false; and add more informative assertion messages to
help with debugging.
In some cases, the Object.hasOwnProperty.call could be replaced with
verifyProperty(), if the property descriptor was also being verified at
the same time.
This fixes some tests that were faulty to begin with: a common mistake was
Object.hasOwnProperty(obj, prop) which is probably going to return false
when that's not what you want.
The only instances left of `Object.hasOwnProperty` are one regression test
in implementation-contributed which I can't tell if it was intentionally
needed to trigger the regression, and a few instances of
`Object.hasOwnProperty('prototype')` which would defeat the purpose to
convert into `Object.prototype.hasOwnProperty.call(Object, 'prototype')`
form.
Closes: #3524
Includes key should use flow notation to be able parsed easier
as suggested in https://github.com/tc39/test262/issues/1997
Added this check to the linting script and updated tests accordingly.
A number of tests were found to be duplicative based on an analysis of
file contents (included below). Eliminate the duplication by removing
the version of each test with less precise metadata. In cases where this
removal could technically be considered a reduction in coverage,
preserve the verification of additional semantics in the remaining test.
$ git grep -El 'new\s+\w+.prototype' | sed 's/[^\/]\+$//g' | sort | uniq -c | grep -vE '^\s+1 ' | awk '{print $2}' | xargs grep -Elr 'new\s+\w+.prototype'
test/built-ins/Array/prototype/join/S15.4.4.5_A6.7.js
test/built-ins/Array/prototype/join/not-a-constructor.js
test/built-ins/Array/prototype/pop/not-a-constructor.js
test/built-ins/Array/prototype/pop/S15.4.4.6_A5.7.js
test/built-ins/Array/prototype/push/S15.4.4.7_A6.7.js
test/built-ins/Array/prototype/push/not-a-constructor.js
test/built-ins/Array/prototype/shift/not-a-constructor.js
test/built-ins/Array/prototype/shift/S15.4.4.9_A5.7.js
test/built-ins/Array/prototype/slice/not-a-constructor.js
test/built-ins/Array/prototype/slice/S15.4.4.10_A5.7.js
test/built-ins/Array/prototype/sort/not-a-constructor.js
test/built-ins/Array/prototype/sort/S15.4.4.11_A7.7.js
test/built-ins/Array/prototype/splice/S15.4.4.12_A5.7.js
test/built-ins/Array/prototype/splice/not-a-constructor.js
test/built-ins/Array/prototype/toLocaleString/S15.4.4.3_A4.7.js
test/built-ins/Array/prototype/toLocaleString/not-a-constructor.js
test/built-ins/Array/prototype/toString/S15.4.4.2_A4.7.js
test/built-ins/Array/prototype/toString/not-a-constructor.js
test/built-ins/Array/prototype/unshift/S15.4.4.13_A5.7.js
test/built-ins/Array/prototype/unshift/not-a-constructor.js
test/built-ins/Function/prototype/apply/S15.3.4.3_A8_T1.js
test/built-ins/Function/prototype/apply/S15.3.4.3_A8_T2.js
test/built-ins/Function/prototype/apply/not-a-constructor.js
test/built-ins/Function/prototype/call/not-a-constructor.js
test/built-ins/Function/prototype/call/S15.3.4.4_A7_T2.js
test/built-ins/Function/prototype/call/S15.3.4.4_A7_T1.js
test/built-ins/Function/prototype/toString/S15.3.4.2_A7.js
test/built-ins/Function/prototype/toString/not-a-constructor.js
test/built-ins/Object/prototype/hasOwnProperty/S15.2.4.5_A7.js
test/built-ins/Object/prototype/hasOwnProperty/not-a-constructor.js
test/built-ins/Object/prototype/propertyIsEnumerable/not-a-constructor.js
test/built-ins/Object/prototype/propertyIsEnumerable/S15.2.4.7_A7.js
test/built-ins/Object/prototype/toLocaleString/S15.2.4.3_A7.js
test/built-ins/Object/prototype/toLocaleString/not-a-constructor.js
test/built-ins/Object/prototype/toString/not-a-constructor.js
test/built-ins/Object/prototype/toString/not-ctor.js
test/built-ins/Object/prototype/valueOf/not-a-constructor.js
test/built-ins/Object/prototype/valueOf/S15.2.4.4_A7.js
The `arrayContains` function has a number of deficiencies which make it
inappropriate for Test262:
- It apparently isn't very useful: despite being available for over 7
years, fewer than ten tests use it
- It's misleading: its documentation reads, "Verify that a subArray is
contained within an array." In reality, it only verifies that all the
elements of one array are present in another--order does not matter.
- It's not ergonomic for test authors: it has been misused to create
tests that were prone to false positives [1]
- It's not ergonomic for implementers: ostensibly designed for use with
`assert`, the failure messages produced by tests that use it do not
necessarily have very much context
All code in the "harness" directory adds to the total amount of
project-specific information which contributors are expected to to
learn. In light of the above deficiencies, the burden of this particular
harness file is unjustified.
Remove the harness file and its associated tests. Update the tests which
depend on it to express their expectations using alternate methods, and
strengthen the tests to assert element order wherever appropriate.
[1] https://github.com/tc39/test262/pull/3289
This reverts commit b690cb67be, reversing
changes made to 50dd431dff. This is
necessary because the reverted changeset reduced coverage by an unknown
extent.
* Add tests for Object.hasOwn
* Update test/built-ins/Object/hasOwn/length.js
Co-authored-by: Jordan Harband <ljharb@gmail.com>
* Update test/built-ins/Object/hasOwn/name.js
Co-authored-by: Jordan Harband <ljharb@gmail.com>
* Fixup comments for Object.hasOwn
* Add Object.hasOwn descriptor test
* use assert.sameValue with true instead of assert()
* remove extra semicolons
* Remove old $ERROR style tests from hasown
* Fix thrown error type in hasown tests
* Fix incorrect test cases
Co-authored-by: Jordan Harband <ljharb@gmail.com>
A quite popular solution for encrypting files on Linux,
[eCryptfs](https://wiki.archlinux.org/index.php/ECryptfs), can't handle
filenames longer than 143 characters when filename encryption is enabled. It
just so happens that the name of this file was 144 characters long, which makes
pulling the repository to an encrypted folder fail.