diff options
Diffstat (limited to 'js/src/vm')
-rw-r--r-- | js/src/vm/ArgumentsObject.cpp | 6 | ||||
-rw-r--r-- | js/src/vm/AsyncFunction.cpp | 24 | ||||
-rw-r--r-- | js/src/vm/AsyncFunction.h | 3 | ||||
-rw-r--r-- | js/src/vm/CommonPropertyNames.h | 2 | ||||
-rw-r--r-- | js/src/vm/Debugger.cpp | 11 | ||||
-rw-r--r-- | js/src/vm/ErrorObject.cpp | 69 | ||||
-rw-r--r-- | js/src/vm/ErrorObject.h | 8 | ||||
-rw-r--r-- | js/src/vm/ForOfIterator.cpp | 51 | ||||
-rw-r--r-- | js/src/vm/GlobalObject.cpp | 4 | ||||
-rw-r--r-- | js/src/vm/GlobalObject.h | 17 | ||||
-rw-r--r-- | js/src/vm/Interpreter.cpp | 135 | ||||
-rw-r--r-- | js/src/vm/Interpreter.h | 9 | ||||
-rw-r--r-- | js/src/vm/ObjectGroup.cpp | 4 | ||||
-rw-r--r-- | js/src/vm/Opcodes.h | 55 | ||||
-rw-r--r-- | js/src/vm/RegExpObject.cpp | 13 | ||||
-rw-r--r-- | js/src/vm/RegExpObject.h | 4 | ||||
-rw-r--r-- | js/src/vm/SelfHosting.cpp | 10 | ||||
-rw-r--r-- | js/src/vm/Shape.cpp | 8 | ||||
-rw-r--r-- | js/src/vm/Stack.cpp | 2 | ||||
-rw-r--r-- | js/src/vm/StructuredClone.cpp | 7 | ||||
-rw-r--r-- | js/src/vm/TypeInference.cpp | 2 | ||||
-rw-r--r-- | js/src/vm/TypedArrayObject.cpp | 2 | ||||
-rw-r--r-- | js/src/vm/Unicode.cpp | 879 | ||||
-rw-r--r-- | js/src/vm/Unicode.h | 28 | ||||
-rw-r--r-- | js/src/vm/UnicodeNonBMP.h | 10 | ||||
-rwxr-xr-x | js/src/vm/make_unicode.py | 324 |
26 files changed, 1579 insertions, 108 deletions
diff --git a/js/src/vm/ArgumentsObject.cpp b/js/src/vm/ArgumentsObject.cpp index d01121ef04..717aa10508 100644 --- a/js/src/vm/ArgumentsObject.cpp +++ b/js/src/vm/ArgumentsObject.cpp @@ -676,7 +676,7 @@ UnmappedArgumentsObject::obj_resolve(JSContext* cx, HandleObject obj, HandleId i if (argsobj->hasOverriddenLength()) return true; } else { - if (!JSID_IS_ATOM(id, cx->names().callee) && !JSID_IS_ATOM(id, cx->names().caller)) + if (!JSID_IS_ATOM(id, cx->names().callee)) return true; attrs = JSPROP_PERMANENT | JSPROP_GETTER | JSPROP_SETTER | JSPROP_SHARED; @@ -709,10 +709,6 @@ UnmappedArgumentsObject::obj_enumerate(JSContext* cx, HandleObject obj) if (!HasProperty(cx, argsobj, id, &found)) return false; - id = NameToId(cx->names().caller); - if (!HasProperty(cx, argsobj, id, &found)) - return false; - id = SYMBOL_TO_JSID(cx->wellKnownSymbols().iterator); if (!HasProperty(cx, argsobj, id, &found)) return false; diff --git a/js/src/vm/AsyncFunction.cpp b/js/src/vm/AsyncFunction.cpp index bd0b4f32ae..f50c871141 100644 --- a/js/src/vm/AsyncFunction.cpp +++ b/js/src/vm/AsyncFunction.cpp @@ -107,19 +107,16 @@ WrappedAsyncFunction(JSContext* cx, unsigned argc, Value* vp) // the async function's body, replacing `await` with `yield`. `wrapped` is a // function that is visible to the outside, and handles yielded values. JSObject* -js::WrapAsyncFunction(JSContext* cx, HandleFunction unwrapped) +js::WrapAsyncFunctionWithProto(JSContext* cx, HandleFunction unwrapped, HandleObject proto) { MOZ_ASSERT(unwrapped->isStarGenerator()); + MOZ_ASSERT(proto, "We need an explicit prototype to avoid the default" + "%FunctionPrototype% fallback in NewFunctionWithProto()."); // Create a new function with AsyncFunctionPrototype, reusing the name and // the length of `unwrapped`. - // Step 1. - RootedObject proto(cx, GlobalObject::getOrCreateAsyncFunctionPrototype(cx, cx->global())); - if (!proto) - return nullptr; - - RootedAtom funName(cx, unwrapped->name()); + RootedAtom funName(cx, unwrapped->explicitName()); uint16_t length; if (!unwrapped->getLength(cx, &length)) return nullptr; @@ -133,6 +130,9 @@ js::WrapAsyncFunction(JSContext* cx, HandleFunction unwrapped) if (!wrapped) return nullptr; + if (unwrapped->hasCompileTimeName()) + wrapped->setCompileTimeName(unwrapped->compileTimeName()); + // Link them to each other to make GetWrappedAsyncFunction and // GetUnwrappedAsyncFunction work. unwrapped->setExtendedSlot(UNWRAPPED_ASYNC_WRAPPED_SLOT, ObjectValue(*wrapped)); @@ -141,6 +141,16 @@ js::WrapAsyncFunction(JSContext* cx, HandleFunction unwrapped) return wrapped; } +JSObject* +js::WrapAsyncFunction(JSContext* cx, HandleFunction unwrapped) +{ + RootedObject proto(cx, GlobalObject::getOrCreateAsyncFunctionPrototype(cx, cx->global())); + if (!proto) + return nullptr; + + return WrapAsyncFunctionWithProto(cx, unwrapped, proto); +} + enum class ResumeKind { Normal, Throw diff --git a/js/src/vm/AsyncFunction.h b/js/src/vm/AsyncFunction.h index ddf81a1774..d7f2c13117 100644 --- a/js/src/vm/AsyncFunction.h +++ b/js/src/vm/AsyncFunction.h @@ -22,6 +22,9 @@ bool IsWrappedAsyncFunction(JSFunction* fun); JSObject* +WrapAsyncFunctionWithProto(JSContext* cx, HandleFunction unwrapped, HandleObject proto); + +JSObject* WrapAsyncFunction(JSContext* cx, HandleFunction unwrapped); MOZ_MUST_USE bool diff --git a/js/src/vm/CommonPropertyNames.h b/js/src/vm/CommonPropertyNames.h index bd0705446d..e971dc8443 100644 --- a/js/src/vm/CommonPropertyNames.h +++ b/js/src/vm/CommonPropertyNames.h @@ -13,7 +13,7 @@ #define FOR_EACH_COMMON_PROPERTYNAME(macro) \ macro(add, add, "add") \ - macro(allowContentSpread, allowContentSpread, "allowContentSpread") \ + macro(allowContentIter, allowContentIter, "allowContentIter") \ macro(anonymous, anonymous, "anonymous") \ macro(Any, Any, "Any") \ macro(apply, apply, "apply") \ diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp index b6bc7d62af..d16781326d 100644 --- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -6890,8 +6890,13 @@ class DebuggerSourceGetTextMatcher bool hasSourceData = ss->hasSourceData(); if (!ss->hasSourceData() && !JSScript::loadSource(cx_, ss, &hasSourceData)) return nullptr; - return hasSourceData ? ss->substring(cx_, 0, ss->length()) - : NewStringCopyZ<CanGC>(cx_, "[no source]"); + if (!hasSourceData) + return NewStringCopyZ<CanGC>(cx_, "[no source]"); + + if (ss->isFunctionBody()) + return ss->functionBodyString(cx_); + + return ss->substring(cx_, 0, ss->length()); } ReturnType match(Handle<WasmInstanceObject*> wasmInstance) { @@ -9504,7 +9509,7 @@ DebuggerObject::name() const { MOZ_ASSERT(isFunction()); - return referent()->as<JSFunction>().name(); + return referent()->as<JSFunction>().explicitName(); } JSAtom* diff --git a/js/src/vm/ErrorObject.cpp b/js/src/vm/ErrorObject.cpp index 47b61b57b0..d8d29830b1 100644 --- a/js/src/vm/ErrorObject.cpp +++ b/js/src/vm/ErrorObject.cpp @@ -164,29 +164,25 @@ js::ErrorObject::getOrCreateErrorReport(JSContext* cx) } static bool -ErrorObject_checkAndUnwrapThis(JSContext* cx, CallArgs& args, const char* fnName, - MutableHandle<ErrorObject*> error) +FindErrorInstanceOrPrototype(JSContext* cx, HandleObject obj, MutableHandleObject result) { - const Value& thisValue = args.thisv(); - - if (!thisValue.isObject()) { - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_NOT_NONNULL_OBJECT, - InformalValueTypeName(thisValue)); - return false; - } - - // Walk up the prototype chain until we find the first ErrorObject that has - // the slots we need. This allows us to support the poor-man's subclassing - // of error: Object.create(Error.prototype). - - RootedObject target(cx, CheckedUnwrap(&thisValue.toObject())); + // Walk up the prototype chain until we find an error object instance or + // prototype object. This allows code like: + // Object.create(Error.prototype).stack + // or + // function NYI() { } + // NYI.prototype = new Error; + // (new NYI).stack + // to continue returning stacks that are useless, but at least don't throw. + + RootedObject target(cx, CheckedUnwrap(obj)); if (!target) { JS_ReportErrorASCII(cx, "Permission denied to access object"); return false; } RootedObject proto(cx); - while (!target->is<ErrorObject>()) { + while (!IsErrorProtoKey(StandardProtoKeyOrNull(target))) { if (!GetPrototype(cx, target, &proto)) return false; @@ -194,7 +190,7 @@ ErrorObject_checkAndUnwrapThis(JSContext* cx, CallArgs& args, const char* fnName // We walked the whole prototype chain and did not find an Error // object. JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_INCOMPATIBLE_PROTO, - js_Error_str, fnName, thisValue.toObject().getClass()->name); + js_Error_str, "(get stack)", obj->getClass()->name); return false; } @@ -205,19 +201,40 @@ ErrorObject_checkAndUnwrapThis(JSContext* cx, CallArgs& args, const char* fnName } } - error.set(&target->as<ErrorObject>()); + result.set(target); return true; } + +static MOZ_ALWAYS_INLINE bool +IsObject(HandleValue v) +{ + return v.isObject(); +} + /* static */ bool js::ErrorObject::getStack(JSContext* cx, unsigned argc, Value* vp) { CallArgs args = CallArgsFromVp(argc, vp); - Rooted<ErrorObject*> error(cx); - if (!ErrorObject_checkAndUnwrapThis(cx, args, "(get stack)", &error)) + // We accept any object here, because of poor-man's subclassing of Error. + return CallNonGenericMethod<IsObject, getStack_impl>(cx, args); +} + +/* static */ bool +js::ErrorObject::getStack_impl(JSContext* cx, const CallArgs& args) +{ + RootedObject thisObj(cx, &args.thisv().toObject()); + + RootedObject obj(cx); + if (!FindErrorInstanceOrPrototype(cx, thisObj, &obj)) return false; - RootedObject savedFrameObj(cx, error->stack()); + if (!obj->is<ErrorObject>()) { + args.rval().setString(cx->runtime()->emptyString); + return true; + } + + RootedObject savedFrameObj(cx, obj->as<ErrorObject>().stack()); RootedString stackString(cx); if (!BuildStackString(cx, savedFrameObj, &stackString)) return false; @@ -245,12 +262,6 @@ js::ErrorObject::getStack(JSContext* cx, unsigned argc, Value* vp) return true; } -static MOZ_ALWAYS_INLINE bool -IsObject(HandleValue v) -{ - return v.isObject(); -} - /* static */ bool js::ErrorObject::setStack(JSContext* cx, unsigned argc, Value* vp) { @@ -262,9 +273,7 @@ js::ErrorObject::setStack(JSContext* cx, unsigned argc, Value* vp) /* static */ bool js::ErrorObject::setStack_impl(JSContext* cx, const CallArgs& args) { - const Value& thisValue = args.thisv(); - MOZ_ASSERT(thisValue.isObject()); - RootedObject thisObj(cx, &thisValue.toObject()); + RootedObject thisObj(cx, &args.thisv().toObject()); if (!args.requireAtLeast(cx, "(set stack)", 1)) return false; diff --git a/js/src/vm/ErrorObject.h b/js/src/vm/ErrorObject.h index 32a691bb4a..0c2d00610a 100644 --- a/js/src/vm/ErrorObject.h +++ b/js/src/vm/ErrorObject.h @@ -38,9 +38,8 @@ class ErrorObject : public NativeObject ScopedJSFreePtr<JSErrorReport>* errorReport, HandleString fileName, HandleObject stack, uint32_t lineNumber, uint32_t columnNumber, HandleString message); - static const ClassSpec errorClassSpec_; - static const ClassSpec subErrorClassSpec_; - static const ClassSpec nonGlobalErrorClassSpec_; + static const ClassSpec classSpecs[JSEXN_ERROR_LIMIT]; + static const Class protoClasses[JSEXN_ERROR_LIMIT]; protected: static const uint32_t EXNTYPE_SLOT = 0; @@ -54,7 +53,7 @@ class ErrorObject : public NativeObject static const uint32_t RESERVED_SLOTS = MESSAGE_SLOT + 1; public: - static const Class classes[JSEXN_LIMIT]; + static const Class classes[JSEXN_ERROR_LIMIT]; static const Class * classForType(JSExnType type) { MOZ_ASSERT(type < JSEXN_WARN); @@ -107,6 +106,7 @@ class ErrorObject : public NativeObject // Getter and setter for the Error.prototype.stack accessor. static bool getStack(JSContext* cx, unsigned argc, Value* vp); + static bool getStack_impl(JSContext* cx, const CallArgs& args); static bool setStack(JSContext* cx, unsigned argc, Value* vp); static bool setStack_impl(JSContext* cx, const CallArgs& args); }; diff --git a/js/src/vm/ForOfIterator.cpp b/js/src/vm/ForOfIterator.cpp index 7bd521a6a5..a67b36774d 100644 --- a/js/src/vm/ForOfIterator.cpp +++ b/js/src/vm/ForOfIterator.cpp @@ -151,6 +151,57 @@ ForOfIterator::next(MutableHandleValue vp, bool* done) return GetProperty(cx_, resultObj, resultObj, cx_->names().value, vp); } +// ES 2017 draft 0f10dba4ad18de92d47d421f378233a2eae8f077 7.4.6. +// When completion.[[Type]] is throw. +void +ForOfIterator::closeThrow() +{ + MOZ_ASSERT(iterator); + + RootedValue completionException(cx_); + if (cx_->isExceptionPending()) { + if (!GetAndClearException(cx_, &completionException)) + completionException.setUndefined(); + } + + // Steps 1-2 (implicit) + + // Step 3 (partial). + RootedValue returnVal(cx_); + if (!GetProperty(cx_, iterator, iterator, cx_->names().return_, &returnVal)) + return; + + // Step 4. + if (returnVal.isUndefined()) { + cx_->setPendingException(completionException); + return; + } + + // Step 3 (remaining part) + if (!returnVal.isObject()) { + JS_ReportErrorNumberASCII(cx_, GetErrorMessage, nullptr, JSMSG_RETURN_NOT_CALLABLE); + return; + } + RootedObject returnObj(cx_, &returnVal.toObject()); + if (!returnObj->isCallable()) { + JS_ReportErrorNumberASCII(cx_, GetErrorMessage, nullptr, JSMSG_RETURN_NOT_CALLABLE); + return; + } + + // Step 5. + RootedValue innerResultValue(cx_); + if (!js::Call(cx_, returnVal, iterator, &innerResultValue)) { + if (cx_->isExceptionPending()) + cx_->clearPendingException(); + } + + // Step 6. + cx_->setPendingException(completionException); + + // Steps 7-9 (skipped). + return; +} + bool ForOfIterator::materializeArrayIterator() { diff --git a/js/src/vm/GlobalObject.cpp b/js/src/vm/GlobalObject.cpp index 039be2e325..280548cd60 100644 --- a/js/src/vm/GlobalObject.cpp +++ b/js/src/vm/GlobalObject.cpp @@ -802,10 +802,10 @@ GlobalObject::getSelfHostedFunction(JSContext* cx, Handle<GlobalObject*> global, return false; if (exists) { RootedFunction fun(cx, &funVal.toObject().as<JSFunction>()); - if (fun->name() == name) + if (fun->explicitName() == name) return true; - if (fun->name() == selfHostedName) { + if (fun->explicitName() == selfHostedName) { // This function was initially cloned because it was called by // other self-hosted code, so the clone kept its self-hosted name, // instead of getting the name it's intended to have in content diff --git a/js/src/vm/GlobalObject.h b/js/src/vm/GlobalObject.h index 05984bc5f0..3534ef2f6c 100644 --- a/js/src/vm/GlobalObject.h +++ b/js/src/vm/GlobalObject.h @@ -427,6 +427,18 @@ class GlobalObject : public NativeObject return &global->getPrototype(key).toObject(); } + static JSFunction* + getOrCreateErrorConstructor(JSContext* cx, Handle<GlobalObject*> global) { + if (!ensureConstructor(cx, global, JSProto_Error)) + return nullptr; + return &global->getConstructor(JSProto_Error).toObject().as<JSFunction>(); + } + + static JSObject* + getOrCreateErrorPrototype(JSContext* cx, Handle<GlobalObject*> global) { + return getOrCreateCustomErrorPrototype(cx, global, JSEXN_ERR); + } + static NativeObject* getOrCreateSetPrototype(JSContext* cx, Handle<GlobalObject*> global) { if (!ensureConstructor(cx, global, JSProto_Set)) return nullptr; @@ -1003,10 +1015,7 @@ GenericCreatePrototype(JSContext* cx, JSProtoKey key) inline JSProtoKey StandardProtoKeyOrNull(const JSObject* obj) { - JSProtoKey key = JSCLASS_CACHED_PROTO_KEY(obj->getClass()); - if (key == JSProto_Error) - return GetExceptionProtoKey(obj->as<ErrorObject>().type()); - return key; + return JSCLASS_CACHED_PROTO_KEY(obj->getClass()); } JSObject* diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp index fbf526ae5b..b747e4d7a0 100644 --- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -282,8 +282,6 @@ MakeDefaultConstructor(JSContext* cx, JSOp op, JSAtom* atom, HandleObject proto) ctor->setIsConstructor(); ctor->setIsClassConstructor(); - if (derived) - ctor->setHasRest(); MOZ_ASSERT(ctor->infallibleIsDefaultClassConstructor(cx)); @@ -1082,6 +1080,9 @@ js::UnwindEnvironmentToTryPc(JSScript* script, JSTryNote* tn) if (tn->kind == JSTRY_CATCH || tn->kind == JSTRY_FINALLY) { pc -= JSOP_TRY_LENGTH; MOZ_ASSERT(*pc == JSOP_TRY); + } else if (tn->kind == JSTRY_DESTRUCTURING_ITERCLOSE) { + pc -= JSOP_TRY_DESTRUCTURING_ITERCLOSE_LENGTH; + MOZ_ASSERT(*pc == JSOP_TRY_DESTRUCTURING_ITERCLOSE); } return pc; } @@ -1158,6 +1159,7 @@ enum HandleErrorContinuation static HandleErrorContinuation ProcessTryNotes(JSContext* cx, EnvironmentIter& ei, InterpreterRegs& regs) { + bool inForOfIterClose = false; for (TryNoteIterInterpreter tni(cx, regs); !tni.done(); ++tni) { JSTryNote* tn = *tni; @@ -1166,10 +1168,38 @@ ProcessTryNotes(JSContext* cx, EnvironmentIter& ei, InterpreterRegs& regs) /* Catch cannot intercept the closing of a generator. */ if (cx->isClosingGenerator()) break; + + // If IteratorClose due to abnormal completion threw inside a + // for-of loop, it is not catchable by try statements inside of + // the for-of loop. + // + // This is handled by this weirdness in the exception handler + // instead of in bytecode because it is hard to do so in bytecode: + // + // 1. IteratorClose emitted due to abnormal completion (break, + // throw, return) are emitted inline, at the source location of + // the break, throw, or return statement. For example: + // + // for (x of iter) { + // try { return; } catch (e) { } + // } + // + // From the try-note nesting's perspective, the IteratorClose + // resulting from |return| is covered by the inner try, when it + // should not be. + // + // 2. Try-catch notes cannot be disjoint. That is, we can't have + // multiple notes with disjoint pc ranges jumping to the same + // catch block. + if (inForOfIterClose) + break; SettleOnTryNote(cx, tn, ei, regs); return CatchContinuation; case JSTRY_FINALLY: + // See note above. + if (inForOfIterClose) + break; SettleOnTryNote(cx, tn, ei, regs); return FinallyContinuation; @@ -1191,7 +1221,31 @@ ProcessTryNotes(JSContext* cx, EnvironmentIter& ei, InterpreterRegs& regs) break; } + case JSTRY_DESTRUCTURING_ITERCLOSE: { + // Whether the destructuring iterator is done is at the top of the + // stack. The iterator object is second from the top. + MOZ_ASSERT(tn->stackDepth > 1); + Value* sp = regs.spForStackDepth(tn->stackDepth); + RootedValue doneValue(cx, sp[-1]); + bool done = ToBoolean(doneValue); + if (!done) { + RootedObject iterObject(cx, &sp[-2].toObject()); + if (!IteratorCloseForException(cx, iterObject)) { + SettleOnTryNote(cx, tn, ei, regs); + return ErrorReturnContinuation; + } + } + break; + } + + case JSTRY_FOR_OF_ITERCLOSE: + inForOfIterClose = true; + break; + case JSTRY_FOR_OF: + inForOfIterClose = false; + break; + case JSTRY_LOOP: break; @@ -1862,15 +1916,11 @@ CASE(EnableInterruptsPseudoOpcode) /* Various 1-byte no-ops. */ CASE(JSOP_NOP) CASE(JSOP_NOP_DESTRUCTURING) -CASE(JSOP_UNUSED182) -CASE(JSOP_UNUSED183) -CASE(JSOP_UNUSED187) CASE(JSOP_UNUSED192) CASE(JSOP_UNUSED209) CASE(JSOP_UNUSED210) CASE(JSOP_UNUSED211) -CASE(JSOP_UNUSED219) -CASE(JSOP_UNUSED220) +CASE(JSOP_TRY_DESTRUCTURING_ITERCLOSE) CASE(JSOP_UNUSED221) CASE(JSOP_UNUSED222) CASE(JSOP_UNUSED223) @@ -2159,6 +2209,13 @@ CASE(JSOP_ENDITER) } END_CASE(JSOP_ENDITER) +CASE(JSOP_ISGENCLOSING) +{ + bool b = REGS.sp[-1].isMagic(JS_GENERATOR_CLOSING); + PUSH_BOOLEAN(b); +} +END_CASE(JSOP_ISGENCLOSING) + CASE(JSOP_DUP) { MOZ_ASSERT(REGS.stackDepth() >= 1); @@ -2196,6 +2253,16 @@ CASE(JSOP_PICK) } END_CASE(JSOP_PICK) +CASE(JSOP_UNPICK) +{ + int i = GET_UINT8(REGS.pc); + MOZ_ASSERT(REGS.stackDepth() >= unsigned(i) + 1); + Value lval = REGS.sp[-1]; + memmove(REGS.sp - i, REGS.sp - (i + 1), sizeof(Value) * i); + REGS.sp[-(i + 1)] = lval; +} +END_CASE(JSOP_UNPICK) + CASE(JSOP_BINDGNAME) CASE(JSOP_BINDNAME) { @@ -2597,6 +2664,15 @@ CASE(JSOP_CHECKISOBJ) } END_CASE(JSOP_CHECKISOBJ) +CASE(JSOP_CHECKISCALLABLE) +{ + if (!IsCallable(REGS.sp[-1])) { + MOZ_ALWAYS_FALSE(ThrowCheckIsCallable(cx, CheckIsCallableKind(GET_UINT8(REGS.pc)))); + goto error; + } +} +END_CASE(JSOP_CHECKISCALLABLE) + CASE(JSOP_CHECKTHIS) { if (REGS.sp[-1].isMagic(JS_UNINITIALIZED_LEXICAL)) { @@ -3484,6 +3560,19 @@ CASE(JSOP_TOASYNC) } END_CASE(JSOP_TOASYNC) +CASE(JSOP_SETFUNNAME) +{ + MOZ_ASSERT(REGS.stackDepth() >= 2); + FunctionPrefixKind prefixKind = FunctionPrefixKind(GET_UINT8(REGS.pc)); + ReservedRooted<Value> name(&rootValue0, REGS.sp[-1]); + ReservedRooted<JSFunction*> fun(&rootFunction0, ®S.sp[-2].toObject().as<JSFunction>()); + if (!SetFunctionNameIfNoOwnName(cx, fun, name, prefixKind)) + goto error; + + REGS.sp--; +} +END_CASE(JSOP_SETFUNNAME) + CASE(JSOP_CALLEE) MOZ_ASSERT(REGS.fp()->isFunctionFrame()); PUSH_COPY(REGS.fp()->calleev()); @@ -4345,7 +4434,7 @@ js::DefFunOperation(JSContext* cx, HandleScript script, HandleObject envChain, parent = parent->enclosingEnvironment(); /* ES5 10.5 (NB: with subsequent errata). */ - RootedPropertyName name(cx, fun->name()->asPropertyName()); + RootedPropertyName name(cx, fun->explicitName()->asPropertyName()); RootedShape shape(cx); RootedObject pobj(cx); @@ -4993,7 +5082,7 @@ js::ReportRuntimeLexicalError(JSContext* cx, unsigned errorNumber, RootedPropertyName name(cx); if (op == JSOP_THROWSETCALLEE) { - name = script->functionNonDelazifying()->name()->asPropertyName(); + name = script->functionNonDelazifying()->explicitName()->asPropertyName(); } else if (IsLocalOp(op)) { name = FrameSlotName(script, pc)->asPropertyName(); } else if (IsAtomOp(op)) { @@ -5021,7 +5110,16 @@ js::ThrowCheckIsObject(JSContext* cx, CheckIsObjectKind kind) { switch (kind) { case CheckIsObjectKind::IteratorNext: - JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_NEXT_RETURNED_PRIMITIVE); + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_ITER_METHOD_RETURNED_PRIMITIVE, "next"); + break; + case CheckIsObjectKind::IteratorReturn: + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_ITER_METHOD_RETURNED_PRIMITIVE, "return"); + break; + case CheckIsObjectKind::IteratorThrow: + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_ITER_METHOD_RETURNED_PRIMITIVE, "throw"); break; case CheckIsObjectKind::GetIterator: JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_GET_ITER_RETURNED_PRIMITIVE); @@ -5033,6 +5131,19 @@ js::ThrowCheckIsObject(JSContext* cx, CheckIsObjectKind kind) } bool +js::ThrowCheckIsCallable(JSContext* cx, CheckIsCallableKind kind) +{ + switch (kind) { + case CheckIsCallableKind::IteratorReturn: + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_RETURN_NOT_CALLABLE); + break; + default: + MOZ_CRASH("Unknown kind"); + } + return false; +} + +bool js::ThrowUninitializedThis(JSContext* cx, AbstractFramePtr frame) { RootedFunction fun(cx); @@ -5061,8 +5172,8 @@ js::ThrowUninitializedThis(JSContext* cx, AbstractFramePtr frame) if (fun->isDerivedClassConstructor()) { const char* name = "anonymous"; JSAutoByteString str; - if (fun->name()) { - if (!AtomToPrintableString(cx, fun->name(), &str)) + if (fun->explicitName()) { + if (!AtomToPrintableString(cx, fun->explicitName(), &str)) return false; name = str.ptr(); } diff --git a/js/src/vm/Interpreter.h b/js/src/vm/Interpreter.h index 1ffe1fdcaf..330dbef5f5 100644 --- a/js/src/vm/Interpreter.h +++ b/js/src/vm/Interpreter.h @@ -562,12 +562,21 @@ ReportRuntimeRedeclaration(JSContext* cx, HandlePropertyName name, const char* r enum class CheckIsObjectKind : uint8_t { IteratorNext, + IteratorReturn, + IteratorThrow, GetIterator }; bool ThrowCheckIsObject(JSContext* cx, CheckIsObjectKind kind); +enum class CheckIsCallableKind : uint8_t { + IteratorReturn +}; + +bool +ThrowCheckIsCallable(JSContext* cx, CheckIsCallableKind kind); + bool ThrowUninitializedThis(JSContext* cx, AbstractFramePtr frame); diff --git a/js/src/vm/ObjectGroup.cpp b/js/src/vm/ObjectGroup.cpp index 7be697fb68..d6a8fcaa46 100644 --- a/js/src/vm/ObjectGroup.cpp +++ b/js/src/vm/ObjectGroup.cpp @@ -6,6 +6,7 @@ #include "vm/ObjectGroup.h" +#include "jsexn.h" #include "jshashutil.h" #include "jsobj.h" @@ -578,11 +579,10 @@ ObjectGroup::defaultNewGroup(ExclusiveContext* cx, const Class* clasp, AddTypePropertyId(cx, group, nullptr, NameToId(names.lastIndex), TypeSet::Int32Type()); } else if (clasp == &StringObject::class_) { AddTypePropertyId(cx, group, nullptr, NameToId(names.length), TypeSet::Int32Type()); - } else if (ErrorObject::isErrorClass((clasp))) { + } else if (ErrorObject::isErrorClass(clasp)) { AddTypePropertyId(cx, group, nullptr, NameToId(names.fileName), TypeSet::StringType()); AddTypePropertyId(cx, group, nullptr, NameToId(names.lineNumber), TypeSet::Int32Type()); AddTypePropertyId(cx, group, nullptr, NameToId(names.columnNumber), TypeSet::Int32Type()); - AddTypePropertyId(cx, group, nullptr, NameToId(names.stack), TypeSet::StringType()); } return group; diff --git a/js/src/vm/Opcodes.h b/js/src/vm/Opcodes.h index 18ae6f0736..4b044c8d8f 100644 --- a/js/src/vm/Opcodes.h +++ b/js/src/vm/Opcodes.h @@ -1870,9 +1870,24 @@ * Stack: => */ \ macro(JSOP_POPVARENV, 181, "popvarenv", NULL, 1, 0, 0, JOF_BYTE) \ - macro(JSOP_UNUSED182, 182,"unused182", NULL, 1, 0, 0, JOF_BYTE) \ - macro(JSOP_UNUSED183, 183,"unused183", NULL, 1, 0, 0, JOF_BYTE) \ - \ + /* + * Pops the top two values on the stack as 'name' and 'fun', defines the + * name of 'fun' to 'name' with prefix if any, and pushes 'fun' back onto + * the stack. + * Category: Statements + * Type: Function + * Operands: uint8_t prefixKind + * Stack: fun, name => fun + */ \ + macro(JSOP_SETFUNNAME, 182,"setfunname", NULL, 2, 2, 1, JOF_UINT8) \ + /* + * Moves the top of the stack value under the nth element of the stack. + * Category: Operators + * Type: Stack Operations + * Operands: uint8_t n + * Stack: v[n], v[n-1], ..., v[1], v[0] => v[0], v[n], v[n-1], ..., v[1] + */ \ + macro(JSOP_UNPICK, 183,"unpick", NULL, 2, 0, 0, JOF_UINT8) \ /* * Pops the top of stack value, pushes property of it onto the stack. * @@ -1901,8 +1916,16 @@ * Stack: => this */ \ macro(JSOP_GLOBALTHIS, 186,"globalthis", NULL, 1, 0, 1, JOF_BYTE) \ - macro(JSOP_UNUSED187, 187,"unused187", NULL, 1, 0, 0, JOF_BYTE) \ - \ + /* + * Pushes a boolean indicating whether the top of the stack is + * MagicValue(JS_GENERATOR_CLOSING). + * + * Category: Statements + * Type: For-In Statement + * Operands: + * Stack: val => val, res + */ \ + macro(JSOP_ISGENCLOSING, 187, "isgenclosing", NULL, 1, 1, 2, JOF_BYTE) \ /* * Pushes unsigned 24-bit int immediate integer operand onto the stack. * Category: Literals @@ -2178,8 +2201,26 @@ */ \ macro(JSOP_HOLE, 218, "hole", NULL, 1, 0, 1, JOF_BYTE) \ \ - macro(JSOP_UNUSED219, 219,"unused219", NULL, 1, 0, 0, JOF_BYTE) \ - macro(JSOP_UNUSED220, 220,"unused220", NULL, 1, 0, 0, JOF_BYTE) \ + /* + * Checks that the top value on the stack is callable, and throws a + * TypeError if not. The operand 'kind' is used only to generate an + * appropriate error message. + * Category: Statements + * Type: Function + * Operands: uint8_t kind + * Stack: result => result, callable + */ \ + macro(JSOP_CHECKISCALLABLE, 219, "checkiscallable", NULL, 2, 1, 1, JOF_UINT8) \ + \ + /* + * No-op used by the exception unwinder to determine the correct + * environment to unwind to when performing IteratorClose due to + * destructuring. + * Category: Other + * Operands: + * Stack: => + */ \ + macro(JSOP_TRY_DESTRUCTURING_ITERCLOSE, 220, "try-destructuring-iterclose", NULL, 1, 0, 0, JOF_BYTE) \ macro(JSOP_UNUSED221, 221,"unused221", NULL, 1, 0, 0, JOF_BYTE) \ macro(JSOP_UNUSED222, 222,"unused222", NULL, 1, 0, 0, JOF_BYTE) \ macro(JSOP_UNUSED223, 223,"unused223", NULL, 1, 0, 0, JOF_BYTE) \ diff --git a/js/src/vm/RegExpObject.cpp b/js/src/vm/RegExpObject.cpp index 97f1163aa8..e0b44e1eb7 100644 --- a/js/src/vm/RegExpObject.cpp +++ b/js/src/vm/RegExpObject.cpp @@ -196,6 +196,12 @@ RegExpObject::trace(JSTracer* trc, JSObject* obj) } } +static JSObject* +CreateRegExpPrototype(JSContext* cx, JSProtoKey key) +{ + return cx->global()->createBlankPrototype(cx, &RegExpObject::protoClass_); +} + static const ClassOps RegExpObjectClassOps = { nullptr, /* addProperty */ nullptr, /* delProperty */ @@ -229,6 +235,13 @@ const Class RegExpObject::class_ = { &RegExpObjectClassSpec }; +const Class RegExpObject::protoClass_ = { + js_Object_str, + JSCLASS_HAS_CACHED_PROTO(JSProto_RegExp), + JS_NULL_CLASS_OPS, + &RegExpObjectClassSpec +}; + RegExpObject* RegExpObject::create(ExclusiveContext* cx, const char16_t* chars, size_t length, RegExpFlag flags, TokenStream* tokenStream, LifoAlloc& alloc) diff --git a/js/src/vm/RegExpObject.h b/js/src/vm/RegExpObject.h index d6dde16684..dc428a9735 100644 --- a/js/src/vm/RegExpObject.h +++ b/js/src/vm/RegExpObject.h @@ -79,9 +79,6 @@ RegExpAlloc(ExclusiveContext* cx, HandleObject proto = nullptr); extern JSObject* CloneRegExpObject(JSContext* cx, JSObject* regexp); -extern JSObject* -CreateRegExpPrototype(JSContext* cx, JSProtoKey key); - /* * A RegExpShared is the compiled representation of a regexp. A RegExpShared is * potentially pointed to by multiple RegExpObjects. Additionally, C++ code may @@ -411,6 +408,7 @@ class RegExpObject : public NativeObject static const unsigned PRIVATE_SLOT = 3; static const Class class_; + static const Class protoClass_; // The maximum number of pairs a MatchResult can have, without having to // allocate a bigger MatchResult. diff --git a/js/src/vm/SelfHosting.cpp b/js/src/vm/SelfHosting.cpp index 6737e774ce..bf49f22688 100644 --- a/js/src/vm/SelfHosting.cpp +++ b/js/src/vm/SelfHosting.cpp @@ -2878,7 +2878,7 @@ CloneObject(JSContext* cx, HandleNativeObject selfHostedObject) RootedObject clone(cx); if (selfHostedObject->is<JSFunction>()) { RootedFunction selfHostedFunction(cx, &selfHostedObject->as<JSFunction>()); - bool hasName = selfHostedFunction->name() != nullptr; + bool hasName = selfHostedFunction->explicitName() != nullptr; // Arrow functions use the first extended slot for their lexical |this| value. MOZ_ASSERT(!selfHostedFunction->isArrow()); @@ -2894,7 +2894,7 @@ CloneObject(JSContext* cx, HandleNativeObject selfHostedObject) // self-hosting compartment has to be stored on the clone. if (clone && hasName) { clone->as<JSFunction>().setExtendedSlot(LAZY_FUNCTION_NAME_SLOT, - StringValue(selfHostedFunction->name())); + StringValue(selfHostedFunction->explicitName())); } } else if (selfHostedObject->is<RegExpObject>()) { RegExpObject& reobj = selfHostedObject->as<RegExpObject>(); @@ -2977,10 +2977,10 @@ JSRuntime::createLazySelfHostedFunctionClone(JSContext* cx, HandlePropertyName s return false; if (!selfHostedFun->isClassConstructor() && !selfHostedFun->hasGuessedAtom() && - selfHostedFun->name() != selfHostedName) + selfHostedFun->explicitName() != selfHostedName) { MOZ_ASSERT(selfHostedFun->getExtendedSlot(HAS_SELFHOSTED_CANONICAL_NAME_SLOT).toBoolean()); - funName = selfHostedFun->name(); + funName = selfHostedFun->explicitName(); } fun.set(NewScriptedFunction(cx, nargs, JSFunction::INTERPRETED_LAZY, @@ -3022,7 +3022,7 @@ JSRuntime::cloneSelfHostedFunctionScript(JSContext* cx, HandlePropertyName name, MOZ_ASSERT(!targetFun->isInterpretedLazy()); MOZ_ASSERT(sourceFun->nargs() == targetFun->nargs()); - MOZ_ASSERT(sourceFun->hasRest() == targetFun->hasRest()); + MOZ_ASSERT(sourceScript->hasRest() == targetFun->nonLazyScript()->hasRest()); // The target function might have been relazified after its flags changed. targetFun->setFlags(targetFun->flags() | sourceFun->flags()); diff --git a/js/src/vm/Shape.cpp b/js/src/vm/Shape.cpp index a64dc529a6..306a2c5400 100644 --- a/js/src/vm/Shape.cpp +++ b/js/src/vm/Shape.cpp @@ -1214,6 +1214,10 @@ JSObject::setFlags(ExclusiveContext* cx, BaseShape::Flag flags, GenerateShape ge RootedObject self(cx, this); + Shape* existingShape = self->ensureShape(cx); + if (!existingShape) + return false; + if (isNative() && as<NativeObject>().inDictionaryMode()) { if (generateShape == GENERATE_SHAPE && !as<NativeObject>().generateOwnShape(cx)) return false; @@ -1227,10 +1231,6 @@ JSObject::setFlags(ExclusiveContext* cx, BaseShape::Flag flags, GenerateShape ge return true; } - Shape* existingShape = self->ensureShape(cx); - if (!existingShape) - return false; - Shape* newShape = Shape::setObjectFlags(cx, flags, self->taggedProto(), existingShape); if (!newShape) return false; diff --git a/js/src/vm/Stack.cpp b/js/src/vm/Stack.cpp index 439bb1ed49..87e95c8936 100644 --- a/js/src/vm/Stack.cpp +++ b/js/src/vm/Stack.cpp @@ -85,7 +85,7 @@ InterpreterFrame::isNonGlobalEvalFrame() const JSObject* InterpreterFrame::createRestParameter(JSContext* cx) { - MOZ_ASSERT(callee().hasRest()); + MOZ_ASSERT(script()->hasRest()); unsigned nformal = callee().nargs() - 1, nactual = numActualArgs(); unsigned nrest = (nactual > nformal) ? nactual - nformal : 0; Value* restvp = argv() + nformal; diff --git a/js/src/vm/StructuredClone.cpp b/js/src/vm/StructuredClone.cpp index 4b01cda85b..3a062c3b8b 100644 --- a/js/src/vm/StructuredClone.cpp +++ b/js/src/vm/StructuredClone.cpp @@ -2188,12 +2188,14 @@ JSStructuredCloneReader::readHeader() return in.reportTruncated(); if (tag != SCTAG_HEADER) { - // Old structured clone buffer. We must have read it from disk or - // somewhere, so we can assume it's scope-compatible. + // Old structured clone buffer. We must have read it from disk. + storedScope = JS::StructuredCloneScope::DifferentProcess; return true; } MOZ_ALWAYS_TRUE(in.readPair(&tag, &data)); + storedScope = JS::StructuredCloneScope(data); + if (data != uint32_t(JS::StructuredCloneScope::SameProcessSameThread) && data != uint32_t(JS::StructuredCloneScope::SameProcessDifferentThread) && data != uint32_t(JS::StructuredCloneScope::DifferentProcess)) @@ -2202,7 +2204,6 @@ JSStructuredCloneReader::readHeader() "invalid structured clone scope"); return false; } - storedScope = JS::StructuredCloneScope(data); if (storedScope < allowedScope) { JS_ReportErrorNumberASCII(context(), GetErrorMessage, nullptr, JSMSG_SC_BAD_SERIALIZED_DATA, "incompatible structured clone scope"); diff --git a/js/src/vm/TypeInference.cpp b/js/src/vm/TypeInference.cpp index 2a7762e4f1..3d09c74641 100644 --- a/js/src/vm/TypeInference.cpp +++ b/js/src/vm/TypeInference.cpp @@ -4541,7 +4541,7 @@ TypeScript::printTypes(JSContext* cx, HandleScript script) const uintptr_t(script.get()), script->filename(), script->lineno()); if (script->functionNonDelazifying()) { - if (JSAtom* name = script->functionNonDelazifying()->name()) + if (JSAtom* name = script->functionNonDelazifying()->explicitName()) name->dumpCharsNoNewline(); } diff --git a/js/src/vm/TypedArrayObject.cpp b/js/src/vm/TypedArrayObject.cpp index 9d4ee94c6d..ae97be0de0 100644 --- a/js/src/vm/TypedArrayObject.cpp +++ b/js/src/vm/TypedArrayObject.cpp @@ -2870,7 +2870,7 @@ bool DataViewObject::defineGetter(JSContext* cx, PropertyName* name, HandleNativeObject proto) { RootedId id(cx, NameToId(name)); - RootedAtom atom(cx, IdToFunctionName(cx, id, "get")); + RootedAtom atom(cx, IdToFunctionName(cx, id, FunctionPrefixKind::Get)); if (!atom) return false; unsigned attrs = JSPROP_SHARED | JSPROP_GETTER; diff --git a/js/src/vm/Unicode.cpp b/js/src/vm/Unicode.cpp index f4acf8f31f..82541c2312 100644 --- a/js/src/vm/Unicode.cpp +++ b/js/src/vm/Unicode.cpp @@ -1748,3 +1748,882 @@ const uint8_t unicode::folding_index2[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; +bool +js::unicode::IsIdentifierStartNonBMP(uint32_t codePoint) +{ + if (codePoint >= 0x10000 && codePoint <= 0x1000b) + return true; + if (codePoint >= 0x1000d && codePoint <= 0x10026) + return true; + if (codePoint >= 0x10028 && codePoint <= 0x1003a) + return true; + if (codePoint >= 0x1003c && codePoint <= 0x1003d) + return true; + if (codePoint >= 0x1003f && codePoint <= 0x1004d) + return true; + if (codePoint >= 0x10050 && codePoint <= 0x1005d) + return true; + if (codePoint >= 0x10080 && codePoint <= 0x100fa) + return true; + if (codePoint >= 0x10140 && codePoint <= 0x10174) + return true; + if (codePoint >= 0x10280 && codePoint <= 0x1029c) + return true; + if (codePoint >= 0x102a0 && codePoint <= 0x102d0) + return true; + if (codePoint >= 0x10300 && codePoint <= 0x1031f) + return true; + if (codePoint >= 0x10330 && codePoint <= 0x1034a) + return true; + if (codePoint >= 0x10350 && codePoint <= 0x10375) + return true; + if (codePoint >= 0x10380 && codePoint <= 0x1039d) + return true; + if (codePoint >= 0x103a0 && codePoint <= 0x103c3) + return true; + if (codePoint >= 0x103c8 && codePoint <= 0x103cf) + return true; + if (codePoint >= 0x103d1 && codePoint <= 0x103d5) + return true; + if (codePoint >= 0x10400 && codePoint <= 0x1049d) + return true; + if (codePoint >= 0x104b0 && codePoint <= 0x104d3) + return true; + if (codePoint >= 0x104d8 && codePoint <= 0x104fb) + return true; + if (codePoint >= 0x10500 && codePoint <= 0x10527) + return true; + if (codePoint >= 0x10530 && codePoint <= 0x10563) + return true; + if (codePoint >= 0x10600 && codePoint <= 0x10736) + return true; + if (codePoint >= 0x10740 && codePoint <= 0x10755) + return true; + if (codePoint >= 0x10760 && codePoint <= 0x10767) + return true; + if (codePoint >= 0x10800 && codePoint <= 0x10805) + return true; + if (codePoint >= 0x10808 && codePoint <= 0x10808) + return true; + if (codePoint >= 0x1080a && codePoint <= 0x10835) + return true; + if (codePoint >= 0x10837 && codePoint <= 0x10838) + return true; + if (codePoint >= 0x1083c && codePoint <= 0x1083c) + return true; + if (codePoint >= 0x1083f && codePoint <= 0x10855) + return true; + if (codePoint >= 0x10860 && codePoint <= 0x10876) + return true; + if (codePoint >= 0x10880 && codePoint <= 0x1089e) + return true; + if (codePoint >= 0x108e0 && codePoint <= 0x108f2) + return true; + if (codePoint >= 0x108f4 && codePoint <= 0x108f5) + return true; + if (codePoint >= 0x10900 && codePoint <= 0x10915) + return true; + if (codePoint >= 0x10920 && codePoint <= 0x10939) + return true; + if (codePoint >= 0x10980 && codePoint <= 0x109b7) + return true; + if (codePoint >= 0x109be && codePoint <= 0x109bf) + return true; + if (codePoint >= 0x10a00 && codePoint <= 0x10a00) + return true; + if (codePoint >= 0x10a10 && codePoint <= 0x10a13) + return true; + if (codePoint >= 0x10a15 && codePoint <= 0x10a17) + return true; + if (codePoint >= 0x10a19 && codePoint <= 0x10a33) + return true; + if (codePoint >= 0x10a60 && codePoint <= 0x10a7c) + return true; + if (codePoint >= 0x10a80 && codePoint <= 0x10a9c) + return true; + if (codePoint >= 0x10ac0 && codePoint <= 0x10ac7) + return true; + if (codePoint >= 0x10ac9 && codePoint <= 0x10ae4) + return true; + if (codePoint >= 0x10b00 && codePoint <= 0x10b35) + return true; + if (codePoint >= 0x10b40 && codePoint <= 0x10b55) + return true; + if (codePoint >= 0x10b60 && codePoint <= 0x10b72) + return true; + if (codePoint >= 0x10b80 && codePoint <= 0x10b91) + return true; + if (codePoint >= 0x10c00 && codePoint <= 0x10c48) + return true; + if (codePoint >= 0x10c80 && codePoint <= 0x10cb2) + return true; + if (codePoint >= 0x10cc0 && codePoint <= 0x10cf2) + return true; + if (codePoint >= 0x11003 && codePoint <= 0x11037) + return true; + if (codePoint >= 0x11083 && codePoint <= 0x110af) + return true; + if (codePoint >= 0x110d0 && codePoint <= 0x110e8) + return true; + if (codePoint >= 0x11103 && codePoint <= 0x11126) + return true; + if (codePoint >= 0x11150 && codePoint <= 0x11172) + return true; + if (codePoint >= 0x11176 && codePoint <= 0x11176) + return true; + if (codePoint >= 0x11183 && codePoint <= 0x111b2) + return true; + if (codePoint >= 0x111c1 && codePoint <= 0x111c4) + return true; + if (codePoint >= 0x111da && codePoint <= 0x111da) + return true; + if (codePoint >= 0x111dc && codePoint <= 0x111dc) + return true; + if (codePoint >= 0x11200 && codePoint <= 0x11211) + return true; + if (codePoint >= 0x11213 && codePoint <= 0x1122b) + return true; + if (codePoint >= 0x11280 && codePoint <= 0x11286) + return true; + if (codePoint >= 0x11288 && codePoint <= 0x11288) + return true; + if (codePoint >= 0x1128a && codePoint <= 0x1128d) + return true; + if (codePoint >= 0x1128f && codePoint <= 0x1129d) + return true; + if (codePoint >= 0x1129f && codePoint <= 0x112a8) + return true; + if (codePoint >= 0x112b0 && codePoint <= 0x112de) + return true; + if (codePoint >= 0x11305 && codePoint <= 0x1130c) + return true; + if (codePoint >= 0x1130f && codePoint <= 0x11310) + return true; + if (codePoint >= 0x11313 && codePoint <= 0x11328) + return true; + if (codePoint >= 0x1132a && codePoint <= 0x11330) + return true; + if (codePoint >= 0x11332 && codePoint <= 0x11333) + return true; + if (codePoint >= 0x11335 && codePoint <= 0x11339) + return true; + if (codePoint >= 0x1133d && codePoint <= 0x1133d) + return true; + if (codePoint >= 0x11350 && codePoint <= 0x11350) + return true; + if (codePoint >= 0x1135d && codePoint <= 0x11361) + return true; + if (codePoint >= 0x11400 && codePoint <= 0x11434) + return true; + if (codePoint >= 0x11447 && codePoint <= 0x1144a) + return true; + if (codePoint >= 0x11480 && codePoint <= 0x114af) + return true; + if (codePoint >= 0x114c4 && codePoint <= 0x114c5) + return true; + if (codePoint >= 0x114c7 && codePoint <= 0x114c7) + return true; + if (codePoint >= 0x11580 && codePoint <= 0x115ae) + return true; + if (codePoint >= 0x115d8 && codePoint <= 0x115db) + return true; + if (codePoint >= 0x11600 && codePoint <= 0x1162f) + return true; + if (codePoint >= 0x11644 && codePoint <= 0x11644) + return true; + if (codePoint >= 0x11680 && codePoint <= 0x116aa) + return true; + if (codePoint >= 0x11700 && codePoint <= 0x11719) + return true; + if (codePoint >= 0x118a0 && codePoint <= 0x118df) + return true; + if (codePoint >= 0x118ff && codePoint <= 0x118ff) + return true; + if (codePoint >= 0x11ac0 && codePoint <= 0x11af8) + return true; + if (codePoint >= 0x11c00 && codePoint <= 0x11c08) + return true; + if (codePoint >= 0x11c0a && codePoint <= 0x11c2e) + return true; + if (codePoint >= 0x11c40 && codePoint <= 0x11c40) + return true; + if (codePoint >= 0x11c72 && codePoint <= 0x11c8f) + return true; + if (codePoint >= 0x12000 && codePoint <= 0x12399) + return true; + if (codePoint >= 0x12400 && codePoint <= 0x1246e) + return true; + if (codePoint >= 0x12480 && codePoint <= 0x12543) + return true; + if (codePoint >= 0x13000 && codePoint <= 0x1342e) + return true; + if (codePoint >= 0x14400 && codePoint <= 0x14646) + return true; + if (codePoint >= 0x16800 && codePoint <= 0x16a38) + return true; + if (codePoint >= 0x16a40 && codePoint <= 0x16a5e) + return true; + if (codePoint >= 0x16ad0 && codePoint <= 0x16aed) + return true; + if (codePoint >= 0x16b00 && codePoint <= 0x16b2f) + return true; + if (codePoint >= 0x16b40 && codePoint <= 0x16b43) + return true; + if (codePoint >= 0x16b63 && codePoint <= 0x16b77) + return true; + if (codePoint >= 0x16b7d && codePoint <= 0x16b8f) + return true; + if (codePoint >= 0x16f00 && codePoint <= 0x16f44) + return true; + if (codePoint >= 0x16f50 && codePoint <= 0x16f50) + return true; + if (codePoint >= 0x16f93 && codePoint <= 0x16f9f) + return true; + if (codePoint >= 0x16fe0 && codePoint <= 0x16fe0) + return true; + if (codePoint >= 0x17000 && codePoint <= 0x187ec) + return true; + if (codePoint >= 0x18800 && codePoint <= 0x18af2) + return true; + if (codePoint >= 0x1b000 && codePoint <= 0x1b001) + return true; + if (codePoint >= 0x1bc00 && codePoint <= 0x1bc6a) + return true; + if (codePoint >= 0x1bc70 && codePoint <= 0x1bc7c) + return true; + if (codePoint >= 0x1bc80 && codePoint <= 0x1bc88) + return true; + if (codePoint >= 0x1bc90 && codePoint <= 0x1bc99) + return true; + if (codePoint >= 0x1d400 && codePoint <= 0x1d454) + return true; + if (codePoint >= 0x1d456 && codePoint <= 0x1d49c) + return true; + if (codePoint >= 0x1d49e && codePoint <= 0x1d49f) + return true; + if (codePoint >= 0x1d4a2 && codePoint <= 0x1d4a2) + return true; + if (codePoint >= 0x1d4a5 && codePoint <= 0x1d4a6) + return true; + if (codePoint >= 0x1d4a9 && codePoint <= 0x1d4ac) + return true; + if (codePoint >= 0x1d4ae && codePoint <= 0x1d4b9) + return true; + if (codePoint >= 0x1d4bb && codePoint <= 0x1d4bb) + return true; + if (codePoint >= 0x1d4bd && codePoint <= 0x1d4c3) + return true; + if (codePoint >= 0x1d4c5 && codePoint <= 0x1d505) + return true; + if (codePoint >= 0x1d507 && codePoint <= 0x1d50a) + return true; + if (codePoint >= 0x1d50d && codePoint <= 0x1d514) + return true; + if (codePoint >= 0x1d516 && codePoint <= 0x1d51c) + return true; + if (codePoint >= 0x1d51e && codePoint <= 0x1d539) + return true; + if (codePoint >= 0x1d53b && codePoint <= 0x1d53e) + return true; + if (codePoint >= 0x1d540 && codePoint <= 0x1d544) + return true; + if (codePoint >= 0x1d546 && codePoint <= 0x1d546) + return true; + if (codePoint >= 0x1d54a && codePoint <= 0x1d550) + return true; + if (codePoint >= 0x1d552 && codePoint <= 0x1d6a5) + return true; + if (codePoint >= 0x1d6a8 && codePoint <= 0x1d6c0) + return true; + if (codePoint >= 0x1d6c2 && codePoint <= 0x1d6da) + return true; + if (codePoint >= 0x1d6dc && codePoint <= 0x1d6fa) + return true; + if (codePoint >= 0x1d6fc && codePoint <= 0x1d714) + return true; + if (codePoint >= 0x1d716 && codePoint <= 0x1d734) + return true; + if (codePoint >= 0x1d736 && codePoint <= 0x1d74e) + return true; + if (codePoint >= 0x1d750 && codePoint <= 0x1d76e) + return true; + if (codePoint >= 0x1d770 && codePoint <= 0x1d788) + return true; + if (codePoint >= 0x1d78a && codePoint <= 0x1d7a8) + return true; + if (codePoint >= 0x1d7aa && codePoint <= 0x1d7c2) + return true; + if (codePoint >= 0x1d7c4 && codePoint <= 0x1d7cb) + return true; + if (codePoint >= 0x1e800 && codePoint <= 0x1e8c4) + return true; + if (codePoint >= 0x1e900 && codePoint <= 0x1e943) + return true; + if (codePoint >= 0x1ee00 && codePoint <= 0x1ee03) + return true; + if (codePoint >= 0x1ee05 && codePoint <= 0x1ee1f) + return true; + if (codePoint >= 0x1ee21 && codePoint <= 0x1ee22) + return true; + if (codePoint >= 0x1ee24 && codePoint <= 0x1ee24) + return true; + if (codePoint >= 0x1ee27 && codePoint <= 0x1ee27) + return true; + if (codePoint >= 0x1ee29 && codePoint <= 0x1ee32) + return true; + if (codePoint >= 0x1ee34 && codePoint <= 0x1ee37) + return true; + if (codePoint >= 0x1ee39 && codePoint <= 0x1ee39) + return true; + if (codePoint >= 0x1ee3b && codePoint <= 0x1ee3b) + return true; + if (codePoint >= 0x1ee42 && codePoint <= 0x1ee42) + return true; + if (codePoint >= 0x1ee47 && codePoint <= 0x1ee47) + return true; + if (codePoint >= 0x1ee49 && codePoint <= 0x1ee49) + return true; + if (codePoint >= 0x1ee4b && codePoint <= 0x1ee4b) + return true; + if (codePoint >= 0x1ee4d && codePoint <= 0x1ee4f) + return true; + if (codePoint >= 0x1ee51 && codePoint <= 0x1ee52) + return true; + if (codePoint >= 0x1ee54 && codePoint <= 0x1ee54) + return true; + if (codePoint >= 0x1ee57 && codePoint <= 0x1ee57) + return true; + if (codePoint >= 0x1ee59 && codePoint <= 0x1ee59) + return true; + if (codePoint >= 0x1ee5b && codePoint <= 0x1ee5b) + return true; + if (codePoint >= 0x1ee5d && codePoint <= 0x1ee5d) + return true; + if (codePoint >= 0x1ee5f && codePoint <= 0x1ee5f) + return true; + if (codePoint >= 0x1ee61 && codePoint <= 0x1ee62) + return true; + if (codePoint >= 0x1ee64 && codePoint <= 0x1ee64) + return true; + if (codePoint >= 0x1ee67 && codePoint <= 0x1ee6a) + return true; + if (codePoint >= 0x1ee6c && codePoint <= 0x1ee72) + return true; + if (codePoint >= 0x1ee74 && codePoint <= 0x1ee77) + return true; + if (codePoint >= 0x1ee79 && codePoint <= 0x1ee7c) + return true; + if (codePoint >= 0x1ee7e && codePoint <= 0x1ee7e) + return true; + if (codePoint >= 0x1ee80 && codePoint <= 0x1ee89) + return true; + if (codePoint >= 0x1ee8b && codePoint <= 0x1ee9b) + return true; + if (codePoint >= 0x1eea1 && codePoint <= 0x1eea3) + return true; + if (codePoint >= 0x1eea5 && codePoint <= 0x1eea9) + return true; + if (codePoint >= 0x1eeab && codePoint <= 0x1eebb) + return true; + if (codePoint >= 0x20000 && codePoint <= 0x2a6d6) + return true; + if (codePoint >= 0x2a700 && codePoint <= 0x2b734) + return true; + if (codePoint >= 0x2b740 && codePoint <= 0x2b81d) + return true; + if (codePoint >= 0x2b820 && codePoint <= 0x2cea1) + return true; + if (codePoint >= 0x2f800 && codePoint <= 0x2fa1d) + return true; + return false; +} + +bool +js::unicode::IsIdentifierPartNonBMP(uint32_t codePoint) +{ + if (codePoint >= 0x10000 && codePoint <= 0x1000b) + return true; + if (codePoint >= 0x1000d && codePoint <= 0x10026) + return true; + if (codePoint >= 0x10028 && codePoint <= 0x1003a) + return true; + if (codePoint >= 0x1003c && codePoint <= 0x1003d) + return true; + if (codePoint >= 0x1003f && codePoint <= 0x1004d) + return true; + if (codePoint >= 0x10050 && codePoint <= 0x1005d) + return true; + if (codePoint >= 0x10080 && codePoint <= 0x100fa) + return true; + if (codePoint >= 0x10140 && codePoint <= 0x10174) + return true; + if (codePoint >= 0x101fd && codePoint <= 0x101fd) + return true; + if (codePoint >= 0x10280 && codePoint <= 0x1029c) + return true; + if (codePoint >= 0x102a0 && codePoint <= 0x102d0) + return true; + if (codePoint >= 0x102e0 && codePoint <= 0x102e0) + return true; + if (codePoint >= 0x10300 && codePoint <= 0x1031f) + return true; + if (codePoint >= 0x10330 && codePoint <= 0x1034a) + return true; + if (codePoint >= 0x10350 && codePoint <= 0x1037a) + return true; + if (codePoint >= 0x10380 && codePoint <= 0x1039d) + return true; + if (codePoint >= 0x103a0 && codePoint <= 0x103c3) + return true; + if (codePoint >= 0x103c8 && codePoint <= 0x103cf) + return true; + if (codePoint >= 0x103d1 && codePoint <= 0x103d5) + return true; + if (codePoint >= 0x10400 && codePoint <= 0x1049d) + return true; + if (codePoint >= 0x104a0 && codePoint <= 0x104a9) + return true; + if (codePoint >= 0x104b0 && codePoint <= 0x104d3) + return true; + if (codePoint >= 0x104d8 && codePoint <= 0x104fb) + return true; + if (codePoint >= 0x10500 && codePoint <= 0x10527) + return true; + if (codePoint >= 0x10530 && codePoint <= 0x10563) + return true; + if (codePoint >= 0x10600 && codePoint <= 0x10736) + return true; + if (codePoint >= 0x10740 && codePoint <= 0x10755) + return true; + if (codePoint >= 0x10760 && codePoint <= 0x10767) + return true; + if (codePoint >= 0x10800 && codePoint <= 0x10805) + return true; + if (codePoint >= 0x10808 && codePoint <= 0x10808) + return true; + if (codePoint >= 0x1080a && codePoint <= 0x10835) + return true; + if (codePoint >= 0x10837 && codePoint <= 0x10838) + return true; + if (codePoint >= 0x1083c && codePoint <= 0x1083c) + return true; + if (codePoint >= 0x1083f && codePoint <= 0x10855) + return true; + if (codePoint >= 0x10860 && codePoint <= 0x10876) + return true; + if (codePoint >= 0x10880 && codePoint <= 0x1089e) + return true; + if (codePoint >= 0x108e0 && codePoint <= 0x108f2) + return true; + if (codePoint >= 0x108f4 && codePoint <= 0x108f5) + return true; + if (codePoint >= 0x10900 && codePoint <= 0x10915) + return true; + if (codePoint >= 0x10920 && codePoint <= 0x10939) + return true; + if (codePoint >= 0x10980 && codePoint <= 0x109b7) + return true; + if (codePoint >= 0x109be && codePoint <= 0x109bf) + return true; + if (codePoint >= 0x10a00 && codePoint <= 0x10a03) + return true; + if (codePoint >= 0x10a05 && codePoint <= 0x10a06) + return true; + if (codePoint >= 0x10a0c && codePoint <= 0x10a13) + return true; + if (codePoint >= 0x10a15 && codePoint <= 0x10a17) + return true; + if (codePoint >= 0x10a19 && codePoint <= 0x10a33) + return true; + if (codePoint >= 0x10a38 && codePoint <= 0x10a3a) + return true; + if (codePoint >= 0x10a3f && codePoint <= 0x10a3f) + return true; + if (codePoint >= 0x10a60 && codePoint <= 0x10a7c) + return true; + if (codePoint >= 0x10a80 && codePoint <= 0x10a9c) + return true; + if (codePoint >= 0x10ac0 && codePoint <= 0x10ac7) + return true; + if (codePoint >= 0x10ac9 && codePoint <= 0x10ae6) + return true; + if (codePoint >= 0x10b00 && codePoint <= 0x10b35) + return true; + if (codePoint >= 0x10b40 && codePoint <= 0x10b55) + return true; + if (codePoint >= 0x10b60 && codePoint <= 0x10b72) + return true; + if (codePoint >= 0x10b80 && codePoint <= 0x10b91) + return true; + if (codePoint >= 0x10c00 && codePoint <= 0x10c48) + return true; + if (codePoint >= 0x10c80 && codePoint <= 0x10cb2) + return true; + if (codePoint >= 0x10cc0 && codePoint <= 0x10cf2) + return true; + if (codePoint >= 0x11000 && codePoint <= 0x11046) + return true; + if (codePoint >= 0x11066 && codePoint <= 0x1106f) + return true; + if (codePoint >= 0x1107f && codePoint <= 0x110ba) + return true; + if (codePoint >= 0x110d0 && codePoint <= 0x110e8) + return true; + if (codePoint >= 0x110f0 && codePoint <= 0x110f9) + return true; + if (codePoint >= 0x11100 && codePoint <= 0x11134) + return true; + if (codePoint >= 0x11136 && codePoint <= 0x1113f) + return true; + if (codePoint >= 0x11150 && codePoint <= 0x11173) + return true; + if (codePoint >= 0x11176 && codePoint <= 0x11176) + return true; + if (codePoint >= 0x11180 && codePoint <= 0x111c4) + return true; + if (codePoint >= 0x111ca && codePoint <= 0x111cc) + return true; + if (codePoint >= 0x111d0 && codePoint <= 0x111da) + return true; + if (codePoint >= 0x111dc && codePoint <= 0x111dc) + return true; + if (codePoint >= 0x11200 && codePoint <= 0x11211) + return true; + if (codePoint >= 0x11213 && codePoint <= 0x11237) + return true; + if (codePoint >= 0x1123e && codePoint <= 0x1123e) + return true; + if (codePoint >= 0x11280 && codePoint <= 0x11286) + return true; + if (codePoint >= 0x11288 && codePoint <= 0x11288) + return true; + if (codePoint >= 0x1128a && codePoint <= 0x1128d) + return true; + if (codePoint >= 0x1128f && codePoint <= 0x1129d) + return true; + if (codePoint >= 0x1129f && codePoint <= 0x112a8) + return true; + if (codePoint >= 0x112b0 && codePoint <= 0x112ea) + return true; + if (codePoint >= 0x112f0 && codePoint <= 0x112f9) + return true; + if (codePoint >= 0x11300 && codePoint <= 0x11303) + return true; + if (codePoint >= 0x11305 && codePoint <= 0x1130c) + return true; + if (codePoint >= 0x1130f && codePoint <= 0x11310) + return true; + if (codePoint >= 0x11313 && codePoint <= 0x11328) + return true; + if (codePoint >= 0x1132a && codePoint <= 0x11330) + return true; + if (codePoint >= 0x11332 && codePoint <= 0x11333) + return true; + if (codePoint >= 0x11335 && codePoint <= 0x11339) + return true; + if (codePoint >= 0x1133c && codePoint <= 0x11344) + return true; + if (codePoint >= 0x11347 && codePoint <= 0x11348) + return true; + if (codePoint >= 0x1134b && codePoint <= 0x1134d) + return true; + if (codePoint >= 0x11350 && codePoint <= 0x11350) + return true; + if (codePoint >= 0x11357 && codePoint <= 0x11357) + return true; + if (codePoint >= 0x1135d && codePoint <= 0x11363) + return true; + if (codePoint >= 0x11366 && codePoint <= 0x1136c) + return true; + if (codePoint >= 0x11370 && codePoint <= 0x11374) + return true; + if (codePoint >= 0x11400 && codePoint <= 0x1144a) + return true; + if (codePoint >= 0x11450 && codePoint <= 0x11459) + return true; + if (codePoint >= 0x11480 && codePoint <= 0x114c5) + return true; + if (codePoint >= 0x114c7 && codePoint <= 0x114c7) + return true; + if (codePoint >= 0x114d0 && codePoint <= 0x114d9) + return true; + if (codePoint >= 0x11580 && codePoint <= 0x115b5) + return true; + if (codePoint >= 0x115b8 && codePoint <= 0x115c0) + return true; + if (codePoint >= 0x115d8 && codePoint <= 0x115dd) + return true; + if (codePoint >= 0x11600 && codePoint <= 0x11640) + return true; + if (codePoint >= 0x11644 && codePoint <= 0x11644) + return true; + if (codePoint >= 0x11650 && codePoint <= 0x11659) + return true; + if (codePoint >= 0x11680 && codePoint <= 0x116b7) + return true; + if (codePoint >= 0x116c0 && codePoint <= 0x116c9) + return true; + if (codePoint >= 0x11700 && codePoint <= 0x11719) + return true; + if (codePoint >= 0x1171d && codePoint <= 0x1172b) + return true; + if (codePoint >= 0x11730 && codePoint <= 0x11739) + return true; + if (codePoint >= 0x118a0 && codePoint <= 0x118e9) + return true; + if (codePoint >= 0x118ff && codePoint <= 0x118ff) + return true; + if (codePoint >= 0x11ac0 && codePoint <= 0x11af8) + return true; + if (codePoint >= 0x11c00 && codePoint <= 0x11c08) + return true; + if (codePoint >= 0x11c0a && codePoint <= 0x11c36) + return true; + if (codePoint >= 0x11c38 && codePoint <= 0x11c40) + return true; + if (codePoint >= 0x11c50 && codePoint <= 0x11c59) + return true; + if (codePoint >= 0x11c72 && codePoint <= 0x11c8f) + return true; + if (codePoint >= 0x11c92 && codePoint <= 0x11ca7) + return true; + if (codePoint >= 0x11ca9 && codePoint <= 0x11cb6) + return true; + if (codePoint >= 0x12000 && codePoint <= 0x12399) + return true; + if (codePoint >= 0x12400 && codePoint <= 0x1246e) + return true; + if (codePoint >= 0x12480 && codePoint <= 0x12543) + return true; + if (codePoint >= 0x13000 && codePoint <= 0x1342e) + return true; + if (codePoint >= 0x14400 && codePoint <= 0x14646) + return true; + if (codePoint >= 0x16800 && codePoint <= 0x16a38) + return true; + if (codePoint >= 0x16a40 && codePoint <= 0x16a5e) + return true; + if (codePoint >= 0x16a60 && codePoint <= 0x16a69) + return true; + if (codePoint >= 0x16ad0 && codePoint <= 0x16aed) + return true; + if (codePoint >= 0x16af0 && codePoint <= 0x16af4) + return true; + if (codePoint >= 0x16b00 && codePoint <= 0x16b36) + return true; + if (codePoint >= 0x16b40 && codePoint <= 0x16b43) + return true; + if (codePoint >= 0x16b50 && codePoint <= 0x16b59) + return true; + if (codePoint >= 0x16b63 && codePoint <= 0x16b77) + return true; + if (codePoint >= 0x16b7d && codePoint <= 0x16b8f) + return true; + if (codePoint >= 0x16f00 && codePoint <= 0x16f44) + return true; + if (codePoint >= 0x16f50 && codePoint <= 0x16f7e) + return true; + if (codePoint >= 0x16f8f && codePoint <= 0x16f9f) + return true; + if (codePoint >= 0x16fe0 && codePoint <= 0x16fe0) + return true; + if (codePoint >= 0x17000 && codePoint <= 0x187ec) + return true; + if (codePoint >= 0x18800 && codePoint <= 0x18af2) + return true; + if (codePoint >= 0x1b000 && codePoint <= 0x1b001) + return true; + if (codePoint >= 0x1bc00 && codePoint <= 0x1bc6a) + return true; + if (codePoint >= 0x1bc70 && codePoint <= 0x1bc7c) + return true; + if (codePoint >= 0x1bc80 && codePoint <= 0x1bc88) + return true; + if (codePoint >= 0x1bc90 && codePoint <= 0x1bc99) + return true; + if (codePoint >= 0x1bc9d && codePoint <= 0x1bc9e) + return true; + if (codePoint >= 0x1d165 && codePoint <= 0x1d169) + return true; + if (codePoint >= 0x1d16d && codePoint <= 0x1d172) + return true; + if (codePoint >= 0x1d17b && codePoint <= 0x1d182) + return true; + if (codePoint >= 0x1d185 && codePoint <= 0x1d18b) + return true; + if (codePoint >= 0x1d1aa && codePoint <= 0x1d1ad) + return true; + if (codePoint >= 0x1d242 && codePoint <= 0x1d244) + return true; + if (codePoint >= 0x1d400 && codePoint <= 0x1d454) + return true; + if (codePoint >= 0x1d456 && codePoint <= 0x1d49c) + return true; + if (codePoint >= 0x1d49e && codePoint <= 0x1d49f) + return true; + if (codePoint >= 0x1d4a2 && codePoint <= 0x1d4a2) + return true; + if (codePoint >= 0x1d4a5 && codePoint <= 0x1d4a6) + return true; + if (codePoint >= 0x1d4a9 && codePoint <= 0x1d4ac) + return true; + if (codePoint >= 0x1d4ae && codePoint <= 0x1d4b9) + return true; + if (codePoint >= 0x1d4bb && codePoint <= 0x1d4bb) + return true; + if (codePoint >= 0x1d4bd && codePoint <= 0x1d4c3) + return true; + if (codePoint >= 0x1d4c5 && codePoint <= 0x1d505) + return true; + if (codePoint >= 0x1d507 && codePoint <= 0x1d50a) + return true; + if (codePoint >= 0x1d50d && codePoint <= 0x1d514) + return true; + if (codePoint >= 0x1d516 && codePoint <= 0x1d51c) + return true; + if (codePoint >= 0x1d51e && codePoint <= 0x1d539) + return true; + if (codePoint >= 0x1d53b && codePoint <= 0x1d53e) + return true; + if (codePoint >= 0x1d540 && codePoint <= 0x1d544) + return true; + if (codePoint >= 0x1d546 && codePoint <= 0x1d546) + return true; + if (codePoint >= 0x1d54a && codePoint <= 0x1d550) + return true; + if (codePoint >= 0x1d552 && codePoint <= 0x1d6a5) + return true; + if (codePoint >= 0x1d6a8 && codePoint <= 0x1d6c0) + return true; + if (codePoint >= 0x1d6c2 && codePoint <= 0x1d6da) + return true; + if (codePoint >= 0x1d6dc && codePoint <= 0x1d6fa) + return true; + if (codePoint >= 0x1d6fc && codePoint <= 0x1d714) + return true; + if (codePoint >= 0x1d716 && codePoint <= 0x1d734) + return true; + if (codePoint >= 0x1d736 && codePoint <= 0x1d74e) + return true; + if (codePoint >= 0x1d750 && codePoint <= 0x1d76e) + return true; + if (codePoint >= 0x1d770 && codePoint <= 0x1d788) + return true; + if (codePoint >= 0x1d78a && codePoint <= 0x1d7a8) + return true; + if (codePoint >= 0x1d7aa && codePoint <= 0x1d7c2) + return true; + if (codePoint >= 0x1d7c4 && codePoint <= 0x1d7cb) + return true; + if (codePoint >= 0x1d7ce && codePoint <= 0x1d7ff) + return true; + if (codePoint >= 0x1da00 && codePoint <= 0x1da36) + return true; + if (codePoint >= 0x1da3b && codePoint <= 0x1da6c) + return true; + if (codePoint >= 0x1da75 && codePoint <= 0x1da75) + return true; + if (codePoint >= 0x1da84 && codePoint <= 0x1da84) + return true; + if (codePoint >= 0x1da9b && codePoint <= 0x1da9f) + return true; + if (codePoint >= 0x1daa1 && codePoint <= 0x1daaf) + return true; + if (codePoint >= 0x1e000 && codePoint <= 0x1e006) + return true; + if (codePoint >= 0x1e008 && codePoint <= 0x1e018) + return true; + if (codePoint >= 0x1e01b && codePoint <= 0x1e021) + return true; + if (codePoint >= 0x1e023 && codePoint <= 0x1e024) + return true; + if (codePoint >= 0x1e026 && codePoint <= 0x1e02a) + return true; + if (codePoint >= 0x1e800 && codePoint <= 0x1e8c4) + return true; + if (codePoint >= 0x1e8d0 && codePoint <= 0x1e8d6) + return true; + if (codePoint >= 0x1e900 && codePoint <= 0x1e94a) + return true; + if (codePoint >= 0x1e950 && codePoint <= 0x1e959) + return true; + if (codePoint >= 0x1ee00 && codePoint <= 0x1ee03) + return true; + if (codePoint >= 0x1ee05 && codePoint <= 0x1ee1f) + return true; + if (codePoint >= 0x1ee21 && codePoint <= 0x1ee22) + return true; + if (codePoint >= 0x1ee24 && codePoint <= 0x1ee24) + return true; + if (codePoint >= 0x1ee27 && codePoint <= 0x1ee27) + return true; + if (codePoint >= 0x1ee29 && codePoint <= 0x1ee32) + return true; + if (codePoint >= 0x1ee34 && codePoint <= 0x1ee37) + return true; + if (codePoint >= 0x1ee39 && codePoint <= 0x1ee39) + return true; + if (codePoint >= 0x1ee3b && codePoint <= 0x1ee3b) + return true; + if (codePoint >= 0x1ee42 && codePoint <= 0x1ee42) + return true; + if (codePoint >= 0x1ee47 && codePoint <= 0x1ee47) + return true; + if (codePoint >= 0x1ee49 && codePoint <= 0x1ee49) + return true; + if (codePoint >= 0x1ee4b && codePoint <= 0x1ee4b) + return true; + if (codePoint >= 0x1ee4d && codePoint <= 0x1ee4f) + return true; + if (codePoint >= 0x1ee51 && codePoint <= 0x1ee52) + return true; + if (codePoint >= 0x1ee54 && codePoint <= 0x1ee54) + return true; + if (codePoint >= 0x1ee57 && codePoint <= 0x1ee57) + return true; + if (codePoint >= 0x1ee59 && codePoint <= 0x1ee59) + return true; + if (codePoint >= 0x1ee5b && codePoint <= 0x1ee5b) + return true; + if (codePoint >= 0x1ee5d && codePoint <= 0x1ee5d) + return true; + if (codePoint >= 0x1ee5f && codePoint <= 0x1ee5f) + return true; + if (codePoint >= 0x1ee61 && codePoint <= 0x1ee62) + return true; + if (codePoint >= 0x1ee64 && codePoint <= 0x1ee64) + return true; + if (codePoint >= 0x1ee67 && codePoint <= 0x1ee6a) + return true; + if (codePoint >= 0x1ee6c && codePoint <= 0x1ee72) + return true; + if (codePoint >= 0x1ee74 && codePoint <= 0x1ee77) + return true; + if (codePoint >= 0x1ee79 && codePoint <= 0x1ee7c) + return true; + if (codePoint >= 0x1ee7e && codePoint <= 0x1ee7e) + return true; + if (codePoint >= 0x1ee80 && codePoint <= 0x1ee89) + return true; + if (codePoint >= 0x1ee8b && codePoint <= 0x1ee9b) + return true; + if (codePoint >= 0x1eea1 && codePoint <= 0x1eea3) + return true; + if (codePoint >= 0x1eea5 && codePoint <= 0x1eea9) + return true; + if (codePoint >= 0x1eeab && codePoint <= 0x1eebb) + return true; + if (codePoint >= 0x20000 && codePoint <= 0x2a6d6) + return true; + if (codePoint >= 0x2a700 && codePoint <= 0x2b734) + return true; + if (codePoint >= 0x2b740 && codePoint <= 0x2b81d) + return true; + if (codePoint >= 0x2b820 && codePoint <= 0x2cea1) + return true; + if (codePoint >= 0x2f800 && codePoint <= 0x2fa1d) + return true; + if (codePoint >= 0xe0100 && codePoint <= 0xe01ef) + return true; + return false; +} diff --git a/js/src/vm/Unicode.h b/js/src/vm/Unicode.h index 8b538d06de..bdac848fbd 100644 --- a/js/src/vm/Unicode.h +++ b/js/src/vm/Unicode.h @@ -143,11 +143,15 @@ IsIdentifierStart(char16_t ch) return CharInfo(ch).isUnicodeIDStart(); } +bool +IsIdentifierStartNonBMP(uint32_t codePoint); + inline bool IsIdentifierStart(uint32_t codePoint) { - // TODO: Supplemental code points not yet supported (bug 1197230). - return codePoint <= UTF16Max && IsIdentifierStart(char16_t(codePoint)); + if (MOZ_UNLIKELY(codePoint > UTF16Max)) + return IsIdentifierStartNonBMP(codePoint); + return IsIdentifierStart(char16_t(codePoint)); } inline bool @@ -170,11 +174,16 @@ IsIdentifierPart(char16_t ch) return CharInfo(ch).isUnicodeIDContinue(); } + +bool +IsIdentifierPartNonBMP(uint32_t codePoint); + inline bool IsIdentifierPart(uint32_t codePoint) { - // TODO: Supplemental code points not yet supported (bug 1197230). - return codePoint <= UTF16Max && IsIdentifierPart(char16_t(codePoint)); + if (MOZ_UNLIKELY(codePoint > UTF16Max)) + return IsIdentifierPartNonBMP(codePoint); + return IsIdentifierPart(char16_t(codePoint)); } inline bool @@ -183,6 +192,17 @@ IsUnicodeIDStart(char16_t ch) return CharInfo(ch).isUnicodeIDStart(); } +bool +IsUnicodeIDStartNonBMP(uint32_t codePoint); + +inline bool +IsUnicodeIDStart(uint32_t codePoint) +{ + if (MOZ_UNLIKELY(codePoint > UTF16Max)) + return IsIdentifierStartNonBMP(codePoint); + return IsUnicodeIDStart(char16_t(codePoint)); +} + inline bool IsSpace(char16_t ch) { diff --git a/js/src/vm/UnicodeNonBMP.h b/js/src/vm/UnicodeNonBMP.h index 6cc64cde4a..f99e227cdd 100644 --- a/js/src/vm/UnicodeNonBMP.h +++ b/js/src/vm/UnicodeNonBMP.h @@ -10,6 +10,16 @@ #ifndef vm_UnicodeNonBMP_h #define vm_UnicodeNonBMP_h +// |macro| receives the following arguments +// macro(FROM, TO, LEAD, TRAIL_FROM, TRAIL_TO, DIFF) +// FROM: code point where the range starts +// TO: code point where the range ends +// LEAD: common lead surrogate of FROM and TO +// TRAIL_FROM: trail surrogate of FROM +// TRAIL_FROM: trail surrogate of TO +// DIFF: the difference between the code point in the range and +// converted code point + #define FOR_EACH_NON_BMP_LOWERCASE(macro) \ macro(0x10400, 0x10427, 0xd801, 0xdc00, 0xdc27, 40) \ macro(0x104b0, 0x104d3, 0xd801, 0xdcb0, 0xdcd3, 40) \ diff --git a/js/src/vm/make_unicode.py b/js/src/vm/make_unicode.py index 5565d7d148..83f0d004b3 100755 --- a/js/src/vm/make_unicode.py +++ b/js/src/vm/make_unicode.py @@ -133,6 +133,17 @@ def read_derived_core_properties(derived_core_properties): for char in range(int(start, 16), int(end, 16) + 1): yield (char, char_property) +def int_ranges(ints): + """ Yields consecutive ranges (inclusive) from integer values. """ + from itertools import tee, izip_longest + + (a, b) = tee(sorted(ints)) + start = next(b) + for (curr, succ) in izip_longest(a, b): + if curr + 1 != succ: + yield (start, curr) + start = succ + def utf16_encode(code): NonBMPMin = 0x10000 LeadSurrogateMin = 0xD800 @@ -144,37 +155,65 @@ def utf16_encode(code): return lead, trail def make_non_bmp_convert_macro(out_file, name, convert_map): + # Find continuous range in convert_map. convert_list = [] entry = None for code in sorted(convert_map.keys()): + lead, trail = utf16_encode(code) converted = convert_map[code] diff = converted - code - if entry and code == entry['code'] + entry['length'] and diff == entry['diff']: + if (entry and code == entry['code'] + entry['length'] and + diff == entry['diff'] and lead == entry['lead']): + entry['length'] += 1 continue - entry = { 'code': code, 'diff': diff, 'length': 1 } + entry = { + 'code': code, + 'diff': diff, + 'length': 1, + 'lead': lead, + 'trail': trail, + } convert_list.append(entry) + # Generate macro call for each range. lines = [] for entry in convert_list: from_code = entry['code'] to_code = entry['code'] + entry['length'] - 1 diff = entry['diff'] - from_lead, from_trail = utf16_encode(from_code) - to_lead, to_trail = utf16_encode(to_code) - - assert from_lead == to_lead + lead = entry['lead'] + from_trail = entry['trail'] + to_trail = entry['trail'] + entry['length'] - 1 lines.append(' macro(0x{:x}, 0x{:x}, 0x{:x}, 0x{:x}, 0x{:x}, {:d})'.format( - from_code, to_code, from_lead, from_trail, to_trail, diff)) + from_code, to_code, lead, from_trail, to_trail, diff)) out_file.write('#define FOR_EACH_NON_BMP_{}(macro) \\\n'.format(name)) out_file.write(' \\\n'.join(lines)) out_file.write('\n') +def for_each_non_bmp_group(group_set): + # Find continuous range in group_set. + group_list = [] + entry = None + for code in sorted(group_set.keys()): + if entry and code == entry['code'] + entry['length']: + entry['length'] += 1 + continue + + entry = { + 'code': code, + 'length': 1 + } + group_list.append(entry) + + for entry in group_list: + yield (entry['code'], entry['code'] + entry['length'] - 1) + def process_derived_core_properties(derived_core_properties): id_start = set() id_continue = set() @@ -203,6 +242,9 @@ def process_unicode_data(unicode_data, derived_core_properties): non_bmp_lower_map = {} non_bmp_upper_map = {} + non_bmp_id_start_set = {} + non_bmp_id_cont_set = {} + non_bmp_space_set = {} (id_start, id_continue) = process_derived_core_properties(derived_core_properties) @@ -235,6 +277,13 @@ def process_unicode_data(unicode_data, derived_core_properties): non_bmp_lower_map[code] = lower if code != upper: non_bmp_upper_map[code] = upper + if category == 'Zs': + non_bmp_space_set[code] = 1 + test_space_table.append(code) + if code in id_start: + non_bmp_id_start_set[code] = 1 + if code in id_continue: + non_bmp_id_cont_set[code] = 1 continue # we combine whitespace and lineterminators because in pratice we don't need them separated @@ -304,6 +353,8 @@ def process_unicode_data(unicode_data, derived_core_properties): table, index, same_upper_table, same_upper_index, non_bmp_lower_map, non_bmp_upper_map, + non_bmp_space_set, + non_bmp_id_start_set, non_bmp_id_cont_set, test_table, test_space_table, ) @@ -401,6 +452,16 @@ def make_non_bmp_file(version, #ifndef vm_UnicodeNonBMP_h #define vm_UnicodeNonBMP_h +// |macro| receives the following arguments +// macro(FROM, TO, LEAD, TRAIL_FROM, TRAIL_TO, DIFF) +// FROM: code point where the range starts +// TO: code point where the range ends +// LEAD: common lead surrogate of FROM and TO +// TRAIL_FROM: trail surrogate of FROM +// TRAIL_FROM: trail surrogate of TO +// DIFF: the difference between the code point in the range and +// converted code point + """) make_non_bmp_convert_macro(non_bmp_file, 'LOWERCASE', non_bmp_lower_map) @@ -514,7 +575,9 @@ if (typeof reportCompare === "function") def make_unicode_file(version, table, index, same_upper_table, same_upper_index, - folding_table, folding_index): + folding_table, folding_index, + non_bmp_space_set, + non_bmp_id_start_set, non_bmp_id_cont_set): index1, index2, shift = splitbins(index) # Don't forget to update CharInfo in Unicode.h if you need to change this @@ -671,6 +734,43 @@ def make_unicode_file(version, dump(folding_index2, 'folding_index2', data_file) data_file.write('\n') + # If the following assert fails, it means space character is added to + # non-BMP area. In that case the following code should be uncommented + # and the corresponding code should be added to frontend. + assert len(non_bmp_space_set.keys()) == 0 + + data_file.write("""\ +bool +js::unicode::IsIdentifierStartNonBMP(uint32_t codePoint) +{ +""") + + for (from_code, to_code) in for_each_non_bmp_group(non_bmp_id_start_set): + data_file.write("""\ + if (codePoint >= 0x{:x} && codePoint <= 0x{:x}) + return true; +""".format(from_code, to_code)) + + data_file.write("""\ + return false; +} + +bool +js::unicode::IsIdentifierPartNonBMP(uint32_t codePoint) +{ +""") + + for (from_code, to_code) in for_each_non_bmp_group(non_bmp_id_cont_set): + data_file.write("""\ + if (codePoint >= 0x{:x} && codePoint <= 0x{:x}) + return true; +""".format(from_code, to_code)) + + data_file.write("""\ + return false; +} +""") + def getsize(data): """ return smallest possible integer size for the given array """ maxdata = max(data) @@ -740,6 +840,204 @@ def splitbins(t): assert t[i] == t2[(t1[i >> shift] << shift) + (i & mask)] return best +def make_irregexp_tables(version, + table, index, + folding_table, folding_index, + test_table): + import string + from functools import partial + from itertools import chain, ifilter, imap + + MAX_ASCII = 0x7F + MAX_LATIN1 = 0xFF + LEAD_SURROGATE_MIN = 0xD800 + TRAIL_SURROGATE_MAX = 0xDFFF + + def hex2(n): + assert 0 <= n and n < 16**2 + return '0x{:02X}'.format(n) + + def hex4(n): + assert 0 <= n and n < 16**4 + return '0x{:04X}'.format(n) + + def uhex4(n): + assert 0 <= n and n < 16**4 + return 'U+{:04X}'.format(n) + + def case_info(code): + assert 0 <= code and code <= MAX_BMP + (upper, lower, flags) = table[index[code]] + return ((code + upper) & 0xffff, (code + lower) & 0xffff, flags) + + def is_space(code): + (_, _, flags) = case_info(code) + return bool(flags & FLAG_SPACE) + + def to_upper(code): + (upper, _, _) = case_info(code) + return upper + + def casefold(code): + assert 0 <= code and code <= MAX_BMP + (folding, _, _, _) = folding_table[folding_index[code]] + return (code + folding) & 0xffff + + def casefolds_to_ascii(code): + return casefold(code) <= MAX_ASCII + + def casefolds_to_latin1(code): + return casefold(code) <= MAX_LATIN1 + + def casemaps_to_nonlatin1(code): + upper = to_upper(code) + return upper > MAX_LATIN1 + + def char_name(code): + assert 0 <= code and code <= MAX_BMP + if code not in test_table: + return '<Unused>' + if code == LEAD_SURROGATE_MIN: + return '<Lead Surrogate Min>' + if code == TRAIL_SURROGATE_MAX: + return '<Trail Surrogate Max>' + (_, _, name, alias) = test_table[code] + return name if not name.startswith('<') else alias + + def write_character_range(println, name, characters): + char_ranges = list(int_ranges(characters)) + println('') + println('const int js::irregexp::k{}Ranges[] = {{'.format(name)) + for (start, end) in char_ranges: + s_name = char_name(start) + e_name = char_name(end) + println(' {}, {} + 1, // {}'.format(hex4(start), hex4(end), + '{}..{}'.format(s_name, e_name) + if start != end else s_name)) + println(' {} + 1'.format(hex4(MAX_BMP))) + println('};') + println('const int js::irregexp::k{}RangeCount = {};'.format(name, + len(char_ranges) * 2 + 1)) + + def write_character_test(println, test, consequent, default): + # Latin1 characters which, when case-mapped through + # String.prototype.toUpperCase(), canonicalize to a non-Latin1 character. + # ES2017, §21.2.2.8.2 Runtime Semantics: Canonicalize + casemapped_to_nonlatin1 = ifilter(casemaps_to_nonlatin1, xrange(0, MAX_LATIN1 + 1)) + + def casemap_closure(ch): + upper = to_upper(ch) + return (ch, [c for c in xrange(MAX_LATIN1 + 1, MAX_BMP + 1) if upper == to_upper(c)]) + + # Mapping from Latin1 characters to the list of case map equivalent + # non-Latin1 characters. + casemap_for_latin1 = dict(chain(imap(casemap_closure, casemapped_to_nonlatin1))) + + # Non-latin1 characters which, when Unicode case-folded, canonicalize to + # a Latin1 character. + # ES2017, §21.2.2.8.2 Runtime Semantics: Canonicalize + casefolded_to_latin1 = ifilter(casefolds_to_latin1, xrange(MAX_LATIN1 + 1, MAX_BMP + 1)) + + println(' if (unicode) {') + for ch in casefolded_to_latin1: + casefolded = casefold(ch) + # Skip if also handled below for case mapping. + if casefolded in casemap_for_latin1 and ch in casemap_for_latin1[casefolded]: + continue + println(' // "{}" case folds to "{}".'.format(char_name(ch), + char_name(casefolded))) + println(' if ({})'.format(test(ch))) + println(' return {};'.format(consequent(casefolded))) + println(' }') + println('') + for (ch, casemapped_chars) in casemap_for_latin1.iteritems(): + for casemapped in casemapped_chars: + println(' // "{}" case maps to "{}".'.format(char_name(casemapped), + char_name(ch))) + println(' if ({})'.format(' || '.join(imap(test, casemapped_chars)))) + println(' return {};'.format(consequent(ch))) + println(' return {};'.format(default)) + + with io.open('../irregexp/RegExpCharacters-inl.h', 'wb') as chars_file: + write = partial(print, file=chars_file, sep='', end='') + println = partial(write, end='\n') + + write(warning_message) + write(unicode_version_message.format(version)) + + println('#ifndef V8_JSREGEXPCHARACTERS_INL_H_') + println('#define V8_JSREGEXPCHARACTERS_INL_H_') + println('') + println('namespace js {') + println('') + println('namespace irregexp {') + println('') + + println('static inline bool') + println('RangeContainsLatin1Equivalents(CharacterRange range, bool unicode)') + println('{') + write_character_test(println, lambda ch: 'range.Contains({})'.format(hex4(ch)), + lambda _: 'true', 'false') + println('}') + + println('') + println('} } // namespace js::irregexp') + println('') + println('#endif // V8_JSREGEXPCHARACTERS_INL_H_') + + with io.open('../irregexp/RegExpCharacters.cpp', 'wb') as chars_file: + write = partial(print, file=chars_file, sep='', end='') + println = partial(write, end='\n') + character_range = partial(write_character_range, println) + + # Characters in \s, 21.2.2.12 CharacterClassEscape. + space_chars = filter(is_space, xrange(0, MAX_BMP + 1)) + + # Characters in \d, 21.2.2.12 CharacterClassEscape. + digit_chars = map(ord, string.digits) + assert all(ch <= MAX_ASCII for ch in digit_chars) + + # Characters in \w, 21.2.2.12 CharacterClassEscape. + word_chars = map(ord, string.digits + string.ascii_letters + '_') + assert all(ch <= MAX_ASCII for ch in word_chars) + + # Characters which case-fold to characters in \w. + ignorecase_word_chars = (word_chars + + filter(casefolds_to_ascii, xrange(MAX_ASCII + 1, MAX_BMP + 1))) + + # Surrogate characters. + surrogate_chars = range(LEAD_SURROGATE_MIN, TRAIL_SURROGATE_MAX + 1) + + write(warning_message) + write(unicode_version_message.format(version)) + println('#include "irregexp/RegExpCharacters.h"') + println('') + println('#include "mozilla/Assertions.h"') + println('') + + println('char16_t') + println('js::irregexp::ConvertNonLatin1ToLatin1(char16_t c, bool unicode)') + println('{') + println(' MOZ_ASSERT(c > {}, "Character mustn\'t be Latin1");'.format(hex2(MAX_LATIN1))) + write_character_test(println, lambda ch: 'c == {}'.format(hex4(ch)), hex2, '0') + println('}') + + character_range('Space', space_chars) + character_range('SpaceAndSurrogate', space_chars + surrogate_chars) + + character_range('Word', word_chars) + character_range('IgnoreCaseWord', ignorecase_word_chars) + character_range('WordAndSurrogate', word_chars + surrogate_chars) + character_range('NegatedIgnoreCaseWordAndSurrogate', + set(xrange(0, MAX_BMP + 1)) - set(ignorecase_word_chars + surrogate_chars)) + + character_range('Digit', digit_chars) + character_range('DigitAndSurrogate', digit_chars + surrogate_chars) + + character_range('Surrogate', surrogate_chars) + + character_range('LineTerminator', line_terminator) + def update_unicode(args): import urllib2 @@ -791,6 +1089,8 @@ def update_unicode(args): table, index, same_upper_table, same_upper_index, non_bmp_lower_map, non_bmp_upper_map, + non_bmp_space_set, + non_bmp_id_start_set, non_bmp_id_cont_set, test_table, test_space_table ) = process_unicode_data(unicode_data, derived_core_properties) ( @@ -803,10 +1103,16 @@ def update_unicode(args): make_unicode_file(unicode_version, table, index, same_upper_table, same_upper_index, - folding_table, folding_index) + folding_table, folding_index, + non_bmp_space_set, + non_bmp_id_start_set, non_bmp_id_cont_set) make_non_bmp_file(unicode_version, non_bmp_lower_map, non_bmp_upper_map, non_bmp_folding_map, non_bmp_rev_folding_map) + make_irregexp_tables(unicode_version, + table, index, + folding_table, folding_index, + test_table) make_bmp_mapping_test(unicode_version, test_table) make_non_bmp_mapping_test(unicode_version, non_bmp_upper_map, non_bmp_lower_map) |