Landing for miket@chromium.org: Add an optional source length field to the Extension constructor.

Original code review: http://codereview.chromium.org/7889046/
Review URL: http://codereview.chromium.org/7978028

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9365 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 6c8472bd
......@@ -1171,7 +1171,8 @@ class String : public Primitive {
* Get the ExternalAsciiStringResource for an external ASCII string.
* Returns NULL if IsExternalAscii() doesn't return true.
*/
V8EXPORT ExternalAsciiStringResource* GetExternalAsciiStringResource() const;
V8EXPORT const ExternalAsciiStringResource* GetExternalAsciiStringResource()
const;
static inline String* Cast(v8::Value* obj);
......@@ -2451,24 +2452,42 @@ class V8EXPORT TypeSwitch : public Data {
// --- Extensions ---
class ExternalAsciiStringResourceImpl
: public String::ExternalAsciiStringResource {
public:
ExternalAsciiStringResourceImpl() : data_(0), length_(0) {}
ExternalAsciiStringResourceImpl(const char* data, size_t length)
: data_(data), length_(length) {}
const char* data() const { return data_; }
size_t length() const { return length_; }
private:
const char* data_;
size_t length_;
};
/**
* Ignore
*/
class V8EXPORT Extension { // NOLINT
public:
// Note that the strings passed into this constructor must live as long
// as the Extension itself.
Extension(const char* name,
const char* source = 0,
int dep_count = 0,
const char** deps = 0);
const char** deps = 0,
int source_length = -1);
virtual ~Extension() { }
virtual v8::Handle<v8::FunctionTemplate>
GetNativeFunction(v8::Handle<v8::String> name) {
return v8::Handle<v8::FunctionTemplate>();
}
const char* name() { return name_; }
const char* source() { return source_; }
const char* name() const { return name_; }
size_t source_length() const { return source_length_; }
const String::ExternalAsciiStringResource* source() const {
return &source_; }
int dependency_count() { return dep_count_; }
const char** dependencies() { return deps_; }
void set_auto_enable(bool value) { auto_enable_ = value; }
......@@ -2476,7 +2495,8 @@ class V8EXPORT Extension { // NOLINT
private:
const char* name_;
const char* source_;
size_t source_length_; // expected to initialize before source_
ExternalAsciiStringResourceImpl source_;
int dep_count_;
const char** deps_;
bool auto_enable_;
......
......@@ -501,9 +501,12 @@ void RegisterExtension(Extension* that) {
Extension::Extension(const char* name,
const char* source,
int dep_count,
const char** deps)
const char** deps,
int source_length)
: name_(name),
source_(source),
source_length_(source_length >= 0 ?
source_length : (source ? strlen(source) : 0)),
source_(source, source_length_),
dep_count_(dep_count),
deps_(deps),
auto_enable_(false) { }
......@@ -3789,10 +3792,11 @@ bool v8::String::IsExternalAscii() const {
void v8::String::VerifyExternalStringResource(
v8::String::ExternalStringResource* value) const {
i::Handle<i::String> str = Utils::OpenHandle(this);
v8::String::ExternalStringResource* expected;
const v8::String::ExternalStringResource* expected;
if (i::StringShape(*str).IsExternalTwoByte()) {
void* resource = i::Handle<i::ExternalTwoByteString>::cast(str)->resource();
expected = reinterpret_cast<ExternalStringResource*>(resource);
const void* resource =
i::Handle<i::ExternalTwoByteString>::cast(str)->resource();
expected = reinterpret_cast<const ExternalStringResource*>(resource);
} else {
expected = NULL;
}
......@@ -3800,7 +3804,7 @@ void v8::String::VerifyExternalStringResource(
}
v8::String::ExternalAsciiStringResource*
const v8::String::ExternalAsciiStringResource*
v8::String::GetExternalAsciiStringResource() const {
i::Handle<i::String> str = Utils::OpenHandle(this);
if (IsDeadCheck(str->GetIsolate(),
......@@ -3808,8 +3812,9 @@ v8::String::ExternalAsciiStringResource*
return NULL;
}
if (i::StringShape(*str).IsExternalAscii()) {
void* resource = i::Handle<i::ExternalAsciiString>::cast(str)->resource();
return reinterpret_cast<ExternalAsciiStringResource*>(resource);
const void* resource =
i::Handle<i::ExternalAsciiString>::cast(str)->resource();
return reinterpret_cast<const ExternalAsciiStringResource*>(resource);
} else {
return NULL;
}
......
......@@ -1940,14 +1940,13 @@ bool Genesis::InstallExtension(v8::RegisteredExtension* current) {
if (!InstallExtension(extension->dependencies()[i])) return false;
}
Isolate* isolate = Isolate::Current();
Vector<const char> source = CStrVector(extension->source());
Handle<String> source_code = isolate->factory()->NewStringFromAscii(source);
bool result = CompileScriptCached(CStrVector(extension->name()),
source_code,
isolate->bootstrapper()->extensions_cache(),
extension,
Handle<Context>(isolate->context()),
false);
bool result = CompileScriptCached(
CStrVector(extension->name()),
isolate->factory()->NewExternalStringFromAscii(extension->source()),
isolate->bootstrapper()->extensions_cache(),
extension,
Handle<Context>(isolate->context()),
false);
ASSERT(isolate->has_pending_exception() != result);
if (!result) {
isolate->clear_pending_exception();
......
......@@ -234,7 +234,7 @@ Handle<String> Factory::NewProperSubString(Handle<String> str,
Handle<String> Factory::NewExternalStringFromAscii(
ExternalAsciiString::Resource* resource) {
const ExternalAsciiString::Resource* resource) {
CALL_HEAP_FUNCTION(
isolate(),
isolate()->heap()->AllocateExternalStringFromAscii(resource),
......@@ -243,7 +243,7 @@ Handle<String> Factory::NewExternalStringFromAscii(
Handle<String> Factory::NewExternalStringFromTwoByte(
ExternalTwoByteString::Resource* resource) {
const ExternalTwoByteString::Resource* resource) {
CALL_HEAP_FUNCTION(
isolate(),
isolate()->heap()->AllocateExternalStringFromTwoByte(resource),
......
......@@ -145,9 +145,9 @@ class Factory {
// not make sense to have a UTF-8 factory function for external strings,
// because we cannot change the underlying buffer.
Handle<String> NewExternalStringFromAscii(
ExternalAsciiString::Resource* resource);
const ExternalAsciiString::Resource* resource);
Handle<String> NewExternalStringFromTwoByte(
ExternalTwoByteString::Resource* resource);
const ExternalTwoByteString::Resource* resource);
// Create a global (but otherwise uninitialized) context.
Handle<Context> NewGlobalContext();
......
......@@ -2919,7 +2919,7 @@ MaybeObject* Heap::AllocateSubString(String* buffer,
MaybeObject* Heap::AllocateExternalStringFromAscii(
ExternalAsciiString::Resource* resource) {
const ExternalAsciiString::Resource* resource) {
size_t length = resource->length();
if (length > static_cast<size_t>(String::kMaxLength)) {
isolate()->context()->mark_out_of_memory();
......@@ -2942,7 +2942,7 @@ MaybeObject* Heap::AllocateExternalStringFromAscii(
MaybeObject* Heap::AllocateExternalStringFromTwoByte(
ExternalTwoByteString::Resource* resource) {
const ExternalTwoByteString::Resource* resource) {
size_t length = resource->length();
if (length > static_cast<size_t>(String::kMaxLength)) {
isolate()->context()->mark_out_of_memory();
......
......@@ -835,9 +835,9 @@ class Heap {
// failed.
// Please note this does not perform a garbage collection.
MUST_USE_RESULT MaybeObject* AllocateExternalStringFromAscii(
ExternalAsciiString::Resource* resource);
const ExternalAsciiString::Resource* resource);
MUST_USE_RESULT MaybeObject* AllocateExternalStringFromTwoByte(
ExternalTwoByteString::Resource* resource);
const ExternalTwoByteString::Resource* resource);
// Finalizes an external string by deleting the associated external
// data and clearing the resource pointer.
......
......@@ -2299,25 +2299,27 @@ void ConsString::set_second(String* value, WriteBarrierMode mode) {
}
ExternalAsciiString::Resource* ExternalAsciiString::resource() {
const ExternalAsciiString::Resource* ExternalAsciiString::resource() {
return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
}
void ExternalAsciiString::set_resource(
ExternalAsciiString::Resource* resource) {
*reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
const ExternalAsciiString::Resource* resource) {
*reinterpret_cast<const Resource**>(
FIELD_ADDR(this, kResourceOffset)) = resource;
}
ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
const ExternalTwoByteString::Resource* ExternalTwoByteString::resource() {
return *reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset));
}
void ExternalTwoByteString::set_resource(
ExternalTwoByteString::Resource* resource) {
*reinterpret_cast<Resource**>(FIELD_ADDR(this, kResourceOffset)) = resource;
const ExternalTwoByteString::Resource* resource) {
*reinterpret_cast<const Resource**>(
FIELD_ADDR(this, kResourceOffset)) = resource;
}
......
......@@ -6379,8 +6379,8 @@ class ExternalAsciiString: public ExternalString {
typedef v8::String::ExternalAsciiStringResource Resource;
// The underlying resource.
inline Resource* resource();
inline void set_resource(Resource* buffer);
inline const Resource* resource();
inline void set_resource(const Resource* buffer);
// Dispatched behavior.
uint16_t ExternalAsciiStringGet(int index);
......@@ -6416,8 +6416,8 @@ class ExternalTwoByteString: public ExternalString {
typedef v8::String::ExternalStringResource Resource;
// The underlying string resource.
inline Resource* resource();
inline void set_resource(Resource* buffer);
inline const Resource* resource();
inline void set_resource(const Resource* buffer);
// Dispatched behavior.
uint16_t ExternalTwoByteStringGet(int index);
......
......@@ -1453,7 +1453,7 @@ void Serializer::ObjectSerializer::VisitExternalAsciiString(
if (!source->IsUndefined()) {
ExternalAsciiString* string = ExternalAsciiString::cast(source);
typedef v8::String::ExternalAsciiStringResource Resource;
Resource* resource = string->resource();
const Resource* resource = string->resource();
if (resource == *resource_pointer) {
sink_->Put(kNativesStringResource, "NativesStringResource");
sink_->PutSection(i, "NativesStringResourceEnd");
......
......@@ -4293,6 +4293,47 @@ THREADED_TEST(SimpleExtensions) {
}
static const char* kEmbeddedExtensionSource =
"function Ret54321(){return 54321;}~~@@$"
"$%% THIS IS A SERIES OF NON-NULL-TERMINATED STRINGS.";
static const int kEmbeddedExtensionSourceValidLen = 34;
THREADED_TEST(ExtensionMissingSourceLength) {
v8::HandleScope handle_scope;
v8::RegisterExtension(new Extension("srclentest_fail",
kEmbeddedExtensionSource));
const char* extension_names[] = { "srclentest_fail" };
v8::ExtensionConfiguration extensions(1, extension_names);
v8::Handle<Context> context = Context::New(&extensions);
CHECK_EQ(0, *context);
}
THREADED_TEST(ExtensionWithSourceLength) {
for (int source_len = kEmbeddedExtensionSourceValidLen - 1;
source_len <= kEmbeddedExtensionSourceValidLen + 1; ++source_len) {
v8::HandleScope handle_scope;
char extension_name[32];
snprintf(extension_name, sizeof(extension_name), "ext #%d", source_len);
v8::RegisterExtension(new Extension(extension_name,
kEmbeddedExtensionSource, 0, 0,
source_len));
const char* extension_names[1] = { extension_name };
v8::ExtensionConfiguration extensions(1, extension_names);
v8::Handle<Context> context = Context::New(&extensions);
if (source_len == kEmbeddedExtensionSourceValidLen) {
Context::Scope lock(context);
v8::Handle<Value> result = Script::Compile(v8_str("Ret54321()"))->Run();
CHECK_EQ(v8::Integer::New(54321), result);
} else {
// Anything but exactly the right length should fail to compile.
CHECK_EQ(0, *context);
}
}
}
static const char* kEvalExtensionSource1 =
"function UseEval1() {"
" var x = 42;"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment