Part 1: Implement ES6 function name property semantics

Issue #78
This commit is contained in:
janekptacijarabaci 2018-03-19 15:47:10 +01:00 committed by Roy Tam
commit 748c69d7fd
30 changed files with 750 additions and 81 deletions

View file

@ -31,6 +31,12 @@ static const uint32_t JSSLOT_BOUND_FUNCTION_ARGS = 4;
static const char FunctionConstructorMedialSigils[] = ") {\n";
static const char FunctionConstructorFinalBrace[] = "\n}";
enum class FunctionPrefixKind {
None,
Get,
Set
};
class JSFunction : public js::NativeObject
{
public:
@ -61,6 +67,9 @@ class JSFunction : public js::NativeObject
function-statement) */
SELF_HOSTED = 0x0080, /* function is self-hosted builtin and must not be
decompilable nor constructible. */
HAS_COMPILE_TIME_NAME = 0x0100, /* function had no explicit name, but a
name was set by SetFunctionName
at compile time */
INTERPRETED_LAZY = 0x0200, /* function is interpreted but doesn't have a script yet */
RESOLVED_LENGTH = 0x0400, /* f.length has been resolved (see fun_resolve). */
RESOLVED_NAME = 0x0800, /* f.name has been resolved (see fun_resolve). */
@ -94,7 +103,7 @@ class JSFunction : public js::NativeObject
NO_XDR_FLAGS = RESOLVED_LENGTH | RESOLVED_NAME,
STABLE_ACROSS_CLONES = CONSTRUCTOR | EXPR_BODY | HAS_GUESSED_ATOM | LAMBDA |
SELF_HOSTED | FUNCTION_KIND_MASK
SELF_HOSTED | HAS_COMPILE_TIME_NAME | FUNCTION_KIND_MASK
};
static_assert((INTERPRETED | INTERPRETED_LAZY) == js::JS_FUNCTION_INTERPRETED_BITS,
@ -179,6 +188,7 @@ class JSFunction : public js::NativeObject
/* Possible attributes of an interpreted function: */
bool isExprBody() const { return flags() & EXPR_BODY; }
bool hasCompileTimeName() const { return flags() & HAS_COMPILE_TIME_NAME; }
bool hasGuessedAtom() const { return flags() & HAS_GUESSED_ATOM; }
bool isLambda() const { return flags() & LAMBDA; }
bool isBoundFunction() const { return flags() & BOUND_FUN; }
@ -220,7 +230,7 @@ class JSFunction : public js::NativeObject
}
bool isNamedLambda() const {
return isLambda() && displayAtom() && !hasGuessedAtom();
return isLambda() && displayAtom() && !hasCompileTimeName() && !hasGuessedAtom();
}
bool hasLexicalThis() const {
@ -308,14 +318,12 @@ class JSFunction : public js::NativeObject
JSAtom* getUnresolvedName(JSContext* cx);
JSAtom* name() const { return hasGuessedAtom() ? nullptr : atom_.get(); }
// Because display names (see Debugger.Object.displayName) are already stored
// on functions and will always contain a valid es6 function name, as described
// in "ECMA-262 (2016-02-27) 9.2.11 SetFunctionName," we have opted to save
// memory by parsing the existing display name when a function's name property
// is accessed.
JSAtom* functionName(JSContext* cx) const;
JSAtom* explicitName() const {
return (hasCompileTimeName() || hasGuessedAtom()) ? nullptr : atom_.get();
}
JSAtom* explicitOrCompileTimeName() const {
return hasGuessedAtom() ? nullptr : atom_.get();
}
void initAtom(JSAtom* atom) { atom_.init(atom); }
@ -325,9 +333,24 @@ class JSFunction : public js::NativeObject
return atom_;
}
void setCompileTimeName(JSAtom* atom) {
MOZ_ASSERT(!atom_);
MOZ_ASSERT(atom);
MOZ_ASSERT(!hasGuessedAtom());
MOZ_ASSERT(!isClassConstructor());
atom_ = atom;
flags_ |= HAS_COMPILE_TIME_NAME;
}
JSAtom* compileTimeName() const {
MOZ_ASSERT(hasCompileTimeName());
MOZ_ASSERT(atom_);
return atom_;
}
void setGuessedAtom(JSAtom* atom) {
MOZ_ASSERT(!atom_);
MOZ_ASSERT(atom);
MOZ_ASSERT(!hasCompileTimeName());
MOZ_ASSERT(!hasGuessedAtom());
atom_ = atom;
flags_ |= HAS_GUESSED_ATOM;
@ -672,7 +695,16 @@ NewFunctionWithProto(ExclusiveContext* cx, JSNative native, unsigned nargs,
NewFunctionProtoHandling protoHandling = NewFunctionClassProto);
extern JSAtom*
IdToFunctionName(JSContext* cx, HandleId id, const char* prefix = nullptr);
IdToFunctionName(JSContext* cx, HandleId id,
FunctionPrefixKind prefixKind = FunctionPrefixKind::None);
extern JSAtom*
NameToFunctionName(ExclusiveContext* cx, HandleAtom name,
FunctionPrefixKind prefixKind = FunctionPrefixKind::None);
extern bool
SetFunctionNameIfNoOwnName(JSContext* cx, HandleFunction fun, HandleValue name,
FunctionPrefixKind prefixKind);
extern JSFunction*
DefineFunction(JSContext* cx, HandleObject obj, HandleId id, JSNative native,