diff --git a/include/hermes/VM/RuntimeModule.h b/include/hermes/VM/RuntimeModule.h index 6c3749544fe..7fec4edbfe7 100644 --- a/include/hermes/VM/RuntimeModule.h +++ b/include/hermes/VM/RuntimeModule.h @@ -208,8 +208,10 @@ class RuntimeModule final : public llvh::ilist_node { /// file's global function (i.e. the first RM created when we started /// interpreting and lazily compiling the source code). For other RMs, /// e.g. those loaded from precompiled bytecode, this is just itself. + /// We also return this for RM created from serialization/deserialization. + /// Note that lazy and serialization are not intended to work together. RuntimeModule *getLazyRootModule() { -#ifdef HERMESVM_LEAN +#if defined(HERMESVM_LEAN) || defined(HERMESVM_SERIALIZE) return this; #else return lazyRoot_; diff --git a/lib/VM/CodeBlock.cpp b/lib/VM/CodeBlock.cpp index b8f2de305e4..2e72b6fe80f 100644 --- a/lib/VM/CodeBlock.cpp +++ b/lib/VM/CodeBlock.cpp @@ -255,8 +255,13 @@ OptValue CodeBlock::getSourceLocation( } OptValue CodeBlock::getFunctionSourceID() const { + // Note that for the case of lazy compilation, the function sources had been + // reserved into the function source table of the root bytecode module. + // For non-lazy module, the lazy root module is itself. llvh::ArrayRef> table = - runtimeModule_->getBytecode()->getFunctionSourceTable(); + runtimeModule_->getLazyRootModule() + ->getBytecode() + ->getFunctionSourceTable(); // Performs a binary search since the function source table is sorted by the // 1st value. We could further optimize the lookup by loading it as a map in diff --git a/lib/VM/JSLib/Function.cpp b/lib/VM/JSLib/Function.cpp index af8509b46e5..79bbaf2ce39 100644 --- a/lib/VM/JSLib/Function.cpp +++ b/lib/VM/JSLib/Function.cpp @@ -127,6 +127,7 @@ functionPrototypeToString(void *, Runtime *runtime, NativeArgs args) { StringPrimitive *source = jsFunc->getCodeBlock() ->getRuntimeModule() + ->getLazyRootModule() ->getStringPrimFromStringIDMayAllocate(*sourceID); // Empty source marks implementation-hidden function, fabricate a source // code string that imitate a NativeFunction. diff --git a/test/hermes/function-toString.js b/test/hermes/function-toString.js index 972e7d1a29b..e6c06a0ef3f 100644 --- a/test/hermes/function-toString.js +++ b/test/hermes/function-toString.js @@ -7,8 +7,10 @@ // RUN: %hermes %s | %FileCheck --match-full-lines %s // RUN: %hermes -O %s | %FileCheck --match-full-lines %s +// RUN: %hermes -lazy %s | %FileCheck --match-full-lines %s // RUN: %hermes -O -target=HBC %s | %FileCheck --match-full-lines %s // RUN: %hermes -O -target=HBC -emit-binary -out %t.hbc %s && %hermes %t.hbc | %FileCheck --match-full-lines %s +// UNSUPPORTED: serializer print('Function.prototype.toString'); // CHECK-LABEL: Function.prototype.toString @@ -42,11 +44,14 @@ print((function now() { 'hide source' }).toString()); // CHECK-NEXT: function now() { [native code] } -/// --- Function Expression / Arrow / Anonymous --- +/// --- Function Expression --- print((function fe() { 'show source' }).toString()); // CHECK-NEXT: function fe() { 'show source' } + +/// --- Arrow Function Expression --- + print((() => { 'show source' }).toString()); // CHECK-NEXT: () => { 'show source' } diff --git a/test/hermes/lazy-function-toString.js b/test/hermes/lazy-function-toString.js new file mode 100644 index 00000000000..713ab01a038 --- /dev/null +++ b/test/hermes/lazy-function-toString.js @@ -0,0 +1,18 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +// RUN: %hermes -non-strict -O0 %s 2>&1 | %FileCheck --match-full-lines %s +// RUN: %hermes -lazy -non-strict -O0 %s 2>&1 | %FileCheck --match-full-lines %s +// UNSUPPORTED: serializer + +// foo is never called, but its source needs to be reserved ahead of time. +function foo(x) { "show source"; } + +(function bar() { + print(foo.toString()); + // CHECK: function foo(x) { "show source"; } +})() diff --git a/test/hermes/source-visibility/global-hide-source.js b/test/hermes/source-visibility/global-hide-source.js index 3d0eafd0787..b4d388bc44d 100644 --- a/test/hermes/source-visibility/global-hide-source.js +++ b/test/hermes/source-visibility/global-hide-source.js @@ -6,6 +6,8 @@ */ // RUN: %hermes -O %s | %FileCheck --match-full-lines %s +// RUN: %hermes -lazy %s | %FileCheck --match-full-lines %s +// UNSUPPORTED: serializer 'hide source'; diff --git a/test/hermes/source-visibility/global-show-source.js b/test/hermes/source-visibility/global-show-source.js index eba96602661..74068f586c8 100644 --- a/test/hermes/source-visibility/global-show-source.js +++ b/test/hermes/source-visibility/global-show-source.js @@ -6,6 +6,8 @@ */ // RUN: %hermes -O %s | %FileCheck --match-full-lines %s +// RUN: %hermes -lazy %s | %FileCheck --match-full-lines %s +// UNSUPPORTED: serializer 'show source'; diff --git a/test/hermes/source-visibility/override.js b/test/hermes/source-visibility/override.js index d806a69ef38..930673c0f21 100644 --- a/test/hermes/source-visibility/override.js +++ b/test/hermes/source-visibility/override.js @@ -6,6 +6,8 @@ */ // RUN: %hermes -O %s | %FileCheck --match-full-lines %s +// RUN: %hermes -lazy %s | %FileCheck --match-full-lines %s +// UNSUPPORTED: serializer // Inner HideSource can override outer ShowSource function showSource1() { diff --git a/test/hermes/source-visibility/with-eval.js b/test/hermes/source-visibility/with-eval.js index 84edc1f1f75..83d16d54b65 100644 --- a/test/hermes/source-visibility/with-eval.js +++ b/test/hermes/source-visibility/with-eval.js @@ -6,6 +6,7 @@ */ // RUN: %hermes -O %s | %FileCheck --match-full-lines %s +// RUN: %hermes -lazy %s | %FileCheck --match-full-lines %s print("with eval"); // CHECK-LABEL: with eval diff --git a/test/serialize/function-usercode.js b/test/serialize/function-usercode.js index 0a13f8dc54f..7b5e43af302 100644 --- a/test/serialize/function-usercode.js +++ b/test/serialize/function-usercode.js @@ -15,6 +15,7 @@ var F = function(x) { return x; }; var f = new F(1); var F2 = function(a,b,c,d,e,f,g,h,i,j,k){} var foo = function badlength(a, b, c){}; +var bar = function showSource(a, b, c){"show source"}; Object.defineProperty(foo, "length", {value:"aa"}); var f2 = function(a, b) { print(arguments.length, this, a, b); @@ -60,6 +61,10 @@ serializeVM(function() { print(foo); // CHECK-NEXT: function badlength() { [bytecode] } + // Source visibility directives + print(bar); + // CHECK-NEXT: function showSource(a, b, c){"show source"} + print('call'); // CHECK-LABEL: call print(f2.length);