mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-09 09:18:42 +09:00
Merge remote-tracking branch 'origin/master' into custom
This commit is contained in:
commit
2b48a6c6ee
48 changed files with 1596 additions and 1006 deletions
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<blocklist lastupdate="1534840140000"
|
||||
<blocklist lastupdate="1554898538000"
|
||||
xmlns="http://www.mozilla.org/2006/addons-blocklist">
|
||||
<emItems>
|
||||
<emItem blockID="i545" id="superlrcs@svenyor.net">
|
||||
|
|
@ -2524,6 +2524,11 @@ xmlns="http://www.mozilla.org/2006/addons-blocklist">
|
|||
</versionRange>
|
||||
<prefs></prefs>
|
||||
</emItem>
|
||||
<emItem blockID="pm114" id="jid1-KKzOGWgsW3Ao4Q@jetpack">
|
||||
<versionRange minVersion="2.9.9" maxVersion="2.9.9" severity="3">
|
||||
</versionRange>
|
||||
<prefs></prefs>
|
||||
</emItem>
|
||||
</emItems>
|
||||
<pluginItems>
|
||||
<pluginItem blockID="p26">
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ var inputTests = [
|
|||
{
|
||||
input: "(function() { return 42; })",
|
||||
output: "function ()",
|
||||
printOutput: "function () { return 42; }",
|
||||
printOutput: "function() { return 42; }",
|
||||
suppressClick: true
|
||||
},
|
||||
|
||||
|
|
@ -40,7 +40,7 @@ var inputTests = [
|
|||
{
|
||||
input: "testobj1.testfn2",
|
||||
output: "function testfn2()",
|
||||
printOutput: "function () { return 42; }",
|
||||
printOutput: "function() { return 42; }",
|
||||
suppressClick: true
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -29,12 +29,12 @@ function run_test_with_server(server, cb) {
|
|||
addSources(debuggee);
|
||||
|
||||
threadClient.getSources(Task.async(function* (res) {
|
||||
do_check_true(res.sources.length === 3, "3 sources exist");
|
||||
do_check_eq(res.sources.length, 3, "3 sources exist");
|
||||
|
||||
yield threadClient.reconfigure({ useSourceMaps: false });
|
||||
|
||||
threadClient.getSources(function(res) {
|
||||
do_check_true(res.sources.length === 1, "1 source exist");
|
||||
do_check_eq(res.sources.length, 1, "1 source exist");
|
||||
client.close().then(cb);
|
||||
});
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -1,10 +1,30 @@
|
|||
# Contributor Code of Conduct
|
||||
|
||||
This code of conduct is intended to lay down the basis on which we, as a community of developers and maintainers, work with each other and with others outside of the community. As always when dealing with groups of people from many different backgrounds, there are no hard and fast rules here, and the intention is not to lay down any sort of restrictive frame to work in, but rather to clarify how we (prefer to) approach each other when working together as volunteers/professionals to improve our respective projects, products and life.
|
||||
# Community Code of Conduct
|
||||
|
||||
This code of conduct is intended to lay down the basis on which we, as a community of developers, maintainers and users, work with each other and with others outside of the community. As always when dealing with groups of people from many different backgrounds, there are no hard and fast rules here, and the intention is not to lay down any sort of restrictive frame to work in, but rather to clarify how we (prefer to) approach each other when working together as volunteers/professionals to improve our respective projects, products and life.
|
||||
|
||||
## Our Goal with this Code of Conduct
|
||||
|
||||
We, as contributors and maintainers, aim to create a _focused but welcoming_ environment for others; collaboration, acceptance and respect are the cornerstones upon which we must build our community, otherwise there is no future for it. As such, we want to keep participation in our project and community free of harassment. We therefore ask of everyone, new contributors and long-standing members alike, to be accepting of others regardless of their age, ethnicity, level of experience, nationality, personal appearance, race, religion, or sexual orientation. None of these (and alike) attributes should influence how we work together in this project, and should not be grounds to judge or dismiss work done.
|
||||
We, as contributors and maintainers, aim to create a _focused but welcoming_ environment for others; collaboration, acceptance and respect are the cornerstones upon which we must build our community, otherwise there is no future for it. As such, we want to ensure smooth communication and keep participation in our project and community free of harassment. We therefore ask of everyone, new contributors and long-standing members alike, to be accepting of others regardless of their age, ethnicity, level of experience, nationality, personal appearance, race, religion, or sexual orientation. None of these (and alike) attributes should influence how we work together in this project, and should not be grounds to judge or dismiss work done.
|
||||
|
||||
## Community of adults, language, and expected tolerance
|
||||
|
||||
To achieve the required level of focus needed, Our community as a whole targets exclusively **adult** participants with a common level of tolerance. This means that the expected conduct and tolerance levels should be fitting the average adult mindset and all participants in the community are assumed to be of adult age or having the mental capacity of an adult.
|
||||
|
||||
When dealing with others in the community, please mind your language use. Try to avoid common curse words or blasphemous expressions. Using strong language is fine, but excessive use of coarse language is frowned upon. Although everyone is assumed to be of adult age (see previous point), and you may be upset about something, you're kindly requested to keep your use of language under control.
|
||||
|
||||
Please keep in mind that the community is made up of people from all walks of life. You are asked to show a reasonable level of tolerance towards other community members, even if their method of approach is different than what you are used to or not the way you would approach others. Many computer software developers are very direct in their approaches or replies because their profession requires them to be focused and efficient in communication; our community has a larger than average percentage of developers among their ranks so you should expect more direct and "things as they are" responses in communication than you might expect in other communities. Be tolerant of this and try to follow instructions if they are given!
|
||||
Conversely, try to keep in mind that other community members may not have the same level of computer skill you do and may need more guidance than you can provide. In that case, please forward the user(s) to the Pale Moon forum in a kind manner or (if already there) step back and excuse yourself and ask someone else to provide further assistance in lieu of getting upset or frustrated.
|
||||
|
||||
Our community is primarily using English as a communication language. Please, at all times, use English when creating tracker issues or asking something of developers. The only exception is the foreign language boards on the forum where you can communicate in non-English languages with other community members to get assistance or discuss things, and of course private communication can be in any language you wish.
|
||||
|
||||
Please do not try to unnecessarily mask your identity. We are all people here, with personalities and identities. It is much easier to relate to and assist someone who actually tries to approach others with a personal identity than someone who goes at length to mask themselves. None of the topics in our community should be personally or ideologically sensitive, so there will be no need to hide/cloak/mask yourself.
|
||||
|
||||
Please do not start discussions about politics, religion, or other touchy subjects that are not necessarily related to the platform and its applications (off-topic) and can easily lead to an very unwelcome atmosphere. Although enforcing of this point will be done leniently, you are asked to apply common sense and stop a particular line of conversation if it gets too heated or opinionated for the community's overall atmosphere. If you want to continue an off-topic or in-depth discussion with someone about such topics, please take it to private chat/channels!
|
||||
|
||||
If your background, religion, upbringing or other social factors make you more sensitive than average in terms of social interaction, imagery and/or language use, and if you easily take offense or are prone to moral outrage over opinions of others, then please understand that this community may possibly not be a good match for you or require you to put in extra effort to be a content member. You should consider this before you decide to join the community in that case, and understand it may require effort to adjust to our average level of tolerance.
|
||||
|
||||
Of course, it should be clear that your participation in our community is at all times one of your own free will. You may leave at any time you wish, for any reason or no reason at all. We do, however, ask of you in that case that no matter the reason, you treat the community you are leaving with respect and honor the choices made for and in it, and do not externalize your grievances with the community as a whole or any specific members in it. If you feel a compelling need to do so (i.e. to go on a "ragequit crusade") then please consider first escalating this to the owner to work things out as adults in private before making a potentially self-damaging mess of things.
|
||||
|
||||
## Examples of acceptable and unacceptable behavior
|
||||
|
||||
|
|
@ -13,9 +33,10 @@ Please note that these lists are examples and not exhaustive. If you have any do
|
|||
Examples of behavior that helps create a positive working environment:
|
||||
|
||||
* Using friendly, neutral and welcoming language.
|
||||
* Being tolerant to the occasional strong language expression and not taking offense at the drop of a hat.
|
||||
* Being clear in your descriptions and not assuming the reader has any sort of prior knowledge of what you are talking about.
|
||||
* Being courteous (use "please" when you ask something of someone).
|
||||
* Being respectful of differing viewpoints and experiences.
|
||||
* Being courteous (use "please" when you ask someone to do something for you).
|
||||
* Being respectful of differing viewpoints, backgrounds and experiences.
|
||||
* Gracefully accepting constructive criticism, even if you disagree with such criticism.
|
||||
* Similarly, accepting that someone may not act on criticism given.
|
||||
* Focusing on what is best for the community and its projects instead of individuals.
|
||||
|
|
@ -25,7 +46,8 @@ Examples of unacceptable behavior:
|
|||
|
||||
* Unwelcome personal attention or advances (sexual or otherwise). If someone asks you to stop approaching them, please respect that.
|
||||
* Displaying disproportionate levels of moral outrage and offense, especially when in response to someone's opinion.
|
||||
* Bullying, trolling, insulting/derogatory comments, and personal or political attacks.
|
||||
* Bullying, trolling, uncalled-for insulting/derogatory comments, and personal or political attacks.
|
||||
* Being disruptive to ongoing discussions (e.g. by purposefully making a technical discussion into a sociopolitical one or trying to derail topical discussions).
|
||||
* Public or private harassment of other community members/contributors.
|
||||
* Publishing others' personal/private information, such as a physical or electronic address, without explicit permission.
|
||||
* Other conduct which could reasonably be considered inappropriate in a professional/workplace setting.
|
||||
|
|
@ -34,7 +56,7 @@ Examples of unacceptable behavior:
|
|||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and above all fair corrective action in response to instances of unacceptable behavior.
|
||||
|
||||
Corrective action: Project staff has the right and responsibility to evaluate, and if necessary to remove, edit, or reject any comments, repository commits, code changes, wiki edits, issues or issue comments, and other contributions that are not aligned with this Code of Conduct or the community's or projects' best interests, or to ban (temporarily or permanently) any contributor, community member or maintainer for other behaviors that they deem inappropriate, threatening, offensive, or harmful. In cases where there is no clear and definitive breach of rules or common sense, it is expected that staff members consult with project leadership before bans are issued to discuss the severity and intended action.
|
||||
Corrective action: Project staff has the right and responsibility to evaluate, and if necessary to remove, edit, or reject any comments, repository commits, code changes, wiki edits, issues or issue comments, and other contributions that are not aligned with this Code of Conduct or the community's or projects' best interests, or to ban (temporarily or permanently) any contributor, community member or maintainer for other behaviors that they deem inappropriate, threatening, disproportionately offensive, or harmful. In cases where there is no clear and definitive breach of rules or common sense, it is expected that staff members consult with project leadership before bans are issued to discuss the severity and intended action.
|
||||
|
||||
## Applicability
|
||||
|
||||
|
|
@ -42,9 +64,9 @@ This Code of Conduct applies within project spaces (forum, website, IRC, reposit
|
|||
|
||||
## Enforcing this Code of Conduct
|
||||
|
||||
We expect our community to apply a good measure of self-regulation when it comes to the conduct displayed by its members. We believe that any community of adults is capable of applying the concepts of common sense, common decency and common courtesy to interactions between its members.
|
||||
That said, there are always exception situations possible where things need to be escalated, which is where this section comes into play.
|
||||
Incidents involving abusive, harassing, or otherwise unacceptable behavior that need to be escalated for resolution may be reported by contacting the project owner at moonchild@palemoon.org. The project owner will then review and investigate all complaints and related communication of the case, and will respond in a way that they deem appropriate for the circumstances.
|
||||
**We expect our community to apply a good measure of self-regulation when it comes to the conduct displayed by its members. We believe that any community of adults is capable of applying the concepts of common sense, common decency and common courtesy to interactions between its members.**
|
||||
That said, there are always exceptional situations possible where things need to be escalated, which is where this section comes into play.
|
||||
Incidents involving abusive, harassing, or otherwise unacceptable behavior that need to be escalated for resolution may be reported by contacting the project owner at moonchild@palemoon.org. The project owner will then review and investigate all complaints and related communication of the case, and will respond in a way that they deem appropriate for the circumstances. It is imperative that any such reports are complete (nothing left out), true to fact, and presented in a coherent fashion.
|
||||
|
||||
## Confidentiality
|
||||
|
||||
|
|
|
|||
|
|
@ -9,11 +9,13 @@
|
|||
#include "mozilla/ArrayUtils.h"
|
||||
|
||||
#include "jscntxt.h"
|
||||
#include "jsstr.h"
|
||||
|
||||
#include "builtin/Eval.h"
|
||||
#include "frontend/BytecodeCompiler.h"
|
||||
#include "jit/InlinableNatives.h"
|
||||
#include "js/UniquePtr.h"
|
||||
#include "vm/AsyncFunction.h"
|
||||
#include "vm/StringBuffer.h"
|
||||
|
||||
#include "jsobjinlines.h"
|
||||
|
|
@ -124,6 +126,27 @@ obj_toSource(JSContext* cx, unsigned argc, Value* vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
template <typename CharT>
|
||||
static bool
|
||||
Consume(const CharT*& s, const CharT* e, const char *chars)
|
||||
{
|
||||
size_t len = strlen(chars);
|
||||
if (s + len >= e)
|
||||
return false;
|
||||
if (!EqualChars(s, chars, len))
|
||||
return false;
|
||||
s += len;
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename CharT>
|
||||
static void
|
||||
ConsumeSpaces(const CharT*& s, const CharT* e)
|
||||
{
|
||||
while (*s == ' ' && s < e)
|
||||
s++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a function source string, return the offset and length of the part
|
||||
* between '(function $name' and ')'.
|
||||
|
|
@ -133,37 +156,53 @@ static bool
|
|||
ArgsAndBodySubstring(mozilla::Range<const CharT> chars, size_t* outOffset, size_t* outLen)
|
||||
{
|
||||
const CharT* const start = chars.begin().get();
|
||||
const CharT* const end = chars.end().get();
|
||||
const CharT* s = start;
|
||||
const CharT* e = chars.end().get();
|
||||
|
||||
uint8_t parenChomp = 0;
|
||||
if (s[0] == '(') {
|
||||
if (s == e)
|
||||
return false;
|
||||
|
||||
// Remove enclosing parentheses.
|
||||
if (*s == '(' && *(e - 1) == ')') {
|
||||
s++;
|
||||
parenChomp = 1;
|
||||
e--;
|
||||
}
|
||||
|
||||
/* Try to jump "function" keyword. */
|
||||
s = js_strchr_limit(s, ' ', end);
|
||||
if (!s)
|
||||
return false;
|
||||
(void) Consume(s, e, "async");
|
||||
ConsumeSpaces(s, e);
|
||||
(void) (Consume(s, e, "function") || Consume(s, e, "get") || Consume(s, e, "set"));
|
||||
ConsumeSpaces(s, e);
|
||||
(void) Consume(s, e, "*");
|
||||
ConsumeSpaces(s, e);
|
||||
|
||||
/*
|
||||
* Jump over the function's name: it can't be encoded as part
|
||||
* of an ECMA getter or setter.
|
||||
*/
|
||||
s = js_strchr_limit(s, '(', end);
|
||||
if (!s)
|
||||
return false;
|
||||
|
||||
if (*s == ' ')
|
||||
// Jump over the function's name.
|
||||
if (Consume(s, e, "[")) {
|
||||
s = js_strchr_limit(s, ']', e);
|
||||
if (!s)
|
||||
return false;
|
||||
s++;
|
||||
ConsumeSpaces(s, e);
|
||||
if (*s != '(')
|
||||
return false;
|
||||
} else {
|
||||
s = js_strchr_limit(s, '(', e);
|
||||
if (!s)
|
||||
return false;
|
||||
}
|
||||
|
||||
*outOffset = s - start;
|
||||
*outLen = end - s - parenChomp;
|
||||
*outLen = e - s;
|
||||
MOZ_ASSERT(*outOffset + *outLen <= chars.length());
|
||||
return true;
|
||||
}
|
||||
|
||||
enum class PropertyKind {
|
||||
Getter,
|
||||
Setter,
|
||||
Method,
|
||||
Normal
|
||||
};
|
||||
|
||||
JSString*
|
||||
js::ObjectToSource(JSContext* cx, HandleObject obj)
|
||||
{
|
||||
|
|
@ -182,59 +221,28 @@ js::ObjectToSource(JSContext* cx, HandleObject obj)
|
|||
if (!buf.append('{'))
|
||||
return nullptr;
|
||||
|
||||
RootedValue v0(cx), v1(cx);
|
||||
MutableHandleValue val[2] = {&v0, &v1};
|
||||
|
||||
RootedString str0(cx), str1(cx);
|
||||
MutableHandleString gsop[2] = {&str0, &str1};
|
||||
|
||||
AutoIdVector idv(cx);
|
||||
if (!GetPropertyKeys(cx, obj, JSITER_OWNONLY | JSITER_SYMBOLS, &idv))
|
||||
return nullptr;
|
||||
|
||||
bool comma = false;
|
||||
for (size_t i = 0; i < idv.length(); ++i) {
|
||||
RootedId id(cx, idv[i]);
|
||||
Rooted<PropertyDescriptor> desc(cx);
|
||||
if (!GetOwnPropertyDescriptor(cx, obj, id, &desc))
|
||||
return nullptr;
|
||||
|
||||
int valcnt = 0;
|
||||
if (desc.object()) {
|
||||
if (desc.isAccessorDescriptor()) {
|
||||
if (desc.hasGetterObject() && desc.getterObject()) {
|
||||
val[valcnt].setObject(*desc.getterObject());
|
||||
gsop[valcnt].set(cx->names().get);
|
||||
valcnt++;
|
||||
}
|
||||
if (desc.hasSetterObject() && desc.setterObject()) {
|
||||
val[valcnt].setObject(*desc.setterObject());
|
||||
gsop[valcnt].set(cx->names().set);
|
||||
valcnt++;
|
||||
}
|
||||
} else {
|
||||
valcnt = 1;
|
||||
val[0].set(desc.value());
|
||||
gsop[0].set(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
auto AddProperty = [cx, &comma, &buf](HandleId id, HandleValue val, PropertyKind kind) -> bool {
|
||||
/* Convert id to a string. */
|
||||
RootedString idstr(cx);
|
||||
if (JSID_IS_SYMBOL(id)) {
|
||||
RootedValue v(cx, SymbolValue(JSID_TO_SYMBOL(id)));
|
||||
idstr = ValueToSource(cx, v);
|
||||
if (!idstr)
|
||||
return nullptr;
|
||||
return false;
|
||||
} else {
|
||||
RootedValue idv(cx, IdToValue(id));
|
||||
idstr = ToString<CanGC>(cx, idv);
|
||||
if (!idstr)
|
||||
return nullptr;
|
||||
return false;
|
||||
|
||||
/*
|
||||
* If id is a string that's not an identifier, or if it's a negative
|
||||
* integer, then it must be quoted.
|
||||
* If id is a string that's not an identifier, or if it's a
|
||||
* negative integer, then it must be quoted.
|
||||
*/
|
||||
if (JSID_IS_ATOM(id)
|
||||
? !IsIdentifier(JSID_TO_ATOM(id))
|
||||
|
|
@ -242,28 +250,65 @@ js::ObjectToSource(JSContext* cx, HandleObject obj)
|
|||
{
|
||||
idstr = QuoteString(cx, idstr, char16_t('\''));
|
||||
if (!idstr)
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (int j = 0; j < valcnt; j++) {
|
||||
/* Convert val[j] to its canonical source form. */
|
||||
JSString* valsource = ValueToSource(cx, val[j]);
|
||||
if (!valsource)
|
||||
return nullptr;
|
||||
RootedString valsource(cx, ValueToSource(cx, val));
|
||||
if (!valsource)
|
||||
return false;
|
||||
|
||||
RootedLinearString valstr(cx, valsource->ensureLinear(cx));
|
||||
if (!valstr)
|
||||
return nullptr;
|
||||
RootedLinearString valstr(cx, valsource->ensureLinear(cx));
|
||||
if (!valstr)
|
||||
return false;
|
||||
|
||||
size_t voffset = 0;
|
||||
size_t vlength = valstr->length();
|
||||
if (comma && !buf.append(", "))
|
||||
return false;
|
||||
comma = true;
|
||||
|
||||
/*
|
||||
* Remove '(function ' from the beginning of valstr and ')' from the
|
||||
* end so that we can put "get" in front of the function definition.
|
||||
*/
|
||||
if (gsop[j] && IsFunctionObject(val[j])) {
|
||||
size_t voffset, vlength;
|
||||
|
||||
// Methods and accessors can return exact syntax of source, that fits
|
||||
// into property without adding property name or "get"/"set" prefix.
|
||||
// Use the exact syntax when the following conditions are met:
|
||||
//
|
||||
// * It's a function object
|
||||
// (exclude proxies)
|
||||
// * Function's kind and property's kind are same
|
||||
// (this can be false for dynamically defined properties)
|
||||
// * Function has explicit name
|
||||
// (this can be false for computed property and dynamically defined
|
||||
// properties)
|
||||
// * Function's name and property's name are same
|
||||
// (this can be false for dynamically defined properties)
|
||||
if (kind == PropertyKind::Getter || kind == PropertyKind::Setter ||
|
||||
kind == PropertyKind::Method)
|
||||
{
|
||||
RootedFunction fun(cx);
|
||||
if (val.toObject().is<JSFunction>()) {
|
||||
fun = &val.toObject().as<JSFunction>();
|
||||
// Method's case should be checked on caller.
|
||||
if (((fun->isGetter() && kind == PropertyKind::Getter) ||
|
||||
(fun->isSetter() && kind == PropertyKind::Setter) ||
|
||||
kind == PropertyKind::Method) &&
|
||||
fun->explicitName())
|
||||
{
|
||||
bool result;
|
||||
if (!EqualStrings(cx, fun->explicitName(), idstr, &result))
|
||||
return false;
|
||||
|
||||
if (result) {
|
||||
if (!buf.append(valstr))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// When falling back try to generate a better string
|
||||
// representation by skipping the prelude, and also removing
|
||||
// the enclosing parentheses.
|
||||
bool success;
|
||||
JS::AutoCheckCannotGC nogc;
|
||||
if (valstr->hasLatin1Chars())
|
||||
|
|
@ -271,29 +316,90 @@ js::ObjectToSource(JSContext* cx, HandleObject obj)
|
|||
else
|
||||
success = ArgsAndBodySubstring(valstr->twoByteRange(nogc), &voffset, &vlength);
|
||||
if (!success)
|
||||
gsop[j].set(nullptr);
|
||||
kind = PropertyKind::Normal;
|
||||
}
|
||||
|
||||
if (comma && !buf.append(", "))
|
||||
return nullptr;
|
||||
comma = true;
|
||||
if (kind == PropertyKind::Getter) {
|
||||
if (!buf.append("get "))
|
||||
return false;
|
||||
} else if (kind == PropertyKind::Setter) {
|
||||
if (!buf.append("set "))
|
||||
return false;
|
||||
} else if (kind == PropertyKind::Method && fun) {
|
||||
if (IsWrappedAsyncFunction(fun)) {
|
||||
if (!buf.append("async "))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (gsop[j]) {
|
||||
if (!buf.append(gsop[j]) || !buf.append(' '))
|
||||
if (fun->isStarGenerator()) {
|
||||
if (!buf.append('*'))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool needsBracket = JSID_IS_SYMBOL(id);
|
||||
if (needsBracket && !buf.append('['))
|
||||
return false;
|
||||
if (!buf.append(idstr))
|
||||
return false;
|
||||
if (needsBracket && !buf.append(']'))
|
||||
return false;
|
||||
|
||||
if (kind == PropertyKind::Getter || kind == PropertyKind::Setter ||
|
||||
kind == PropertyKind::Method)
|
||||
{
|
||||
if (!buf.appendSubstring(valstr, voffset, vlength))
|
||||
return false;
|
||||
} else {
|
||||
if (!buf.append(':'))
|
||||
return false;
|
||||
if (!buf.append(valstr))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
RootedId id(cx);
|
||||
Rooted<PropertyDescriptor> desc(cx);
|
||||
RootedValue val(cx);
|
||||
RootedFunction fun(cx);
|
||||
for (size_t i = 0; i < idv.length(); ++i) {
|
||||
id = idv[i];
|
||||
if (!GetOwnPropertyDescriptor(cx, obj, id, &desc))
|
||||
return nullptr;
|
||||
|
||||
if (!desc.object())
|
||||
continue;
|
||||
|
||||
if (desc.isAccessorDescriptor()) {
|
||||
if (desc.hasGetterObject() && desc.getterObject()) {
|
||||
val.setObject(*desc.getterObject());
|
||||
if (!AddProperty(id, val, PropertyKind::Getter))
|
||||
return nullptr;
|
||||
}
|
||||
if (JSID_IS_SYMBOL(id) && !buf.append('['))
|
||||
return nullptr;
|
||||
if (!buf.append(idstr))
|
||||
return nullptr;
|
||||
if (JSID_IS_SYMBOL(id) && !buf.append(']'))
|
||||
return nullptr;
|
||||
if (!buf.append(gsop[j] ? ' ' : ':'))
|
||||
return nullptr;
|
||||
|
||||
if (!buf.appendSubstring(valstr, voffset, vlength))
|
||||
return nullptr;
|
||||
if (desc.hasSetterObject() && desc.setterObject()) {
|
||||
val.setObject(*desc.setterObject());
|
||||
if (!AddProperty(id, val, PropertyKind::Setter))
|
||||
return nullptr;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
val.set(desc.value());
|
||||
if (IsFunctionObject(val, fun.address())) {
|
||||
if (IsWrappedAsyncFunction(fun))
|
||||
fun = GetUnwrappedAsyncFunction(fun);
|
||||
|
||||
if (fun->isMethod()) {
|
||||
if (!AddProperty(id, val, PropertyKind::Method))
|
||||
return nullptr;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!AddProperty(id, val, PropertyKind::Normal))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!buf.append('}'))
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ class MOZ_STACK_CLASS BytecodeCompiler
|
|||
bool canLazilyParse();
|
||||
bool createParser();
|
||||
bool createSourceAndParser(Maybe<uint32_t> parameterListEnd = Nothing());
|
||||
bool createScript();
|
||||
bool createScript(uint32_t preludeStart = 0);
|
||||
bool emplaceEmitter(Maybe<BytecodeEmitter>& emitter, SharedContext* sharedContext);
|
||||
bool handleParseFailure(const Directives& newDirectives);
|
||||
bool deoptimizeArgumentsInEnclosingScripts(JSContext* cx, HandleObject environment);
|
||||
|
|
@ -242,10 +242,11 @@ BytecodeCompiler::createSourceAndParser(Maybe<uint32_t> parameterListEnd /* = No
|
|||
}
|
||||
|
||||
bool
|
||||
BytecodeCompiler::createScript()
|
||||
BytecodeCompiler::createScript(uint32_t preludeStart /* = 0 */)
|
||||
{
|
||||
script = JSScript::Create(cx, options,
|
||||
sourceObject, /* sourceStart = */ 0, sourceBuffer.length());
|
||||
sourceObject, /* sourceStart = */ 0, sourceBuffer.length(),
|
||||
preludeStart);
|
||||
return script != nullptr;
|
||||
}
|
||||
|
||||
|
|
@ -456,7 +457,7 @@ BytecodeCompiler::compileStandaloneFunction(MutableHandleFunction fun,
|
|||
if (fn->pn_funbox->function()->isInterpreted()) {
|
||||
MOZ_ASSERT(fun == fn->pn_funbox->function());
|
||||
|
||||
if (!createScript())
|
||||
if (!createScript(fn->pn_funbox->preludeStart))
|
||||
return false;
|
||||
|
||||
Maybe<BytecodeEmitter> emitter;
|
||||
|
|
@ -650,7 +651,8 @@ frontend::CompileLazyFunction(JSContext* cx, Handle<LazyScript*> lazy, const cha
|
|||
MOZ_ASSERT(sourceObject);
|
||||
|
||||
Rooted<JSScript*> script(cx, JSScript::Create(cx, options, sourceObject,
|
||||
lazy->begin(), lazy->end()));
|
||||
lazy->begin(), lazy->end(),
|
||||
lazy->preludeStart()));
|
||||
if (!script)
|
||||
return false;
|
||||
|
||||
|
|
|
|||
|
|
@ -109,6 +109,8 @@ IsIdentifier(JSLinearString* str);
|
|||
* As above, but taking chars + length.
|
||||
*/
|
||||
bool
|
||||
IsIdentifier(const char* chars, size_t length);
|
||||
bool
|
||||
IsIdentifier(const char16_t* chars, size_t length);
|
||||
|
||||
/* True if str is a keyword. Defined in TokenStream.cpp. */
|
||||
|
|
|
|||
|
|
@ -3559,9 +3559,11 @@ BytecodeEmitter::maybeSetSourceMap()
|
|||
if (parser->options().sourceMapURL()) {
|
||||
// Warn about the replacement, but use the new one.
|
||||
if (parser->ss->hasSourceMapURL()) {
|
||||
if(!parser->report(ParseWarning, false, nullptr, JSMSG_ALREADY_HAS_PRAGMA,
|
||||
parser->ss->filename(), "//# sourceMappingURL"))
|
||||
if (!parser->reportNoOffset(ParseWarning, false, JSMSG_ALREADY_HAS_PRAGMA,
|
||||
parser->ss->filename(), "//# sourceMappingURL"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!parser->ss->setSourceMapURL(cx, parser->options().sourceMapURL()))
|
||||
|
|
@ -3606,13 +3608,13 @@ BytecodeEmitter::reportError(ParseNode* pn, unsigned errorNumber, ...)
|
|||
}
|
||||
|
||||
bool
|
||||
BytecodeEmitter::reportStrictWarning(ParseNode* pn, unsigned errorNumber, ...)
|
||||
BytecodeEmitter::reportExtraWarning(ParseNode* pn, unsigned errorNumber, ...)
|
||||
{
|
||||
TokenPos pos = pn ? pn->pn_pos : tokenStream()->currentToken().pos;
|
||||
|
||||
va_list args;
|
||||
va_start(args, errorNumber);
|
||||
bool result = tokenStream()->reportStrictWarningErrorNumberVA(pos.begin, errorNumber, args);
|
||||
bool result = tokenStream()->reportExtraWarningErrorNumberVA(pos.begin, errorNumber, args);
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
|
|
@ -7834,7 +7836,8 @@ BytecodeEmitter::emitFunction(ParseNode* pn, bool needsProto)
|
|||
|
||||
Rooted<JSObject*> sourceObject(cx, script->sourceObject());
|
||||
Rooted<JSScript*> script(cx, JSScript::Create(cx, options, sourceObject,
|
||||
funbox->bufStart, funbox->bufEnd));
|
||||
funbox->bufStart, funbox->bufEnd,
|
||||
funbox->preludeStart));
|
||||
if (!script)
|
||||
return false;
|
||||
|
||||
|
|
@ -8704,13 +8707,13 @@ BytecodeEmitter::emitStatement(ParseNode* pn)
|
|||
}
|
||||
|
||||
if (directive) {
|
||||
if (!reportStrictWarning(pn2, JSMSG_CONTRARY_NONDIRECTIVE, directive))
|
||||
if (!reportExtraWarning(pn2, JSMSG_CONTRARY_NONDIRECTIVE, directive))
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
current->currentLine = parser->tokenStream.srcCoords.lineNum(pn2->pn_pos.begin);
|
||||
current->lastColumn = 0;
|
||||
if (!reportStrictWarning(pn2, JSMSG_USELESS_EXPR))
|
||||
if (!reportExtraWarning(pn2, JSMSG_USELESS_EXPR))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -388,7 +388,7 @@ struct MOZ_STACK_CLASS BytecodeEmitter
|
|||
}
|
||||
|
||||
bool reportError(ParseNode* pn, unsigned errorNumber, ...);
|
||||
bool reportStrictWarning(ParseNode* pn, unsigned errorNumber, ...);
|
||||
bool reportExtraWarning(ParseNode* pn, unsigned errorNumber, ...);
|
||||
bool reportStrictModeError(ParseNode* pn, unsigned errorNumber, ...);
|
||||
|
||||
// If pn contains a useful expression, return true with *answer set to true.
|
||||
|
|
|
|||
|
|
@ -670,9 +670,18 @@ class FullParseHandler
|
|||
pn->setDirectRHSAnonFunction(true);
|
||||
}
|
||||
|
||||
ParseNode* newFunctionDefinition() {
|
||||
return new_<CodeNode>(PNK_FUNCTION, pos());
|
||||
ParseNode* newFunctionStatement() {
|
||||
return new_<CodeNode>(PNK_FUNCTION, JSOP_NOP, pos());
|
||||
}
|
||||
|
||||
ParseNode* newFunctionExpression() {
|
||||
return new_<CodeNode>(PNK_FUNCTION, JSOP_LAMBDA, pos());
|
||||
}
|
||||
|
||||
ParseNode* newArrowFunction() {
|
||||
return new_<CodeNode>(PNK_FUNCTION, JSOP_LAMBDA_ARROW, pos());
|
||||
}
|
||||
|
||||
bool setComprehensionLambdaBody(ParseNode* pn, ParseNode* body) {
|
||||
MOZ_ASSERT(body->isKind(PNK_STATEMENTLIST));
|
||||
ParseNode* paramsBody = newList(PNK_PARAMSBODY, body);
|
||||
|
|
@ -699,7 +708,7 @@ class FullParseHandler
|
|||
}
|
||||
|
||||
ParseNode* newModule() {
|
||||
return new_<CodeNode>(PNK_MODULE, pos());
|
||||
return new_<CodeNode>(PNK_MODULE, JSOP_NOP, pos());
|
||||
}
|
||||
|
||||
ParseNode* newLexicalScope(LexicalScope::Data* bindings, ParseNode* body) {
|
||||
|
|
@ -845,7 +854,7 @@ class FullParseHandler
|
|||
MOZ_MUST_USE ParseNode* setLikelyIIFE(ParseNode* pn) {
|
||||
return parenthesize(pn);
|
||||
}
|
||||
void setPrologue(ParseNode* pn) {
|
||||
void setInDirectivePrologue(ParseNode* pn) {
|
||||
pn->pn_prologue = true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -926,10 +926,14 @@ struct ListNode : public ParseNode
|
|||
|
||||
struct CodeNode : public ParseNode
|
||||
{
|
||||
CodeNode(ParseNodeKind kind, const TokenPos& pos)
|
||||
: ParseNode(kind, JSOP_NOP, PN_CODE, pos)
|
||||
CodeNode(ParseNodeKind kind, JSOp op, const TokenPos& pos)
|
||||
: ParseNode(kind, op, PN_CODE, pos)
|
||||
{
|
||||
MOZ_ASSERT(kind == PNK_FUNCTION || kind == PNK_MODULE);
|
||||
MOZ_ASSERT_IF(kind == PNK_MODULE, op == JSOP_NOP);
|
||||
MOZ_ASSERT(op == JSOP_NOP || // statement, module
|
||||
op == JSOP_LAMBDA_ARROW || // arrow function
|
||||
op == JSOP_LAMBDA); // expression, method, comprehension, accessor, &c.
|
||||
MOZ_ASSERT(!pn_body);
|
||||
MOZ_ASSERT(!pn_objbox);
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -769,13 +769,13 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
|||
*
|
||||
* Ex:
|
||||
* PossibleError possibleError(*this);
|
||||
* possibleError.setPendingExpressionError(pn, JSMSG_BAD_PROP_ID);
|
||||
* possibleError.setPendingExpressionErrorAt(pos, JSMSG_BAD_PROP_ID);
|
||||
* // A JSMSG_BAD_PROP_ID ParseError is reported, returns false.
|
||||
* if (!possibleError.checkForExpressionError())
|
||||
* return false; // we reach this point with a pending exception
|
||||
*
|
||||
* PossibleError possibleError(*this);
|
||||
* possibleError.setPendingExpressionError(pn, JSMSG_BAD_PROP_ID);
|
||||
* possibleError.setPendingExpressionErrorAt(pos, JSMSG_BAD_PROP_ID);
|
||||
* // Returns true, no error is reported.
|
||||
* if (!possibleError.checkForDestructuringError())
|
||||
* return false; // not reached, no pending exception
|
||||
|
|
@ -815,7 +815,7 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
|||
|
||||
// Set a pending error. Only a single error may be set per instance and
|
||||
// error kind.
|
||||
void setPending(ErrorKind kind, Node pn, unsigned errorNumber);
|
||||
void setPending(ErrorKind kind, const TokenPos& pos, unsigned errorNumber);
|
||||
|
||||
// If there is a pending error, report it and return false, otherwise
|
||||
// return true.
|
||||
|
|
@ -830,12 +830,12 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
|||
// Set a pending destructuring error. Only a single error may be set
|
||||
// per instance, i.e. subsequent calls to this method are ignored and
|
||||
// won't overwrite the existing pending error.
|
||||
void setPendingDestructuringError(Node pn, unsigned errorNumber);
|
||||
void setPendingDestructuringErrorAt(const TokenPos& pos, unsigned errorNumber);
|
||||
|
||||
// Set a pending expression error. Only a single error may be set per
|
||||
// instance, i.e. subsequent calls to this method are ignored and won't
|
||||
// overwrite the existing pending error.
|
||||
void setPendingExpressionError(Node pn, unsigned errorNumber);
|
||||
void setPendingExpressionErrorAt(const TokenPos& pos, unsigned errorNumber);
|
||||
|
||||
// If there is a pending destructuring error, report it and return
|
||||
// false, otherwise return true. Clears any pending expression error.
|
||||
|
|
@ -903,14 +903,40 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
|||
void prepareNodeForMutation(Node node) { handler.prepareNodeForMutation(node); }
|
||||
void freeTree(Node node) { handler.freeTree(node); }
|
||||
|
||||
private:
|
||||
bool reportHelper(ParseReportKind kind, bool strict, uint32_t offset,
|
||||
unsigned errorNumber, va_list args);
|
||||
public:
|
||||
bool report(ParseReportKind kind, bool strict, Node pn, unsigned errorNumber, ...);
|
||||
bool reportNoOffset(ParseReportKind kind, bool strict, unsigned errorNumber, ...);
|
||||
bool reportWithOffset(ParseReportKind kind, bool strict, uint32_t offset, unsigned errorNumber,
|
||||
...);
|
||||
|
||||
/* Report the given error at the current offset. */
|
||||
void error(unsigned errorNumber, ...);
|
||||
|
||||
/* Report the given error at the given offset. */
|
||||
void errorAt(uint32_t offset, unsigned errorNumber, ...);
|
||||
|
||||
/*
|
||||
* Handle a strict mode error at the current offset. Report an error if in
|
||||
* strict mode code, or warn if not, using the given error number and
|
||||
* arguments.
|
||||
*/
|
||||
MOZ_MUST_USE bool strictModeError(unsigned errorNumber, ...);
|
||||
|
||||
/*
|
||||
* Handle a strict mode error at the given offset. Report an error if in
|
||||
* strict mode code, or warn if not, using the given error number and
|
||||
* arguments.
|
||||
*/
|
||||
MOZ_MUST_USE bool strictModeErrorAt(uint32_t offset, unsigned errorNumber, ...);
|
||||
|
||||
/* Report the given warning at the current offset. */
|
||||
MOZ_MUST_USE bool warning(unsigned errorNumber, ...);
|
||||
|
||||
/* Report the given warning at the given offset. */
|
||||
MOZ_MUST_USE bool warningAt(uint32_t offset, unsigned errorNumber, ...);
|
||||
|
||||
/*
|
||||
* If extra warnings are enabled, report the given warning at the current
|
||||
* offset.
|
||||
*/
|
||||
MOZ_MUST_USE bool extraWarning(unsigned errorNumber, ...);
|
||||
|
||||
Parser(ExclusiveContext* cx, LifoAlloc& alloc, const ReadOnlyCompileOptions& options,
|
||||
const char16_t* chars, size_t length, bool foldConstants, UsedNameTracker& usedNames,
|
||||
|
|
@ -954,7 +980,8 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
|||
* cx->tempLifoAlloc.
|
||||
*/
|
||||
ObjectBox* newObjectBox(JSObject* obj);
|
||||
FunctionBox* newFunctionBox(Node fn, JSFunction* fun, Directives directives,
|
||||
FunctionBox* newFunctionBox(Node fn, JSFunction* fun, uint32_t preludeStart,
|
||||
Directives directives,
|
||||
GeneratorKind generatorKind, FunctionAsyncKind asyncKind,
|
||||
bool tryAnnexB);
|
||||
|
||||
|
|
@ -1034,8 +1061,9 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
|||
|
||||
// Parse an inner function given an enclosing ParseContext and a
|
||||
// FunctionBox for the inner function.
|
||||
bool innerFunction(Node pn, ParseContext* outerpc, FunctionBox* funbox, InHandling inHandling,
|
||||
YieldHandling yieldHandling, FunctionSyntaxKind kind,
|
||||
bool innerFunction(Node pn, ParseContext* outerpc, FunctionBox* funbox, uint32_t preludeStart,
|
||||
InHandling inHandling, YieldHandling yieldHandling,
|
||||
FunctionSyntaxKind kind,
|
||||
Directives inheritedDirectives, Directives* newDirectives);
|
||||
|
||||
// Parse a function's formal parameters and its body assuming its function
|
||||
|
|
@ -1088,9 +1116,10 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
|||
* Some parsers have two versions: an always-inlined version (with an 'i'
|
||||
* suffix) and a never-inlined version (with an 'n' suffix).
|
||||
*/
|
||||
Node functionStmt(YieldHandling yieldHandling, DefaultHandling defaultHandling,
|
||||
Node functionStmt(uint32_t preludeStart,
|
||||
YieldHandling yieldHandling, DefaultHandling defaultHandling,
|
||||
FunctionAsyncKind asyncKind = SyncFunction);
|
||||
Node functionExpr(InvokedPrediction invoked = PredictUninvoked,
|
||||
Node functionExpr(uint32_t preludeStart, InvokedPrediction invoked = PredictUninvoked,
|
||||
FunctionAsyncKind asyncKind = SyncFunction);
|
||||
|
||||
Node statementList(YieldHandling yieldHandling);
|
||||
|
|
@ -1106,7 +1135,6 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
|||
Node* forInitialPart,
|
||||
mozilla::Maybe<ParseContext::Scope>& forLetImpliedScope,
|
||||
Node* forInOrOfExpression);
|
||||
bool validateForInOrOfLHSExpression(Node target, PossibleError* possibleError);
|
||||
Node expressionAfterForInOrOf(ParseNodeKind forHeadKind, YieldHandling yieldHandling);
|
||||
|
||||
Node switchStatement(YieldHandling yieldHandling);
|
||||
|
|
@ -1222,7 +1250,7 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
|||
bool tryNewTarget(Node& newTarget);
|
||||
bool checkAndMarkSuperScope();
|
||||
|
||||
Node methodDefinition(PropertyType propType, HandleAtom funName);
|
||||
Node methodDefinition(uint32_t preludeStart, PropertyType propType, HandleAtom funName);
|
||||
|
||||
/*
|
||||
* Additional JS parsers.
|
||||
|
|
@ -1230,10 +1258,11 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
|||
bool functionArguments(YieldHandling yieldHandling, FunctionSyntaxKind kind,
|
||||
Node funcpn);
|
||||
|
||||
Node functionDefinition(InHandling inHandling, YieldHandling yieldHandling, HandleAtom name,
|
||||
Node functionDefinition(uint32_t preludeStart, Node pn,
|
||||
InHandling inHandling, YieldHandling yieldHandling, HandleAtom name,
|
||||
FunctionSyntaxKind kind,
|
||||
GeneratorKind generatorKind, FunctionAsyncKind asyncKind,
|
||||
InvokedPrediction invoked = PredictUninvoked);
|
||||
bool tryAnnexB = false);
|
||||
|
||||
// Parse a function body. Pass StatementListBody if the body is a list of
|
||||
// statements; pass ExpressionBody if the body is a single expression.
|
||||
|
|
@ -1298,17 +1327,6 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
|||
#endif
|
||||
}
|
||||
|
||||
enum AssignmentFlavor {
|
||||
PlainAssignment,
|
||||
CompoundAssignment,
|
||||
KeyedDestructuringAssignment,
|
||||
IncrementAssignment,
|
||||
DecrementAssignment,
|
||||
ForInOrOfTarget
|
||||
};
|
||||
|
||||
bool checkAndMarkAsAssignmentLhs(Node pn, AssignmentFlavor flavor,
|
||||
PossibleError* possibleError=nullptr);
|
||||
bool matchInOrOf(bool* isForInp, bool* isForOfp);
|
||||
|
||||
bool hasUsedFunctionSpecialName(HandlePropertyName name);
|
||||
|
|
@ -1319,16 +1337,16 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
|||
Node newDotGeneratorName();
|
||||
bool declareDotGeneratorName();
|
||||
|
||||
bool checkFunctionDefinition(HandleAtom funAtom, Node pn, FunctionSyntaxKind kind,
|
||||
GeneratorKind generatorKind, bool* tryAnnexB);
|
||||
bool skipLazyInnerFunction(Node pn, FunctionSyntaxKind kind, bool tryAnnexB);
|
||||
bool innerFunction(Node pn, ParseContext* outerpc, HandleFunction fun,
|
||||
bool skipLazyInnerFunction(Node pn, uint32_t preludeStart, FunctionSyntaxKind kind,
|
||||
bool tryAnnexB);
|
||||
bool innerFunction(Node pn, ParseContext* outerpc, HandleFunction fun, uint32_t preludeStart,
|
||||
InHandling inHandling, YieldHandling yieldHandling,
|
||||
FunctionSyntaxKind kind,
|
||||
GeneratorKind generatorKind, FunctionAsyncKind asyncKind, bool tryAnnexB,
|
||||
Directives inheritedDirectives, Directives* newDirectives);
|
||||
bool trySyntaxParseInnerFunction(Node pn, HandleFunction fun, InHandling inHandling,
|
||||
YieldHandling yieldHandling, FunctionSyntaxKind kind,
|
||||
bool trySyntaxParseInnerFunction(Node pn, HandleFunction fun, uint32_t preludeStart,
|
||||
InHandling inHandling, YieldHandling yieldHandling,
|
||||
FunctionSyntaxKind kind,
|
||||
GeneratorKind generatorKind, FunctionAsyncKind asyncKind,
|
||||
bool tryAnnexB,
|
||||
Directives inheritedDirectives, Directives* newDirectives);
|
||||
|
|
@ -1346,10 +1364,7 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
|||
FunctionCallBehavior behavior = ForbidAssignmentToFunctionCalls);
|
||||
|
||||
private:
|
||||
bool reportIfArgumentsEvalTarget(Node nameNode);
|
||||
bool reportIfNotValidSimpleAssignmentTarget(Node target, AssignmentFlavor flavor);
|
||||
|
||||
bool checkAndMarkAsIncOperand(Node kid, AssignmentFlavor flavor);
|
||||
bool checkIncDecOperand(Node operand, uint32_t operandOffset);
|
||||
bool checkStrictAssignment(Node lhs);
|
||||
bool checkStrictBinding(PropertyName* name, TokenPos pos);
|
||||
|
||||
|
|
@ -1404,16 +1419,12 @@ class Parser final : private JS::AutoGCRooter, public StrictModeGetter
|
|||
bool checkDestructuringObject(Node objectPattern, mozilla::Maybe<DeclarationKind> maybeDecl);
|
||||
bool checkDestructuringName(Node expr, mozilla::Maybe<DeclarationKind> maybeDecl);
|
||||
|
||||
bool checkAssignmentToCall(Node node, unsigned errnum);
|
||||
|
||||
Node newNumber(const Token& tok) {
|
||||
return handler.newNumber(tok.number(), tok.decimalPoint(), tok.pos);
|
||||
}
|
||||
|
||||
static Node null() { return ParseHandler::null(); }
|
||||
|
||||
bool reportBadReturn(Node pn, ParseReportKind kind, unsigned errnum, unsigned anonerrnum);
|
||||
|
||||
JSAtom* prefixAccessorName(PropertyType propType, HandleAtom propAtom);
|
||||
|
||||
TokenPos pos() const { return tokenStream.currentToken().pos; }
|
||||
|
|
|
|||
|
|
@ -450,6 +450,7 @@ class FunctionBox : public ObjectBox, public SharedContext
|
|||
uint32_t bufEnd;
|
||||
uint32_t startLine;
|
||||
uint32_t startColumn;
|
||||
uint32_t preludeStart;
|
||||
uint16_t length;
|
||||
|
||||
uint8_t generatorKindBits_; /* The GeneratorKind of this function. */
|
||||
|
|
@ -476,8 +477,8 @@ class FunctionBox : public ObjectBox, public SharedContext
|
|||
FunctionContextFlags funCxFlags;
|
||||
|
||||
FunctionBox(ExclusiveContext* cx, LifoAlloc& alloc, ObjectBox* traceListHead, JSFunction* fun,
|
||||
Directives directives, bool extraWarnings, GeneratorKind generatorKind,
|
||||
FunctionAsyncKind asyncKind);
|
||||
uint32_t preludeStart, Directives directives, bool extraWarnings,
|
||||
GeneratorKind generatorKind, FunctionAsyncKind asyncKind);
|
||||
|
||||
MutableHandle<LexicalScope::Data*> namedLambdaBindings() {
|
||||
MOZ_ASSERT(context->compartment()->runtimeFromAnyThread()->keepAtoms());
|
||||
|
|
|
|||
|
|
@ -342,7 +342,10 @@ class SyntaxParseHandler
|
|||
|
||||
void checkAndSetIsDirectRHSAnonFunction(Node pn) {}
|
||||
|
||||
Node newFunctionDefinition() { return NodeFunctionDefinition; }
|
||||
Node newFunctionStatement() { return NodeFunctionDefinition; }
|
||||
Node newFunctionExpression() { return NodeFunctionDefinition; }
|
||||
Node newArrowFunction() { return NodeFunctionDefinition; }
|
||||
|
||||
bool setComprehensionLambdaBody(Node pn, Node body) { return true; }
|
||||
void setFunctionFormalParametersAndBody(Node pn, Node kid) {}
|
||||
void setFunctionBody(Node pn, Node kid) {}
|
||||
|
|
@ -519,7 +522,7 @@ class SyntaxParseHandler
|
|||
MOZ_MUST_USE Node setLikelyIIFE(Node pn) {
|
||||
return pn; // Remain in syntax-parse mode.
|
||||
}
|
||||
void setPrologue(Node pn) {}
|
||||
void setInDirectivePrologue(Node pn) {}
|
||||
|
||||
bool isConstant(Node pn) { return false; }
|
||||
|
||||
|
|
|
|||
|
|
@ -171,6 +171,12 @@ frontend::IsIdentifier(JSLinearString* str)
|
|||
: ::IsIdentifierMaybeNonBMP(str->twoByteChars(nogc), str->length());
|
||||
}
|
||||
|
||||
bool
|
||||
frontend::IsIdentifier(const char* chars, size_t length)
|
||||
{
|
||||
return ::IsIdentifier(chars, length);
|
||||
}
|
||||
|
||||
bool
|
||||
frontend::IsIdentifier(const char16_t* chars, size_t length)
|
||||
{
|
||||
|
|
@ -780,7 +786,7 @@ TokenStream::reportWarning(unsigned errorNumber, ...)
|
|||
}
|
||||
|
||||
bool
|
||||
TokenStream::reportStrictWarningErrorNumberVA(uint32_t offset, unsigned errorNumber, va_list args)
|
||||
TokenStream::reportExtraWarningErrorNumberVA(uint32_t offset, unsigned errorNumber, va_list args)
|
||||
{
|
||||
if (!options().extraWarningsOption)
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -375,8 +375,7 @@ class MOZ_STACK_CLASS TokenStream
|
|||
va_list args);
|
||||
bool reportStrictModeErrorNumberVA(uint32_t offset, bool strictMode, unsigned errorNumber,
|
||||
va_list args);
|
||||
bool reportStrictWarningErrorNumberVA(uint32_t offset, unsigned errorNumber,
|
||||
va_list args);
|
||||
bool reportExtraWarningErrorNumberVA(uint32_t offset, unsigned errorNumber, va_list args);
|
||||
|
||||
// asm.js reporter
|
||||
void reportAsmJSError(uint32_t offset, unsigned errorNumber, ...);
|
||||
|
|
@ -570,6 +569,14 @@ class MOZ_STACK_CLASS TokenStream
|
|||
return true;
|
||||
}
|
||||
|
||||
MOZ_MUST_USE bool peekOffset(uint32_t* offset, Modifier modifier = None) {
|
||||
TokenPos pos;
|
||||
if (!peekTokenPos(&pos, modifier))
|
||||
return false;
|
||||
*offset = pos.begin;
|
||||
return true;
|
||||
}
|
||||
|
||||
// This is like peekToken(), with one exception: if there is an EOL
|
||||
// between the end of the current token and the start of the next token, it
|
||||
// return true and store TOK_EOL in |*ttp|. In that case, no token with
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ var f0 = function() {
|
|||
|
||||
}
|
||||
|
||||
funcBody1 = funcBody.replace('function f0','function ');
|
||||
funcBody1 = funcBody.replace('function f0','function');
|
||||
assertEq(f0.toString(), funcBody1);
|
||||
assertEq(f0.toSource(), '(' + funcBody1 + ')');
|
||||
|
||||
|
|
@ -48,14 +48,14 @@ assertEq(g.toString(), funcBody2);
|
|||
assertEq(g.toSource(), '(' + funcBody2 + ')');
|
||||
|
||||
f0 = new Function(bodyOnly);
|
||||
assertEq(f0.toString(), "function anonymous() {\n" + bodyOnly + "\n}");
|
||||
assertEq(f0.toSource(), "(function anonymous() {\n" + bodyOnly + "\n})");
|
||||
assertEq(f0.toString(), "function anonymous(\n) {\n" + bodyOnly + "\n}");
|
||||
assertEq(f0.toSource(), "(function anonymous(\n) {\n" + bodyOnly + "\n})");
|
||||
|
||||
if (isAsmJSCompilationAvailable() && isCachingEnabled()) {
|
||||
var m = new Function(bodyOnly);
|
||||
assertEq(isAsmJSModuleLoadedFromCache(m), true);
|
||||
assertEq(m.toString(), "function anonymous() {\n" + bodyOnly + "\n}");
|
||||
assertEq(m.toSource(), "(function anonymous() {\n" + bodyOnly + "\n})");
|
||||
assertEq(m.toString(), "function anonymous(\n) {\n" + bodyOnly + "\n}");
|
||||
assertEq(m.toSource(), "(function anonymous(\n) {\n" + bodyOnly + "\n})");
|
||||
}
|
||||
|
||||
})();
|
||||
|
|
@ -91,7 +91,7 @@ f1 = function(glob) {
|
|||
|
||||
}
|
||||
|
||||
funcBody1 = funcBody.replace('function f1', 'function ');
|
||||
funcBody1 = funcBody.replace('function f1', 'function');
|
||||
assertEq(f1.toString(), funcBody1);
|
||||
assertEq(f1.toSource(), '(' + funcBody1 + ')');
|
||||
|
||||
|
|
@ -107,14 +107,14 @@ assertEq(g.toString(), funcBody2);
|
|||
assertEq(g.toSource(), '(' + funcBody2 + ')');
|
||||
|
||||
f1 = new Function('glob', bodyOnly);
|
||||
assertEq(f1.toString(), "function anonymous(glob) {\n" + bodyOnly + "\n}");
|
||||
assertEq(f1.toSource(), "(function anonymous(glob) {\n" + bodyOnly + "\n})");
|
||||
assertEq(f1.toString(), "function anonymous(glob\n) {\n" + bodyOnly + "\n}");
|
||||
assertEq(f1.toSource(), "(function anonymous(glob\n) {\n" + bodyOnly + "\n})");
|
||||
|
||||
if (isAsmJSCompilationAvailable() && isCachingEnabled()) {
|
||||
var m = new Function('glob', bodyOnly);
|
||||
assertEq(isAsmJSModuleLoadedFromCache(m), true);
|
||||
assertEq(m.toString(), "function anonymous(glob) {\n" + bodyOnly + "\n}");
|
||||
assertEq(m.toSource(), "(function anonymous(glob) {\n" + bodyOnly + "\n})");
|
||||
assertEq(m.toString(), "function anonymous(glob\n) {\n" + bodyOnly + "\n}");
|
||||
assertEq(m.toSource(), "(function anonymous(glob\n) {\n" + bodyOnly + "\n})");
|
||||
}
|
||||
|
||||
})();
|
||||
|
|
@ -144,14 +144,14 @@ var funcBody = 'function f2(glob, ffi) {\n\
|
|||
assertEq(f2.toString(), funcBody);
|
||||
assertEq(f2.toSource(), funcBody);
|
||||
|
||||
f2 = function (glob, ffi) {
|
||||
f2 = function(glob, ffi) {
|
||||
"use asm";
|
||||
function g() {}
|
||||
return g;
|
||||
|
||||
}
|
||||
|
||||
funcBody1 = funcBody.replace('function f2', 'function ');
|
||||
funcBody1 = funcBody.replace('function f2', 'function');
|
||||
assertEq(f2.toString(), funcBody1);
|
||||
assertEq(f2.toSource(), '(' + funcBody1 + ')');
|
||||
|
||||
|
|
@ -167,14 +167,14 @@ assertEq(g.toString(), funcBody2);
|
|||
assertEq(g.toSource(), '(' + funcBody2 + ')');
|
||||
|
||||
f2 = new Function('glob', 'ffi', bodyOnly);
|
||||
assertEq(f2.toString(), "function anonymous(glob, ffi) {\n" + bodyOnly + "\n}");
|
||||
assertEq(f2.toSource(), "(function anonymous(glob, ffi) {\n" + bodyOnly + "\n})");
|
||||
assertEq(f2.toString(), "function anonymous(glob,ffi\n) {\n" + bodyOnly + "\n}");
|
||||
assertEq(f2.toSource(), "(function anonymous(glob,ffi\n) {\n" + bodyOnly + "\n})");
|
||||
|
||||
if (isAsmJSCompilationAvailable() && isCachingEnabled()) {
|
||||
var m = new Function('glob', 'ffi', bodyOnly);
|
||||
assertEq(isAsmJSModuleLoadedFromCache(m), true);
|
||||
assertEq(m.toString(), "function anonymous(glob, ffi) {\n" + bodyOnly + "\n}");
|
||||
assertEq(m.toSource(), "(function anonymous(glob, ffi) {\n" + bodyOnly + "\n})");
|
||||
assertEq(m.toString(), "function anonymous(glob,ffi\n) {\n" + bodyOnly + "\n}");
|
||||
assertEq(m.toSource(), "(function anonymous(glob,ffi\n) {\n" + bodyOnly + "\n})");
|
||||
}
|
||||
|
||||
})();
|
||||
|
|
@ -204,14 +204,14 @@ var funcBody = 'function f3(glob, ffi, heap) {\n\
|
|||
assertEq(f3.toString(), funcBody);
|
||||
assertEq(f3.toSource(), funcBody);
|
||||
|
||||
f3 = function (glob, ffi, heap) {
|
||||
f3 = function(glob, ffi, heap) {
|
||||
"use asm";
|
||||
function g() {}
|
||||
return g;
|
||||
|
||||
}
|
||||
|
||||
funcBody1 = funcBody.replace('function f3', 'function ');
|
||||
funcBody1 = funcBody.replace('function f3', 'function');
|
||||
assertEq(f3.toString(), funcBody1);
|
||||
assertEq(f3.toSource(), '(' + funcBody1 + ')');
|
||||
|
||||
|
|
@ -227,14 +227,14 @@ assertEq(g.toString(), funcBody2);
|
|||
assertEq(g.toSource(), '(' + funcBody2 + ')');
|
||||
|
||||
f3 = new Function('glob', 'ffi', 'heap', bodyOnly);
|
||||
assertEq(f3.toString(), "function anonymous(glob, ffi, heap) {\n" + bodyOnly + "\n}");
|
||||
assertEq(f3.toSource(), "(function anonymous(glob, ffi, heap) {\n" + bodyOnly + "\n})");
|
||||
assertEq(f3.toString(), "function anonymous(glob,ffi,heap\n) {\n" + bodyOnly + "\n}");
|
||||
assertEq(f3.toSource(), "(function anonymous(glob,ffi,heap\n) {\n" + bodyOnly + "\n})");
|
||||
|
||||
if (isAsmJSCompilationAvailable() && isCachingEnabled()) {
|
||||
var m = new Function('glob', 'ffi', 'heap', bodyOnly);
|
||||
assertEq(isAsmJSModuleLoadedFromCache(m), true);
|
||||
assertEq(m.toString(), "function anonymous(glob, ffi, heap) {\n" + bodyOnly + "\n}");
|
||||
assertEq(m.toSource(), "(function anonymous(glob, ffi, heap) {\n" + bodyOnly + "\n})");
|
||||
assertEq(m.toString(), "function anonymous(glob,ffi,heap\n) {\n" + bodyOnly + "\n}");
|
||||
assertEq(m.toSource(), "(function anonymous(glob,ffi,heap\n) {\n" + bodyOnly + "\n})");
|
||||
}
|
||||
|
||||
})();
|
||||
|
|
@ -243,7 +243,7 @@ if (isAsmJSCompilationAvailable() && isCachingEnabled()) {
|
|||
(function() {
|
||||
|
||||
var funcSource =
|
||||
`function (glob, ffi, heap) {
|
||||
`function(glob, ffi, heap) {
|
||||
"use asm";
|
||||
function g() {}
|
||||
return g;
|
||||
|
|
@ -252,7 +252,7 @@ var funcSource =
|
|||
var f4 = eval("\"use strict\";\n(" + funcSource + ")");
|
||||
|
||||
var expectedToString = funcSource;
|
||||
var expectedToSource = '(' + expectedToString + ')'
|
||||
var expectedToSource = '(' + expectedToString + ')';
|
||||
|
||||
assertEq(f4.toString(), expectedToString);
|
||||
assertEq(f4.toSource(), expectedToSource);
|
||||
|
|
|
|||
|
|
@ -5,4 +5,4 @@ for (var i=0; i<400; ++i) {
|
|||
x += String.fromCharCode(i * 289);
|
||||
}
|
||||
var s = "'" + x + "'";
|
||||
assertEq(Function("evt", s).toString(), "function anonymous(evt) {\n" + s + "\n}");
|
||||
assertEq(Function("evt", s).toString(), "function anonymous(evt\n) {\n" + s + "\n}");
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
var f = Function("a", "b", "return a + b;");
|
||||
assertEq(f.toString(), "function anonymous(a, b) {\nreturn a + b;\n}");
|
||||
assertEq(f.toSource(), "(function anonymous(a, b) {\nreturn a + b;\n})");
|
||||
assertEq(f.toString(), "function anonymous(a,b\n) {\nreturn a + b;\n}");
|
||||
assertEq(f.toSource(), "(function anonymous(a,b\n) {\nreturn a + b;\n})");
|
||||
assertEq(decompileFunction(f), f.toString());
|
||||
f = Function("a", "...rest", "return rest[42] + b;");
|
||||
assertEq(f.toString(), "function anonymous(a, ...rest) {\nreturn rest[42] + b;\n}");
|
||||
assertEq(f.toSource(), "(function anonymous(a, ...rest) {\nreturn rest[42] + b;\n})")
|
||||
assertEq(f.toString(), "function anonymous(a,...rest\n) {\nreturn rest[42] + b;\n}");
|
||||
assertEq(f.toSource(), "(function anonymous(a,...rest\n) {\nreturn rest[42] + b;\n})")
|
||||
assertEq(decompileFunction(f), f.toString());
|
||||
f = Function("");
|
||||
assertEq(f.toString(), "function anonymous() {\n\n}");
|
||||
assertEq(f.toString(), "function anonymous(\n) {\n\n}");
|
||||
f = Function("", "(abc)");
|
||||
assertEq(f.toString(), "function anonymous() {\n(abc)\n}");
|
||||
f = Function("", "return function (a, b) a + b;")();
|
||||
assertEq(f.toString(), "function (a, b) a + b");
|
||||
assertEq(f.toString(), "function anonymous(\n) {\n(abc)\n}");
|
||||
f = Function("", "return function (a,b) a + b;")();
|
||||
assertEq(f.toString(), "function (a,b) a + b");
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
var o = {get prop() a + b, set prop(x) a + b};
|
||||
var prop = Object.getOwnPropertyDescriptor(o, "prop");
|
||||
assertEq(prop.get.toString(), "function get prop() a + b");
|
||||
assertEq(prop.get.toSource(), "(function get prop() a + b)");
|
||||
assertEq(prop.set.toString(), "function set prop(x) a + b");
|
||||
assertEq(prop.set.toSource(), "(function set prop(x) a + b)");
|
||||
assertEq(o.toSource(), "({get prop () a + b, set prop (x) a + b})");
|
||||
assertEq(prop.get.toString(), "get prop() { a + b; }");
|
||||
assertEq(prop.get.toSource(), "get prop() { a + b; }");
|
||||
assertEq(prop.set.toString(), "set prop(x) { a + b; }");
|
||||
assertEq(prop.set.toSource(), "set prop(x) { a + b; }");
|
||||
assertEq(o.toSource(), "({get prop() { a + b; }, set prop(x) { a + b; }})");
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ function test(str, arg, result)
|
|||
var fun = new Function('x', str);
|
||||
|
||||
var got = fun.toSource();
|
||||
var expect = '(function anonymous(x) {\n' + str + '\n})';
|
||||
var expect = '(function anonymous(x\n) {\n' + str + '\n})';
|
||||
if (got !== expect) {
|
||||
print("GOT: " + got);
|
||||
print("EXPECT: " + expect);
|
||||
|
|
|
|||
|
|
@ -10,5 +10,5 @@ assertEq(arr.length, 10);
|
|||
gc();
|
||||
|
||||
for (var i = 0; i < arr.length; i++)
|
||||
assertEq(arr[i].lineCount, 3);
|
||||
assertEq(arr[i].lineCount, 4);
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,6 @@ assertEq(arr.length, 100);
|
|||
gc(g);
|
||||
|
||||
for (var i = 0; i < arr.length; i++)
|
||||
assertEq(arr[i].lineCount, 3);
|
||||
assertEq(arr[i].lineCount, 4);
|
||||
|
||||
gc();
|
||||
|
|
|
|||
|
|
@ -20,6 +20,6 @@ function test(string, range) {
|
|||
}
|
||||
|
||||
test("eval('2 * 3')", [0, 5]);
|
||||
test("new Function('2 * 3')", [0, 12]);
|
||||
test("new Function('x', 'x * x')", [0, 13]);
|
||||
test("new Function('2 * 3')", [0, 31]);
|
||||
test("new Function('x', 'x * x')", [0, 32]);
|
||||
assertEq(count, 6);
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
let g = newGlobal();
|
||||
let dbg = new Debugger(g);
|
||||
|
||||
var text;
|
||||
var count = 0;
|
||||
dbg.onNewScript = function (script) {
|
||||
++count;
|
||||
|
|
|
|||
|
|
@ -12,18 +12,18 @@ var o = {};
|
|||
Object.defineProperty(o, "prop", {get: function() { return 1; },
|
||||
set: function() { return 2; },
|
||||
enumerable: true, configurable: true});
|
||||
assertEq(o.toSource(), "({get prop () { return 1; }, set prop () { return 2; }})");
|
||||
assertEq(o.toSource(), "({get prop() { return 1; }, set prop() { return 2; }})");
|
||||
|
||||
// obj.toSource TwoByte
|
||||
Object.defineProperty(o, "prop", {get: function() { return "\u1200"; },
|
||||
set: function() { return "\u1200"; },
|
||||
enumerable: true});
|
||||
assertEq(o.toSource(), '({get prop () { return "\\u1200"; }, set prop () { return "\\u1200"; }})');
|
||||
assertEq(o.toSource(), '({get prop() { return "\\u1200"; }, set prop() { return "\\u1200"; }})');
|
||||
|
||||
var ff = function() { return 10; };
|
||||
ff.toSource = function() { return "((11))"; }
|
||||
Object.defineProperty(o, "prop", {get: ff, set: ff, enumerable: true});
|
||||
assertEq(o.toSource(), "({prop:((11)), prop:((11))})");
|
||||
assertEq(o.toSource(), "({get prop(11), set prop(11)})");
|
||||
|
||||
// XDR
|
||||
load(libdir + 'bytecode-cache.js');
|
||||
|
|
|
|||
|
|
@ -6,11 +6,11 @@ function test() {
|
|||
|
||||
var f = Function(arg1TwoByte, arg2Latin1, bodyLatin1);
|
||||
assertEq(f(10, 20), 60);
|
||||
assertEq(f.toSource().includes("arg1\u1200, arg2"), true);
|
||||
assertEq(f.toSource().includes("arg1\u1200,arg2"), true);
|
||||
|
||||
var bodyTwoByte = "return arg1\u1200 + arg2;";
|
||||
f = Function(arg1TwoByte, arg2Latin1, bodyTwoByte);
|
||||
assertEq(f(30, 40), 70);
|
||||
assertEq(f.toSource().includes("arg1\u1200, arg2"), true);
|
||||
assertEq(f.toSource().includes("arg1\u1200,arg2"), true);
|
||||
}
|
||||
test();
|
||||
|
|
|
|||
|
|
@ -186,7 +186,6 @@ MSG_DEF(JSMSG_AS_AFTER_IMPORT_STAR, 0, JSEXN_SYNTAXERR, "missing keyword 'as'
|
|||
MSG_DEF(JSMSG_AS_AFTER_RESERVED_WORD, 1, JSEXN_SYNTAXERR, "missing keyword 'as' after reserved word '{0}'")
|
||||
MSG_DEF(JSMSG_ASYNC_GENERATOR, 0, JSEXN_SYNTAXERR, "generator function or method can't be async")
|
||||
MSG_DEF(JSMSG_AWAIT_IN_DEFAULT, 0, JSEXN_SYNTAXERR, "await can't be used in default expression")
|
||||
MSG_DEF(JSMSG_BAD_ANON_GENERATOR_RETURN, 0, JSEXN_TYPEERR, "anonymous generator function returns a value")
|
||||
MSG_DEF(JSMSG_BAD_ARROW_ARGS, 0, JSEXN_SYNTAXERR, "invalid arrow-function arguments (parentheses around the arrow-function may help)")
|
||||
MSG_DEF(JSMSG_BAD_BINDING, 1, JSEXN_SYNTAXERR, "redefining {0} is deprecated")
|
||||
MSG_DEF(JSMSG_BAD_CONST_DECL, 0, JSEXN_SYNTAXERR, "missing = in const declaration")
|
||||
|
|
@ -200,12 +199,12 @@ MSG_DEF(JSMSG_BAD_FOR_EACH_LOOP, 0, JSEXN_SYNTAXERR, "invalid for each loo
|
|||
MSG_DEF(JSMSG_BAD_FOR_LEFTSIDE, 0, JSEXN_SYNTAXERR, "invalid for-in/of left-hand side")
|
||||
MSG_DEF(JSMSG_LEXICAL_DECL_DEFINES_LET,0, JSEXN_SYNTAXERR, "a lexical declaration can't define a 'let' binding")
|
||||
MSG_DEF(JSMSG_LET_STARTING_FOROF_LHS, 0, JSEXN_SYNTAXERR, "an expression X in 'for (X of Y)' must not start with 'let'")
|
||||
MSG_DEF(JSMSG_BAD_GENERATOR_RETURN, 1, JSEXN_TYPEERR, "generator function {0} returns a value")
|
||||
MSG_DEF(JSMSG_BAD_FUNCTION_YIELD, 0, JSEXN_TYPEERR, "can't use 'yield' in a function that can return a value")
|
||||
MSG_DEF(JSMSG_BAD_GENERATOR_RETURN, 0, JSEXN_TYPEERR, "generator function can't return a value")
|
||||
MSG_DEF(JSMSG_BAD_GENEXP_BODY, 1, JSEXN_SYNTAXERR, "illegal use of {0} in generator expression")
|
||||
MSG_DEF(JSMSG_BAD_INCOP_OPERAND, 0, JSEXN_REFERENCEERR, "invalid increment/decrement operand")
|
||||
MSG_DEF(JSMSG_BAD_INCOP_OPERAND, 0, JSEXN_SYNTAXERR, "invalid increment/decrement operand")
|
||||
MSG_DEF(JSMSG_BAD_METHOD_DEF, 0, JSEXN_SYNTAXERR, "bad method definition")
|
||||
MSG_DEF(JSMSG_BAD_OCTAL, 1, JSEXN_SYNTAXERR, "{0} is not a legal ECMA-262 octal constant")
|
||||
MSG_DEF(JSMSG_BAD_OPERAND, 1, JSEXN_SYNTAXERR, "invalid {0} operand")
|
||||
MSG_DEF(JSMSG_BAD_POW_LEFTSIDE, 0, JSEXN_SYNTAXERR, "unparenthesized unary expression can't appear on the left-hand side of '**'")
|
||||
MSG_DEF(JSMSG_BAD_PROP_ID, 0, JSEXN_SYNTAXERR, "invalid property id")
|
||||
MSG_DEF(JSMSG_BAD_RETURN_OR_YIELD, 1, JSEXN_SYNTAXERR, "{0} not in function")
|
||||
|
|
@ -262,6 +261,8 @@ MSG_DEF(JSMSG_GARBAGE_AFTER_INPUT, 2, JSEXN_SYNTAXERR, "unexpected garbage a
|
|||
MSG_DEF(JSMSG_IDSTART_AFTER_NUMBER, 0, JSEXN_SYNTAXERR, "identifier starts immediately after numeric literal")
|
||||
MSG_DEF(JSMSG_ILLEGAL_CHARACTER, 0, JSEXN_SYNTAXERR, "illegal character")
|
||||
MSG_DEF(JSMSG_IMPORT_DECL_AT_TOP_LEVEL, 0, JSEXN_SYNTAXERR, "import declarations may only appear at top level of a module")
|
||||
MSG_DEF(JSMSG_OF_AFTER_FOR_LOOP_DECL, 0, JSEXN_SYNTAXERR, "a declaration in the head of a for-of loop can't have an initializer")
|
||||
MSG_DEF(JSMSG_IN_AFTER_LEXICAL_FOR_DECL,0,JSEXN_SYNTAXERR, "a lexical declaration in the head of a for-in loop can't have an initializer")
|
||||
MSG_DEF(JSMSG_INVALID_FOR_IN_DECL_WITH_INIT,0,JSEXN_SYNTAXERR,"for-in loop head declarations may not have initializers")
|
||||
MSG_DEF(JSMSG_LABEL_NOT_FOUND, 0, JSEXN_SYNTAXERR, "label not found")
|
||||
MSG_DEF(JSMSG_LET_COMP_BINDING, 0, JSEXN_SYNTAXERR, "'let' is not a valid name for a comprehension variable")
|
||||
|
|
|
|||
|
|
@ -4250,7 +4250,7 @@ JS_GetFunctionScript(JSContext* cx, HandleFunction fun)
|
|||
*/
|
||||
static bool
|
||||
CompileFunction(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
|
||||
const char* name,
|
||||
HandleAtom name, bool isInvalidName,
|
||||
SourceBufferHolder& srcBuf, uint32_t parameterListEnd,
|
||||
HandleObject enclosingEnv, HandleScope enclosingScope,
|
||||
MutableHandleFunction fun)
|
||||
|
|
@ -4261,13 +4261,8 @@ CompileFunction(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
|
|||
assertSameCompartment(cx, enclosingEnv);
|
||||
RootedAtom funAtom(cx);
|
||||
|
||||
if (name) {
|
||||
funAtom = Atomize(cx, name, strlen(name));
|
||||
if (!funAtom)
|
||||
return false;
|
||||
}
|
||||
|
||||
fun.set(NewScriptedFunction(cx, 0, JSFunction::INTERPRETED_NORMAL, funAtom,
|
||||
fun.set(NewScriptedFunction(cx, 0, JSFunction::INTERPRETED_NORMAL,
|
||||
isInvalidName ? nullptr : name,
|
||||
/* proto = */ nullptr,
|
||||
gc::AllocKind::FUNCTION, TenuredObject,
|
||||
enclosingEnv));
|
||||
|
|
@ -4285,11 +4280,17 @@ CompileFunction(JSContext* cx, const ReadOnlyCompileOptions& optionsArg,
|
|||
return false;
|
||||
}
|
||||
|
||||
// When function name is not a valid identifier, the generated function
|
||||
// source in srcBuf doesn't have a function name. Set it here.
|
||||
if (isInvalidName)
|
||||
fun->setAtom(name);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static MOZ_MUST_USE bool
|
||||
BuildFunctionString(unsigned nargs, const char* const* argnames,
|
||||
BuildFunctionString(const char* name, size_t nameLen,
|
||||
unsigned nargs, const char* const* argnames,
|
||||
const SourceBufferHolder& srcBuf, StringBuffer* out,
|
||||
uint32_t* parameterListEnd)
|
||||
{
|
||||
|
|
@ -4298,6 +4299,12 @@ BuildFunctionString(unsigned nargs, const char* const* argnames,
|
|||
|
||||
if (!out->ensureTwoByteChars())
|
||||
return false;
|
||||
if (!out->append("function "))
|
||||
return false;
|
||||
if (name) {
|
||||
if (!out->append(name, nameLen))
|
||||
return false;
|
||||
}
|
||||
if (!out->append("("))
|
||||
return false;
|
||||
for (unsigned i = 0; i < nargs; i++) {
|
||||
|
|
@ -4334,15 +4341,32 @@ JS::CompileFunction(JSContext* cx, AutoObjectVector& envChain,
|
|||
if (!CreateNonSyntacticEnvironmentChain(cx, envChain, &env, &scope))
|
||||
return false;
|
||||
|
||||
size_t nameLen = 0;
|
||||
bool isInvalidName = false;
|
||||
RootedAtom nameAtom(cx);
|
||||
if (name) {
|
||||
nameLen = strlen(name);
|
||||
nameAtom = Atomize(cx, name, nameLen);
|
||||
if (!nameAtom)
|
||||
return false;
|
||||
|
||||
// If name is not valid identifier
|
||||
if (!js::frontend::IsIdentifier(name, nameLen))
|
||||
isInvalidName = true;
|
||||
}
|
||||
|
||||
uint32_t parameterListEnd;
|
||||
StringBuffer funStr(cx);
|
||||
if (!BuildFunctionString(nargs, argnames, srcBuf, &funStr, ¶meterListEnd))
|
||||
if (!BuildFunctionString(isInvalidName ? nullptr : name, nameLen, nargs, argnames, srcBuf,
|
||||
&funStr, ¶meterListEnd)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t newLen = funStr.length();
|
||||
SourceBufferHolder newSrcBuf(funStr.stealChars(), newLen, SourceBufferHolder::GiveOwnership);
|
||||
|
||||
return CompileFunction(cx, options, name, newSrcBuf, parameterListEnd, env, scope, fun);
|
||||
return CompileFunction(cx, options, nameAtom, isInvalidName, newSrcBuf, parameterListEnd, env,
|
||||
scope, fun);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
|
|
|
|||
|
|
@ -781,8 +781,10 @@ CreateFunctionPrototype(JSContext* cx, JSProtoKey key)
|
|||
|
||||
RootedFunction functionProto(cx, &functionProto_->as<JSFunction>());
|
||||
|
||||
const char* rawSource = "() {\n}";
|
||||
const char* rawSource = "function () {\n}";
|
||||
size_t sourceLen = strlen(rawSource);
|
||||
size_t begin = 9;
|
||||
MOZ_ASSERT(rawSource[begin] == '(');
|
||||
mozilla::UniquePtr<char16_t[], JS::FreePolicy> source(InflateString(cx, rawSource, &sourceLen));
|
||||
if (!source)
|
||||
return nullptr;
|
||||
|
|
@ -804,8 +806,9 @@ CreateFunctionPrototype(JSContext* cx, JSProtoKey key)
|
|||
RootedScript script(cx, JSScript::Create(cx,
|
||||
options,
|
||||
sourceObject,
|
||||
0,
|
||||
ss->length()));
|
||||
begin,
|
||||
ss->length(),
|
||||
0));
|
||||
if (!script || !JSScript::initFunctionPrototype(cx, script, functionProto))
|
||||
return nullptr;
|
||||
|
||||
|
|
@ -985,53 +988,62 @@ js::FunctionToString(JSContext* cx, HandleFunction fun, bool prettyPrint)
|
|||
}
|
||||
}
|
||||
|
||||
if (fun->isAsync()) {
|
||||
if (!out.append("async "))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool funIsMethodOrNonArrowLambda = (fun->isLambda() && !fun->isArrow()) || fun->isMethod() ||
|
||||
fun->isGetter() || fun->isSetter();
|
||||
bool funIsNonArrowLambda = fun->isLambda() && !fun->isArrow();
|
||||
bool haveSource = fun->isInterpreted() && !fun->isSelfHostedBuiltin();
|
||||
|
||||
// If we're not in pretty mode, put parentheses around lambda functions and methods.
|
||||
if (haveSource && !prettyPrint && funIsMethodOrNonArrowLambda) {
|
||||
// If we're not in pretty mode, put parentheses around lambda functions
|
||||
// so that eval returns lambda, not function statement.
|
||||
if (haveSource && !prettyPrint && funIsNonArrowLambda) {
|
||||
if (!out.append("("))
|
||||
return nullptr;
|
||||
}
|
||||
if (!fun->isArrow()) {
|
||||
bool ok;
|
||||
if (fun->isStarGenerator() && !fun->isAsync())
|
||||
ok = out.append("function* ");
|
||||
else
|
||||
ok = out.append("function ");
|
||||
if (!ok)
|
||||
return nullptr;
|
||||
}
|
||||
if (fun->explicitName()) {
|
||||
if (!out.append(fun->explicitName()))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (haveSource && !script->scriptSource()->hasSourceData() &&
|
||||
!JSScript::loadSource(cx, script->scriptSource(), &haveSource))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto AppendPrelude = [&out, &fun]() {
|
||||
if (fun->isAsync()) {
|
||||
if (!out.append("async "))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!fun->isArrow()) {
|
||||
if (!out.append("function"))
|
||||
return false;
|
||||
|
||||
if (fun->isStarGenerator()) {
|
||||
if (!out.append('*'))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (fun->explicitName()) {
|
||||
if (!out.append(' '))
|
||||
return false;
|
||||
if (!out.append(fun->explicitName()))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
if (haveSource) {
|
||||
Rooted<JSFlatString*> src(cx, script->sourceData(cx));
|
||||
Rooted<JSFlatString*> src(cx, script->sourceDataWithPrelude(cx));
|
||||
if (!src)
|
||||
return nullptr;
|
||||
|
||||
if (!out.append(src))
|
||||
return nullptr;
|
||||
|
||||
if (!prettyPrint && funIsMethodOrNonArrowLambda) {
|
||||
if (!prettyPrint && funIsNonArrowLambda) {
|
||||
if (!out.append(")"))
|
||||
return nullptr;
|
||||
}
|
||||
} else if (fun->isInterpreted() && !fun->isSelfHostedBuiltin()) {
|
||||
if (!out.append("() {\n ") ||
|
||||
if (!AppendPrelude() ||
|
||||
!out.append("() {\n ") ||
|
||||
!out.append("[sourceless code]") ||
|
||||
!out.append("\n}"))
|
||||
{
|
||||
|
|
@ -1042,13 +1054,15 @@ js::FunctionToString(JSContext* cx, HandleFunction fun, bool prettyPrint)
|
|||
|
||||
bool derived = fun->infallibleIsDefaultClassConstructor(cx);
|
||||
if (derived && fun->isDerivedClassConstructor()) {
|
||||
if (!out.append("(...args) {\n ") ||
|
||||
if (!AppendPrelude() ||
|
||||
!out.append("(...args) {\n ") ||
|
||||
!out.append("super(...args);\n}"))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
if (!out.append("() {\n "))
|
||||
if (!AppendPrelude() ||
|
||||
!out.append("() {\n "))
|
||||
return nullptr;
|
||||
|
||||
if (!derived) {
|
||||
|
|
@ -1635,7 +1649,18 @@ FunctionConstructor(JSContext* cx, const CallArgs& args, GeneratorKind generator
|
|||
|
||||
StringBuffer sb(cx);
|
||||
|
||||
if (!sb.append('('))
|
||||
if (isAsync) {
|
||||
if (!sb.append("async "))
|
||||
return false;
|
||||
}
|
||||
if (!sb.append("function"))
|
||||
return false;
|
||||
if (isStarGenerator && !isAsync) {
|
||||
if (!sb.append('*'))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!sb.append(" anonymous("))
|
||||
return false;
|
||||
|
||||
if (args.length() > 1) {
|
||||
|
|
@ -1656,12 +1681,15 @@ FunctionConstructor(JSContext* cx, const CallArgs& args, GeneratorKind generator
|
|||
|
||||
if (i < args.length() - 2) {
|
||||
// Step 9.d.iii.
|
||||
if (!sb.append(", "))
|
||||
if (!sb.append(","))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!sb.append('\n'))
|
||||
return false;
|
||||
|
||||
// Remember the position of ")".
|
||||
Maybe<uint32_t> parameterListEnd = Some(uint32_t(sb.length()));
|
||||
MOZ_ASSERT(FunctionConstructorMedialSigils[0] == ')');
|
||||
|
|
|
|||
|
|
@ -235,6 +235,7 @@ XDRRelazificationInfo(XDRState<mode>* xdr, HandleFunction fun, HandleScript scri
|
|||
{
|
||||
uint32_t begin = script->sourceStart();
|
||||
uint32_t end = script->sourceEnd();
|
||||
uint32_t preludeStart = script->preludeStart();
|
||||
uint32_t lineno = script->lineno();
|
||||
uint32_t column = script->column();
|
||||
|
||||
|
|
@ -242,6 +243,7 @@ XDRRelazificationInfo(XDRState<mode>* xdr, HandleFunction fun, HandleScript scri
|
|||
packedFields = lazy->packedFields();
|
||||
MOZ_ASSERT(begin == lazy->begin());
|
||||
MOZ_ASSERT(end == lazy->end());
|
||||
MOZ_ASSERT(preludeStart == lazy->preludeStart());
|
||||
MOZ_ASSERT(lineno == lazy->lineno());
|
||||
MOZ_ASSERT(column == lazy->column());
|
||||
// We can assert we have no inner functions because we don't
|
||||
|
|
@ -255,7 +257,7 @@ XDRRelazificationInfo(XDRState<mode>* xdr, HandleFunction fun, HandleScript scri
|
|||
|
||||
if (mode == XDR_DECODE) {
|
||||
lazy.set(LazyScript::Create(cx, fun, script, enclosingScope, script,
|
||||
packedFields, begin, end, lineno, column));
|
||||
packedFields, begin, end, preludeStart, lineno, column));
|
||||
|
||||
// As opposed to XDRLazyScript, we need to restore the runtime bits
|
||||
// of the script, as we are trying to match the fact this function
|
||||
|
|
@ -517,7 +519,7 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope, HandleScrip
|
|||
sourceObject = &enclosingScript->sourceObject()->as<ScriptSourceObject>();
|
||||
}
|
||||
|
||||
script = JSScript::Create(cx, options, sourceObject, 0, 0);
|
||||
script = JSScript::Create(cx, options, sourceObject, 0, 0, 0);
|
||||
if (!script)
|
||||
return false;
|
||||
|
||||
|
|
@ -600,6 +602,8 @@ js::XDRScript(XDRState<mode>* xdr, HandleScope scriptEnclosingScope, HandleScrip
|
|||
return false;
|
||||
if (!xdr->codeUint32(&script->sourceEnd_))
|
||||
return false;
|
||||
if (!xdr->codeUint32(&script->preludeStart_))
|
||||
return false;
|
||||
|
||||
if (!xdr->codeUint32(&lineno) ||
|
||||
!xdr->codeUint32(&column) ||
|
||||
|
|
@ -930,6 +934,7 @@ js::XDRLazyScript(XDRState<mode>* xdr, HandleScope enclosingScope, HandleScript
|
|||
{
|
||||
uint32_t begin;
|
||||
uint32_t end;
|
||||
uint32_t preludeStart;
|
||||
uint32_t lineno;
|
||||
uint32_t column;
|
||||
uint64_t packedFields;
|
||||
|
|
@ -943,12 +948,14 @@ js::XDRLazyScript(XDRState<mode>* xdr, HandleScope enclosingScope, HandleScript
|
|||
|
||||
begin = lazy->begin();
|
||||
end = lazy->end();
|
||||
preludeStart = lazy->preludeStart();
|
||||
lineno = lazy->lineno();
|
||||
column = lazy->column();
|
||||
packedFields = lazy->packedFields();
|
||||
}
|
||||
|
||||
if (!xdr->codeUint32(&begin) || !xdr->codeUint32(&end) ||
|
||||
!xdr->codeUint32(&preludeStart) ||
|
||||
!xdr->codeUint32(&lineno) || !xdr->codeUint32(&column) ||
|
||||
!xdr->codeUint64(&packedFields))
|
||||
{
|
||||
|
|
@ -957,7 +964,7 @@ js::XDRLazyScript(XDRState<mode>* xdr, HandleScope enclosingScope, HandleScript
|
|||
|
||||
if (mode == XDR_DECODE) {
|
||||
lazy.set(LazyScript::Create(cx, fun, nullptr, enclosingScope, enclosingScript,
|
||||
packedFields, begin, end, lineno, column));
|
||||
packedFields, begin, end, preludeStart, lineno, column));
|
||||
if (!lazy)
|
||||
return false;
|
||||
fun->initLazyScript(lazy);
|
||||
|
|
@ -1430,6 +1437,13 @@ JSScript::sourceData(JSContext* cx)
|
|||
return scriptSource()->substring(cx, sourceStart(), sourceEnd());
|
||||
}
|
||||
|
||||
JSFlatString*
|
||||
JSScript::sourceDataWithPrelude(JSContext* cx)
|
||||
{
|
||||
MOZ_ASSERT(scriptSource()->hasSourceData());
|
||||
return scriptSource()->substring(cx, preludeStart(), sourceEnd());
|
||||
}
|
||||
|
||||
UncompressedSourceCache::AutoHoldEntry::AutoHoldEntry()
|
||||
: cache_(nullptr), sourceChunk_()
|
||||
{
|
||||
|
|
@ -2428,7 +2442,8 @@ JSScript::initCompartment(ExclusiveContext* cx)
|
|||
|
||||
/* static */ JSScript*
|
||||
JSScript::Create(ExclusiveContext* cx, const ReadOnlyCompileOptions& options,
|
||||
HandleObject sourceObject, uint32_t bufStart, uint32_t bufEnd)
|
||||
HandleObject sourceObject, uint32_t bufStart, uint32_t bufEnd,
|
||||
uint32_t preludeStart)
|
||||
{
|
||||
MOZ_ASSERT(bufStart <= bufEnd);
|
||||
|
||||
|
|
@ -2450,6 +2465,7 @@ JSScript::Create(ExclusiveContext* cx, const ReadOnlyCompileOptions& options,
|
|||
script->setSourceObject(sourceObject);
|
||||
script->sourceStart_ = bufStart;
|
||||
script->sourceEnd_ = bufEnd;
|
||||
script->preludeStart_ = preludeStart;
|
||||
|
||||
return script;
|
||||
}
|
||||
|
|
@ -3382,7 +3398,8 @@ CreateEmptyScriptForClone(JSContext* cx, HandleScript src)
|
|||
.setNoScriptRval(src->noScriptRval())
|
||||
.setVersion(src->getVersion());
|
||||
|
||||
return JSScript::Create(cx, options, sourceObject, src->sourceStart(), src->sourceEnd());
|
||||
return JSScript::Create(cx, options, sourceObject, src->sourceStart(), src->sourceEnd(),
|
||||
src->preludeStart());
|
||||
}
|
||||
|
||||
JSScript*
|
||||
|
|
@ -3932,7 +3949,8 @@ JSScript::formalLivesInArgumentsObject(unsigned argSlot)
|
|||
}
|
||||
|
||||
LazyScript::LazyScript(JSFunction* fun, void* table, uint64_t packedFields,
|
||||
uint32_t begin, uint32_t end, uint32_t lineno, uint32_t column)
|
||||
uint32_t begin, uint32_t end,
|
||||
uint32_t preludeStart, uint32_t lineno, uint32_t column)
|
||||
: script_(nullptr),
|
||||
function_(fun),
|
||||
enclosingScope_(nullptr),
|
||||
|
|
@ -3941,6 +3959,7 @@ LazyScript::LazyScript(JSFunction* fun, void* table, uint64_t packedFields,
|
|||
packedFields_(packedFields),
|
||||
begin_(begin),
|
||||
end_(end),
|
||||
preludeStart_(preludeStart),
|
||||
lineno_(lineno),
|
||||
column_(column)
|
||||
{
|
||||
|
|
@ -3990,7 +4009,7 @@ LazyScript::maybeForwardedScriptSource() const
|
|||
/* static */ LazyScript*
|
||||
LazyScript::CreateRaw(ExclusiveContext* cx, HandleFunction fun,
|
||||
uint64_t packedFields, uint32_t begin, uint32_t end,
|
||||
uint32_t lineno, uint32_t column)
|
||||
uint32_t preludeStart, uint32_t lineno, uint32_t column)
|
||||
{
|
||||
union {
|
||||
PackedView p;
|
||||
|
|
@ -4018,7 +4037,8 @@ LazyScript::CreateRaw(ExclusiveContext* cx, HandleFunction fun,
|
|||
|
||||
cx->compartment()->scheduleDelazificationForDebugger();
|
||||
|
||||
return new (res) LazyScript(fun, table.forget(), packed, begin, end, lineno, column);
|
||||
return new (res) LazyScript(fun, table.forget(), packed, begin, end,
|
||||
preludeStart, lineno, column);
|
||||
}
|
||||
|
||||
/* static */ LazyScript*
|
||||
|
|
@ -4026,7 +4046,8 @@ LazyScript::Create(ExclusiveContext* cx, HandleFunction fun,
|
|||
const frontend::AtomVector& closedOverBindings,
|
||||
Handle<GCVector<JSFunction*, 8>> innerFunctions,
|
||||
JSVersion version,
|
||||
uint32_t begin, uint32_t end, uint32_t lineno, uint32_t column)
|
||||
uint32_t begin, uint32_t end,
|
||||
uint32_t preludeStart, uint32_t lineno, uint32_t column)
|
||||
{
|
||||
union {
|
||||
PackedView p;
|
||||
|
|
@ -4049,7 +4070,8 @@ LazyScript::Create(ExclusiveContext* cx, HandleFunction fun,
|
|||
p.isDerivedClassConstructor = false;
|
||||
p.needsHomeObject = false;
|
||||
|
||||
LazyScript* res = LazyScript::CreateRaw(cx, fun, packedFields, begin, end, lineno, column);
|
||||
LazyScript* res = LazyScript::CreateRaw(cx, fun, packedFields, begin, end, preludeStart,
|
||||
lineno, column);
|
||||
if (!res)
|
||||
return nullptr;
|
||||
|
||||
|
|
@ -4070,7 +4092,7 @@ LazyScript::Create(ExclusiveContext* cx, HandleFunction fun,
|
|||
HandleScript script, HandleScope enclosingScope,
|
||||
HandleScript enclosingScript,
|
||||
uint64_t packedFields, uint32_t begin, uint32_t end,
|
||||
uint32_t lineno, uint32_t column)
|
||||
uint32_t preludeStart, uint32_t lineno, uint32_t column)
|
||||
{
|
||||
// Dummy atom which is not a valid property name.
|
||||
RootedAtom dummyAtom(cx, cx->names().comma);
|
||||
|
|
@ -4079,7 +4101,8 @@ LazyScript::Create(ExclusiveContext* cx, HandleFunction fun,
|
|||
// holding this lazy script.
|
||||
HandleFunction dummyFun = fun;
|
||||
|
||||
LazyScript* res = LazyScript::CreateRaw(cx, fun, packedFields, begin, end, lineno, column);
|
||||
LazyScript* res = LazyScript::CreateRaw(cx, fun, packedFields, begin, end, preludeStart,
|
||||
lineno, column);
|
||||
if (!res)
|
||||
return nullptr;
|
||||
|
||||
|
|
|
|||
|
|
@ -575,10 +575,6 @@ class ScriptSource
|
|||
introductionOffset_ = offset;
|
||||
hasIntroductionOffset_ = true;
|
||||
}
|
||||
|
||||
uint32_t parameterListEnd() const {
|
||||
return parameterListEnd_;
|
||||
}
|
||||
};
|
||||
|
||||
class ScriptSourceHolder
|
||||
|
|
@ -857,9 +853,19 @@ class JSScript : public js::gc::TenuredCell
|
|||
|
||||
uint32_t bodyScopeIndex_; /* index into the scopes array of the body scope */
|
||||
|
||||
/* Range of characters in scriptSource which contains this script's source. */
|
||||
// Range of characters in scriptSource which contains this script's source.
|
||||
// each field points the following location.
|
||||
//
|
||||
// function * f(a, b) { return a + b; }
|
||||
// ^ ^ ^
|
||||
// | | |
|
||||
// | sourceStart_ sourceEnd_
|
||||
// |
|
||||
// preludeStart_
|
||||
//
|
||||
uint32_t sourceStart_;
|
||||
uint32_t sourceEnd_;
|
||||
uint32_t preludeStart_;
|
||||
|
||||
// Number of times the script has been called or has had backedges taken.
|
||||
// When running in ion, also increased for any inlined scripts. Reset if
|
||||
|
|
@ -1020,7 +1026,7 @@ class JSScript : public js::gc::TenuredCell
|
|||
// instead of private to suppress -Wunused-private-field compiler warnings.
|
||||
protected:
|
||||
#if JS_BITS_PER_WORD == 32
|
||||
// Currently no padding is needed.
|
||||
uint32_t padding;
|
||||
#endif
|
||||
|
||||
//
|
||||
|
|
@ -1031,7 +1037,7 @@ class JSScript : public js::gc::TenuredCell
|
|||
static JSScript* Create(js::ExclusiveContext* cx,
|
||||
const JS::ReadOnlyCompileOptions& options,
|
||||
js::HandleObject sourceObject, uint32_t sourceStart,
|
||||
uint32_t sourceEnd);
|
||||
uint32_t sourceEnd, uint32_t preludeStart);
|
||||
|
||||
void initCompartment(js::ExclusiveContext* cx);
|
||||
|
||||
|
|
@ -1178,6 +1184,10 @@ class JSScript : public js::gc::TenuredCell
|
|||
return sourceEnd_;
|
||||
}
|
||||
|
||||
size_t preludeStart() const {
|
||||
return preludeStart_;
|
||||
}
|
||||
|
||||
bool noScriptRval() const {
|
||||
return noScriptRval_;
|
||||
}
|
||||
|
|
@ -1501,7 +1511,8 @@ class JSScript : public js::gc::TenuredCell
|
|||
bool mayReadFrameArgsDirectly();
|
||||
|
||||
JSFlatString* sourceData(JSContext* cx);
|
||||
|
||||
JSFlatString* sourceDataWithPrelude(JSContext* cx);
|
||||
|
||||
static bool loadSource(JSContext* cx, js::ScriptSource* ss, bool* worked);
|
||||
|
||||
void setSourceObject(JSObject* object);
|
||||
|
|
@ -1920,7 +1931,8 @@ class LazyScript : public gc::TenuredCell
|
|||
// instead of private to suppress -Wunused-private-field compiler warnings.
|
||||
protected:
|
||||
#if JS_BITS_PER_WORD == 32
|
||||
uint32_t padding;
|
||||
// uint32_t padding;
|
||||
// Currently no padding is needed.
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
|
@ -1960,20 +1972,25 @@ class LazyScript : public gc::TenuredCell
|
|||
};
|
||||
|
||||
// Source location for the script.
|
||||
// See the comment in JSScript for the details.
|
||||
uint32_t begin_;
|
||||
uint32_t end_;
|
||||
uint32_t preludeStart_;
|
||||
// Line and column of |begin_| position, that is the position where we
|
||||
// start parsing.
|
||||
uint32_t lineno_;
|
||||
uint32_t column_;
|
||||
|
||||
LazyScript(JSFunction* fun, void* table, uint64_t packedFields,
|
||||
uint32_t begin, uint32_t end, uint32_t lineno, uint32_t column);
|
||||
uint32_t begin, uint32_t end, uint32_t preludeStart,
|
||||
uint32_t lineno, uint32_t column);
|
||||
|
||||
// Create a LazyScript without initializing the closedOverBindings and the
|
||||
// innerFunctions. To be GC-safe, the caller must initialize both vectors
|
||||
// with valid atoms and functions.
|
||||
static LazyScript* CreateRaw(ExclusiveContext* cx, HandleFunction fun,
|
||||
uint64_t packedData, uint32_t begin, uint32_t end,
|
||||
uint32_t lineno, uint32_t column);
|
||||
uint32_t preludeStart, uint32_t lineno, uint32_t column);
|
||||
|
||||
public:
|
||||
static const uint32_t NumClosedOverBindingsLimit = 1 << NumClosedOverBindingsBits;
|
||||
|
|
@ -1985,7 +2002,7 @@ class LazyScript : public gc::TenuredCell
|
|||
const frontend::AtomVector& closedOverBindings,
|
||||
Handle<GCVector<JSFunction*, 8>> innerFunctions,
|
||||
JSVersion version, uint32_t begin, uint32_t end,
|
||||
uint32_t lineno, uint32_t column);
|
||||
uint32_t preludeStart, uint32_t lineno, uint32_t column);
|
||||
|
||||
// Create a LazyScript and initialize the closedOverBindings and the
|
||||
// innerFunctions with dummy values to be replaced in a later initialization
|
||||
|
|
@ -2000,7 +2017,7 @@ class LazyScript : public gc::TenuredCell
|
|||
HandleScript script, HandleScope enclosingScope,
|
||||
HandleScript enclosingScript,
|
||||
uint64_t packedData, uint32_t begin, uint32_t end,
|
||||
uint32_t lineno, uint32_t column);
|
||||
uint32_t preludeStart, uint32_t lineno, uint32_t column);
|
||||
|
||||
void initRuntimeFields(uint64_t packedFields);
|
||||
|
||||
|
|
@ -2173,6 +2190,9 @@ class LazyScript : public gc::TenuredCell
|
|||
uint32_t end() const {
|
||||
return end_;
|
||||
}
|
||||
uint32_t preludeStart() const {
|
||||
return preludeStart_;
|
||||
}
|
||||
uint32_t lineno() const {
|
||||
return lineno_;
|
||||
}
|
||||
|
|
@ -2199,7 +2219,8 @@ class LazyScript : public gc::TenuredCell
|
|||
};
|
||||
|
||||
/* If this fails, add/remove padding within LazyScript. */
|
||||
JS_STATIC_ASSERT(sizeof(LazyScript) % js::gc::CellSize == 0);
|
||||
static_assert(sizeof(LazyScript) % js::gc::CellSize == 0,
|
||||
"Size of LazyScript must be an integral multiple of js::gc::CellSize");
|
||||
|
||||
struct ScriptAndCounts
|
||||
{
|
||||
|
|
|
|||
370
js/src/tests/ecma_2017/Function/Object-toSource.js
Normal file
370
js/src/tests/ecma_2017/Function/Object-toSource.js
Normal file
|
|
@ -0,0 +1,370 @@
|
|||
var BUGNUMBER = 1317400;
|
||||
var summary = "Function string representation in Object.prototype.toSource";
|
||||
|
||||
print(BUGNUMBER + ": " + summary);
|
||||
|
||||
// Methods.
|
||||
|
||||
assertEq(({ foo(){} }).toSource(),
|
||||
"({foo(){}})");
|
||||
assertEq(({ *foo(){} }).toSource(),
|
||||
"({*foo(){}})");
|
||||
assertEq(({ async foo(){} }).toSource(),
|
||||
"({async foo(){}})");
|
||||
|
||||
assertEq(({ 1(){} }).toSource(),
|
||||
"({1(){}})");
|
||||
|
||||
// Methods with more spacing.
|
||||
// Spacing is kept.
|
||||
|
||||
assertEq(({ foo (){} }).toSource(),
|
||||
"({foo (){}})");
|
||||
assertEq(({ foo () {} }).toSource(),
|
||||
"({foo () {}})");
|
||||
|
||||
// Methods with computed name.
|
||||
// Method syntax is composed.
|
||||
|
||||
let name = "foo";
|
||||
assertEq(({ [name](){} }).toSource(),
|
||||
"({foo(){}})");
|
||||
assertEq(({ *[name](){} }).toSource(),
|
||||
"({*foo(){}})");
|
||||
assertEq(({ async [name](){} }).toSource(),
|
||||
"({async foo(){}})");
|
||||
|
||||
assertEq(({ [ Symbol.iterator ](){} }).toSource(),
|
||||
"({[Symbol.iterator](){}})");
|
||||
|
||||
// Accessors.
|
||||
|
||||
assertEq(({ get foo(){} }).toSource(),
|
||||
"({get foo(){}})");
|
||||
assertEq(({ set foo(v){} }).toSource(),
|
||||
"({set foo(v){}})");
|
||||
|
||||
// Accessors with computed name.
|
||||
// Method syntax is composed.
|
||||
|
||||
assertEq(({ get [name](){} }).toSource(),
|
||||
"({get foo(){}})");
|
||||
assertEq(({ set [name](v){} }).toSource(),
|
||||
"({set foo(v){}})");
|
||||
|
||||
assertEq(({ get [ Symbol.iterator ](){} }).toSource(),
|
||||
"({get [Symbol.iterator](){}})");
|
||||
assertEq(({ set [ Symbol.iterator ](v){} }).toSource(),
|
||||
"({set [Symbol.iterator](v){}})");
|
||||
|
||||
// Getter and setter with same name.
|
||||
// Getter always comes before setter.
|
||||
|
||||
assertEq(({ get foo(){}, set foo(v){} }).toSource(),
|
||||
"({get foo(){}, set foo(v){}})");
|
||||
assertEq(({ set foo(v){}, get foo(){} }).toSource(),
|
||||
"({get foo(){}, set foo(v){}})");
|
||||
|
||||
// Normal properties.
|
||||
|
||||
assertEq(({ foo: function(){} }).toSource(),
|
||||
"({foo:(function(){})})");
|
||||
assertEq(({ foo: function bar(){} }).toSource(),
|
||||
"({foo:(function bar(){})})");
|
||||
assertEq(({ foo: function*(){} }).toSource(),
|
||||
"({foo:(function*(){})})");
|
||||
assertEq(({ foo: async function(){} }).toSource(),
|
||||
"({foo:(async function(){})})");
|
||||
|
||||
// Normal properties with computed name.
|
||||
|
||||
assertEq(({ [ Symbol.iterator ]: function(){} }).toSource(),
|
||||
"({[Symbol.iterator]:(function(){})})");
|
||||
|
||||
// Dynamically defined properties with function expression.
|
||||
// Never become a method syntax.
|
||||
|
||||
let obj = {};
|
||||
obj.foo = function() {};
|
||||
assertEq(obj.toSource(),
|
||||
"({foo:(function() {})})");
|
||||
|
||||
obj = {};
|
||||
Object.defineProperty(obj, "foo", {value: function() {}});
|
||||
assertEq(obj.toSource(),
|
||||
"({})");
|
||||
|
||||
obj = {};
|
||||
Object.defineProperty(obj, "foo", {value: function() {}, enumerable: true});
|
||||
assertEq(obj.toSource(),
|
||||
"({foo:(function() {})})");
|
||||
|
||||
obj = {};
|
||||
Object.defineProperty(obj, "foo", {value: function bar() {}, enumerable: true});
|
||||
assertEq(obj.toSource(),
|
||||
"({foo:(function bar() {})})");
|
||||
|
||||
obj = {};
|
||||
Object.defineProperty(obj, Symbol.iterator, {value: function() {}, enumerable: true});
|
||||
assertEq(obj.toSource(),
|
||||
"({[Symbol.iterator]:(function() {})})");
|
||||
|
||||
// Dynamically defined property with other object's method.
|
||||
// Method syntax is composed.
|
||||
|
||||
let method = ({foo() {}}).foo;
|
||||
|
||||
obj = {};
|
||||
Object.defineProperty(obj, "foo", {value: method, enumerable: true});
|
||||
assertEq(obj.toSource(),
|
||||
"({foo() {}})");
|
||||
|
||||
obj = {};
|
||||
Object.defineProperty(obj, "bar", {value: method, enumerable: true});
|
||||
assertEq(obj.toSource(),
|
||||
"({bar() {}})");
|
||||
|
||||
method = ({*foo() {}}).foo;
|
||||
|
||||
obj = {};
|
||||
Object.defineProperty(obj, "bar", {value: method, enumerable: true});
|
||||
assertEq(obj.toSource(),
|
||||
"({*bar() {}})");
|
||||
|
||||
method = ({async foo() {}}).foo;
|
||||
|
||||
obj = {};
|
||||
Object.defineProperty(obj, "bar", {value: method, enumerable: true});
|
||||
assertEq(obj.toSource(),
|
||||
"({async bar() {}})");
|
||||
|
||||
// Dynamically defined accessors.
|
||||
// Accessor syntax is composed.
|
||||
|
||||
obj = {};
|
||||
Object.defineProperty(obj, "foo", {get: function() {}, enumerable: true});
|
||||
assertEq(obj.toSource(),
|
||||
"({get foo() {}})");
|
||||
|
||||
obj = {};
|
||||
Object.defineProperty(obj, "foo", {set: function() {}, enumerable: true});
|
||||
assertEq(obj.toSource(),
|
||||
"({set foo() {}})");
|
||||
|
||||
obj = {};
|
||||
Object.defineProperty(obj, Symbol.iterator, {get: function() {}, enumerable: true});
|
||||
assertEq(obj.toSource(),
|
||||
"({get [Symbol.iterator]() {}})");
|
||||
|
||||
obj = {};
|
||||
Object.defineProperty(obj, Symbol.iterator, {set: function() {}, enumerable: true});
|
||||
assertEq(obj.toSource(),
|
||||
"({set [Symbol.iterator]() {}})");
|
||||
|
||||
// Dynamically defined accessors with other object's accessors.
|
||||
// Accessor syntax is composed.
|
||||
|
||||
let accessor = Object.getOwnPropertyDescriptor({ get foo() {} }, "foo").get;
|
||||
obj = {};
|
||||
Object.defineProperty(obj, "foo", {get: accessor, enumerable: true});
|
||||
assertEq(obj.toSource(),
|
||||
"({get foo() {}})");
|
||||
|
||||
accessor = Object.getOwnPropertyDescriptor({ get bar() {} }, "bar").get;
|
||||
obj = {};
|
||||
Object.defineProperty(obj, "foo", {get: accessor, enumerable: true});
|
||||
assertEq(obj.toSource(),
|
||||
"({get foo() {}})");
|
||||
|
||||
accessor = Object.getOwnPropertyDescriptor({ set foo(v) {} }, "foo").set;
|
||||
obj = {};
|
||||
Object.defineProperty(obj, "foo", {get: accessor, enumerable: true});
|
||||
assertEq(obj.toSource(),
|
||||
"({get foo(v) {}})");
|
||||
|
||||
accessor = Object.getOwnPropertyDescriptor({ set bar(v) {} }, "bar").set;
|
||||
obj = {};
|
||||
Object.defineProperty(obj, "foo", {get: accessor, enumerable: true});
|
||||
assertEq(obj.toSource(),
|
||||
"({get foo(v) {}})");
|
||||
|
||||
accessor = Object.getOwnPropertyDescriptor({ get foo() {} }, "foo").get;
|
||||
obj = {};
|
||||
Object.defineProperty(obj, "foo", {set: accessor, enumerable: true});
|
||||
assertEq(obj.toSource(),
|
||||
"({set foo() {}})");
|
||||
|
||||
accessor = Object.getOwnPropertyDescriptor({ get bar() {} }, "bar").get;
|
||||
obj = {};
|
||||
Object.defineProperty(obj, "foo", {set: accessor, enumerable: true});
|
||||
assertEq(obj.toSource(),
|
||||
"({set foo() {}})");
|
||||
|
||||
accessor = Object.getOwnPropertyDescriptor({ set foo(v) {} }, "foo").set;
|
||||
obj = {};
|
||||
Object.defineProperty(obj, "foo", {set: accessor, enumerable: true});
|
||||
assertEq(obj.toSource(),
|
||||
"({set foo(v) {}})");
|
||||
|
||||
accessor = Object.getOwnPropertyDescriptor({ set bar(v) {} }, "bar").set;
|
||||
obj = {};
|
||||
Object.defineProperty(obj, "foo", {set: accessor, enumerable: true});
|
||||
assertEq(obj.toSource(),
|
||||
"({set foo(v) {}})");
|
||||
|
||||
// Methods with proxy.
|
||||
// Treated as normal property.
|
||||
|
||||
method = ({foo() {}}).foo;
|
||||
let handler = {
|
||||
get(that, name) {
|
||||
if (name == "toSource") {
|
||||
return function() {
|
||||
return that.toSource();
|
||||
};
|
||||
}
|
||||
return that[name];
|
||||
}
|
||||
};
|
||||
let proxy = new Proxy(method, handler);
|
||||
|
||||
obj = {};
|
||||
Object.defineProperty(obj, "foo", {value: proxy, enumerable: true});
|
||||
assertEq(obj.toSource(),
|
||||
"({foo:foo() {}})");
|
||||
|
||||
// Accessors with proxy.
|
||||
// Accessor syntax is composed.
|
||||
|
||||
accessor = Object.getOwnPropertyDescriptor({ get foo() {} }, "foo").get;
|
||||
proxy = new Proxy(accessor, handler);
|
||||
|
||||
obj = {};
|
||||
Object.defineProperty(obj, "foo", {get: proxy, enumerable: true});
|
||||
assertEq(obj.toSource(),
|
||||
"({get foo() {}})");
|
||||
|
||||
obj = {};
|
||||
Object.defineProperty(obj, "foo", {set: proxy, enumerable: true});
|
||||
assertEq(obj.toSource(),
|
||||
"({set foo() {}})");
|
||||
|
||||
// Methods from other global.
|
||||
// Treated as normal property.
|
||||
|
||||
let g = newGlobal();
|
||||
|
||||
method = g.eval("({ foo() {} }).foo");
|
||||
|
||||
obj = {};
|
||||
Object.defineProperty(obj, "foo", {value: method, enumerable: true});
|
||||
assertEq(obj.toSource(),
|
||||
"({foo:foo() {}})");
|
||||
|
||||
// Accessors from other global.
|
||||
// Accessor syntax is composed.
|
||||
|
||||
accessor = g.eval("Object.getOwnPropertyDescriptor({ get foo() {} }, 'foo').get");
|
||||
|
||||
obj = {};
|
||||
Object.defineProperty(obj, "foo", {get: accessor, enumerable: true});
|
||||
assertEq(obj.toSource(),
|
||||
"({get foo() {}})");
|
||||
|
||||
accessor = g.eval("Object.getOwnPropertyDescriptor({ get bar() {} }, 'bar').get");
|
||||
|
||||
obj = {};
|
||||
Object.defineProperty(obj, "foo", {get: accessor, enumerable: true});
|
||||
assertEq(obj.toSource(),
|
||||
"({get foo() {}})");
|
||||
|
||||
accessor = g.eval("Object.getOwnPropertyDescriptor({ set foo(v) {} }, 'foo').set");
|
||||
|
||||
obj = {};
|
||||
Object.defineProperty(obj, "foo", {get: accessor, enumerable: true});
|
||||
assertEq(obj.toSource(),
|
||||
"({get foo(v) {}})");
|
||||
|
||||
accessor = g.eval("Object.getOwnPropertyDescriptor({ set bar(v) {} }, 'bar').set");
|
||||
|
||||
obj = {};
|
||||
Object.defineProperty(obj, "foo", {get: accessor, enumerable: true});
|
||||
assertEq(obj.toSource(),
|
||||
"({get foo(v) {}})");
|
||||
|
||||
accessor = g.eval("Object.getOwnPropertyDescriptor({ get foo() {} }, 'foo').get");
|
||||
|
||||
obj = {};
|
||||
Object.defineProperty(obj, "foo", {set: accessor, enumerable: true});
|
||||
assertEq(obj.toSource(),
|
||||
"({set foo() {}})");
|
||||
|
||||
accessor = g.eval("Object.getOwnPropertyDescriptor({ get bar() {} }, 'bar').get");
|
||||
|
||||
obj = {};
|
||||
Object.defineProperty(obj, "foo", {set: accessor, enumerable: true});
|
||||
assertEq(obj.toSource(),
|
||||
"({set foo() {}})");
|
||||
|
||||
accessor = g.eval("Object.getOwnPropertyDescriptor({ set foo(v) {} }, 'foo').set");
|
||||
|
||||
obj = {};
|
||||
Object.defineProperty(obj, "foo", {set: accessor, enumerable: true});
|
||||
assertEq(obj.toSource(),
|
||||
"({set foo(v) {}})");
|
||||
|
||||
accessor = g.eval("Object.getOwnPropertyDescriptor({ set bar(v) {} }, 'bar').set");
|
||||
|
||||
obj = {};
|
||||
Object.defineProperty(obj, "foo", {set: accessor, enumerable: true});
|
||||
assertEq(obj.toSource(),
|
||||
"({set foo(v) {}})");
|
||||
|
||||
// **** Some weird cases ****
|
||||
|
||||
// Accessors with generator or async.
|
||||
|
||||
obj = {};
|
||||
Object.defineProperty(obj, "foo", {get: function*() {}, enumerable: true});
|
||||
assertEq(obj.toSource(),
|
||||
"({get foo() {}})");
|
||||
|
||||
obj = {};
|
||||
Object.defineProperty(obj, "foo", {set: async function() {}, enumerable: true});
|
||||
assertEq(obj.toSource(),
|
||||
"({set foo() {}})");
|
||||
|
||||
// Modified toSource.
|
||||
|
||||
obj = { foo() {} };
|
||||
obj.foo.toSource = () => "hello";
|
||||
assertEq(obj.toSource(),
|
||||
"({hello})");
|
||||
|
||||
obj = { foo() {} };
|
||||
obj.foo.toSource = () => "bar() {}";
|
||||
assertEq(obj.toSource(),
|
||||
"({bar() {}})");
|
||||
|
||||
// Modified toSource with different method name.
|
||||
|
||||
obj = {};
|
||||
Object.defineProperty(obj, "foo", {value: function bar() {}, enumerable: true});
|
||||
obj.foo.toSource = () => "hello";
|
||||
assertEq(obj.toSource(),
|
||||
"({foo:hello})");
|
||||
|
||||
obj = {};
|
||||
Object.defineProperty(obj, "foo", {value: function* bar() {}, enumerable: true});
|
||||
obj.foo.toSource = () => "hello";
|
||||
assertEq(obj.toSource(),
|
||||
"({foo:hello})");
|
||||
|
||||
obj = {};
|
||||
Object.defineProperty(obj, "foo", {value: async function bar() {}, enumerable: true});
|
||||
obj.foo.toSource = () => "hello";
|
||||
assertEq(obj.toSource(),
|
||||
"({foo:hello})");
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
||||
0
js/src/tests/ecma_2017/Function/browser.js
Normal file
0
js/src/tests/ecma_2017/Function/browser.js
Normal file
0
js/src/tests/ecma_2017/Function/shell.js
Normal file
0
js/src/tests/ecma_2017/Function/shell.js
Normal file
|
|
@ -109,7 +109,7 @@ function TestGeneratorFunction() {
|
|||
// Doesn't matter particularly what string gets serialized, as long
|
||||
// as it contains "function*" and "yield 10".
|
||||
assertEq(GeneratorFunction('yield 10').toString(),
|
||||
"function* anonymous() {\nyield 10\n}");
|
||||
"function* anonymous(\n) {\nyield 10\n}");
|
||||
}
|
||||
TestGeneratorFunction();
|
||||
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ with (x)
|
|||
}
|
||||
status = inSection(5);
|
||||
actual = x.g.toString();
|
||||
expect = (function () {}).toString();
|
||||
expect = (function() {}).toString();
|
||||
addThis();
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
var BUGNUMBER = 354945;
|
||||
var summary = 'Do not crash with new Iterator';
|
||||
var expect = 'TypeError: trap __iterator__ for ({__iterator__:(function (){ })}) returned a primitive value';
|
||||
var expect = 'TypeError: trap __iterator__ for ({__iterator__:(function(){ })}) returned a primitive value';
|
||||
var actual;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ function test()
|
|||
printBugNumber(BUGNUMBER);
|
||||
printStatus (summary);
|
||||
|
||||
expect = 'TypeError: trap __iterator__ for ({__iterator__:(function (){ })}) returned a primitive value';
|
||||
expect = 'TypeError: trap __iterator__ for ({__iterator__:(function(){ })}) returned a primitive value';
|
||||
var obj = {};
|
||||
obj.__iterator__ = function(){ };
|
||||
try
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ function test()
|
|||
printBugNumber(BUGNUMBER);
|
||||
printStatus (summary);
|
||||
|
||||
expect = /TypeError: anonymous generator function returns a value/;
|
||||
expect = /TypeError: can't use 'yield' in a function that can return a value/;
|
||||
try
|
||||
{
|
||||
var gen = eval('(function() { { return 5; } yield 3; })');
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ function test()
|
|||
printBugNumber(BUGNUMBER);
|
||||
printStatus (summary);
|
||||
|
||||
expect = "generator function foo returns a value";
|
||||
expect = "can't use 'yield' in a function that can return a value";
|
||||
try
|
||||
{
|
||||
actual = 'No Error';
|
||||
|
|
@ -32,7 +32,7 @@ function test()
|
|||
}
|
||||
reportCompare(expect, actual, summary + ": 1");
|
||||
|
||||
expect = "generator function foo returns a value";
|
||||
expect = "generator function can't return a value";
|
||||
try
|
||||
{
|
||||
actual = 'No Error';
|
||||
|
|
@ -44,7 +44,7 @@ function test()
|
|||
}
|
||||
reportCompare(expect, actual, summary + ": 2");
|
||||
|
||||
expect = "generator function foo returns a value";
|
||||
expect = "can't use 'yield' in a function that can return a value";
|
||||
try
|
||||
{
|
||||
actual = 'No Error';
|
||||
|
|
@ -56,7 +56,7 @@ function test()
|
|||
}
|
||||
reportCompare(expect, actual, summary + ": 3");
|
||||
|
||||
expect = "generator function foo returns a value";
|
||||
expect = "generator function can't return a value";
|
||||
try
|
||||
{
|
||||
actual = 'No Error';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
var actual;
|
||||
var expect = "function f() { ff (); }";
|
||||
var expect = "function f () { ff (); }";
|
||||
function fun() {
|
||||
(new Function ("function ff () { actual = '' + ff. caller; } function f () { ff (); } f ();")) ();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -318,6 +318,7 @@ struct js::AsmJSMetadata : Metadata, AsmJSMetadataCacheablePod
|
|||
// Function constructor, this will be the first character in the function
|
||||
// source. Otherwise, it will be the opening parenthesis of the arguments
|
||||
// list.
|
||||
uint32_t preludeStart;
|
||||
uint32_t srcStart;
|
||||
uint32_t srcBodyStart;
|
||||
bool strict;
|
||||
|
|
@ -1758,6 +1759,7 @@ class MOZ_STACK_CLASS ModuleValidator
|
|||
if (!asmJSMetadata_)
|
||||
return false;
|
||||
|
||||
asmJSMetadata_->preludeStart = moduleFunctionNode_->pn_funbox->preludeStart;
|
||||
asmJSMetadata_->srcStart = moduleFunctionNode_->pn_body->pn_pos.begin;
|
||||
asmJSMetadata_->srcBodyStart = parser_.tokenStream.currentToken().pos.end;
|
||||
asmJSMetadata_->strict = parser_.pc->sc()->strict() &&
|
||||
|
|
@ -7049,6 +7051,7 @@ ParseFunction(ModuleValidator& m, ParseNode** fnOut, unsigned* line)
|
|||
TokenStream& tokenStream = m.tokenStream();
|
||||
|
||||
tokenStream.consumeKnownToken(TOK_FUNCTION, TokenStream::Operand);
|
||||
uint32_t preludeStart = tokenStream.currentToken().pos.begin;
|
||||
*line = tokenStream.srcCoords.lineNum(tokenStream.currentToken().pos.end);
|
||||
|
||||
TokenKind tk;
|
||||
|
|
@ -7061,7 +7064,7 @@ ParseFunction(ModuleValidator& m, ParseNode** fnOut, unsigned* line)
|
|||
if (!name)
|
||||
return false;
|
||||
|
||||
ParseNode* fn = m.parser().handler.newFunctionDefinition();
|
||||
ParseNode* fn = m.parser().handler.newFunctionStatement();
|
||||
if (!fn)
|
||||
return false;
|
||||
|
||||
|
|
@ -7071,7 +7074,7 @@ ParseFunction(ModuleValidator& m, ParseNode** fnOut, unsigned* line)
|
|||
|
||||
ParseContext* outerpc = m.parser().pc;
|
||||
Directives directives(outerpc);
|
||||
FunctionBox* funbox = m.parser().newFunctionBox(fn, fun, directives, NotGenerator,
|
||||
FunctionBox* funbox = m.parser().newFunctionBox(fn, fun, preludeStart, directives, NotGenerator,
|
||||
SyncFunction, /* tryAnnexB = */ false);
|
||||
if (!funbox)
|
||||
return false;
|
||||
|
|
@ -8054,7 +8057,7 @@ HandleInstantiationFailure(JSContext* cx, CallArgs args, const AsmJSMetadata& me
|
|||
return false;
|
||||
}
|
||||
|
||||
uint32_t begin = metadata.srcStart;
|
||||
uint32_t begin = metadata.preludeStart;
|
||||
uint32_t end = metadata.srcEndAfterCurly();
|
||||
Rooted<JSFlatString*> src(cx, source->substringDontDeflate(cx, begin, end));
|
||||
if (!src)
|
||||
|
|
@ -8085,7 +8088,7 @@ HandleInstantiationFailure(JSContext* cx, CallArgs args, const AsmJSMetadata& me
|
|||
SourceBufferHolder::Ownership ownership = stableChars.maybeGiveOwnershipToCaller()
|
||||
? SourceBufferHolder::GiveOwnership
|
||||
: SourceBufferHolder::NoOwnership;
|
||||
SourceBufferHolder srcBuf(chars, stableChars.twoByteRange().length(), ownership);
|
||||
SourceBufferHolder srcBuf(chars, end - begin, ownership);
|
||||
if (!frontend::CompileStandaloneFunction(cx, &fun, options, srcBuf, Nothing()))
|
||||
return false;
|
||||
|
||||
|
|
@ -8537,6 +8540,7 @@ LookupAsmJSModuleInCache(ExclusiveContext* cx, AsmJSParser& parser, bool* loaded
|
|||
return true;
|
||||
|
||||
// See AsmJSMetadata comment as well as ModuleValidator::init().
|
||||
asmJSMetadata->preludeStart = parser.pc->functionBox()->preludeStart;
|
||||
asmJSMetadata->srcStart = parser.pc->functionBox()->functionNode->pn_body->pn_pos.begin;
|
||||
asmJSMetadata->srcBodyStart = parser.tokenStream.currentToken().pos.end;
|
||||
asmJSMetadata->strict = parser.pc->sc()->strict() && !parser.pc->sc()->hasExplicitUseStrict();
|
||||
|
|
@ -8834,7 +8838,7 @@ js::AsmJSModuleToString(JSContext* cx, HandleFunction fun, bool addParenToLambda
|
|||
MOZ_ASSERT(IsAsmJSModule(fun));
|
||||
|
||||
const AsmJSMetadata& metadata = AsmJSModuleFunctionToModule(fun).metadata().asAsmJS();
|
||||
uint32_t begin = metadata.srcStart;
|
||||
uint32_t begin = metadata.preludeStart;
|
||||
uint32_t end = metadata.srcEndAfterCurly();
|
||||
ScriptSource* source = metadata.scriptSource.get();
|
||||
|
||||
|
|
@ -8843,17 +8847,15 @@ js::AsmJSModuleToString(JSContext* cx, HandleFunction fun, bool addParenToLambda
|
|||
if (addParenToLambda && fun->isLambda() && !out.append("("))
|
||||
return nullptr;
|
||||
|
||||
if (!out.append("function "))
|
||||
return nullptr;
|
||||
|
||||
if (fun->explicitName() && !out.append(fun->explicitName()))
|
||||
return nullptr;
|
||||
|
||||
bool haveSource = source->hasSourceData();
|
||||
if (!haveSource && !JSScript::loadSource(cx, source, &haveSource))
|
||||
return nullptr;
|
||||
|
||||
if (!haveSource) {
|
||||
if (!out.append("function "))
|
||||
return nullptr;
|
||||
if (fun->explicitName() && !out.append(fun->explicitName()))
|
||||
return nullptr;
|
||||
if (!out.append("() {\n [sourceless code]\n}"))
|
||||
return nullptr;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -685,7 +685,7 @@ nsSVGUtils::PaintFrameWithEffects(nsIFrame *aFrame,
|
|||
bool isOK = effectProperties.HasNoFilterOrHasValidFilter();
|
||||
nsSVGClipPathFrame *clipPathFrame = effectProperties.GetClipPathFrame(&isOK);
|
||||
nsSVGMaskFrame *maskFrame = effectProperties.GetFirstMaskFrame(&isOK);
|
||||
if (!isOK || !maskFrame) {
|
||||
if (!isOK) {
|
||||
// Some resource is invalid. We shouldn't paint anything.
|
||||
return DrawResult::SUCCESS;
|
||||
}
|
||||
|
|
@ -734,9 +734,12 @@ nsSVGUtils::PaintFrameWithEffects(nsIFrame *aFrame,
|
|||
RefPtr<SourceSurface> maskSurface;
|
||||
|
||||
if (maskUsage.shouldGenerateMaskLayer) {
|
||||
maskSurface =
|
||||
maskFrame->GetMaskForMaskedFrame(&aContext, aFrame, aTransform,
|
||||
maskUsage.opacity, &maskTransform);
|
||||
// Make sure we have a mask frame.
|
||||
if (maskFrame) {
|
||||
maskSurface =
|
||||
maskFrame->GetMaskForMaskedFrame(&aContext, aFrame, aTransform,
|
||||
maskUsage.opacity, &maskTransform);
|
||||
}
|
||||
|
||||
if (!maskSurface) {
|
||||
// Entire surface is clipped out.
|
||||
|
|
|
|||
|
|
@ -22,21 +22,21 @@
|
|||
storage.b = 0;
|
||||
assert_equals(storage.b, "0");
|
||||
storage.c = function(){};
|
||||
assert_equals(storage.c, "function (){}");
|
||||
assert_equals(storage.c, "function(){}");
|
||||
|
||||
storage.setItem('d', null);
|
||||
assert_equals(storage.d, "null");
|
||||
storage.setItem('e', 0);
|
||||
assert_equals(storage.e, "0");
|
||||
storage.setItem('f', function(){});
|
||||
assert_equals(storage.f, "function (){}");
|
||||
assert_equals(storage.f, "function(){}");
|
||||
|
||||
storage['g'] = null;
|
||||
assert_equals(storage.g, "null");
|
||||
storage['h'] = 0;
|
||||
assert_equals(storage.h, "0");
|
||||
storage['i'] = function(){};
|
||||
assert_equals(storage.f, "function (){}");
|
||||
assert_equals(storage.f, "function(){}");
|
||||
|
||||
}, name + " only stores strings");
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1162,7 +1162,7 @@ add_test({
|
|||
|
||||
self.assertTestResult(False)
|
||||
self.assertInLog(TEST_FAIL_STRING)
|
||||
self.assertInLog("TypeError: generator function run_test returns a value at")
|
||||
self.assertInLog("TypeError: generator function can't return a value at")
|
||||
self.assertInLog("test_error.js:4")
|
||||
self.assertNotInLog(TEST_PASS_STRING)
|
||||
|
||||
|
|
|
|||
|
|
@ -381,12 +381,12 @@ add_task(function* log_message_with_params() {
|
|||
ob = function() {};
|
||||
ob.toJSON = function() {throw "oh noes JSON"};
|
||||
do_check_eq(formatMessage("Fail is ${sub}", {sub: ob}),
|
||||
'Fail is (function () {})');
|
||||
'Fail is (function() {})');
|
||||
|
||||
// Fall back to .toString if both .toJSON and .toSource fail.
|
||||
ob.toSource = function() {throw "oh noes SOURCE"};
|
||||
do_check_eq(formatMessage("Fail is ${sub}", {sub: ob}),
|
||||
'Fail is function () {}');
|
||||
'Fail is function() {}');
|
||||
|
||||
// Fall back to '[object]' if .toJSON, .toSource and .toString fail.
|
||||
ob.toString = function() {throw "oh noes STRING"};
|
||||
|
|
@ -450,7 +450,7 @@ add_task(function* log_message_with_params() {
|
|||
// doesn't cause the logger to fail.
|
||||
let vOf = {a: 1, valueOf: function() {throw "oh noes valueOf"}};
|
||||
do_check_eq(formatMessage("Broken valueOf ${}", vOf),
|
||||
'Broken valueOf ({a:1, valueOf:(function () {throw "oh noes valueOf"})})');
|
||||
'Broken valueOf ({a:1, valueOf:(function() {throw "oh noes valueOf"})})');
|
||||
|
||||
// Test edge cases of bad data to formatter:
|
||||
// If 'params' is not an object, format it as a basic type.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue