diff --git a/deps/chakrashim/chakrashim.gyp b/deps/chakrashim/chakrashim.gyp index 68ddc488fb4..3511194f00c 100644 --- a/deps/chakrashim/chakrashim.gyp +++ b/deps/chakrashim/chakrashim.gyp @@ -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', diff --git a/deps/chakrashim/include/v8.h b/deps/chakrashim/include/v8.h index 0fdc2850b67..bfecaa21906 100644 --- a/deps/chakrashim/include/v8.h +++ b/deps/chakrashim/include/v8.h @@ -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_ @@ -324,6 +325,7 @@ class Local { friend class TryCatch; friend class UnboundScript; friend class Value; + friend class JSON; template friend class FunctionCallbackInfo; template friend class MaybeLocal; template friend class PersistentBase; @@ -364,7 +366,7 @@ class MaybeLocal { public: MaybeLocal() : val_(nullptr) {} template - MaybeLocal(Local that) + MaybeLocal(Local that) // NOLINT(runtime/explicit) : val_(reinterpret_cast(*that)) { TYPE_CHECK(T, S); } @@ -821,6 +823,7 @@ class ScriptOrigin { V8_INLINE Local ScriptID() const { return script_id_; } + private: Local resource_name_; Local resource_line_offset_; @@ -886,7 +889,8 @@ class V8_EXPORT ScriptCompiler { : source_string(source_string), resource_name(origin.ResourceName()) { } - Source(Local source_string, CachedData * cached_data = NULL) + Source(Local source_string, // NOLINT(runtime/explicit) + CachedData * cached_data = NULL) : source_string(source_string) { } @@ -995,7 +999,9 @@ class V8_EXPORT StackFrame { enum class PromiseHookType { kInit, kResolve, kBefore, kAfter }; -typedef void(*PromiseHook)(PromiseHookType type, Local promise, Local parent); +typedef void(*PromiseHook)(PromiseHookType type, + Local promise, + Local parent); class V8_EXPORT Value : public Data { @@ -1283,7 +1289,7 @@ class V8_EXPORT Symbol : public Name { public: // Returns the print name string of the symbol, or undefined if none. Local Name() const; - static Local New(Isolate* isolate, + static Local New(Isolate* isolate, Local name = Local()); static Symbol* Cast(Value* obj); @@ -1354,8 +1360,9 @@ class V8_EXPORT Object : public Value { Local context, Local key, Local value, PropertyAttribute attributes = None); - V8_WARN_UNUSED_RESULT Maybe DefineProperty( - Local context, Local, PropertyDescriptor& decriptor); + V8_WARN_UNUSED_RESULT Maybe DefineProperty(Local context, + Local, + PropertyDescriptor& decriptor); // NOLINT(runtime/references) V8_DEPRECATE_SOON("Use maybe version", bool ForceSet(Handle key, Handle value, @@ -1764,16 +1771,17 @@ enum class ConstructorBehavior { kThrow, kAllow }; class V8_EXPORT Function : public Object { public: - static MaybeLocal New(Local context, - FunctionCallback callback, - Local data = Local(), - int length = 0, - ConstructorBehavior behavior = ConstructorBehavior::kAllow); + static MaybeLocal New( + Local context, + FunctionCallback callback, + Local data = Local(), + int length = 0, + ConstructorBehavior behavior = ConstructorBehavior::kAllow); static V8_DEPRECATE_SOON("Use maybe version", - Local New(Isolate* isolate, - FunctionCallback callback, - Local data = Local(), - int length = 0)); + Local New(Isolate* isolate, + FunctionCallback callback, + Local data = Local(), + int length = 0)); V8_DEPRECATE_SOON("Use maybe version", Local NewInstance(int argc, @@ -1847,6 +1855,7 @@ class V8_EXPORT Promise : public Object { bool HasHandler(); static Promise* Cast(Value* obj); + private: Promise(); }; @@ -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 Parse(Local json_string)); + static V8_DEPRECATE_SOON("Use the maybe version taking context", + MaybeLocal Parse(Isolate* isolate, + Local json_string)); + static V8_WARN_UNUSED_RESULT MaybeLocal Parse( + Local context, Local json_string); + + static V8_WARN_UNUSED_RESULT MaybeLocal Stringify( + Local context, Local json_object, + Local gap = Local()); +}; + class V8_EXPORT ValueSerializer { -public: + public: class V8_EXPORT Delegate { - public: + public: virtual ~Delegate() {} virtual void ThrowDataCloneError(Local message) = 0; @@ -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 ReadHostObject(Isolate* isolate); @@ -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; }; @@ -2354,7 +2378,7 @@ class V8_EXPORT Exception { }; class V8_EXPORT MicrotasksScope { -public: + public: enum Type { kRunMicrotasks, kDoNotRunMicrotasks }; MicrotasksScope(Isolate* isolate, Type type); @@ -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); @@ -3023,3 +3050,5 @@ Isolate* PropertyCallbackInfo::GetIsolate() const { } } // namespace v8 + +#endif // DEPS_CHAKRASHIM_INCLUDE_V8_H_ diff --git a/deps/chakrashim/lib/chakra_shim.js b/deps/chakrashim/lib/chakra_shim.js index a2f533f0b4f..c601fba8795 100644 --- a/deps/chakrashim/lib/chakra_shim.js +++ b/deps/chakrashim/lib/chakra_shim.js @@ -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; @@ -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); diff --git a/deps/chakrashim/src/jsrtcachedpropertyidref.inc b/deps/chakrashim/src/jsrtcachedpropertyidref.inc index bebf48bddbb..a2f0e99403e 100644 --- a/deps/chakrashim/src/jsrtcachedpropertyidref.inc +++ b/deps/chakrashim/src/jsrtcachedpropertyidref.inc @@ -83,6 +83,8 @@ DEF(getLineNumber) DEF(prototype) DEF(toString) DEF(valueOf) +DEF(jsonParse) +DEF(jsonStringify) DEF(arguments) DEF(breakpointId) diff --git a/deps/chakrashim/src/jsrtcontextshim.cc b/deps/chakrashim/src/jsrtcontextshim.cc index 480874f8150..124513833db 100644 --- a/deps/chakrashim/src/jsrtcontextshim.cc +++ b/deps/chakrashim/src/jsrtcontextshim.cc @@ -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)); } @@ -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" diff --git a/deps/chakrashim/src/jsrtcontextshim.h b/deps/chakrashim/src/jsrtcontextshim.h index 789d49df19c..eef8b72e0e3 100644 --- a/deps/chakrashim/src/jsrtcontextshim.h +++ b/deps/chakrashim/src/jsrtcontextshim.h @@ -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 diff --git a/deps/chakrashim/src/v8json.cc b/deps/chakrashim/src/v8json.cc new file mode 100644 index 00000000000..ec12d232393 --- /dev/null +++ b/deps/chakrashim/src/v8json.cc @@ -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 JSON::Parse(Local json_string) { + v8::Isolate* iso = jsrt::IsolateShim::GetCurrentAsIsolate(); + return FromMaybe(JSON::Parse(iso, json_string)); + } + + MaybeLocal JSON::Parse(Isolate* isolate, + Local json_string) { + Local context = isolate->GetCurrentContext(); + return JSON::Parse(context, json_string); + } + + MaybeLocal JSON::Parse(Local context, + Local 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(); + } + + return Local::New(obj); + } + + MaybeLocal JSON::Stringify(Local context, + Local json_object, + Local 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(*gap); + + if (jsrt::CallFunction(jsonStringifyFunction, (JsValueRef)*json_object, + jsrt::GetUndefined(), actualGap, &str) != JsNoError) { + return Local(); + } + + return Local::New(str); + } +} // namespace v8 diff --git a/node.gypi b/node.gypi index 49ed1e45b0c..eb02224efb9 100644 --- a/node.gypi +++ b/node.gypi @@ -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' ], diff --git a/test/addons/json/binding.cc b/test/addons/json/binding.cc new file mode 100644 index 00000000000..8bb72493735 --- /dev/null +++ b/test/addons/json/binding.cc @@ -0,0 +1,26 @@ +#include +#include + +namespace { + +void Stringify(const v8::FunctionCallbackInfo& args) { + auto result = v8::JSON::Stringify(args.GetIsolate()->GetCurrentContext(), + args[0].As(), + args[1].As()); + args.GetReturnValue().Set(result.ToLocalChecked()); +} + +void Parse(const v8::FunctionCallbackInfo& args) { + auto result = v8::JSON::Parse(args.GetIsolate()->GetCurrentContext(), + args[0].As()); + args.GetReturnValue().Set(result.ToLocalChecked()); +} + +inline void Initialize(v8::Local binding) { + NODE_SET_METHOD(binding, "stringify", Stringify); + NODE_SET_METHOD(binding, "parse", Parse); +} + +NODE_MODULE(binding, Initialize) + +} // anonymous namespace diff --git a/test/addons/json/binding.gyp b/test/addons/json/binding.gyp new file mode 100644 index 00000000000..7ede63d94a0 --- /dev/null +++ b/test/addons/json/binding.gyp @@ -0,0 +1,9 @@ +{ + 'targets': [ + { + 'target_name': 'binding', + 'defines': [ 'V8_DEPRECATION_WARNINGS=1' ], + 'sources': [ 'binding.cc' ] + } + ] +} diff --git a/test/addons/json/test.js b/test/addons/json/test.js new file mode 100644 index 00000000000..a46f054763b --- /dev/null +++ b/test/addons/json/test.js @@ -0,0 +1,16 @@ +'use strict'; + +const common = require('../../common'); +const assert = require('assert'); +const binding = require(`./build/${common.buildType}/binding`); + +const obj = { some_key: 'some_value' }; +const str = JSON.stringify(obj); + +assert.strictEqual(str, binding.stringify(obj)); +assert.strictEqual(JSON.stringify(obj, undefined, 5), + binding.stringify(obj, 5)); +assert.strictEqual('string', typeof binding.stringify(obj)); + +assert.strictEqual(obj.some_key, binding.parse(str).some_key); +assert.strictEqual('object', typeof binding.parse(str)); diff --git a/vcbuild.bat b/vcbuild.bat index 7573c8b5d0d..2a00e070385 100644 --- a/vcbuild.bat +++ b/vcbuild.bat @@ -151,7 +151,7 @@ if "%i18n_arg%"=="without-intl" set configure_flags=%configure_flags% --without- if "%engine%"=="chakracore" ( set configure_flags=%configure_flags% --without-bundled-v8 set chakra_jslint=deps\chakrashim\lib - set chakra_cpplint=deps\chakrashim\src\*.cc deps\chakrashim\src\*.h + set chakra_cpplint=deps\chakrashim\src\*.cc deps\chakrashim\src\*.h deps\chakrashim\include\v8.h ) if "%target_arch%"=="arm" (