bool JSCompartment::wrap(JSContext *cx, JSString **strp) { JS_ASSERT(!cx->runtime()->isAtomsCompartment(this)); JS_ASSERT(cx->compartment() == this); /* If the string is already in this compartment, we are done. */ JSString *str = *strp; if (str->zone() == zone()) return true; /* If the string is an atom, we don't have to copy. */ if (str->isAtom()) { JS_ASSERT(cx->runtime()->isAtomsZone(str->zone())); return true; } /* Check the cache. */ RootedValue key(cx, StringValue(str)); if (WrapperMap::Ptr p = crossCompartmentWrappers.lookup(key)) { *strp = p->value().get().toString(); return true; } /* * No dice. Make a copy, and cache it. Directly allocate the copy in the * destination compartment, rather than first flattening it (and possibly * allocating in source compartment), because we don't know whether the * flattening will pay off later. */ JSString *copy; if (str->hasPureChars()) { copy = js_NewStringCopyN<CanGC>(cx, str->pureChars(), str->length()); } else { ScopedJSFreePtr<jschar> copiedChars; if (!str->copyNonPureCharsZ(cx, copiedChars)) return false; copy = js_NewString<CanGC>(cx, copiedChars.forget(), str->length()); } if (!copy) return false; if (!putWrapper(cx, key, StringValue(copy))) return false; *strp = copy; return true; }