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

Commit

Permalink
chakrashim: add shim for JSON methods
Browse files Browse the repository at this point in the history
Add v8::JSON::Parse and v8::JSON::Stringify to chakrashim.

Also fixes some cpplint errors in v8.h and adds v8.h to
the set of files we lint in vcbuild.bat.

Fix the MacOS build to make sure that all chakrashim
exports are re-exported by node.

PR-URL: #313
Reviewed-By: Kunal Pathak <kunal.pathak@microsoft.com>
Reviewed-By: Kyle Farnung <kfarnung@microsoft.com>
Reviewed-By: Jimmy Thomson <jithomso@microsoft.com>
  • Loading branch information
boingoing authored and kfarnung committed Jun 26, 2017
1 parent 360e93e commit 4be96a0
Show file tree
Hide file tree
Showing 12 changed files with 206 additions and 30 deletions.
1 change: 1 addition & 0 deletions deps/chakrashim/chakrashim.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@
'src/v8int32.cc',
'src/v8integer.cc',
'src/v8isolate.cc',
'src/v8json.cc',
'src/v8map.cc',
'src/v8message.cc',
'src/v8microtasksscope.cc',
Expand Down
83 changes: 56 additions & 27 deletions deps/chakrashim/include/v8.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#pragma once
#ifndef DEPS_CHAKRASHIM_INCLUDE_V8_H_
#define DEPS_CHAKRASHIM_INCLUDE_V8_H_

// Stops windows.h from including winsock.h (conflicting with winsock2.h).
#ifndef _WINSOCKAPI_
Expand Down Expand Up @@ -324,6 +325,7 @@ class Local {
friend class TryCatch;
friend class UnboundScript;
friend class Value;
friend class JSON;
template <class F> friend class FunctionCallbackInfo;
template <class F> friend class MaybeLocal;
template <class F> friend class PersistentBase;
Expand Down Expand Up @@ -364,7 +366,7 @@ class MaybeLocal {
public:
MaybeLocal() : val_(nullptr) {}
template <class S>
MaybeLocal(Local<S> that)
MaybeLocal(Local<S> that) // NOLINT(runtime/explicit)
: val_(reinterpret_cast<T*>(*that)) {
TYPE_CHECK(T, S);
}
Expand Down Expand Up @@ -821,6 +823,7 @@ class ScriptOrigin {
V8_INLINE Local<Integer> ScriptID() const {
return script_id_;
}

private:
Local<Value> resource_name_;
Local<Integer> resource_line_offset_;
Expand Down Expand Up @@ -886,7 +889,8 @@ class V8_EXPORT ScriptCompiler {
: source_string(source_string), resource_name(origin.ResourceName()) {
}

Source(Local<String> source_string, CachedData * cached_data = NULL)
Source(Local<String> source_string, // NOLINT(runtime/explicit)
CachedData * cached_data = NULL)
: source_string(source_string) {
}

Expand Down Expand Up @@ -995,7 +999,9 @@ class V8_EXPORT StackFrame {

enum class PromiseHookType { kInit, kResolve, kBefore, kAfter };

typedef void(*PromiseHook)(PromiseHookType type, Local<Promise> promise, Local<Value> parent);
typedef void(*PromiseHook)(PromiseHookType type,
Local<Promise> promise,
Local<Value> parent);


class V8_EXPORT Value : public Data {
Expand Down Expand Up @@ -1283,7 +1289,7 @@ class V8_EXPORT Symbol : public Name {
public:
// Returns the print name string of the symbol, or undefined if none.
Local<Value> Name() const;
static Local<Symbol> New(Isolate* isolate,
static Local<Symbol> New(Isolate* isolate,
Local<String> name = Local<String>());
static Symbol* Cast(Value* obj);

Expand Down Expand Up @@ -1354,8 +1360,9 @@ class V8_EXPORT Object : public Value {
Local<Context> context, Local<Name> key, Local<Value> value,
PropertyAttribute attributes = None);

V8_WARN_UNUSED_RESULT Maybe<bool> DefineProperty(
Local<Context> context, Local<Name>, PropertyDescriptor& decriptor);
V8_WARN_UNUSED_RESULT Maybe<bool> DefineProperty(Local<Context> context,
Local<Name>,
PropertyDescriptor& decriptor); // NOLINT(runtime/references)

V8_DEPRECATE_SOON("Use maybe version",
bool ForceSet(Handle<Value> key, Handle<Value> value,
Expand Down Expand Up @@ -1764,16 +1771,17 @@ enum class ConstructorBehavior { kThrow, kAllow };

class V8_EXPORT Function : public Object {
public:
static MaybeLocal<Function> New(Local<Context> context,
FunctionCallback callback,
Local<Value> data = Local<Value>(),
int length = 0,
ConstructorBehavior behavior = ConstructorBehavior::kAllow);
static MaybeLocal<Function> New(
Local<Context> context,
FunctionCallback callback,
Local<Value> data = Local<Value>(),
int length = 0,
ConstructorBehavior behavior = ConstructorBehavior::kAllow);
static V8_DEPRECATE_SOON("Use maybe version",
Local<Function> New(Isolate* isolate,
FunctionCallback callback,
Local<Value> data = Local<Value>(),
int length = 0));
Local<Function> New(Isolate* isolate,
FunctionCallback callback,
Local<Value> data = Local<Value>(),
int length = 0));

V8_DEPRECATE_SOON("Use maybe version",
Local<Object> NewInstance(int argc,
Expand Down Expand Up @@ -1847,6 +1855,7 @@ class V8_EXPORT Promise : public Object {

bool HasHandler();
static Promise* Cast(Value* obj);

private:
Promise();
};
Expand Down Expand Up @@ -2061,17 +2070,32 @@ class V8_EXPORT Float64Array : public TypedArray {
};

class V8_EXPORT SharedArrayBuffer : public Object {
public:
public:
static SharedArrayBuffer* Cast(Value* obj);

private:
private:
SharedArrayBuffer();
};

class V8_EXPORT JSON {
public:
static V8_DEPRECATED("Use the maybe version taking context",
Local<Value> Parse(Local<String> json_string));
static V8_DEPRECATE_SOON("Use the maybe version taking context",
MaybeLocal<Value> Parse(Isolate* isolate,
Local<String> json_string));
static V8_WARN_UNUSED_RESULT MaybeLocal<Value> Parse(
Local<Context> context, Local<String> json_string);

static V8_WARN_UNUSED_RESULT MaybeLocal<String> Stringify(
Local<Context> context, Local<Object> json_object,
Local<String> gap = Local<String>());
};

class V8_EXPORT ValueSerializer {
public:
public:
class V8_EXPORT Delegate {
public:
public:
virtual ~Delegate() {}

virtual void ThrowDataCloneError(Local<String> message) = 0;
Expand Down Expand Up @@ -2099,15 +2123,15 @@ class V8_EXPORT ValueSerializer {
void WriteDouble(double value);
void WriteRawBytes(const void* source, size_t length);

private:
private:
ValueSerializer(const ValueSerializer&) = delete;
void operator=(const ValueSerializer&) = delete;
};

class V8_EXPORT ValueDeserializer {
public:
public:
class V8_EXPORT Delegate {
public:
public:
virtual ~Delegate() {}

virtual MaybeLocal<Object> ReadHostObject(Isolate* isolate);
Expand All @@ -2129,7 +2153,7 @@ class V8_EXPORT ValueDeserializer {
V8_WARN_UNUSED_RESULT bool ReadDouble(double* value);
V8_WARN_UNUSED_RESULT bool ReadRawBytes(size_t length, const void** data);

private:
private:
ValueDeserializer(const ValueDeserializer&) = delete;
void operator=(const ValueDeserializer&) = delete;
};
Expand Down Expand Up @@ -2354,7 +2378,7 @@ class V8_EXPORT Exception {
};

class V8_EXPORT MicrotasksScope {
public:
public:
enum Type { kRunMicrotasks, kDoNotRunMicrotasks };

MicrotasksScope(Isolate* isolate, Type type);
Expand Down Expand Up @@ -2532,8 +2556,11 @@ class V8_EXPORT Isolate {
};

static Isolate* NewWithTTDSupport(const CreateParams& params,
size_t optReplayUriLength, const char* optReplayUri,
bool doRecord, bool doReplay, bool doDebug,
size_t optReplayUriLength,
const char* optReplayUri,
bool doRecord,
bool doReplay,
bool doDebug,
uint32_t snapInterval,
uint32_t snapHistoryLength);
static Isolate* New(const CreateParams& params);
Expand Down Expand Up @@ -3023,3 +3050,5 @@ Isolate* PropertyCallbackInfo<T>::GetIsolate() const {
}

} // namespace v8

#endif // DEPS_CHAKRASHIM_INCLUDE_V8_H_
10 changes: 9 additions & 1 deletion deps/chakrashim/lib/chakra_shim.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@
Set_values = Set.prototype.values,
Symbol_keyFor = Symbol.keyFor,
Symbol_for = Symbol.for,
Global_ParseInt = parseInt;
Global_ParseInt = parseInt,
JSON_parse = JSON.parse,
JSON_stringify = JSON.stringify;
var BuiltInError = Error;
var global = this;

Expand Down Expand Up @@ -585,6 +587,12 @@
utils.getSymbolFor = function(key) {
return Symbol_for(key);
};
utils.jsonParse = function(text, reviver) {
return JSON_parse(text, reviver);
};
utils.jsonStringify = function(value, replacer, space) {
return JSON_stringify(value, replacer, space);
};
utils.ensureDebug = ensureDebug;
utils.enqueueMicrotask = function(task) {
microTasks.push(task);
Expand Down
2 changes: 2 additions & 0 deletions deps/chakrashim/src/jsrtcachedpropertyidref.inc
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ DEF(getLineNumber)
DEF(prototype)
DEF(toString)
DEF(valueOf)
DEF(jsonParse)
DEF(jsonStringify)

DEF(arguments)
DEF(breakpointId)
Expand Down
6 changes: 5 additions & 1 deletion deps/chakrashim/src/jsrtcontextshim.cc
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,9 @@ ContextShim::ContextShim(IsolateShim * isolateShim,
enqueueMicrotaskFunction(JS_INVALID_REFERENCE),
dequeueMicrotaskFunction(JS_INVALID_REFERENCE),
getPropertyAttributesFunction(JS_INVALID_REFERENCE),
getOwnPropertyNamesFunction(JS_INVALID_REFERENCE) {
getOwnPropertyNamesFunction(JS_INVALID_REFERENCE),
jsonParseFunction(JS_INVALID_REFERENCE),
jsonStringifyFunction(JS_INVALID_REFERENCE) {
memset(globalConstructor, 0, sizeof(globalConstructor));
memset(globalPrototypeFunction, 0, sizeof(globalPrototypeFunction));
}
Expand Down Expand Up @@ -635,6 +637,8 @@ CHAKRASHIM_FUNCTION_GETTER(enqueueMicrotask);
CHAKRASHIM_FUNCTION_GETTER(dequeueMicrotask);
CHAKRASHIM_FUNCTION_GETTER(getPropertyAttributes);
CHAKRASHIM_FUNCTION_GETTER(getOwnPropertyNames);
CHAKRASHIM_FUNCTION_GETTER(jsonParse);
CHAKRASHIM_FUNCTION_GETTER(jsonStringify);

#define DEF_IS_TYPE(F) CHAKRASHIM_FUNCTION_GETTER(F)
#include "jsrtcachedpropertyidref.inc"
Expand Down
2 changes: 2 additions & 0 deletions deps/chakrashim/src/jsrtcontextshim.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,8 @@ class ContextShim {
DECLARE_CHAKRASHIM_FUNCTION_GETTER(dequeueMicrotask);
DECLARE_CHAKRASHIM_FUNCTION_GETTER(getPropertyAttributes);
DECLARE_CHAKRASHIM_FUNCTION_GETTER(getOwnPropertyNames);
DECLARE_CHAKRASHIM_FUNCTION_GETTER(jsonParse);
DECLARE_CHAKRASHIM_FUNCTION_GETTER(jsonStringify);
};

} // namespace jsrt
Expand Down
69 changes: 69 additions & 0 deletions deps/chakrashim/src/v8json.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// 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 {
Local<Value> JSON::Parse(Local<String> json_string) {
v8::Isolate* iso = jsrt::IsolateShim::GetCurrentAsIsolate();
return FromMaybe(JSON::Parse(iso, json_string));
}

MaybeLocal<Value> JSON::Parse(Isolate* isolate,
Local<String> json_string) {
Local<Context> context = isolate->GetCurrentContext();
return JSON::Parse(context, json_string);
}

MaybeLocal<Value> JSON::Parse(Local<Context> context,
Local<String> json_string) {
jsrt::ContextShim *contextShim = jsrt::IsolateShim::GetContextShim(
(JsContextRef)*context);

JsValueRef jsonParseFunction = contextShim->GetjsonParseFunction();
JsValueRef obj = JS_INVALID_REFERENCE;

if (jsrt::CallFunction(jsonParseFunction, (JsValueRef)*json_string,
&obj) != JsNoError) {
return Local<Value>();
}

return Local<Value>::New(obj);
}

MaybeLocal<String> JSON::Stringify(Local<Context> context,
Local<Object> json_object,
Local<String> gap) {
jsrt::ContextShim *contextShim = jsrt::IsolateShim::GetContextShim(
(JsContextRef)*context);

JsValueRef jsonStringifyFunction = contextShim->GetjsonStringifyFunction();
JsValueRef str = JS_INVALID_REFERENCE;
JsValueRef actualGap =
gap.IsEmpty() ? jsrt::GetUndefined() : static_cast<JsValueRef>(*gap);

if (jsrt::CallFunction(jsonStringifyFunction, (JsValueRef)*json_object,
jsrt::GetUndefined(), actualGap, &str) != JsNoError) {
return Local<String>();
}

return Local<String>::New(str);
}
} // namespace v8
10 changes: 10 additions & 0 deletions node.gypi
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,16 @@
'dependencies': [
'deps/chakrashim/chakrashim.gyp:chakrashim'
],
'conditions': [
# -force_load is not applicable for the static library
[ 'node_target_type!="static_library"', {
'xcode_settings': {
'OTHER_LDFLAGS': [
'-Wl,-force_load,<(CHAKRASHIM_BASE)',
],
},
}],
],
}],
[ 'node_shared_zlib=="false"', {
'dependencies': [ 'deps/zlib/zlib.gyp:zlib' ],
Expand Down
26 changes: 26 additions & 0 deletions test/addons/json/binding.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#include <node.h>
#include <v8.h>

namespace {

void Stringify(const v8::FunctionCallbackInfo<v8::Value>& args) {
auto result = v8::JSON::Stringify(args.GetIsolate()->GetCurrentContext(),
args[0].As<v8::Object>(),
args[1].As<v8::String>());
args.GetReturnValue().Set(result.ToLocalChecked());
}

void Parse(const v8::FunctionCallbackInfo<v8::Value>& args) {
auto result = v8::JSON::Parse(args.GetIsolate()->GetCurrentContext(),
args[0].As<v8::String>());
args.GetReturnValue().Set(result.ToLocalChecked());
}

inline void Initialize(v8::Local<v8::Object> binding) {
NODE_SET_METHOD(binding, "stringify", Stringify);
NODE_SET_METHOD(binding, "parse", Parse);
}

NODE_MODULE(binding, Initialize)

} // anonymous namespace
9 changes: 9 additions & 0 deletions test/addons/json/binding.gyp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
'targets': [
{
'target_name': 'binding',
'defines': [ 'V8_DEPRECATION_WARNINGS=1' ],
'sources': [ 'binding.cc' ]
}
]
}
Loading

0 comments on commit 4be96a0

Please sign in to comment.