js/src/jsapi-tests/testFunctionNonSyntactic.cpp
author Mozilla Releng Treescript <release+treescript@mozilla.org>
Sat, 25 Jun 2022 19:02:59 +0000
changeset 622090 c9b65d44600ac04887d0dcf6242c5d98fe7bd242
parent 589115 245e0bc541f95eb137e75f4cbe216707b56335b4
permissions -rw-r--r--
no bug - Bumping Firefox l10n changesets r=release a=l10n-bump DONTBUILD el -> 58cf40fbc7269bbf9fada1253ec8f011507a992f it -> 31a83f189f50d61cf1cf21a2215cd158c27cdc9c ro -> de1113d8613b112c14d8e75a3e1e0ce7b1a6236e ru -> ebb41fc34812cd2b60b9d71d4131620e5be1cbd3 sl -> f13ec224df213c09e026461144f137d231bd6fd0 tg -> 8584c83ca1fe45406ba32353ae7e76c98d026363 zh-CN -> 09b635a976c6192dccb652bb137867db8b16f722

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
 * vim: set ts=8 sts=2 et sw=2 tw=80:
 *
 * Test function with enclosing non-syntactic scope.
 */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "mozilla/Utf8.h"  // mozilla::Utf8Unit

#include "js/CallAndConstruct.h"
#include "js/CompilationAndEvaluation.h"  // JS::CompileFunction
#include "js/PropertyAndElement.h"        // JS_DefineProperty
#include "js/SourceText.h"                // JS::Source{Ownership,Text}
#include "jsapi-tests/tests.h"
#include "util/Text.h"
#include "vm/JSFunction.h"  // JSFunction
#include "vm/ScopeKind.h"   // ScopeKind

using namespace js;

BEGIN_TEST(testFunctionNonSyntactic) {
  JS::RootedObjectVector scopeChain(cx);

  {
    JS::RootedObject scopeObj(cx, JS_NewPlainObject(cx));
    CHECK(scopeObj);
    JS::RootedValue val(cx);
    val.setNumber(1);
    CHECK(JS_DefineProperty(cx, scopeObj, "foo", val, JSPROP_ENUMERATE));
    CHECK(scopeChain.append(scopeObj));
  }

  {
    JS::RootedObject scopeObj(cx, JS_NewPlainObject(cx));
    CHECK(scopeObj);
    JS::RootedValue val(cx);
    val.setNumber(20);
    CHECK(JS_DefineProperty(cx, scopeObj, "bar", val, JSPROP_ENUMERATE));
    CHECK(scopeChain.append(scopeObj));
  }

  {
    static const char src[] = "return foo + bar;";

    JS::SourceText<mozilla::Utf8Unit> srcBuf;
    CHECK(srcBuf.init(cx, src, js_strlen(src), JS::SourceOwnership::Borrowed));

    JS::CompileOptions options(cx);
    options.setFileAndLine(__FILE__, __LINE__);
    RootedFunction fun(cx, JS::CompileFunction(cx, scopeChain, options, "test",
                                               0, nullptr, srcBuf));
    CHECK(fun);

    CHECK(fun->enclosingScope()->kind() == ScopeKind::NonSyntactic);

    JS::RootedValue funVal(cx, JS::ObjectValue(*fun));
    JS::RootedValue rval(cx);
    CHECK(JS::Call(cx, JS::UndefinedHandleValue, funVal,
                   JS::HandleValueArray::empty(), &rval));
    CHECK(rval.isNumber());
    CHECK(rval.toNumber() == 21);
  }

  // With extra body bar.
  {
    const char* args[] = {
        "a = 300",
    };
    static const char src[] = "var x = 4000; return a + x + foo + bar;";

    JS::SourceText<mozilla::Utf8Unit> srcBuf;
    CHECK(srcBuf.init(cx, src, js_strlen(src), JS::SourceOwnership::Borrowed));

    JS::CompileOptions options(cx);
    options.setFileAndLine(__FILE__, __LINE__);
    RootedFunction fun(cx, JS::CompileFunction(cx, scopeChain, options, "test",
                                               1, args, srcBuf));
    CHECK(fun);

    CHECK(fun->enclosingScope()->kind() == ScopeKind::NonSyntactic);

    JS::RootedValue funVal(cx, JS::ObjectValue(*fun));
    JS::RootedValue rval(cx);
    CHECK(JS::Call(cx, JS::UndefinedHandleValue, funVal,
                   JS::HandleValueArray::empty(), &rval));
    CHECK(rval.isNumber());
    CHECK(rval.toNumber() == 4321);
  }

  return true;
}
END_TEST(testFunctionNonSyntactic)