[builtins] Convert String HTML functions (ex. anchor, big, bold) to CSA
- Added TFJ builtins for S.p.{anchor, big, blink, bold, fontcolor, fontsize, fixed, italics, link, small, strike, sub, sup} - Removed functionality from string.js Bug: v8:5049 Change-Id: I3a91b52eaceef5c47bb55ed62780d72ef1e802e9 Reviewed-on: https://chromium-review.googlesource.com/666487 Commit-Queue: Jakob Gruber <jgruber@chromium.org> Reviewed-by: Jakob Gruber <jgruber@chromium.org> Cr-Commit-Position: refs/heads/master@{#48056}
This commit is contained in:
parent
3d046986f0
commit
8dfdeae0f1
@ -1939,6 +1939,14 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
|
||||
DONT_ENUM);
|
||||
|
||||
// Install the String.prototype methods.
|
||||
SimpleInstallFunction(prototype, "anchor", Builtins::kStringPrototypeAnchor,
|
||||
1, true);
|
||||
SimpleInstallFunction(prototype, "big", Builtins::kStringPrototypeBig, 0,
|
||||
true);
|
||||
SimpleInstallFunction(prototype, "blink", Builtins::kStringPrototypeBlink,
|
||||
0, true);
|
||||
SimpleInstallFunction(prototype, "bold", Builtins::kStringPrototypeBold, 0,
|
||||
true);
|
||||
SimpleInstallFunction(prototype, "charAt", Builtins::kStringPrototypeCharAt,
|
||||
1, true);
|
||||
SimpleInstallFunction(prototype, "charCodeAt",
|
||||
@ -1949,12 +1957,22 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
|
||||
1, false);
|
||||
SimpleInstallFunction(prototype, "endsWith",
|
||||
Builtins::kStringPrototypeEndsWith, 1, false);
|
||||
SimpleInstallFunction(prototype, "fontcolor",
|
||||
Builtins::kStringPrototypeFontcolor, 1, true);
|
||||
SimpleInstallFunction(prototype, "fontsize",
|
||||
Builtins::kStringPrototypeFontsize, 1, true);
|
||||
SimpleInstallFunction(prototype, "fixed", Builtins::kStringPrototypeFixed,
|
||||
0, true);
|
||||
SimpleInstallFunction(prototype, "includes",
|
||||
Builtins::kStringPrototypeIncludes, 1, false);
|
||||
SimpleInstallFunction(prototype, "indexOf",
|
||||
Builtins::kStringPrototypeIndexOf, 1, false);
|
||||
SimpleInstallFunction(prototype, "italics",
|
||||
Builtins::kStringPrototypeItalics, 0, true);
|
||||
SimpleInstallFunction(prototype, "lastIndexOf",
|
||||
Builtins::kStringPrototypeLastIndexOf, 1, false);
|
||||
SimpleInstallFunction(prototype, "link", Builtins::kStringPrototypeLink, 1,
|
||||
true);
|
||||
SimpleInstallFunction(prototype, "localeCompare",
|
||||
Builtins::kStringPrototypeLocaleCompare, 1, true);
|
||||
#ifdef V8_INTL_SUPPORT
|
||||
@ -1970,12 +1988,20 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
|
||||
Builtins::kStringPrototypeReplace, 2, true);
|
||||
SimpleInstallFunction(prototype, "slice", Builtins::kStringPrototypeSlice,
|
||||
2, false);
|
||||
SimpleInstallFunction(prototype, "small", Builtins::kStringPrototypeSmall,
|
||||
0, true);
|
||||
SimpleInstallFunction(prototype, "split", Builtins::kStringPrototypeSplit,
|
||||
2, false);
|
||||
SimpleInstallFunction(prototype, "strike", Builtins::kStringPrototypeStrike,
|
||||
0, true);
|
||||
SimpleInstallFunction(prototype, "sub", Builtins::kStringPrototypeSub, 0,
|
||||
true);
|
||||
SimpleInstallFunction(prototype, "substr", Builtins::kStringPrototypeSubstr,
|
||||
2, false);
|
||||
SimpleInstallFunction(prototype, "substring",
|
||||
Builtins::kStringPrototypeSubstring, 2, false);
|
||||
SimpleInstallFunction(prototype, "sup", Builtins::kStringPrototypeSup, 0,
|
||||
true);
|
||||
SimpleInstallFunction(prototype, "startsWith",
|
||||
Builtins::kStringPrototypeStartsWith, 1, false);
|
||||
SimpleInstallFunction(prototype, "toString",
|
||||
|
@ -894,6 +894,14 @@ namespace internal {
|
||||
CPP(StringFromCodePoint) \
|
||||
/* ES6 #sec-string.fromcharcode */ \
|
||||
TFJ(StringFromCharCode, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
|
||||
/* ES6 #sec-string.prototype.anchor */ \
|
||||
TFJ(StringPrototypeAnchor, 1, kValue) \
|
||||
/* ES6 #sec-string.prototype.big */ \
|
||||
TFJ(StringPrototypeBig, 0) \
|
||||
/* ES6 #sec-string.prototype.blink */ \
|
||||
TFJ(StringPrototypeBlink, 0) \
|
||||
/* ES6 #sec-string.prototype.bold */ \
|
||||
TFJ(StringPrototypeBold, 0) \
|
||||
/* ES6 #sec-string.prototype.charat */ \
|
||||
TFJ(StringPrototypeCharAt, 1, kPosition) \
|
||||
/* ES6 #sec-string.prototype.charcodeat */ \
|
||||
@ -904,13 +912,23 @@ namespace internal {
|
||||
TFJ(StringPrototypeConcat, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
|
||||
/* ES6 #sec-string.prototype.endswith */ \
|
||||
CPP(StringPrototypeEndsWith) \
|
||||
/* ES6 #sec-string.prototype.fontcolor */ \
|
||||
TFJ(StringPrototypeFontcolor, 1, kValue) \
|
||||
/* ES6 #sec-string.prototype.fontsize */ \
|
||||
TFJ(StringPrototypeFontsize, 1, kValue) \
|
||||
/* ES6 #sec-string.prototype.fixed */ \
|
||||
TFJ(StringPrototypeFixed, 0) \
|
||||
/* ES6 #sec-string.prototype.includes */ \
|
||||
TFJ(StringPrototypeIncludes, \
|
||||
SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
|
||||
/* ES6 #sec-string.prototype.indexof */ \
|
||||
TFJ(StringPrototypeIndexOf, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
|
||||
/* ES6 #sec-string.prototype.italics */ \
|
||||
TFJ(StringPrototypeItalics, 0) \
|
||||
/* ES6 #sec-string.prototype.lastindexof */ \
|
||||
CPP(StringPrototypeLastIndexOf) \
|
||||
/* ES6 #sec-string.prototype.link */ \
|
||||
TFJ(StringPrototypeLink, 1, kValue) \
|
||||
/* ES6 #sec-string.prototype.localecompare */ \
|
||||
CPP(StringPrototypeLocaleCompare) \
|
||||
/* ES6 #sec-string.prototype.repeat */ \
|
||||
@ -919,13 +937,21 @@ namespace internal {
|
||||
TFJ(StringPrototypeReplace, 2, kSearch, kReplace) \
|
||||
/* ES6 #sec-string.prototype.slice */ \
|
||||
TFJ(StringPrototypeSlice, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
|
||||
/* ES6 #sec-string.prototype.small */ \
|
||||
TFJ(StringPrototypeSmall, 0) \
|
||||
/* ES6 #sec-string.prototype.split */ \
|
||||
TFJ(StringPrototypeSplit, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
|
||||
/* ES6 #sec-string.prototype.strike */ \
|
||||
TFJ(StringPrototypeStrike, 0) \
|
||||
/* ES6 #sec-string.prototype.sub */ \
|
||||
TFJ(StringPrototypeSub, 0) \
|
||||
/* ES6 #sec-string.prototype.substr */ \
|
||||
TFJ(StringPrototypeSubstr, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
|
||||
/* ES6 #sec-string.prototype.substring */ \
|
||||
TFJ(StringPrototypeSubstring, \
|
||||
SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
|
||||
/* ES6 #sec-string.prototype.sup */ \
|
||||
TFJ(StringPrototypeSup, 0) \
|
||||
/* ES6 #sec-string.prototype.startswith */ \
|
||||
CPP(StringPrototypeStartsWith) \
|
||||
/* ES6 #sec-string.prototype.tostring */ \
|
||||
|
@ -2154,5 +2154,166 @@ TF_BUILTIN(StringIteratorPrototypeNext, StringBuiltinsAssembler) {
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// ES6 section B.2.3 Additional Properties of the String.prototype object
|
||||
|
||||
class StringHtmlAssembler : public StringBuiltinsAssembler {
|
||||
public:
|
||||
explicit StringHtmlAssembler(compiler::CodeAssemblerState* state)
|
||||
: StringBuiltinsAssembler(state) {}
|
||||
|
||||
protected:
|
||||
void Generate(Node* const context, Node* const receiver,
|
||||
const char* method_name, const char* tag_name) {
|
||||
Node* const string = ToThisString(context, receiver, method_name);
|
||||
std::string open_tag = "<" + std::string(tag_name) + ">";
|
||||
std::string close_tag = "</" + std::string(tag_name) + ">";
|
||||
|
||||
Node* strings[] = {StringConstant(open_tag.c_str()), string,
|
||||
StringConstant(close_tag.c_str())};
|
||||
Return(ConcatStrings(context, strings, arraysize(strings)));
|
||||
}
|
||||
|
||||
void GenerateWithAttribute(Node* const context, Node* const receiver,
|
||||
const char* method_name, const char* tag_name,
|
||||
const char* attr, Node* const value) {
|
||||
Node* const string = ToThisString(context, receiver, method_name);
|
||||
Node* const value_string =
|
||||
EscapeQuotes(context, ToString_Inline(context, value));
|
||||
std::string open_tag_attr =
|
||||
"<" + std::string(tag_name) + " " + std::string(attr) + "=\"";
|
||||
std::string close_tag = "</" + std::string(tag_name) + ">";
|
||||
|
||||
Node* strings[] = {StringConstant(open_tag_attr.c_str()), value_string,
|
||||
StringConstant("\">"), string,
|
||||
StringConstant(close_tag.c_str())};
|
||||
Return(ConcatStrings(context, strings, arraysize(strings)));
|
||||
}
|
||||
|
||||
Node* ConcatStrings(Node* const context, Node** strings, int len) {
|
||||
VARIABLE(var_result, MachineRepresentation::kTagged, strings[0]);
|
||||
for (int i = 1; i < len; i++) {
|
||||
var_result.Bind(CallStub(CodeFactory::StringAdd(isolate()), context,
|
||||
var_result.value(), strings[i]));
|
||||
}
|
||||
return var_result.value();
|
||||
}
|
||||
|
||||
Node* EscapeQuotes(Node* const context, Node* const string) {
|
||||
CSA_ASSERT(this, IsString(string));
|
||||
Node* const regexp_function = LoadContextElement(
|
||||
LoadNativeContext(context), Context::REGEXP_FUNCTION_INDEX);
|
||||
Node* const initial_map = LoadObjectField(
|
||||
regexp_function, JSFunction::kPrototypeOrInitialMapOffset);
|
||||
// TODO(pwong): Refactor to not allocate RegExp
|
||||
Node* const regexp =
|
||||
CallRuntime(Runtime::kRegExpInitializeAndCompile, context,
|
||||
AllocateJSObjectFromMap(initial_map), StringConstant("\""),
|
||||
StringConstant("g"));
|
||||
|
||||
return CallRuntime(Runtime::kRegExpInternalReplace, context, regexp, string,
|
||||
StringConstant("""));
|
||||
}
|
||||
};
|
||||
|
||||
// ES6 #sec-string.prototype.anchor
|
||||
TF_BUILTIN(StringPrototypeAnchor, StringHtmlAssembler) {
|
||||
Node* const context = Parameter(Descriptor::kContext);
|
||||
Node* const receiver = Parameter(Descriptor::kReceiver);
|
||||
Node* const value = Parameter(Descriptor::kValue);
|
||||
GenerateWithAttribute(context, receiver, "String.prototype.anchor", "a",
|
||||
"name", value);
|
||||
}
|
||||
|
||||
// ES6 #sec-string.prototype.big
|
||||
TF_BUILTIN(StringPrototypeBig, StringHtmlAssembler) {
|
||||
Node* const context = Parameter(Descriptor::kContext);
|
||||
Node* const receiver = Parameter(Descriptor::kReceiver);
|
||||
Generate(context, receiver, "String.prototype.big", "big");
|
||||
}
|
||||
|
||||
// ES6 #sec-string.prototype.blink
|
||||
TF_BUILTIN(StringPrototypeBlink, StringHtmlAssembler) {
|
||||
Node* const context = Parameter(Descriptor::kContext);
|
||||
Node* const receiver = Parameter(Descriptor::kReceiver);
|
||||
Generate(context, receiver, "String.prototype.blink", "blink");
|
||||
}
|
||||
|
||||
// ES6 #sec-string.prototype.bold
|
||||
TF_BUILTIN(StringPrototypeBold, StringHtmlAssembler) {
|
||||
Node* const context = Parameter(Descriptor::kContext);
|
||||
Node* const receiver = Parameter(Descriptor::kReceiver);
|
||||
Generate(context, receiver, "String.prototype.bold", "b");
|
||||
}
|
||||
|
||||
// ES6 #sec-string.prototype.fontcolor
|
||||
TF_BUILTIN(StringPrototypeFontcolor, StringHtmlAssembler) {
|
||||
Node* const context = Parameter(Descriptor::kContext);
|
||||
Node* const receiver = Parameter(Descriptor::kReceiver);
|
||||
Node* const value = Parameter(Descriptor::kValue);
|
||||
GenerateWithAttribute(context, receiver, "String.prototype.fontcolor", "font",
|
||||
"color", value);
|
||||
}
|
||||
|
||||
// ES6 #sec-string.prototype.fontsize
|
||||
TF_BUILTIN(StringPrototypeFontsize, StringHtmlAssembler) {
|
||||
Node* const context = Parameter(Descriptor::kContext);
|
||||
Node* const receiver = Parameter(Descriptor::kReceiver);
|
||||
Node* const value = Parameter(Descriptor::kValue);
|
||||
GenerateWithAttribute(context, receiver, "String.prototype.fontsize", "font",
|
||||
"size", value);
|
||||
}
|
||||
|
||||
// ES6 #sec-string.prototype.fixed
|
||||
TF_BUILTIN(StringPrototypeFixed, StringHtmlAssembler) {
|
||||
Node* const context = Parameter(Descriptor::kContext);
|
||||
Node* const receiver = Parameter(Descriptor::kReceiver);
|
||||
Generate(context, receiver, "String.prototype.fixed", "tt");
|
||||
}
|
||||
|
||||
// ES6 #sec-string.prototype.italics
|
||||
TF_BUILTIN(StringPrototypeItalics, StringHtmlAssembler) {
|
||||
Node* const context = Parameter(Descriptor::kContext);
|
||||
Node* const receiver = Parameter(Descriptor::kReceiver);
|
||||
Generate(context, receiver, "String.prototype.italics", "i");
|
||||
}
|
||||
|
||||
// ES6 #sec-string.prototype.link
|
||||
TF_BUILTIN(StringPrototypeLink, StringHtmlAssembler) {
|
||||
Node* const context = Parameter(Descriptor::kContext);
|
||||
Node* const receiver = Parameter(Descriptor::kReceiver);
|
||||
Node* const value = Parameter(Descriptor::kValue);
|
||||
GenerateWithAttribute(context, receiver, "String.prototype.link", "a", "href",
|
||||
value);
|
||||
}
|
||||
|
||||
// ES6 #sec-string.prototype.small
|
||||
TF_BUILTIN(StringPrototypeSmall, StringHtmlAssembler) {
|
||||
Node* const context = Parameter(Descriptor::kContext);
|
||||
Node* const receiver = Parameter(Descriptor::kReceiver);
|
||||
Generate(context, receiver, "String.prototype.small", "small");
|
||||
}
|
||||
|
||||
// ES6 #sec-string.prototype.strike
|
||||
TF_BUILTIN(StringPrototypeStrike, StringHtmlAssembler) {
|
||||
Node* const context = Parameter(Descriptor::kContext);
|
||||
Node* const receiver = Parameter(Descriptor::kReceiver);
|
||||
Generate(context, receiver, "String.prototype.strike", "strike");
|
||||
}
|
||||
|
||||
// ES6 #sec-string.prototype.sub
|
||||
TF_BUILTIN(StringPrototypeSub, StringHtmlAssembler) {
|
||||
Node* const context = Parameter(Descriptor::kContext);
|
||||
Node* const receiver = Parameter(Descriptor::kReceiver);
|
||||
Generate(context, receiver, "String.prototype.sub", "sub");
|
||||
}
|
||||
|
||||
// ES6 #sec-string.prototype.sup
|
||||
TF_BUILTIN(StringPrototypeSup, StringHtmlAssembler) {
|
||||
Node* const context = Parameter(Descriptor::kContext);
|
||||
Node* const receiver = Parameter(Descriptor::kReceiver);
|
||||
Generate(context, receiver, "String.prototype.sup", "sup");
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -306,6 +306,7 @@ bool IntrinsicHasNoSideEffect(Runtime::FunctionId id) {
|
||||
V(StringCharCodeAt) \
|
||||
V(StringIndexOfUnchecked) \
|
||||
V(StringEqual) \
|
||||
V(RegExpInitializeAndCompile) \
|
||||
V(SymbolDescriptiveString) \
|
||||
V(GenerateRandomNumbers) \
|
||||
V(GlobalPrint) \
|
||||
@ -588,19 +589,32 @@ bool BuiltinHasNoSideEffect(Builtins::Name id) {
|
||||
case Builtins::kStringFromCharCode:
|
||||
case Builtins::kStringFromCodePoint:
|
||||
case Builtins::kStringConstructor:
|
||||
case Builtins::kStringPrototypeAnchor:
|
||||
case Builtins::kStringPrototypeBig:
|
||||
case Builtins::kStringPrototypeBlink:
|
||||
case Builtins::kStringPrototypeBold:
|
||||
case Builtins::kStringPrototypeCharAt:
|
||||
case Builtins::kStringPrototypeCharCodeAt:
|
||||
case Builtins::kStringPrototypeCodePointAt:
|
||||
case Builtins::kStringPrototypeConcat:
|
||||
case Builtins::kStringPrototypeEndsWith:
|
||||
case Builtins::kStringPrototypeFixed:
|
||||
case Builtins::kStringPrototypeFontcolor:
|
||||
case Builtins::kStringPrototypeFontsize:
|
||||
case Builtins::kStringPrototypeIncludes:
|
||||
case Builtins::kStringPrototypeIndexOf:
|
||||
case Builtins::kStringPrototypeItalics:
|
||||
case Builtins::kStringPrototypeLastIndexOf:
|
||||
case Builtins::kStringPrototypeLink:
|
||||
case Builtins::kStringPrototypeRepeat:
|
||||
case Builtins::kStringPrototypeSlice:
|
||||
case Builtins::kStringPrototypeSmall:
|
||||
case Builtins::kStringPrototypeStartsWith:
|
||||
case Builtins::kStringPrototypeStrike:
|
||||
case Builtins::kStringPrototypeSub:
|
||||
case Builtins::kStringPrototypeSubstr:
|
||||
case Builtins::kStringPrototypeSubstring:
|
||||
case Builtins::kStringPrototypeSup:
|
||||
case Builtins::kStringPrototypeToString:
|
||||
#ifndef V8_INTL_SUPPORT
|
||||
case Builtins::kStringPrototypeToLowerCase:
|
||||
|
@ -17,11 +17,6 @@ var searchSymbol = utils.ImportNow("search_symbol");
|
||||
|
||||
//-------------------------------------------------------------------
|
||||
|
||||
// ES#sec-createhtml
|
||||
function HtmlEscape(str) {
|
||||
return %RegExpInternalReplace(/"/g, TO_STRING(str), """);
|
||||
}
|
||||
|
||||
// Set up the non-enumerable functions on the String prototype object.
|
||||
DEFINE_METHODS(
|
||||
GlobalString.prototype,
|
||||
@ -61,87 +56,6 @@ DEFINE_METHODS(
|
||||
var regexp = %RegExpCreate(pattern);
|
||||
return %_Call(regexp[searchSymbol], regexp, subject);
|
||||
}
|
||||
|
||||
/* ES#sec-string.prototype.anchor */
|
||||
anchor(name) {
|
||||
CHECK_OBJECT_COERCIBLE(this, "String.prototype.anchor");
|
||||
return "<a name=\"" + HtmlEscape(name) + "\">" + TO_STRING(this) +
|
||||
"</a>";
|
||||
}
|
||||
|
||||
/* ES#sec-string.prototype.big */
|
||||
big() {
|
||||
CHECK_OBJECT_COERCIBLE(this, "String.prototype.big");
|
||||
return "<big>" + TO_STRING(this) + "</big>";
|
||||
}
|
||||
|
||||
/* ES#sec-string.prototype.blink */
|
||||
blink() {
|
||||
CHECK_OBJECT_COERCIBLE(this, "String.prototype.blink");
|
||||
return "<blink>" + TO_STRING(this) + "</blink>";
|
||||
}
|
||||
|
||||
/* ES#sec-string.prototype.bold */
|
||||
bold() {
|
||||
CHECK_OBJECT_COERCIBLE(this, "String.prototype.bold");
|
||||
return "<b>" + TO_STRING(this) + "</b>";
|
||||
}
|
||||
|
||||
/* ES#sec-string.prototype.fixed */
|
||||
fixed() {
|
||||
CHECK_OBJECT_COERCIBLE(this, "String.prototype.fixed");
|
||||
return "<tt>" + TO_STRING(this) + "</tt>";
|
||||
}
|
||||
|
||||
/* ES#sec-string.prototype.fontcolor */
|
||||
fontcolor(color) {
|
||||
CHECK_OBJECT_COERCIBLE(this, "String.prototype.fontcolor");
|
||||
return "<font color=\"" + HtmlEscape(color) + "\">" + TO_STRING(this) +
|
||||
"</font>";
|
||||
}
|
||||
|
||||
/* ES#sec-string.prototype.fontsize */
|
||||
fontsize(size) {
|
||||
CHECK_OBJECT_COERCIBLE(this, "String.prototype.fontsize");
|
||||
return "<font size=\"" + HtmlEscape(size) + "\">" + TO_STRING(this) +
|
||||
"</font>";
|
||||
}
|
||||
|
||||
/* ES#sec-string.prototype.italics */
|
||||
italics() {
|
||||
CHECK_OBJECT_COERCIBLE(this, "String.prototype.italics");
|
||||
return "<i>" + TO_STRING(this) + "</i>";
|
||||
}
|
||||
|
||||
/* ES#sec-string.prototype.link */
|
||||
link(s) {
|
||||
CHECK_OBJECT_COERCIBLE(this, "String.prototype.link");
|
||||
return "<a href=\"" + HtmlEscape(s) + "\">" + TO_STRING(this) + "</a>";
|
||||
}
|
||||
|
||||
/* ES#sec-string.prototype.small */
|
||||
small() {
|
||||
CHECK_OBJECT_COERCIBLE(this, "String.prototype.small");
|
||||
return "<small>" + TO_STRING(this) + "</small>";
|
||||
}
|
||||
|
||||
/* ES#sec-string.prototype.strike */
|
||||
strike() {
|
||||
CHECK_OBJECT_COERCIBLE(this, "String.prototype.strike");
|
||||
return "<strike>" + TO_STRING(this) + "</strike>";
|
||||
}
|
||||
|
||||
/* ES#sec-string.prototype.sub */
|
||||
sub() {
|
||||
CHECK_OBJECT_COERCIBLE(this, "String.prototype.sub");
|
||||
return "<sub>" + TO_STRING(this) + "</sub>";
|
||||
}
|
||||
|
||||
/* ES#sec-string.prototype.sup */
|
||||
sup() {
|
||||
CHECK_OBJECT_COERCIBLE(this, "String.prototype.sup");
|
||||
return "<sup>" + TO_STRING(this) + "</sup>";
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -8,7 +8,8 @@
|
||||
assertEquals('_'.anchor('b'), '<a name="b">_</a>');
|
||||
assertEquals('<'.anchor('<'), '<a name="<"><</a>');
|
||||
assertEquals('_'.anchor(0x2A), '<a name="42">_</a>');
|
||||
assertEquals('_'.anchor('\x22'), '<a name=""">_</a>');
|
||||
assertEquals('_'.anchor('\x22\x22'), '<a name="""">_</a>');
|
||||
assertEquals('_'.anchor(), '<a name="undefined">_</a>');
|
||||
assertEquals(String.prototype.anchor.call(0x2A, 0x2A), '<a name="42">42</a>');
|
||||
assertThrows(function() {
|
||||
String.prototype.anchor.call(undefined);
|
||||
|
Loading…
Reference in New Issue
Block a user