Skip to content
This repository has been archived by the owner on Oct 15, 2020. It is now read-only.

Commit

Permalink
chakrashim: correct Template properties support
Browse files Browse the repository at this point in the history
Template (ObjectTemplate, FunctionTemplate) properties can be Templates.
When creating Template instances, Template properties need to be replaced
with corresponding Template instantiations.

`nodejs/master` starts to depend on this feature.

PR-URL: #64
Reviewed-By: Sandeep Agarwal <Agarwal.Sandeep@microsoft.com>
  • Loading branch information
Jianchun Xu committed Apr 27, 2016
1 parent acca384 commit 2a8b3b0
Show file tree
Hide file tree
Showing 9 changed files with 480 additions and 350 deletions.
1 change: 1 addition & 0 deletions deps/chakrashim/chakrashim.gyp
Expand Up @@ -80,6 +80,7 @@
'src/v8arraybuffer.cc',
'src/v8boolean.cc',
'src/v8booleanobject.cc',
'src/v8chakra.cc',
'src/v8chakra.h',
'src/v8context.cc',
'src/v8date.cc',
Expand Down
38 changes: 17 additions & 21 deletions deps/chakrashim/include/v8.h
Expand Up @@ -119,7 +119,6 @@ template <typename T> class PropertyCallbackInfo;

class JitCodeEvent;
class RetainedObjectInfo;
struct ExternalArrayData;

enum PropertyAttribute {
None = 0,
Expand Down Expand Up @@ -283,15 +282,15 @@ class Local {
friend class Debug;
friend class External;
friend class Function;
friend struct FunctionCallbackData;
friend class FunctionCallbackData;
friend class FunctionTemplate;
friend struct FunctionTemplateData;
friend class FunctionTemplateData;
friend class HandleScope;
friend class Integer;
friend class Number;
friend class NumberObject;
friend class Object;
friend struct ObjectData;
friend class ObjectData;
friend class ObjectTemplate;
friend class Private;
friend class Signature;
Expand Down Expand Up @@ -619,13 +618,13 @@ class Persistent : public PersistentBase<T> {

private:
friend class Object;
friend struct ObjectData;
friend class ObjectData;
friend class ObjectTemplate;
friend struct ObjectTemplateData;
friend struct TemplateData;
friend struct FunctionCallbackData;
friend class ObjectTemplateData;
friend class TemplateData;
friend class FunctionCallbackData;
friend class FunctionTemplate;
friend struct FunctionTemplateData;
friend class FunctionTemplateData;
friend class Utils;
template <class F> friend class Local;
template <class F> friend class ReturnValue;
Expand Down Expand Up @@ -1430,7 +1429,7 @@ class V8_EXPORT Object : public Value {
static Object *Cast(Value *obj);

private:
friend struct ObjectData;
friend class ObjectData;
friend class ObjectTemplate;
friend class Utils;

Expand All @@ -1444,7 +1443,7 @@ class V8_EXPORT Object : public Value {
PropertyAttribute attribute,
Handle<AccessorSignature> signature);

JsErrorCode GetObjectData(struct ObjectData** objectData);
JsErrorCode GetObjectData(ObjectData** objectData);
ObjectTemplate* GetObjectTemplate();
};

Expand Down Expand Up @@ -1837,10 +1836,9 @@ typedef bool (*IndexedSecurityCallback)(

class V8_EXPORT Template : public Data {
public:
void Set(Handle<String> name,
Handle<Data> value,
void Set(Local<Name> name, Local<Data> value,
PropertyAttribute attributes = None);
void Set(Isolate* isolate, const char* name, Handle<Data> value) {
V8_INLINE void Set(Isolate* isolate, const char* name, Local<Data> value) {
Set(v8::String::NewFromUtf8(isolate, name), value);
}
private:
Expand All @@ -1850,11 +1848,9 @@ class V8_EXPORT Template : public Data {
class V8_EXPORT FunctionTemplate : public Template {
public:
static Local<FunctionTemplate> New(
Isolate* isolate,
FunctionCallback callback = 0,
Handle<Value> data = Handle<Value>(),
Handle<Signature> signature = Handle<Signature>(),
int length = 0);
Isolate* isolate, FunctionCallback callback = 0,
Local<Value> data = Local<Value>(),
Local<Signature> signature = Local<Signature>(), int length = 0);

V8_DEPRECATE_SOON("Use maybe version", Local<Function> GetFunction());
V8_WARN_UNUSED_RESULT MaybeLocal<Function> GetFunction(
Expand Down Expand Up @@ -1984,8 +1980,8 @@ class V8_EXPORT ObjectTemplate : public Template {
Handle<Value> data = Handle<Value>());

private:
friend struct FunctionCallbackData;
friend struct FunctionTemplateData;
friend class FunctionCallbackData;
friend class FunctionTemplateData;
friend class Utils;

Local<Object> NewInstance(Handle<Object> prototype);
Expand Down
8 changes: 8 additions & 0 deletions deps/chakrashim/src/jsrtutils.h
Expand Up @@ -39,6 +39,14 @@
} \
}

#define IfJsErrorRet(expr, ...) \
{ \
JsErrorCode _error = (expr); \
if (_error != JsNoError) { \
return _error, ##__VA_ARGS__; \
} \
}

#define CHAKRA_UNIMPLEMENTED() jsrt::Unimplemented(__FUNCTION__)
#define CHAKRA_UNIMPLEMENTED_(message) jsrt::Unimplemented(message)

Expand Down
100 changes: 100 additions & 0 deletions deps/chakrashim/src/v8chakra.cc
@@ -0,0 +1,100 @@
// Copyright Microsoft. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and / or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.

#include "v8chakra.h"

namespace v8 {

using jsrt::IsolateShim;

Object* TemplateData::EnsureProperties() {
if (properties.IsEmpty()) {
properties = Object::New();
}

return *properties;
}

bool TemplateData::Is(ExternalData* data) {
return data->GetType() == ExternalDataTypes::ObjectTemplateData
|| data->GetType() == ExternalDataTypes::FunctionTemplateData;
}

// Clone the template properties into the new instance
JsErrorCode TemplateData::CopyPropertiesTo(JsValueRef newInstance) {
if (properties.IsEmpty()) {
return JsNoError;
}

JsValueRef propertiesRef = *properties;
JsValueRef propertyNames;
IfJsErrorRet(JsGetOwnPropertyNames(propertiesRef, &propertyNames));

unsigned int length;
IfJsErrorRet(jsrt::GetArrayLength(propertyNames, &length));

JsPropertyIdRef valueIdRef;
if (length > 0) {
valueIdRef = IsolateShim::GetCurrent()->GetCachedPropertyIdRef(
jsrt::CachedPropertyIdRef::value);
}

for (unsigned int index = 0; index < length; index++) {
JsValueRef indexValue;
IfJsErrorRet(JsIntToNumber(index, &indexValue));

JsValueRef propertyNameValue;
IfJsErrorRet(JsGetIndexedProperty(propertyNames, indexValue,
&propertyNameValue));

const wchar_t *propertyName;
size_t propertyNameLength;
IfJsErrorRet(JsStringToPointer(propertyNameValue,
&propertyName, &propertyNameLength));

JsPropertyIdRef propertyId;
IfJsErrorRet(JsGetPropertyIdFromName(propertyName, &propertyId));

JsValueRef propertyDescriptor;
IfJsErrorRet(JsGetOwnPropertyDescriptor(propertiesRef, propertyId,
&propertyDescriptor));

// If it is a Template, try create an instance
JsValueRef value;
IfJsErrorRet(JsGetProperty(propertyDescriptor, valueIdRef, &value));
ExternalData* data = nullptr;
if (ExternalData::TryGet(value, &data) && TemplateData::Is(data)) {
TemplateData* templateData = static_cast<TemplateData*>(data);
value = templateData->NewInstance(value);
if (value == JS_INVALID_REFERENCE) {
return JsErrorFatal; // Just to indicate failed
}
IfJsErrorRet(JsSetProperty(propertyDescriptor, valueIdRef, value, false));
}

bool result;
IfJsErrorRet(JsDefineProperty(newInstance, propertyId, propertyDescriptor,
&result));
}

return JsNoError;
}

} // namespace v8
82 changes: 74 additions & 8 deletions deps/chakrashim/src/v8chakra.h
Expand Up @@ -25,14 +25,64 @@
namespace v8 {

using jsrt::ContextShim;

struct ObjectTemplateData;
class ObjectTemplateData;

extern __declspec(thread) bool g_EnableDebug;
extern ArrayBuffer::Allocator* g_arrayBufferAllocator;

struct ObjectData {
// External object data types
enum class ExternalDataTypes {
Unknown,
ObjectTemplateData,
ObjectData,
FunctionTemplateData,
FunctionCallbackData,
};

// Base class for external object data
class ExternalData {
private:
const ExternalDataTypes type;

public:
ExternalData(ExternalDataTypes type) : type(type) {}
virtual ~ExternalData() {}

ExternalDataTypes GetType() const { return type; }

template <class T>
static bool Is(T* data) {
return data->GetType() == T::ExternalDataType;
}

static JsErrorCode GetExternalData(JsValueRef ref, ExternalData** data) {
return JsGetExternalData(ref, reinterpret_cast<void**>(data));
}

template <class T>
static JsErrorCode GetExternalData(JsValueRef ref, T** data) {
ExternalData* p = nullptr;
JsErrorCode error = GetExternalData(ref, &p);
*data = (error == JsNoError
&& p != nullptr
&& p->GetType() == T::ExternalDataType) ?
static_cast<T*>(p) : nullptr;

CHAKRA_ASSERT(*data == nullptr || (error == JsNoError && Is(*data)));
return error;
}

template <class T>
static bool TryGet(JsValueRef ref, T** data) {
return GetExternalData(ref, data) == JsNoError && *data != nullptr;
}
};

class ObjectData: public ExternalData {
public:
static const ExternalDataTypes ExternalDataType =
ExternalDataTypes::ObjectData;

struct FieldValue {
public:
FieldValue() : value(nullptr), isRefValue(false) {}
Expand Down Expand Up @@ -70,20 +120,27 @@ struct ObjectData {
FieldValue* internalFields;

ObjectData(ObjectTemplate* objectTemplate, ObjectTemplateData *templateData);
void Dispose();
~ObjectData();
static void CALLBACK FinalizeCallback(void *data);

static FieldValue* GetInternalField(Object* object, int index);
};

struct TemplateData {
protected:
class TemplateData : public ExternalData {
private:
Persistent<Object> properties;
virtual void CreateProperties(); // Allow properties to be created lazily

public:
virtual ~TemplateData() {}
explicit TemplateData(ExternalDataTypes type) : ExternalData(type) {}
virtual ~TemplateData() {
properties.Reset();
}

static bool Is(ExternalData* data);
virtual JsValueRef NewInstance(JsValueRef templateRef) = 0;

Object* EnsureProperties();
JsErrorCode CopyPropertiesTo(JsValueRef newInstance);
};

class Utils {
Expand Down Expand Up @@ -180,6 +237,15 @@ class Utils {
static Local<T> NewTypedArray(ContextShim::GlobalType constructorIndex,
Handle<ArrayBuffer> array_buffer,
size_t byte_offset, size_t length);

static ObjectTemplate* EnsureObjectTemplate(
Persistent<ObjectTemplate>& objectTemplate) {
if (objectTemplate.IsEmpty()) {
// Create ObjectTemplate lazily
objectTemplate = ObjectTemplate::New(nullptr);
}
return *objectTemplate;
}
};


Expand Down

0 comments on commit 2a8b3b0

Please sign in to comment.