SPDX License Identifiers are a more compact / standardized
way of representing file license information.
See: https://spdx.dev/resources/use/#identifiers
This was done with the `ambr` search and replace tool.
ambr --no-parent-ignore --key-from-file --rep-from-file key.txt rep.txt *
This was failing to take two things into account:
- When constructing a PropertyName from a value, it won't automatically
convert to Type::Number for something like string "0", even though
that's how things work internally, since indexed properties are stored
separately. This will be improved in a future patch, it's a footgun
and should happen automatically.
- Those can't be looked up on the shape, we have to go through the
indexed properties instead.
Additionally it now operates on the shape or indexed properties directly
as define_property() was overly strict and would throw if a property was
already non-configurable.
Fixes#6469.
This would crash on an undefined match (no match), since the matched
result was assumed to be a string (such as on discord.com). The spec
suggests converting it to a string as well:
https://tc39.es/ecma262/#sec-regexp.prototype-@@replace (14#c)
This should allow creating intrusive lists that have smart pointers,
while remaining free (compared to the impl before this commit) when
holding raw pointers :^)
As a sidenote, this also adds a `RawPtr<T>` type, which is just
equivalent to `T*`.
Note that this does not actually use such functionality, but is only
expected to pave the way for #6369, to replace NonnullRefPtrVector<T>
with intrusive lists.
As it is with zero-cost things, this makes the interface a bit less nice
by requiring the type name of what an `IntrusiveListNode` holds (and
optionally its container, if not RawPtr), and also requiring the type of
the container (normally `RawPtr`) on the `IntrusiveList` instance.
This flag warns on classes which have `virtual` functions but do not
have a `virtual` destructor.
This patch adds both the flag and missing destructors. The access level
of the destructors was determined by a two rules of thumb:
1. A destructor should have a similar or lower access level to that of a
constructor.
2. Having a `private` destructor implicitly deletes the default
constructor, which is probably undesirable for "interface" types
(classes with only virtual functions and no data).
In short, most of the added destructors are `protected`, unless the
compiler complained about access.
This has the nice side effect of giving us a decent error message for
something like undefined.foo() - another useless "ToObject on null or
undefined" gone. :^)
Also turn the various ternary operators into two separate if branches,
they don't really share that much.
Fixes#6325
The JavaScript on the HTML Spec site that caused the crash is:
window.location.hash.substr(1)
Of course, window.location.hash can be the empty string. The spec allows
for calling substr(1) on an empty string, but our partial implementation
wasn't handling it properly.
Otherwise these will get their name/default message from the Error
prototype, and as a result would always just say "Error" in error
messages, not the specific type.
Something I missed in da177c6, now with tests. :^)
Sometimes we just want to set m_exception to some value we stored
previously, without really "throwing" it again - that's what
set_exception() does now. Since we have clear_exception(), it does take
a reference, i.e. you don't set_exception(nullptr). For consistency I
updated throw_exception() to do the same.
Previously we would always return the result of executing the finalizer,
however the spec dictates the finalizer result must only be returned for
a non-normal completion.
I added some more comments along the way, which should make it more
clear what's going on - the unwinding and exception flow isn't super
straightforward here.
The previous handling of the name and message properties specifically
was breaking websites that created their own error types and relied on
the error prototype working correctly - not assuming an JS::Error this
object, that is.
The way it works now, and it is supposed to work, is:
- Error.prototype.name and Error.prototype.message just have initial
string values and are no longer getters/setters
- When constructing an error with a message, we create a regular
property on the newly created object, so a lookup of the message
property will either get it from the object directly or go though the
prototype chain
- Internal m_name/m_message properties are no longer needed and removed
This makes printing errors slightly more complicated, as we can no
longer rely on the (safe) internal properties, and cannot trust a
property lookup either - get_without_side_effects() is used to solve
this, it's not perfect but something we can revisit later.
I did some refactoring along the way, there was some really old stuff in
there - accessing vm.call_frame().arguments[0] is not something we (have
to) do anymore :^)
Fixes#6245.
Similar to Value::to_string_without_side_effects() this is mostly a
regular object property lookup, but with the guarantee that it will be
side-effect free, i.e. no accessors or native property functions will
be called. This is needed when we want to access user-controlled object
properties for debug logging, for example. The specific use case will be
error objects which will soon no longer have internal name/message
properties, so we need to guarantee that printing an error, which may
already be the result of an exception, won't blow up in our face :^)
This fixes two cases of indexed access (array holes, out-of-bounds
string object access) where we would not follow the prototype chain and
incorrectly return undefined:
// Should be "a", returned undefined
Object.setPrototypeOf([,], ["a"])[0]
// Should be "a", returned undefined
Object.setPrototypeOf(new String(""), new String("a"))[0]
The actual fix is simple, instead of returning early if the requested
index is past the string's length or within the indexed properties size
but has no value, we just continue the prototype chain traversal and get
correct behaviour from that.
Otherwise the GC won't be able to keep track of the stored values
and they may suddenly disappear from underneath us, thinking
they're not in use.
Fixes a crash when going to the Bootstrap website, where the first
replace call in jQuery caused a jump to a bogus address.
This commit makes the user-facing StdLibExtras templates and utilities
arguably more nice-looking by removing the need to reach into the
wrapper structs generated by them to get the value/type needed.
The C++ standard library had to invent `_v` and `_t` variants (likely
because of backwards compat), but we don't need to cater to any codebase
except our own, so might as well have good things for free. :^)
This implements the missing step 6a of 14.7.5.6 ForIn/OfHeadEvaluation:
a. If exprValue is undefined or null, then
i. Return Completion { [[Type]]: break, [[Value]]: empty, [[Target]]: empty }.
In other words, this should just do nothing instead of throwing during
the undefined to object coercion:
for (const x in undefined);
This replaces the current 'function plus boolean indicating the type'
API, which makes it easier to set both getter and setter at once.
This was already possible before but required two calls of this
function, which wasn't intuitive:
define_accessor(name, getter, true, ...);
define_accessor(name, setter, false, ...);
Which now becomes:
define_accessor(name, getter, setter, ...);