testFunctionNonSyntactic.cpp (3223B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 3 * 4 * Test function with enclosing non-syntactic scope. 5 */ 6 /* This Source Code Form is subject to the terms of the Mozilla Public 7 * License, v. 2.0. If a copy of the MPL was not distributed with this 8 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 9 10 #include "mozilla/Utf8.h" // mozilla::Utf8Unit 11 12 #include "js/CallAndConstruct.h" 13 #include "js/CompilationAndEvaluation.h" // JS::CompileFunction 14 #include "js/EnvironmentChain.h" // JS::EnvironmentChain 15 #include "js/PropertyAndElement.h" // JS_DefineProperty 16 #include "js/SourceText.h" // JS::Source{Ownership,Text} 17 #include "jsapi-tests/tests.h" 18 #include "util/Text.h" 19 #include "vm/JSFunction.h" // JSFunction 20 #include "vm/Scope.h" // Scope 21 #include "vm/ScopeKind.h" // ScopeKind 22 23 using namespace js; 24 25 BEGIN_TEST(testFunctionNonSyntactic) { 26 JS::EnvironmentChain envChain(cx, JS::SupportUnscopables::No); 27 28 { 29 JS::RootedObject scopeObj(cx, JS_NewPlainObject(cx)); 30 CHECK(scopeObj); 31 JS::RootedValue val(cx); 32 val.setNumber(1); 33 CHECK(JS_DefineProperty(cx, scopeObj, "foo", val, JSPROP_ENUMERATE)); 34 CHECK(envChain.append(scopeObj)); 35 } 36 37 { 38 JS::RootedObject scopeObj(cx, JS_NewPlainObject(cx)); 39 CHECK(scopeObj); 40 JS::RootedValue val(cx); 41 val.setNumber(20); 42 CHECK(JS_DefineProperty(cx, scopeObj, "bar", val, JSPROP_ENUMERATE)); 43 CHECK(envChain.append(scopeObj)); 44 } 45 46 { 47 static const char src[] = "return foo + bar;"; 48 49 JS::SourceText<mozilla::Utf8Unit> srcBuf; 50 CHECK(srcBuf.init(cx, src, js_strlen(src), JS::SourceOwnership::Borrowed)); 51 52 JS::CompileOptions options(cx); 53 options.setFileAndLine(__FILE__, __LINE__); 54 RootedFunction fun(cx, JS::CompileFunction(cx, envChain, options, "test", 0, 55 nullptr, srcBuf)); 56 CHECK(fun); 57 58 CHECK(fun->enclosingScope()->kind() == ScopeKind::NonSyntactic); 59 60 JS::RootedValue funVal(cx, JS::ObjectValue(*fun)); 61 JS::RootedValue rval(cx); 62 CHECK(JS::Call(cx, JS::UndefinedHandleValue, funVal, 63 JS::HandleValueArray::empty(), &rval)); 64 CHECK(rval.isNumber()); 65 CHECK(rval.toNumber() == 21); 66 } 67 68 // With extra body bar. 69 { 70 const char* args[] = { 71 "a = 300", 72 }; 73 static const char src[] = "var x = 4000; return a + x + foo + bar;"; 74 75 JS::SourceText<mozilla::Utf8Unit> srcBuf; 76 CHECK(srcBuf.init(cx, src, js_strlen(src), JS::SourceOwnership::Borrowed)); 77 78 JS::CompileOptions options(cx); 79 options.setFileAndLine(__FILE__, __LINE__); 80 RootedFunction fun(cx, JS::CompileFunction(cx, envChain, options, "test", 1, 81 args, srcBuf)); 82 CHECK(fun); 83 84 CHECK(fun->enclosingScope()->kind() == ScopeKind::NonSyntactic); 85 86 JS::RootedValue funVal(cx, JS::ObjectValue(*fun)); 87 JS::RootedValue rval(cx); 88 CHECK(JS::Call(cx, JS::UndefinedHandleValue, funVal, 89 JS::HandleValueArray::empty(), &rval)); 90 CHECK(rval.isNumber()); 91 CHECK(rval.toNumber() == 4321); 92 } 93 94 return true; 95 } 96 END_TEST(testFunctionNonSyntactic)