Bug 987556 Part 1 Add JS::SourceBufferHolder for passing source script data. r=luke

This commit is contained in:
Ben Kelly 2014-04-25 10:11:56 -04:00
parent 6bcbfcfc7d
commit 85c3a02ab2

View File

@ -877,6 +877,91 @@ class AutoIdRooter : private AutoGCRooter
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
// Container class for passing in script source buffers to the JS engine. This
// not only groups the buffer and length values, it also provides a way to
// optionally pass ownership of the buffer to the JS engine without copying.
// Rules for use:
//
// 1) The data array must be allocated with js_malloc() or js_realloc() if
// ownership is being granted to the SourceBufferHolder.
// 2) If ownership is not given to the SourceBufferHolder, then the memory
// must be kept alive until the JS compilation is complete.
// 3) Any code calling SourceBufferHolder::take() must guarantee to keep the
// memory alive until JS compilation completes. Normally only the JS
// engine should be calling take().
//
// Example use:
//
// size_t length = 512;
// jschar* chars = static_cast<jschar*>(js_malloc(sizeof(jschar) * length));
// JS::SourceBufferHolder srcBuf(chars, length, JS::SourceBufferHolder::GiveOwnership);
// JS::Compile(cx, obj, options, srcBuf);
//
class MOZ_STACK_CLASS SourceBufferHolder MOZ_FINAL
{
public:
enum Ownership {
NoOwnership,
GiveOwnership
};
SourceBufferHolder(const jschar *data, size_t dataLength, Ownership ownership)
: data_(data),
length_(dataLength),
ownsChars_(ownership == GiveOwnership)
{
// Ensure that null buffers properly return an unowned, empty,
// null-terminated string.
static const jschar NullChar_ = 0;
if (!get()) {
data_ = &NullChar_;
length_ = 0;
ownsChars_ = false;
}
}
~SourceBufferHolder() {
if (ownsChars_)
js_free(const_cast<jschar *>(data_));
}
// Access the underlying source buffer without affecting ownership.
const jschar *get() const { return data_; }
// Length of the source buffer in jschars (not bytes)
size_t length() const { return length_; }
// Returns true if the SourceBufferHolder owns the buffer and will free
// it upon destruction. If true, it is legal to call take().
bool ownsChars() const { return ownsChars_; }
// Retrieve and take ownership of the underlying data buffer. The caller
// is now responsible for calling js_free() on the returned value, *but only
// after JS script compilation has completed*.
//
// After the buffer has been taken the SourceBufferHolder functions as if
// it had been constructed on an unowned buffer; get() and length() still
// work. In order for this to be safe the taken buffer must be kept alive
// until after JS script compilation completes as noted above.
//
// Note, it's the caller's responsibility to check ownsChars() before taking
// the buffer. Taking and then free'ing an unowned buffer will have dire
// consequences.
jschar *take() {
JS_ASSERT(ownsChars_);
ownsChars_ = false;
return const_cast<jschar *>(data_);
}
private:
SourceBufferHolder(SourceBufferHolder &) MOZ_DELETE;
SourceBufferHolder &operator=(SourceBufferHolder &) MOZ_DELETE;
const jschar *data_;
size_t length_;
bool ownsChars_;
};
} /* namespace JS */
/************************************************************************/