Bug 928508 - Change String.prototype.@@iterator to iterate over code points. r=jorendorff.
This commit is contained in:
@@ -560,7 +560,7 @@ struct JSClass {
|
|||||||
// with the following flags. Failure to use JSCLASS_GLOBAL_FLAGS was
|
// with the following flags. Failure to use JSCLASS_GLOBAL_FLAGS was
|
||||||
// previously allowed, but is now an ES5 violation and thus unsupported.
|
// previously allowed, but is now an ES5 violation and thus unsupported.
|
||||||
//
|
//
|
||||||
#define JSCLASS_GLOBAL_SLOT_COUNT (3 + JSProto_LIMIT * 3 + 27)
|
#define JSCLASS_GLOBAL_SLOT_COUNT (3 + JSProto_LIMIT * 3 + 28)
|
||||||
#define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n) \
|
#define JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(n) \
|
||||||
(JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + (n)))
|
(JSCLASS_IS_GLOBAL | JSCLASS_HAS_RESERVED_SLOTS(JSCLASS_GLOBAL_SLOT_COUNT + (n)))
|
||||||
#define JSCLASS_GLOBAL_FLAGS \
|
#define JSCLASS_GLOBAL_FLAGS \
|
||||||
|
|||||||
@@ -40,6 +40,51 @@ function String_repeat(count) {
|
|||||||
return T;
|
return T;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define STRING_ITERATOR_SLOT_ITERATED_OBJECT 0
|
||||||
|
#define STRING_ITERATOR_SLOT_NEXT_INDEX 1
|
||||||
|
|
||||||
|
// ES6 draft specification, section 21.1.3.27, version 2013-09-27.
|
||||||
|
function String_iterator() {
|
||||||
|
CheckObjectCoercible(this);
|
||||||
|
var S = ToString(this);
|
||||||
|
var iterator = NewStringIterator();
|
||||||
|
UnsafeSetReservedSlot(iterator, STRING_ITERATOR_SLOT_ITERATED_OBJECT, S);
|
||||||
|
UnsafeSetReservedSlot(iterator, STRING_ITERATOR_SLOT_NEXT_INDEX, 0);
|
||||||
|
return iterator;
|
||||||
|
}
|
||||||
|
|
||||||
|
function StringIteratorIdentity() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
function StringIteratorNext() {
|
||||||
|
// FIXME: Cross-compartment wrapper StringIterator objects should pass this test. Bug 924059.
|
||||||
|
if (!IsObject(this) || !IsStringIterator(this))
|
||||||
|
ThrowError(JSMSG_INCOMPATIBLE_METHOD, "StringIterator", "next", ToString(this));
|
||||||
|
|
||||||
|
var S = UnsafeGetReservedSlot(this, STRING_ITERATOR_SLOT_ITERATED_OBJECT);
|
||||||
|
var index = UnsafeGetReservedSlot(this, STRING_ITERATOR_SLOT_NEXT_INDEX);
|
||||||
|
var size = S.length;
|
||||||
|
|
||||||
|
if (index >= size) {
|
||||||
|
return { value: undefined, done: true };
|
||||||
|
}
|
||||||
|
|
||||||
|
var charCount = 1;
|
||||||
|
var first = callFunction(std_String_charCodeAt, S, index);
|
||||||
|
if (first >= 0xD800 && first <= 0xDBFF && index + 1 < size) {
|
||||||
|
var second = callFunction(std_String_charCodeAt, S, index + 1);
|
||||||
|
if (second >= 0xDC00 && second <= 0xDFFF) {
|
||||||
|
charCount = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UnsafeSetReservedSlot(this, STRING_ITERATOR_SLOT_NEXT_INDEX, index + charCount);
|
||||||
|
var value = callFunction(std_String_substring, S, index, index + charCount);
|
||||||
|
|
||||||
|
return { value: value, done: false };
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compare this String against that String, using the locale and collation
|
* Compare this String against that String, using the locale and collation
|
||||||
* options provided.
|
* options provided.
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ var std_Object_getOwnPropertyNames = Object.getOwnPropertyNames;
|
|||||||
var std_Object_hasOwnProperty = Object.prototype.hasOwnProperty;
|
var std_Object_hasOwnProperty = Object.prototype.hasOwnProperty;
|
||||||
var std_RegExp_test = RegExp.prototype.test;
|
var std_RegExp_test = RegExp.prototype.test;
|
||||||
var Std_String = String;
|
var Std_String = String;
|
||||||
|
var std_String_charCodeAt = String.prototype.charCodeAt;
|
||||||
var std_String_indexOf = String.prototype.indexOf;
|
var std_String_indexOf = String.prototype.indexOf;
|
||||||
var std_String_lastIndexOf = String.prototype.lastIndexOf;
|
var std_String_lastIndexOf = String.prototype.lastIndexOf;
|
||||||
var std_String_match = String.prototype.match;
|
var std_String_match = String.prototype.match;
|
||||||
|
|||||||
24
js/src/jit-test/lib/string.js
Normal file
24
js/src/jit-test/lib/string.js
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
|
||||||
|
if (typeof isHighSurrogate === 'undefined') {
|
||||||
|
var isHighSurrogate = function isHighSurrogate(s) {
|
||||||
|
var c = s.charCodeAt(0);
|
||||||
|
return c >= 0xD800 && c <= 0xDBFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof isLowSurrogate === 'undefined') {
|
||||||
|
var isLowSurrogate = function isLowSurrogate(s) {
|
||||||
|
var c = s.charCodeAt(0);
|
||||||
|
return c >= 0xDC00 && c <= 0xDFFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof isSurrogatePair === 'undefined') {
|
||||||
|
var isSurrogatePair = function isSurrogatePair(s) {
|
||||||
|
return s.length == 2 && isHighSurrogate(s[0]) && isLowSurrogate(s[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,14 +2,24 @@
|
|||||||
|
|
||||||
load(libdir + "asserts.js");
|
load(libdir + "asserts.js");
|
||||||
load(libdir + "iteration.js");
|
load(libdir + "iteration.js");
|
||||||
|
load(libdir + "string.js");
|
||||||
|
|
||||||
function test(obj) {
|
function test(obj) {
|
||||||
var it = String.prototype[std_iterator].call(obj);
|
var it = String.prototype[std_iterator].call(obj);
|
||||||
for (var i = 0; i < (obj.length >>> 0); i++)
|
var s = String(obj);
|
||||||
assertIteratorNext(it, obj[i]);
|
for (var i = 0, length = s.length; i < length;) {
|
||||||
|
var r = s[i++];
|
||||||
|
if (isHighSurrogate(r) && i < length && isLowSurrogate(s[i])) {
|
||||||
|
r += s[i++];
|
||||||
|
}
|
||||||
|
assertIteratorNext(it, r);
|
||||||
|
}
|
||||||
assertIteratorDone(it, undefined);
|
assertIteratorDone(it, undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
test({length: 0});
|
test({toString: () => ""});
|
||||||
test(Object.create(['x', 'y', 'z']));
|
test({toString: () => "xyz"});
|
||||||
test(Object.create({length: 2, 0: 'x', 1: 'y'}));
|
test({toString: () => "\ud808\udf45"});
|
||||||
|
test({valueOf: () => ""});
|
||||||
|
test({valueOf: () => "xyz"});
|
||||||
|
test({valueOf: () => "\ud808\udf45"});
|
||||||
|
|||||||
76
js/src/jit-test/tests/for-of/string-iterator-surfaces.js
Normal file
76
js/src/jit-test/tests/for-of/string-iterator-surfaces.js
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
// String.prototype[@@iterator] and StringIterator.prototype surface tests
|
||||||
|
|
||||||
|
load(libdir + "array-compare.js");
|
||||||
|
load(libdir + "asserts.js");
|
||||||
|
load(libdir + "iteration.js");
|
||||||
|
|
||||||
|
function assertDataDescriptor(actual, expected) {
|
||||||
|
assertEq(actual.value, expected.value);
|
||||||
|
assertEq(actual.writable, expected.writable);
|
||||||
|
assertEq(actual.enumerable, expected.enumerable);
|
||||||
|
assertEq(actual.configurable, expected.configurable);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isConstructor(o) {
|
||||||
|
try {
|
||||||
|
new (new Proxy(o, {construct: () => ({})}));
|
||||||
|
return true;
|
||||||
|
} catch(e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function assertBuiltinFunction(o, name, arity) {
|
||||||
|
var fn = o[name];
|
||||||
|
assertDataDescriptor(Object.getOwnPropertyDescriptor(o, name), {
|
||||||
|
value: fn,
|
||||||
|
writable: true,
|
||||||
|
enumerable: false,
|
||||||
|
configurable: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
assertEq(typeof fn, "function");
|
||||||
|
assertEq(Object.getPrototypeOf(fn), Function.prototype);
|
||||||
|
// FIXME: Proxy should only have [[Construct]] if target has [[Construct]] (bug 929467)
|
||||||
|
// assertEq(isConstructor(fn), false);
|
||||||
|
|
||||||
|
arraysEqual(Object.getOwnPropertyNames(fn).sort(), ["length", "name", "arguments", "caller"].sort());
|
||||||
|
|
||||||
|
// Also test "name", "arguments" and "caller" in addition to "length"?
|
||||||
|
assertDataDescriptor(Object.getOwnPropertyDescriptor(fn, "length"), {
|
||||||
|
value: arity,
|
||||||
|
writable: false,
|
||||||
|
enumerable: false,
|
||||||
|
configurable: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// String.prototype[@@iterator] is a built-in function
|
||||||
|
assertBuiltinFunction(String.prototype, std_iterator, 0);
|
||||||
|
|
||||||
|
// Test StringIterator.prototype surface
|
||||||
|
var iter = ""[std_iterator]();
|
||||||
|
var iterProto = Object.getPrototypeOf(iter);
|
||||||
|
|
||||||
|
// StringIterator.prototype inherits from Object.prototype
|
||||||
|
assertEq(Object.getPrototypeOf(iterProto), Object.prototype);
|
||||||
|
|
||||||
|
// Own properties for StringIterator.prototype: "next" and @@iterator
|
||||||
|
arraysEqual(Object.getOwnPropertyNames(iterProto).sort(), ["next", std_iterator].sort());
|
||||||
|
|
||||||
|
// StringIterator.prototype[@@iterator] is a built-in function
|
||||||
|
assertBuiltinFunction(iterProto, std_iterator, 0);
|
||||||
|
|
||||||
|
// StringIterator.prototype.next is a built-in function
|
||||||
|
assertBuiltinFunction(iterProto, "next", 0);
|
||||||
|
|
||||||
|
// StringIterator.prototype[@@iterator] is generic and returns |this|
|
||||||
|
for (var v of [void 0, null, true, false, "", 0, 1, {}, [], iter, iterProto]) {
|
||||||
|
assertEq(iterProto[std_iterator].call(v), v);
|
||||||
|
}
|
||||||
|
|
||||||
|
// StringIterator.prototype.next is not generic
|
||||||
|
for (var v of [void 0, null, true, false, "", 0, 1, {}, [], iterProto]) {
|
||||||
|
assertThrowsInstanceOf(() => iterProto.next.call(v), TypeError);
|
||||||
|
}
|
||||||
@@ -1,26 +1,47 @@
|
|||||||
// for-of works on strings and String objects.
|
// for-of works on strings and String objects.
|
||||||
|
|
||||||
function test(s) {
|
load(libdir + "string.js");
|
||||||
|
|
||||||
|
function test(s, expectedCodePoints) {
|
||||||
var copy = '';
|
var copy = '';
|
||||||
|
var codepoints = 0;
|
||||||
|
var singleHighSurrogate = false;
|
||||||
for (var v of s) {
|
for (var v of s) {
|
||||||
assertEq(typeof v, 'string');
|
assertEq(typeof v, 'string');
|
||||||
assertEq(v.length, 1);
|
assertEq(v.length, isSurrogatePair(v) ? 2 : 1);
|
||||||
|
assertEq(false, singleHighSurrogate && isLowSurrogate(v));
|
||||||
copy += v;
|
copy += v;
|
||||||
|
codepoints += 1;
|
||||||
|
singleHighSurrogate = !isSurrogatePair(v) && isHighSurrogate(v);
|
||||||
}
|
}
|
||||||
assertEq(copy, String(s));
|
assertEq(copy, String(s));
|
||||||
|
assertEq(codepoints, expectedCodePoints);
|
||||||
}
|
}
|
||||||
|
|
||||||
test('');
|
test('', 0);
|
||||||
test('abc');
|
test('abc', 3);
|
||||||
test('a \0 \ufffe \ufeff');
|
test('a \0 \ufffe \ufeff', 7);
|
||||||
|
|
||||||
// Non-BMP characters are generally passed to JS in UTF-16, as surrogate pairs.
|
// Non-BMP characters are generally passed to JS in UTF-16, as surrogate pairs.
|
||||||
// ES requires that such pairs be treated as two 16-bit "characters" in pretty
|
// ES6 requires that such pairs be treated as a single code point in for-of.
|
||||||
// much every circumstance, including string indexing. We anticipate the same
|
test('\ud808\udf45', 1);
|
||||||
// requirement will be imposed here, though it's not a sure thing.
|
|
||||||
test('\ud808\udf45');
|
|
||||||
|
|
||||||
test(new String(''));
|
// Also test invalid surrogate pairs:
|
||||||
test(new String('abc'));
|
// (1) High surrogate not followed by low surrogate
|
||||||
test(new String('a \0 \ufffe \ufeff'));
|
test('\ud808', 1);
|
||||||
test(new String('\ud808\udf45'));
|
test('\ud808\u0000', 2);
|
||||||
|
// (2) Low surrogate not preceded by high surrogate
|
||||||
|
test('\udf45', 1);
|
||||||
|
test('\u0000\udf45', 2);
|
||||||
|
// (3) Low surrogate followed by high surrogate
|
||||||
|
test('\udf45\ud808', 2);
|
||||||
|
|
||||||
|
test(new String(''), 0);
|
||||||
|
test(new String('abc'), 3);
|
||||||
|
test(new String('a \0 \ufffe \ufeff'), 7);
|
||||||
|
test(new String('\ud808\udf45'), 1);
|
||||||
|
test(new String('\ud808'), 1);
|
||||||
|
test(new String('\ud808\u0000'), 2);
|
||||||
|
test(new String('\udf45'), 1);
|
||||||
|
test(new String('\u0000\udf45'), 2);
|
||||||
|
test(new String('\udf45\ud808'), 2);
|
||||||
|
|||||||
@@ -868,6 +868,45 @@ static const JSFunctionSpec array_iterator_methods[] = {
|
|||||||
JS_FS_END
|
JS_FS_END
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const Class StringIteratorPrototypeClass = {
|
||||||
|
"String Iterator",
|
||||||
|
JSCLASS_IMPLEMENTS_BARRIERS,
|
||||||
|
JS_PropertyStub, /* addProperty */
|
||||||
|
JS_DeletePropertyStub, /* delProperty */
|
||||||
|
JS_PropertyStub, /* getProperty */
|
||||||
|
JS_StrictPropertyStub, /* setProperty */
|
||||||
|
JS_EnumerateStub,
|
||||||
|
JS_ResolveStub,
|
||||||
|
JS_ConvertStub,
|
||||||
|
nullptr /* finalize */
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
StringIteratorSlotIteratedObject,
|
||||||
|
StringIteratorSlotNextIndex,
|
||||||
|
StringIteratorSlotCount
|
||||||
|
};
|
||||||
|
|
||||||
|
const Class StringIteratorObject::class_ = {
|
||||||
|
"String Iterator",
|
||||||
|
JSCLASS_IMPLEMENTS_BARRIERS |
|
||||||
|
JSCLASS_HAS_RESERVED_SLOTS(StringIteratorSlotCount),
|
||||||
|
JS_PropertyStub, /* addProperty */
|
||||||
|
JS_DeletePropertyStub, /* delProperty */
|
||||||
|
JS_PropertyStub, /* getProperty */
|
||||||
|
JS_StrictPropertyStub, /* setProperty */
|
||||||
|
JS_EnumerateStub,
|
||||||
|
JS_ResolveStub,
|
||||||
|
JS_ConvertStub,
|
||||||
|
nullptr /* finalize */
|
||||||
|
};
|
||||||
|
|
||||||
|
static const JSFunctionSpec string_iterator_methods[] = {
|
||||||
|
JS_SELF_HOSTED_FN("@@iterator", "StringIteratorIdentity", 0, 0),
|
||||||
|
JS_SELF_HOSTED_FN("next", "StringIteratorNext", 0, 0),
|
||||||
|
JS_FS_END
|
||||||
|
};
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
CloseLegacyGenerator(JSContext *cx, HandleObject genobj);
|
CloseLegacyGenerator(JSContext *cx, HandleObject genobj);
|
||||||
|
|
||||||
@@ -1853,6 +1892,14 @@ GlobalObject::initIteratorClasses(JSContext *cx, Handle<GlobalObject *> global)
|
|||||||
global->setReservedSlot(ARRAY_ITERATOR_PROTO, ObjectValue(*proto));
|
global->setReservedSlot(ARRAY_ITERATOR_PROTO, ObjectValue(*proto));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (global->getSlot(STRING_ITERATOR_PROTO).isUndefined()) {
|
||||||
|
const Class *cls = &StringIteratorPrototypeClass;
|
||||||
|
proto = global->createBlankPrototype(cx, cls);
|
||||||
|
if (!proto || !DefinePropertiesAndBrand(cx, proto, nullptr, string_iterator_methods))
|
||||||
|
return false;
|
||||||
|
global->setReservedSlot(STRING_ITERATOR_PROTO, ObjectValue(*proto));
|
||||||
|
}
|
||||||
|
|
||||||
if (global->getSlot(LEGACY_GENERATOR_OBJECT_PROTO).isUndefined()) {
|
if (global->getSlot(LEGACY_GENERATOR_OBJECT_PROTO).isUndefined()) {
|
||||||
proto = NewObjectWithObjectPrototype(cx, global);
|
proto = NewObjectWithObjectPrototype(cx, global);
|
||||||
if (!proto || !DefinePropertiesAndBrand(cx, proto, nullptr, legacy_generator_methods))
|
if (!proto || !DefinePropertiesAndBrand(cx, proto, nullptr, legacy_generator_methods))
|
||||||
|
|||||||
@@ -139,6 +139,12 @@ class ArrayIteratorObject : public JSObject
|
|||||||
static const Class class_;
|
static const Class class_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class StringIteratorObject : public JSObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static const Class class_;
|
||||||
|
};
|
||||||
|
|
||||||
bool
|
bool
|
||||||
VectorToIdArray(JSContext *cx, AutoIdVector &props, JSIdArray **idap);
|
VectorToIdArray(JSContext *cx, AutoIdVector &props, JSIdArray **idap);
|
||||||
|
|
||||||
|
|||||||
@@ -3658,7 +3658,7 @@ static const JSFunctionSpec string_methods[] = {
|
|||||||
JS_FN("sup", str_sup, 0,0),
|
JS_FN("sup", str_sup, 0,0),
|
||||||
JS_FN("sub", str_sub, 0,0),
|
JS_FN("sub", str_sub, 0,0),
|
||||||
#endif
|
#endif
|
||||||
JS_SELF_HOSTED_FN("@@iterator", "ArrayValues", 0,0),
|
JS_SELF_HOSTED_FN("@@iterator", "String_iterator", 0,0),
|
||||||
JS_FS_END
|
JS_FS_END
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -96,7 +96,8 @@ class GlobalObject : public JSObject
|
|||||||
|
|
||||||
/* One-off properties stored after slots for built-ins. */
|
/* One-off properties stored after slots for built-ins. */
|
||||||
static const unsigned ARRAY_ITERATOR_PROTO = FROM_BUFFER_UINT8CLAMPED + 1;
|
static const unsigned ARRAY_ITERATOR_PROTO = FROM_BUFFER_UINT8CLAMPED + 1;
|
||||||
static const unsigned LEGACY_GENERATOR_OBJECT_PROTO = ARRAY_ITERATOR_PROTO + 1;
|
static const unsigned STRING_ITERATOR_PROTO = ARRAY_ITERATOR_PROTO + 1;
|
||||||
|
static const unsigned LEGACY_GENERATOR_OBJECT_PROTO = STRING_ITERATOR_PROTO + 1;
|
||||||
static const unsigned STAR_GENERATOR_OBJECT_PROTO = LEGACY_GENERATOR_OBJECT_PROTO + 1;
|
static const unsigned STAR_GENERATOR_OBJECT_PROTO = LEGACY_GENERATOR_OBJECT_PROTO + 1;
|
||||||
static const unsigned MAP_ITERATOR_PROTO = STAR_GENERATOR_OBJECT_PROTO + 1;
|
static const unsigned MAP_ITERATOR_PROTO = STAR_GENERATOR_OBJECT_PROTO + 1;
|
||||||
static const unsigned SET_ITERATOR_PROTO = MAP_ITERATOR_PROTO + 1;
|
static const unsigned SET_ITERATOR_PROTO = MAP_ITERATOR_PROTO + 1;
|
||||||
@@ -466,6 +467,10 @@ class GlobalObject : public JSObject
|
|||||||
return getOrCreateObject(cx, ARRAY_ITERATOR_PROTO, initIteratorClasses);
|
return getOrCreateObject(cx, ARRAY_ITERATOR_PROTO, initIteratorClasses);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JSObject *getOrCreateStringIteratorPrototype(JSContext *cx) {
|
||||||
|
return getOrCreateObject(cx, STRING_ITERATOR_PROTO, initIteratorClasses);
|
||||||
|
}
|
||||||
|
|
||||||
JSObject *getOrCreateLegacyGeneratorObjectPrototype(JSContext *cx) {
|
JSObject *getOrCreateLegacyGeneratorObjectPrototype(JSContext *cx) {
|
||||||
return getOrCreateObject(cx, LEGACY_GENERATOR_OBJECT_PROTO, initIteratorClasses);
|
return getOrCreateObject(cx, LEGACY_GENERATOR_OBJECT_PROTO, initIteratorClasses);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -505,6 +505,35 @@ intrinsic_IsArrayIterator(JSContext *cx, unsigned argc, Value *vp)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
intrinsic_NewStringIterator(JSContext *cx, unsigned argc, Value *vp)
|
||||||
|
{
|
||||||
|
CallArgs args = CallArgsFromVp(argc, vp);
|
||||||
|
JS_ASSERT(args.length() == 0);
|
||||||
|
|
||||||
|
RootedObject proto(cx, cx->global()->getOrCreateStringIteratorPrototype(cx));
|
||||||
|
if (!proto)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
JSObject *obj = NewObjectWithGivenProto(cx, &StringIteratorObject::class_, proto, cx->global());
|
||||||
|
if (!obj)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
args.rval().setObject(*obj);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
intrinsic_IsStringIterator(JSContext *cx, unsigned argc, Value *vp)
|
||||||
|
{
|
||||||
|
CallArgs args = CallArgsFromVp(argc, vp);
|
||||||
|
JS_ASSERT(args.length() == 1);
|
||||||
|
JS_ASSERT(args[0].isObject());
|
||||||
|
|
||||||
|
args.rval().setBoolean(args[0].toObject().is<StringIteratorObject>());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ParallelTestsShouldPass(): Returns false if we are running in a
|
* ParallelTestsShouldPass(): Returns false if we are running in a
|
||||||
* mode (such as --ion-eager) that is known to cause additional
|
* mode (such as --ion-eager) that is known to cause additional
|
||||||
@@ -588,6 +617,9 @@ static const JSFunctionSpec intrinsic_functions[] = {
|
|||||||
JS_FN("NewArrayIterator", intrinsic_NewArrayIterator, 0,0),
|
JS_FN("NewArrayIterator", intrinsic_NewArrayIterator, 0,0),
|
||||||
JS_FN("IsArrayIterator", intrinsic_IsArrayIterator, 1,0),
|
JS_FN("IsArrayIterator", intrinsic_IsArrayIterator, 1,0),
|
||||||
|
|
||||||
|
JS_FN("NewStringIterator", intrinsic_NewStringIterator, 0,0),
|
||||||
|
JS_FN("IsStringIterator", intrinsic_IsStringIterator, 1,0),
|
||||||
|
|
||||||
JS_FN("ForkJoin", intrinsic_ForkJoin, 2,0),
|
JS_FN("ForkJoin", intrinsic_ForkJoin, 2,0),
|
||||||
JS_FN("ForkJoinSlices", intrinsic_ForkJoinSlices, 0,0),
|
JS_FN("ForkJoinSlices", intrinsic_ForkJoinSlices, 0,0),
|
||||||
JS_FN("NewParallelArray", intrinsic_NewParallelArray, 3,0),
|
JS_FN("NewParallelArray", intrinsic_NewParallelArray, 3,0),
|
||||||
|
|||||||
Reference in New Issue
Block a user